catchup merge on all of alfadur's cool server changes
authornemo
Fri, 20 Jul 2018 20:00:52 -0400
changeset 13536 282218ab1b28
parent 13535 80db7232b4b5 (current diff)
parent 13524 1232ab8206d4 (diff)
child 13539 395a4c92e523
catchup merge on all of alfadur's cool server changes
gameServer2/src/protocol/messages.rs
tools/build_windows.bat
tools/w32DownloadUnzip.vbs
--- a/ChangeLog.txt	Sat Jul 21 02:19:32 2018 +0300
+++ b/ChangeLog.txt	Fri Jul 20 20:00:52 2018 -0400
@@ -4,10 +4,18 @@
 Game:
  + Add new key to show mission panel (default: M)
  + Add chat command “/help”, displays help for chat commands
+ + Increase hedgehog limit to 64
+ * Functionality of controllers restored
+ * Fix crash when 2 or more controllers were connected
  * Fix extreme amounts of droplets when shooting with minigun into ocean world edge
  * Fix hog being unable to walk after using sniper rifle without firing both shots
+ * Fix video recorder not working when game audio was disabled
+ * Fix cursor teleporting to center after leaving game with a video recording
  * Fix teleport tooltip claiming it doesn't end turn in hog placing phase with inf. attack
 
+Frontend:
+ * Controllers are detected again
+
 Highlander:
  * Fix all hogs getting teleport after hog placement phase
 
@@ -52,6 +60,7 @@
  + New call: GetAmmo(ammoType): Returns ammo configuration (corresponds to SetAmmo)
  + New parameter: SetAmmoTexts: 5th param. showExtra: Set to false to hide texts like “Not yet available”
  + New parameter: ShowMission: 6th param. forceDisplay: Set to true to prevent this particular mission panel to be hidden manually by player
+ + New Lua library: Achievements
  * Changed global: lfCurrentHog becomes lfCurHogCrate
  * Fixed variable: TotalRounds was -1 (instead of 0) in first real round after hog placement phase
  * AI sometimes intentionally shot hedgehogs with aihDoesntMatter set
--- a/INSTALL.md	Sat Jul 21 02:19:32 2018 +0300
+++ b/INSTALL.md	Fri Jul 20 20:00:52 2018 -0400
@@ -79,7 +79,10 @@
     - `entropy`
     - `zlib` >= 0.5.3 and < 0.6
     - `regex-tdfa`
-
+    - `binary` >= 0.8.5.1
+    - `yaml` >= 0.8.30
+    - `aeson`
+    - `text` >= 1.2
 
 Building
 --------
--- a/QTfrontend/CMakeLists.txt	Sat Jul 21 02:19:32 2018 +0300
+++ b/QTfrontend/CMakeLists.txt	Fri Jul 20 20:00:52 2018 -0400
@@ -94,6 +94,7 @@
     campaign.cpp
     ui_hwform.cpp
     ${CMAKE_CURRENT_BINARY_DIR}/hwconsts.cpp
+    ${CMAKE_CURRENT_BINARY_DIR}/sdlkeys.cpp
     )
 
 if(MINGW)
--- a/QTfrontend/hwconsts.cpp.in	Sat Jul 21 02:19:32 2018 +0300
+++ b/QTfrontend/hwconsts.cpp.in	Fri Jul 20 20:00:52 2018 -0400
@@ -16,6 +16,12 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
+/*
+ * PLEASE NOTE: hwconsts.cpp is automatically generated from hwconsts.cpp.in.
+ * Do not edit hwconsts.cpp manually, it will be overwritten when building.
+ * Edit hwconsts.cpp.in to change the code.
+ */
+
 #include <QStandardItemModel>
 
 #include "hwconsts.h"
@@ -37,6 +43,7 @@
 bool custom_data = false;
 
 int cMaxTeams = 8;
+int cMaxHHs = HEDGEHOGS_PER_TEAM * cMaxTeams;
 int cMinServerVersion = 3;
 
 QString * cDefaultAmmoStore = new QString( AMMOLINE_DEFAULT_QT AMMOLINE_DEFAULT_PROB
--- a/QTfrontend/hwconsts.h	Sat Jul 21 02:19:32 2018 +0300
+++ b/QTfrontend/hwconsts.h	Fri Jul 20 20:00:52 2018 -0400
@@ -37,6 +37,7 @@
 extern bool custom_data;
 
 extern int cMaxTeams;
+extern int cMaxHHs;
 extern int cMinServerVersion;
 
 class QStandardItemModel;
@@ -73,6 +74,9 @@
 #define NETGAME_DEFAULT_PORT 46631
 #define HEDGEHOGS_PER_TEAM 8
 
+//Selected engine exit codes, see hedgewars/uConsts.pas
+#define HWENGINE_EXITCODE_OK 0
+#define HWENGINE_EXITCODE_FATAL 52
 
 // see https://en.wikipedia.org/wiki/List_of_colors
 /*define HW_TEAMCOLOR_ARRAY  {0xff007fff, /. azure          ./ \
--- a/QTfrontend/hwform.cpp	Sat Jul 21 02:19:32 2018 +0300
+++ b/QTfrontend/hwform.cpp	Fri Jul 20 20:00:52 2018 -0400
@@ -1707,14 +1707,6 @@
 
 void HWForm::StartMPGame()
 {
-    int numHogs = ui.pageMultiplayer->teamsSelect->getNumHedgehogs();
-    /* Don't allow to start game with >48 hogs.
-    TODO: Remove this as soon the engine supports more hogs. */
-    if(numHogs > 48)
-    {
-        MessageDialog::ShowErrorMessage(QMessageBox::tr("Sorry, Hedgewars can't be played with more than 48 hedgehogs. Please try again with fewer hedgehogs.\n\nCurrent number of hedgehogs: %1").arg(numHogs), this);
-        return;
-    }
     QString ammo;
     ammo = ui.pageMultiplayer->gameCFG->WeaponsName->itemData(
                ui.pageMultiplayer->gameCFG->WeaponsName->currentIndex()
--- a/QTfrontend/main.cpp	Sat Jul 21 02:19:32 2018 +0300
+++ b/QTfrontend/main.cpp	Fri Jul 20 20:00:52 2018 -0400
@@ -161,28 +161,6 @@
 }
 
 int main(int argc, char *argv[]) {
-    /* Qt5 Base removed Motif, Plastique. These are now in the Qt style plugins
-    (Ubuntu: qt5-style-plugins, which was NOT backported by Debian/Ubuntu to stable/LTS).
-    Windows appears to render best of the remaining options but still isn't quite right. */
-
-    // Try setting Plastique if available
-    QStyle* coreStyle;
-    coreStyle = QStyleFactory::create("Plastique");
-    if(coreStyle != 0) {
-        QApplication::setStyle(coreStyle);
-        qDebug("Qt style set: Plastique");
-    } else {
-        // Use Windows as fallback.
-        // FIXME: Under Windows style, some widgets like scrollbars don't render as nicely
-        coreStyle = QStyleFactory::create("Windows");
-        if(coreStyle != 0) {
-            QApplication::setStyle(coreStyle);
-            qDebug("Qt style set: Windows");
-        } else {
-            // Windows style should not be missing in Qt5 Base. If it does, something went terribly wrong!
-            qWarning("No Qt style could be set! Using the default one.");
-        }
-    }
 
     // Since we're calling this first, closeResources() will be the last thing called after main() returns.
     atexit(closeResources);
@@ -191,8 +169,6 @@
     cocoaInit = new CocoaInitializer(); // Creates the autoreleasepool preventing cocoa object leaks on OS X.
 #endif
 
-    SDLInteraction::instance();
-
     HWApplication app(argc, argv);
     app.setAttribute(Qt::AA_DontShowIconsInMenus,false);
 
@@ -274,6 +250,29 @@
 
     // end of parameter parsing
 
+    // Select Qt style
+    /* Qt5 Base removed Motif, Plastique. These are now in the Qt style plugins
+    (Ubuntu: qt5-style-plugins, which was NOT backported by Debian/Ubuntu to stable/LTS).
+    Windows appears to render best of the remaining options but still isn't quite right. */
+
+    // Try setting Plastique if available
+    QStyle* coreStyle;
+    coreStyle = QStyleFactory::create("Plastique");
+    if(coreStyle != 0) {
+        QApplication::setStyle(coreStyle);
+        qDebug("Qt style set: Plastique");
+    } else {
+        // Use Windows as fallback.
+        // FIXME: Under Windows style, some widgets like scrollbars don't render as nicely
+        coreStyle = QStyleFactory::create("Windows");
+        if(coreStyle != 0) {
+            QApplication::setStyle(coreStyle);
+            qDebug("Qt style set: Windows");
+        } else {
+            // Windows style should not be missing in Qt5 Base. If it does, something went terribly wrong!
+            qWarning("No Qt style could be set! Using the default one.");
+        }
+    }
 
 #ifdef Q_OS_WIN
     QPixmap pixmap(":/res/splash.png");
@@ -414,6 +413,8 @@
     }
 #endif
 
+    SDLInteraction::instance();
+
     QString style = "";
     QString fname;
 
--- a/QTfrontend/net/recorder.cpp	Sat Jul 21 02:19:32 2018 +0300
+++ b/QTfrontend/net/recorder.cpp	Fri Jul 20 20:00:52 2018 -0400
@@ -140,7 +140,10 @@
 // Could use a field to use quality instead. maybe quality could override bitrate - or just pass (and set) both.
 // The library does support using both at once after all.
     arguments << QString::number(config->rec_Bitrate()*1024);
-    arguments << (config->recordAudio() ? config->audioCodec() : "no");
+    if (config->recordAudio() && (config->isSoundEnabled() || config->isMusicEnabled()))
+        arguments << config->audioCodec();
+    else
+        arguments << "no";
 
     return arguments;
 }
--- a/QTfrontend/net/tcpBase.cpp	Sat Jul 21 02:19:32 2018 +0300
+++ b/QTfrontend/net/tcpBase.cpp	Fri Jul 20 20:00:52 2018 -0400
@@ -235,7 +235,7 @@
 
     // show error message if there was an error that was not an engine's
     // fatal error - because that one already sent a info via IPC
-    if ((exitCode != 0) && (exitCode != 2))
+    if ((exitCode != HWENGINE_EXITCODE_OK) && (exitCode != HWENGINE_EXITCODE_FATAL))
     {
         // inform user that something bad happened
         MessageDialog::ShowFatalMessage(
@@ -251,9 +251,15 @@
 
 void TCPBase::tcpServerReady()
 {
-    disconnect(srvsList.first(), SIGNAL(isReadyNow()), this, SLOT(tcpServerReady()));
-
-    RealStart();
+    if (!srvsList.isEmpty())
+    {
+        disconnect(srvsList.first(), SIGNAL(isReadyNow()), this, SLOT(tcpServerReady()));
+        RealStart();
+    }
+    else
+    {
+        qDebug("tcpServerReady() called while srvsList was empty. Not starting TCP server");
+    }
 }
 
 void TCPBase::Start(bool couldCancelPreviousRequest)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/sdlkeys.cpp	Fri Jul 20 20:00:52 2018 -0400
@@ -0,0 +1,199 @@
+/*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2004-2015 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * This 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "sdlkeys.h"
+
+#include <QtGlobal>
+
+char sdlkeys[1024][2][128] =
+{
+    {"mousel", QT_TRANSLATE_NOOP("binds (keys)", "Mouse: Left button")},
+    {"mousem", QT_TRANSLATE_NOOP("binds (keys)", "Mouse: Middle button")},
+    {"mouser", QT_TRANSLATE_NOOP("binds (keys)", "Mouse: Right button")},
+    {"wheelup", QT_TRANSLATE_NOOP("binds (keys)", "Mouse: Wheel up")},
+    {"wheeldown", QT_TRANSLATE_NOOP("binds (keys)", "Mouse: Wheel down")},
+    {"backspace", QT_TRANSLATE_NOOP("binds (keys)", "Backspace")},
+    {"tab", QT_TRANSLATE_NOOP("binds (keys)", "Tab")},
+    {"clear", QT_TRANSLATE_NOOP("binds (keys)", "Clear")},
+    {"return", QT_TRANSLATE_NOOP("binds (keys)", "Return")},
+    {"pause", QT_TRANSLATE_NOOP("binds (keys)", "Pause")},
+    {"escape", QT_TRANSLATE_NOOP("binds (keys)", "Escape")},
+    {"space", QT_TRANSLATE_NOOP("binds (keys)", "Space")},
+    {"!", "!"},
+    {"\"", "\""},
+    {"#", "#"},
+    {"$", "$"},
+    {"&", "&"},
+    {"'", "'"},
+    {"(", "("},
+    {")", ")"},
+    {"*", "*"},
+    {"+", "+"},
+    {",", ","},
+    {"-", "-"},
+    {".", "."},
+    {"/", "/"},
+    {"0", "0"},
+    {"1", "1"},
+    {"2", "2"},
+    {"3", "3"},
+    {"4", "4"},
+    {"5", "5"},
+    {"6", "6"},
+    {"7", "7"},
+    {"8", "8"},
+    {"9", "9"},
+    {":", ":"},
+    {";", ";"},
+    {"<", "<"},
+    {"=", "="},
+    {">", ">"},
+    {"?", "?"},
+    {"@", "@"},
+    {"[", "["},
+    {"\\", "\\"},
+    {"]", "]"},
+    {"^", "^"},
+    {"_", "_"},
+    {"`", "`"},
+    {"a", "A"},
+    {"b", "B"},
+    {"c", "C"},
+    {"d", "D"},
+    {"e", "E"},
+    {"f", "F"},
+    {"g", "G"},
+    {"h", "H"},
+    {"i", "I"},
+    {"j", "J"},
+    {"k", "K"},
+    {"l", "L"},
+    {"m", "M"},
+    {"n", "N"},
+    {"o", "O"},
+    {"p", "P"},
+    {"q", "Q"},
+    {"r", "R"},
+    {"s", "S"},
+    {"t", "T"},
+    {"u", "U"},
+    {"v", "V"},
+    {"w", "W"},
+    {"x", "X"},
+    {"y", "Y"},
+    {"z", "Z"},
+    {"delete", QT_TRANSLATE_NOOP("binds (keys)", "Delete")},
+    {"keypad_0", QT_TRANSLATE_NOOP("binds (keys)", "Numpad 0")},
+    {"keypad_1", QT_TRANSLATE_NOOP("binds (keys)", "Numpad 1")},
+    {"keypad_2", QT_TRANSLATE_NOOP("binds (keys)", "Numpad 2")},
+    {"keypad_3", QT_TRANSLATE_NOOP("binds (keys)", "Numpad 3")},
+    {"keypad_4", QT_TRANSLATE_NOOP("binds (keys)", "Numpad 4")},
+    {"keypad_5", QT_TRANSLATE_NOOP("binds (keys)", "Numpad 5")},
+    {"keypad_6", QT_TRANSLATE_NOOP("binds (keys)", "Numpad 6")},
+    {"keypad_7", QT_TRANSLATE_NOOP("binds (keys)", "Numpad 7")},
+    {"keypad_8", QT_TRANSLATE_NOOP("binds (keys)", "Numpad 8")},
+    {"keypad_9", QT_TRANSLATE_NOOP("binds (keys)", "Numpad 9")},
+    {"keypad_.", QT_TRANSLATE_NOOP("binds (keys)", "Numpad .")},
+    {"keypad_/", QT_TRANSLATE_NOOP("binds (keys)", "Numpad /")},
+    {"keypad_*", QT_TRANSLATE_NOOP("binds (keys)", "Numpad *")},
+    {"keypad_-", QT_TRANSLATE_NOOP("binds (keys)", "Numpad -")},
+    {"keypad_+", QT_TRANSLATE_NOOP("binds (keys)", "Numpad +")},
+    {"enter", QT_TRANSLATE_NOOP("binds (keys)", "Enter")},
+    {"equals", QT_TRANSLATE_NOOP("binds (keys)", "Equals")},
+    {"up", QT_TRANSLATE_NOOP("binds (keys)", "Up")},
+    {"down", QT_TRANSLATE_NOOP("binds (keys)", "Down")},
+    {"right", QT_TRANSLATE_NOOP("binds (keys)", "Right")},
+    {"left", QT_TRANSLATE_NOOP("binds (keys)", "Left")},
+    {"insert", QT_TRANSLATE_NOOP("binds (keys)", "Insert")},
+    {"home", QT_TRANSLATE_NOOP("binds (keys)", "Home")},
+    {"end", QT_TRANSLATE_NOOP("binds (keys)", "End")},
+    {"page_up", QT_TRANSLATE_NOOP("binds (keys)", "Page up")},
+    {"page_down", QT_TRANSLATE_NOOP("binds (keys)", "Page down")},
+    {"f1", "F1"},
+    {"f2", "F2"},
+    {"f3", "F3"},
+    {"f4", "F4"},
+    {"f5", "F5"},
+    {"f6", "F6"},
+    {"f7", "F7"},
+    {"f8", "F8"},
+    {"f9", "F9"},
+    {"f10", "F10"},
+    {"f11", "F11"},
+    {"f12", "F12"},
+    {"f13", "F13"},
+    {"f14", "F14"},
+    {"f15", "F15"},
+    {"numlock", QT_TRANSLATE_NOOP("binds (keys)", "Num lock")},
+    {"caps_lock", QT_TRANSLATE_NOOP("binds (keys)", "Caps lock")},
+    {"scroll_lock", QT_TRANSLATE_NOOP("binds (keys)", "Scroll lock")},
+    {"right_shift", QT_TRANSLATE_NOOP("binds (keys)", "Right shift")},
+    {"left_shift", QT_TRANSLATE_NOOP("binds (keys)", "Left shift")},
+    {"right_ctrl", QT_TRANSLATE_NOOP("binds (keys)", "Right ctrl")},
+    {"left_ctrl", QT_TRANSLATE_NOOP("binds (keys)", "Left ctrl")},
+    {"right_alt", QT_TRANSLATE_NOOP("binds (keys)", "Right alt")},
+    {"left_alt", QT_TRANSLATE_NOOP("binds (keys)", "Left alt")},
+    {"right_meta", QT_TRANSLATE_NOOP("binds (keys)", "Right meta")},
+    {"left_meta", QT_TRANSLATE_NOOP("binds (keys)", "Left meta")}
+};
+
+// button name definitions for Microsoft's XBox360 controller
+// don't modify button order!
+char xb360buttons[10][128] =
+{
+    QT_TRANSLATE_NOOP("binds (keys)", "A button"),
+    QT_TRANSLATE_NOOP("binds (keys)", "B button"),
+    QT_TRANSLATE_NOOP("binds (keys)", "X button"),
+    QT_TRANSLATE_NOOP("binds (keys)", "Y button"),
+    QT_TRANSLATE_NOOP("binds (keys)", "LB button"),
+    QT_TRANSLATE_NOOP("binds (keys)", "RB button"),
+    QT_TRANSLATE_NOOP("binds (keys)", "Back button"),
+    QT_TRANSLATE_NOOP("binds (keys)", "Start button"),
+    QT_TRANSLATE_NOOP("binds (keys)", "Left stick"),
+    QT_TRANSLATE_NOOP("binds (keys)", "Right stick")
+};
+
+// axis name definitions for Microsoft's XBox360 controller
+// don't modify axis order!
+char xbox360axes[][128] =
+{
+    QT_TRANSLATE_NOOP("binds (keys)", "Left stick (Right)"),
+    QT_TRANSLATE_NOOP("binds (keys)", "Left stick (Left)"),
+    QT_TRANSLATE_NOOP("binds (keys)", "Left stick (Down)"),
+    QT_TRANSLATE_NOOP("binds (keys)", "Left stick (Up)"),
+    QT_TRANSLATE_NOOP("binds (keys)", "Left trigger"),
+    QT_TRANSLATE_NOOP("binds (keys)", "Right trigger"),
+    QT_TRANSLATE_NOOP("binds (keys)", "Right stick (Down)"),
+    QT_TRANSLATE_NOOP("binds (keys)", "Right stick (Up)"),
+    QT_TRANSLATE_NOOP("binds (keys)", "Right stick (Right)"),
+    QT_TRANSLATE_NOOP("binds (keys)", "Right stick (Left)"),
+};
+char xb360dpad[128] = QT_TRANSLATE_NOOP("binds (keys)", "D-pad");
+
+// Generic controller binding names
+//: Game controller axis direction. %1 = axis number, %2 = direction
+char controlleraxis[128] = QT_TRANSLATE_NOOP("binds (keys)", "Axis %1 %2");
+//: Game controller button. %1 = button number
+char controllerbutton[128] = QT_TRANSLATE_NOOP("binds (keys)", "Button %1");
+//: Game controller D-pad button. %1 = D-pad number, %2 = direction
+char controllerhat[128] = QT_TRANSLATE_NOOP("binds (keys)", "D-pad %1 %2");
+char controllerup[128] = QT_TRANSLATE_NOOP("binds (keys)", "Up");
+char controllerdown[128] = QT_TRANSLATE_NOOP("binds (keys)", "Down");
+char controllerleft[128] = QT_TRANSLATE_NOOP("binds (keys)", "Left");
+char controllerright[128] = QT_TRANSLATE_NOOP("binds (keys)", "Right");
+
--- a/QTfrontend/sdlkeys.h	Sat Jul 21 02:19:32 2018 +0300
+++ b/QTfrontend/sdlkeys.h	Fri Jul 20 20:00:52 2018 -0400
@@ -16,167 +16,19 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-char sdlkeys[1024][2][128] =
-{
-    {"mousel", QT_TRANSLATE_NOOP("binds (keys)", "Mouse: Left button")},
-    {"mousem", QT_TRANSLATE_NOOP("binds (keys)", "Mouse: Middle button")},
-    {"mouser", QT_TRANSLATE_NOOP("binds (keys)", "Mouse: Right button")},
-    {"wheelup", QT_TRANSLATE_NOOP("binds (keys)", "Mouse: Wheel up")},
-    {"wheeldown", QT_TRANSLATE_NOOP("binds (keys)", "Mouse: Wheel down")},
-    {"backspace", QT_TRANSLATE_NOOP("binds (keys)", "Backspace")},
-    {"tab", QT_TRANSLATE_NOOP("binds (keys)", "Tab")},
-    {"clear", QT_TRANSLATE_NOOP("binds (keys)", "Clear")},
-    {"return", QT_TRANSLATE_NOOP("binds (keys)", "Return")},
-    {"pause", QT_TRANSLATE_NOOP("binds (keys)", "Pause")},
-    {"escape", QT_TRANSLATE_NOOP("binds (keys)", "Escape")},
-    {"space", QT_TRANSLATE_NOOP("binds (keys)", "Space")},
-    {"!", "!"},
-    {"\"", "\""},
-    {"#", "#"},
-    {"$", "$"},
-    {"&", "&"},
-    {"'", "'"},
-    {"(", "("},
-    {")", ")"},
-    {"*", "*"},
-    {"+", "+"},
-    {",", ","},
-    {"-", "-"},
-    {".", "."},
-    {"/", "/"},
-    {"0", "0"},
-    {"1", "1"},
-    {"2", "2"},
-    {"3", "3"},
-    {"4", "4"},
-    {"5", "5"},
-    {"6", "6"},
-    {"7", "7"},
-    {"8", "8"},
-    {"9", "9"},
-    {":", ":"},
-    {";", ";"},
-    {"<", "<"},
-    {"=", "="},
-    {">", ">"},
-    {"?", "?"},
-    {"@", "@"},
-    {"[", "["},
-    {"\\", "\\"},
-    {"]", "]"},
-    {"^", "^"},
-    {"_", "_"},
-    {"`", "`"},
-    {"a", "A"},
-    {"b", "B"},
-    {"c", "C"},
-    {"d", "D"},
-    {"e", "E"},
-    {"f", "F"},
-    {"g", "G"},
-    {"h", "H"},
-    {"i", "I"},
-    {"j", "J"},
-    {"k", "K"},
-    {"l", "L"},
-    {"m", "M"},
-    {"n", "N"},
-    {"o", "O"},
-    {"p", "P"},
-    {"q", "Q"},
-    {"r", "R"},
-    {"s", "S"},
-    {"t", "T"},
-    {"u", "U"},
-    {"v", "V"},
-    {"w", "W"},
-    {"x", "X"},
-    {"y", "Y"},
-    {"z", "Z"},
-    {"delete", QT_TRANSLATE_NOOP("binds (keys)", "Delete")},
-    {"keypad_0", QT_TRANSLATE_NOOP("binds (keys)", "Numpad 0")},
-    {"keypad_1", QT_TRANSLATE_NOOP("binds (keys)", "Numpad 1")},
-    {"keypad_2", QT_TRANSLATE_NOOP("binds (keys)", "Numpad 2")},
-    {"keypad_3", QT_TRANSLATE_NOOP("binds (keys)", "Numpad 3")},
-    {"keypad_4", QT_TRANSLATE_NOOP("binds (keys)", "Numpad 4")},
-    {"keypad_5", QT_TRANSLATE_NOOP("binds (keys)", "Numpad 5")},
-    {"keypad_6", QT_TRANSLATE_NOOP("binds (keys)", "Numpad 6")},
-    {"keypad_7", QT_TRANSLATE_NOOP("binds (keys)", "Numpad 7")},
-    {"keypad_8", QT_TRANSLATE_NOOP("binds (keys)", "Numpad 8")},
-    {"keypad_9", QT_TRANSLATE_NOOP("binds (keys)", "Numpad 9")},
-    {"keypad_.", QT_TRANSLATE_NOOP("binds (keys)", "Numpad .")},
-    {"keypad_/", QT_TRANSLATE_NOOP("binds (keys)", "Numpad /")},
-    {"keypad_*", QT_TRANSLATE_NOOP("binds (keys)", "Numpad *")},
-    {"keypad_-", QT_TRANSLATE_NOOP("binds (keys)", "Numpad -")},
-    {"keypad_+", QT_TRANSLATE_NOOP("binds (keys)", "Numpad +")},
-    {"enter", QT_TRANSLATE_NOOP("binds (keys)", "Enter")},
-    {"equals", QT_TRANSLATE_NOOP("binds (keys)", "Equals")},
-    {"up", QT_TRANSLATE_NOOP("binds (keys)", "Up")},
-    {"down", QT_TRANSLATE_NOOP("binds (keys)", "Down")},
-    {"right", QT_TRANSLATE_NOOP("binds (keys)", "Right")},
-    {"left", QT_TRANSLATE_NOOP("binds (keys)", "Left")},
-    {"insert", QT_TRANSLATE_NOOP("binds (keys)", "Insert")},
-    {"home", QT_TRANSLATE_NOOP("binds (keys)", "Home")},
-    {"end", QT_TRANSLATE_NOOP("binds (keys)", "End")},
-    {"page_up", QT_TRANSLATE_NOOP("binds (keys)", "Page up")},
-    {"page_down", QT_TRANSLATE_NOOP("binds (keys)", "Page down")},
-    {"f1", "F1"},
-    {"f2", "F2"},
-    {"f3", "F3"},
-    {"f4", "F4"},
-    {"f5", "F5"},
-    {"f6", "F6"},
-    {"f7", "F7"},
-    {"f8", "F8"},
-    {"f9", "F9"},
-    {"f10", "F10"},
-    {"f11", "F11"},
-    {"f12", "F12"},
-    {"f13", "F13"},
-    {"f14", "F14"},
-    {"f15", "F15"},
-    {"numlock", QT_TRANSLATE_NOOP("binds (keys)", "Num lock")},
-    {"caps_lock", QT_TRANSLATE_NOOP("binds (keys)", "Caps lock")},
-    {"scroll_lock", QT_TRANSLATE_NOOP("binds (keys)", "Scroll lock")},
-    {"right_shift", QT_TRANSLATE_NOOP("binds (keys)", "Right shift")},
-    {"left_shift", QT_TRANSLATE_NOOP("binds (keys)", "Left shift")},
-    {"right_ctrl", QT_TRANSLATE_NOOP("binds (keys)", "Right ctrl")},
-    {"left_ctrl", QT_TRANSLATE_NOOP("binds (keys)", "Left ctrl")},
-    {"right_alt", QT_TRANSLATE_NOOP("binds (keys)", "Right alt")},
-    {"left_alt", QT_TRANSLATE_NOOP("binds (keys)", "Left alt")},
-    {"right_meta", QT_TRANSLATE_NOOP("binds (keys)", "Right meta")},
-    {"left_meta", QT_TRANSLATE_NOOP("binds (keys)", "Left meta")}
-};
+#ifndef SDLKEYS_H
+#define SDLKEYS_H
 
-// button name definitions for Microsoft's XBox360 controller
-// don't modify button order!
-char xb360buttons[][128] =
-{
-    QT_TRANSLATE_NOOP("binds (keys)", "A button"),
-    QT_TRANSLATE_NOOP("binds (keys)", "B button"),
-    QT_TRANSLATE_NOOP("binds (keys)", "X button"),
-    QT_TRANSLATE_NOOP("binds (keys)", "Y button"),
-    QT_TRANSLATE_NOOP("binds (keys)", "LB button"),
-    QT_TRANSLATE_NOOP("binds (keys)", "RB button"),
-    QT_TRANSLATE_NOOP("binds (keys)", "Back button"),
-    QT_TRANSLATE_NOOP("binds (keys)", "Start button"),
-    QT_TRANSLATE_NOOP("binds (keys)", "Left stick"),
-    QT_TRANSLATE_NOOP("binds (keys)", "Right stick")
-};
+extern char sdlkeys[1024][2][128];
+extern char xb360buttons[10][128];
+extern char xbox360axes[10][128];
+extern char xb360dpad[128];
+extern char controlleraxis[128];
+extern char controllerbutton[128];
+extern char controllerhat[128];
+extern char controllerup[128];
+extern char controllerdown[128];
+extern char controllerleft[128];
+extern char controllerright[128];
 
-// axis name definitions for Microsoft's XBox360 controller
-// don't modify axis order!
-char xbox360axes[][128] =
-{
-    QT_TRANSLATE_NOOP("binds (keys)", "Left stick (Right)"),
-    QT_TRANSLATE_NOOP("binds (keys)", "Left stick (Left)"),
-    QT_TRANSLATE_NOOP("binds (keys)", "Left stick (Down)"),
-    QT_TRANSLATE_NOOP("binds (keys)", "Left stick (Up)"),
-    QT_TRANSLATE_NOOP("binds (keys)", "Left trigger"),
-    QT_TRANSLATE_NOOP("binds (keys)", "Right trigger"),
-    QT_TRANSLATE_NOOP("binds (keys)", "Right stick (Down)"),
-    QT_TRANSLATE_NOOP("binds (keys)", "Right stick (Up)"),
-    QT_TRANSLATE_NOOP("binds (keys)", "Right stick (Right)"),
-    QT_TRANSLATE_NOOP("binds (keys)", "Right stick (Left)"),
-};
-char xb360dpad[128] = QT_TRANSLATE_NOOP("binds (keys)", "DPad");
+#endif
--- a/QTfrontend/ui/widget/chatwidget.cpp	Sat Jul 21 02:19:32 2018 +0300
+++ b/QTfrontend/ui/widget/chatwidget.cpp	Fri Jul 20 20:00:52 2018 -0400
@@ -381,7 +381,10 @@
     return QString("<span class=\"nick\">%1</span>").arg(nickname.toHtmlEscaped());
 }
 
-const QRegExp HWChatWidget::URLREGEXP = QRegExp("(http(s)?://)?(www\\.)?((([^/:?&#]+\\.)?hedgewars\\.org|code\\.google\\.com|googlecode\\.com|hh\\.unit22\\.org)(/[^ ]*)?)");
+// Regex to make some URLs clickable for selected domains:
+// - hedgewars.org (official website)
+// - hh.unit22.org (community addon server)
+const QRegExp HWChatWidget::URLREGEXP = QRegExp("(http(s)?://)?(www\\.)?((([^/:?&#]+\\.)?hedgewars\\.org|hh\\.unit22\\.org)(/[^ ]*)?)");
 
 bool HWChatWidget::containsHighlight(const QString & sender, const QString & message)
 {
@@ -401,7 +404,7 @@
 QString HWChatWidget::messageToHTML(const QString & message)
 {
     QString formattedStr = message.toHtmlEscaped();
-    // link some urls
+    // link some URLs
     formattedStr = formattedStr.replace(URLREGEXP, "<a href=\"http\\2://\\4\">\\4</a>");
     return formattedStr;
 }
--- a/QTfrontend/ui/widget/frameTeam.cpp	Sat Jul 21 02:19:32 2018 +0300
+++ b/QTfrontend/ui/widget/frameTeam.cpp	Fri Jul 20 20:00:52 2018 -0400
@@ -126,7 +126,7 @@
 
 bool FrameTeams::isFullTeams() const
 {
-    return teamToWidget.size() >= 8;
+    return teamToWidget.size() >= cMaxTeams;
 }
 
 void FrameTeams::emitTeamColorChanged(const HWTeam& team)
--- a/QTfrontend/util/SDLInteraction.cpp	Sat Jul 21 02:19:32 2018 +0300
+++ b/QTfrontend/util/SDLInteraction.cpp	Fri Jul 20 20:00:52 2018 -0400
@@ -25,6 +25,7 @@
 #include "SDL_mixer.h"
 
 #include "HWApplication.h"
+#include "sdlkeys.h"
 #include "hwform.h" /* you know, we could just put a config singleton lookup function in gameuiconfig or something... */
 #include "gameuiconfig.h"
 
@@ -32,12 +33,6 @@
 
 #include "physfsrwops.h"
 
-extern char sdlkeys[1024][2][128];
-extern char xb360buttons[][128];
-extern char xb360dpad[128];
-extern char xbox360axes[][128];
-
-
 SDLInteraction & SDLInteraction::instance()
 {
     static SDLInteraction instance;
@@ -105,19 +100,23 @@
     QStringList result;
 
 #if SDL_VERSION_ATLEAST(2, 0, 0)
-// TODO or not TODO?
-#else
     int i = 0;
     while(i < 1024 && sdlkeys[i][1][0] != '\0')
         i++;
 
     // Iterate through all game controllers
+    qDebug("Detecting controllers ...");
     for(int jid = 0; jid < SDL_NumJoysticks(); jid++)
     {
         SDL_Joystick* joy = SDL_JoystickOpen(jid);
 
-        // Retrieve the game controller's name and strip "Controller (...)" that's added by some drivers (English only)
-        QString joyname = QString(SDL_JoystickName(jid)).replace(QRegExp("^Controller \\((.*)\\)$"), "\\1");
+        // Retrieve the game controller's name
+        QString joyname = QString(SDL_JoystickNameForIndex(jid));
+
+        // Strip "Controller (...)" that's added by some drivers (English only)
+        joyname.replace(QRegExp("^Controller \\((.*)\\)$"), "\\1");
+
+        qDebug("- Controller no. %d: %s", jid, qPrintable(joyname));
 
         // Connected Xbox 360 controller? Use specific button names then
         // Might be interesting to add 'named' buttons for the most often used gamepads
@@ -129,39 +128,38 @@
         // Register entries for missing axes not assigned to sticks of this joystick/gamepad
         for(int aid = 0; aid < SDL_JoystickNumAxes(joy) && i < 1021; aid++)
         {
-            // Again store the part of the string not changing for multiple uses
-            QString axis = prefix + HWApplication::translate("binds (keys)", "Axis") + QString(" %1 ").arg(aid + 1);
+            QString axis = prefix + HWApplication::translate("binds (keys)", controlleraxis).arg(aid + 1);
 
             // Entry for "Axis Up"
             sprintf(sdlkeys[i][0], "j%da%du", jid, aid);
-            sprintf(sdlkeys[i++][1], "%s", ((isxb && aid < 5) ? (prefix + HWApplication::translate("binds (keys)", xbox360axes[aid * 2])) : axis + HWApplication::translate("binds (keys)", "(Up)")).toUtf8().constData());
+            sprintf(sdlkeys[i++][1], "%s", ((isxb && aid < 5) ? (prefix + HWApplication::translate("binds (keys)", xbox360axes[aid * 2])) : (axis.arg(HWApplication::translate("binds (keys)", controllerup)))).toUtf8().constData());
 
             // Entry for "Axis Down"
             sprintf(sdlkeys[i][0], "j%da%dd", jid, aid);
-            sprintf(sdlkeys[i++][1], "%s", ((isxb && aid < 5) ? (prefix + HWApplication::translate("binds (keys)", xbox360axes[aid * 2 + 1])) : axis + HWApplication::translate("binds (keys)", "(Down)")).toUtf8().constData());
+            sprintf(sdlkeys[i++][1], "%s", ((isxb && aid < 5) ? (prefix + HWApplication::translate("binds (keys)", xbox360axes[aid * 2 + 1])) : (axis.arg(HWApplication::translate("binds (keys)", controllerdown)))).toUtf8().constData());
         }
 
         // Register entries for all coolie hats of this joystick/gamepad
         for(int hid = 0; hid < SDL_JoystickNumHats(joy) && i < 1019; hid++)
         {
             // Again store the part of the string not changing for multiple uses
-            QString hat = prefix + (isxb ? (HWApplication::translate("binds (keys)", xb360dpad) + QString(" ")) : HWApplication::translate("binds (keys)", "Hat") + QString(" %1 ").arg(hid + 1));
+            QString hat = prefix + (isxb ? (HWApplication::translate("binds (keys)", xb360dpad) + QString(" ")) : HWApplication::translate("binds (keys)", controllerhat).arg(hid + 1));
 
             // Entry for "Hat Up"
             sprintf(sdlkeys[i][0], "j%dh%du", jid, hid);
-            sprintf(sdlkeys[i++][1], "%s", (hat + HWApplication::translate("binds (keys)", "(Up)")).toUtf8().constData());
+            sprintf(sdlkeys[i++][1], "%s", hat.arg(HWApplication::translate("binds (keys)", controllerup)).toUtf8().constData());
 
             // Entry for "Hat Down"
             sprintf(sdlkeys[i][0], "j%dh%dd", jid, hid);
-            sprintf(sdlkeys[i++][1], "%s", (hat + HWApplication::translate("binds (keys)", "(Down)")).toUtf8().constData());
+            sprintf(sdlkeys[i++][1], "%s", hat.arg(HWApplication::translate("binds (keys)", controllerdown)).toUtf8().constData());
 
             // Entry for "Hat Left"
             sprintf(sdlkeys[i][0], "j%dh%dl", jid, hid);
-            sprintf(sdlkeys[i++][1], "%s", (hat + HWApplication::translate("binds (keys)", "(Left)")).toUtf8().constData());
+            sprintf(sdlkeys[i++][1], "%s", hat.arg(HWApplication::translate("binds (keys)", controllerleft)).toUtf8().constData());
 
             // Entry for "Hat Right"
             sprintf(sdlkeys[i][0], "j%dh%dr", jid, hid);
-            sprintf(sdlkeys[i++][1], "%s", (hat + HWApplication::translate("binds (keys)", "(Right)")).toUtf8().constData());
+            sprintf(sdlkeys[i++][1], "%s", hat.arg(HWApplication::translate("binds (keys)", controllerright)).toUtf8().constData());
         }
 
         // Register entries for all buttons of this joystick/gamepad
@@ -169,7 +167,7 @@
         {
             // Buttons
             sprintf(sdlkeys[i][0], "j%db%d", jid, bid);
-            sprintf(sdlkeys[i++][1], "%s", (prefix + ((isxb && bid < 10) ? (HWApplication::translate("binds (keys)", xb360buttons[bid]) + QString(" ")) : HWApplication::translate("binds (keys)", "Button") + QString(" %1").arg(bid + 1))).toUtf8().constData());
+            sprintf(sdlkeys[i++][1], "%s", (prefix + ((isxb && bid < 10) ? (HWApplication::translate("binds (keys)", xb360buttons[bid]) + QString(" ")) : HWApplication::translate("binds (keys)", controllerbutton).arg(bid + 1))).toUtf8().constData());
         }
         // Close the game controller as we no longer need it
         SDL_JoystickClose(joy);
--- a/README.md	Sat Jul 21 02:19:32 2018 +0300
+++ b/README.md	Fri Jul 20 20:00:52 2018 -0400
@@ -69,6 +69,24 @@
 * T: Chat
 * U: Team chat
 
+### Default controller controls
+Hedgewars also supports controllers. By default, Hedgewars sets up a few
+controls for your first (!) connected controller.
+This default might not be ideal, we recommend you set manual controls
+in the settings menu.
+
+* 1st D-pad: Walk and aim
+* 2nd D-pad / 1st thumbstick: Move camera/cursor
+* Button 1: Long jump
+* Button 2: High jump
+* Button 3: Attack
+* Button 4: Ammo menu
+* Button 5: Precise
+* Button 6: Select target, or pick weapon (in ammo menu)
+* Button 7: Switch hedgehog
+* Button 8: Find hedgehog / toggle auto camera
+* Button 9: Mission panel
+
 For the full list, go to the Hedgewars settings. Also read the weapon tooltips
 for weapon-specific controls.
 
--- a/cmake_modules/cpackvars.cmake	Sat Jul 21 02:19:32 2018 +0300
+++ b/cmake_modules/cpackvars.cmake	Fri Jul 20 20:00:52 2018 -0400
@@ -19,8 +19,8 @@
 
 if(WIN32 AND NOT UNIX)
     set(CPACK_NSIS_DISPLAY_NAME "Hedgewars")
-    set(CPACK_NSIS_HELP_LINK "http://www.hedgewars.org/")
-    set(CPACK_NSIS_URL_INFO_ABOUT "http://www.hedgewars.org/")
+    set(CPACK_NSIS_HELP_LINK "https://www.hedgewars.org/")
+    set(CPACK_NSIS_URL_INFO_ABOUT "https://www.hedgewars.org/")
     set(CPACK_NSIS_CONTACT "unC0Rr@gmail.com")
     set(CPACK_NSIS_MODIFY_PATH OFF)
     set(CPACK_NSIS_EXECUTABLES_DIRECTORY ".")
--- a/gameServer/Actions.hs	Sat Jul 21 02:19:32 2018 +0300
+++ b/gameServer/Actions.hs	Fri Jul 20 20:00:52 2018 -0400
@@ -634,7 +634,7 @@
         mapM_ processAction
             [
                 CheckBanned True
-                , AnswerClients [sendChan cl] ["CONNECTED", "Hedgewars server http://www.hedgewars.org/", serverVersion]
+                , AnswerClients [sendChan cl] ["CONNECTED", "Hedgewars server https://www.hedgewars.org/", serverVersion]
             ]
         else
         processAction $ ByeClient $ loc "Reconnected too fast"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gameServer/CommandHelp.hs	Fri Jul 20 20:00:52 2018 -0400
@@ -0,0 +1,105 @@
+{-
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2004-2015 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * This 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ \-}
+
+{-# LANGUAGE OverloadedStrings #-}
+module CommandHelp where
+
+import qualified Data.ByteString.Char8 as B
+
+import CoreTypes
+import Utils
+
+-- List and documentation of chat commands
+
+cmdHelpSharedPlayer :: [B.ByteString]
+cmdHelpSharedPlayer = [
+    loc "/info <player>: Show info about player",
+    loc "/me <message>: Chat action, e.g. '/me eats pizza' becomes '* Player eats pizza'",
+    loc "/rnd: Flip a virtual coin and reply with 'heads' or 'tails'",
+    loc "/rnd [A] [B] [C] [...]: Reply with a random word from the given list",
+    loc "/watch <id>: Watch a demo stored on the server with the given ID",
+    loc "/help: Show chat command help"
+    ]
+
+cmdHelpRoomOnlyPlayer :: [B.ByteString]
+cmdHelpRoomOnlyPlayer = [
+    -- For everyone
+    loc "/callvote [arguments]: Start a vote",
+    loc "/vote <yes/no>: Vote 'yes' or 'no' for active vote",
+    -- For room master only
+    loc "/greeting <message>: Set greeting message to be shown to players who join the room",
+    loc "/delegate <player>: Surrender room control to player",
+    loc "/maxteams <N>: Limit maximum number of teams to N"
+    ]
+
+cmdHelpSharedAdmin :: [B.ByteString]
+cmdHelpSharedAdmin = [
+    loc "/global <message>: Send global chat message which can be seen by everyone on the server",
+    loc "/registered_only: Toggle 'registered only' state. If enabled, only registered players can join server",
+    loc "/super_power: Activate your super power. With it you can enter any room and are protected from kicking. Expires when you leave server",
+    -- TODO: Add help for /save
+    loc "/save <parameter>"
+    -- TODO: Add /restart_server? This command seems broken at the moment
+    ]
+
+cmdHelpLobbyOnlyAdmin :: [B.ByteString]
+cmdHelpLobbyOnlyAdmin = [
+    loc "/stats: Query server stats"
+    ]
+
+cmdHelpRoomOnlyAdmin :: [B.ByteString]
+cmdHelpRoomOnlyAdmin = [
+    loc "/force <yes/no>: Force vote result for active vote",
+    loc "/fix: Force this room to stay open when it is empty",
+    loc "/unfix: Undo the /fix command",
+    loc "/saveroom <file name>: Save room configuration into a file",
+    loc "/loadroom <file name>: Load room configuration from a file",
+    -- TODO: Add help for /delete
+    loc "/delete <parameter>"
+    ]
+
+cmdHelpHeaderLobby :: [B.ByteString]
+cmdHelpHeaderLobby = [ loc "List of lobby chat commands:" ]
+
+cmdHelpHeaderRoom :: [B.ByteString]
+cmdHelpHeaderRoom = [ loc "List of room chat commands:" ]
+
+cmdHelpHeaderAdmin :: [B.ByteString]
+cmdHelpHeaderAdmin = [ loc "Commands for server admins only:" ]
+
+-- Put it all together
+-- Lobby commands
+cmdHelpLobbyPlayer :: [B.ByteString]
+cmdHelpLobbyPlayer = cmdHelpHeaderLobby ++ cmdHelpSharedPlayer
+
+cmdHelpLobbyAdmin :: [B.ByteString]
+cmdHelpLobbyAdmin = cmdHelpLobbyPlayer ++ cmdHelpHeaderAdmin ++ cmdHelpLobbyOnlyAdmin ++ cmdHelpSharedAdmin
+
+-- Room commands
+cmdHelpRoomPlayer :: [B.ByteString]
+cmdHelpRoomPlayer = cmdHelpHeaderRoom ++ cmdHelpRoomOnlyPlayer ++ cmdHelpSharedPlayer
+
+cmdHelpRoomAdmin :: [B.ByteString]
+cmdHelpRoomAdmin = cmdHelpRoomPlayer ++ cmdHelpHeaderAdmin ++ cmdHelpRoomOnlyAdmin ++ cmdHelpSharedAdmin
+
+-- Helper functions for chat command handler
+cmdHelpActionEntry :: [ClientChan] -> B.ByteString -> Action
+cmdHelpActionEntry chan msg = AnswerClients chan [ "CHAT", "[server]", B.concat [ " ", msg ] ]
+
+cmdHelpActionList :: [ClientChan] -> [B.ByteString] -> [Action]
+cmdHelpActionList chan list = map (cmdHelpActionEntry chan) list
--- a/gameServer/Consts.hs	Sat Jul 21 02:19:32 2018 +0300
+++ b/gameServer/Consts.hs	Fri Jul 20 20:00:52 2018 -0400
@@ -23,3 +23,12 @@
 
 serverVersion :: B.ByteString
 serverVersion = "3"
+
+cHogsPerTeam :: Int
+cHogsPerTeam = 8
+
+cMaxTeams :: Int
+cMaxTeams = 8
+
+cMaxHHs :: Int
+cMaxHHs = cHogsPerTeam * cMaxTeams
--- a/gameServer/CoreTypes.hs	Sat Jul 21 02:19:32 2018 +0300
+++ b/gameServer/CoreTypes.hs	Fri Jul 20 20:00:52 2018 -0400
@@ -310,8 +310,8 @@
     ServerInfo
         True
         False
-        "<h2><p align=center><a href=\"http://www.hedgewars.org/\">http://www.hedgewars.org/</a></p></h2>"
-        "<font color=yellow><h3 align=center>Hedgewars 0.9.24 is out! Please update.</h3><p align=center><a href=http://hedgewars.org/download.html>Download page here</a></font>"
+        "<h2><p align=center><a href=\"https://www.hedgewars.org/\">https://www.hedgewars.org/</a></p></h2>"
+        "<font color=yellow><h3 align=center>Hedgewars 0.9.24 is out! Please update.</h3><p align=center><a href=https://hedgewars.org/download.html>Download page here</a></font>"
         55 -- latestReleaseVersion
         41 -- earliestCompatibleVersion
         46631
--- a/gameServer/HWProtoCore.hs	Sat Jul 21 02:19:32 2018 +0300
+++ b/gameServer/HWProtoCore.hs	Fri Jul 20 20:00:52 2018 -0400
@@ -87,9 +87,14 @@
                          | otherwise = let (c, p) = extractParameters msg in
                                            if B.null p then handleCmd ["CALLVOTE", c] else handleCmd ["CALLVOTE", c, p]
         h "VOTE" msg | not $ B.null msg = handleCmd ["VOTE", upperCase msg]
+                     | otherwise = handleCmd ["VOTE", ""]
+        h "FORCE" msg | not $ B.null msg = handleCmd ["VOTE", upperCase msg, "FORCE"]
+                      | otherwise = handleCmd ["VOTE", "", "FORCE"]
+        h "VOTE" msg | not $ B.null msg = handleCmd ["VOTE", upperCase msg]
         h "FORCE" msg | not $ B.null msg = handleCmd ["VOTE", upperCase msg, "FORCE"]
         h "MAXTEAMS" n | not $ B.null n = handleCmd ["MAXTEAMS", n]
         h "INFO" n | not $ B.null n = handleCmd ["INFO", n]
+        h "HELP" _ = handleCmd ["HELP"]
         h "RESTART_SERVER" "YES" = handleCmd ["RESTART_SERVER"]
         h "REGISTERED_ONLY" _ = serverAdminOnly $ do
             cl <- thisClient
@@ -98,7 +103,8 @@
                 , AnswerClients [sendChan cl] ["CHAT", "[server]", "'Registered only' state toggled"]
                 ]
         h "SUPER_POWER" _ = serverAdminOnly $ return [ModifyClient (\c -> c{hasSuperPower = True})]
-        h c p = return [Warning $ B.concat ["Unknown cmd: /", c, " ", p]]
+        h c p = return [Warning $ B.concat [ loc "Unknown command:", " /", c, " ", p, "<br/>", loc "Say '/help' in chat for a list of commands" ]]
+
 
         extractParameters p = let (a, b) = B.break (== ' ') p in (upperCase a, B.dropWhile (== ' ') b)
 
@@ -113,14 +119,14 @@
     let clRoom = room rnc roomId
     let roomMasterSign = if isMaster cl then "+" else ""
     let adminSign = if isAdministrator cl then "@" else ""
-    let rInfo = if roomId /= lobbyId then B.concat [adminSign, roomMasterSign, "room ", name clRoom] else adminSign `B.append` "lobby"
+    let rInfo = if roomId /= lobbyId then B.concat [adminSign, roomMasterSign, loc "room", " ", name clRoom] else adminSign `B.append` (loc "lobby")
     let roomStatus = if isJust $ gameInfo clRoom then
-            if teamsInGame cl > 0 then "(playing)" else "(spectating)"
+            if teamsInGame cl > 0 then (loc "(playing)") else (loc "(spectating)")
             else
             ""
     let hostStr = if isAdminAsking then host cl else B.empty
     if noSuchClient then
-        return []
+        answerClient [ "CHAT", "[server]", loc "Player is not online." ]
         else
         answerClient [
             "INFO",
--- a/gameServer/HWProtoInRoomState.hs	Sat Jul 21 02:19:32 2018 +0300
+++ b/gameServer/HWProtoInRoomState.hs	Fri Jul 20 20:00:52 2018 -0400
@@ -27,11 +27,13 @@
 import Control.Monad.Reader
 --------------------------------------
 import CoreTypes
+import Consts
 import Utils
 import HandlerUtils
 import RoomsAndClients
 import EngineInteraction
 import Votes
+import CommandHelp
 
 startGame :: Reader (ClientIndex, IRnC) [Action]
 startGame = do
@@ -144,7 +146,7 @@
                 AnswerClients roomChans ["HH_NUM", tName, showB $ hhnum newTeam]
                 ]
         where
-        canAddNumber rt = (48::Int) - (sum $ map hhnum rt)
+        canAddNumber rt = (cMaxHHs) - (sum $ map hhnum rt)
         findTeam = find (\t -> tName == teamname t) . teams
         dif = readInt_ difStr
         hhsList [] = []
@@ -153,7 +155,7 @@
         newTeamHHNum rt p = min p (canAddNumber rt)
         maxTeams r
             | roomProto r < 38 = 6
-            | otherwise = 8
+            | otherwise = cMaxTeams
 
 
 handleCmd_inRoom ["REMOVE_TEAM", tName] = do
@@ -196,7 +198,7 @@
             [ProtocolError $ loc "You're not the room master!"]
         else if isNothing maybeTeam then
             []
-        else if hhNumber < 1 || hhNumber > 8 || hhNumber > canAddNumber r + hhnum team then
+        else if hhNumber < 1 || hhNumber > cHogsPerTeam || hhNumber > canAddNumber r + hhnum team then
             [AnswerClients clChan ["HH_NUM", teamName, showB $ hhnum team]]
         else
             [ModifyRoom $ modifyTeam team{hhnum = hhNumber},
@@ -204,7 +206,7 @@
     where
         hhNumber = readInt_ numberStr
         findTeam = find (\t -> teamName == teamname t) . teams
-        canAddNumber = (-) 48 . sum . map hhnum . teams
+        canAddNumber = (-) cMaxHHs . sum . map hhnum . teams
 
 
 
@@ -393,7 +395,7 @@
 handleCmd_inRoom ["MAXTEAMS", n] = roomAdminOnly $ do
     cl <- thisClient
     let m = readInt_ n
-    if m < 2 || m > 8 then
+    if m < 2 || m > cMaxTeams then
         return [AnswerClients [sendChan cl] ["CHAT", "[server]", loc "/maxteams: specify number from 2 to 8"]]
     else
         return [ModifyRoom (\r -> r{teamsNumberLimit = m})]
@@ -404,6 +406,13 @@
 handleCmd_inRoom ["UNFIX"] = serverAdminOnly $
     return [ModifyRoom (\r -> r{isSpecial = False})]
 
+handleCmd_inRoom ["HELP"] = do
+    cl <- thisClient
+    if isAdministrator cl then
+        return (cmdHelpActionList [sendChan cl] cmdHelpRoomAdmin)
+    else
+        return (cmdHelpActionList [sendChan cl] cmdHelpRoomPlayer)
+
 handleCmd_inRoom ["GREETING", msg] = do
     cl <- thisClient
     rm <- thisRoom
@@ -476,7 +485,7 @@
     cl <- thisClient
     let h = readInt_ hhs
 
-    if h > 0 && h <= 8 then
+    if h > 0 && h <= cHogsPerTeam then
         startVote $ VoteHedgehogsPerTeam h
         else
         return [AnswerClients [sendChan cl] ["CHAT", "[server]", loc "/callvote hedgehogs: Specify number from 1 to 8."]]
@@ -487,8 +496,13 @@
     let b = if m == "YES" then Just True else if m == "NO" then Just False else Nothing
     if isJust b then
         voted (p == ["FORCE"]) (fromJust b)
-        else
-        return [AnswerClients [sendChan cl] ["CHAT", "[server]", "/vote: Please use 'yes' or 'no'."]]
+    else
+        return [AnswerClients [sendChan cl] ["CHAT", "[server]",
+            if (p == ["FORCE"]) then
+                loc "/force: Please use 'yes' or 'no'."
+            else
+                loc "/vote: Please use 'yes' or 'no'."
+        ]]
 
 
 handleCmd_inRoom ["SAVE", stateName, location] = serverAdminOnly $ do
--- a/gameServer/HWProtoLobbyState.hs	Sat Jul 21 02:19:32 2018 +0300
+++ b/gameServer/HWProtoLobbyState.hs	Fri Jul 20 20:00:52 2018 -0400
@@ -29,6 +29,7 @@
 import HandlerUtils
 import RoomsAndClients
 import EngineInteraction
+import CommandHelp
 
 
 handleCmd_lobby :: CmdHandler
@@ -166,6 +167,13 @@
     c <- liftM sendChan thisClient
     return [Random [c] rs]
 
+handleCmd_lobby ["HELP"] = do
+    cl <- thisClient
+    if isAdministrator cl then
+        return (cmdHelpActionList [sendChan cl] cmdHelpLobbyAdmin)
+    else
+        return (cmdHelpActionList [sendChan cl] cmdHelpLobbyPlayer)
+
     ---------------------------
     -- Administrator's stuff --
 
--- a/gameServer/Votes.hs	Sat Jul 21 02:19:32 2018 +0300
+++ b/gameServer/Votes.hs	Fri Jul 20 20:00:52 2018 -0400
@@ -28,6 +28,7 @@
 import Data.Maybe
 import Control.Applicative
 -------------------
+import Consts
 import Utils
 import CoreTypes
 import HandlerUtils
@@ -118,7 +119,7 @@
         let answers = concatMap (\t -> 
                 [ModifyRoom $ modifyTeam t{hhnum = h}
                 , AnswerClients chans ["HH_NUM", teamname t, showB h]]
-                ) $ if length curteams * h > 48 then [] else curteams
+                ) $ if length curteams * h > cMaxHHs then [] else curteams
             ;
             curteams =
                 if isJust $ gameInfo rm then
--- a/gameServer/hedgewars-server.cabal	Sat Jul 21 02:19:32 2018 +0300
+++ b/gameServer/hedgewars-server.cabal	Fri Jul 20 20:00:52 2018 -0400
@@ -2,7 +2,7 @@
 Version:             0.1
 Synopsis:            hedgewars server
 Description:         hedgewars server
-Homepage:            http://www.hedgewars.org/
+Homepage:            https://www.hedgewars.org/
 License:             GPL-2
 Author:              unC0Rr
 Maintainer:          a.korotaev@hedgewars.org
--- a/gameServer2/src/protocol/messages.rs	Sat Jul 21 02:19:32 2018 +0300
+++ b/gameServer2/src/protocol/messages.rs	Fri Jul 20 20:00:52 2018 -0400
@@ -260,7 +260,7 @@
             Pong => msg!["PONG"],
             Connected(protocol_version) => msg![
                 "CONNECTED",
-                "Hedgewars server http://www.hedgewars.org/",
+                "Hedgewars server https://www.hedgewars.org/",
                 protocol_version],
             Bye(msg) => msg!["BYE", msg],
             Nick(nick) => msg!["NICK", nick],
--- a/hedgewars/ArgParsers.pas	Sat Jul 21 02:19:32 2018 +0300
+++ b/hedgewars/ArgParsers.pas	Fri Jul 20 20:00:52 2018 -0400
@@ -34,6 +34,7 @@
 implementation
 uses uVariables, uTypes, uUtils, uSound, uConsts;
 var isInternal: Boolean;
+    helpCommandUsed: Boolean;
 
 {$IFDEF HWLIBRARY}
 
@@ -100,8 +101,9 @@
     WriteLn(stdout, ' --help');
     WriteLn(stdout, '');
     WriteLn(stdout, 'For more detailed help and examples go to:');
-    WriteLn(stdout, 'http://hedgewars.org/kb/CommandLineOptions');
-    GameType:= gmtSyntax;
+    WriteLn(stdout, 'https://hedgewars.org/kb/CommandLineOptions');
+    GameType:= gmtSyntaxHelp;
+    helpCommandUsed:= true;
 end;
 
 procedure setDepth(var paramIndex: LongInt);
@@ -357,12 +359,13 @@
         inc(paramIndex);
         end;
     if wrongParameter = true then
-        GameType:= gmtSyntax;
+        GameType:= gmtBadSyntax;
 end;
 
 procedure GetParams;
 begin
     isInternal:= (ParamStr(1) = '--internal');
+    helpCommandUsed:= false;
 
     UserPathPrefix := _S'.';
     PathPrefix     := cDefaultPathPrefix;
@@ -372,18 +375,19 @@
     if (isInternal) and (ParamCount<=1) then
         begin
         WriteLn(stderr, '--internal should not be manually used');
-        GameType := gmtSyntax;
+        GameType := gmtBadSyntax;
         end;
 
-    if (not cTestLua) and (not isInternal) and (recordFileName = '') then
-        begin
-        WriteLn(stderr, 'You must specify a replay file');
-        GameType := gmtSyntax;
-        end
-    else if (recordFileName <> '') then
-        WriteLn(stdout, 'Attempting to play demo file "' + recordFilename + '"');
+    if (not helpCommandUsed) then
+        if (not cTestLua) and (not isInternal) and (recordFileName = '') then
+            begin
+            WriteLn(stderr, 'You must specify a replay file');
+            GameType := gmtBadSyntax;
+            end
+        else if (recordFileName <> '') then
+            WriteLn(stdout, 'Attempting to play demo file "' + recordFilename + '"');
 
-    if (GameType = gmtSyntax) then
+    if (GameType = gmtBadSyntax) then
         WriteLn(stderr, 'Please use --help to see possible arguments and their usage');
 
     (*
--- a/hedgewars/LuaPas.pas	Sat Jul 21 02:19:32 2018 +0300
+++ b/hedgewars/LuaPas.pas	Fri Jul 20 20:00:52 2018 -0400
@@ -114,7 +114,7 @@
 (*
 ** $Id: lua.h,v 1.216 2006/01/10 12:50:13 roberto Exp $
 ** Lua - An Extensible Extension Language
-** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
+** Lua.org, PUC-Rio, Brazil (https://www.lua.org)
 ** See Copyright Notice at the end of this file
 *)
 
--- a/hedgewars/SDLh.pas	Sat Jul 21 02:19:32 2018 +0300
+++ b/hedgewars/SDLh.pas	Fri Jul 20 20:00:52 2018 -0400
@@ -541,8 +541,8 @@
 /////////////////////////////////////////////////////////////////
 
 // two important reference points for the wanderers of this area
-// http://www.freepascal.org/docs-html/ref/refsu5.html
-// http://www.freepascal.org/docs-html/prog/progsu144.html
+// https://www.freepascal.org/docs-html/ref/refsu5.html
+// https://www.freepascal.org/docs-html/prog/progsu144.html
 
 type
     PSDL_Window   = Pointer;
@@ -553,6 +553,7 @@
     TSDL_FingerId = Int64;
     TSDL_Keycode = LongInt;
     TSDL_Scancode = LongInt;
+    TSDL_JoystickID = LongInt;
 
     TSDL_eventaction = (SDL_ADDEVENT, SDL_PEEPEVENT, SDL_GETEVENT);
 
@@ -765,7 +766,7 @@
     TSDL_ControllerAxisEvent = record
         type_: LongWord;
         timestamp: LongWord;
-        which: LongInt;
+        which: TSDL_JoystickID;
         axis, padding1, padding2, padding3: Byte;
         value: SmallInt;
         padding4: Word;
@@ -774,14 +775,14 @@
     TSDL_ControllerButtonEvent = record
         type_: LongWord;
         timestamp: LongWord;
-        which: LongInt;
+        which: TSDL_JoystickID;
         button, states, padding1, padding2: Byte;
         end;
 
     TSDL_ControllerDeviceEvent = record
         type_: LongWord;
         timestamp: LongWord;
-        which: SmallInt;
+        which: LongInt;
         end;
 
     TSDL_JoyDeviceEvent = TSDL_ControllerDeviceEvent;
@@ -829,17 +830,17 @@
     TSDL_JoyAxisEvent = record
         type_: LongWord;
         timestamp: LongWord;
-        which: LongWord;
+        which: TSDL_JoystickID;
         axis: Byte;
         padding1, padding2, padding3: Byte;
-        value: LongInt;
+        value: SmallInt;
         padding4: Word;
         end;
 
     TSDL_JoyBallEvent = record
         type_: LongWord;
         timestamp: LongWord;
-        which: LongWord;
+        which: TSDL_JoystickID;
         ball: Byte;
         padding1, padding2, padding3: Byte;
         xrel, yrel: SmallInt;
@@ -848,7 +849,7 @@
     TSDL_JoyHatEvent = record
         type_: LongWord;
         timestamp: LongWord;
-        which: LongWord;
+        which: TSDL_JoystickID;
         hat: Byte;
         value: Byte;
         padding1, padding2: Byte;
@@ -857,10 +858,11 @@
     TSDL_JoyButtonEvent = record
         type_: LongWord;
         timestamp: LongWord;
-        which: Byte;
+        which: TSDL_JoystickID;
         button: Byte;
         state: Byte;
         padding1: Byte;
+        padding2: Byte;
         end;
 
     TSDL_QuitEvent = record
@@ -1165,7 +1167,7 @@
 procedure SDL_UnlockAudio; cdecl; external SDLLibName;
 
 function  SDL_NumJoysticks: LongInt; cdecl; external SDLLibName;
-function  SDL_JoystickName(idx: LongInt): PChar; cdecl; external SDLLibName;
+function  SDL_JoystickNameForIndex(idx: LongInt): PChar; cdecl; external SDLLibName;
 function  SDL_JoystickOpen(idx: LongInt): PSDL_Joystick; cdecl; external SDLLibName;
 function  SDL_JoystickOpened(idx: LongInt): LongInt; cdecl; external SDLLibName;
 function  SDL_JoystickIndex(joy: PSDL_Joystick): LongInt; cdecl; external SDLLibName;
--- a/hedgewars/hwLibrary.pas	Sat Jul 21 02:19:32 2018 +0300
+++ b/hedgewars/hwLibrary.pas	Fri Jul 20 20:00:52 2018 -0400
@@ -24,7 +24,7 @@
  * and language of choice.
  *
  * See also: C declarations on Wikipedia
- *           http://en.wikipedia.org/wiki/X86_calling_conventions#cdecl
+ *           https://en.wikipedia.org/wiki/X86_calling_conventions#cdecl
  *)
 
 Library hwLibrary;
--- a/hedgewars/hwengine.pas	Sat Jul 21 02:19:32 2018 +0300
+++ b/hedgewars/hwengine.pas	Fri Jul 20 20:00:52 2018 -0400
@@ -45,12 +45,14 @@
 procedure preInitEverything();
 procedure initEverything(complete:boolean);
 procedure freeEverything(complete:boolean);
+procedure catchUnhandledException(Obj: TObject; Addr: Pointer; FrameCount: Longint; Frames: PPointer);
 
 implementation
 {$ELSE}
 procedure preInitEverything(); forward;
 procedure initEverything(complete:boolean); forward;
 procedure freeEverything(complete:boolean); forward;
+procedure catchUnhandledException(Obj: TObject; Addr: Pointer; FrameCount: Longint; Frames: PPointer); forward;
 {$ENDIF}
 
 {$IFDEF WIN32}
@@ -597,6 +599,28 @@
     freeEverything(false);
 end;
 
+// Write backtrace to console and log when an unhandled exception occurred
+procedure catchUnhandledException(Obj: TObject; Addr: Pointer; FrameCount: Longint; Frames: PPointer);
+var
+  Message: string;
+  i: LongInt;
+begin
+  WriteLnToConsole('An unhandled exception occurred at $' + HexStr(Addr) + ':');
+  if Obj is exception then
+   begin
+     Message := Exception(Obj).ClassName + ': ' + Exception(Obj).Message;
+     WriteLnToConsole(Message);
+   end
+  else
+    WriteLnToConsole('Exception object ' + Obj.ClassName + ' is not of class Exception.');
+  WriteLnToConsole(BackTraceStrFunc(Addr));
+  if (FrameCount > 0) then
+    begin
+      for i := 0 to FrameCount - 1 do
+        WriteLnToConsole(BackTraceStrFunc(Frames[i]));
+    end;
+end;
+
 {$IFDEF HWLIBRARY}
 function RunEngine(argc: LongInt; argv: PPChar): LongInt; cdecl; export;
 begin
@@ -624,17 +648,20 @@
     // workaround for pascal's ParamStr and ParamCount
     init(argc, argv);
 {$ENDIF}
+    // Custom procedure for unhandled exceptions; ExceptProc is used by sysutils module
+    ExceptProc:= @catchUnhandledException;
+
     preInitEverything();
 
     GetParams();
 
     if GameType = gmtLandPreview then
         GenLandPreview()
-    else if GameType <> gmtSyntax then
+    else if (GameType <> gmtBadSyntax) and (GameType <> gmtSyntaxHelp) then
         Game();
 
-    // return 1 when engine is not called correctly
-    if GameType = gmtSyntax then
+    // return error when engine is not called correctly
+    if GameType = gmtBadSyntax then
         {$IFDEF PAS2C}
         exit(HaltUsageError);
         {$ELSE}
--- a/hedgewars/uAmmos.pas	Sat Jul 21 02:19:32 2018 +0300
+++ b/hedgewars/uAmmos.pas	Fri Jul 20 20:00:52 2018 -0400
@@ -160,7 +160,7 @@
 
 function GetAmmoByNum(num: LongInt): PHHAmmo;
 begin
-    if checkFails(num < StoreCnt, 'Invalid store number', true) then
+    if checkFails(num < StoreCnt, 'Invalid ammo store number', true) then
         GetAmmoByNum:= nil
     else
         GetAmmoByNum:= StoresList[num]
--- a/hedgewars/uConsts.pas	Sat Jul 21 02:19:32 2018 +0300
+++ b/hedgewars/uConsts.pas	Fri Jul 20 20:00:52 2018 -0400
@@ -37,6 +37,7 @@
     HaltFatalError      =  52;
     HaltStartupError    =  53;
     HaltFatalErrorNoIPC =  54;
+    HaltVideoRec        =  55;
 
     // for automatic tests
     HaltTestSuccess     =  0;
@@ -171,7 +172,7 @@
 
     cMaxTeams        = 8;
     cMaxHHIndex      = 7;
-    cMaxHHs          = 48;
+    cMaxHHs          = cMaxTeams * (cMaxHHIndex+1);
 
     cMaxEdgePoints = 32768;
 
--- a/hedgewars/uCursor.pas	Sat Jul 21 02:19:32 2018 +0300
+++ b/hedgewars/uCursor.pas	Fri Jul 20 20:00:52 2018 -0400
@@ -9,7 +9,7 @@
 
 implementation
 
-uses SDLh, uVariables;
+uses SDLh, uVariables, uTypes;
 
 procedure init;
 begin
@@ -18,6 +18,8 @@
 
 procedure resetPosition;
 begin
+    if GameType = gmtRecord then
+        exit;
     // Move curser by 1px in case it's already centered.
     // The game camera in the Alpha for 0.9.23 screwed up if
     // the game started with the mouse already being centered.
@@ -31,13 +33,14 @@
 procedure updatePosition;
 var x, y: LongInt;
 begin
-    SDL_GetMouseState(@x, @y);
+    if GameType <> gmtRecord then
+        SDL_GetMouseState(@x, @y);
 
     if(x <> cScreenWidth div 2) or (y <> cScreenHeight div 2) then
     begin
         handlePositionUpdate(x - cScreenWidth div 2, y - cScreenHeight div 2);
 
-        if cHasFocus then
+        if cHasFocus and (GameType <> gmtRecord) then
             SDL_WarpMouse(cScreenWidth div 2, cScreenHeight div 2);
     end
 end;
--- a/hedgewars/uDebug.pas	Sat Jul 21 02:19:32 2018 +0300
+++ b/hedgewars/uDebug.pas	Fri Jul 20 20:00:52 2018 -0400
@@ -56,7 +56,7 @@
     if not Assert then
         begin
         lastConsoleLine:= Msg;
-        OutError(Msg, false);
+        OutError(Msg, isFatal);
         end;
 
     allOK:= allOK and (Assert or (not isFatal));
--- a/hedgewars/uGame.pas	Sat Jul 21 02:19:32 2018 +0300
+++ b/hedgewars/uGame.pas	Fri Jul 20 20:00:52 2018 -0400
@@ -86,7 +86,7 @@
         begin
         j:= Volume;
         i:= ChangeVolume(cVolumeDelta);
-        if isAudioMuted and (j<>i) then
+        if (not cIsSoundEnabled) or (isAudioMuted and (j<>i)) then
             AddCaption(trmsg[sidMute], cWhiteColor, capgrpVolume)
         else if not isAudioMuted then
             begin
--- a/hedgewars/uIO.pas	Sat Jul 21 02:19:32 2018 +0300
+++ b/hedgewars/uIO.pas	Fri Jul 20 20:00:52 2018 -0400
@@ -515,7 +515,7 @@
         end
     else
         if CurrentTeam^.ExtDriven then
-            OutError('got /put while not being in choose target mode', false)
+            OutError('Got /put while not being in choose target mode', false)
 end;
 
 procedure initModule;
--- a/hedgewars/uInputHandler.pas	Sat Jul 21 02:19:32 2018 +0300
+++ b/hedgewars/uInputHandler.pas	Fri Jul 20 20:00:52 2018 -0400
@@ -109,7 +109,7 @@
     else begin
         code:= 0;
         while (code <= High(CurrentBinds.indices)) and (CurrentBinds.indices[code] <> index) do inc(code);
-        checkFails(code <= High(CurrentBinds.indices), 'binds registry inconsistency', True);
+        checkFails(code <= High(CurrentBinds.indices), 'Inconsistency in key binding registry', True);
         KeyBindToCode:= code;
     end;
 end;
@@ -333,7 +333,7 @@
 procedure RegisterBind(var binds: TBinds; key, value: shortstring);
 var code: LongInt;
 begin
-    checkFails(binds.lastIndex < 255, 'too many binds', true);
+    checkFails(binds.lastIndex < 255, 'Too many key bindings', true);
 
     code:= KeyNameToCode(key);
 
@@ -393,11 +393,40 @@
     RegisterBind(DefaultBinds, 'right', '+right');
     RegisterBind(DefaultBinds, 'left_shift', '+precise');
 
+    // Default controls for first connected controller
+    { NOTE: This is provided for convenience so players
+    don't have to set-up the controller entirely in a new install.
+    It's not ideal, so players are still encourages to
+    set up things manually. }
+    // Essential controls
+    RegisterBind(DefaultBinds, 'j0h0r', '+right');
+    RegisterBind(DefaultBinds, 'j0h0l', '+left');
+    RegisterBind(DefaultBinds, 'j0h0u', '+up');
+    RegisterBind(DefaultBinds, 'j0h0d', '+down');
+    RegisterBind(DefaultBinds, 'j0b0', 'ljump');
+    RegisterBind(DefaultBinds, 'j0b1', 'hjump');
+    RegisterBind(DefaultBinds, 'j0b2', '+attack');
+    RegisterBind(DefaultBinds, 'j0b3', 'ammomenu');
+    RegisterBind(DefaultBinds, 'j0b4', '+precise');
+    RegisterBind(DefaultBinds, 'j0b5', 'put');
+    RegisterBind(DefaultBinds, 'j0b6', 'switch');
+    // TODO: Add controller-friendly way to change timer
 
-    RegisterBind(DefaultBinds, 'j0a0u', '+left');
-    RegisterBind(DefaultBinds, 'j0a0d', '+right');
-    RegisterBind(DefaultBinds, 'j0a1u', '+up');
-    RegisterBind(DefaultBinds, 'j0a1d', '+down');
+    // Cursor movement (also essential)
+    RegisterBind(DefaultBinds, 'j0h1r', '+cur_r');
+    RegisterBind(DefaultBinds, 'j0h1l', '+cur_l');
+    RegisterBind(DefaultBinds, 'j0h1d', '+cur_d');
+    RegisterBind(DefaultBinds, 'j0h1u', '+cur_u');
+
+    RegisterBind(DefaultBinds, 'j0a0u', '+cur_r');
+    RegisterBind(DefaultBinds, 'j0a0d', '+cur_l');
+    RegisterBind(DefaultBinds, 'j0a1u', '+cur_d');
+    RegisterBind(DefaultBinds, 'j0a1d', '+cur_u');
+
+    // Additional controls
+    RegisterBind(DefaultBinds, 'j0b7', 'findhh');
+    RegisterBind(DefaultBinds, 'j0b8', '+mission');
+
     for i:= 1 to 10 do RegisterBind(DefaultBinds, 'f'+IntToStr(i), 'slot '+char(48+i));
     for i:= 1 to 5  do RegisterBind(DefaultBinds, IntToStr(i), 'timer '+IntToStr(i));
 
@@ -514,10 +543,10 @@
     begin
     for j:= 0 to pred(ControllerNumControllers) do
         begin
-        WriteLnToConsole('Using game controller: ' + shortstring(SDL_JoystickName(j)));
+        WriteLnToConsole('Game controller no. ' + IntToStr(j) + ', name "' + shortstring(SDL_JoystickNameForIndex(j)) + '":');
         Controller[j]:= SDL_JoystickOpen(j);
         if Controller[j] = nil then
-            WriteLnToConsole('* Failed to open game controller!')
+            WriteLnToConsole('* Failed to open game controller no. ' + IntToStr(j) + '!')
         else
             begin
             ControllerNumAxes[j]:= SDL_JoystickNumAxes(Controller[j]);
--- a/hedgewars/uLand.pas	Sat Jul 21 02:19:32 2018 +0300
+++ b/hedgewars/uLand.pas	Fri Jul 20 20:00:52 2018 -0400
@@ -314,7 +314,7 @@
             end else getRandom(1);
 
         case cTemplateFilter of
-        0: OutError('Ask unC0Rr about what you did wrong', true);
+        0: OutError('Error selecting TemplateFilter. Ask unC0Rr about what you did wrong', true);
         1: SelectTemplate:= SmallTemplates[getrandom(TemplateCounts[cTemplateFilter])];
         2: SelectTemplate:= MediumTemplates[getrandom(TemplateCounts[cTemplateFilter])];
         3: SelectTemplate:= LargeTemplates[getrandom(TemplateCounts[cTemplateFilter])];
@@ -974,7 +974,7 @@
     if digest = '' then
         digest:= s
     else
-        checkFails(s = digest, 'Different map or critical resources loaded, sorry', true);
+        checkFails(s = digest, 'Loaded map or other critical resource does not match across all players', true);
 end;
 
 procedure chSendLandDigest(var s: shortstring);
--- a/hedgewars/uLandObjects.pas	Sat Jul 21 02:19:32 2018 +0300
+++ b/hedgewars/uLandObjects.pas	Fri Jul 20 20:00:52 2018 -0400
@@ -647,9 +647,9 @@
 procedure CheckRect(Width, Height, x, y, w, h: LongWord);
 begin
     if (x + w > Width) then
-        OutError('Object''s rectangle exceeds image: x + w (' + inttostr(x) + ' + ' + inttostr(w) + ') > Width (' + inttostr(Width) + ')', true);
+        OutError('Broken theme. Object''s rectangle exceeds image: x + w (' + inttostr(x) + ' + ' + inttostr(w) + ') > Width (' + inttostr(Width) + ')', true);
     if (y + h > Height) then
-        OutError('Object''s rectangle exceeds image: y + h (' + inttostr(y) + ' + ' + inttostr(h) + ') > Height (' + inttostr(Height) + ')', true);
+        OutError('Broken theme. Object''s rectangle exceeds image: y + h (' + inttostr(y) + ' + ' + inttostr(h) + ') > Height (' + inttostr(Height) + ')', true);
 end;
 
 procedure ReadRect(var rect: TSDL_Rect; var s: ShortString);
@@ -901,7 +901,7 @@
             Maxcnt:= StrToInt(Trim(Copy(s, 1, Pred(i))));
             Delete(s, 1, i);
             if (Maxcnt < 1) or (Maxcnt > MAXTHEMEOBJECTS) then
-                OutError('Object''s max count should be between 1 and '+ inttostr(MAXTHEMEOBJECTS) +' (it was '+ inttostr(Maxcnt) +').', true);
+                OutError('Broken theme. Object''s max. count should be between 1 and '+ inttostr(MAXTHEMEOBJECTS) +' (it was '+ inttostr(Maxcnt) +').', true);
             ChecksumLandObjectImage(Surf);
             ChecksumLandObjectImage(Mask);
 
@@ -920,7 +920,7 @@
             end;
 
             if inrectcnt > MAXOBJECTRECTS then
-                OutError('Object''s inland rectangle count should be no more than '+ inttostr(MAXOBJECTRECTS) +' (it was '+ inttostr(inrectcnt) +').', true);
+                OutError('Broken theme. Object''s inland rectangle count should be no more than '+ inttostr(MAXOBJECTRECTS) +' (it was '+ inttostr(inrectcnt) +').', true);
 
             for ii:= 0 to Pred(inrectcnt) do
                 ReadRect(inland[ii], s);
@@ -930,7 +930,7 @@
             Delete(s, 1, i);
 
             if outrectcnt > MAXOBJECTRECTS then
-                OutError('Object''s outland rectangle count should be no more than '+ inttostr(MAXOBJECTRECTS) +' (it was '+ inttostr(outrectcnt) +').', true);
+                OutError('Broken theme. Object''s outland rectangle count should be no more than '+ inttostr(MAXOBJECTRECTS) +' (it was '+ inttostr(outrectcnt) +').', true);
 
             for ii:= 0 to Pred(outrectcnt) do
                 ReadRect(outland[ii], s);
@@ -944,13 +944,13 @@
             if ThemeObjects.objs[ii].Name = nameRef then with ThemeObjects.objs[ii] do
                 begin
                 if anchorcnt <> 0 then
-                    OutError('Duplicate anchors declaration for ' + nameRef, true);
+                    OutError('Broken theme. Duplicate anchors declaration for object ' + nameRef, true);
                 Delete(s, 1, i);
                 i:= Pos(',', s);
                 anchorcnt:= StrToInt(Trim(Copy(s, 1, Pred(i))));
                 Delete(s, 1, i);
                 if anchorcnt > MAXOBJECTRECTS then
-                    OutError('Object''s anchor rectangle count should be no more than '+ inttostr(MAXOBJECTRECTS) +' (it was '+ inttostr(anchorcnt) +').', true);
+                    OutError('Broken theme. Object''s anchor rectangle count should be no more than '+ inttostr(MAXOBJECTRECTS) +' (it was '+ inttostr(anchorcnt) +').', true);
                 for t:= 0 to Pred(anchorcnt) do
                     ReadRect(anchors[t], s);
                 break
@@ -964,13 +964,13 @@
             if ThemeObjects.objs[ii].Name = nameRef then with ThemeObjects.objs[ii] do
             begin
                 if overlaycnt <> 0 then
-                    OutError('Duplicate overlays declaration for ' + nameRef, true);
+                    OutError('Broken theme. Duplicate overlays declaration for object ' + nameRef, true);
                 Delete(s, 1, i);
                 i:= Pos(',', s);
                 overlaycnt:= StrToInt(Trim(Copy(s, 1, Pred(i))));
                 Delete(s, 1, i);
                 if overlaycnt > MAXOBJECTRECTS then
-                    OutError('Object''s overlay count should be no more than '+ inttostr(MAXOBJECTRECTS) +' (it was '+ inttostr(overlaycnt) +').', true);
+                    OutError('Broken theme. Object''s overlay count should be no more than '+ inttostr(MAXOBJECTRECTS) +' (it was '+ inttostr(overlaycnt) +').', true);
                 for t:= 0 to Pred(overlaycnt) do
                     ReadOverlay(overlays[t], s);
                 break
--- a/hedgewars/uMatrix.pas	Sat Jul 21 02:19:32 2018 +0300
+++ b/hedgewars/uMatrix.pas	Fri Jul 20 20:00:52 2018 -0400
@@ -260,7 +260,7 @@
             write(Result[i, j]);
           writeln;
         end;
-        checkFails(false, 'error in matrix multiplication?!', true);
+        checkFails(false, 'Error in matrix multiplication?!', true);
     end;
     {$ENDIF}
 
--- a/hedgewars/uPhysFSLayer.pas	Sat Jul 21 02:19:32 2018 +0300
+++ b/hedgewars/uPhysFSLayer.pas	Fri Jul 20 20:00:52 2018 -0400
@@ -202,7 +202,7 @@
 {$ENDIF}
 begin
 {$IFDEF HWLIBRARY}
-    //TODO: http://icculus.org/pipermail/physfs/2011-August/001006.html
+    //TODO: https://icculus.org/pipermail/physfs/2011-August/001006.html
     cPhysfsId:= shortstring(GetCurrentDir()) + {$IFDEF DARWIN}{$IFNDEF IPHONEOS}'/Hedgewars.app/Contents/MacOS/' + {$ENDIF}{$ENDIF} ' hedgewars';
 {$ELSE}
     cPhysfsId:= ParamStr(0);
--- a/hedgewars/uRender.pas	Sat Jul 21 02:19:32 2018 +0300
+++ b/hedgewars/uRender.pas	Fri Jul 20 20:00:52 2018 -0400
@@ -527,7 +527,10 @@
 
 {$IFNDEF PAS2C}
     if not Load_GL_VERSION_2_0 then
-        halt;
+        begin
+        WriteLnToConsole('Load_GL_VERSION_2_0 returned false!');
+        halt(HaltStartupError);
+        end;
 {$ENDIF}
 
     shaderWater:= CompileProgram('water');
@@ -718,7 +721,7 @@
 end;
 
 procedure openglRotatef(RotX, RotY, RotZ: GLfloat; dir: LongInt); inline;
-{ workaround for pascal bug http://bugs.freepascal.org/view.php?id=27222 }
+{ workaround for pascal bug https://bugs.freepascal.org/view.php?id=27222 }
 var tmpdir: LongInt;
 begin
 tmpdir:=dir;
--- a/hedgewars/uRenderUtils.pas	Sat Jul 21 02:19:32 2018 +0300
+++ b/hedgewars/uRenderUtils.pas	Fri Jul 20 20:00:52 2018 -0400
@@ -46,7 +46,7 @@
 begin
     r:= rect^;
     if Clear then
-        SDL_FillRect(Surface, @r, 0);
+        SDL_FillRect(Surface, @r, SDL_MapRGB(Surface^.format, 0, 0, 0));
 
     BorderColor:= SDL_MapRGB(Surface^.format, BorderColor shr 16, BorderColor shr 8, BorderColor and $FF);
     FillColor:= SDL_MapRGB(Surface^.format, FillColor shr 16, FillColor shr 8, FillColor and $FF);
@@ -554,7 +554,7 @@
     rect.h:= textHeight + cornerHeight * 2 - edgeHeight * 2;
     i:= rect.w;
     j:= rect.h;
-    SDL_FillRect(finalSurface, @rect, cWhiteColor);
+    SDL_FillRect(finalSurface, @rect, SDL_MapRGB(finalSurface^.format, cWhiteColor shr 16, cWhiteColor shr 8, cWhiteColor and $FF));
 
     pos:= 1; line:= 0;
     while GetNextSpeechLine(s, #1, pos, substr) do
--- a/hedgewars/uSound.pas	Sat Jul 21 02:19:32 2018 +0300
+++ b/hedgewars/uSound.pas	Fri Jul 20 20:00:52 2018 -0400
@@ -339,7 +339,11 @@
 var success: boolean;
 begin
     if not (isSoundEnabled or isMusicEnabled) then
+        begin
+        isAudioMuted:= true;
+        cInitVolume:= 0;
         exit;
+        end;
     WriteToConsole('Init sound...');
     success:= SDL_InitSubSystem(SDL_INIT_AUDIO) = 0;
 
@@ -357,12 +361,17 @@
         WriteLnToConsole(msgFailed);
         isSoundEnabled:= false;
         isMusicEnabled:= false;
+        isAudioMuted:= true;
+        cInitVolume:= 0;
     end;
 
     WriteToConsole('Init SDL_mixer... ');
     if SDLCheck(Mix_Init(MIX_INIT_OGG) <> 0, 'Mix_Init', true) then exit;
     WriteLnToConsole(msgOK);
 
+    // from uVariables to be used by other modules
+    cIsSoundEnabled:= true;
+
     Mix_AllocateChannels(Succ(chanTPU));
     previousVolume:= cInitVolume;
     ChangeVolume(cInitVolume);
--- a/hedgewars/uStore.pas	Sat Jul 21 02:19:32 2018 +0300
+++ b/hedgewars/uStore.pas	Fri Jul 20 20:00:52 2018 -0400
@@ -288,7 +288,7 @@
                     if (month = 4) and (md = 1) then
                         begin
                         AprilOne:= true;
-                        Hat := 'fr_tomato'; // avoid promoting violence to hedgehogs. see http://hedgewars.org/node/5818
+                        Hat := 'fr_tomato'; // avoid promoting violence to hedgehogs. see https://hedgewars.org/node/5818
                         end;
 
                     if Hat <> 'NoHat' then
@@ -829,7 +829,7 @@
         {$ENDIF}
         end;
 
-    if checkFails((ProgrTex <> nil) and (LoadingText <> nil), 'Error - Progress or Loading Texture is nil!', true) then exit;
+    if checkFails((ProgrTex <> nil) and (LoadingText <> nil), 'Error - Progress or Loading texture is nil!', true) then exit;
 
     RenderClear();
     if Step < numsquares then
@@ -975,7 +975,7 @@
 r.y:= cFontBorder + 4;
 r.w:= 32;
 r.h:= 32;
-SDL_FillRect(tmpsurf, @r, $ff000000);
+SDL_FillRect(tmpsurf, @r, SDL_MapRGB(tmpsurf^.format, 0, 0, 0));
 SDL_UpperBlit(iconsurf, iconrect, tmpsurf, @r);
 
 RenderHelpWindow:=  Surface2Tex(tmpsurf, true);
--- a/hedgewars/uTeams.pas	Sat Jul 21 02:19:32 2018 +0300
+++ b/hedgewars/uTeams.pas	Fri Jul 20 20:00:52 2018 -0400
@@ -148,7 +148,7 @@
     PrevHH, PrevTeam : LongWord;
 begin
 TargetPoint.X:= NoPointX;
-if checkFails(CurrentTeam <> nil, 'nil Team', true) then exit;
+if checkFails(CurrentTeam <> nil, 'Team is nil!', true) then exit;
 with CurrentHedgehog^ do
     if (PreviousTeam <> nil) and PlacingHogs and Unplaced then
         begin
--- a/hedgewars/uTypes.pas	Sat Jul 21 02:19:32 2018 +0300
+++ b/hedgewars/uTypes.pas	Fri Jul 20 20:00:52 2018 -0400
@@ -39,7 +39,7 @@
     TGameState = (gsLandGen, gsStart, gsGame, gsConfirm, gsExit, gsSuspend);
 
     // Game types that help determining what the engine is actually supposed to do
-    TGameType = (gmtLocal, gmtDemo, gmtNet, gmtSave, gmtLandPreview, gmtSyntax, gmtRecord);
+    TGameType = (gmtLocal, gmtDemo, gmtNet, gmtSave, gmtLandPreview, gmtBadSyntax, gmtRecord, gmtSyntaxHelp);
 
     // Different files are stored in different folders, this enumeration is used to tell which folder to use
     TPathType = (ptNone, ptData, ptGraphics, ptThemes, ptCurrTheme, ptConfig, ptTeams, ptMaps,
--- a/hedgewars/uVariables.pas	Sat Jul 21 02:19:32 2018 +0300
+++ b/hedgewars/uVariables.pas	Fri Jul 20 20:00:52 2018 -0400
@@ -168,6 +168,7 @@
     cScriptName     : shortstring;
     cScriptParam    : shortstring;
     cSeed           : shortstring;
+    cIsSoundEnabled : boolean; // If the sound system is enabled
     cVolumeDelta    : LongInt;
     cMuteToggle     : boolean; // Mute toggle requested
     cHasFocus       : boolean;
@@ -2852,6 +2853,7 @@
     fastScrolling   := false;
     autoCameraOn    := true;
     cSeed           := '';
+    cIsSoundEnabled := false;
     cVolumeDelta    := 0;
     cMuteToggle     := false;
     cHasFocus       := true;
--- a/hedgewars/uVideoRec.pas	Sat Jul 21 02:19:32 2018 +0300
+++ b/hedgewars/uVideoRec.pas	Fri Jul 20 20:00:52 2018 -0400
@@ -48,7 +48,7 @@
 procedure freeModule;
 
 implementation
-uses uVariables, GLunit, SDLh, SysUtils, uUtils, uIO, uMisc, uTypes, uDebug;
+uses uVariables, GLunit, SDLh, SysUtils, uUtils, uIO, uMisc, uConsts, uTypes, uDebug;
 
 type TAddFileLogRaw = procedure (s: pchar); cdecl;
 const AvwrapperLibName = 'libavwrapper';
@@ -73,7 +73,8 @@
     numPixels: LongWord;
     startTime, numFrames, curTime, progress, maxProgress: LongWord;
     soundFilePath: shortstring;
-    thumbnailSaved : Boolean;
+    thumbnailSaved: boolean;
+    recordAudio: boolean;
 
 function BeginVideoRecording: Boolean;
 var filename, desc: shortstring;
@@ -113,7 +114,12 @@
     desc:= desc + 'prefix[' + RecPrefix + ']prefix';
 
     filename:= UserPathPrefix + '/VideoTemp/' + RecPrefix;
-    soundFilePath:= UserPathPrefix + '/VideoTemp/' + RecPrefix + '.sw';
+
+    recordAudio:= (cAudioCodec <> 'no');
+    if recordAudio then
+        soundFilePath:= UserPathPrefix + '/VideoTemp/' + RecPrefix + '.sw'
+    else
+        soundFilePath:= '';
 
     if checkFails(AVWrapper_Init(@AddFileLogRaw
         , PChar(ansistring(filename))
@@ -147,9 +153,20 @@
     FreeMem(RGB_Buffer, 4*numPixels);
     Close(cameraFile);
     if AVWrapper_Close() < 0 then
-        halt(-1);
-    Erase(cameraFile);
-    DeleteFile(soundFilePath);
+        begin
+        AddFileLog('AVWrapper_Close() has failed.');
+        halt(HaltVideoRec);
+        end;
+{$IOCHECKS OFF}
+    // Provoke IOResult to be set
+    FileSize(cameraFile);
+    if IOResult = 0 then
+        Erase(cameraFile)
+    else
+        AddFileLog('Warning: Tried to delete the cameraFile but it was already deleted');
+{$IOCHECKS ON}
+    if recordAudio and FileExists(soundFilePath) then
+        DeleteFile(soundFilePath);
     SendIPC(_S'v'); // inform frontend that we finished
 end;
 
@@ -160,7 +177,10 @@
     glReadPixels(0, 0, cScreenWidth, cScreenHeight, GL_RGBA, GL_UNSIGNED_BYTE, RGB_Buffer);
 
     if AVWrapper_WriteFrame(RGB_Buffer) < 0 then
-        halt(-1);
+        begin
+        AddFileLog('AVWrapper_WriteFrame(RGB_Buffer) has failed.');
+        halt(HaltVideoRec);
+        end;
 
     // inform frontend that we have encoded new frame
     s[0]:= #3;
@@ -268,43 +288,49 @@
         CopyFile(recordFileName, UserPathPrefix + '/VideoTemp/' + RecPrefix + '.hwd');
     end;
 
-    Mix_QuerySpec(@frequency, @format, @channels);
-    AddFileLog('sound: frequency = ' + IntToStr(frequency) + ', format = ' + IntToStr(format) + ', channels = ' + IntToStr(channels));
-    if format <> $8010 then
-    begin
-        // TODO: support any audio format
-        AddFileLog('Error: Unexpected audio format ' + IntToStr(format));
-        exit;
-    end;
+    if cIsSoundEnabled then
+        begin
+        Mix_QuerySpec(@frequency, @format, @channels);
+        AddFileLog('sound: frequency = ' + IntToStr(frequency) + ', format = ' + IntToStr(format) + ', channels = ' + IntToStr(channels));
+        if format <> $8010 then
+            begin
+            // TODO: support any audio format
+            AddFileLog('Error: Unexpected audio format ' + IntToStr(format));
+            exit;
+            end;
 
 {$IOCHECKS OFF}
-    // create sound file
-    filename:= UserPathPrefix + '/VideoTemp/' + RecPrefix + '.sw';
-    Assign(audioFile, filename);
-    Rewrite(audioFile, 1);
-    if IOResult <> 0 then
-    begin
-        AddFileLog('Error: Could not write to ' + filename);
-        exit;
-    end;
+        // create sound file
+        filename:= UserPathPrefix + '/VideoTemp/' + RecPrefix + '.sw';
+        Assign(audioFile, filename);
+        Rewrite(audioFile, 1);
+        if IOResult <> 0 then
+            begin
+            AddFileLog('Error: Could not write to ' + filename);
+            exit;
+            end;
+        end;
 
     // create file with camera positions
     filename:= UserPathPrefix + '/VideoTemp/' + RecPrefix + '.txtout';
     Assign(cameraFile, filename);
     Rewrite(cameraFile);
     if IOResult <> 0 then
-    begin
+        begin
         AddFileLog('Error: Could not write to ' + filename);
         exit;
-    end;
+        end;
 
-    // save audio parameters in sound file
-    BlockWrite(audioFile, frequency, 4);
-    BlockWrite(audioFile, channels, 4);
+    if cIsSoundEnabled then
+        begin
+        // save audio parameters in sound file
+        BlockWrite(audioFile, frequency, 4);
+        BlockWrite(audioFile, channels, 4);
 {$IOCHECKS ON}
 
-    // register callback for actual audio recording
-    Mix_SetPostMix(@RecordPostMix, nil);
+        // register callback for actual audio recording
+        Mix_SetPostMix(@RecordPostMix, nil);
+        end;
 
     startTime:= SDL_GetTicks();
     flagPrerecording:= true;
@@ -315,12 +341,18 @@
     AddFileLog('StopPreRecording');
     flagPrerecording:= false;
 
-    // call SDL_LockAudio because RecordPostMix may be executing right now
-    SDL_LockAudio();
-    Close(audioFile);
+    if cIsSoundEnabled then
+        begin
+        // call SDL_LockAudio because RecordPostMix may be executing right now
+        SDL_LockAudio();
+        Close(audioFile);
+        end;
     Close(cameraFile);
-    Mix_SetPostMix(nil, nil);
-    SDL_UnlockAudio();
+    if cIsSoundEnabled then
+        begin
+        Mix_SetPostMix(nil, nil);
+        SDL_UnlockAudio();
+        end;
 
     if not thumbnailSaved then
         SaveThumbnail();
--- a/misc/hats_js_anim.xhtml	Sat Jul 21 02:19:32 2018 +0300
+++ b/misc/hats_js_anim.xhtml	Fri Jul 20 20:00:52 2018 -0400
@@ -45,7 +45,7 @@
     <script type="application/ecmascript">
 //<![CDATA[
 /* javascript version of a sprite sheet - this could be pretty trivially done in pure HTML, but maintenance
-would be easier with a server-side portion. list of sprites could be gotten from googlecode, but would require XSS whitelisting */
+would be easier with a server-side portion. list of sprites could be gotten from server, but would require XSS whitelisting */
 /*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 = {
--- a/misc/racer.yaml	Sat Jul 21 02:19:32 2018 +0300
+++ b/misc/racer.yaml	Fri Jul 20 20:00:52 2018 -0400
@@ -1,5 +1,5 @@
 - Game starts when everyone is ready! Type '/callvote map' to switch maps, '/vote
-  yes' to vote. Check results at http://hedgewars.org/records
+  yes' to vote. Check results at https://hedgewars.org/records
 - ! '#16':
   - ! 'Racer Challenge #16'
   - SEED: ! '{173c526c-5464-40af-beb2-f130f6998625}'
--- a/misc/theme_editor.html	Sat Jul 21 02:19:32 2018 +0300
+++ b/misc/theme_editor.html	Fri Jul 20 20:00:52 2018 -0400
@@ -33,27 +33,27 @@
 
                     sky = new Image();
                     sky.onload = tryToDraw;
-                    sky.src = 'http://hedgewars.googlecode.com/hg/share/hedgewars/Data/Themes/Nature/Sky.png';
+                    sky.src = 'https://hg.hedgewars.org/hedgewars/raw-file/tip/share/hedgewars/Data/Themes/Nature/Sky.png';
 
                     clouds = new Image();
                     clouds.onload = tryToDraw;
-                    clouds.src = 'http://hedgewars.googlecode.com/hg/share/hedgewars/Data/Graphics/Clouds.png';
+                    clouds.src = 'https://hg.hedgewars.org/hedgewars/raw-file/tip/share/hedgewars/Data/Graphics/Clouds.png';
 
                     horizont = new Image();
                     horizont.onload = tryToDraw;
-                    horizont.src = 'http://hedgewars.googlecode.com/hg/share/hedgewars/Data/Themes/Nature/horizont.png';
+                    horizont.src = 'https://hg.hedgewars.org/hedgewars/raw-file/share/hedgewars/Data/Themes/Nature/horizont.png';
 
                     land = new Image();
                     land.onload = tryToDraw;
-                    land.src = 'http://hedgewars.googlecode.com/hg/share/hedgewars/Data/Themes/Nature/LandTex.png';
+                    land.src = 'https://hg.hedgewars.org/hedgewars/raw-file/tip/share/hedgewars/Data/Themes/Nature/LandTex.png';
 
                     border = new Image();
                     border.onload = tryToDraw;
-                    border.src = 'http://hedgewars.googlecode.com/hg/share/hedgewars/Data/Themes/Nature/Border.png';
+                    border.src = 'https://hg.hedgewars.org/hedgewars/raw-file/tip/share/hedgewars/Data/Themes/Nature/Border.png';
 
                     water = new Image();
                     water.onload = tryToDraw;
-                    water.src = 'http://hedgewars.googlecode.com/hg/share/hedgewars/Data/Graphics/BlueWater.png';
+                    water.src = 'https://hg.hedgewars.org/hedgewars/raw-file/tip/share/hedgewars/Data/Graphics/BlueWater.png';
 
                     landArray = new Array(512);
                     for (var x = 0; x < landArray.length; x++)
--- a/project_files/HedgewarsMobile/Classes/SupportViewController.m	Sat Jul 21 02:19:32 2018 +0300
+++ b/project_files/HedgewarsMobile/Classes/SupportViewController.m	Fri Jul 20 20:00:52 2018 -0400
@@ -122,16 +122,16 @@
         switch ([indexPath row])
         {
             case 0:
-                urlString = @"http://www.facebook.com/Hedgewars";
+                urlString = @"https://www.facebook.com/Hedgewars";
                 break;
             case 1:
-                urlString = @"http://twitter.com/hedgewars";
+                urlString = @"https://twitter.com/hedgewars";
                 break;
             case 2:
-                urlString = @"http://www.hedgewars.org";
+                urlString = @"https://www.hedgewars.org";
                 break;
             case 3:
-                urlString = @"http://webchat.freenode.net/?channels=hedgewars";
+                urlString = @"https://webchat.freenode.net/?channels=hedgewars";
                 break;
             default:
                 DLog(@"No way");
--- a/share/hedgewars.appdata.xml	Sat Jul 21 02:19:32 2018 +0300
+++ b/share/hedgewars.appdata.xml	Fri Jul 20 20:00:52 2018 -0400
@@ -52,42 +52,42 @@
   <screenshot type="default">
     <caption>A classic Hedgewars match</caption>
     <caption xml:lang="de">Eine klassische Runde Hedgewars</caption>
-    <image width="1600" height="900">http://hedgewars.org/images/screenshots/0_9_19-Snow_Dynamite.png</image>
+    <image width="1600" height="900">https://hedgewars.org/images/screenshots/0_9_19-Snow_Dynamite.png</image>
   </screenshot>
   <screenshot>
     <caption>Throwing the dangerous hellish hand-grenade</caption>
     <caption xml:lang="de">Die gefährliche höllische Handgranate wird geworfen</caption>
-    <image width="1600" height="900">http://hedgewars.org/images/screenshots/0_9_19-Hell_HellishHandgrenade.png</image>
+    <image width="1600" height="900">https://hedgewars.org/images/screenshots/0_9_19-Hell_HellishHandgrenade.png</image>
   </screenshot>
   <screenshot>
     <caption>The awesome shoryuken attack</caption>
     <caption xml:lang="de">Der großartige Shoryuken-Angriff</caption>
-    <image width="1600" height="900">http://hedgewars.org/images/screenshots/0_9_19-Trash_Shoryuken.png</image>
+    <image width="1600" height="900">https://hedgewars.org/images/screenshots/0_9_19-Trash_Shoryuken.png</image>
   </screenshot>
   <screenshot>
     <caption>Kamikaze attack</caption>
     <caption xml:lang="de">Kamikaze-Angriff</caption>
-    <image width="1600" height="900">http://hedgewars.org/images/screenshots/0_9_19-Fruit_Kamikaze.png</image>
+    <image width="1600" height="900">https://hedgewars.org/images/screenshots/0_9_19-Fruit_Kamikaze.png</image>
   </screenshot>
   <screenshot>
     <caption>Hedgehog using a sniper rifle</caption>
     <caption xml:lang="de">Igel, der ein Scharfschützengewehr benutzt</caption>
-    <image width="1600" height="900">http://hedgewars.org/images/screenshots/0_9_19-EarthRise_Sniper.png</image>
+    <image width="1600" height="900">https://hedgewars.org/images/screenshots/0_9_19-EarthRise_Sniper.png</image>
   </screenshot>
   <screenshot>
     <caption>2nd mission in the campaign “A Classic Fairytale”</caption>
     <caption xml:lang="de">2. Mission in der Kampagne „Ein klassisches Märchen”</caption>
-    <image width="1600" height="900">http://hedgewars.org/images/screenshots/0_9_19-AFT02.png</image>
+    <image width="1600" height="900">https://hedgewars.org/images/screenshots/0_9_19-AFT02.png</image>
   </screenshot>
   <screenshot>
     <caption>9th mission in the campaign “A Classic Fairytale”</caption>
     <caption xml:lang="de">9. Mission in der Kampagne „Ein klassisches Märchen”</caption>
-    <image width="1600" height="900">http://hedgewars.org/images/screenshots/0_9_19-AFT09.png</image>
+    <image width="1600" height="900">https://hedgewars.org/images/screenshots/0_9_19-AFT09.png</image>
   </screenshot>
  </screenshots>
- <url type="homepage">http://hedgewars.org/</url>
- <url type="bugtracker">http://hedgewars.org/bugs</url>
- <url type="faq">http://hedgewars.org/faq</url>
- <url type="help">http://hedgewars.org/wiki.html</url>
+ <url type="homepage">https://hedgewars.org/</url>
+ <url type="bugtracker">https://hedgewars.org/bugs</url>
+ <url type="faq">https://hedgewars.org/faq</url>
+ <url type="help">https://hedgewars.org/wiki.html</url>
  <developer_name>Hedgewars Project</developer_name>
 </component>
--- a/share/hedgewars/Data/Locale/tips_cs.xml	Sat Jul 21 02:19:32 2018 +0300
+++ b/share/hedgewars/Data/Locale/tips_cs.xml	Fri Jul 20 20:00:52 2018 -0400
@@ -6,13 +6,13 @@
     <tip>Jednoduše zvol stejnou barvu jako spoluhráč, abys hrál ve stejném týmu. Každý z vás bude mít kontrolu nad svými vlastními ježky, ale vyhraje nebo prohraje společně.</tip>
     <tip>Některé zbraně mohou způsobovat jen malé poškození, ale mohou být devastující v pravé chvíli. Zkus použít pistoli Desert Eagle ke sražení několika nepřátelských ježků do vody.</tip>
     <tip>Pokud si nejsi jistý, co dělat a nechceš plýtvat municí, přeskoč tah. Ale nenech uběhnout moc času, protože pak přijde Náhlá smrt!</tip>
-    <tip>Pokud chceš zabránit ostatním, aby používali tvoji oblíbenou přezdívku na oficiálním serveru, zaregistruj se na http://www.hedgewars.org/.</tip>
+    <tip>Pokud chceš zabránit ostatním, aby používali tvoji oblíbenou přezdívku na oficiálním serveru, zaregistruj se na https://www.hedgewars.org/.</tip>
     <tip>Jsi znuděn standardní hrou? Vyzkoušej některou misi - nabídnou jiný herní zážitek v závislosti na tom, kterou si vybereš.</tip>
     <tip>Standardně hra vždycky nahrává poslední odehraný zápas jako ukázku. Vyber si 'Místní hru' a zvol tlačítko 'Ukázky' v pravém spodním rohu k jejich přehrávání a správě.</tip>
     <tip>Hedgewars je Open Source a Freeware, který jsme vytvořili v našem volném čase. Pokud máš problémy, zeptej se na našem fóru, ale neočekávej prosím nonstop podporu!</tip>
     <tip>Hedgewars je Open Source a Freeware, který jsme vytvořili v našem volném čase. Pokud se ti líbí, pomož nám malým příspěvkem, nebo se podílej na práci!</tip>
     <tip>Hedgewars je Open Source a Freeware, který jsme vytvořili v našem volném čase. Sdílej ho se svoji rodinou a přáteli dle libosti!</tip>
-    <tip>Čas od času se konají oficiální turnaje. Nadcházející události budou publikovány na http://www.hedgewars.org/ s několika denním předstihem.</tip>
+    <tip>Čas od času se konají oficiální turnaje. Nadcházející události budou publikovány na https://www.hedgewars.org/ s několika denním předstihem.</tip>
     <tip>Hedgewars je k dispozici v mnoha jazycích. Pokud překlad do tvého jazyka vypadá zastaralý nebo chybí, neváhej nás kontaktovat!</tip>
     <tip>Hedgewars může být spuštěno na mnoha různých operačních systémech včetně Microsoft Windows, Mac OS X a Linuxu.</tip>
     <tip>Vždycky si pamatuj, že můžeš vytvořit vlastní hru na místní síti i internetu. Nejsi odkázán jen na možnost 'Prostá hra'.</tip>
--- a/share/hedgewars/Data/Locale/tips_da.xml	Sat Jul 21 02:19:32 2018 +0300
+++ b/share/hedgewars/Data/Locale/tips_da.xml	Fri Jul 20 20:00:52 2018 -0400
@@ -6,13 +6,13 @@
     <tip>Bare vælg samme farve som en ven for at spille sammen som et hold. Hver af jer vil stadig kontrollere sine egne pindsvin, men vil vinde eller tabe sammen.</tip>
     <tip>Nogle våben giver måske ikke særlig meget skade, men de kan være meget mere farlige i de rigtige situationer. Prøv at bruge Desert Eagle-pistolen til at skubbe flere pindsvin i vandet.</tip>
     <tip>Hvis du er usikker på hvad du skal gøre og ikke vil spilde ammunition, kan du springe en runde over. Men lad der ikke gå alt for meget tid, for ellers indtræffer Pludselig Død!</tip>
-    <tip>Hvis du ikke vil have at andre anvender dit foretrukne brugernavn på den officielle server, kan du registrere en bruger på http://www.hedgewars.org/.</tip>
+    <tip>Hvis du ikke vil have at andre anvender dit foretrukne brugernavn på den officielle server, kan du registrere en bruger på https://www.hedgewars.org/.</tip>
     <tip>Er du træt af den almindelige måde at spille på? Prøv en af missionerne - de tilbyder forskellige måder at spille på afhængigt af hvilken en du vælger.</tip>
     <tip>Som standard optager spillet altid det sidste spil du har spillet som en demo. Tryk på 'Lokalt spil' og vælg 'Demoer'-knappen i nederste højre hjørne for at afspille eller administrere dem.</tip>
     <tip>Hedgewars er Open Source og et gratis spil vi laver i vores fritid. Hvis du har problemer er du velkommen til at spørge på forummet, men forvent ikke at få hjælp 24 timer i døgnet!</tip>
     <tip>Hedgewars er Open Source og et gratis spil vi laver i vores fritid. Hvis du holder af det, kan du hjælpe os med en lille donation eller ved at indsende dine egne modifikationer!</tip>
     <tip>Hedgewars er Open Source og et gratis spil vi laver i vores fritid. Del det med dine venner og din familie som du ønsker!</tip>
-    <tip>Fra tid til anden er der officielle turneringer. Kommende begivenheder vil blive annonceret på http://www.hedgewars.org/ et par dage i forvejen.</tip>
+    <tip>Fra tid til anden er der officielle turneringer. Kommende begivenheder vil blive annonceret på https://www.hedgewars.org/ et par dage i forvejen.</tip>
     <tip>Hedgewars er tilgængeligt på mange sprog. Hvis oversættelsen på dit sprog mangler noget eller er uddateret, skal du være velkommen til at kontakte os!</tip>
     <tip>Hedgewars kan køre på mange forskellige operativsystemer, herunder Microsoft Windows, Mac OS X og Linux.</tip>
     <tip>Husk altid at du kan sætte dine egne spil op under lokale-, netværks- og online-spil. Du er ikke begrænset til kun at bruge 'Simpelt spil'-muligheden.</tip>
--- a/share/hedgewars/Data/Locale/tips_de.xml	Sat Jul 21 02:19:32 2018 +0300
+++ b/share/hedgewars/Data/Locale/tips_de.xml	Fri Jul 20 20:00:52 2018 -0400
@@ -7,19 +7,19 @@
     <tip>Einige Waffen mögen zwar nur geringfügigen Schaden anrichten, aber sie können in der passenden Situation verheerend sein. Versuche, die Desert Eagle zu benutzen, um mehrere Igel ins Wasser zu schubsen.</tip>
     <tip>Falls du dir unsicher darüber bist, was du tun sollst und du keine Munition verschwenden willst, überspring die Runde. Aber lass nicht zu viel Zeit verstreichen, weil irgendwann der Sudden Death kommt.</tip>
     <tip>Willst du Seile sparen? Lass das Seil im Flug los und schieß erneut. Solange du den Boden nicht berührst und kein Schuss daneben geht, wirst du dein Seil wiederverwenden, ohne Vorräte zu vergeuden.</tip>
-    <tip>Wenn du Andere davon abhalten willst, deinen Lieblingsspitznamen auf dem offiziellen Server zu benutzen, registriere ein Benutzerkonto auf <a href="http://www.hedgewars.org/">http://www.hedgewars.org/</a>.</tip>
+    <tip>Wenn du Andere davon abhalten willst, deinen Lieblingsspitznamen auf dem offiziellen Server zu benutzen, registriere ein Benutzerkonto auf <a href="https://www.hedgewars.org/">https://www.hedgewars.org/</a>.</tip>
     <tip>Bist du vom Standardspiel gelangweilt? Dann probier eine der Missionen aus – sie spielen sich anders, je nach dem, welche Mission du ausgewählt hast.</tip>
     <tip>Standardmäßig wird das Programm immer vom letzten Spiel eine Wiederholung abspeichern. Wähle »Auf einen einzelnen Computer spielen« und dann den »Aufgezeichnete Wiederholungen ansehen«-Knopf auf der rechten unteren Ecke, um sie abzuspielen oder zu verwalten.</tip>
     <tip>Hedgewars ist freie Open-Source-Software, die wir in unserer Freizeit erstellen. Falls du Probleme hast, frag uns in unseren Foren oder besuch unseren IRC-Channel!</tip>
     <tip>Hedgewars ist freie Open-Source-Software, die wir in unserer Freizeit erstellen. Wenn es dir gefällt, hilf uns mit einer kleinen Spende oder steuere deine eigenen Werke bei!</tip>
     <tip>Hedgewars ist freie Open-Source-Software, die wir in unserer Freizeit erstellen. Teile es mit deiner Familie und deinen Freunden, wie es dir gefällt!</tip>
     <tip>Hedgewars ist freie Open-Source-Software, die wir in unserer Freizeit nur so zum Spaß erstellen. Triff die Entwickler auf <a href="irc://irc.freenode.net/hedgewars">#hedgewars</a>!</tip>
-    <tip>Von Zeit zu Zeit wird es offizielle Turniere geben. Bevorstehende Ereignisse werden auf <a href="http://www.hedgewars.org/">http://www.hedgewars.org/</a> ein paar Tage im Voraus angekündigt.</tip>
+    <tip>Von Zeit zu Zeit wird es offizielle Turniere geben. Bevorstehende Ereignisse werden auf <a href="https://www.hedgewars.org/">https://www.hedgewars.org/</a> ein paar Tage im Voraus angekündigt.</tip>
     <tip>Hedgewars ist in vielen Sprachen verfügbar. Wenn die Übersetzung deiner Sprache zu fehlen oder veraltet zu sein scheint, nimm ruhig mit uns Kontakt auf!</tip>
     <tip>Hedgewars läuft auf vielen verschiedenen Betriebssystemen, unter anderem Microsoft Windows, Mac OS X und GNU/Linux.</tip>
     <tip>Denk immer daran, dass du in der Lage bist, deine eigenen Spiele in lokalen Spielen und Netzwerkspielen aufzusetzen. Du musst nicht zwangsläufig nur einfache Spiele spielen.</tip>
     <tip>Verbinde einen oder mehr Gamepads, bevor du das Spiel startest, damit du ihre Belegung deinen Teams zuweisen kannst.</tip>
-    <tip>Erstelle ein Benutzerkonto auf <a href="http://www.hedgewars.org/">http://www.hedgewars.org/</a>, um andere davon abzuhalten, deinen Lieblingsspitznamen beim Spielen auf dem offiziellen Server zu benutzen.</tip>
+    <tip>Erstelle ein Benutzerkonto auf <a href="https://www.hedgewars.org/">https://www.hedgewars.org/</a>, um andere davon abzuhalten, deinen Lieblingsspitznamen beim Spielen auf dem offiziellen Server zu benutzen.</tip>
     <tip>Wenn du spielst, solltest du dir wenigstens ein mal pro Stunde eine kurze Pause gönnen.</tip>
     <tip>Wenn deine Grafikkarte nicht in der Lage ist, hardwarebeschleunigtes OpenGL zur Verfügung zu stellen, versuche es mit einer niedrigen Qualitätsstufe (in den Grafikeinstellungen), um die Geschwindigkeit zu erhöhen.</tip>
     <tip>Wenn deine Grafikkarte nicht in der Lage ist, hardwarebeschleunigtes OpenGL zur Verfügung zu stellen, versuche, die benötigten Treiber zu updaten.</tip>
@@ -43,7 +43,7 @@
     <tip>Der Flammenwerfer ist eine Waffe, aber sie kann auch zum Tunnelgraben verwendet werden.</tip>
     <tip>Benutze den Molotowcocktail oder Flammenwerfer, um kurzzeitig Igel daran zu hindern, Gelände wie Tunnel oder Bauträger zu überqueren.</tip>
     <tip>Willst du wissen, wer hinter dem Spiel steckt? Klick auf das Hedgewars-Logo im Hauptmenü, um die Liste der Mitwirkenden (derzeit nur auf Englisch, Anm. eines Übersetzers) zu sehen.</tip>
-    <tip>Magst du Hedgewars? Werd zum Fan auf <a href="http://www.facebook.com/Hedgewars">Facebook</a> oder folg uns auf <a href="http://twitter.com/hedgewars">Twitter</a>!</tip>
+    <tip>Magst du Hedgewars? Werd zum Fan auf <a href="https://www.facebook.com/Hedgewars">Facebook</a> oder folg uns auf <a href="https://twitter.com/hedgewars">Twitter</a>!</tip>
     <tip>Tu dir keinen Zwang an, dir deine eigenen Grabsteine, Hüte, Flaggen oder sogar Karten und Szenerien zu malen! Aber beachte, dass du sie irgendwo online teilen musst, um sie online benutzen zu können.</tip>
     <tip>Halte deine Grafikkartentreiber auf dem neuesten Stand, um Probleme beim Spielen des Spiels zu vermeiden.</tip>
     <tip>Kopf oder Zahl? Gib »/rnd« in der Lobby ein und finde es heraus. »/rnd Schere Stein Papier« funktioniert auch!</tip>
--- a/share/hedgewars/Data/Locale/tips_en.xml	Sat Jul 21 02:19:32 2018 +0300
+++ b/share/hedgewars/Data/Locale/tips_en.xml	Fri Jul 20 20:00:52 2018 -0400
@@ -7,14 +7,14 @@
     <tip>Some weapons might do only low damage but they can be a lot more devastating in the right situation. Try to use the Desert Eagle to knock multiple hedgehogs into the water.</tip>
     <tip>If you’re unsure what to do and don’t want to waste ammo, skip one round. But don’t let too much time pass as there will be Sudden Death!</tip>
     <tip>Want to save ropes? Release the rope in mid air and then shoot again. As long as you don’t touch the ground or miss a shot you’ll reuse your rope without wasting ammo!</tip>
-    <tip>If you’d like to keep others from using your preferred nickname on the official server, register an account at <a href="http://www.hedgewars.org/">http://www.hedgewars.org/</a>.</tip>
+    <tip>If you’d like to keep others from using your preferred nickname on the official server, register an account at <a href="https://www.hedgewars.org/">https://www.hedgewars.org/</a>.</tip>
     <tip>You're bored of default gameplay? Try one of the missions — they'll offer different gameplay depending on the one you picked.</tip>
     <tip>By default the game will always record the last game played as a demo. Select “Local Game” and pick the “Demos” button on the lower right corner to play or manage them.</tip>
     <tip>Hedgewars is free software (Open Source) we create in our spare time. If you’ve got problems, ask on our forums or visit our IRC room!</tip>
     <tip>Hedgewars is free software (Open Source) we create in our spare time. If you like it, feel free to help us with a small donation or contribute your own work!</tip>
     <tip>Hedgewars is free software (Open Source) we create in our spare time. Share it with your family and friends as you like!</tip>
     <tip>Hedgewars is free software (Open Source) we create in our spare time, just for fun! Meet the devs in <a href="irc://irc.freenode.net/hedgewars">#hedgewars</a>!</tip>
-    <tip>From time to time there will be official tournaments. Upcoming events will be announced at <a href="http://www.hedgewars.org/">http://www.hedgewars.org/</a> some days in advance.</tip>
+    <tip>From time to time there will be official tournaments. Upcoming events will be announced at <a href="https://www.hedgewars.org/">https://www.hedgewars.org/</a> some days in advance.</tip>
     <tip>Hedgewars is available in many languages. If the translation in your language seems to be missing or outdated, feel free to contact us!</tip>
     <tip>Hedgewars can be run on lots of different operating systems including Microsoft Windows, Mac OS X and GNU/Linux.</tip>
     <tip>Always remember you’re able to set up your own games in local and network/online play. You’re not restricted to the “Simple Game” option.</tip>
@@ -42,7 +42,7 @@
     <tip>The Flame Thrower is a weapon but it can be used for tunnel digging as well.</tip>
     <tip>Use the Molotov or Flame Thrower to temporary keep hedgehogs from passing terrain such as tunnels or platforms.</tip>
     <tip>Want to know who’s behind the game? Click on the Hedgewars logo in the main menu to see the credits.</tip>
-    <tip>Like Hedgewars? Become a fan on <a href="http://www.facebook.com/Hedgewars">Facebook</a> or follow us on <a href="http://twitter.com/hedgewars">Twitter</a></tip>
+    <tip>Like Hedgewars? Become a fan on <a href="https://www.facebook.com/Hedgewars">Facebook</a> or follow us on <a href="https://twitter.com/hedgewars">Twitter</a></tip>
     <tip>Feel free to draw your own graves, hats, flags or even maps and themes! But note that you’ll have to share them somewhere to use them online.</tip>
     <tip>Keep your video card drivers up to date to avoid issues playing the game.</tip>
     <tip>Heads or tails? Type “/rnd” in the lobby and you’ll find out. Also “/rnd rock paper scissors” works!</tip>
--- a/share/hedgewars/Data/Locale/tips_es.xml	Sat Jul 21 02:19:32 2018 +0300
+++ b/share/hedgewars/Data/Locale/tips_es.xml	Fri Jul 20 20:00:52 2018 -0400
@@ -6,13 +6,13 @@
     <tip>Elige el mismo color que tus amigos para hacer una alianza con ellos. Cada uno de vosotros controlará sus propios erizos, pero la victoria o derrota será compartida por vuestra facción.</tip>
     <tip>Puede que algunas armas hagan poco daño, pero pueden ser realmente devastadoras si son usadas en el momento correcto. Prueba a usar la Desert eagle para empujar erizos enemigos al agua, por ejemplo.</tip>
     <tip>Si no tienes claro qué vas a hacer y prefieres no desperdiciar munición puedes pasar un turno. ¡Pero ten cuidado, si dejas pasar muchos turnos puede que empiece la muerte súbita!</tip>
-    <tip>Si prefieres que nadie más use tu nick en el servidor oficial puedes registrarlo en http://www.hedgewars.org/.</tip>
+    <tip>Si prefieres que nadie más use tu nick en el servidor oficial puedes registrarlo en https://www.hedgewars.org/.</tip>
     <tip>¿Estás cansado del modo de juego de siempre? Prueba alguna de las misiones, encontrarás en ellas nuevos tipos de juego dependiendo de la que elijas.</tip>
     <tip>El juego intentará guardar la última partida como una demo de forma predeterminada. Más tarde puedes ir a "Juego local" y visitar la sección de "Demos" en la esquina inferior derecha para reproducirlas o gestionarlas.</tip>
     <tip>Hedgewars es un juego gratuito de código abierto que hemos creado en nuestro tiempo libre. Si tienes algún problema estaremos encantados de ayudarte en nuestros foros o canal de IRC, pero ¡no esperes que estemos allí las 24 horas del día!</tip>
     <tip>Hedgewars es un juego gratuito de código abierto que hemos creado en nuestro tiempo libre. ¡Si te gusta podrías considerar el ayudarnos con una pequeña donación o contribuyendo con tu propio trabajo!</tip>
     <tip>Hedgewars es un juego gratuito de código abierto que hemos creado en nuestro tiempo libre. ¡Compártelo con tu família y amigos tanto como quieras!</tip>
-    <tip>De cuando en cuando celebramos torneos oficiales. Puedes mantenerte al día sobre los próximos eventos en http://www.hedgewars.org.</tip>
+    <tip>De cuando en cuando celebramos torneos oficiales. Puedes mantenerte al día sobre los próximos eventos en https://www.hedgewars.org.</tip>
     <tip>Hedgewars está disponible en varios idiomas. Si no encuentras traducción a tu idioma o piensas que la actual es de baja calidad o está desactualizada estaremos encantados de aceptar tu colaboración para mejorarla.</tip>
     <tip>Hedgewars es un juego multiplataforma que puede ser ejecutado en diversos sistemas operativos, incluyendo Windows, Mac OS X y Linux.</tip>
     <tip>Recuerda: puedes crear tus propias partidas multijugador tanto en local como por red, no estás limitado a jugar contra la máquina.</tip>
--- a/share/hedgewars/Data/Locale/tips_fi.xml	Sat Jul 21 02:19:32 2018 +0300
+++ b/share/hedgewars/Data/Locale/tips_fi.xml	Fri Jul 20 20:00:52 2018 -0400
@@ -6,13 +6,13 @@
     <tip>Valitse sama väri kaverisi kanssa pelataksesi samassa joukkueessa. Kumpikin ohjaa omia siilejään, mutta voitatte ja häviätte yhdessä.</tip>
     <tip>Jotkut aseet tekevät vain vähän vahinkoa, mutta voivat olla tehokkaita sopivassa tilanteessa. Kokeile ampua useampi siili veteen Desert Eaglella.</tip>
     <tip>Jos et tiedä mitä tehdä, etkä halua tuhlata ammuksia, jätä vuoro väliin. Mutta älä viivyttele liikaa koska Äkkikuolema koittaa ennemmin tai myöhemmin!</tip>
-    <tip>Jos haluat estää muita käyttämästä nimimerkkiäsi virallisella palvelimella, rekisteröi tunnus osoitteessa <a href="http://www.hedgewars.org/">www.hedgewars.org</a></tip>
+    <tip>Jos haluat estää muita käyttämästä nimimerkkiäsi virallisella palvelimella, rekisteröi tunnus osoitteessa <a href="https://www.hedgewars.org/">www.hedgewars.org</a></tip>
     <tip>Kyllästyttääkö normaali peli? Kokeile operaatioita - Ne tarjoaa erilaisia pelitilanteita.</tip>
     <tip>Oletuksena viimeisin peli nauhoitetaan muistiin. Klikkaa filmikameran kuvaa nähdäksesi tallennetut pelit. Filmikela-kuvakkeesta aukeaa nauhoitetut videoklipit.</tip>
     <tip>Hedgewars on avointa lähdekoodia ja ilmainen peli, jota me kehitämme vapaa-aikanamme. Jos sinulla on ongelmia, kysy keskustelualueilta apua, mutta älä vaadi 24/7-tukea!</tip>
     <tip>Hedgewars on avointa lähdekoodia ja ilmainen peli, jota me kehitämme vapaa-aikanamme. Jos pidät siitä, voit auttaa meitä pienellä lahjoituksella tai omaa työllä!</tip>
     <tip>Hedgewars on avointa lähdekoodia ja ilmainen peli, jota me kehitämme vapaa-aikanamme. Pelaa sitä ystäviesi kanssa miten paljon haluat!</tip>
-    <tip>Toisinaan järjestetään virallisia turnauksia. Tulevista tapahtumista tiedotetaan osoitteessa <a href="http://www.hedgewars.org/">www.hedgewars.org</a> muutama päivä etukäteen.</tip>
+    <tip>Toisinaan järjestetään virallisia turnauksia. Tulevista tapahtumista tiedotetaan osoitteessa <a href="https://www.hedgewars.org/">www.hedgewars.org</a> muutama päivä etukäteen.</tip>
     <tip>Hedgewars on saatavilla monilla kielillä. Jos oman kielinen käännös puuttuu tai on vanhentunut, ota yhteyttä!</tip>
     <tip>Hedgewars toimii useilla eri käyttöjärjestelmillä, kuten Microsoft Windowsissa, Mac OS X:ssä ja Linuxissa.</tip>
     <tip>Voit aina luoda oman pelisi paikallisesti ja verkkopelissä. Et ole rajoitettu yksinkertaiseen peliin.</tip>
@@ -42,7 +42,7 @@
     <tip>Haluatko todella pitää tiettyä hattua? Lahjoita meille niin saat yksinoikeudella vapaavalintaisen hatun!</tip>
     <tip>Pidä näytönohjaimesi ajurit ajantasalla jotta peli pyörii sulavasti ja ongelmitta.</tip>
     <tip>Löydät Hedgewars-asetustiedostot hakemistosta "Omat tiedostot\Hedgewars". Ota varmuuskopio tai ota ne mukaasi, mutta älä muokkaa niitä käsin.</tip>
-    <tip>Seuraa Hedgewarsia <a href="http://www.facebook.com/Hedgewars">Facebookissa</a> ja <a href="http://twitter.com/hedgewars">Twitterissä</a>.</tip>
+    <tip>Seuraa Hedgewarsia <a href="https://www.facebook.com/Hedgewars">Facebookissa</a> ja <a href="https://twitter.com/hedgewars">Twitterissä</a>.</tip>
     <tip>Kruunu vai klaava? Kirjoita "/rnd" aulassa ja ota selvää. Myös "/rnd kivi paperi sakset" toimii! </tip>
     <tip>Pelitiedostot (tallennukset ja demot) voidaan assosioida pelin kanssa, jolloin ne aukeavat suoraan verkko- ja tiedostoselaimesta.</tip>
     <tip>Suutarit miinat eivät ole harmittomia: ne räjähtävät kovasta iskusta!</tip>
--- a/share/hedgewars/Data/Locale/tips_fr.xml	Sat Jul 21 02:19:32 2018 +0300
+++ b/share/hedgewars/Data/Locale/tips_fr.xml	Fri Jul 20 20:00:52 2018 -0400
@@ -6,13 +6,13 @@
     <tip>Choisissez la même couleur qu'un ami pour jouer dans la même équipe. Chacun de vous continuera à contrôler son ou ses hérissons mais ils gagneront ou perdront ensembles.</tip>
     <tip>Certaines armes peuvent occasionner seulement de faibles dommages mais être beaucoup plus dévastatrices dans la situation adéquate. Essayez le Révolver pour envoyer plusieurs hérissons à l'eau.</tip>
     <tip>Si vous ne savez pas quoi faire et ne voulez pas gaspiller de munitions, passez un tour. Mais ne laissez pas trop filer le temps ou ce sera la Mort Subite !</tip>
-    <tip>Si vous voulez empêcher les autres d'utiliser votre pseudo sur le serveur officiel, créez un compte sur http://www.hedgewars.org/.</tip>
+    <tip>Si vous voulez empêcher les autres d'utiliser votre pseudo sur le serveur officiel, créez un compte sur https://www.hedgewars.org/.</tip>
     <tip>Assez du mode par défaut ? Essayez une des missions - elles offrent différents types de jeu suivant votre choix.</tip>
     <tip>Par défaut le jeu enregistre la dernière partie jouée comme une démonstration. Sélectionnez « Jeu en local » puis « Démonstrations » en bas à droite pour les visionner ou les gérer.</tip>
     <tip>Hedgewars est un jeu libre et gratuit créé sur notre temps libre. Si vous avez des problèmes, demandez sur nos forums mais n'attendez pas de support 24h/24.</tip>
     <tip>Hedgewars est un jeu libre et gratuit créé sur notre temps libre. Si vous l'aimez, aidez-nous avec un petit don ou contribuez par votre travail !</tip>
     <tip>Hedgewars est un jeu libre et gratuit créé sur notre temps libre. Partagez-le avec votre famille et vos amis comme vous le voulez !</tip>
-    <tip>De temps en temps il y aura des tournois officiels. Les évènements à venir seront annoncés sur http://www.hedgewars.org/ quelques jours à l'avance.</tip>
+    <tip>De temps en temps il y aura des tournois officiels. Les évènements à venir seront annoncés sur https://www.hedgewars.org/ quelques jours à l'avance.</tip>
     <tip>Hedgewars est disponible dans de nombreuses langues. Si la traduction dans votre langue est partielle ou obsolète, contactez-nous !</tip>
     <tip>Hedgewars peux être exécuté sur de nombreux systèmes d'exploitation différents, incluant Microsoft Windows, Mac OS X et Linux. </tip>
     <tip>Souvenez-vous que vous pouvez créer votre propres parties en local et en ligne. Vous n'est pas limités aux options de jeu par défaut.</tip>
--- a/share/hedgewars/Data/Locale/tips_gd.xml	Sat Jul 21 02:19:32 2018 +0300
+++ b/share/hedgewars/Data/Locale/tips_gd.xml	Fri Jul 20 20:00:52 2018 -0400
@@ -7,14 +7,14 @@
     <tip>Tha airm ann nach dèan ach beagan a dhochann ach dh'fhaoidte gum bi iad glè èifeachdach a-rèir an t-suidheachaidh. Feuch gun cleachd thu Iolaire an fhàsaich gus iomadh gràineag a chur dhan mhuir.</tip>
     <tip>Mur eil thu cinnteach na nì thu agus mur eil thu airson connadh a chaitheamh gun fheum, leig seachad do chuairt. Ach na fuirich ro fhada on a thigeadh bàs obann ort!</tip>
     <tip>A bheil thu airson ròpannan a shàbhaladh? Leig às an ròpa fad 's a bhios tu san adhair is loisg e a-rithist. Cho fad 's nach bean thu ri tìr is a chuimsicheas tu gu soirbheachail, cleachdaidh tu an ròpa agad a-rithist gun a bhith a' caitheamh connaidh!</tip>
-    <tip>Mur eil thu ag iarraidh gun cleachd daoine eile am far-ainm as fhearr leat air an fhrithealaiche oifigeil, clàraich cunntas air <a href="http://www.hedgewars.org/">http://www.hedgewars.org/</a>.</tip>
+    <tip>Mur eil thu ag iarraidh gun cleachd daoine eile am far-ainm as fhearr leat air an fhrithealaiche oifigeil, clàraich cunntas air <a href="https://www.hedgewars.org/">https://www.hedgewars.org/</a>.</tip>
     <tip>A bheil thu seachd searbh dhen gheama àbhaisteach? Feuch fear dhe na miseanan — bheir iad dòigh-chluiche eadar-dhealaichte dhut a-rèir an fhir a thagh thu</tip>
     <tip>Clàraichidh sinn an geama mu dheireadh a chluich thu mar demo gu fèin-obrachail. Tagh “Geama ionadail” agus tagh putan nan “Demo” taobh deas aig a' bhonn gus an cluich no an stiùireadh.</tip>
     <tip>'S e bathar-bog saor (Open Source) a th' ann an Hedgewars a tha sinn a' cruthachadh gu saor-thoileach. Ma tha duilgheadas agad, faighnich air a' bhòrd-bhrath no tadhail air an t-seòmar IRC againn!</tip>
     <tip>'S e bathar-bog saor (Open Source) a th' ann an Hedgewars a tha sinn a' cruthachadh gu saor-thoileach. Ma tha e a' còrdadh riut, nach doir thu tabhartas airgid no obrach dhuinn?</tip>
     <tip>'S e bathar-bog saor (Open Source) a th' ann an Hedgewars a tha sinn a' cruthachadh gu saor-thoileach. Co-roinn e le do theaghlach is caraidean mar a thogras tu!</tip>
     <tip>'S e bathar-bog saor (Open Source) a th' ann an Hedgewars a tha sinn a' cruthachadh gu saor-thoileach a cum tlachd! Coinnich ris an luchd-leasachaidh ann an <a href="irc://irc.freenode.net/hedgewars">#hedgewars</a>!</tip>
-    <tip>Bi fèill-chluiche oifigeil againn o àm gu àm. Sgaoilidh sinn brathan-naidheachd mu na tachartasan air <a href="http://www.hedgewars.org/">http://www.hedgewars.org/</a> beagan làithean ro làimh.</tip>
+    <tip>Bi fèill-chluiche oifigeil againn o àm gu àm. Sgaoilidh sinn brathan-naidheachd mu na tachartasan air <a href="https://www.hedgewars.org/">https://www.hedgewars.org/</a> beagan làithean ro làimh.</tip>
     <tip>Tha Hedgewars ri fhaighinn ann an iomadh cànan. Ma tha an cànan agad a dhìth no an t-eadar-theangachadh ro shean, nach cuir thu fios thugainn?</tip>
     <tip>Gabhaidh Hedgewars a ruith air iomadh siostam-obrachaidh, a' gabhail a-steach Microsoft Windows, Mac OS X agus GNU/Linux.</tip>
     <tip>Cuimhnich gur urrainn dhut na geamannan agad fhèin a suidheachadh air an lìonra ionadail no air loidhne. Tha barrachd roghainnean na geama simplidh agad.</tip>
@@ -42,7 +42,7 @@
     <tip>The Flame Thrower is a weapon but it can be used for tunnel digging as well.</tip>
     <tip>Use the Molotov or Flame Thrower to temporary keep hedgehogs from passing terrain such as tunnels or platforms.</tip>
     <tip>Want to know who’s behind the game? Click on the Hedgewars logo in the main menu to see the credits.</tip>
-    <tip>Like Hedgewars? Become a fan on <a href="http://www.facebook.com/Hedgewars">Facebook</a> or follow us on <a href="http://twitter.com/hedgewars">Twitter</a></tip>
+    <tip>Like Hedgewars? Become a fan on <a href="https://www.facebook.com/Hedgewars">Facebook</a> or follow us on <a href="https://twitter.com/hedgewars">Twitter</a></tip>
     <tip>Feel free to draw your own graves, hats, flags or even maps and themes! But note that you’ll have to share them somewhere to use them online.</tip>
     <tip>Keep your video card drivers up to date to avoid issues playing the game.</tip>
     <tip>Heads or tails? Type “/rnd” in the lobby and you’ll find out. Also “/rnd rock paper scissors” works!</tip>
@@ -66,7 +66,7 @@
     <tip>Be aware in lands of Snow and Christmas, because girders are made of slippery ice.</tip>
     <tip>The retreat time depends on the weapon you used. Be careful, some weapons don’t have a retreat time and immediately end your turn!</tip>
     <windows-only>
-        <tip>This version of Hedgewars supports <a href="http://www.xfire.com">Xfire</a>. Make sure to add Hedgewars to its game list so your friends can see you playing.</tip>
+        <tip>This version of Hedgewars supports <a href="https://www.xfire.com">Xfire</a>. Make sure to add Hedgewars to its game list so your friends can see you playing.</tip>
         <tip>You can find your Hedgewars configuration files under “My Documents\Hedgewars”. Create backups or take the files with you, but don’t edit them by hand.</tip>
     </windows-only>
     <mac-only>
@@ -75,4 +75,4 @@
     <linux-only>
         <tip>You can find your Hedgewars configuration files under “.hedgewars” in your home directory. Create backups or take the files with you, but don’t edit them by hand.</tip>
     </linux-only>
-</tips>
\ No newline at end of file
+</tips>
--- a/share/hedgewars/Data/Locale/tips_it.xml	Sat Jul 21 02:19:32 2018 +0300
+++ b/share/hedgewars/Data/Locale/tips_it.xml	Fri Jul 20 20:00:52 2018 -0400
@@ -7,14 +7,14 @@
     <tip>Alcune armi potrebbero fare pochi danni ma possono essere devastanti se usate al momento giusto. Prova ad esempio ad utilizzare la Desert Eagle per spingere più ricci in acqua.</tip>
     <tip>Se non sai cosa fare e non vuoi sprecare munizioni, salta il turno. Ma non farlo troppe volte perché c'è il Sudden Death!</tip>
     <tip>Vuoi utilizzare più a lungo la corda? Rilascia la corda a mezz'aria e spara di nuovo. Finché non tocchi il terreno potrai riusare la corda senza sprecare munizioni!</tip>
-    <tip>Se vuoi evitare che altri possano impersonarti, utilizzando il tuo nickname, sul server ufficiale, registrati su http://www.hedgewars.org/.</tip>
+    <tip>Se vuoi evitare che altri possano impersonarti, utilizzando il tuo nickname, sul server ufficiale, registrati su https://www.hedgewars.org/.</tip>
     <tip>Sei stanco delle partite preimpostate? Prova una missione - le missioni offrono interessanti modalità differenti di partite in base alle tue scelte.</tip>
     <tip>Il gioco salverà sempre l'ultima partita giocata come demo. Seleziona 'Gioco locale' e clicca il bottone 'Demos' nell'angolo in basso a destra per gestirle.</tip>
     <tip>Hedgewars è un programma Open Source e gratuito che creiamo nel nostro tempo libero. Se hai problemi, chiedi nei nostri forum oppure visita il nostro canale IRC!</tip>
     <tip>Hedgewars è un programma Open Source e gratuito che creiamo nel nostro tempo libero. Se ti piace, aiutaci con una piccola donazione o contribuisci con il tuo lavoro!</tip>
     <tip>Hedgewars è un programma Open Source e gratuito che creiamo nel nostro tempo libero. Condividilo con tutta la famiglia e con gli amici come più ti piace!</tip>
     <tip>Hedgewars è un programma Open Source e gratuito che creiamo nel nostro tempo libero. Incontra gli sviluppatori sul canale <a href="irc://irc.freenode.net/hedgewars">#hedgewars</a>!</tip>
-    <tip>Di tanto in tanto ci saranno tornei ufficiali. Gli eventi saranno annunciati su <a href="http://www.hedgewars.org/">http://www.hedgewars.org/</a> con qualche giorno di anticipo.</tip>
+    <tip>Di tanto in tanto ci saranno tornei ufficiali. Gli eventi saranno annunciati su <a href="https://www.hedgewars.org/">https://www.hedgewars.org/</a> con qualche giorno di anticipo.</tip>
     <tip>Hedgewars è disponibile in molte lingue. Se la traduzione nella tua lingua sembra mancante o non aggiornata, sentiti libero di contattaci!</tip>
     <tip>Hedgewars può essere usato su molti sistemi operativi differenti come Microsoft Windows, Mac OS X e GNU/Linux.</tip>
     <tip>Ricordati che sei sempre in grado di configurare partire personalizzate in locale e online. Non devi sentirti limitato alle opzioni predefinite!</tip>
@@ -42,7 +42,7 @@
     <tip>Il Lanciafiamme è un'arma che può essere usata anche per scavare gallerie.</tip>
     <tip>Usa la Bomba Molotov o il Lanciafiamme per impedire temporaneamente ai ricci di attraversare terreni pianeggianti, tunnel o collinette.</tip>
     <tip>Vuoi sapere chi c'è dietro il gioco? Clicca sul logo Hedgewars nel menu principale per vederne gli autori e sviluppatori.</tip>
-    <tip>Ti piace Hedgewars? Diventa fan su <a href="http://www.facebook.com/Hedgewars">Facebook</a> oppure seguici su <a href="http://twitter.com/hedgewars">Twitter</a></tip>
+    <tip>Ti piace Hedgewars? Diventa fan su <a href="https://www.facebook.com/Hedgewars">Facebook</a> oppure seguici su <a href="https://twitter.com/hedgewars">Twitter</a></tip>
     <tip>Sentiti libero di disegnare tombe, cappelli, bandiere o anche mappe e temi personalizzati! Ma nota che dovrai condividerli in qualche modo per usarli online.</tip>
     <tip>Mantieni aggiornati i driver della tua scheda video, per evitare problemi durante il gioco.</tip>
     <tip>Testa o croce? Scrivi “/rnd” nella schermata LOBBY e lo scoprirai. Funziona anche “/rnd carta sasso forbice”!</tip>
--- a/share/hedgewars/Data/Locale/tips_pl.xml	Sat Jul 21 02:19:32 2018 +0300
+++ b/share/hedgewars/Data/Locale/tips_pl.xml	Fri Jul 20 20:00:52 2018 -0400
@@ -12,7 +12,7 @@
     <tip>Hedgewars jest darmową grą o otwartym kodzie, którą tworzymy w naszym wolnym czasie. Jeśli ją lubisz, wspomóż nas małą wpłatą lub wnieś w nią trochę własnej pracy!</tip>
     <tip>Hedgewars jest darmową grą o otwartym kodzie, którą tworzymy w naszym wolnym czasie. Jeśli tylko chcesz, rozdaj ją swojej rodzinie i kolegom!</tip>
     <tip>Hedgewars jest darmową grą o otwartym kodzie, którą tworzymy w naszym wolnym czasie, tylko dla zabawy! Poznaj twórcó na <a href="irc://irc.freenode.net/hedgewars">#hedgewars</a>!</tip>
-    <tip>Od czasu do czasu będą organizowane mistrzostwa. Będą one ogłaszane z wyprzedzeniem na <a href="http://www.hedgewars.org/">http://www.hedgewars.org/</a>.</tip>
+    <tip>Od czasu do czasu będą organizowane mistrzostwa. Będą one ogłaszane z wyprzedzeniem na <a href="https://www.hedgewars.org/">https://www.hedgewars.org/</a>.</tip>
     <tip>Hedgewars jest dostępne w wielu językach. Jeśli brakuje tłumaczenia w twoim języku bądź jest ono niekompletne, nie bój się z nami skontaktować!</tip>
     <tip>Hedgewars może być uruchomione na różnych systemach operacyjnych, takich jak Microsoft Windows, Mac OS X, oraz GNU/Linux.</tip>
     <tip>Zawsze możesz zmieniać ustawienia gry w opcjach gry lokalnej lub sieciowej. Nie musisz ciągle używać tzw. "Szybkiej gry".</tip>
@@ -26,7 +26,7 @@
     <tip>Żaden jeż nie został ranny w czasie tworzenia tej gry.</tip>
     <tip>Hedgewars jest darmową grą o otwartym kodzie źródłowym, którą tworzymy w naszym wolnym czasie. Jeśli ktokolwiek sprzedał Tobie tę grę, powinieneś upomnieć się o swoje pieniądze!</tip>
     <tip>Jeśli podłączysz jeden lub więcej gamepadów przed włączeniem gry, będziesz mieć możliwość przypisania klawiszy, by sterować swoimi jeżami.</tip>
-    <tip>Stwórz konto na <a href="http://www.hedgewars.org/">http://www.hedgewars.org/</a>, by zapobiec używania twojego ulubionego nicku przez innych na oficjalnym serwerze.</tip>
+    <tip>Stwórz konto na <a href="https://www.hedgewars.org/">https://www.hedgewars.org/</a>, by zapobiec używania twojego ulubionego nicku przez innych na oficjalnym serwerze.</tip>
     <tip>Jeśli twoja karta nie wspiera sprzętowego przyspieszania OpenGL, spróbuj uaktualnić swoje sterowniki.</tip>
     <tip>Są trzy różne rodzaje skoku możliwe do wykonania. Naciśnij [wysoki skok] dwa razy by zrobić bardzo wysoki skok w tył.</tip>
     <tip>Boisz się upadku z krawędzi terenu? Przytrzymaj klawisz [precyzyjnego celowania], by obrócić się w [lewo] lub [prawo] bez ruszenia się z miejsca.</tip>
@@ -40,7 +40,7 @@
     <tip>Dystans, który ciasto może przebyć, zależy od terenu, który ma do przebycia. Użyj [ataku] by zdetonować je wcześniej.</tip>
     <tip>Miotacz ognia jest śmiercionośną bronią ale może być użyty również jako narzędzie do kopania tuneli.</tip>
     <tip>Chcesz wiedzieć kto tworzy tę grę? Kliknij logo w głównym menu, by zobaczyć autorów.</tip>
-    <tip>Lubisz Hedgewars? Zostań fanem na <a href="http://www.facebook.com/Hedgewars">Facebooku</a> lub obserwuj nas na <a href="http://twitter.com/hedgewars">Twitterze</a>!</tip>
+    <tip>Lubisz Hedgewars? Zostań fanem na <a href="https://www.facebook.com/Hedgewars">Facebooku</a> lub obserwuj nas na <a href="https://twitter.com/hedgewars">Twitterze</a>!</tip>
     <tip>Możesz rysować własne nagrobki, czapki, flagi lub nawet mapy albo motywy! Miej na uwadze by udostępnić je każdemu, kto będzie grał z Tobą przez sieć.</tip>
     <tip>Chcesz nosić wymarzoną czapkę? Wspomóż nas pieniężnie, a my zrobimy specjalną czapkę tylko dla Ciebie!</tip>
     <tip>Pamiętaj o aktualizowaniu sterowników, by zapobiec problemom z grami.</tip>
--- a/share/hedgewars/Data/Locale/tips_ru.xml	Sat Jul 21 02:19:32 2018 +0300
+++ b/share/hedgewars/Data/Locale/tips_ru.xml	Fri Jul 20 20:00:52 2018 -0400
@@ -6,13 +6,13 @@
     <tip>Выберите тот же цвет команда, что у друга, чтобы играть в союзе. Вы будете управлять своими ежами, но выиграете или проиграете вместе.</tip>
     <tip>Некоторые виды оружия наносят небольшой урон, но могут наносить больший урон в правильной ситуации. Попробуйте использовать пистолет Дезерт Игл, чтобы столкнуть несколько ежей в воду.</tip>
     <tip>Если вы не уверены в том, что хотите сделать и не хотите тратить снаряды, пропустите ход. Но не теряйте много времени, так как смерть неизбежна!</tip>
-    <tip>Если вы хотите предотвратить использование вашего псевдонима другими игроками на официальном игровом сервере, зарегистрируйтесь на http://www.hedgewars.org/.</tip>
+    <tip>Если вы хотите предотвратить использование вашего псевдонима другими игроками на официальном игровом сервере, зарегистрируйтесь на https://www.hedgewars.org/.</tip>
     <tip>Наскучила обычная игра? Попробуйте миссии, имеющие различные виды сценариев.</tip>
     <tip>По умолчанию игры всегда записывает последнюю игру в виде демки. Выберите "Локальную игру" и нажмите кнопку "Демки" в правом нижнем углу, чтобы проиграть запись.</tip>
     <tip>Hedgewars - это открытое и свободное программное обеспечение, которое мы создаём в наше свободное время. Если у вас возникают вопросы, задавайте их на нашем форуме, но пожалуйста, не ожидайте круглосуточной поддержки!</tip>
     <tip>Hedgewars - это открытое и свободное программное обеспечение, которое мы создаём в наше свободное время. Если вам понравилась игра, помогите нам денежным вознаграждением или вкладом в виде вашей работы!</tip>
     <tip>Hedgewars - это открытое и свободное программное обеспечение, которое мы создаём в наше свободное время. Распространяйте его среди друзей и членов семьи!</tip>
-    <tip>Время от времени проводятся официальные турниры. Предстоящие события анонсируются на http://www.hedgewars.org/ за несколько дней.</tip>
+    <tip>Время от времени проводятся официальные турниры. Предстоящие события анонсируются на https://www.hedgewars.org/ за несколько дней.</tip>
     <tip>Hedgewars доступен на многих языках. Если перевод на ваш язык отсутствует или устарел, сообщите нам!</tip>
     <tip>Hedgewars запускается на множестве различных операционных систем, включая Microsoft Windows, Mac OS X и Linux.</tip>
     <tip>Помните, что у вас есть возможность создать собственную игру локально или по сети. Вы не ограничены кнопкой "Простая игра".</tip>
@@ -26,7 +26,7 @@
     <tip>При подготовке игры не пострадал ни один ёж.</tip>
     <tip>Hedgewars - это открытое и свободное программное обеспечение, которое мы создаём в наше свободное время. Если кто-то продал вам игру, потребуйте возврат денег!</tip>
     <tip>Подсоедините один или несколько геймпадов перед запуском игры, и вы сможете настроить их для управления командами.</tip>
-    <tip>Если вы хотите предотвратить использование вашего псевдонима другими игроками на официальном игровом сервере, зарегистрируйтесь на http://www.hedgewars.org/.</tip>
+    <tip>Если вы хотите предотвратить использование вашего псевдонима другими игроками на официальном игровом сервере, зарегистрируйтесь на https://www.hedgewars.org/.</tip>
     <tip>Если ваша видеокарта не поддерживает ускорение OpenGL, попробуйте обновить видеодрайвер.</tip>
     <tip>Есть три вида прыжков. Нажмите [прыжок вверх] дважды, чтобы сделать очень высокий прыжок назад.</tip>
     <tip>Боитесь упасть с обрыва? Нажмите левый shift, чтобы повернуться влево или вправо, не передвигаясь.</tip>
--- a/share/hedgewars/Data/Locale/tips_sk.xml	Sat Jul 21 02:19:32 2018 +0300
+++ b/share/hedgewars/Data/Locale/tips_sk.xml	Fri Jul 20 20:00:52 2018 -0400
@@ -6,13 +6,13 @@
     <tip>Ak chcete hrať s priateľom ako tím, jednoducho si zvoľte tú istú farbu. I naďalej budete ovládať svojich vlastných ježkov, ale víťazstvá či prehry budú spoločné.</tip>
     <tip>Niektoré zbrane môžu spôsobovať málo škody, ale dokážu byť oveľa účinnejšie v tej správnej situácii. Skúste použiť Desert Eagle na zostrelenie viacerých ježkov do vody.</tip>
     <tip>Ak neviete, čo robiť a nechcete mrhať muníciou, preskočte ťah. Ale nerobte tak príliš často, pretože príde Náhla smrť!</tip>
-    <tip>Ak nechcete, aby niekto iný používal vašu prezývku na oficiálnom serveri, registrujte si účet na http://www.hedgewars.org/.</tip>
+    <tip>Ak nechcete, aby niekto iný používal vašu prezývku na oficiálnom serveri, registrujte si účet na https://www.hedgewars.org/.</tip>
     <tip>Nudí vás štandardná hra? Vyskúšajte si jednu z misii - ponúkajú iný herný zážitok v závislosti na tom, akú si vyberiete.</tip>
     <tip>Vo východzom nastavení sa posledná hra automaticky ukladá ako demo. Vyberte 'Miestna hra' a kliknite na tlačidlo 'Demá' v pravom dolnom rohu, ak si chcete demo uložiť alebo prehrať.</tip>
     <tip>Hedgewars je Open Source a Freeware, ktorý vytvárame vo voľnom čase. Ak máte problém, spýtajte sa na fóre, ale nečakajte podporu 24 hodín v týždni!</tip>
     <tip>Hedgewars je Open Source a Freeware, ktorý vytvárame vo voľnom čase. Ak chcete pomôcť, môžete nám zaslať malú finančnú výpomoc alebo prispieť vlastnou prácou!</tip>
     <tip>Hedgewars je Open Source a Freeware, ktorý vytvárame vo voľnom čase. Podeľte sa oň so svojou rodinou a priateľmi!</tip>
-    <tip>Z času na čas bývajú usporiadavané oficiálne turnaje. Najbližšie akcie sú vždy uverejnené na http://www.hedgewars.org/ pár dní dopredu.</tip>
+    <tip>Z času na čas bývajú usporiadavané oficiálne turnaje. Najbližšie akcie sú vždy uverejnené na https://www.hedgewars.org/ pár dní dopredu.</tip>
     <tip>Hedgewars je dostupný v mnohých jazykoch. Ak preklad do vašej reči chýba alebo nie je aktuálny, prosím, kontaktujte nás!</tip>
     <tip>Hedgewars beží na množstve rozličných operačných systémov vrátane Microsoft Windows, Mac OS X a Linuxu.</tip>
     <tip>Nezabudnite, že si vždy môžete vytvoriť vlastnú lokálnu alebo sieťovú/online hru. Nie ste obmedzený len na voľbu 'Jednoduchá hra'.</tip>
--- a/share/hedgewars/Data/Locale/tips_uk.xml	Sat Jul 21 02:19:32 2018 +0300
+++ b/share/hedgewars/Data/Locale/tips_uk.xml	Fri Jul 20 20:00:52 2018 -0400
@@ -6,13 +6,13 @@
     <tip>Виберіть той же колір що і в друга щоб грати в одній команді. Кожен з вас буде керувати власними їжаками але вони виграють чи програють разом.</tip>
     <tip>Деяка зброя наносить мало шкоди, але вона може бути більш руйнівною в правильній ситуації. Спробуйте використати Пустельного Орла для скидання кількох їжаків у воду.</tip>
     <tip>Якщо ви не знаєте що робити і не хочете витрачати боєприпаси, пропустіть один раунд. Але не марнуйте занадто багато часу, тому-що прийде Раптова Смерть!</tip>
-    <tip>Якщо ви хочете закріпити за собою нік на офіційному сервері, зареєструйте аккаунт на http://www.hedgewars.org/.</tip>
+    <tip>Якщо ви хочете закріпити за собою нік на офіційному сервері, зареєструйте аккаунт на https://www.hedgewars.org/.</tip>
     <tip>Ви втомилися від гри за замовчуванням? Спробуйте одну з місій - вони пропонують різні види гри залежно від вашого вибору.</tip>
     <tip>За замовчуванням остання гра завжди буде записуватись в якості демо. Виберіть 'Локальну Гру' і натисніть кнопку 'Демонстрації' у нижньому правому куті щоб грати або керувати ними.</tip>
     <tip>Hedgewars є відкритою та безплатною, ми створюємо її у вільний час. Якщо у вас є проблеми, запитайте на нашому форумі, але будь-ласка, не чекайте підтримки 24/7!</tip>
     <tip>Hedgewars є відкритою та безплатною, ми створюємо її у вільний час. Якщо вона вам подобається, допоможіть нам невеликим внеском або вкладіть свою роботу!</tip>
     <tip>Hedgewars є відкритою та безплатною, ми створюємо її у вільний час. Поділіться грою з родиною та друзями!</tip>
-    <tip>Час від часу проводяться офіційні турніри. Майбутні події будуть оголошені на http://www.hedgewars.org/ за кілька днів перед проведенням.</tip>
+    <tip>Час від часу проводяться офіційні турніри. Майбутні події будуть оголошені на https://www.hedgewars.org/ за кілька днів перед проведенням.</tip>
     <tip>Hedgewars доступна на багатьох мовах. Якщо переклад на вашу мову застарів чи відсутній, не соромтеся звертатися до нас!</tip>
     <tip>Hedgewars може бути запущений на багатьох операційних системах, включаючи Microsoft Windows, Mac OS X і Linux.</tip>
     <tip>Завжди пам'ятайте, ви можете створити свою власну гру в локальному та мережному/онлайн-режимах. Ви не обмежені опцією 'Проста Гра'.</tip>
--- a/share/hedgewars/Data/Missions/Challenge/User_Mission_-_RCPlane_Challenge.lua	Sat Jul 21 02:19:32 2018 +0300
+++ b/share/hedgewars/Data/Missions/Challenge/User_Mission_-_RCPlane_Challenge.lua	Fri Jul 20 20:00:52 2018 -0400
@@ -1,4 +1,5 @@
 HedgewarsScriptLoad("/Scripts/Locale.lua")
+HedgewarsScriptLoad("/Scripts/Achievements.lua")
 
 local player = nil
 local RCGear = nil
@@ -424,7 +425,7 @@
 			end
 			if(planesUsed == 1) then
 				SendStat(siCustomAchievement, loc("Congratulations! You have truly mastered this challenge! Don't forget to save the demo."))
-				SendStat(siCustomAchievement, string.format(loc("Achievement gotten: %s"), loc("Prestigious Pilot")))
+				awardAchievement(loc("Prestigious Pilot"), nil, false)
 			end
 
 			ShowMission     (
--- a/share/hedgewars/Data/Missions/Challenge/User_Mission_-_That_Sinking_Feeling.lua	Sat Jul 21 02:19:32 2018 +0300
+++ b/share/hedgewars/Data/Missions/Challenge/User_Mission_-_That_Sinking_Feeling.lua	Fri Jul 20 20:00:52 2018 -0400
@@ -1,6 +1,7 @@
 
 
 HedgewarsScriptLoad("/Scripts/Locale.lua")
+HedgewarsScriptLoad("/Scripts/Achievements.lua")
 
 local player
 local hh = {}
@@ -241,8 +242,7 @@
 				SendStat(siCustomAchievement, string.format(loc("You saved %d of 8 Hapless Hogs."), hhLeft))
 
 				if hhLeft == 8 then
-					AddCaption(string.format(loc("Achievement gotten: %s"), loc("Lively Lifeguard")) ,0xffba00ff,capgrpMessage2)
-					SendStat(siCustomAchievement, loc("You have obtained an achievement: Lively Lifeguard"))
+					awardAchievement(loc("Lively Lifeguard"))
 				end
 				EndGame()
 
--- a/share/hedgewars/Data/Missions/Scenario/User_Mission_-_Bamboo_Thicket.lua	Sat Jul 21 02:19:32 2018 +0300
+++ b/share/hedgewars/Data/Missions/Scenario/User_Mission_-_Bamboo_Thicket.lua	Fri Jul 20 20:00:52 2018 -0400
@@ -1,5 +1,6 @@
 
 HedgewarsScriptLoad("/Scripts/Locale.lua")
+HedgewarsScriptLoad("/Scripts/Achievements.lua")
 
 local player = nil 
 local enemy = nil
@@ -81,9 +82,7 @@
 		ShowMission(loc("Bamboo Thicket"), loc("MISSION SUCCESSFUL"), loc("Congratulations!"), 0, 0)
 		
 		if (turnNumber < 6) and (firedShell == false) then
-			local achievementString = string.format(loc("Achievement gotten: %s"), loc("Energetic Engineer"))
-			AddCaption(achievementString, 0xffba00ff, capgrpMessage2)
-			SendStat(siCustomAchievement, achievementString)
+			awardAchievement(loc("Energetic Engineer"))
 		end
 
 	elseif gear == player then
--- a/share/hedgewars/Data/Missions/Scenario/User_Mission_-_Dangerous_Ducklings.lua	Sat Jul 21 02:19:32 2018 +0300
+++ b/share/hedgewars/Data/Missions/Scenario/User_Mission_-_Dangerous_Ducklings.lua	Fri Jul 20 20:00:52 2018 -0400
@@ -1,5 +1,6 @@
 
 HedgewarsScriptLoad("/Scripts/Locale.lua")
+HedgewarsScriptLoad("/Scripts/Achievements.lua")
 
 local player = nil -- This variable will point to the hog's gear
 local instructor = nil
@@ -136,9 +137,7 @@
 		elseif (gear == instructor) and (GetY(gear) > WaterLine) then
 			HogSay(player, loc("See ya!"), SAY_THINK)
 			TurnTimeLeft = 3000
-			local achievementString = string.format(loc("Achievement gotten: %s"), loc("Naughty Ninja"))
-			AddCaption(achievementString, 0xffba00ff, capgrpMessage2)
-			SendStat(siCustomAchievement, achievementString)
+			awardAchievement(loc("Naughty Ninja"))
 			DismissTeam(loc("Blue Team"))
 			gameWon = true
 		elseif gear == enemy then
--- a/share/hedgewars/Data/Missions/Training/Basic_Training_-_Bazooka.lua	Sat Jul 21 02:19:32 2018 +0300
+++ b/share/hedgewars/Data/Missions/Training/Basic_Training_-_Bazooka.lua	Fri Jul 20 20:00:52 2018 -0400
@@ -12,6 +12,7 @@
 ]]
 
 HedgewarsScriptLoad("/Scripts/Locale.lua")
+HedgewarsScriptLoad("/Scripts/Achievements.lua")
 
 local hog			-- Hog gear
 local weaponSelected = false	-- Player has selected the weapon
@@ -190,6 +191,9 @@
 		AddAmmo(CurrentHedgehog, amBazooka, 0)
 		if shotsFired > maxTargets then
 			flawless = false
+		else
+			-- For 100% accuracy
+			awardAchievement(loc("Bazooka Master"))
 		end
 		if flawless then
 			PlaySound(sndFlawless, hog)
@@ -217,6 +221,12 @@
 	end
 end
 
+function onAttack()
+	if GetCurAmmoType() == amBazooka then
+		HideMission()
+	end
+end
+
 function onGearAdd(gear)
 	if GetGearType(gear) == gtTarget then
 		targetsLeft = targetsLeft + 1
--- a/share/hedgewars/Data/Missions/Training/Basic_Training_-_Grenade.lua	Sat Jul 21 02:19:32 2018 +0300
+++ b/share/hedgewars/Data/Missions/Training/Basic_Training_-_Grenade.lua	Fri Jul 20 20:00:52 2018 -0400
@@ -192,6 +192,12 @@
 	end
 end
 
+function onAttack()
+	if GetCurAmmoType() == amGrenade then
+		HideMission()
+	end
+end
+
 function onGearAdd(gear)
 	if GetGearType(gear) == gtTarget then
 		targetsLeft = targetsLeft + 1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/share/hedgewars/Data/Scripts/Achievements.lua	Fri Jul 20 20:00:52 2018 -0400
@@ -0,0 +1,15 @@
+HedgewarsScriptLoad("/Scripts/Locale.lua")
+
+function awardAchievement(name, statMessage, capgrp)
+	local achievementString = string.format(loc("Achievement gotten: %s"), name)
+	if capgrp == nil then
+		captionType = capgrpMessage2
+	end
+	if capgrp ~= false then
+		AddCaption(achievementString, 0xFFBA00FF, capgrpMessage2)
+	end
+	if not statMessage then
+		statMessage = achievementString
+	end
+	SendStat(siCustomAchievement, statMessage)
+end
--- a/share/hedgewars/Data/Scripts/Multiplayer/Continental_supplies.lua	Sat Jul 21 02:19:32 2018 +0300
+++ b/share/hedgewars/Data/Scripts/Multiplayer/Continental_supplies.lua	Fri Jul 20 20:00:52 2018 -0400
@@ -1017,7 +1017,7 @@
 --cont=no		remove the pre-defined continents
 
 --for custom made continent, follows the same standards as the globalism one. You can make your continent with <Name>~<Information>~<Weapons>. Take the weapons generated from globalism, if you want a GUI :P
---weapons=<ammo><types>, ammo = ascii[116(1 ammo) to 125(inf ammo)] types = ascii[36(Grenade), 37(Clusterbomb) to 90(knife)] see http://hedgewars.org/kb/AmmoTypes
+--weapons=<ammo><types>, ammo = ascii[116(1 ammo) to 125(inf ammo)] types = ascii[36(Grenade), 37(Clusterbomb) to 90(knife)] see https://hedgewars.org/kb/AmmoTypes
 --ex "Own continent~this continent rocks!~tZ}$" will get 1 knife and inf grenades
 function onParameters()
 
--- a/share/hedgewars/Data/Scripts/Multiplayer/HedgeEditor.lua	Sat Jul 21 02:19:32 2018 +0300
+++ b/share/hedgewars/Data/Scripts/Multiplayer/HedgeEditor.lua	Fri Jul 20 20:00:52 2018 -0400
@@ -7,7 +7,7 @@
 -- Original author: mikade
 
 -- feel free to shower me with your adoration and/or hate mail
--- more info can be found at http://hedgewars.org/HedgeEditor
+-- more info can be found at https://hedgewars.org/HedgeEditor
 
 -- special thanks to nemo, unC0Rr, sheepluva and koda for their assistance
 
--- a/share/hedgewars/Data/Scripts/Multiplayer/WxW.lua	Sat Jul 21 02:19:32 2018 +0300
+++ b/share/hedgewars/Data/Scripts/Multiplayer/WxW.lua	Fri Jul 20 20:00:52 2018 -0400
@@ -6,7 +6,7 @@
 -- by mikade
 
 -- feel free to add map specific walls to LoadConfig, or post additional
--- wall suggestions on our forum at: http://www.hedgewars.org/forum
+-- wall suggestions on our forum at: https://www.hedgewars.org/forum
 
 ----------------
 --0.1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/README.md	Fri Jul 20 20:00:52 2018 -0400
@@ -0,0 +1,20 @@
+# tools/ directory
+
+This directory contains various tools for HW development.
+
+To learn more about each individual tool, open its source file in a text editor,
+it often contains a brief comment at the top.
+
+## List of tools (excerpt)
+
+### Files
+* `update_locale_files.sh`: Update locale files
+* `hwmap2lua.sh`: Convert HWMAP files to Lua code for usage in missions
+* `create_dmg.sh`: Generate a .dmg file (relevant for Mac)
+* `dmg_pkg_install.sh`: Downloads and install a .dmg from a URL (relevant for Mac)
+* `docgen.sh`: Generate QTfrontend documentation with Doxygen (it's not very good)
+
+### Directories
+* `hwmapconverter`: C++ application to edit HWMAP files in text form
+* `pas2c`: Pascal-to-C rewriter. Used when hwengine is built as C application with `BUILD_ENGINE_C=1`
+* `old`: Very outdated stuff that needs re-examination and possibly deletion
--- a/tools/build_windows.bat	Sat Jul 21 02:19:32 2018 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-@echo off
-::edit these variables if you need
-set PASCAL=C:\FPC\2.6.0\bin\i386-win32\
-set QTDIR=C:\QtSDK\Desktop\Qt\4.7.4\mingw\bin
-set PATH=%PATH%;%PASCAL%
-set BUILD_TYPE="Debug"
-
-:setup
-set CURRDIR="%CD%"
-cd ..
-
-echo Fetching all DLLs...
-if %BUILD_TYPE%=="Debug" (
-    for %%G in (QtCored4 QtGuid4 QtNetworkd4) do xcopy /d/y %QTDIR%\%%G.dll %CD%\bin\
-)
-:: should you libgcc dynamically you should try adding libgcc_s_dw2-1 and mingwm10
-for %%G in (QtCore4 QtGui4 QtNetwork4) do (
-    xcopy /d/y %QTDIR%\%%G.dll %CD%\bin\
-)
-
-if not exist %CD%\misc\winutils\bin\ mkdir %CD%\misc\winutils\bin\
-if not exist %CD%\misc\winutils\bin\SDL.dll cscript %CD%\tools\w32DownloadUnzip.vbs http://www.libsdl.org/release/SDL-1.2.15-win32.zip %CD%\misc\winutils\bin
-if not exist %CD%\misc\winutils\bin\SDL_image.dll cscript %CD%\tools\w32DownloadUnzip.vbs http://www.libsdl.org/projects/SDL_image/release/SDL_image-1.2.12-win32.zip %CD%\misc\winutils\bin
-if not exist %CD%\misc\winutils\bin\SDL_net.dll cscript %CD%\tools\w32DownloadUnzip.vbs http://www.libsdl.org/projects/SDL_net/release/SDL_net-1.2.8-win32.zip %CD%\misc\winutils\bin
-if not exist %CD%\misc\winutils\bin\SDL_mixer.dll cscript %CD%\tools\w32DownloadUnzip.vbs http://www.libsdl.org/projects/SDL_mixer/release/SDL_mixer-1.2.12-win32.zip %CD%\misc\winutils\bin
-if not exist %CD%\misc\winutils\bin\SDL_ttf.dll cscript %CD%\tools\w32DownloadUnzip.vbs  http://www.libsdl.org/projects/SDL_ttf/release/SDL_ttf-2.0.11-win32.zip %CD%\misc\winutils\bin
-
-::for video recording
-if not exist %CD%\misc\winutils\bin\avformat-54.dll cscript %CD%\tools\w32DownloadUnzip.vbs http://hedgewars.googlecode.com/files/libav-win32-20121022-dll.zip %CD%\misc\winutils\bin
-
-::this is needed because fpc png unit hardcodes libpng-1.2.12
-if not exist %CD%\misc\winutils\bin\libpng13.dll copy /y %CD%\misc\winutils\bin\libpng15-15.dll %CD%\misc\winutils\bin\libpng13.dll
-
-xcopy /d/y %CD%\misc\winutils\bin\*.dll %CD%\bin\
-
-::setting up the environment...
-call %QTDIR%\qtenv2.bat
-
-echo Running cmake...
-set ERRORLEVEL=
-cmake . -G "MinGW Makefiles" -DPNG_LIBRARY="%CD%\misc\winutils\bin\libpng13.dll" -DCMAKE_BUILD_TYPE="%BUILD_TYPE%" -DCMAKE_PREFIX_PATH="%CD%\misc\winutils\\"
-:: prefix should be last
-
-if %ERRORLEVEL% NEQ 0 goto exitpoint
-
-echo Running make...
-set ERRORLEVEL=
-mingw32-make VERBOSE=1
-if %ERRORLEVEL% NEQ 0 goto exitpoint
-
-echo Installing...
-set ERRORLEVEL=
-mingw32-make install > nul
-if %ERRORLEVEL% NEQ 0 goto exitpoint
-
-echo Creating commodity shortcut...
-copy /y %CD%\misc\winutils\Hedgewars.lnk C:%HOMEPATH%\Desktop\Hedgewars.lnk
-
-echo ALL DONE, Hedgewars has been successfully compiled and installed
-
-:exitpoint
-cd %CURRDIR%
-pause
--- a/tools/darkMagic.hs	Sat Jul 21 02:19:32 2018 +0300
+++ b/tools/darkMagic.hs	Fri Jul 20 20:00:52 2018 -0400
@@ -1,3 +1,5 @@
+{-# LANGUAGE FlexibleContexts #-}
+
 module Main where
 
 import System.Directory
@@ -156,4 +158,4 @@
 
     mapM_ processScript scripts
 
-    --putStrLn $ unlines l18ns
\ No newline at end of file
+    --putStrLn $ unlines l18ns
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/old/build_windows.bat	Fri Jul 20 20:00:52 2018 -0400
@@ -0,0 +1,80 @@
+:: WARNNG WARNING WARNING ::
+:: This Batch script is BROKEN and EXTREMELY OUTDATED!
+:: It does not work with latest version and needs a complete redo or removal.
+:: Its functionality has been disabled.
+
+:: Print dummy text and return.
+echo Sorry, this script is outdated. You're on your own.
+exit
+
+
+::::::::::::::::::::::::::::::
+:: Old script code follows ...
+::::::::::::::::::::::::::::::
+@echo off
+::edit these variables if you need
+set PASCAL=C:\FPC\2.6.0\bin\i386-win32\
+:: FIXME: Go Qt 5
+set QTDIR=C:\QtSDK\Desktop\Qt\4.7.4\mingw\bin
+set PATH=%PATH%;%PASCAL%
+set BUILD_TYPE="Debug"
+
+:setup
+set CURRDIR="%CD%"
+cd ..
+
+echo Fetching all DLLs...
+if %BUILD_TYPE%=="Debug" (
+    for %%G in (QtCored4 QtGuid4 QtNetworkd4) do xcopy /d/y %QTDIR%\%%G.dll %CD%\bin\
+)
+:: should you libgcc dynamically you should try adding libgcc_s_dw2-1 and mingwm10
+:: FIXME: Use Qt5
+for %%G in (QtCore4 QtGui4 QtNetwork4) do (
+    xcopy /d/y %QTDIR%\%%G.dll %CD%\bin\
+)
+
+:: FIXME: Use SDL 2.0
+if not exist %CD%\misc\winutils\bin\ mkdir %CD%\misc\winutils\bin\
+if not exist %CD%\misc\winutils\bin\SDL.dll cscript %CD%\tools\w32DownloadUnzip.vbs http://www.libsdl.org/release/SDL-1.2.15-win32.zip %CD%\misc\winutils\bin
+if not exist %CD%\misc\winutils\bin\SDL_image.dll cscript %CD%\tools\w32DownloadUnzip.vbs http://www.libsdl.org/projects/SDL_image/release/SDL_image-1.2.12-win32.zip %CD%\misc\winutils\bin
+if not exist %CD%\misc\winutils\bin\SDL_net.dll cscript %CD%\tools\w32DownloadUnzip.vbs http://www.libsdl.org/projects/SDL_net/release/SDL_net-1.2.8-win32.zip %CD%\misc\winutils\bin
+if not exist %CD%\misc\winutils\bin\SDL_mixer.dll cscript %CD%\tools\w32DownloadUnzip.vbs http://www.libsdl.org/projects/SDL_mixer/release/SDL_mixer-1.2.12-win32.zip %CD%\misc\winutils\bin
+if not exist %CD%\misc\winutils\bin\SDL_ttf.dll cscript %CD%\tools\w32DownloadUnzip.vbs  http://www.libsdl.org/projects/SDL_ttf/release/SDL_ttf-2.0.11-win32.zip %CD%\misc\winutils\bin
+
+::for video recording
+:: FIXME: googlecode.com is defunct.
+if not exist %CD%\misc\winutils\bin\avformat-54.dll cscript %CD%\tools\w32DownloadUnzip.vbs http://hedgewars.googlecode.com/files/libav-win32-20121022-dll.zip %CD%\misc\winutils\bin
+
+::this is needed because fpc png unit hardcodes libpng-1.2.12
+if not exist %CD%\misc\winutils\bin\libpng13.dll copy /y %CD%\misc\winutils\bin\libpng15-15.dll %CD%\misc\winutils\bin\libpng13.dll
+
+xcopy /d/y %CD%\misc\winutils\bin\*.dll %CD%\bin\
+
+::setting up the environment...
+call %QTDIR%\qtenv2.bat
+
+echo Running cmake...
+set ERRORLEVEL=
+cmake . -G "MinGW Makefiles" -DPNG_LIBRARY="%CD%\misc\winutils\bin\libpng13.dll" -DCMAKE_BUILD_TYPE="%BUILD_TYPE%" -DCMAKE_PREFIX_PATH="%CD%\misc\winutils\\"
+:: prefix should be last
+
+if %ERRORLEVEL% NEQ 0 goto exitpoint
+
+echo Running make...
+set ERRORLEVEL=
+mingw32-make VERBOSE=1
+if %ERRORLEVEL% NEQ 0 goto exitpoint
+
+echo Installing...
+set ERRORLEVEL=
+mingw32-make install > nul
+if %ERRORLEVEL% NEQ 0 goto exitpoint
+
+echo Creating commodity shortcut...
+copy /y %CD%\misc\winutils\Hedgewars.lnk C:%HOMEPATH%\Desktop\Hedgewars.lnk
+
+echo ALL DONE, Hedgewars has been successfully compiled and installed
+
+:exitpoint
+cd %CURRDIR%
+pause
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/old/w32DownloadUnzip.vbs	Fri Jul 20 20:00:52 2018 -0400
@@ -0,0 +1,66 @@
+' w32DownloadUnzip.vbs
+'   Download a zipfile and uncompress it with no external tools in Windows
+'
+' Copyright (c) 2012, Vittorio Giovara, <vittorio.giovara@gmail.com>
+' Redistribution and use is allowed according to the terms of the BSD license.
+'
+' References
+'   http://superuser.com/questions/59465/is-it-possible-to-download-using-the-windows-command-line
+'   http://stackoverflow.com/questions/1021557/how-to-unzip-a-file-using-the-command-line
+'   http://stackoverflow.com/questions/424331/get-the-current-temporary-directory-path-in-vbscript
+
+Set ArgObj = WScript.Arguments
+
+If (Wscript.Arguments.Count = 1) Then
+    strFileURL = ArgObj(0)
+    strOutputPath = CreateObject("Scripting.FileSystemObject").GetAbsolutePathName(".")
+Else
+    If (Wscript.Arguments.Count = 2) Then
+        strFileURL = ArgObj(0)
+        strOutputPath = ArgObj(1)
+    Else
+        WScript.Echo ("Usage: csript.exe w32DownloadUnzip.vbs url output")
+        WScript.Quit
+    End if
+End if
+
+' Temporary directory
+strHDLocation = WScript.CreateObject("Scripting.FileSystemObject").GetSpecialFolder(2) + "\hwlibtemp.zip"
+
+' Fetch the file
+WScript.Echo ( "Trying to download from " & strFileURL)
+Set objXMLHTTP = CreateObject("MSXML2.XMLHTTP")
+objXMLHTTP.open "GET", strFileURL, false
+objXMLHTTP.send()
+
+If objXMLHTTP.Status = 200 Then
+    Set objADOStream = CreateObject("ADODB.Stream")
+    objADOStream.Open
+    objADOStream.Type = 1 'adTypeBinary
+
+    objADOStream.Write objXMLHTTP.ResponseBody
+    objADOStream.Position = 0 'Set the stream position to the start
+
+    Set objFSO = Createobject("Scripting.FileSystemObject")
+    If objFSO.Fileexists(strHDLocation) Then objFSO.DeleteFile strHDLocation
+    Set objFSO = Nothing
+
+    objADOStream.SaveToFile strHDLocation
+    objADOStream.Close
+    Set objADOStream = Nothing
+    Set objXMLHTTP = Nothing
+Else
+    WScript.Echo ("Error downloading file (error code: " & objXMLHTTP.Status & ")")
+    Set objXMLHTTP = Nothing
+    WScript.Quit
+End if
+
+WScript.Echo ( "Extracting file to " & strOutputPath)
+Set objShell = CreateObject( "Shell.Application" )
+Set objSource = objShell.NameSpace(strHDLocation).Items()
+Set objTarget = objShell.NameSpace(strOutputPath)
+intOptions = 16 'no user prompt
+objTarget.CopyHere objSource, intOptions
+
+WScript.Echo ( "Success!" )
+Set objShell = Nothing
--- a/tools/pas2c/pas2c.cabal	Sat Jul 21 02:19:32 2018 +0300
+++ b/tools/pas2c/pas2c.cabal	Fri Jul 20 20:00:52 2018 -0400
@@ -2,7 +2,7 @@
 Version:             0.1
 Synopsis:            pas2c
 Description:         pas2c
-Homepage:            http://www.hedgewars.org/
+Homepage:            https://www.hedgewars.org/
 License:             GPL-2
 Author:              unC0Rr
 Maintainer:          unC0Rr@hedgewars.org
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/update_frontend_locale_files.sh	Fri Jul 20 20:00:52 2018 -0400
@@ -0,0 +1,8 @@
+#!/bin/sh -
+# Script to update all frontend locale files.
+
+# HOW TO USE:
+# - Run this script in the tools/ directory.
+# Result: All .ts files in share/hedgewars/Data/Locale will be updated.
+
+lupdate ../QTfrontend -ts ../share/hedgewars/Data/Locale/hedgewars_*.ts
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/update_locale_files.sh	Fri Jul 20 20:00:52 2018 -0400
@@ -0,0 +1,10 @@
+#!/bin/sh -
+# Script to update all Lua and frontend locale files.
+
+# HOW TO USE:
+# - Run this script in the tools/ directory.
+# Result: All .ts and .lua files in share/hedgewars/Data/Locale will be updated.
+# This will take a while!
+
+./update_frontend_locale_files.sh
+./update_lua_locale_files.sh
--- a/tools/update_lua_locale_files.sh	Sat Jul 21 02:19:32 2018 +0300
+++ b/tools/update_lua_locale_files.sh	Fri Jul 20 20:00:52 2018 -0400
@@ -5,13 +5,16 @@
 
 # HOW TO USE:
 # - Run this script in the tools/ directory.
-# - All .lua files in share/hedgewars/Data/Locale will be updated.
-# - Change LOCALEFILES below to limit the number of locale files to update
+# - (Optional) Change LOCALEFILES below to limit the number of locale files to update
+# Result: All .lua files in share/hedgewars/Data/Locale will be updated.
 
+# SETTINGS:
 # Space-separated list of locale files to update, or *.lua for all.
 # (Note: always include stub.lua)
 LOCALEFILES="*.lua"
 
+# END OF SETTINGS
+
 # List of all Lua files to scan:
 # * Missions
 # * Campaign missions
--- a/tools/w32DownloadUnzip.vbs	Sat Jul 21 02:19:32 2018 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-' w32DownloadUnzip.vbs
-'   Download a zipfile and uncompress it with no external tools in Windows
-'
-' Copyright (c) 2012, Vittorio Giovara, <vittorio.giovara@gmail.com>
-' Redistribution and use is allowed according to the terms of the BSD license.
-'
-' References
-'   http://superuser.com/questions/59465/is-it-possible-to-download-using-the-windows-command-line
-'   http://stackoverflow.com/questions/1021557/how-to-unzip-a-file-using-the-command-line
-'   http://stackoverflow.com/questions/424331/get-the-current-temporary-directory-path-in-vbscript
-
-Set ArgObj = WScript.Arguments
-
-If (Wscript.Arguments.Count = 1) Then
-    strFileURL = ArgObj(0)
-    strOutputPath = CreateObject("Scripting.FileSystemObject").GetAbsolutePathName(".")
-Else
-    If (Wscript.Arguments.Count = 2) Then
-        strFileURL = ArgObj(0)
-        strOutputPath = ArgObj(1)
-    Else
-        WScript.Echo ("Usage: csript.exe w32DownloadUnzip.vbs url output")
-        WScript.Quit
-    End if
-End if
-
-' Temporary directory
-strHDLocation = WScript.CreateObject("Scripting.FileSystemObject").GetSpecialFolder(2) + "\hwlibtemp.zip"
-
-' Fetch the file
-WScript.Echo ( "Trying to download from " & strFileURL)
-Set objXMLHTTP = CreateObject("MSXML2.XMLHTTP")
-objXMLHTTP.open "GET", strFileURL, false
-objXMLHTTP.send()
-
-If objXMLHTTP.Status = 200 Then
-    Set objADOStream = CreateObject("ADODB.Stream")
-    objADOStream.Open
-    objADOStream.Type = 1 'adTypeBinary
-
-    objADOStream.Write objXMLHTTP.ResponseBody
-    objADOStream.Position = 0 'Set the stream position to the start
-
-    Set objFSO = Createobject("Scripting.FileSystemObject")
-    If objFSO.Fileexists(strHDLocation) Then objFSO.DeleteFile strHDLocation
-    Set objFSO = Nothing
-
-    objADOStream.SaveToFile strHDLocation
-    objADOStream.Close
-    Set objADOStream = Nothing
-    Set objXMLHTTP = Nothing
-Else
-    WScript.Echo ("Error downloading file (error code: " & objXMLHTTP.Status & ")")
-    Set objXMLHTTP = Nothing
-    WScript.Quit
-End if
-
-WScript.Echo ( "Extracting file to " & strOutputPath)
-Set objShell = CreateObject( "Shell.Application" )
-Set objSource = objShell.NameSpace(strHDLocation).Items()
-Set objTarget = objShell.NameSpace(strOutputPath)
-intOptions = 16 'no user prompt
-objTarget.CopyHere objSource, intOptions
-
-WScript.Echo ( "Success!" )
-Set objShell = Nothing