Merge default qmlfrontend
authorunc0rr
Mon, 25 Apr 2016 22:10:06 +0300
branchqmlfrontend
changeset 11699 83c40c1eb0e7
parent 11634 0af93f018701 (current diff)
parent 11698 e86feecadced (diff)
child 11786 0aa4b3d02cba
Merge default
CMakeLists.txt
QTfrontend/res/iconDud@2x.png
QTfrontend/res/iconMine@2x.png
hedgewars/ArgParsers.pas
hedgewars/CMakeLists.txt
hedgewars/SDLh.pas
hedgewars/hwengine.pas
hedgewars/uInputHandler.pas
hedgewars/uLocale.pas
hedgewars/uPhysFSLayer.pas
share/hedgewars/Data/Graphics/Hats/tf_scount.png
--- a/.travis.yml	Tue Mar 29 22:36:59 2016 +0300
+++ b/.travis.yml	Mon Apr 25 22:10:06 2016 +0300
@@ -44,7 +44,7 @@
     sudo apt-get install debhelper cmake dpkg-dev libqt4-dev qt4-qmake libphysfs-dev libsdl2-dev libsdl2-ttf-dev libsdl2-mixer-dev libsdl2-image-dev libsdl2-net-dev bzip2 ghc libghc-mtl-dev libghc-parsec3-dev libghc-bytestring-show-dev libghc-vector-dev libghc-zlib-dev libghc-random-dev libghc-stm-dev libghc-network-dev libghc-dataenc-dev libghc-hslogger-dev libghc-utf8-string-dev libghc-sha-dev libghc-entropy-dev liblua5.1-0-dev imagemagick fpc fp-compiler fp-units-misc libpng-dev fp-units-gfx libavcodec-dev libavformat-dev libglew1.6-dev
   elif [ "$TRAVIS_OS_NAME" == "osx" ]; then
     brew install fpc glew qt physfs lua51 sdl2 sdl2_image sdl2_net sdl2_ttf ffmpeg ghc cabal-install
-    brew install sdl2_mixer --with-vorbis
+    brew install sdl2_mixer --with-libvorbis
     # use cabal install haskell deps, pas2c ones are covered by server
     if [[ "$BUILD_ARGS" != *"NOSERVER"* ]]; then
       cabal update
--- a/CMakeLists.txt	Tue Mar 29 22:36:59 2016 +0300
+++ b/CMakeLists.txt	Mon Apr 25 22:10:06 2016 +0300
@@ -41,6 +41,7 @@
 option(SKIPBUNDLE "Do not create relocate bundle (off)" OFF)
 
 option(BUILD_ENGINE_C "Compile hwengine as native C (off)" OFF)
+option(BUILD_ENGINE_JS "Compile hwengine as javascript (off)" OFF)
 option(GL2 "Enable OpenGL 2 rendering !!!EXPERIMENTAL - DO NOT USE!!! [default: off)" OFF)
 
 set(GHFLAGS "" CACHE STRING "Additional Haskell flags")
@@ -50,6 +51,22 @@
 
 option(NOVERSIONINFOUPDATE "Disable update of version_info.txt. To be used if source is in a git/repo that is NOT the hedgewars repo" OFF)
 
+
+if(BUILD_ENGINE_JS)
+    if(NOT CMAKE_TOOLCHAIN_FILE)
+        message(FATAL_ERROR "Missing emscripten toolchain file\nRerun cmake with -DCMAKE_TOOLCHAIN_FILE=${CMAKE_SOURCE_DIR}/cmake_modules/Platform/Emscripten.cmake")
+    endif()
+
+    set(BUILD_ENGINE_C ON CACHE STRING "Required for BUILD_ENGINE_JS" FORCE)
+    set(NOAUTOUPDATE ON CACHE STRING "Required for BUILD_ENGINE_JS" FORCE)
+    set(PHYSFS_SYSTEM OFF CACHE STRING "Required for BUILD_ENGINE_JS" FORCE)
+    set(LUA_SYSTEM OFF CACHE STRING "Required for BUILD_ENGINE_JS" FORCE)
+    set(NOVIDEOREC ON CACHE STRING "Required for BUILD_ENGINE_JS" FORCE)
+    set(NOSERVER ON CACHE STRING "Required for BUILD_ENGINE_JS" FORCE)
+    set(GL2 ON CACHE STRING "Required for BUILD_ENGINE_JS" FORCE)
+    set(BUILD_SHARED_LIBS OFF CACHE STRING "Required for BUILD_ENGINE_JS" FORCE)
+endif()
+
 #system paths for finding required fonts (see share/hedgewars/Data/fonts)
 #subdirectories will NOT be searched.
 #all fonts that can't be found will be bundled with hedgewars
@@ -90,7 +107,10 @@
 
 
 #perform safe check that enable/disable compilation features
-include(${CMAKE_MODULE_PATH}/compilerchecks.cmake)
+#skip when crosscompiling to javascript
+if(NOT BUILD_ENGINE_JS)
+    include(${CMAKE_MODULE_PATH}/compilerchecks.cmake)
+endif()
 
 #set default compiler flags
 add_flag_append(CMAKE_C_FLAGS "-Wall -pipe")
@@ -135,7 +155,7 @@
 
 
 #build engine without freepascal
-if(BUILD_ENGINE_C)
+if(BUILD_ENGINE_C AND NOT BUILD_ENGINE_JS)
     find_package(Clang REQUIRED)
 
     if(${CLANG_VERSION} VERSION_LESS "3.0")
@@ -232,9 +252,13 @@
 if(ANDROID)
     add_subdirectory(project_files/Android-build)
 else(ANDROID)
+    #skip frontend for javascript
+    if(NOT BUILD_ENGINE_JS)
+        add_subdirectory(qmlFrontend)
+        add_subdirectory(share)
+    endif()
+
     add_subdirectory(bin)
-    add_subdirectory(qmlFrontend)
-    add_subdirectory(share)
     add_subdirectory(tools)
 endif(ANDROID)
 
--- a/QTfrontend/hedgewars.qrc	Tue Mar 29 22:36:59 2016 +0300
+++ b/QTfrontend/hedgewars.qrc	Mon Apr 25 22:10:06 2016 +0300
@@ -122,7 +122,10 @@
         <file>res/btnBottomBorder@2x.png</file>
         <file>res/iconBox.png</file>
         <file>res/iconHealth.png</file>
+        <file>res/iconHealthPercent.png</file>
         <file>res/iconSuddenDeath.png</file>
+        <file>res/iconSuddenDeathTime.png</file>
+        <file>res/iconSuddenDeathWater.png</file>
         <file>res/iconDamage.png</file>
         <file>res/iconDamageLockG.png</file>
         <file>res/iconDamageLockR.png</file>
@@ -130,9 +133,13 @@
         <file>res/iconTimeLockG.png</file>
         <file>res/iconTimeLockR.png</file>
         <file>res/iconMine.png</file>
+        <file>res/iconMineTime.png</file>
         <file>res/iconDud.png</file>
+        <file>res/iconExplosive.png</file>
+        <file>res/iconAirMine.png</file>
         <file>res/iconRope.png</file>
         <file>res/iconEarth.png</file>
+        <file>res/iconScript.png</file>
         <file>res/dice.png</file>
         <file>res/Star.png</file>
         <file>res/inverse-corner-bl.png</file>
Binary file QTfrontend/res/iconAirMine.png has changed
Binary file QTfrontend/res/iconDud.png has changed
Binary file QTfrontend/res/iconDud@2x.png has changed
Binary file QTfrontend/res/iconExplosive.png has changed
Binary file QTfrontend/res/iconExplosive@2x.png has changed
Binary file QTfrontend/res/iconHealthPercent.png has changed
Binary file QTfrontend/res/iconMine.png has changed
Binary file QTfrontend/res/iconMine@2x.png has changed
Binary file QTfrontend/res/iconMineTime.png has changed
Binary file QTfrontend/res/iconScript.png has changed
Binary file QTfrontend/res/iconScript@2x.png has changed
Binary file QTfrontend/res/iconSuddenDeathTime.png has changed
Binary file QTfrontend/res/iconSuddenDeathWater.png has changed
--- a/QTfrontend/ui/page/pagecampaign.cpp	Tue Mar 29 22:36:59 2016 +0300
+++ b/QTfrontend/ui/page/pagecampaign.cpp	Mon Apr 25 22:10:06 2016 +0300
@@ -55,6 +55,9 @@
     CBTeam = new QComboBox(this);
     CBMission = new QComboBox(this);
     CBCampaign = new QComboBox(this);
+    CBTeam->setMaxVisibleItems(30);
+    CBMission->setMaxVisibleItems(30);
+    CBCampaign->setMaxVisibleItems(30);
 
     infoLayout->addWidget(btnPreview,0,1,2,1);
     infoLayout->addWidget(lbltitle,0,2,1,2);
--- a/QTfrontend/ui/page/pageeditteam.cpp	Tue Mar 29 22:36:59 2016 +0300
+++ b/QTfrontend/ui/page/pageeditteam.cpp	Mon Apr 25 22:10:06 2016 +0300
@@ -129,16 +129,19 @@
 
     CBGrave = new QComboBox(GBoxTeam);
     CBGrave->setMaxCount(65535);
+    CBGrave->setMaxVisibleItems(20);
     CBGrave->setIconSize(QSize(32, 32));
     GBTLayout->addWidget(CBGrave, 2, 1);
 
     CBFlag = new QComboBox(GBoxTeam);
     CBFlag->setMaxCount(65535);
+    CBFlag->setMaxVisibleItems(50);
     CBFlag->setIconSize(QSize(22, 15));
     GBTLayout->addWidget(CBFlag, 3, 1);
 
     QHBoxLayout * hbox = new QHBoxLayout();
     CBVoicepack = new QComboBox(GBoxTeam);
+    CBVoicepack->setMaxVisibleItems(50);
 
     hbox->addWidget(CBVoicepack, 100);
     btnTestSound = addSoundlessButton(":/res/PlaySound.png", hbox, 1, true);
--- a/QTfrontend/ui/page/pageoptions.cpp	Tue Mar 29 22:36:59 2016 +0300
+++ b/QTfrontend/ui/page/pageoptions.cpp	Mon Apr 25 22:10:06 2016 +0300
@@ -132,6 +132,7 @@
             groupTeams->layout()->setColumnStretch(0, 1);
 
             CBTeamName = new QComboBox(groupTeams);
+            CBTeamName->setMaxVisibleItems(50);
             groupTeams->layout()->addWidget(CBTeamName, 0, 0);
 
             BtnNewTeam = new QPushButton(groupTeams);
@@ -172,6 +173,7 @@
             groupSchemes->layout()->setColumnStretch(0, 1);
 
             SchemesName = new QComboBox(groupSchemes);
+            SchemesName->setMaxVisibleItems(50);
             groupSchemes->layout()->addWidget(SchemesName, 0, 0);
 
             SchemeNew = new QPushButton(groupSchemes);
@@ -203,6 +205,7 @@
             groupWeapons->layout()->setColumnStretch(0, 1);
 
             WeaponsName = new QComboBox(groupWeapons);
+            WeaponsName->setMaxVisibleItems(50);
             groupWeapons->layout()->addWidget(WeaponsName, 0, 0);
 
             WeaponNew = new QPushButton(groupWeapons);
@@ -256,6 +259,7 @@
             groupGame->layout()->addWidget(lblFullScreenRes, 1, 0);
 
             CBResolution = new QComboBox(groupGame);
+            CBResolution->setMaxVisibleItems(50);
             CBResolution->setFixedWidth(200);
             groupGame->layout()->addWidget(CBResolution, 1, 1, Qt::AlignLeft);
 
@@ -310,6 +314,7 @@
             groupGame->layout()->addWidget(lblStereo, 4, 0);
 
             CBStereoMode = new QComboBox(groupGame);
+            CBStereoMode->setMaxVisibleItems(50);
             CBStereoMode->addItem(QComboBox::tr("Disabled"));
             CBStereoMode->addItem(QComboBox::tr("Red/Cyan"));
             CBStereoMode->addItem(QComboBox::tr("Cyan/Red"));
@@ -618,6 +623,7 @@
             groupMisc->layout()->addWidget(labelLanguage, 0, 0);
 
             CBLanguage = new QComboBox(groupMisc);
+            CBLanguage->setMaxVisibleItems(50);
             groupMisc->layout()->addWidget(CBLanguage, 0, 1);
             QStringList locs = DataManager::instance().entryList("Locale", QDir::Files, QStringList("hedgewars_*.qm"));
             CBLanguage->addItem(QComboBox::tr("(System default)"), QString());
@@ -696,6 +702,7 @@
         // list of supported formats
 
         comboAVFormats = new QComboBox(groupVideoRec);
+        comboAVFormats->setMaxVisibleItems(50);
         groupVideoRec->layout()->addWidget(comboAVFormats, 0, 1, 1, 4);
         LibavInteraction::instance().fillFormats(comboAVFormats);
 
@@ -716,6 +723,7 @@
         // list of supported audio codecs
 
         comboAudioCodecs = new QComboBox(groupVideoRec);
+        comboAudioCodecs->setMaxVisibleItems(50);
         groupVideoRec->layout()->addWidget(comboAudioCodecs, 2, 1, 1, 3);
 
         // checkbox 'record audio'
@@ -741,6 +749,7 @@
         // list of supported video codecs
 
         comboVideoCodecs = new QComboBox(groupVideoRec);
+        comboVideoCodecs->setMaxVisibleItems(50);
         groupVideoRec->layout()->addWidget(comboVideoCodecs, 4, 1, 1, 4);
 
         // label for resolution
--- a/QTfrontend/ui/page/pagescheme.cpp	Tue Mar 29 22:36:59 2016 +0300
+++ b/QTfrontend/ui/page/pagescheme.cpp	Mon Apr 25 22:10:06 2016 +0300
@@ -71,102 +71,101 @@
     TBW_mode_Forts->setWhatsThis(tr("Defend your fort and destroy the opponents, two team colours max!"));
     glGMLayout->addWidget(TBW_mode_Forts,0,0,1,1);
 
-    TBW_teamsDivide = new ToggleButtonWidget(gbGameModes, ":/res/btnTeamsDivide@2x.png");
-    TBW_teamsDivide->setWhatsThis(tr("Teams will start on opposite sides of the terrain, two team colours max!"));
-    glGMLayout->addWidget(TBW_teamsDivide,0,1,1,1);
+    TBW_disablegirders = new ToggleButtonWidget(gbGameModes, ":/res/btnDisableGirders@2x.png");
+    TBW_disablegirders->setWhatsThis(tr("Disable girders when generating random maps."));
+    glGMLayout->addWidget(TBW_disablegirders,0,1,1,1);
 
-    TBW_solid = new ToggleButtonWidget(gbGameModes, ":/res/btnSolid@2x.png");
-    TBW_solid->setWhatsThis(tr("Land can not be destroyed!"));
-    glGMLayout->addWidget(TBW_solid,0,2,1,1);
+    TBW_disablelandobjects = new ToggleButtonWidget(gbGameModes, ":/res/btnDisableLandObjects@2x.png");
+    TBW_disablelandobjects->setWhatsThis(tr("Disable land objects when generating random maps."));
+    glGMLayout->addWidget(TBW_disablelandobjects,0,2,1,1);
 
     TBW_border = new ToggleButtonWidget(gbGameModes, ":/res/btnBorder@2x.png");
     TBW_border->setWhatsThis(tr("Add an indestructible border around the terrain"));
     glGMLayout->addWidget(TBW_border,0,3,1,1);
 
+    TBW_bottomborder = new ToggleButtonWidget(gbGameModes, ":/res/btnBottomBorder@2x.png");
+    TBW_bottomborder->setWhatsThis(tr("Add an indestructible border along the bottom"));
+    glGMLayout->addWidget(TBW_bottomborder,0,4,1,1);
+
+    TBW_solid = new ToggleButtonWidget(gbGameModes, ":/res/btnSolid@2x.png");
+    TBW_solid->setWhatsThis(tr("Land can not be destroyed!"));
+    glGMLayout->addWidget(TBW_solid,1,0,1,1);
+
     TBW_lowGravity = new ToggleButtonWidget(gbGameModes, ":/res/btnLowGravity@2x.png");
     TBW_lowGravity->setWhatsThis(tr("Lower gravity"));
-    glGMLayout->addWidget(TBW_lowGravity,0,4,1,1);
-
-    TBW_laserSight = new ToggleButtonWidget(gbGameModes, ":/res/btnLaserSight@2x.png");
-    TBW_laserSight->setWhatsThis(tr("Assisted aiming with laser sight"));
-    glGMLayout->addWidget(TBW_laserSight,1,0,1,1);
-
-    TBW_invulnerable = new ToggleButtonWidget(gbGameModes, ":/res/btnInvulnerable@2x.png");
-    TBW_invulnerable->setWhatsThis(tr("All hogs have a personal forcefield"));
-    glGMLayout->addWidget(TBW_invulnerable,1,1,1,1);
+    glGMLayout->addWidget(TBW_lowGravity,1,1,1,1);
 
-    TBW_resethealth = new ToggleButtonWidget(gbGameModes, ":/res/btnResetHealth@2x.png");
-    TBW_resethealth->setWhatsThis(tr("All (living) hedgehogs are fully restored at the end of turn"));
-    glGMLayout->addWidget(TBW_resethealth,1,2,1,1);
+    TBW_nowind = new ToggleButtonWidget(gbGameModes, ":/res/btnNoWind@2x.png");
+    TBW_nowind->setWhatsThis(tr("You will not have to worry about wind anymore."));
+    glGMLayout->addWidget(TBW_nowind,1,2,1,1);
 
-    TBW_vampiric = new ToggleButtonWidget(gbGameModes, ":/res/btnVampiric@2x.png");
-    TBW_vampiric->setWhatsThis(tr("Gain 80% of the damage you do back in health"));
-    glGMLayout->addWidget(TBW_vampiric,1,3,1,1);
-
-    TBW_karma = new ToggleButtonWidget(gbGameModes, ":/res/btnKarma@2x.png");
-    TBW_karma->setWhatsThis(tr("Share your opponents pain, share their damage"));
-    glGMLayout->addWidget(TBW_karma,1,4,1,1);
+    TBW_morewind = new ToggleButtonWidget(gbGameModes, ":/res/btnMoreWind@2x.png");
+    TBW_morewind->setWhatsThis(tr("Wind will affect almost everything."));
+    glGMLayout->addWidget(TBW_morewind,1,3,1,1);
 
     TBW_artillery = new ToggleButtonWidget(gbGameModes, ":/res/btnArtillery@2x.png");
     TBW_artillery->setWhatsThis(tr("Your hogs are unable to move, put your artillery skills to the test"));
-    glGMLayout->addWidget(TBW_artillery,2,0,1,1);
+    glGMLayout->addWidget(TBW_artillery,1,4,1,1);
 
-    TBW_randomorder = new ToggleButtonWidget(gbGameModes, ":/res/btnRandomOrder@2x.png");
-    TBW_randomorder->setWhatsThis(tr("Order of play is random instead of in room order."));
-    glGMLayout->addWidget(TBW_randomorder,2,1,1,1);
+    TBW_vampiric = new ToggleButtonWidget(gbGameModes, ":/res/btnVampiric@2x.png");
+    TBW_vampiric->setWhatsThis(tr("Gain 80% of the damage you do back in health"));
+    glGMLayout->addWidget(TBW_vampiric,2,0,1,1);
+
+    TBW_karma = new ToggleButtonWidget(gbGameModes, ":/res/btnKarma@2x.png");
+    TBW_karma->setWhatsThis(tr("Share your opponents pain, share their damage"));
+    glGMLayout->addWidget(TBW_karma,2,1,1,1);
 
-    TBW_king = new ToggleButtonWidget(gbGameModes, ":/res/btnKing@2x.png");
-    TBW_king->setWhatsThis(tr("Play with a King. If he dies, your side dies."));
-    glGMLayout->addWidget(TBW_king,2,2,1,1);
+    TBW_resethealth = new ToggleButtonWidget(gbGameModes, ":/res/btnResetHealth@2x.png");
+    TBW_resethealth->setWhatsThis(tr("All (living) hedgehogs are fully restored at the end of turn"));
+    glGMLayout->addWidget(TBW_resethealth,2,2,1,1);
+
+    TBW_aisurvival = new ToggleButtonWidget(gbGameModes, ":/res/btnAISurvival@2x.png");
+    TBW_aisurvival->setWhatsThis(tr("AI respawns on death."));
+    glGMLayout->addWidget(TBW_aisurvival,2,3,1,1);
 
-    TBW_placehog = new ToggleButtonWidget(gbGameModes, ":/res/btnPlaceHog@2x.png");
-    TBW_placehog->setWhatsThis(tr("Take turns placing your hedgehogs before the start of play."));
-    glGMLayout->addWidget(TBW_placehog,2,3,1,1);
+    TBW_invulnerable = new ToggleButtonWidget(gbGameModes, ":/res/btnInvulnerable@2x.png");
+    TBW_invulnerable->setWhatsThis(tr("All hogs have a personal forcefield"));
+    glGMLayout->addWidget(TBW_invulnerable,2,4,1,1);
+
+    TBW_perhogammo = new ToggleButtonWidget(gbGameModes, ":/res/btnPerHogAmmo@2x.png");
+    TBW_perhogammo->setWhatsThis(tr("Each hedgehog has its own ammo. It does not share with the team."));
+    glGMLayout->addWidget(TBW_perhogammo,3,0,1,1);
 
     TBW_sharedammo = new ToggleButtonWidget(gbGameModes, ":/res/btnSharedAmmo@2x.png");
     TBW_sharedammo->setWhatsThis(tr("Ammo is shared between all teams that share a colour."));
-    glGMLayout->addWidget(TBW_sharedammo,2,4,1,1);
-
-    TBW_disablegirders = new ToggleButtonWidget(gbGameModes, ":/res/btnDisableGirders@2x.png");
-    TBW_disablegirders->setWhatsThis(tr("Disable girders when generating random maps."));
-    glGMLayout->addWidget(TBW_disablegirders,3,0,1,1);
+    glGMLayout->addWidget(TBW_sharedammo,3,1,1,1);
 
-    TBW_disablelandobjects = new ToggleButtonWidget(gbGameModes, ":/res/btnDisableLandObjects@2x.png");
-    TBW_disablelandobjects->setWhatsThis(tr("Disable land objects when generating random maps."));
-    glGMLayout->addWidget(TBW_disablelandobjects,3,1,1,1);
-
-    TBW_aisurvival = new ToggleButtonWidget(gbGameModes, ":/res/btnAISurvival@2x.png");
-    TBW_aisurvival->setWhatsThis(tr("AI respawns on death."));
-    glGMLayout->addWidget(TBW_aisurvival,3,2,1,1);
+    TBW_resetweps = new ToggleButtonWidget(gbGameModes, ":/res/btnResetWeps@2x.png");
+    TBW_resetweps->setWhatsThis(tr("Weapons are reset to starting values each turn."));
+    glGMLayout->addWidget(TBW_resetweps,3,2,1,1);
 
     TBW_infattack = new ToggleButtonWidget(gbGameModes, ":/res/btnInfAttack@2x.png");
     TBW_infattack->setWhatsThis(tr("Attacking does not end your turn."));
     glGMLayout->addWidget(TBW_infattack,3,3,1,1);
 
-    TBW_resetweps = new ToggleButtonWidget(gbGameModes, ":/res/btnResetWeps@2x.png");
-    TBW_resetweps->setWhatsThis(tr("Weapons are reset to starting values each turn."));
-    glGMLayout->addWidget(TBW_resetweps,3,4,1,1);
+    TBW_laserSight = new ToggleButtonWidget(gbGameModes, ":/res/btnLaserSight@2x.png");
+    TBW_laserSight->setWhatsThis(tr("Assisted aiming with laser sight"));
+    glGMLayout->addWidget(TBW_laserSight,3,4,1,1);
 
-    TBW_perhogammo = new ToggleButtonWidget(gbGameModes, ":/res/btnPerHogAmmo@2x.png");
-    TBW_perhogammo->setWhatsThis(tr("Each hedgehog has its own ammo. It does not share with the team."));
-    glGMLayout->addWidget(TBW_perhogammo,4,0,1,1);
+    TBW_randomorder = new ToggleButtonWidget(gbGameModes, ":/res/btnRandomOrder@2x.png");
+    TBW_randomorder->setWhatsThis(tr("Order of play is random instead of in room order."));
+    glGMLayout->addWidget(TBW_randomorder,4,0,1,1);
 
-    TBW_nowind = new ToggleButtonWidget(gbGameModes, ":/res/btnNoWind@2x.png");
-    TBW_nowind->setWhatsThis(tr("You will not have to worry about wind anymore."));
-    glGMLayout->addWidget(TBW_nowind,4,1,1,1);
+    TBW_placehog = new ToggleButtonWidget(gbGameModes, ":/res/btnPlaceHog@2x.png");
+    TBW_placehog->setWhatsThis(tr("Take turns placing your hedgehogs before the start of play."));
+    glGMLayout->addWidget(TBW_placehog,4,1,1,1);
 
-    TBW_morewind = new ToggleButtonWidget(gbGameModes, ":/res/btnMoreWind@2x.png");
-    TBW_morewind->setWhatsThis(tr("Wind will affect almost everything."));
-    glGMLayout->addWidget(TBW_morewind,4,2,1,1);
+    TBW_teamsDivide = new ToggleButtonWidget(gbGameModes, ":/res/btnTeamsDivide@2x.png");
+    TBW_teamsDivide->setWhatsThis(tr("Teams will start on opposite sides of the terrain, two team colours max!"));
+    glGMLayout->addWidget(TBW_teamsDivide,4,2,1,1);
 
     TBW_tagteam = new ToggleButtonWidget(gbGameModes, ":/res/btnTagTeam@2x.png");
     TBW_tagteam->setWhatsThis(tr("Teams in each clan take successive turns sharing their turn time."));
     glGMLayout->addWidget(TBW_tagteam,4,3,1,1);
 
-    TBW_bottomborder = new ToggleButtonWidget(gbGameModes, ":/res/btnBottomBorder@2x.png");
-    TBW_bottomborder->setWhatsThis(tr("Add an indestructible border along the bottom"));
-    glGMLayout->addWidget(TBW_bottomborder,4,4,1,1);
-
+    TBW_king = new ToggleButtonWidget(gbGameModes, ":/res/btnKing@2x.png");
+    TBW_king->setWhatsThis(tr("Play with a King. If he dies, your side dies."));
+    glGMLayout->addWidget(TBW_king,4,4,1,1);
 
     // Right
     QLabel * l;
@@ -219,7 +218,7 @@
     glBSLayout->addWidget(l,3,0,1,1);
     l = new QLabel(gbBasicSettings);
     l->setFixedSize(32,32);
-    l->setPixmap(QPixmap(":/res/iconSuddenDeath.png"));
+    l->setPixmap(QPixmap(":/res/iconSuddenDeathTime.png"));
     glBSLayout->addWidget(l,3,1,1,1);
     SB_SuddenDeath = new QSpinBox(gbBasicSettings);
     SB_SuddenDeath->setRange(0, 50);
@@ -233,7 +232,7 @@
     glBSLayout->addWidget(l,4,0,1,1);
     l = new QLabel(gbBasicSettings);
     l->setFixedSize(32,32);
-    l->setPixmap(QPixmap(":/res/iconSuddenDeath.png")); // TODO: icon
+    l->setPixmap(QPixmap(":/res/iconSuddenDeathWater.png"));
     glBSLayout->addWidget(l,4,1,1,1);
     SB_WaterRise = new QSpinBox(gbBasicSettings);
     SB_WaterRise->setRange(0, 100);
@@ -247,7 +246,7 @@
     glBSLayout->addWidget(l,5,0,1,1);
     l = new QLabel(gbBasicSettings);
     l->setFixedSize(32,32);
-    l->setPixmap(QPixmap(":/res/iconSuddenDeath.png")); // TODO: icon
+    l->setPixmap(QPixmap(":/res/iconSuddenDeath.png"));
     glBSLayout->addWidget(l,5,1,1,1);
     SB_HealthDecrease = new QSpinBox(gbBasicSettings);
     SB_HealthDecrease->setRange(0, 100);
@@ -288,7 +287,7 @@
     glBSLayout->addWidget(l,8,0,1,1);
     l = new QLabel(gbBasicSettings);
     l->setFixedSize(32,32);
-    l->setPixmap(QPixmap(":/res/iconHealth.png")); // TODO: icon
+    l->setPixmap(QPixmap(":/res/iconHealthPercent.png"));
     glBSLayout->addWidget(l,8,1,1,1);
     SB_HealthCrates = new QSpinBox(gbBasicSettings);
     SB_HealthCrates->setRange(0, 100);
@@ -302,7 +301,7 @@
     glBSLayout->addWidget(l,9,0,1,1);
     l = new QLabel(gbBasicSettings);
     l->setFixedSize(32,32);
-    l->setPixmap(QPixmap(":/res/iconHealth.png")); // TODO: icon
+    l->setPixmap(QPixmap(":/res/iconHealth.png"));
     glBSLayout->addWidget(l,9,1,1,1);
     SB_CrateHealth = new QSpinBox(gbBasicSettings);
     SB_CrateHealth->setRange(0, 200);
@@ -316,7 +315,7 @@
     glBSLayout->addWidget(l,10,0,1,1);
     l = new QLabel(gbBasicSettings);
     l->setFixedSize(32,32);
-    l->setPixmap(QPixmap(":/res/iconTime.png")); // TODO: icon
+    l->setPixmap(QPixmap(":/res/iconMineTime.png"));
     glBSLayout->addWidget(l,10,1,1,1);
     SB_MinesTime = new QSpinBox(gbBasicSettings);
     SB_MinesTime->setRange(-1, 5);
@@ -332,7 +331,7 @@
     glBSLayout->addWidget(l,11,0,1,1);
     l = new QLabel(gbBasicSettings);
     l->setFixedSize(32,32);
-    l->setPixmap(QPixmap(":/res/iconMine.png")); // TODO: icon
+    l->setPixmap(QPixmap(":/res/iconMine.png"));
     glBSLayout->addWidget(l,11,1,1,1);
     SB_Mines = new QSpinBox(gbBasicSettings);
     SB_Mines->setRange(0, 200);
@@ -360,7 +359,7 @@
     glBSLayout->addWidget(l,13,0,1,1);
     l = new QLabel(gbBasicSettings);
     l->setFixedSize(32,32);
-    l->setPixmap(QPixmap(":/res/iconDamage.png"));
+    l->setPixmap(QPixmap(":/res/iconExplosive.png"));
     glBSLayout->addWidget(l,13,1,1,1);
     SB_Explosives = new QSpinBox(gbBasicSettings);
     SB_Explosives->setRange(0, 200);
@@ -374,7 +373,7 @@
     glBSLayout->addWidget(l,14,0,1,1);
     l = new QLabel(gbBasicSettings);
     l->setFixedSize(32,32);
-    l->setPixmap(QPixmap(":/res/iconMine.png")); // TODO: icon
+    l->setPixmap(QPixmap(":/res/iconAirMine.png"));
     glBSLayout->addWidget(l,14,1,1,1);
     SB_AirMines = new QSpinBox(gbBasicSettings);
     SB_AirMines->setRange(0, 200);
@@ -420,7 +419,7 @@
     glBSLayout->addWidget(l,17,0,1,1);
     l = new QLabel(gbBasicSettings);
     l->setFixedSize(32,32);
-    l->setPixmap(QPixmap(":/res/iconBox.png"));
+    l->setPixmap(QPixmap(":/res/iconScript.png"));
     glBSLayout->addWidget(l,17,1,1,1);
 
     LE_ScriptParam = new QLineEdit(gbBasicSettings);
@@ -443,6 +442,7 @@
 {
     QHBoxLayout * bottomLayout = new QHBoxLayout();
     selectScheme = new QComboBox(this);
+    selectScheme->setMaxVisibleItems(50);
 
     bottomLayout->addWidget(selectScheme, 0);
     BtnCopy = addButton(tr("Copy"), bottomLayout, 1);
--- a/QTfrontend/ui/page/pageselectweapon.cpp	Tue Mar 29 22:36:59 2016 +0300
+++ b/QTfrontend/ui/page/pageselectweapon.cpp	Mon Apr 25 22:10:06 2016 +0300
@@ -40,6 +40,7 @@
     QGridLayout * bottomLayout = new QGridLayout();
 
     selectWeaponSet = new QComboBox(this);
+    selectWeaponSet->setMaxVisibleItems(50);
     bottomLayout->addWidget(selectWeaponSet, 0, 0, 2, 1);
 
     // first row
--- a/QTfrontend/ui/widget/feedbackdialog.cpp	Tue Mar 29 22:36:59 2016 +0300
+++ b/QTfrontend/ui/widget/feedbackdialog.cpp	Mon Apr 25 22:10:06 2016 +0300
@@ -61,7 +61,6 @@
     setWindowFlags(Qt::Sheet);
     setWindowModality(Qt::WindowModal);
     setWindowTitle(tr("Feedback"));
-    setMinimumSize(700, 460);
     resize(700, 460);
     setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
 
@@ -71,11 +70,9 @@
     /* Top layout */
 
     QVBoxLayout * pageLayout = new QVBoxLayout();
-    QHBoxLayout * summaryLayout = new QHBoxLayout();
-    QHBoxLayout * emailLayout = new QHBoxLayout();
-    QHBoxLayout * descriptionLayout = new QHBoxLayout();
-    QHBoxLayout * combinedTopLayout = new QHBoxLayout();
-    QHBoxLayout * systemLayout = new QHBoxLayout();
+    QGridLayout * feedbackLayout = new QGridLayout();
+
+    setStyleSheet("QPushButton { padding: 5px }");
 
     info = new QLabel();
     info->setText(QString(
@@ -96,65 +93,45 @@
     info->setOpenExternalLinks(true);
     pageLayout->addWidget(info);
 
-    QVBoxLayout * summaryEmailLayout = new QVBoxLayout();
-
-    const int labelWidth = 90;
-
     label_email = new QLabel();
     label_email->setText(QLabel::tr("Your Email"));
-    label_email->setFixedWidth(labelWidth);
-    emailLayout->addWidget(label_email);
     email = new QLineEdit();
-    emailLayout->addWidget(email);
-    summaryEmailLayout->addLayout(emailLayout);
+    feedbackLayout->addWidget(label_email, 0, 0);
+    feedbackLayout->addWidget(email, 0, 1);
 
     label_summary = new QLabel();
     label_summary->setText(QLabel::tr("Summary"));
-    label_summary->setFixedWidth(labelWidth);
-    summaryLayout->addWidget(label_summary);
     summary = new QLineEdit();
-    summaryLayout->addWidget(summary);
-    summaryEmailLayout->addLayout(summaryLayout);
-
-    combinedTopLayout->addLayout(summaryEmailLayout);
+    feedbackLayout->addWidget(label_summary, 1, 0);
+    feedbackLayout->addWidget(summary, 1, 1);
 
     CheckSendSpecs = new QCheckBox();
     CheckSendSpecs->setText(QLabel::tr("Send system information"));
     CheckSendSpecs->setChecked(true);
-    systemLayout->addWidget(CheckSendSpecs);
     BtnViewInfo = new QPushButton(tr("View"));
-    systemLayout->addWidget(BtnViewInfo, 1);
-    BtnViewInfo->setFixedSize(60, 30);
+    BtnViewInfo->setFixedHeight(40);
+    feedbackLayout->addWidget(CheckSendSpecs, 0, 2, 2, 1);
+    feedbackLayout->addWidget(BtnViewInfo, 0, 3, 2, 1);
     connect(BtnViewInfo, SIGNAL(clicked()), this, SLOT(ShowSpecs()));
-    combinedTopLayout->addLayout(systemLayout);
 
-    combinedTopLayout->setStretch(0, 1);
-    combinedTopLayout->insertSpacing(1, 20);
-
-    pageLayout->addLayout(combinedTopLayout);
 
     label_description = new QLabel();
     label_description->setText(QLabel::tr("Description"));
-    label_description->setFixedWidth(labelWidth);
-    descriptionLayout->addWidget(label_description, 0, Qt::AlignTop);
     description = new QTextBrowser();
     description->setReadOnly(false);
-    descriptionLayout->addWidget(description);
-    pageLayout->addLayout(descriptionLayout);
+    feedbackLayout->addWidget(label_description, 2, 0);
+    feedbackLayout->addWidget(description, 2, 1, 1, 3);
 
     /* Bottom layout */
 
-    QHBoxLayout * bottomLayout = new QHBoxLayout();
     QHBoxLayout * captchaLayout = new QHBoxLayout();
     QVBoxLayout * captchaInputLayout = new QVBoxLayout();
 
     QPushButton * BtnCancel = new QPushButton(tr("Cancel"));
-    bottomLayout->addWidget(BtnCancel, 0);
-    BtnCancel->setFixedSize(100, 40);
+    feedbackLayout->addWidget(BtnCancel, 3, 0);
+    BtnCancel->setFixedHeight(40);
     connect(BtnCancel, SIGNAL(clicked()), this, SLOT(reject()));
 
-    bottomLayout->insertStretch(1);
-
     label_captcha = new QLabel();
     label_captcha->setStyleSheet("border: 3px solid #ffcc00; border-radius: 4px");
     label_captcha->setText("loading<br>captcha");
@@ -166,27 +143,27 @@
     captchaInputLayout->addWidget(label_captcha_input);
     captchaInputLayout->setAlignment(label_captcha, Qt::AlignBottom);
     captcha_code = new QLineEdit();
-    captcha_code->setFixedSize(165, 30);
+    captcha_code->setFixedHeight(30);
     captchaInputLayout->addWidget(captcha_code);
     captchaInputLayout->setAlignment(captcha_code, Qt::AlignTop);
     captchaLayout->addLayout(captchaInputLayout);
     captchaLayout->setAlignment(captchaInputLayout, Qt::AlignLeft);
 
-    bottomLayout->addLayout(captchaLayout);
-    bottomLayout->addSpacing(40);
+    QWidget * captchaLayoutWidget = new QWidget();
+    captchaLayoutWidget->setContentsMargins(0, 0, 0, 0);
+    captchaLayoutWidget->setLayout(captchaLayout);
+    feedbackLayout->addWidget(captchaLayoutWidget, 3, 1, 1, 2);
 
     // TODO: Set green arrow icon for send button (:/res/Start.png)
     BtnSend = new QPushButton(tr("Send Feedback"));
-    bottomLayout->addWidget(BtnSend, 0);
-    BtnSend->setFixedSize(120, 40);
+    feedbackLayout->addWidget(BtnSend, 3, 3);
+    BtnSend->setFixedHeight(40);
     connect(BtnSend, SIGNAL(clicked()), this, SLOT(SendFeedback()));
 
-    bottomLayout->setStretchFactor(captchaLayout, 0);
-    bottomLayout->setStretchFactor(BtnSend, 1);
+    pageLayout->addLayout(feedbackLayout);
 
     QVBoxLayout * dialogLayout = new QVBoxLayout(this);
     dialogLayout->addLayout(pageLayout, 1);
-    dialogLayout->addLayout(bottomLayout);
 
     LoadCaptchaImage();
 }
--- a/QTfrontend/ui/widget/gamecfgwidget.cpp	Tue Mar 29 22:36:59 2016 +0300
+++ b/QTfrontend/ui/widget/gamecfgwidget.cpp	Mon Apr 25 22:10:06 2016 +0300
@@ -108,6 +108,7 @@
     GBoxOptionsLayout->addWidget(new QLabel(QLabel::tr("Style"), this), 1, 0);
 
     Scripts = new QComboBox(this);
+    Scripts->setMaxVisibleItems(30);
     GBoxOptionsLayout->addWidget(Scripts, 1, 1);
 
     Scripts->setModel(DataManager::instance().gameStyleModel());
@@ -121,6 +122,7 @@
     SchemeWidgetLayout->setMargin(0);
 
     GameSchemes = new QComboBox(SchemeWidget);
+    GameSchemes->setMaxVisibleItems(30);
     SchemeWidgetLayout->addWidget(GameSchemes, 0, 2);
     connect(GameSchemes, SIGNAL(currentIndexChanged(int)), this, SLOT(schemeChanged(int)));
 
@@ -139,6 +141,7 @@
     SchemeWidgetLayout->addWidget(new QLabel(QLabel::tr("Weapons"), SchemeWidget), 1, 0);
 
     WeaponsName = new QComboBox(SchemeWidget);
+    WeaponsName->setMaxVisibleItems(30);
     SchemeWidgetLayout->addWidget(WeaponsName, 1, 2);
 
     connect(WeaponsName, SIGNAL(currentIndexChanged(int)), this, SLOT(ammoChanged(int)));
--- a/QTfrontend/ui/widget/keybinder.cpp	Tue Mar 29 22:36:59 2016 +0300
+++ b/QTfrontend/ui/widget/keybinder.cpp	Mon Apr 25 22:10:06 2016 +0300
@@ -170,6 +170,7 @@
         comboBox->setModel((QAbstractItemModel*)DataManager::instance().bindsModel());
         comboBox->setVisible(false);
         comboBox->setFixedWidth(200);
+        comboBox->setMaxVisibleItems(50);
 
         // Table row
         int row = curTable->rowCount();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cmake_modules/CMakeSystemSpecificInformation.cmake	Mon Apr 25 22:10:06 2016 +0300
@@ -0,0 +1,123 @@
+# XXX Emscripten:
+# This file is copied as-is from the CMake source tree. Due to how CMake
+# platform toolchain files work, we must have a copy of this file located
+# relative to Emscripten platform toolchain file, or file inclusion order
+# in cmGlobalGenerator::EnableLanguage will not find Emscripten.cmake
+# toolchain file, and as a result, it is not possible to set the default
+# compilation output suffix to .js, and as a consequence the script
+# check_function_exists() will not function properly (it will try to
+# build to wrong file suffix)
+
+# CMake - Cross Platform Makefile Generator
+# Copyright 2000-2014 Kitware, Inc.
+# Copyright 2000-2011 Insight Software Consortium
+# All rights reserved.
+
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+
+# * Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+
+# * Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+
+# * Neither the names of Kitware, Inc., the Insight Software Consortium,
+#   nor the names of their contributors may be used to endorse or promote
+#   products derived from this software without specific prior written
+#   permission.
+
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# ------------------------------------------------------------------------------
+
+# The above copyright and license notice applies to distributions of
+# CMake in source and binary form.  Some source files contain additional
+# notices of original copyright by their contributors; see each source
+# for details.  Third-party software packages supplied with CMake under
+# compatible licenses provide their own copyright notices documented in
+# corresponding subdirectories.
+
+# ------------------------------------------------------------------------------
+
+# CMake was initially developed by Kitware with the following sponsorship:
+
+#  * National Library of Medicine at the National Institutes of Health
+#    as part of the Insight Segmentation and Registration Toolkit (ITK).
+
+#  * US National Labs (Los Alamos, Livermore, Sandia) ASC Parallel
+#    Visualization Initiative.
+
+#  * National Alliance for Medical Image Computing (NAMIC) is funded by the
+#    National Institutes of Health through the NIH Roadmap for Medical Research,
+#    Grant U54 EB005149.
+
+#  * Kitware, Inc.
+
+# This file is included by cmGlobalGenerator::EnableLanguage.
+# It is included after the compiler has been determined, so
+# we know things like the compiler name and if the compiler is gnu.
+
+# before cmake 2.6 these variables were set in cmMakefile.cxx. This is still
+# done to keep scripts and custom language and compiler modules working.
+# But they are reset here and set again in the platform files for the target
+# platform, so they can be used for testing the target platform instead
+# of testing the host platform.
+set(APPLE  )
+set(UNIX   )
+set(CYGWIN )
+set(WIN32  )
+
+
+# include Generic system information
+include(CMakeGenericSystem)
+
+# 2. now include SystemName.cmake file to set the system specific information
+set(CMAKE_SYSTEM_INFO_FILE Platform/${CMAKE_SYSTEM_NAME})
+
+include(${CMAKE_SYSTEM_INFO_FILE} OPTIONAL RESULT_VARIABLE _INCLUDED_SYSTEM_INFO_FILE)
+
+if(NOT _INCLUDED_SYSTEM_INFO_FILE)
+  message("System is unknown to cmake, create:\n${CMAKE_SYSTEM_INFO_FILE}"
+          " to use this system, please send your config file to "
+          "cmake@www.cmake.org so it can be added to cmake")
+  if(EXISTS ${CMAKE_BINARY_DIR}/CMakeCache.txt)
+    configure_file(${CMAKE_BINARY_DIR}/CMakeCache.txt
+                   ${CMAKE_BINARY_DIR}/CopyOfCMakeCache.txt COPYONLY)
+    message("Your CMakeCache.txt file was copied to CopyOfCMakeCache.txt. "
+            "Please send that file to cmake@www.cmake.org.")
+   endif()
+endif()
+
+
+# optionally include a file which can do extra-generator specific things, e.g.
+# CMakeFindEclipseCDT4.cmake asks gcc for the system include dirs for the Eclipse CDT4 generator
+if(CMAKE_EXTRA_GENERATOR)
+  string(REPLACE " " "" _CMAKE_EXTRA_GENERATOR_NO_SPACES ${CMAKE_EXTRA_GENERATOR} )
+  include("CMakeFind${_CMAKE_EXTRA_GENERATOR_NO_SPACES}" OPTIONAL)
+endif()
+
+
+# for most systems a module is the same as a shared library
+# so unless the variable CMAKE_MODULE_EXISTS is set just
+# copy the values from the LIBRARY variables
+# this has to be done after the system information has been loaded
+if(NOT CMAKE_MODULE_EXISTS)
+  set(CMAKE_SHARED_MODULE_PREFIX "${CMAKE_SHARED_LIBRARY_PREFIX}")
+  set(CMAKE_SHARED_MODULE_SUFFIX "${CMAKE_SHARED_LIBRARY_SUFFIX}")
+endif()
+
+
+set(CMAKE_SYSTEM_SPECIFIC_INFORMATION_LOADED 1)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cmake_modules/CheckTypeSize.c.in	Mon Apr 25 22:10:06 2016 +0300
@@ -0,0 +1,37 @@
+@headers@
+
+#undef KEY
+#if defined(__i386)
+# define KEY '_','_','i','3','8','6'
+#elif defined(__x86_64)
+# define KEY '_','_','x','8','6','_','6','4'
+#elif defined(__ppc__)
+# define KEY '_','_','p','p','c','_','_'
+#elif defined(__ppc64__)
+# define KEY '_','_','p','p','c','6','4','_','_'
+#endif
+
+#define SIZE (sizeof(@type@))
+char info_size[] =  {'I', 'N', 'F', 'O', ':', 's','i','z','e','[',
+  ('0' + ((SIZE / 10000)%10)),
+  ('0' + ((SIZE / 1000)%10)),
+  ('0' + ((SIZE / 100)%10)),
+  ('0' + ((SIZE / 10)%10)),
+  ('0' +  (SIZE    % 10)),
+  ']',
+#ifdef KEY
+  ' ','k','e','y','[', KEY, ']',
+#endif
+  '\0'};
+
+#ifdef __CLASSIC_C__
+int main(argc, argv) int argc; char *argv[];
+#else
+int main(int argc, char *argv[])
+#endif
+{
+  int require = 0;
+  require += info_size[argc];
+  (void)argv;
+  return SIZE;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cmake_modules/CheckTypeSize.cmake	Mon Apr 25 22:10:06 2016 +0300
@@ -0,0 +1,231 @@
+#.rst:
+# CheckTypeSize
+# -------------
+#
+# Check sizeof a type
+#
+# ::
+#
+#   CHECK_TYPE_SIZE(TYPE VARIABLE [BUILTIN_TYPES_ONLY]
+#                                 [LANGUAGE <language>])
+#
+# Check if the type exists and determine its size.  On return,
+# "HAVE_${VARIABLE}" holds the existence of the type, and "${VARIABLE}"
+# holds one of the following:
+#
+# ::
+#
+#    <size> = type has non-zero size <size>
+#    "0"    = type has arch-dependent size (see below)
+#    ""     = type does not exist
+#
+# Both ``HAVE_${VARIABLE}`` and ``${VARIABLE}`` will be created as internal
+# cache variables.
+#
+# Furthermore, the variable "${VARIABLE}_CODE" holds C preprocessor code
+# to define the macro "${VARIABLE}" to the size of the type, or leave
+# the macro undefined if the type does not exist.
+#
+# The variable "${VARIABLE}" may be "0" when CMAKE_OSX_ARCHITECTURES has
+# multiple architectures for building OS X universal binaries.  This
+# indicates that the type size varies across architectures.  In this
+# case "${VARIABLE}_CODE" contains C preprocessor tests mapping from
+# each architecture macro to the corresponding type size.  The list of
+# architecture macros is stored in "${VARIABLE}_KEYS", and the value for
+# each key is stored in "${VARIABLE}-${KEY}".
+#
+# If the BUILTIN_TYPES_ONLY option is not given, the macro checks for
+# headers <sys/types.h>, <stdint.h>, and <stddef.h>, and saves results
+# in HAVE_SYS_TYPES_H, HAVE_STDINT_H, and HAVE_STDDEF_H.  The type size
+# check automatically includes the available headers, thus supporting
+# checks of types defined in the headers.
+#
+# If LANGUAGE is set, the specified compiler will be used to perform the
+# check. Acceptable values are C and CXX
+#
+# Despite the name of the macro you may use it to check the size of more
+# complex expressions, too.  To check e.g.  for the size of a struct
+# member you can do something like this:
+#
+# ::
+#
+#   check_type_size("((struct something*)0)->member" SIZEOF_MEMBER)
+#
+#
+#
+# The following variables may be set before calling this macro to modify
+# the way the check is run:
+#
+# ::
+#
+#   CMAKE_REQUIRED_FLAGS = string of compile command line flags
+#   CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar)
+#   CMAKE_REQUIRED_INCLUDES = list of include directories
+#   CMAKE_REQUIRED_LIBRARIES = list of libraries to link
+#   CMAKE_REQUIRED_QUIET = execute quietly without messages
+#   CMAKE_EXTRA_INCLUDE_FILES = list of extra headers to include
+
+#=============================================================================
+# Copyright 2002-2009 Kitware, Inc.
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+#  License text for the above reference.)
+
+include(CheckIncludeFile)
+include(CheckIncludeFileCXX)
+
+cmake_policy(PUSH)
+cmake_policy(VERSION 3.0)
+
+get_filename_component(__check_type_size_dir "${CMAKE_CURRENT_LIST_FILE}" PATH)
+
+#-----------------------------------------------------------------------------
+# Helper function.  DO NOT CALL DIRECTLY.
+function(__check_type_size_impl type var map builtin language)
+  if(NOT CMAKE_REQUIRED_QUIET)
+    message(STATUS "Check size of ${type}")
+  endif()
+
+  # Include header files.
+  set(headers)
+  if(builtin)
+    if(HAVE_SYS_TYPES_H)
+      set(headers "${headers}#include <sys/types.h>\n")
+    endif()
+    if(HAVE_STDINT_H)
+      set(headers "${headers}#include <stdint.h>\n")
+    endif()
+    if(HAVE_STDDEF_H)
+      set(headers "${headers}#include <stddef.h>\n")
+    endif()
+  endif()
+  foreach(h ${CMAKE_EXTRA_INCLUDE_FILES})
+    set(headers "${headers}#include \"${h}\"\n")
+  endforeach()
+
+  # Perform the check.
+
+  if("${language}" STREQUAL "C")
+    set(src ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CheckTypeSize/${var}.c)
+  elseif("${language}" STREQUAL "CXX")
+    set(src ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CheckTypeSize/${var}.cpp)
+  else()
+    message(FATAL_ERROR "Unknown language:\n  ${language}\nSupported languages: C, CXX.\n")
+  endif()
+  set(bin ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CheckTypeSize/${var}.bin)
+  configure_file(${__check_type_size_dir}/CheckTypeSize.c.in ${src} @ONLY)
+  try_run(${var}_run_result HAVE_${var} ${CMAKE_BINARY_DIR} ${src}
+    COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
+    LINK_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES}
+    CMAKE_FLAGS
+      "-DCOMPILE_DEFINITIONS:STRING=${CMAKE_REQUIRED_FLAGS}"
+      "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}"
+    RUN_OUTPUT_VARIABLE ${var}_run_output
+    COMPILE_OUTPUT_VARIABLE output
+    )
+
+  if(${HAVE_${var}} AND NOT "${${var}_run_result}" STREQUAL "FAILED_TO_RUN")
+    set(${var} ${${var}_run_result})
+    if(NOT CMAKE_REQUIRED_QUIET)
+      message(STATUS "Check size of ${type} - done")
+    endif()
+    file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
+      "Determining size of ${type} passed with the following output:\n${output}\n\n")
+    set(${var} "${${var}}" CACHE INTERNAL "CHECK_TYPE_SIZE: sizeof(${type})")
+  else()
+    # The check failed to compile.
+    if(NOT CMAKE_REQUIRED_QUIET)
+      message(STATUS "Check size of ${type} - failed")
+    endif()
+    file(READ ${src} content)
+    file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
+      "Determining size of ${type} failed with the following output:\n${output}\n${src}:\n${content}\n\n")
+    set(${var} "" CACHE INTERNAL "CHECK_TYPE_SIZE: ${type} unknown")
+    file(REMOVE ${map})
+  endif()
+endfunction()
+
+#-----------------------------------------------------------------------------
+macro(CHECK_TYPE_SIZE TYPE VARIABLE)
+  # parse arguments
+  unset(doing)
+  foreach(arg ${ARGN})
+    if("x${arg}" STREQUAL "xBUILTIN_TYPES_ONLY")
+      set(_CHECK_TYPE_SIZE_${arg} 1)
+      unset(doing)
+    elseif("x${arg}" STREQUAL "xLANGUAGE") # change to MATCHES for more keys
+      set(doing "${arg}")
+      set(_CHECK_TYPE_SIZE_${doing} "")
+    elseif("x${doing}" STREQUAL "xLANGUAGE")
+      set(_CHECK_TYPE_SIZE_${doing} "${arg}")
+      unset(doing)
+    else()
+      message(FATAL_ERROR "Unknown argument:\n  ${arg}\n")
+    endif()
+  endforeach()
+  if("x${doing}" MATCHES "^x(LANGUAGE)$")
+    message(FATAL_ERROR "Missing argument:\n  ${doing} arguments requires a value\n")
+  endif()
+  if(DEFINED _CHECK_TYPE_SIZE_LANGUAGE)
+    if(NOT "x${_CHECK_TYPE_SIZE_LANGUAGE}" MATCHES "^x(C|CXX)$")
+      message(FATAL_ERROR "Unknown language:\n  ${_CHECK_TYPE_SIZE_LANGUAGE}.\nSupported languages: C, CXX.\n")
+    endif()
+    set(_language ${_CHECK_TYPE_SIZE_LANGUAGE})
+  else()
+    set(_language C)
+  endif()
+
+  # Optionally check for standard headers.
+  if(_CHECK_TYPE_SIZE_BUILTIN_TYPES_ONLY)
+    set(_builtin 0)
+  else()
+    set(_builtin 1)
+    if("${_language}" STREQUAL "C")
+      check_include_file(sys/types.h HAVE_SYS_TYPES_H)
+      check_include_file(stdint.h HAVE_STDINT_H)
+      check_include_file(stddef.h HAVE_STDDEF_H)
+    elseif("${_language}" STREQUAL "CXX")
+      check_include_file_cxx(sys/types.h HAVE_SYS_TYPES_H)
+      check_include_file_cxx(stdint.h HAVE_STDINT_H)
+      check_include_file_cxx(stddef.h HAVE_STDDEF_H)
+    endif()
+  endif()
+  unset(_CHECK_TYPE_SIZE_BUILTIN_TYPES_ONLY)
+  unset(_CHECK_TYPE_SIZE_LANGUAGE)
+
+  # Compute or load the size or size map.
+  set(${VARIABLE}_KEYS)
+  set(_map_file ${CMAKE_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/CheckTypeSize/${VARIABLE}.cmake)
+  if(NOT DEFINED HAVE_${VARIABLE})
+    __check_type_size_impl(${TYPE} ${VARIABLE} ${_map_file} ${_builtin} ${_language})
+  endif()
+  include(${_map_file} OPTIONAL)
+  set(_map_file)
+  set(_builtin)
+
+  # Create preprocessor code.
+  if(${VARIABLE}_KEYS)
+    set(${VARIABLE}_CODE)
+    set(_if if)
+    foreach(key ${${VARIABLE}_KEYS})
+      set(${VARIABLE}_CODE "${${VARIABLE}_CODE}#${_if} defined(${key})\n# define ${VARIABLE} ${${VARIABLE}-${key}}\n")
+      set(_if elif)
+    endforeach()
+    set(${VARIABLE}_CODE "${${VARIABLE}_CODE}#else\n# error ${VARIABLE} unknown\n#endif")
+    set(_if)
+  elseif(${VARIABLE})
+    set(${VARIABLE}_CODE "#define ${VARIABLE} ${${VARIABLE}}")
+  else()
+    set(${VARIABLE}_CODE "/* #undef ${VARIABLE} */")
+  endif()
+endmacro()
+
+#-----------------------------------------------------------------------------
+cmake_policy(POP)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cmake_modules/FindEmscripten.cmake	Mon Apr 25 22:10:06 2016 +0300
@@ -0,0 +1,36 @@
+# - Try to find the Clang/LLVM executable
+# Once done this will define
+#
+#  EMSCRIPTEN_FOUND       - system has Clang
+#  EMSCRIPTEN_VERSION     - Clang version
+#  EMSCRIPTEN_EXECUTABLE  - Clang executable
+#
+# Copyright (c) 2013, Vittorio Giovara <vittorio.giovara@gmail.com>
+#
+# Redistribution and use is allowed according to the terms of the BSD license.
+# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+
+find_program(EMSCRIPTEN_EXECUTABLE
+        NAMES emcc
+        PATHS /opt/local/bin /usr/local/bin /usr/bin)
+
+if (EMSCRIPTEN_EXECUTABLE)
+    execute_process(COMMAND ${EMSCRIPTEN_EXECUTABLE} -v
+                    OUTPUT_VARIABLE EMSCRIPTEN_VERSION_OUTPUT
+                    ERROR_VARIABLE EMSCRIPTEN_VERSION_ERROR
+                    RESULT_VARIABLE EMSCRIPTEN_VERSION_RESULT
+                    OUTPUT_STRIP_TRAILING_WHITESPACE
+                    )
+
+    if(${EMSCRIPTEN_VERSION_RESULT} EQUAL 0)
+        string(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" EMSCRIPTEN_VERSION "${EMSCRIPTEN_VERSION_OUTPUT}")
+        string(REGEX REPLACE "([0-9]+\\.[0-9]+\\.[0-9]+)" "\\1" EMSCRIPTEN_VERSION "${EMSCRIPTEN_VERSION}")
+    else()
+        message(SEND_ERROR "Command \"${EMSCRIPTEN_EXECUTABLE} --version\" failed with output: ${EMSCRIPTEN_VERSION_ERROR}")
+    endif()
+endif()
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(Emscripten DEFAULT_MSG EMSCRIPTEN_EXECUTABLE EMSCRIPTEN_VERSION)
+mark_as_advanced(EMSCRIPTEN_VERSION)
+
--- a/cmake_modules/FindGLEW.cmake	Tue Mar 29 22:36:59 2016 +0300
+++ b/cmake_modules/FindGLEW.cmake	Mon Apr 25 22:10:06 2016 +0300
@@ -34,6 +34,11 @@
             $ENV{PROGRAMFILES}/GLEW/lib
             DOC "The GLEW library")
 
+if(BUILD_ENGINE_JS)
+    set(GLEW_INCLUDE_DIR "${EMSCRIPTEN_ROOT_PATH}/system/include")
+    SET(GLEW_LIBRARY "glew_emscripten_internal")
+endif()
+
 find_package_handle_standard_args(GLEW DEFAULT_MSG GLEW_LIBRARY GLEW_INCLUDE_DIR)
 mark_as_advanced(GLEW_LIBRARY GLEW_INCLUDE_DIR)
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cmake_modules/FindOpenGL.cmake	Mon Apr 25 22:10:06 2016 +0300
@@ -0,0 +1,209 @@
+#.rst:
+# FindOpenGL
+# ----------
+#
+# FindModule for OpenGL and GLU.
+#
+# Result Variables
+# ^^^^^^^^^^^^^^^^
+#
+# This module sets the following variables:
+#
+# ``OPENGL_FOUND``
+#  True, if the system has OpenGL.
+# ``OPENGL_XMESA_FOUND``
+#  True, if the system has XMESA.
+# ``OPENGL_GLU_FOUND``
+#  True, if the system has GLU.
+# ``OPENGL_INCLUDE_DIR``
+#  Path to the OpenGL include directory.
+# ``OPENGL_LIBRARIES``
+#  Paths to the OpenGL and GLU libraries.
+#
+# If you want to use just GL you can use these values:
+#
+# ``OPENGL_gl_LIBRARY``
+#  Path to the OpenGL library.
+# ``OPENGL_glu_LIBRARY``
+#  Path to the GLU library.
+#
+# OSX Specific
+# ^^^^^^^^^^^^
+#
+# On OSX default to using the framework version of OpenGL. People will
+# have to change the cache values of OPENGL_glu_LIBRARY and
+# OPENGL_gl_LIBRARY to use OpenGL with X11 on OSX.
+
+
+#=============================================================================
+# Copyright 2001-2009 Kitware, Inc.
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+#  License text for the above reference.)
+
+set(_OpenGL_REQUIRED_VARS OPENGL_gl_LIBRARY)
+
+if (CYGWIN)
+
+  find_path(OPENGL_INCLUDE_DIR GL/gl.h )
+  list(APPEND _OpenGL_REQUIRED_VARS OPENGL_INCLUDE_DIR)
+
+  find_library(OPENGL_gl_LIBRARY opengl32 )
+
+  find_library(OPENGL_glu_LIBRARY glu32 )
+
+elseif (WIN32)
+
+  if(BORLAND)
+    set (OPENGL_gl_LIBRARY import32 CACHE STRING "OpenGL library for win32")
+    set (OPENGL_glu_LIBRARY import32 CACHE STRING "GLU library for win32")
+  else()
+    set (OPENGL_gl_LIBRARY opengl32 CACHE STRING "OpenGL library for win32")
+    set (OPENGL_glu_LIBRARY glu32 CACHE STRING "GLU library for win32")
+  endif()
+
+elseif (APPLE)
+
+  # The OpenGL.framework provides both gl and glu
+  find_library(OPENGL_gl_LIBRARY OpenGL DOC "OpenGL library for OS X")
+  find_library(OPENGL_glu_LIBRARY OpenGL DOC
+    "GLU library for OS X (usually same as OpenGL library)")
+  find_path(OPENGL_INCLUDE_DIR OpenGL/gl.h DOC "Include for OpenGL on OS X")
+  list(APPEND _OpenGL_REQUIRED_VARS OPENGL_INCLUDE_DIR)
+
+else()
+  if (CMAKE_SYSTEM_NAME MATCHES "HP-UX")
+    # Handle HP-UX cases where we only want to find OpenGL in either hpux64
+    # or hpux32 depending on if we're doing a 64 bit build.
+    if(CMAKE_SIZEOF_VOID_P EQUAL 4)
+      set(_OPENGL_LIB_PATH
+        /opt/graphics/OpenGL/lib/hpux32/)
+    else()
+      set(_OPENGL_LIB_PATH
+        /opt/graphics/OpenGL/lib/hpux64/
+        /opt/graphics/OpenGL/lib/pa20_64)
+    endif()
+  elseif(CMAKE_SYSTEM_NAME STREQUAL Haiku)
+    set(_OPENGL_LIB_PATH
+      /boot/develop/lib/x86)
+    set(_OPENGL_INCLUDE_PATH
+      /boot/develop/headers/os/opengl)
+  endif()
+
+  # The first line below is to make sure that the proper headers
+  # are used on a Linux machine with the NVidia drivers installed.
+  # They replace Mesa with NVidia's own library but normally do not
+  # install headers and that causes the linking to
+  # fail since the compiler finds the Mesa headers but NVidia's library.
+  # Make sure the NVIDIA directory comes BEFORE the others.
+  #  - Atanas Georgiev <atanas@cs.columbia.edu>
+
+  find_path(OPENGL_INCLUDE_DIR GL/gl.h
+    /usr/share/doc/NVIDIA_GLX-1.0/include
+    /usr/openwin/share/include
+    /opt/graphics/OpenGL/include /usr/X11R6/include
+    ${_OPENGL_INCLUDE_PATH}
+  )
+  list(APPEND _OpenGL_REQUIRED_VARS OPENGL_INCLUDE_DIR)
+
+  find_path(OPENGL_xmesa_INCLUDE_DIR GL/xmesa.h
+    /usr/share/doc/NVIDIA_GLX-1.0/include
+    /usr/openwin/share/include
+    /opt/graphics/OpenGL/include /usr/X11R6/include
+  )
+
+  find_library(OPENGL_gl_LIBRARY
+    NAMES GL MesaGL
+    PATHS /opt/graphics/OpenGL/lib
+          /usr/openwin/lib
+          /usr/shlib /usr/X11R6/lib
+          ${_OPENGL_LIB_PATH}
+  )
+
+  unset(_OPENGL_INCLUDE_PATH)
+  unset(_OPENGL_LIB_PATH)
+
+  find_library(OPENGL_glu_LIBRARY
+    NAMES GLU MesaGLU
+    PATHS ${OPENGL_gl_LIBRARY}
+          /opt/graphics/OpenGL/lib
+          /usr/openwin/lib
+          /usr/shlib /usr/X11R6/lib
+  )
+
+endif ()
+
+if(OPENGL_gl_LIBRARY)
+
+    if(OPENGL_xmesa_INCLUDE_DIR)
+      set( OPENGL_XMESA_FOUND "YES" )
+    else()
+      set( OPENGL_XMESA_FOUND "NO" )
+    endif()
+
+    set( OPENGL_LIBRARIES  ${OPENGL_gl_LIBRARY} ${OPENGL_LIBRARIES})
+    if(OPENGL_glu_LIBRARY)
+      set( OPENGL_GLU_FOUND "YES" )
+      if(NOT "${OPENGL_glu_LIBRARY}" STREQUAL "${OPENGL_gl_LIBRARY}")
+        set( OPENGL_LIBRARIES ${OPENGL_glu_LIBRARY} ${OPENGL_LIBRARIES} )
+      endif()
+    else()
+      set( OPENGL_GLU_FOUND "NO" )
+    endif()
+
+    # This deprecated setting is for backward compatibility with CMake1.4
+    set (OPENGL_LIBRARY ${OPENGL_LIBRARIES})
+
+endif()
+
+# This deprecated setting is for backward compatibility with CMake1.4
+set(OPENGL_INCLUDE_PATH ${OPENGL_INCLUDE_DIR})
+
+if(BUILD_ENGINE_JS)
+    # The implementation is based on the standard FindOpenGL.cmake provided
+    # with CMake, but customized for targeting Emscripten only.
+
+    # These libraries are provided with Emscripten
+    SET(OPENGL_FOUND TRUE)
+    SET(OPENGL_GLU_FOUND TRUE)
+
+    # Doesn't look like this one is part of Emscripten
+    SET(OPENGL_XMESA_FOUND FALSE)
+
+    # This is the path where <GL/gl.h> is found
+    SET(OPENGL_INCLUDE_DIR "${EMSCRIPTEN_ROOT_PATH}/system/include")
+
+    # No library to link against for OpenGL, since Emscripten picks it up
+    # automatically from library_gl.js, but need to report something, or
+    # CMake thinks we failed in the search.
+    SET(OPENGL_LIBRARIES "opengl_emscripten_internal")
+    SET(OPENGL_gl_LIBRARY "gl_emscripten_internal")
+    SET(OPENGL_glu_LIBRARY "glu_emscripten_internal")
+
+    mark_as_advanced(
+      OPENGL_INCLUDE_DIR
+      OPENGL_glu_LIBRARY
+      OPENGL_gl_LIBRARY
+    )
+endif()
+
+# handle the QUIETLY and REQUIRED arguments and set OPENGL_FOUND to TRUE if
+# all listed variables are TRUE
+INCLUDE(FindPackageHandleStandardArgs)
+
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenGL REQUIRED_VARS ${_OpenGL_REQUIRED_VARS})
+unset(_OpenGL_REQUIRED_VARS)
+
+mark_as_advanced(
+  OPENGL_INCLUDE_DIR
+  OPENGL_xmesa_INCLUDE_DIR
+  OPENGL_glu_LIBRARY
+  OPENGL_gl_LIBRARY
+)
--- a/cmake_modules/FindSDL2.cmake	Tue Mar 29 22:36:59 2016 +0300
+++ b/cmake_modules/FindSDL2.cmake	Mon Apr 25 22:10:06 2016 +0300
@@ -158,6 +158,11 @@
     SET(SDL2_LIBRARY_TEMP "${SDL2_LIBRARY_TEMP}" CACHE INTERNAL "")
 ENDIF(SDL2_LIBRARY_TEMP)
 
+if(BUILD_ENGINE_JS)
+    set(SDL2_LIBRARY "sdl2_emscripten_internal" CACHE STRING "emscripten override" FORCE)
+    set(SDL2_INCLUDE_DIR "${CMAKE_SYSTEM_INCLUDE_PATH}/SDL" CACHE STRING "emscripten override" FORCE)
+endif()
+
 INCLUDE(FindPackageHandleStandardArgs)
 
 FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2 REQUIRED_VARS SDL2_LIBRARY SDL2_INCLUDE_DIR)
--- a/cmake_modules/FindSDL2_image.cmake	Tue Mar 29 22:36:59 2016 +0300
+++ b/cmake_modules/FindSDL2_image.cmake	Mon Apr 25 22:10:06 2016 +0300
@@ -74,6 +74,12 @@
 set(SDL2_IMAGE_LIBRARIES ${SDL2_IMAGE_LIBRARY})
 set(SDL2_IMAGE_INCLUDE_DIRS ${SDL2_IMAGE_INCLUDE_DIR})
 
+if(BUILD_ENGINE_JS)
+    set(SDL2_IMAGE_LIBRARY "sdl2_image_emscripten_internal")
+    set(SDL2_IMAGE_LIBRARIES "sdl2_image_emscripten_internal")
+    set(SDL2_IMAGE_INCLUDE_DIRS "${CMAKE_SYSTEM_INCLUDE_PATH}/SDL")
+endif()
+
 include(FindPackageHandleStandardArgs)
 
 FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2_image
--- a/cmake_modules/FindSDL2_mixer.cmake	Tue Mar 29 22:36:59 2016 +0300
+++ b/cmake_modules/FindSDL2_mixer.cmake	Mon Apr 25 22:10:06 2016 +0300
@@ -74,6 +74,12 @@
 set(SDL2_MIXER_LIBRARIES ${SDL2_MIXER_LIBRARY})
 set(SDL2_MIXER_INCLUDE_DIRS ${SDL2_MIXER_INCLUDE_DIR})
 
+if(BUILD_ENGINE_JS)
+    set(SDL2_MIXER_LIBRARY "sdl2_mixer_emscripten_internal")
+    set(SDL2_MIXER_LIBRARIES "sdl2_mixer_emscripten_internal")
+    set(SDL2_MIXER_INCLUDE_DIRS "${CMAKE_SYSTEM_INCLUDE_PATH}/SDL")
+endif()
+
 include(FindPackageHandleStandardArgs)
 
 FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2_mixer
--- a/cmake_modules/FindSDL2_net.cmake	Tue Mar 29 22:36:59 2016 +0300
+++ b/cmake_modules/FindSDL2_net.cmake	Mon Apr 25 22:10:06 2016 +0300
@@ -74,6 +74,12 @@
 set(SDL2_NET_LIBRARIES ${SDL2_NET_LIBRARY})
 set(SDL2_NET_INCLUDE_DIRS ${SDL2_NET_INCLUDE_DIR})
 
+if(BUILD_ENGINE_JS)
+    set(SDL2_NET_LIBRARY "sdl2_net_emscripten_internal")
+    set(SDL2_NET_LIBRARIES "sdl2_net_emscripten_internal")
+    set(SDL2_NET_INCLUDE_DIRS "${CMAKE_SYSTEM_INCLUDE_PATH}/SDL")
+endif()
+
 include(FindPackageHandleStandardArgs)
 
 FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2_net
--- a/cmake_modules/FindSDL2_ttf.cmake	Tue Mar 29 22:36:59 2016 +0300
+++ b/cmake_modules/FindSDL2_ttf.cmake	Mon Apr 25 22:10:06 2016 +0300
@@ -74,6 +74,12 @@
 set(SDL2_TTF_LIBRARIES ${SDL2_TTF_LIBRARY})
 set(SDL2_TTF_INCLUDE_DIRS ${SDL2_TTF_INCLUDE_DIR})
 
+if(BUILD_ENGINE_JS)
+    set(SDL2_TTF_LIBRARY "sdl2_ttf_emscripten_internal")
+    set(SDL2_TTF_LIBRARIES "sdl2_ttf_emscripten_internal")
+    set(SDL2_TTF_INCLUDE_DIRS "${CMAKE_SYSTEM_INCLUDE_PATH}/SDL")
+endif()
+
 include(FindPackageHandleStandardArgs)
 
 FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2_ttf
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cmake_modules/Platform/Emscripten.cmake	Mon Apr 25 22:10:06 2016 +0300
@@ -0,0 +1,275 @@
+# This file is a 'toolchain description file' for CMake.
+# It teaches CMake about the Emscripten compiler, so that CMake can generate makefiles
+# from CMakeLists.txt that invoke emcc.
+
+# To use this toolchain file with CMake, invoke CMake with the following command line parameters
+# cmake -DCMAKE_TOOLCHAIN_FILE=<EmscriptenRoot>/cmake/Modules/Platform/Emscripten.cmake
+#       -DCMAKE_BUILD_TYPE=<Debug|RelWithDebInfo|Release|MinSizeRel>
+#       -G "Unix Makefiles" (Linux and OSX)
+#       -G "MinGW Makefiles" (Windows)
+#       <path/to/CMakeLists.txt> # Note, pass in here ONLY the path to the file, not the filename 'CMakeLists.txt' itself.
+
+# After that, build the generated Makefile with the command 'make'. On Windows, you may download and use 'mingw32-make' instead.
+
+# The following variable describes the target OS we are building to.
+set(CMAKE_SYSTEM_NAME Emscripten)
+set(CMAKE_SYSTEM_VERSION 1)
+
+set(CMAKE_CROSSCOMPILING TRUE)
+
+# Advertise Emscripten as a 32-bit platform (as opposed to CMAKE_SYSTEM_PROCESSOR=x86_64 for 64-bit platform),
+# since some projects (e.g. OpenCV) use this to detect bitness.
+set(CMAKE_SYSTEM_PROCESSOR x86)
+
+# Tell CMake how it should instruct the compiler to generate multiple versions of an outputted .so library: e.g. "libfoo.so, libfoo.so.1, libfoo.so.1.4" etc.
+# This feature is activated if a shared library project has the property SOVERSION defined.
+set(CMAKE_SHARED_LIBRARY_SONAME_C_FLAG "-Wl,-soname,")
+
+# In CMake, CMAKE_HOST_WIN32 is set when we are cross-compiling from Win32 to Emscripten: http://www.cmake.org/cmake/help/v2.8.12/cmake.html#variable:CMAKE_HOST_WIN32
+# The variable WIN32 is set only when the target arch that will run the code will be WIN32, so unset WIN32 when cross-compiling.
+set(WIN32)
+
+# The same logic as above applies for APPLE and CMAKE_HOST_APPLE, so unset APPLE.
+set(APPLE)
+
+# And for UNIX and CMAKE_HOST_UNIX. However, Emscripten is often able to mimic being a Linux/Unix system, in which case a lot of existing CMakeLists.txt files can be configured for Emscripten while assuming UNIX build, so this is left enabled.
+set(UNIX 1)
+
+# Do a no-op access on the CMAKE_TOOLCHAIN_FILE variable so that CMake will not issue a warning on it being unused.
+if(CMAKE_TOOLCHAIN_FILE)
+endif()
+
+# In order for check_function_exists() detection to work, we must signal it to pass an additional flag, which causes the compilation
+# to abort if linking results in any undefined symbols. The CMake detection mechanism depends on the undefined symbol error to be raised.
+set(CMAKE_REQUIRED_FLAGS "-s ERROR_ON_UNDEFINED_SYMBOLS=1")
+
+# Locate where the Emscripten compiler resides in relative to this toolchain file.
+if("${EMSCRIPTEN_ROOT_PATH}" STREQUAL "")
+    get_filename_component(GUESS_EMSCRIPTEN_ROOT_PATH "${CMAKE_CURRENT_LIST_DIR}/../../../" ABSOLUTE)
+    if(EXISTS "${GUESS_EMSCRIPTEN_ROOT_PATH}/emranlib")
+        set(EMSCRIPTEN_ROOT_PATH "${GUESS_EMSCRIPTEN_ROOT_PATH}")
+    endif()
+endif()
+
+# If not found by above search, locate using the EMSCRIPTEN environment variable.
+if("${EMSCRIPTEN_ROOT_PATH}" STREQUAL "")
+    set(EMSCRIPTEN_ROOT_PATH "$ENV{EMSCRIPTEN}")
+endif()
+
+# Abort if not found.
+if("${EMSCRIPTEN_ROOT_PATH}" STREQUAL "")
+    message(FATAL_ERROR "Could not locate the Emscripten compiler toolchain directory! Either set the EMSCRIPTEN environment variable, or pass -DEMSCRIPTEN_ROOT_PATH=xxx to CMake to explicitly specify the location of the compiler! This usually matches EMSCRIPTEN_ROOT from your ~/.emscripten file.")
+endif()
+
+# Normalize, convert Windows backslashes to forward slashes or CMake will crash.
+get_filename_component(EMSCRIPTEN_ROOT_PATH "${EMSCRIPTEN_ROOT_PATH}" ABSOLUTE)
+
+if(NOT CMAKE_MODULE_PATH)
+    set(CMAKE_MODULE_PATH "")
+endif()
+set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${EMSCRIPTEN_ROOT_PATH}/cmake/Modules")
+
+set(CMAKE_FIND_ROOT_PATH "${EMSCRIPTEN_ROOT_PATH}/system")
+
+if(CMAKE_HOST_WIN32)
+    set(EMCC_SUFFIX ".bat")
+else()
+    set(EMCC_SUFFIX "")
+endif()
+
+# Specify the compilers to use for C and C++
+if("${CMAKE_C_COMPILER}" STREQUAL "")
+    set(CMAKE_C_COMPILER "${EMSCRIPTEN_ROOT_PATH}/emcc${EMCC_SUFFIX}")
+endif()
+if("${CMAKE_CXX_COMPILER}" STREQUAL "")
+    set(CMAKE_CXX_COMPILER "${EMSCRIPTEN_ROOT_PATH}/em++${EMCC_SUFFIX}")
+endif()
+
+if("${CMAKE_AR}" STREQUAL "")
+    set(CMAKE_AR "${EMSCRIPTEN_ROOT_PATH}/emar${EMCC_SUFFIX}" CACHE FILEPATH "Emscripten ar")
+endif()
+
+if("${CMAKE_RANLIB}" STREQUAL "")
+    set(CMAKE_RANLIB "${EMSCRIPTEN_ROOT_PATH}/emranlib${EMCC_SUFFIX}" CACHE FILEPATH "Emscripten ranlib")
+endif()
+
+# Don't do compiler autodetection, since we are cross-compiling.
+include(CMakeForceCompiler)
+CMAKE_FORCE_C_COMPILER("${CMAKE_C_COMPILER}" Clang)
+CMAKE_FORCE_CXX_COMPILER("${CMAKE_CXX_COMPILER}" Clang)
+
+# To find programs to execute during CMake run time with find_program(), e.g. 'git' or so, we allow looking
+# into system paths.
+set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+
+# Since Emscripten is a cross-compiler, we should never look at the system-provided directories like /usr/include and so on.
+# Therefore only CMAKE_FIND_ROOT_PATH should be used as a find directory. See http://www.cmake.org/cmake/help/v3.0/variable/CMAKE_FIND_ROOT_PATH_MODE_INCLUDE.html
+set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
+
+set(CMAKE_SYSTEM_INCLUDE_PATH "${EMSCRIPTEN_ROOT_PATH}/system/include")
+
+# We would prefer to specify a standard set of Clang+Emscripten-friendly common convention for suffix files, especially for CMake executable files,
+# but if these are adjusted, ${CMAKE_ROOT}/Modules/CheckIncludeFile.cmake will fail, since it depends on being able to compile output files with predefined names.
+#SET(CMAKE_LINK_LIBRARY_SUFFIX "")
+#SET(CMAKE_STATIC_LIBRARY_PREFIX "")
+#SET(CMAKE_STATIC_LIBRARY_SUFFIX ".bc")
+#SET(CMAKE_SHARED_LIBRARY_PREFIX "")
+#SET(CMAKE_SHARED_LIBRARY_SUFFIX ".bc")
+SET(CMAKE_EXECUTABLE_SUFFIX ".js")
+#SET(CMAKE_FIND_LIBRARY_PREFIXES "")
+#SET(CMAKE_FIND_LIBRARY_SUFFIXES ".bc")
+
+SET(CMAKE_C_USE_RESPONSE_FILE_FOR_LIBRARIES 1)
+SET(CMAKE_CXX_USE_RESPONSE_FILE_FOR_LIBRARIES 1)
+SET(CMAKE_C_USE_RESPONSE_FILE_FOR_OBJECTS 1)
+SET(CMAKE_CXX_USE_RESPONSE_FILE_FOR_OBJECTS 1)
+SET(CMAKE_C_USE_RESPONSE_FILE_FOR_INCLUDES 1)
+SET(CMAKE_CXX_USE_RESPONSE_FILE_FOR_INCLUDES 1)
+
+set(CMAKE_C_RESPONSE_FILE_LINK_FLAG "@")
+set(CMAKE_CXX_RESPONSE_FILE_LINK_FLAG "@")
+
+# Specify the program to use when building static libraries. Force Emscripten-related command line options to clang.
+set(CMAKE_C_CREATE_STATIC_LIBRARY "<CMAKE_AR> rc <TARGET> <LINK_FLAGS> <OBJECTS>")
+set(CMAKE_CXX_CREATE_STATIC_LIBRARY "<CMAKE_AR> rc <TARGET> <LINK_FLAGS> <OBJECTS>")
+
+# Set a global EMSCRIPTEN variable that can be used in client CMakeLists.txt to detect when building using Emscripten.
+set(EMSCRIPTEN 1 CACHE BOOL "If true, we are targeting Emscripten output.")
+
+# Hardwire support for cmake-2.8/Modules/CMakeBackwardsCompatibilityC.cmake without having CMake to try complex things
+# to autodetect these:
+set(CMAKE_SKIP_COMPATIBILITY_TESTS 1)
+set(CMAKE_SIZEOF_CHAR 1)
+set(CMAKE_SIZEOF_UNSIGNED_SHORT 2)
+set(CMAKE_SIZEOF_SHORT 2)
+set(CMAKE_SIZEOF_INT 4)
+set(CMAKE_SIZEOF_UNSIGNED_LONG 4)
+set(CMAKE_SIZEOF_UNSIGNED_INT 4)
+set(CMAKE_SIZEOF_LONG 4)
+set(CMAKE_SIZEOF_VOID_P 4)
+set(CMAKE_SIZEOF_FLOAT 4)
+set(CMAKE_SIZEOF_DOUBLE 8)
+set(CMAKE_C_SIZEOF_DATA_PTR 4)
+set(CMAKE_CXX_SIZEOF_DATA_PTR 4)
+set(CMAKE_HAVE_LIMITS_H 1)
+set(CMAKE_HAVE_UNISTD_H 1)
+set(CMAKE_HAVE_PTHREAD_H 1)
+set(CMAKE_HAVE_SYS_PRCTL_H 1)
+set(CMAKE_WORDS_BIGENDIAN 0)
+set(CMAKE_DL_LIBS)
+
+set(CMAKE_C_FLAGS_RELEASE "-DNDEBUG -O2" CACHE STRING "Emscripten-overridden CMAKE_C_FLAGS_RELEASE")
+set(CMAKE_C_FLAGS_MINSIZEREL "-DNDEBUG -Os" CACHE STRING "Emscripten-overridden CMAKE_C_FLAGS_MINSIZEREL")
+set(CMAKE_C_FLAGS_RELWITHDEBINFO "-O2" CACHE STRING "Emscripten-overridden CMAKE_C_FLAGS_RELWITHDEBINFO")
+set(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG -O2" CACHE STRING "Emscripten-overridden CMAKE_CXX_FLAGS_RELEASE")
+set(CMAKE_CXX_FLAGS_MINSIZEREL "-DNDEBUG -Os" CACHE STRING "Emscripten-overridden CMAKE_CXX_FLAGS_MINSIZEREL")
+set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2" CACHE STRING "Emscripten-overridden CMAKE_CXX_FLAGS_RELWITHDEBINFO")
+
+set(CMAKE_EXE_LINKER_FLAGS_RELEASE "-O2" CACHE STRING "Emscripten-overridden CMAKE_EXE_LINKER_FLAGS_RELEASE")
+set(CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "-Os" CACHE STRING "Emscripten-overridden CMAKE_EXE_LINKER_FLAGS_MINSIZEREL")
+set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "-O2 -g" CACHE STRING "Emscripten-overridden CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO")
+set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "-O2" CACHE STRING "Emscripten-overridden CMAKE_SHARED_LINKER_FLAGS_RELEASE")
+set(CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL "-Os" CACHE STRING "Emscripten-overridden CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL")
+set(CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO "-O2 -g" CACHE STRING "Emscripten-overridden CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO")
+set(CMAKE_MODULE_LINKER_FLAGS_RELEASE "-O2" CACHE STRING "Emscripten-overridden CMAKE_MODULE_LINKER_FLAGS_RELEASE")
+set(CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL "-Os" CACHE STRING "Emscripten-overridden CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL")
+set(CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO "-O2 -g" CACHE STRING "Emscripten-overridden CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO")
+
+function(em_validate_asmjs_after_build target)
+    add_custom_command(TARGET ${target} POST_BUILD COMMAND ${CMAKE_COMMAND} -E echo Validating build output for asm.js... COMMAND "python" ARGS "${EMSCRIPTEN_ROOT_PATH}/tools/validate_asmjs.py" "$<TARGET_FILE:${target}>")
+endfunction()
+
+# A global counter to guarantee unique names for js library files.
+set(link_js_counter 1)
+
+# Internal function: Do not call from user CMakeLists.txt files. Use one of em_link_js_library()/em_link_pre_js()/em_link_post_js() instead.
+function(em_add_tracked_link_flag target flagname)
+
+    # User can input list of JS files either as a single list, or as variable arguments to this function, so iterate over varargs, and treat each
+    # item in varargs as a list itself, to support both syntax forms.
+    foreach(jsFileList ${ARGN})
+        foreach(jsfile ${jsFileList})
+            # If the user edits the JS file, we want to relink the emscripten application, but unfortunately it is not possible to make a link step
+            # depend directly on a source file. Instead, we must make a dummy no-op build target on that source file, and make the project depend on
+            # that target.
+
+            # Sanitate the source .js filename to a good symbol name to use as a dummy filename.
+            get_filename_component(jsname "${jsfile}" NAME)
+            string(REGEX REPLACE "[/:\\\\.\ ]" "_" dummy_js_target ${jsname})
+            set(dummy_lib_name ${target}_${link_js_counter}_${dummy_js_target})
+            set(dummy_c_name "${CMAKE_BINARY_DIR}/${dummy_js_target}_tracker.c")
+
+            # Create a new static library target that with a single dummy .c file.
+            add_library(${dummy_lib_name} STATIC ${dummy_c_name})
+            # Make the dummy .c file depend on the .js file we are linking, so that if the .js file is edited, the dummy .c file, and hence the static library will be rebuild (no-op). This causes the main application to be relinked, which is what we want.
+            # This approach was recommended by http://www.cmake.org/pipermail/cmake/2010-May/037206.html
+            add_custom_command(OUTPUT ${dummy_c_name} COMMAND ${CMAKE_COMMAND} -E touch ${dummy_c_name} DEPENDS ${jsfile})
+            target_link_libraries(${target} ${dummy_lib_name})
+
+            # Link the js-library to the target
+            # When a linked library starts with a "-" cmake will just add it to the linker command line as it is.
+            # The advantage of doing it this way is that the js-library will also be automatically linked to targets
+            # that depend on this target.
+            get_filename_component(js_file_absolute_path "${jsfile}" ABSOLUTE )
+            target_link_libraries(${target} "${flagname} \"${js_file_absolute_path}\"")
+
+            math(EXPR link_js_counter "${link_js_counter} + 1")
+        endforeach()
+    endforeach()
+endfunction()
+
+# This function links a (list of ) .js library file(s) to the given CMake project.
+# Example: em_link_js_library(my_executable "lib1.js" "lib2.js")
+#    will result in emcc passing --js-library lib1.js --js-library lib2.js to the emscripten linker, as well as
+#    tracking the modification timestamp between the linked .js files and the main project, so that editing the .js file
+#    will cause the target project to be relinked.
+function(em_link_js_library target)
+    em_add_tracked_link_flag(${target} "--js-library" ${ARGN})
+endfunction()
+
+# This function is identical to em_link_js_library(), except the .js files will be added with '--pre-js file.js' command line flag,
+# which is generally used to add some preamble .js code to a generated output file.
+function(em_link_pre_js target)
+    em_add_tracked_link_flag(${target} "--pre-js" ${ARGN})
+endfunction()
+
+# This function is identical to em_link_js_library(), except the .js files will be added with '--post-js file.js' command line flag,
+# which is generally used to add some postamble .js code to a generated output file.
+function(em_link_post_js target)
+    em_add_tracked_link_flag(${target} "--post-js" ${ARGN})
+endfunction()
+
+# Experimental support for targeting generation of Visual Studio project files (vs-tool) of Emscripten projects for Windows.
+# To use this, pass the combination -G "Visual Studio 10" -DCMAKE_TOOLCHAIN_FILE=Emscripten.cmake
+if ("${CMAKE_GENERATOR}" MATCHES "^Visual Studio.*")
+    # By default, CMake generates VS project files with a <GenerateManifest>true</GenerateManifest> directive.
+    # This causes VS to attempt to invoke rc.exe during the build, which will fail since app manifests are meaningless for Emscripten.
+    # To disable this, add the following linker flag. This flag will not go to emcc, since the Visual Studio CMake generator will swallow it.
+    set(EMSCRIPTEN_VS_LINKER_FLAGS "/MANIFEST:NO")
+    # CMake is hardcoded to write a ClCompile directive <ObjectFileName>$(IntDir)</ObjectFileName> in all VS project files it generates.
+    # This makes VS pass emcc a -o param that points to a directory instead of a file, which causes emcc autogenerate the output filename.
+    # CMake is hardcoded to assume all object files have the suffix .obj, so adjust the emcc-autogenerated default suffix name to match.
+    set(EMSCRIPTEN_VS_LINKER_FLAGS "${EMSCRIPTEN_VS_LINKER_FLAGS} --default-obj-ext .obj")
+    # Also hint CMake that it should not hardcode <ObjectFileName> generation. Requires a custom CMake build for this to work (ignored on others)
+    # See http://www.cmake.org/Bug/view.php?id=14673 and https://github.com/juj/CMake
+    set(CMAKE_VS_NO_DEFAULT_OBJECTFILENAME 1)
+
+    # Apply and cache Emscripten Visual Studio IDE-specific linker flags.
+    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${EMSCRIPTEN_VS_LINKER_FLAGS}" CACHE STRING "")
+    set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${EMSCRIPTEN_VS_LINKER_FLAGS}" CACHE STRING "")
+    set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${EMSCRIPTEN_VS_LINKER_FLAGS}" CACHE STRING "")
+endif()
+
+if(NOT DEFINED CMAKE_CROSSCOMPILING_EMULATOR)
+  find_program(NODE_JS_EXECUTABLE NAMES nodejs node)
+  if(NODE_JS_EXECUTABLE)
+    set(CMAKE_CROSSCOMPILING_EMULATOR "${NODE_JS_EXECUTABLE}" CACHE FILEPATH "Path to the emulator for the target system.")
+  endif()
+endif()
+
+# No-op on CMAKE_CROSSCOMPILING_EMULATOR so older versions of cmake do not
+# complain about unused CMake variable.
+if(CMAKE_CROSSCOMPILING_EMULATOR)
+endif()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cmake_modules/TestBigEndian.cmake	Mon Apr 25 22:10:06 2016 +0300
@@ -0,0 +1,30 @@
+#.rst:
+# TestBigEndian
+# -------------
+#
+# The TestBigEndian.cmake module that ships with CMake, which
+# checks if the system is big endian or little endian, assumes
+# that a binary is produced that will have bytes that correspond to the
+# endianness on the target system. Since emscripten produces Javascript, we
+# override the default behavior and always return little endian.
+#
+# ::
+#
+#   TEST_BIG_ENDIAN(VARIABLE)
+#   VARIABLE - variable to store the result to
+#=============================================================================
+# Copyright 2002-2009 Kitware, Inc.
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+#  License text for the above reference.)
+
+function(TEST_BIG_ENDIAN VARIABLE)
+  set(${VARIABLE} 0 CACHE INTERNAL "Result of TEST_BIG_ENDIAN" FORCE)
+endfunction()
--- a/hedgewars/ArgParsers.pas	Tue Mar 29 22:36:59 2016 +0300
+++ b/hedgewars/ArgParsers.pas	Mon Apr 25 22:10:06 2016 +0300
@@ -22,7 +22,6 @@
 interface
 
 procedure GetParams;
-{$IFDEF HWLIBRARY}
 {$IFNDEF BSD}
 var operatingsystem_parameter_argc: NativeInt; external;
     operatingsystem_parameter_argv: pointer; external;
@@ -32,16 +31,14 @@
     operatingsystem_parameter_argv: pointer; export;
     operatingsystem_parameter_envp: pointer; export;
 {$ENDIF}
+
 function ParamCount: LongInt;
 function ParamStr(i: LongInt): shortstring;
-{$ENDIF}
 
 implementation
 uses uVariables, uTypes, uUtils, uSound, uConsts;
 var isInternal: Boolean;
 
-{$IFDEF HWLIBRARY}
-
 type PCharArray = array[0..255] of PChar;
      PPCharArray = ^PCharArray;
 
@@ -55,8 +52,6 @@
     ParamStr:= StrPas(PPCharArray(operatingsystem_parameter_argv)^[i])
 end;
 
-{$ENDIF}
-
 procedure GciEasterEgg;
 begin
     WriteLn(stdout, '                                                                ');
--- a/hedgewars/CMakeLists.txt	Tue Mar 29 22:36:59 2016 +0300
+++ b/hedgewars/CMakeLists.txt	Mon Apr 25 22:10:06 2016 +0300
@@ -11,7 +11,7 @@
 
 
 enable_language(Pascal)
-add_flag_append(CMAKE_Pascal_FLAGS "-Cs2000000")
+add_flag_append(CMAKE_Pascal_FLAGS "-Cs2000000 -B")
 add_flag_append(CMAKE_Pascal_FLAGS_DEBUG "-gv")
 add_flag_append(CMAKE_Pascal_FLAGS_RELEASE "-Xs")
 if(UNIX)
--- a/hedgewars/SDLh.pas	Tue Mar 29 22:36:59 2016 +0300
+++ b/hedgewars/SDLh.pas	Mon Apr 25 22:10:06 2016 +0300
@@ -1049,7 +1049,6 @@
 
 function  SDL_GetError: PChar; cdecl; external SDLLibName;
 
-function  SDL_SetVideoMode(width, height, bpp: LongInt; flags: LongWord): PSDL_Surface; cdecl; external SDLLibName;
 function  SDL_CreateRGBSurface(flags: LongWord; Width, Height, Depth: LongInt; RMask, GMask, BMask, AMask: LongWord): PSDL_Surface; cdecl; external SDLLibName;
 function  SDL_CreateRGBSurfaceFrom(pixels: Pointer; width, height, depth, pitch: LongInt; RMask, GMask, BMask, AMask: LongWord): PSDL_Surface; cdecl; external SDLLibName;
 procedure SDL_FreeSurface(Surface: PSDL_Surface); cdecl; external SDLLibName;
--- a/hedgewars/options.inc	Tue Mar 29 22:36:59 2016 +0300
+++ b/hedgewars/options.inc	Mon Apr 25 22:10:06 2016 +0300
@@ -46,7 +46,9 @@
     {$DEFINE USE_TOUCH_INTERFACE}
 {$ELSE}
     {$DEFINE USE_AM_NUMCOLUMN}
-    {$DEFINE USE_S3D_RENDERING}
+    {$IFNDEF WEBGL}
+        {$DEFINE USE_S3D_RENDERING}
+    {$ENDIF}
 {$ENDIF}
 
 
--- a/hedgewars/pas2cRedo.pas	Tue Mar 29 22:36:59 2016 +0300
+++ b/hedgewars/pas2cRedo.pas	Mon Apr 25 22:10:06 2016 +0300
@@ -113,4 +113,5 @@
 
     Load_GL_VERSION_2_0 : procedure;
 
+    GetCurrentDir : function : PChar;
 
--- a/hedgewars/pas2cSystem.pas	Tue Mar 29 22:36:59 2016 +0300
+++ b/hedgewars/pas2cSystem.pas	Mon Apr 25 22:10:06 2016 +0300
@@ -130,10 +130,12 @@
     clear_filelist_hook, add_file_hook, idb_loader_hook, mainloop_hook, drawworld_hook : procedure;
     SDL_InitPatch : procedure;
 
-    PHYSFS_init, PHYSFS_deinit, PHYSFS_mount, PHYSFS_readBytes, PHYSFS_read : function : LongInt;
-    PHYSFSRWOPS_openRead, PHYSFSRWOPS_openWrite, PHYSFS_openRead : function : pointer;
-    PHYSFS_eof, PHYSFS_close, PHYSFS_exists : function : boolean;
+    PHYSFS_init, PHYSFS_deinit, PHYSFS_mount, PHYSFS_readBytes, PHYSFS_writeBytes, PHYSFS_read : function : LongInt;
+    PHYSFSRWOPS_openRead, PHYSFSRWOPS_openWrite, PHYSFS_openRead, PHYSFS_openWrite : function : pointer;
+    PHYSFS_eof, PHYSFS_close, PHYSFS_exists, PHYSFS_mkdir, PHYSFS_flush, PHYSFS_setWriteDir : function : boolean;
     PHYSFS_getLastError : function : PChar;
+    PHYSFS_enumerateFiles : function : PPChar;
+    PHYSFS_freeList : procedure;
 
     hedgewarsMountPackages, physfsReaderSetBuffer, hedgewarsMountPackage : procedure;
     physfsReader : function : pointer;
--- a/hedgewars/uChat.pas	Tue Mar 29 22:36:59 2016 +0300
+++ b/hedgewars/uChat.pas	Mon Apr 25 22:10:06 2016 +0300
@@ -1011,10 +1011,12 @@
 procedure TextInput(var event: TSDL_TextInputEvent);
 var s: shortstring;
     l: byte;
+    isl: integer;
 begin
     DeleteSelected();
 
     l:= 0;
+    // fetch all bytes of character/input
     while event.text[l] <> #0 do
         begin
         s[l + 1]:= event.text[l];
@@ -1023,9 +1025,30 @@
 
     if l > 0 then
         begin
-        if byte(InputStr.s[0]) + l > 240 then exit;
-        s[0]:= char(l);
-        InsertIntoInputStr(s);
+        isl:= Length(InputStr.s);
+        // check if user is typing a redundant closing hog-speech quotation mark
+        if (l = 1) and (isl >= 2) and (cursorPos = isl - 1) and charIsForHogSpeech(s[1])
+          and (s[1] = InputStr.s[1]) and (s[1] = InputStr.s[isl]) then
+            begin
+            MoveCursorToNextChar();
+            UpdateCursorCoords();
+            end
+        else
+            begin
+            // don't add input that doesn't fit
+            if isl + l > MaxInputStrLen then exit;
+            s[0]:= char(l);
+            InsertIntoInputStr(s);
+
+            // add closing hog speech quotation marks automagically
+            if (l = 1) and (Length(InputStr.s) = 1) and charIsForHogSpeech(s[1]) then
+                begin
+                InsertIntoInputStr(s);
+                MoveCursorToPreviousChar();
+                UpdateCursorCoords();
+                end;
+            end;
+
         end
 end;
 
--- a/hedgewars/uGearsHandlersMess.pas	Tue Mar 29 22:36:59 2016 +0300
+++ b/hedgewars/uGearsHandlersMess.pas	Mon Apr 25 22:10:06 2016 +0300
@@ -3413,7 +3413,7 @@
         Gear^.Timer := 0;
         inc(Gear^.Pos);
         if Gear^.Pos = 5 then
-            PlaySoundV(sndYoohoo, Gear^.Hedgehog^.Team^.voicepack)
+            PlaySound(sndYoohoo);
         end;
 
     if (Gear^.Pos = 14) and (RealTicks and $3 = 0) then
--- a/hedgewars/uInputHandler.pas	Tue Mar 29 22:36:59 2016 +0300
+++ b/hedgewars/uInputHandler.pas	Mon Apr 25 22:10:06 2016 +0300
@@ -318,7 +318,7 @@
     DefaultBinds[KeyNameToCode('j0a0d')]:= '+right';
     DefaultBinds[KeyNameToCode('j0a1u')]:= '+up';
     DefaultBinds[KeyNameToCode('j0a1d')]:= '+down';
-    for i:= 1 to 10 do DefaultBinds[KeyNameToCode('f'+IntToStr(i))]:= 'slot '+IntToStr(i);
+    for i:= 1 to 10 do DefaultBinds[KeyNameToCode('f'+IntToStr(i))]:= 'slot '+char(48+i);
     for i:= 1 to 5  do DefaultBinds[KeyNameToCode(IntToStr(i))]:= 'timer '+IntToStr(i);
 
     loadBinds('dbind', cPathz[ptData] + '/settings.ini');
--- a/hedgewars/uLand.pas	Tue Mar 29 22:36:59 2016 +0300
+++ b/hedgewars/uLand.pas	Mon Apr 25 22:10:06 2016 +0300
@@ -33,7 +33,7 @@
 uses uConsole, uStore, uRandom, uLandObjects, uIO, uLandTexture, SysUtils,
      uVariables, uUtils, uCommands, adler32, uDebug, uLandPainted, uTextures,
      uLandGenMaze, uPhysFSLayer, uScript, uLandGenPerlin,
-     uLandGenTemplateBased, uLandUtils;
+     uLandGenTemplateBased, uLandUtils, uRenderUtils;
 
 var digest: shortstring;
     maskOnly: boolean;
@@ -49,7 +49,7 @@
 
 procedure DrawBorderFromImage(Surface: PSDL_Surface);
 var tmpsurf: PSDL_Surface;
-    r, rr: TSDL_Rect;
+    //r, rr: TSDL_Rect;
     x, yd, yu: LongInt;
     targetMask: Word;
 begin
@@ -79,25 +79,9 @@
             while (yu < yd ) and ((Land[yu, x] and targetMask) =  0) do inc(yu);
 
             if (yd < LAND_HEIGHT - 1) and ((yd - yu) >= 16) then
-                begin
-                rr.x:= x;
-                rr.y:= yd - 15;
-                r.x:= x mod tmpsurf^.w;
-                r.y:= 16;
-                r.w:= 1;
-                r.h:= 16;
-                SDL_UpperBlit(tmpsurf, @r, Surface, @rr);
-                end;
+                copyToXYFromRect(tmpsurf, Surface, x mod tmpsurf^.w, 16, 1, 16, x, yd - 15);
             if (yu > 0) then
-                begin
-                rr.x:= x;
-                rr.y:= yu;
-                r.x:= x mod tmpsurf^.w;
-                r.y:= 0;
-                r.w:= 1;
-                r.h:= Min(16, yd - yu + 1);
-                SDL_UpperBlit(tmpsurf, @r, Surface, @rr);
-                end;
+                copyToXYFromRect(tmpsurf, Surface, x mod tmpsurf^.w, 0, 1, Min(16, yd - yu + 1), x, yu);
             yd:= yu - 1;
         until yd < 0;
     end;
@@ -194,7 +178,8 @@
         r.x:= 0;
         while r.x < LAND_WIDTH do
             begin
-            SDL_UpperBlit(tmpsurf, nil, Surface, @r);
+            copyToXY(tmpsurf, Surface, r.x, r.y);
+            //SDL_UpperBlit(tmpsurf, nil, Surface, @r);
             inc(r.x, tmpsurf^.w)
             end;
         inc(y, tmpsurf^.h);
--- a/hedgewars/uPhysFSLayer.pas	Tue Mar 29 22:36:59 2016 +0300
+++ b/hedgewars/uPhysFSLayer.pas	Mon Apr 25 22:10:06 2016 +0300
@@ -187,15 +187,12 @@
         pfsBlockRead:= r
 end;
 
-procedure pfsMount(path: ansistring; mountpoint: PChar);
+procedure pfsMount(path: PChar; mountpoint: PChar);
 begin
-    if PHYSFS_mount(PChar(path), mountpoint, false) then
-        //AddFileLog('[PhysFS] mount ' + shortstring(path) + ' at ' + shortstring(mountpoint) + ' : ok')
-    else
-        //AddFileLog('[PhysFS] mount ' + shortstring(path) + ' at ' + shortstring(mountpoint) + ' : FAILED ("' + shortstring(PHYSFS_getLastError()) + '")');
+    PHYSFS_mount(path, mountpoint, false)
 end;
 
-procedure pfsMountAtRoot(path: ansistring);
+procedure pfsMountAtRoot(path: PChar);
 begin
     pfsMount(path, PChar(_S'/'));
 end;
@@ -208,7 +205,7 @@
 {$ENDIF}
 begin
     //TODO: http://icculus.org/pipermail/physfs/2011-August/001006.html
-    cPhysfsId:= GetCurrentDir() + {$IFDEF DARWIN}{$IFNDEF IPHONEOS}'/Hedgewars.app/Contents/MacOS/' + {$ENDIF}{$ENDIF} ' hedgewars';
+    cPhysfsId:= shortstring(GetCurrentDir()) + {$IFDEF DARWIN}{$IFNDEF IPHONEOS}'/Hedgewars.app/Contents/MacOS/' + {$ENDIF}{$ENDIF} ' hedgewars';
 
     i:= PHYSFS_init(Str2PChar(cPhysfsId));
     //AddFileLog('[PhysFS] init: ' + inttostr(i));
@@ -219,7 +216,7 @@
         begin
             fp := cFontsPaths[i];
             if fp <> nil then
-                pfsMount(ansistring(fp), _P'/Fonts');
+                pfsMount(fp, _P'/Fonts');
         end;
 {$ENDIF}
 
@@ -227,14 +224,14 @@
     pfsMount(userPrefix, PChar('/Config'));
     pfsMakeDir('/Config/Data');
     pfsMakeDir('/Config/Logs');
-    pfsMountAtRoot(userPrefix + ansistring('/Data'));
+    pfsMountAtRoot(Str2PChar(shortstring(userPrefix) + '/Data'));
     PHYSFS_setWriteDir(userPrefix);
 
     hedgewarsMountPackages;
 
     if cTestLua then
         begin
-            pfsMountAtRoot(ansistring(ExtractFileDir(cScriptName)));
+            pfsMountAtRoot(Str2PChar(ExtractFileDir(cScriptName)));
             cScriptName := ExtractFileName(cScriptName);
         end;
 end;
--- a/hedgewars/uScript.pas	Tue Mar 29 22:36:59 2016 +0300
+++ b/hedgewars/uScript.pas	Mon Apr 25 22:10:06 2016 +0300
@@ -56,7 +56,6 @@
 procedure freeModule;
 
 implementation
-{$IFDEF USE_LUA_SCRIPT}
 
 uses LuaPas,
     uConsole,
@@ -104,6 +103,7 @@
     PointsBuffer: shortstring;
     prevCursorPoint: TPoint;  // why is tpoint still in sdlh...
 
+{$IFDEF USE_LUA_SCRIPT}
 procedure ScriptPrepareAmmoStore; forward;
 procedure ScriptApplyAmmoStore; forward;
 procedure ScriptSetAmmo(ammo : TAmmoType; count, probability, delay, reinforcement: Byte); forward;
@@ -338,7 +338,7 @@
         LuaToMapGenOrd:= i;
 end;
 
-// wrapped calls //
+// wrapped calls
 
 // functions called from Lua:
 // function(L : Plua_State) : LongInt; Cdecl;
@@ -490,7 +490,7 @@
             cs:= 0; // current slot
             fa:= 0; // first ammo item to check
 
-            // if something is selected, find it's successor
+            // if something is selected, find it is successor
             if curAmmoType <> amNothing then
                 begin
                 // get current slot index
@@ -499,7 +499,7 @@
                 while (fa < cMaxSlotAmmoIndex)
                     and (Ammo^[cs, fa].AmmoType <> CurAmmoType) do
                         inc(fa);
-                // increase once more because we won't successor
+                // increase once more because we will not successor
                 inc(fa);
                 end;
 
@@ -913,7 +913,7 @@
     lc_setvisualgearvalues:= 0
 end;
 
-// so. going to use this to get/set some of the more obscure gear values which weren't already exposed elsewhere
+// so. going to use this to get/set some of the more obscure gear values which were not already exposed elsewhere
 // can keep adding things in the future. isnoneornil makes it safe
 function lc_getgearvalues(L : Plua_State) : LongInt; Cdecl;
 var gear: PGear;
@@ -1226,8 +1226,8 @@
 begin
     if CheckLuaParamCount(L, 2, 'SetClanColor', 'clan, color') then
         begin
-	i:= lua_tointeger(L,1);
-	if i >= ClansCount then exit(0);
+        i:= lua_tointeger(L,1);
+        if i >= ClansCount then exit(0);
         clan := ClansArray[i];
         clan^.Color:= lua_tointeger(L, 2) shr 8;
 
@@ -1248,7 +1248,7 @@
             team^.NameTagTex:= RenderStringTex(ansistring(clan^.Teams[i]^.TeamName), clan^.Color, fnt16);
             end;
 
-	    FreeAndNilTexture(clan^.HealthTex);
+        FreeAndNilTexture(clan^.HealthTex);
         clan^.HealthTex:= makeHealthBarTexture(cTeamHealthWidth + 5, clan^.Teams[0]^.NameTagTex^.h, clan^.Color);
         end;
 
@@ -2287,16 +2287,16 @@
     if CheckAndFetchLuaParamMinCount(L, 4, call, params, n) then
         begin
         if not lua_isnoneornil(L, 5) then
-	        tint := lua_tointeger(L, 5)
+            tint := lua_tointeger(L, 5)
         else tint := $FFFFFFFF;
         if not lua_isnoneornil(L, 6) then
-	        behind := lua_toboolean(L, 6)
+            behind := lua_toboolean(L, 6)
         else behind := false;
         if not lua_isnoneornil(L, 7) then
-	        flipHoriz := lua_toboolean(L, 7)
+            flipHoriz := lua_toboolean(L, 7)
         else flipHoriz := false;
         if not lua_isnoneornil(L, 8) then
-	        flipVert := lua_toboolean(L, 8)
+            flipVert := lua_toboolean(L, 8)
         else flipVert := false;
         lf:= 0;
 
@@ -2334,16 +2334,16 @@
     if CheckAndFetchLuaParamMinCount(L, 4, call, params, n) then
         begin
         if not lua_isnoneornil(L, 5) then
-	        eraseOnLFMatch := lua_toboolean(L, 5)
+            eraseOnLFMatch := lua_toboolean(L, 5)
         else eraseOnLFMatch := false;
         if not lua_isnoneornil(L, 6) then
-	        onlyEraseLF := lua_toboolean(L, 6)
+            onlyEraseLF := lua_toboolean(L, 6)
         else onlyEraseLF := false;
         if not lua_isnoneornil(L, 7) then
-	        flipHoriz := lua_toboolean(L, 7)
+            flipHoriz := lua_toboolean(L, 7)
         else flipHoriz := false;
         if not lua_isnoneornil(L, 8) then
-	        flipVert := lua_toboolean(L, 8)
+            flipVert := lua_toboolean(L, 8)
         else flipVert := false;
         lf:= 0;
 
@@ -2869,7 +2869,7 @@
 ScriptSetInteger('WaterLine', cWaterLine);
 if isCursorVisible and (not bShowAmmoMenu) then
     begin
-    if (prevCursorPoint.X <> CursorPoint.X) or 
+    if (prevCursorPoint.X <> CursorPoint.X) or
        (prevCursorPoint.Y <> CursorPoint.Y) then
         begin
         ScriptSetInteger('CursorX', CursorPoint.X - WorldDx);
@@ -3028,13 +3028,13 @@
 
 procedure ScriptSetAmmoDelay(ammo : TAmmoType; delay: Byte);
 begin
-// change loadout string if ammo store hasn't been initialized yet
+// change loadout string if ammo store has not been initialized yet
 if (StoreCnt = 0) then
 begin
     if (delay <= 9) then
         ScriptAmmoDelay[ord(ammo)]:= inttostr(delay)[1];
 end
-// change "live" delay values
+// change 'live' delay values
 else if (CurrentTeam <> nil) then
         ammoz[ammo].SkipTurns:= CurrentTeam^.Clan^.TurnNumber + delay;
 end;
@@ -3452,6 +3452,22 @@
 begin
 end;
 
+procedure ScriptOnPreviewInit;
+begin
+end;
+
+procedure ScriptSetInteger(name : shortstring; value : LongInt);
+begin
+end;
+
+procedure ScriptSetString(name : shortstring; value : shortstring);
+begin
+end;
+
+procedure LuaParseString(s : ShortString);
+begin
+end;
+
 procedure initModule;
 begin
 mapDims:= false;
--- a/hedgewars/uSound.pas	Tue Mar 29 22:36:59 2016 +0300
+++ b/hedgewars/uSound.pas	Mon Apr 25 22:10:06 2016 +0300
@@ -425,7 +425,7 @@
             s:= cPathz[Soundz[snd].Path] + '/' + Soundz[snd].FileName;
             WriteToConsole(msgLoading + s + ' ');
             defVoicepack^.chunks[snd]:= Mix_LoadWAV_RW(rwopsOpenRead(s), 1);
-            if not SDLCheck(defVoicepack^.chunks[snd] <> nil, 'Mix_LoadWAV_RW', true) then exit;
+            if SDLCheck(defVoicepack^.chunks[snd] <> nil, 'Mix_LoadWAV_RW', true) then exit;
             WriteLnToConsole(msgOK);
             end;
         lastChan[snd]:= Mix_PlayChannelTimed(-1, defVoicepack^.chunks[snd], 0, -1)
--- a/misc/liblua/CMakeLists.txt	Tue Mar 29 22:36:59 2016 +0300
+++ b/misc/liblua/CMakeLists.txt	Mon Apr 25 22:10:06 2016 +0300
@@ -23,4 +23,8 @@
 set(LUA_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR} CACHE STRING "Lua include dir" FORCE)
 set(LUA_LIBRARY ${lua_fullpath} CACHE STRING "Lua library" FORCE)
 
+#emscripten does not expose headers but has an internal binary copy
+if(BUILD_ENGINE_JS)
+    set(LUA_LIBRARY "lua_emscripten_internal" CACHE STRING "Lua library" FORCE)
+endif()
 
--- a/misc/libphyslayer/CMakeLists.txt	Tue Mar 29 22:36:59 2016 +0300
+++ b/misc/libphyslayer/CMakeLists.txt	Mon Apr 25 22:10:06 2016 +0300
@@ -26,3 +26,7 @@
 set(PHYSLAYER_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR} CACHE STRING "Physlayer include dir" FORCE)
 set(PHYSLAYER_LIBRARY ${physlayer_fullpath} CACHE STRING "Physlayer library" FORCE)
 
+if(BUILD_ENGINE_JS)
+    set_target_properties(physlayer PROPERTIES SUFFIX ".bc")
+endif()
+
--- a/misc/libphyslayer/physfsrwops.c	Tue Mar 29 22:36:59 2016 +0300
+++ b/misc/libphyslayer/physfsrwops.c	Mon Apr 25 22:10:06 2016 +0300
@@ -180,7 +180,7 @@
         retval = SDL_AllocRW();
         if (retval != NULL)
         {
-#if TARGET_SDL13
+#if TARGET_SDL13 && !defined(EMSCRIPTEN)
             retval->size  = physfsrwops_size;
 #endif
             retval->seek  = physfsrwops_seek;
--- a/project_files/hwc/CMakeLists.txt	Tue Mar 29 22:36:59 2016 +0300
+++ b/project_files/hwc/CMakeLists.txt	Mon Apr 25 22:10:06 2016 +0300
@@ -57,15 +57,20 @@
 list(APPEND engine_sources_pas ${CMAKE_SOURCE_DIR}/hedgewars/pas2cRedo.pas)
 
 
+set(pas2c_args -n hwengine
+               -i ${CMAKE_SOURCE_DIR}/hedgewars
+               -o ${CMAKE_CURRENT_BINARY_DIR}
+               -a ${CMAKE_CURRENT_BINARY_DIR}
+               -d ENDIAN_LITTLE
+               -d DEBUGFILE)
+if(BUILD_ENGINE_JS)
+    set(pas2c_args ${pas2c_args} -d WEBGL -d HWLIBRARY)
+endif()
+
 #invoke pas2c on main module, it will call all the others
 add_custom_command(OUTPUT ${engine_sources}
                    COMMAND "${EXECUTABLE_OUTPUT_PATH}/pas2c${CMAKE_EXECUTABLE_SUFFIX}"
-                   ARGS -n "hwengine"
-                        -i "${CMAKE_SOURCE_DIR}/hedgewars"
-                        -o "${CMAKE_CURRENT_BINARY_DIR}"
-                        -a "${CMAKE_CURRENT_BINARY_DIR}"
-                        -d "ENDIAN_LITTLE"
-                        -d "DEBUGFILE"
+                   ARGS ${pas2c_args}
                    DEPENDS pas2c                     #converter tool
                            ${engine_sources_pas}     #original pascal file
                   )
@@ -74,12 +79,20 @@
 add_custom_target(engine_c DEPENDS ${engine_sources})
 
 
+if(BUILD_ENGINE_JS)
+    add_flag_append(CMAKE_C_FLAGS "-s ABORTING_MALLOC=0")
+endif()
+
 #compile the c files
 add_definitions(-DPAS2C)
 add_definitions(-Werror=incompatible-pointer-types)
 
 add_executable(hwengine WIN32 ${engine_sources})
 
+if(BUILD_ENGINE_JS)
+    set_target_properties(hwengine PROPERTIES SUFFIX ".html")
+endif()
+
 target_link_libraries(hwengine  fpcrtl
                                 ${LUA_LIBRARY}
                                 ${OPENGL_LIBRARY}
--- a/project_files/hwc/rtl/CMakeLists.txt	Tue Mar 29 22:36:59 2016 +0300
+++ b/project_files/hwc/rtl/CMakeLists.txt	Mon Apr 25 22:10:06 2016 +0300
@@ -5,12 +5,3 @@
 
 add_library(fpcrtl STATIC ${fpcrtl_src})
 
-#if(WEBGL)
-#    set_target_properties(fpcrtl PROPERTIES PREFIX "em")
-#    set_target_properties(fpcrtl PROPERTIES SUFFIX ".bc")
-#endif(WEBGL)
-
-
-
-
-
--- a/project_files/hwc/rtl/fileio.c	Tue Mar 29 22:36:59 2016 +0300
+++ b/project_files/hwc/rtl/fileio.c	Mon Apr 25 22:10:06 2016 +0300
@@ -8,9 +8,11 @@
 #include <stdlib.h>
 #include <assert.h>
 #include <sys/stat.h>
+#include <unistd.h>
 
 io_result_t IOResult;
 int FileMode;
+char cwd[1024];
 
 static void init(File f) {
     f->fp = NULL;
@@ -219,6 +221,17 @@
     return false;
 }
 
+char * fpcrtl_getCurrentDir(void) {
+
+    IOResult = IO_NO_ERROR;
+
+    if (getcwd(cwd, sizeof(cwd)) != NULL)
+        return cwd;
+
+    IOResult = IO_ERROR_DUMMY;
+    return "";
+}
+
 void __attribute__((overloadable)) fpcrtl_flush(Text f) {
     fflush(f->fp);
 }
--- a/project_files/hwc/rtl/fileio.h	Tue Mar 29 22:36:59 2016 +0300
+++ b/project_files/hwc/rtl/fileio.h	Mon Apr 25 22:10:06 2016 +0300
@@ -75,4 +75,7 @@
 bool        fpcrtl_fileExists(string255 filename);
 #define     fpcrtl_FileExists                           fpcrtl_fileExists
 
+char *      fpcrtl_getCurrentDir(void);
+#define     fpcrtl_GetCurrentDir                        fpcrtl_getCurrentDir
+
 #endif /* FILEIO_H_ */
--- a/project_files/hwc/rtl/misc.c	Tue Mar 29 22:36:59 2016 +0300
+++ b/project_files/hwc/rtl/misc.c	Mon Apr 25 22:10:06 2016 +0300
@@ -78,8 +78,8 @@
 {
     if(s.len < MAX_ANSISTRING_LENGTH)
     {
+        ++s.len;
         s.s[s.len] = c;
-        ++s.len;
     }
 
     return s;
--- a/project_files/hwc/rtl/pmath.h	Tue Mar 29 22:36:59 2016 +0300
+++ b/project_files/hwc/rtl/pmath.h	Mon Apr 25 22:10:06 2016 +0300
@@ -21,4 +21,17 @@
 int         __attribute__((overloadable))   fpcrtl_abs(int x);
 int64_t     __attribute__((overloadable))   fpcrtl_abs(int64_t x);
 
+/* emscripten cannot find math.h through our cmake */
+#ifdef EMSCRIPTEN
+double      exp(double);
+double      log(double);
+double      sin(double);
+double      cos(double);
+double      fabs(double);
+double      ceil(double);
+double      sqrt(double);
+double      atan(double);
+double      atan2(double, double);
+#endif
+
 #endif /* PMATH_H_ */
--- a/project_files/hwc/rtl/system.c	Tue Mar 29 22:36:59 2016 +0300
+++ b/project_files/hwc/rtl/system.c	Mon Apr 25 22:10:06 2016 +0300
@@ -3,6 +3,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <wchar.h>
+#include "pmath.h"
 
 #ifndef M_PI
 // some math.h do not have M_PI macros
Binary file share/hedgewars/Data/Graphics/Flags/cm_cyborg.png has changed
Binary file share/hedgewars/Data/Graphics/Flags/cm_fcw.png has changed
Binary file share/hedgewars/Data/Graphics/Hats/tf_scount.png has changed
Binary file share/hedgewars/Data/Graphics/Hats/tf_scout.png has changed
--- a/share/hedgewars/Data/Locale/campaigns_en.txt	Tue Mar 29 22:36:59 2016 +0300
+++ b/share/hedgewars/Data/Locale/campaigns_en.txt	Mon Apr 25 22:10:06 2016 +0300
@@ -19,16 +19,16 @@
 A_Classic_Fairytale-epil.desc="Congratulations! Leaks a lot can finally leave in peace and get praised by his new friends and his tribe. Be proud for what you succeed! You can play again previous missions and see the other possible endings."
 
 A_Space_Adventure-cosmos.desc="Hogera, the planet of hogs is about to be hit by a gigantic meteorite. In this race for survival you have to lead PAotH's best pilot, Hog Solo, in a space trip around the neighbor planets to collect all the 4 pieces of the long lost anti gravity device!"
-A_Space_Adventure-moon01.desc="Hog Solo has landed on the moon to refuel his saucer but professor Hogevil has gone there first and set an ambush! Rescue the captured PAotH researchers and drive professor Hogevil away!"
-A_Space_Adventure-moon02.desc="Hog Solo visits an hermit, old PAotH veteran, who lives in moon in order to gather some intel about Pr. Hogevil. However, he has to beat the hermit, Soneek the Crazy Runner, in a chase game first!"
+A_Space_Adventure-moon01.desc="Hog Solo has landed on the moon to refuel his saucer but professor Hogevil has gone there first and set an ambush! Rescue the captured PAotH researchers and drive Professor Hogevil away!"
+A_Space_Adventure-moon02.desc="Hog Solo visits an hermit, old PAotH veteran, who lives on the moon in order to gather some intel about Prof. Hogevil. However, he has to beat the hermit, Soneek the Crazy Runner, in a chase game first!"
 A_Space_Adventure-ice01.desc="Welcome to the planet of ice. Here, it's so cold that most of Hog Solo's weapons won't work. You have to get the lost part from the bandit leader Thanta using the weapons that you'll find there!"
-A_Space_Adventure-ice02.desc="Hog Solo couldn't just visit the Ice Planet without visiting the Olympic stadium of saucer flying! In this mission you can prove your flying skills and claim your place between the best!"
+A_Space_Adventure-ice02.desc="Hog Solo couldn't just visit the Ice Planet without visiting the Olympic Stadium of Saucer Flying! In this mission you can prove your flying skills and claim your place among the best!"
 A_Space_Adventure-desert01.desc="You have landed to the planet of sand! Hog Solo has to find the missing part in the underground tunnels. Be careful as vicious smugglers await to attack and rob you!"
 A_Space_Adventure-desert02.desc="Hog Solo was searching for the part in this tunnel when it unexpectedly start getting flooded! Get to the surface as soon as possible and be careful not to trigger a mine."
 A_Space_Adventure-desert03.desc="Hog Solo has some time to fly his RC plane and have some fun. Fly the RC plane and hit all the targets!"
 A_Space_Adventure-fruit01.desc="In the fruit planet things aren't going so well. Hogs aren't collecting fruits but they are preparing for battle. You'll have to choose if you'll fight or if you'll flee."
-A_Space_Adventure-fruit02.desc="Hog Solo gets closer to the lost part in the Fruit Planet. Will Captain Lime help him acquire the part or not?"
-A_Space_Adventure-fruit03.desc="Hog Solo got lost and got ambushed by the Red Strawberries. Help him eliminate them and win some extra ammo for the Getting to the device mission."
-A_Space_Adventure-death01.desc="In the Death Planet, the most infertile planet around, Hog Solo is very close to get the last part of the device! However an unpleasant surprise awaits him..."
-A_Space_Adventure-death02.desc="Again Hog Solo has got himself in a difficult situation. Help him defeat the “5 deadly hogs“ in their own game!"
+A_Space_Adventure-fruit02.desc="Hog Solo gets closer to the lost part on the Fruit Planet. Will Captain Lime help him acquire the part or not?"
+A_Space_Adventure-fruit03.desc="Hog Solo got lost and got ambushed by the Red Strawberries. Help him eliminate them and win some extra ammo for the mission “Getting to the device”."
+A_Space_Adventure-death01.desc="On the Death Planet, the most infertile planet around, Hog Solo is very close to get the last part of the device! However, an unpleasant surprise awaits him ..."
+A_Space_Adventure-death02.desc="Again Hog Solo has got himself in a difficult situation. Help him defeat the “5 Deadly Hogs“ in their own game!"
 A_Space_Adventure-final.desc="Hog Solo has to detonate some explosives that have been placed on the meteorite. Help him complete his mission without getting hurt!"
--- a/share/hedgewars/Data/Locale/fr.lua	Tue Mar 29 22:36:59 2016 +0300
+++ b/share/hedgewars/Data/Locale/fr.lua	Mon Apr 25 22:10:06 2016 +0300
@@ -17,7 +17,7 @@
       ["A Classic Fairytale"] = "Un conte classique de fée",
       ["Actually, you aren't worthy of life! Take this..."] = "En fait, tu n'es pas digne de vivre ! Prends ça....",
       ["A cy-what?"] = "Un cy-quoi ?",
-      ["Advanced Repositioning Mode"] = "Mode de repositionnement avancé"
+      ["Advanced Repositioning Mode"] = "Mode de repositionnement avancé",
       ["Adventurous"] = "Aventurier",
       ["a frenetic Hedgewars mini-game"] = "un mini-jeu frénétique d'HedgeWars", -- Frenzy
       ["Africa"] = "Afrique", -- Continental_supplies
--- a/share/hedgewars/Data/Maps/ClimbHome/map.lua	Tue Mar 29 22:36:59 2016 +0300
+++ b/share/hedgewars/Data/Maps/ClimbHome/map.lua	Mon Apr 25 22:10:06 2016 +0300
@@ -19,6 +19,7 @@
 local teams = {}
 local teamScoreStats = {}
 local teamBests = {}
+local teamTimes = {}
 local MrMine -- in honour of sparkle's first arrival in the cabin
 local YouWon = false
 local YouLost = false
@@ -447,8 +448,15 @@
             end
 
             if (y > 286) or (y < 286 and MaxHeight > 286) then
+                if MaxHeight > 286 and y <= 286 then
+                    -- wow, reached top
+                    local teamName = GetHogTeamName(CurrentHedgehog)
+                    if teamTimes[teamName] == nil or teamTimes[teamName] > GameTime - startTime then 
+                        teamTimes[teamName] = GameTime - startTime 
+                    end
+                    MaxHeight = 286
+                end
                 if y < MaxHeight and y > 286 then MaxHeight = y end
-                if y < 286 then MaxHeight = 286 end
                 if MaxHeight < hTagHeight then
                     hTagHeight = MaxHeight
                     if hTag ~= nil then DeleteVisualGear(hTag) end
@@ -687,4 +695,7 @@
     for teamname, score in pairs(teamBests) do
         DeclareAchievement("height reached", teamname, "ClimbHome", -score)
     end
+    for teamname, score in pairs(teamTimes) do
+        DeclareAchievement("rope race", teamname, "ClimbHome", score)
+    end
 end
--- a/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/cosmos.lua	Tue Mar 29 22:36:59 2016 +0300
+++ b/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/cosmos.lua	Mon Apr 25 22:10:06 2016 +0300
@@ -61,7 +61,7 @@
 director.name = loc("H")
 director.x = 1350
 director.y = 1550
-doctor.name = loc("Dr.Cornelius")
+doctor.name = loc("Dr. Cornelius")
 doctor.x = 1300
 doctor.y = 1550
 guard1.name = loc("Bob")
@@ -362,10 +362,10 @@
 	if checkPointReached == 1 then
 		-- player climbed the moon with rope
 		FollowGear(doctor.gear)
-		AnimSay(doctor.gear, loc("One cannot simply walk in moon with rope!"), SAY_SHOUT, 4000)
+		AnimSay(doctor.gear, loc("One does not simply rope to the moon!"), SAY_SHOUT, 4000)
 		SendStat(siGameResult, loc("This is the wrong way!"))
-		SendStat(siCustomAchievement, loc("Collect the crate with the flying saucer"))
-		SendStat(siCustomAchievement, loc("Fly to the moon"))
+		SendStat(siCustomAchievement, loc("Collect the crate with the flying saucer!"))
+		SendStat(siCustomAchievement, loc("Fly to the moon."))
 		SendStat(siPlayerKills,'0',teamC.name)
 		EndGame()
 	else
@@ -380,7 +380,7 @@
 		SaveCampaignVar("Mission1", "2")
 		SaveCampaignVar("Mission2", "13")
 		SaveCampaignVar("Mission3", "1")
-		sendStats(loc("the moon"))
+		sendStats(loc("Hog Solo arrived at the moon!"))
 	end
 end
 
@@ -402,7 +402,7 @@
 			SaveCampaignVar("Mission2", "10")
 			SaveCampaignVar("Mission3", "1")
 		end
-		sendStats(loc("the Fruit Planet"))
+		sendStats(loc("Hog Solo arrived at the Fruit Planet!"))
 	end
 end
 
@@ -417,7 +417,7 @@
 		SaveCampaignVar("Mission2", "7")
 		SaveCampaignVar("Mission3", "12")
 		SaveCampaignVar("Mission4", "1")
-		sendStats(loc("the Desert Planet"))
+		sendStats(loc("Hog Solo arrived at the Desert Planet!"))
 	end
 end
 
@@ -431,7 +431,7 @@
 		SaveCampaignVar("Mission1", "5")
 		SaveCampaignVar("Mission2", "6")
 		SaveCampaignVar("Mission3", "1")
-		sendStats(loc("the Ice Planet"))
+		sendStats(loc("Hog Solo arrived at the Ice Planet!"))
 	end
 end
 
@@ -447,7 +447,7 @@
 		SaveCampaignVar("Mission1", "9")
 		SaveCampaignVar("Mission2", "11")
 		SaveCampaignVar("Mission3", "1")
-		sendStats(loc("the Planet of Death"))
+		sendStats(loc("Hog Solo arrived at the Planet of Death!"))
 	end
 end
 
@@ -463,7 +463,7 @@
 		SaveCampaignVar("UnlockedMissions", "2")
 		SaveCampaignVar("Mission1", "14")
 		SaveCampaignVar("Mission2", "1")
-		sendStats(loc("the meteorite"))
+		sendStats(loc("Hog Solo arrived at the meteorite!"))
 	end
 end
 
@@ -522,23 +522,23 @@
 	-- DIALOG 01 - Start
 	AddSkipFunction(dialog01, Skipanim, {dialog01})
 	table.insert(dialog01, {func = AnimWait, args = {doctor.gear, 3000}})
-	table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("Near secret base 17 of PAotH in the rural Hogland..."),  4000}})
-	table.insert(dialog01, {func = AnimSay, args = {director.gear, loc("So Hog Solo, here we are..."), SAY_SAY, 2000}})
-	table.insert(dialog01, {func = AnimSay, args = {director.gear, loc("Behind these trees on the east side there is secret base 17"), SAY_SAY, 4000}})
+	table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("Near Secret Base 17 of PAotH in the rural Hogland ..."),  4000}})
+	table.insert(dialog01, {func = AnimSay, args = {director.gear, loc("So Hog Solo, here we are ..."), SAY_SAY, 2000}})
+	table.insert(dialog01, {func = AnimSay, args = {director.gear, loc("Behind these trees on the east side there is Secret Base 17."), SAY_SAY, 4000}})
 	table.insert(dialog01, {func = AnimSay, args = {director.gear, loc("You have to continue alone from now on."), SAY_SAY, 3000}})
 	table.insert(dialog01, {func = AnimSay, args = {director.gear, loc("Be careful, the future of Hogera is in your hands!"), SAY_SAY, 7200}})
-	table.insert(dialog01, {func = AnimSay, args = {doctor.gear, loc("We'll use our communicators to contact you"), SAY_SAY, 2600}})
-	table.insert(dialog01, {func = AnimSay, args = {doctor.gear, loc("In am also entrusting you with some rope"), SAY_SAY, 5000}})
-	table.insert(dialog01, {func = AnimSay, args = {doctor.gear, loc("You may find it handy"), SAY_SAY, 2300}})
-	table.insert(dialog01, {func = AnimSay, args = {hero.gear, loc("Thank you Dr.Cornelius"), SAY_SAY, 1600}})
-	table.insert(dialog01, {func = AnimSay, args = {hero.gear, loc("I'll make good use of it"), SAY_SAY, 4500}})
-	table.insert(dialog01, {func = AnimSay, args = {director.gear, loc("It would be wiser to steal the space ship while PAotH guards are taking a brake!"), SAY_SAY, 7000}})
+	table.insert(dialog01, {func = AnimSay, args = {doctor.gear, loc("We'll use our communicators to contact you."), SAY_SAY, 2600}})
+	table.insert(dialog01, {func = AnimSay, args = {doctor.gear, loc("In am also entrusting you with some rope."), SAY_SAY, 5000}})
+	table.insert(dialog01, {func = AnimSay, args = {doctor.gear, loc("You may find it handy."), SAY_SAY, 2300}})
+	table.insert(dialog01, {func = AnimSay, args = {hero.gear, loc("Thank you, Dr. Cornelius."), SAY_SAY, 1600}})
+	table.insert(dialog01, {func = AnimSay, args = {hero.gear, loc("I'll make good use of it."), SAY_SAY, 4500}})
+	table.insert(dialog01, {func = AnimSay, args = {director.gear, loc("It would be wiser to steal the space ship while the PAotH guards are taking a brake!"), SAY_SAY, 7000}})
 	table.insert(dialog01, {func = AnimSay, args = {director.gear, loc("Remember! Many will seek the anti-gravity device! Now go, hurry up!"), SAY_SAY, 4000}})
 	table.insert(dialog01, {func = AnimSwitchHog, args = {hero.gear}})
 	-- DIALOG 02 - Hero got the saucer
 	AddSkipFunction(dialog02, Skipanim, {dialog02})
 	table.insert(dialog02, {func = AnimWait, args = {hero.gear, 500}})
-	table.insert(dialog02, {func = AnimCaption, args = {hero.gear, loc("CheckPoint reached!"),  4000}})
+	table.insert(dialog02, {func = AnimCaption, args = {hero.gear, loc("Checkpoint reached!"),  4000}})
 	table.insert(dialog02, {func = AnimSay, args = {hero.gear, loc("Got the saucer!"), SAY_SHOUT, 2000}})
 	table.insert(dialog02, {func = AnimSay, args = {director.gear, loc("Nice!"), SAY_SHOUT, 1000}})
 	table.insert(dialog02, {func = AnimSay, args = {director.gear, loc("Now use it and go to the moon PAotH station to get more fuel!"), SAY_SHOUT, 5000}})
@@ -547,7 +547,7 @@
 	AddSkipFunction(dialog03, Skipanim, {dialog03})
 	table.insert(dialog03, {func = AnimWait, args = {guard1.gear, 4000}})
 	table.insert(dialog03, {func = AnimCaption, args = {guard1.gear, loc("Prepare to flee!"),  4000}})
-	table.insert(dialog03, {func = AnimSay, args = {guard1.gear, loc("Hey").." "..guard2.name.."! "..loc("Look, someone is stealing the saucer!"), SAY_SHOUT, 4000}})
+	table.insert(dialog03, {func = AnimSay, args = {guard1.gear, string.format(loc("Hey, %s! Look, someone is stealing the saucer!"), guard2.name), SAY_SHOUT, 4000}})
 	table.insert(dialog03, {func = AnimSay, args = {guard2.gear, loc("I'll get him!"), SAY_SAY, 4000}})
 	table.insert(dialog03, {func = startCombat, args = {guard1.gear}})
 	-- DIALOG 04 - Hero out of sight
@@ -558,24 +558,24 @@
 	table.insert(dialog04, {func = AnimSwitchHog, args = {hero.gear}})
 	-- DIALOG 05 - Hero returned from moon without fuels
 	AddSkipFunction(dialog05, Skipanim, {dialog05})
-	table.insert(dialog05, {func = AnimSay, args = {hero.gear, loc("I guess I can't go far without fuels!"), SAY_THINK, 6000}})
-	table.insert(dialog05, {func = AnimSay, args = {hero.gear, loc("Go to go back"), SAY_THINK, 2000}})
+	table.insert(dialog05, {func = AnimSay, args = {hero.gear, loc("I guess I can't go far without fuel!"), SAY_THINK, 6000}})
+	table.insert(dialog05, {func = AnimSay, args = {hero.gear, loc("Got to go back."), SAY_THINK, 2000}})
 	table.insert(dialog05, {func = sendStatsOnRetry, args = {hero.gear}})
 	-- DIALOG 06 - Landing on wrong planet or on earth if not enough fuels
 	AddSkipFunction(dialog06, Skipanim, {dialog06})
 	table.insert(dialog06, {func = AnimCaption, args = {hero.gear, loc("You have to try again!"),  5000}})
-	table.insert(dialog06, {func = AnimSay, args = {hero.gear, loc("Hm... Now I ran out of fuel..."), SAY_THINK, 3000}})
+	table.insert(dialog06, {func = AnimSay, args = {hero.gear, loc("Hm ... Now I ran out of fuel."), SAY_THINK, 3000}})
 	table.insert(dialog06, {func = sendStatsOnRetry, args = {hero.gear}})
 	-- DIALOG 07 - Hero lands on Death Planet but isn't allowed yet to play this map
 	AddSkipFunction(dialog07, Skipanim, {dialog07})
 	table.insert(dialog07, {func = AnimCaption, args = {hero.gear, loc("This planet seems dangerous!"),  5000}})
-	table.insert(dialog07, {func = AnimSay, args = {hero.gear, loc("I am not ready for this planet yet. I should visit it when I have found all the other device parts"), SAY_THINK, 4000}})
+	table.insert(dialog07, {func = AnimSay, args = {hero.gear, loc("I am not ready for this planet yet. I should visit it when I have found all the other device parts."), SAY_THINK, 4000}})
 	-- DIALOG 08 - Hero wins death01
 	AddSkipFunction(dialog08, Skipanim, {dialog08})
-	table.insert(dialog08, {func = AnimCaption, args = {hero.gear, loc("Under the meteorite shadow..."),  4000}})
-	table.insert(dialog08, {func = AnimSay, args = {doctor.gear, loc("You did great Hog Solo! However we aren't out of danger yet!"), SAY_SHOUT, 4500}})
-	table.insert(dialog08, {func = AnimSay, args = {doctor.gear, loc("The meteorite has come too close and the anti-gravity device isn't powerful enough to stop it now"), SAY_SHOUT, 5000}})
-	table.insert(dialog08, {func = AnimSay, args = {doctor.gear, loc("We need it to get split into at least two parts"), SAY_SHOUT, 3000}})
+	table.insert(dialog08, {func = AnimCaption, args = {hero.gear, loc("Under the meteorites shadow ..."),  4000}})
+	table.insert(dialog08, {func = AnimSay, args = {doctor.gear, loc("You did great, Hog Solo! However, we aren't out of danger yet!"), SAY_SHOUT, 4500}})
+	table.insert(dialog08, {func = AnimSay, args = {doctor.gear, loc("The meteorite has come too close and the anti-gravity device isn't powerful enough to stop it now."), SAY_SHOUT, 5000}})
+	table.insert(dialog08, {func = AnimSay, args = {doctor.gear, loc("We need it to get split into at least two parts."), SAY_SHOUT, 3000}})
 	table.insert(dialog08, {func = AnimSay, args = {doctor.gear, loc("PAotH has sent explosives but unfortunately the trigger mechanism seems to be faulty!"), SAY_SHOUT, 5000}})
 	table.insert(dialog08, {func = AnimSay, args = {doctor.gear, loc("We need you to go there and detonate them yourself! Good luck!"), SAY_SHOUT, 500}})
 	table.insert(dialog08, {func = AnimWait, args = {doctor.gear, 3000}})
@@ -590,20 +590,20 @@
 	TurnTimeLeft = 0
 end
 
-function sendStats(planet)
-	SendStat(siGameResult, loc("Hog Solo arrived at "..planet))
-	SendStat(siCustomAchievement, loc("Return to the mission menu by pressing the \"Go back\" button"))
-	SendStat(siCustomAchievement, loc("You can choose another planet by replaying this mission"))
-	SendStat(siCustomAchievement, loc("Planets with completed main missions will be marked with a flower"))
+function sendStats(planetMsg)
+	SendStat(siGameResult, planetMsg)
+	SendStat(siCustomAchievement, loc("Return to the mission menu by pressing the \"Go back\" button."))
+	SendStat(siCustomAchievement, loc("You can choose another planet by replaying this mission."))
+	SendStat(siCustomAchievement, loc("Planets with completed main missions will be marked with a flower."))
 	SendStat(siPlayerKills,'1',teamC.name)
 	EndGame()
 end
 
 function sendStatsOnRetry()
 	SendStat(siGameResult, loc("You have to travel again"))
-	SendStat(siCustomAchievement, loc("Your first destination is the moon in order to get more fuel"))
-	SendStat(siCustomAchievement, loc("You have to complete the main mission on moon in order to travel to other planets"))
-	SendStat(siCustomAchievement, loc("You have to be careful and not die!"))
+	SendStat(siCustomAchievement, loc("Your first destination is the moon in order to get more fuel."))
+	SendStat(siCustomAchievement, loc("You have to complete the main mission on moon in order to travel to other planets."))
+	SendStat(siCustomAchievement, loc("You have to be careful and must not die!"))
 	SendStat(siPlayerKills,'0',teamC.name)
 	EndGame()
 end
--- a/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/death01.lua	Tue Mar 29 22:36:59 2016 +0300
+++ b/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/death01.lua	Mon Apr 25 22:10:06 2016 +0300
@@ -44,17 +44,17 @@
 local teamB = {}
 local teamC = {}
 -- hedgehogs values
-hero.name = "Hog Solo"
+hero.name = loc("Hog Solo")
 hero.x = 520
 hero.y = 845
 hero.dead = false
-paoth1.name = "H"
+paoth1.name = loc("H")
 paoth1.x = 3730
 paoth1.y = 1480
-paoth2.name = "Dr.Cornelius"
+paoth2.name = loc("Dr. Cornelius")
 paoth2.x = 3800
 paoth2.y = 1480
-professor.name = "Prof. Hogevil"
+professor.name = loc("Prof. Hogevil")
 professor.dead = false
 thug1.x = 1265
 thug1.y = 1400
@@ -123,7 +123,7 @@
 	HogTurnLeft(professor.bot, true)
 	professor.gear = professor.bot
 	for i=1,table.getn(thugs) do
-		thugs[i].gear = AddHog(loc("thug").." #"..i, 1, thugs[i].health, "war_desertgrenadier1")
+		thugs[i].gear = AddHog(string.format(loc("Thug #%d"), i), 1, thugs[i].health, "war_desertgrenadier1")
 		AnimSetGearPosition(thugs[i].gear, thugs[i].x, thugs[i].y)
 		HogTurnLeft(thugs[i].gear, not thugs[i].turnLeft)
 	end
@@ -265,7 +265,7 @@
 
 function heroDeath(gear)
 	SendStat(siGameResult, loc("Hog Solo lost, try again!"))
-	SendStat(siCustomAchievement, loc("To win the game you have to eliminate all your enemies"))
+	SendStat(siCustomAchievement, loc("To win the game you have to eliminate all your enemies."))
 	SendStat(siPlayerKills,'1',teamC.name)
 	SendStat(siPlayerKills,'0',teamA.name)
 	EndGame()
@@ -274,10 +274,10 @@
 function enemiesDeath(gear)
 	saveCompletedStatus(6)
 	SendStat(siGameResult, loc("Congratulations, you won!"))
-	SendStat(siCustomAchievement, loc("You have successfully eliminated Professor Hogevil"))
-	SendStat(siCustomAchievement, loc("You have rescued H and Dr.Cornelius"))
-	SendStat(siCustomAchievement, loc("You have acquired the last device part"))
-	SendStat(siCustomAchievement, loc("Now go and play the menu mission to complete the campaign"))
+	SendStat(siCustomAchievement, loc("You have successfully eliminated Professor Hogevil."))
+	SendStat(siCustomAchievement, loc("You have rescued H and Dr. Cornelius."))
+	SendStat(siCustomAchievement, loc("You have acquired the last device part."))
+	SendStat(siCustomAchievement, loc("Now go and play the menu mission to complete the campaign."))
 	SendStat(siPlayerKills,'1',teamA.name)
 	SendStat(siPlayerKills,'0',teamC.name)
 	EndGame()
@@ -296,11 +296,11 @@
 	-- DIALOG01, GAME START, INTRODUCTION
 	AddSkipFunction(dialog01, Skipanim, {dialog01})
 	table.insert(dialog01, {func = AnimWait, args = {hero.gear, 3000}})
-	table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("Somewhere in the uninhabitable Death Planet..."), 5000}})
+	table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("Somewhere on the uninhabitable Death Planet ..."), 5000}})
 	table.insert(dialog01, {func = AnimSay, args = {professor.human, loc("Welcome Hog Solo, surprised to see me?"), SAY_SAY, 4000}})
 	table.insert(dialog01, {func = AnimSay, args = {professor.human, loc("As you can see I have survived our last encounter and I had time to plot my master plan!"), SAY_SAY, 4000}})
 	table.insert(dialog01, {func = AnimSay, args = {professor.human, loc("I've thought that the best way to get the device is to let you collect most of the parts for me!"), SAY_SAY, 4000}})
-	table.insert(dialog01, {func = AnimSay, args = {professor.human, loc("So, now I got the last part and I have your friends captured..."), SAY_SAY, 4000}})
+	table.insert(dialog01, {func = AnimSay, args = {professor.human, loc("So, now I got the last part and I have your friends captured."), SAY_SAY, 4000}})
 	table.insert(dialog01, {func = AnimSay, args = {professor.human, loc("Will you give me the other parts?"), SAY_SAY, 4000}})
 	table.insert(dialog01, {func = AnimWait, args = {hero.gear, 3000}})
 	table.insert(dialog01, {func = AnimSay, args = {hero.gear, loc("I will never hand you the parts!"), SAY_SAY, 4000}})
--- a/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/death02.lua	Tue Mar 29 22:36:59 2016 +0300
+++ b/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/death02.lua	Mon Apr 25 22:10:06 2016 +0300
@@ -10,19 +10,19 @@
 ----------------- VARIABLES --------------------
 -- globals
 local missionName = loc("Killing the specialists")
-local challengeObjectives = loc("Use your available weapons in order to eliminate the enemies").."|"..
-	loc("Each time you play this missions enemy hogs will play in a random order").."|"..
-	loc("At the start of the game each enemy hog has only the weapon that he is named after").."|"..
-	loc("A random hedgehog will inherit the weapons of his deceased team-mates").."|"..
-	loc("If you kill a hedgehog with the respective weapon your health points will be set to 100").."|"..
-	loc("If you injure a hedgehog you'll get 35% of the damage dealt").."|"..
-	loc("Every time you kill an enemy hog your ammo will get reset").."|"..
-	loc("Rope won't get reset")
+local challengeObjectives = loc("Use your available weapons in order to eliminate the enemies.").."|"..
+	loc("Each time you play this missions enemy hogs will play in a random order.").."|"..
+	loc("At the start of the game each enemy hog has only the weapon that he is named after.").."|"..
+	loc("A random hedgehog will inherit the weapons of his deceased team-mates.").."|"..
+	loc("If you kill a hedgehog with the respective weapon your health points will be set to 100.").."|"..
+	loc("If you injure a hedgehog you'll get 35% of the damage dealt.").."|"..
+	loc("Every time you kill an enemy hog your ammo will get reset.").."|"..
+	loc("The rope won't get reset.")
 -- dialogs
 local dialog01 = {}
 -- mission objectives
 local goals = {
-	[dialog01] = {missionName, loc("Challenge Objectives"), challengeObjectives, 1, 4500},
+	[dialog01] = {missionName, loc("Challenge objectives"), challengeObjectives, 1, 4500},
 }
 -- hogs
 local hero = {
@@ -48,7 +48,7 @@
 	color = tonumber("38D61C",16) -- green
 }
 local teamB = {
-	name = loc("5 deadly hogs"),
+	name = loc("5 Deadly Hogs"),
 	color = tonumber("FF0000",16) -- red
 }
 
@@ -177,8 +177,8 @@
 
 function heroDeath(gear)
 	SendStat(siGameResult, loc("Hog Solo lost, try again!"))
-	SendStat(siCustomAchievement, loc("You have to eliminate all the enemies"))
-	SendStat(siCustomAchievement, loc("Read the Challenge Objectives from within the mission for more details"))
+	SendStat(siCustomAchievement, loc("You have to eliminate all the enemies."))
+	SendStat(siCustomAchievement, loc("Read the challenge objectives from within the mission for more details."))
 	SendStat(siPlayerKills,'1',teamB.name)
 	SendStat(siPlayerKills,'0',teamA.name)
 	EndGame()
@@ -187,8 +187,8 @@
 function heroWin(gear)
 	saveBonus(3, 4)
 	SendStat(siGameResult, loc("Congratulations, you won!"))
-	SendStat(siCustomAchievement, loc("You complete the mission in "..TotalRounds.." rounds"))
-	SendStat(siCustomAchievement, loc("The next 4 times you play the \"The last encounter\" mission you'll get 20 more hit points and a Laser Sight"))
+	SendStat(siCustomAchievement, string.format(loc("You completed the mission in %d rounds."), TotalRounds))
+	SendStat(siCustomAchievement, loc("The next 4 times you play the \"The last encounter\" mission you'll get 20 more hit points and a laser sight."))
 	SendStat(siPlayerKills,'1',teamA.name)
 	EndGame()
 end
@@ -206,8 +206,8 @@
 	-- DIALOG 01 - Start, game instructions
 	AddSkipFunction(dialog01, Skipanim, {dialog01})
 	table.insert(dialog01, {func = AnimWait, args = {hero.gear, 3000}})
-	table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("Somewhere in the Planet of Death..."), 3000}})
-	table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("...Hog Solo fights for his life"), 3000}})
+	table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("Somewhere on the Planet of Death ..."), 3000}})
+	table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("... Hog Solo fights for his life"), 3000}})
 	table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("Each time you play this missions enemy hogs will play in a random order"), 5000}})
 	table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("At the start of the game each enemy hog has only the weapon that he is named after"), 5000}})
 	table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("A random hedgehog will inherit the weapons of his deceased team-mates"), 5000}})
--- a/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/desert01.lua	Tue Mar 29 22:36:59 2016 +0300
+++ b/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/desert01.lua	Mon Apr 25 22:10:06 2016 +0300
@@ -412,7 +412,7 @@
 end
 
 function heroFleeFirstBattle(gear)
-	AnimSay(smuggler1.gear, loc("Run away you coward!"), SAY_SHOUT, 4000)
+	AnimSay(smuggler1.gear, loc("Run away, you coward!"), SAY_SHOUT, 4000)
 	TurnTimeLeft = 0
 	heroIsInBattle = false
 	ongoingBattle = 0
@@ -439,7 +439,7 @@
 function heroAtThirdBattle(gear)
 	heroIsInBattle = true
 	ongoingBattle = 3
-	AnimSay(smuggler3.gear, loc("Who's there?! I'll get you..."), SAY_SHOUT, 5000)
+	AnimSay(smuggler3.gear, loc("Who's there?! I'll get you!"), SAY_SHOUT, 5000)
 	AnimSwitchHog(smuggler3.gear)
 	TurnTimeLeft = 0
 end
@@ -479,22 +479,22 @@
 	-- DIALOG 01 - Start, getting info about the device
 	AddSkipFunction(dialog01, Skipanim, {dialog01})
 	table.insert(dialog01, {func = AnimWait, args = {hero.gear, 3000}})
-	table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("In the Planet of Sand, you have to double check your moves..."), 5000}})
-	table.insert(dialog01, {func = AnimSay, args = {ally.gear, loc("Finally you are here..."), SAY_SAY, 2000}})
+	table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("On the Planet of Sand, you have to double check your moves ..."), 5000}})
+	table.insert(dialog01, {func = AnimSay, args = {ally.gear, loc("Finally you are here!"), SAY_SAY, 2000}})
 	table.insert(dialog01, {func = AnimWait, args = {hero.gear, 2000}})
 	table.insert(dialog01, {func = AnimSay, args = {hero.gear, loc("Thank you for meeting me on such a short notice!"), SAY_SAY, 3000}})
 	table.insert(dialog01, {func = AnimWait, args = {ally.gear, 4000}})
 	table.insert(dialog01, {func = AnimSay, args = {ally.gear, loc("No problem, I would do anything for H!"), SAY_SAY, 4000}})
 	table.insert(dialog01, {func = AnimSay, args = {ally.gear, loc("Now listen carefully! Below us there are tunnels that have been created naturally over the years"), SAY_SAY, 4000}})
-	table.insert(dialog01, {func = AnimSay, args = {ally.gear, loc("I have heard that the local tribes say that many years ago some PAotH scientists were dumping their waste here"), SAY_SAY, 5000}})
-	table.insert(dialog01, {func = AnimSay, args = {ally.gear, loc("H confirmed that there isn't such a PAotH activity logged"), SAY_SAY, 4000}})
-	table.insert(dialog01, {func = AnimSay, args = {ally.gear, loc("So, I believe that it's a good place to start"), SAY_SAY, 3000}})
-	table.insert(dialog01, {func = AnimSay, args = {ally.gear, loc("Beware though! Many smugglers come often to explore these tunnels and scavenge whatever valuable items they can find"), SAY_SAY, 5000}})
+	table.insert(dialog01, {func = AnimSay, args = {ally.gear, loc("I have heard that the local tribes say that many years ago some PAotH scientists were dumping their waste here."), SAY_SAY, 5000}})
+	table.insert(dialog01, {func = AnimSay, args = {ally.gear, loc("H confirmed that there isn't such a PAotH activity logged."), SAY_SAY, 4000}})
+	table.insert(dialog01, {func = AnimSay, args = {ally.gear, loc("So, I believe that it's a good place to start."), SAY_SAY, 3000}})
+	table.insert(dialog01, {func = AnimSay, args = {ally.gear, loc("Beware, though! Many smugglers come often to explore these tunnels and scavenge whatever valuable items they can find."), SAY_SAY, 5000}})
 	table.insert(dialog01, {func = AnimSay, args = {ally.gear, loc("They won't hesitate to attack you in order to rob you!"), SAY_SAY, 4000}})
 	table.insert(dialog01, {func = AnimWait, args = {hero.gear, 6000}})
-	table.insert(dialog01, {func = AnimSay, args = {hero.gear, loc("OK, I'll be extra careful!"), SAY_SAY, 4000}})
+	table.insert(dialog01, {func = AnimSay, args = {hero.gear, loc("Okay, I'll be extra careful!"), SAY_SAY, 4000}})
 	table.insert(dialog01, {func = AnimWait, args = {ally.gear, 2000}})
-	table.insert(dialog01, {func = AnimSay, args = {ally.gear, loc("There is the tunnel entrance"), SAY_SAY, 3000}})
+	table.insert(dialog01, {func = AnimSay, args = {ally.gear, loc("The tunnel entrance is over there."), SAY_SAY, 3000}})
 	table.insert(dialog01, {func = AnimSay, args = {ally.gear, loc("Good luck!"), SAY_SAY, 3000}})
 	table.insert(dialog01, {func = AnimWait, args = {hero.gear, 500}})
 	table.insert(dialog01, {func = startMission, args = {hero.gear}})
@@ -510,11 +510,11 @@
 function secondBattle()
 	-- second battle
 	if heroIsInBattle and ongoingBattle == 1 then
-		AnimSay(smuggler1.gear, loc("Get him Spike!"), SAY_SHOUT, 4000)
+		AnimSay(smuggler1.gear, loc("Get him, Spike!"), SAY_SHOUT, 4000)
 	end
 	heroIsInBattle = true
 	ongoingBattle = 2
-	AnimSay(smuggler2.gear, loc("This is seems like a wealthy hedgehog, nice..."), SAY_THINK, 5000)
+	AnimSay(smuggler2.gear, loc("This is seems like a wealthy hedgehog, nice ..."), SAY_THINK, 5000)
 	AnimSwitchHog(smuggler2.gear)
 	TurnTimeLeft = 0
 end
@@ -551,14 +551,14 @@
 function checkForWin()
 	if cratesFound ==  0 then
 		-- have to look more
-		AnimSay(hero.gear, loc("Haven't found it yet..."), SAY_THINK, 5000)
+		AnimSay(hero.gear, loc("Haven't found it yet ..."), SAY_THINK, 5000)
 		cratesFound = cratesFound + 1
 	elseif cratesFound == 1 then
 		-- end game
 		saveCompletedStatus(5)
-		AnimSay(hero.gear, loc("Hoorah!!!"), SAY_SHOUT, 5000)
+		AnimSay(hero.gear, loc("Hooray!"), SAY_SHOUT, 5000)
 		SendStat(siGameResult, loc("Congratulations, you won!"))
-		SendStat(siCustomAchievement, loc("To win the game you had to collect the 2 crates with no specific order"))
+		SendStat(siCustomAchievement, loc("To win the game you had to collect the 2 crates with no specific order."))
 		SendStat(siPlayerKills,'1',teamC.name)
 		SendStat(siPlayerKills,'0',teamB.name)
 		EndGame()
@@ -567,9 +567,9 @@
 
 function lose()
 	SendStat(siGameResult, loc("Hog Solo lost, try again!"))
-	SendStat(siCustomAchievement, loc("To win the game you have to find the right crate"))
-	SendStat(siCustomAchievement, loc("You can avoid some battles"))
-	SendStat(siCustomAchievement, loc("Use your ammo wisely"))
+	SendStat(siCustomAchievement, loc("To win the game you have to find the right crate."))
+	SendStat(siCustomAchievement, loc("You can avoid some battles."))
+	SendStat(siCustomAchievement, loc("Use your ammo wisely."))
 	SendStat(siCustomAchievement, loc("Don't destroy the device crate!"))
 	SendStat(siPlayerKills,'1',teamB.name)
 	SendStat(siPlayerKills,'0',teamC.name)
--- a/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/desert02.lua	Tue Mar 29 22:36:59 2016 +0300
+++ b/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/desert02.lua	Mon Apr 25 22:10:06 2016 +0300
@@ -144,17 +144,17 @@
 
 function heroDeath(gear)
 	SendStat(siGameResult, loc("Hog Solo lost, try again!"))
-	SendStat(siCustomAchievement, loc("To win the game you have to go to the surface"))
-	SendStat(siCustomAchievement, loc("Most mines are not active"))
-	SendStat(siCustomAchievement, loc("From the second turn and beyond the water rises"))
+	SendStat(siCustomAchievement, loc("To win the game you have to go to the surface."))
+	SendStat(siCustomAchievement, loc("Most mines are not active."))
+	SendStat(siCustomAchievement, loc("From the second turn and beyond the water rises."))
 	SendStat(siPlayerKills,'0',teamA.name)
 	EndGame()
 end
 
 function heroSafe(gear)
 	SendStat(siGameResult, loc("Congratulations, you won!"))
-	SendStat(siCustomAchievement, loc("You have escaped successfully"))
-	SendStat(siCustomAchievement, loc("Your escape took you "..TotalRounds.." turns"))
+	SendStat(siCustomAchievement, loc("You have escaped successfully."))
+	SendStat(siCustomAchievement, string.format(loc("Your escape took you %d turns."), TotalRounds))
 	SendStat(siPlayerKills,'1',teamA.name)
 	EndGame()
 end
@@ -172,9 +172,9 @@
 	-- DIALOG 01 - Start
 	AddSkipFunction(dialog01, Skipanim, {dialog01})
 	table.insert(dialog01, {func = AnimWait, args = {hero.gear, 3000}})
-	table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("Many meters below the surface..."), 5000}})
-	table.insert(dialog01, {func = AnimSay, args = {hero.gear, loc("The tunnel is about to get flooded..."), SAY_THINK, 4000}})
-	table.insert(dialog01, {func = AnimSay, args = {hero.gear, loc("I have to reach the surface as quickly as I can..."), SAY_THINK, 4000}})
+	table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("Many meters below the surface ..."), 5000}})
+	table.insert(dialog01, {func = AnimSay, args = {hero.gear, loc("The tunnel is about to get flooded!"), SAY_THINK, 4000}})
+	table.insert(dialog01, {func = AnimSay, args = {hero.gear, loc("I have to reach the surface as quickly as I can."), SAY_THINK, 4000}})
 	table.insert(dialog01, {func = AnimWait, args = {hero.gear, 500}})
 	table.insert(dialog01, {func = challengeStart, args = {hero.gear}})
 end
--- a/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/desert03.lua	Tue Mar 29 22:36:59 2016 +0300
+++ b/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/desert03.lua	Mon Apr 25 22:10:06 2016 +0300
@@ -18,7 +18,7 @@
 local dialog01 = {}
 -- mission objectives
 local goals = {
-	[dialog01] = {missionName, loc("Challenge Objectives"), challengeObjectives, 1, 4500},
+	[dialog01] = {missionName, loc("Challenge objectives"), challengeObjectives, 1, 4500},
 }
 -- hogs
 local hero = {
@@ -81,7 +81,7 @@
 function onGameStart()
 	AnimWait(hero.gear, 3000)
 	FollowGear(hero.gear)
-	ShowMission(missionName, loc("Challenge Objectives"), challengeObjectives, -amSkip, 0)
+	ShowMission(missionName, loc("Challenge objectives"), challengeObjectives, -amSkip, 0)
 
 	AddEvent(onHeroDeath, {hero.gear}, heroDeath, {hero.gear}, 0)
 	AddEvent(onLose, {hero.gear}, lose, {hero.gear}, 0)
@@ -159,7 +159,7 @@
 	-- DIALOG 01 - Start, game instructions
 	AddSkipFunction(dialog01, Skipanim, {dialog01})
 	table.insert(dialog01, {func = AnimWait, args = {hero.gear, 3000}})
-	table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("On the Desert Planet, Hog Solo found some time to play with his RC plane..."), 3000}})
+	table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("On the Desert Planet, Hog Solo found some time to play with his RC plane"), 3000}})
 	table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("Each time you destroy all the targets on your current level you'll get teleported to the next level"), 5000}})
 	table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("You'll have only one RC plane at the start of the mission"), 5000}})
 	table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("During the game you can get new RC planes by collecting the weapon crates"), 5000}})
@@ -209,18 +209,18 @@
 function win()
 	saveBonus(1, 1)
 	SendStat(siGameResult, loc("Congratulations, you are the best!"))
-	SendStat(siCustomAchievement, loc("You have destroyed all the targets"))
-	SendStat(siCustomAchievement, loc("You are indeed the best PAotH pilot"))
-	SendStat(siCustomAchievement, loc("Next time you play \"Searching in the dust\" you'll have an RC plane available"))
+	SendStat(siCustomAchievement, loc("You have destroyed all the targets."))
+	SendStat(siCustomAchievement, loc("You are indeed the best PAotH pilot."))
+	SendStat(siCustomAchievement, loc("Next time you play \"Searching in the dust\" you'll have an RC plane available."))
 	SendStat(siPlayerKills,'1',teamA.name)
 	EndGame()
 end
 
 function gameOver()
 	SendStat(siGameResult, loc("Hog Solo lost, try again!"))
-	SendStat(siCustomAchievement, loc("You have to destroy all the targets"))
-	SendStat(siCustomAchievement, loc("You will fail if you run out of ammo and there are still targets available"))
-	SendStat(siCustomAchievement, loc("Read the Challenge Objectives from within the mission for more details"))
+	SendStat(siCustomAchievement, loc("You have to destroy all the targets."))
+	SendStat(siCustomAchievement, loc("You will fail if you run out of ammo and there are still targets available."))
+	SendStat(siCustomAchievement, loc("Read the challenge objectives from within the mission for more details."))
 	SendStat(siPlayerKills,'0',teamA.name)
 	EndGame()
 end
--- a/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/final.lua	Tue Mar 29 22:36:59 2016 +0300
+++ b/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/final.lua	Mon Apr 25 22:10:06 2016 +0300
@@ -14,7 +14,7 @@
 local missionName = loc("The big bang")
 local challengeObjectives = loc("Find a way to detonate all the explosives and stay alive!").."|"..
 							loc("Red areas are indestructible").."|"..
-							loc("Green areas aren't portal enabled")
+							loc("Green areas are portal-proof")
 local explosives = {}
 local currentHealth = 1
 local currentDamage = 0
@@ -57,7 +57,7 @@
 function onGameStart()
 	AnimWait(hero.gear, 3000)
 	FollowGear(hero.gear)
-	ShowMission(missionName, loc("Challenge Objectives"), challengeObjectives, -amSkip, 0)
+	ShowMission(missionName, loc("Challenge objectives"), challengeObjectives, -amSkip, 0)
 
 	-- explosives
 	x = 400
@@ -143,8 +143,8 @@
 function heroDeath(gear)
 	SendStat(siGameResult, loc("Hog Solo lost, try again!"))
 	SendStat(siCustomAchievement, loc("You have to destroy all the explosives without dying!"))
-	SendStat(siCustomAchievement, loc("Red areas are indestructible"))
-	SendStat(siCustomAchievement, loc("Green areas aren't portal enabled"))
+	SendStat(siCustomAchievement, loc("Red areas are indestructible."))
+	SendStat(siCustomAchievement, loc("Green areas are portal-proof and repel portals."))
 	SendStat(siPlayerKills,'0',teamA.name)
 	EndGame()
 end
--- a/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/fruit01.lua	Tue Mar 29 22:36:59 2016 +0300
+++ b/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/fruit01.lua	Mon Apr 25 22:10:06 2016 +0300
@@ -32,9 +32,9 @@
 local dialog03 = {}
 -- mission objectives
 local goals = {
-	[dialog01] = {missionName, loc("Ready for Battle?"), loc("Walk left if you want to join Captain Lime or right if you want to decline his offer"), 1, 4000},
-	[dialog02] = {missionName, loc("Battle Starts Now!"), loc("You have chosen to fight! Lead the Green Bananas to battle and eliminate all the enemies"), 1, 4000},
-	[dialog03] = {missionName, loc("Time to run!"), loc("You have chosen to flee... Unfortunately the only place where you can launch your saucer is the left-most place on the map"), 1, 4000},
+	[dialog01] = {missionName, loc("Ready for Battle?"), loc("Walk left if you want to join Captain Lime or right if you want to decline his offer."), 1, 4000},
+	[dialog02] = {missionName, loc("Battle Starts Now!"), loc("You have chosen to fight! Lead the Green Bananas to battle and eliminate all the enemies!"), 1, 4000},
+	[dialog03] = {missionName, loc("Time to run!"), loc("You have chosen to flee ... Unfortunately, the only place where you can launch your saucer is the left-most place on the map."), 1, 4000},
 }
 -- crates
 local crateWMX = 2170
@@ -387,42 +387,42 @@
 	-- DIALOG 01 - Start, Captain Lime talks explains to Hog Solo
 	AddSkipFunction(dialog01, Skipanim, {dialog01})
 	table.insert(dialog01, {func = AnimWait, args = {hero.gear, 3000}})
-	table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("Somewhere on the Planet of Fruits a terrible war is about to begin..."), 5000}})
+	table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("Somewhere on the Planet of Fruits a terrible war is about to begin ..."), 5000}})
 	table.insert(dialog01, {func = AnimSay, args = {hero.gear, loc("I was told that as the leader of the king's guard, no one knows this world better than you!"), SAY_SAY, 5000}})
-	table.insert(dialog01, {func = AnimSay, args = {hero.gear, loc("So, I kindly ask for your help"), SAY_SAY, 3000}})
+	table.insert(dialog01, {func = AnimSay, args = {hero.gear, loc("So, I kindly ask for your help."), SAY_SAY, 3000}})
 	table.insert(dialog01, {func = AnimWait, args = {green1.gear, 2000}})
-	table.insert(dialog01, {func = AnimSay, args = {green1.gear, loc("You couldn't have come to a worse time Hog Solo!"), SAY_SAY, 3000}})
-	table.insert(dialog01, {func = AnimSay, args = {green1.gear, loc("The clan of the Red Strawberry wants to take over the dominion and overthrone king Pineapple."), SAY_SAY, 5000}})
-	table.insert(dialog01, {func = AnimSay, args = {green1.gear, loc("Under normal circumstances we could easily defeat them but we have kindly sent most of our men to the kingdom of Sand to help to the annual dusting of the king's palace."), SAY_SAY, 8000}})
-	table.insert(dialog01, {func = AnimSay, args = {green1.gear, loc("However the army of Yellow Watermelons is about to attack any moment now."), SAY_SAY, 4000}})
+	table.insert(dialog01, {func = AnimSay, args = {green1.gear, loc("You couldn't have come to a worse time, Hog Solo!"), SAY_SAY, 3000}})
+	table.insert(dialog01, {func = AnimSay, args = {green1.gear, loc("The clan of the Red Strawberry wants to take over the dominion and overthrow King Pineapple."), SAY_SAY, 5000}})
+	table.insert(dialog01, {func = AnimSay, args = {green1.gear, loc("Under normal circumstances we could easily defeat them but we have kindly sent most of our men to the Kingdom of Sand to help with the annual dusting of the king's palace."), SAY_SAY, 8000}})
+	table.insert(dialog01, {func = AnimSay, args = {green1.gear, loc("However, the army of Yellow Watermelons is about to attack any moment now."), SAY_SAY, 4000}})
 	table.insert(dialog01, {func = AnimSay, args = {green1.gear, loc("I would gladly help you if we won this battle but under these circumstances I'll only help you if you fight for our side."), SAY_SAY, 6000}})
 	table.insert(dialog01, {func = AnimSay, args = {green1.gear, loc("What do you say? Will you fight for us?"), SAY_SAY, 3000}})
 	table.insert(dialog01, {func = AnimWait, args = {hero.gear, 500}})
-	table.insert(dialog01, {func = ShowMission, args = {missionName, loc("Ready for Battle?"), loc("Walk left if you want to join Captain Lime or right if you want to decline his offer"), 1, 7000}})
+	table.insert(dialog01, {func = ShowMission, args = {missionName, loc("Ready for Battle?"), loc("Walk left if you want to join Captain Lime or right if you want to decline his offer."), 1, 7000}})
 	table.insert(dialog01, {func = AnimSwitchHog, args = {hero.gear}})
 	-- DIALOG 02 - Hero selects to fight
 	AddSkipFunction(dialog02, Skipanim, {dialog02})
 	table.insert(dialog02, {func = AnimWait, args = {green1.gear, 3000}})
-	table.insert(dialog02, {func = AnimSay, args = {green1.gear, loc("You choose well Hog Solo!"), SAY_SAY, 3000}})
-	table.insert(dialog02, {func = AnimSay, args = {green1.gear, loc("I have only 3 hogs available and they are all cadets"), SAY_SAY, 4000}})
-	table.insert(dialog02, {func = AnimSay, args = {green1.gear, loc("As you are more experienced, I want you to lead them to the battle"), SAY_SAY, 4000}})
-	table.insert(dialog02, {func = AnimSay, args = {green1.gear, loc("I of course will observe the battle and intervene if necessary"), SAY_SAY, 5000}})
+	table.insert(dialog02, {func = AnimSay, args = {green1.gear, loc("You choose well, Hog Solo!"), SAY_SAY, 3000}})
+	table.insert(dialog02, {func = AnimSay, args = {green1.gear, loc("I have only 3 hogs available and they are all cadets."), SAY_SAY, 4000}})
+	table.insert(dialog02, {func = AnimSay, args = {green1.gear, loc("As you are more experienced, I want you to lead them to battle."), SAY_SAY, 4000}})
+	table.insert(dialog02, {func = AnimSay, args = {green1.gear, loc("Of course, I will observe the battle and intervene if necessary."), SAY_SAY, 5000}})
 	table.insert(dialog02, {func = AnimWait, args = {hero.gear, 4500}})
-	table.insert(dialog02, {func = AnimSay, args = {hero.gear, loc("No problem Captain!"), SAY_SAY, 2000}})
+	table.insert(dialog02, {func = AnimSay, args = {hero.gear, loc("No problem, Captain!"), SAY_SAY, 2000}})
 	table.insert(dialog02, {func = AnimSay, args = {hero.gear, loc("The enemies aren't many anyway, it is going to be easy!"), SAY_SAY, 1}})
 	table.insert(dialog02, {func = AnimWait, args = {green1.gear, 9000}})
-	table.insert(dialog02, {func = AnimSay, args = {green1.gear, loc("Don't be foolish son, there will be more"), SAY_SAY, 2000}})
+	table.insert(dialog02, {func = AnimSay, args = {green1.gear, loc("Don't be foolish, son, there will be more."), SAY_SAY, 2000}})
 	table.insert(dialog02, {func = AnimSay, args = {green1.gear, loc("Try to be smart and eliminate them quickly. This way you might scare off the rest!"), SAY_SAY, 5000}})
 	table.insert(dialog02, {func = AnimWait, args = {hero.gear, 5000}})
 	table.insert(dialog02, {func = startBattle, args = {hero.gear}})
 	-- DIALOG 03 - Hero selects to flee
 	AddSkipFunction(dialog03, Skipanim, {dialog03})
 	table.insert(dialog03, {func = AnimWait, args = {green1.gear, 3000}})
-	table.insert(dialog03, {func = AnimSay, args = {green1.gear, loc("Too bad... Then you should really leave!"), SAY_SAY, 3000}})
-	table.insert(dialog03, {func = AnimSay, args = {green1.gear, loc("Things are going to get messy around here"), SAY_SAY, 3000}})
-	table.insert(dialog03, {func = AnimSay, args = {green1.gear, loc("Also, you should know that the only place where you can fly is the left-most part of this area"), SAY_SAY, 5000}})
-	table.insert(dialog03, {func = AnimSay, args = {green1.gear, loc("All the other places are protected by our flight-inhibiting weapons"), SAY_SAY, 4000}})
-	table.insert(dialog03, {func = AnimSay, args = {green1.gear, loc("Now go and don't waste more of my time you coward..."), SAY_SAY, 4000}})
+	table.insert(dialog03, {func = AnimSay, args = {green1.gear, loc("Too bad! Then you should really leave!"), SAY_SAY, 3000}})
+	table.insert(dialog03, {func = AnimSay, args = {green1.gear, loc("Things are going to get messy around here."), SAY_SAY, 3000}})
+	table.insert(dialog03, {func = AnimSay, args = {green1.gear, loc("Also, you should know that the only place where you can fly is the left-most part of this area."), SAY_SAY, 5000}})
+	table.insert(dialog03, {func = AnimSay, args = {green1.gear, loc("All the other places are protected by our flight-inhibiting weapons."), SAY_SAY, 4000}})
+	table.insert(dialog03, {func = AnimSay, args = {green1.gear, loc("Now go and don't waste more of my time, you coward!"), SAY_SAY, 4000}})
 	table.insert(dialog03, {func = AnimWait, args = {hero.gear, 5000}})
 	table.insert(dialog03, {func = startBattle, args = {hero.gear}})
 end
@@ -447,16 +447,16 @@
 function gameLost()
 	if chooseToBattle then
 		SendStat(siGameResult, loc("The Green Bananas lost, try again!"))
-		SendStat(siCustomAchievement, loc("You have to eliminate all the visible enemies"))
-		SendStat(siCustomAchievement, loc("5 additional enemies will be spawned during the game"))
-		SendStat(siCustomAchievement, loc("You are in control of all the active ally units"))
-		SendStat(siCustomAchievement, loc("The ally units share their ammo"))
-		SendStat(siCustomAchievement, loc("Try to keep as many allies alive as possible"))
+		SendStat(siCustomAchievement, loc("You have to eliminate all the visible enemies."))
+		SendStat(siCustomAchievement, loc("5 additional enemies will be spawned during the game."))
+		SendStat(siCustomAchievement, loc("You are in control of all the active ally units."))
+		SendStat(siCustomAchievement, loc("The ally units share their ammo."))
+		SendStat(siCustomAchievement, loc("Try to keep as many allies alive as possible."))
 	else
 		SendStat(siGameResult, loc("Hog Solo couldn't escape, try again!"))
-		SendStat(siCustomAchievement, loc("You have to get to the left-most land and remove any enemy hog from there"))
-		SendStat(siCustomAchievement, loc("You will play every 3 turns"))
-		SendStat(siCustomAchievement, loc("Green hogs won't intentionally hurt you"))
+		SendStat(siCustomAchievement, loc("You have to get to the left-most land and remove any enemy hog from there."))
+		SendStat(siCustomAchievement, loc("You will play every 3 turns."))
+		SendStat(siCustomAchievement, loc("Green hogs won't intentionally hurt you."))
 	end
 	SendStat(siPlayerKills,'1',teamC.name)
 	SendStat(siPlayerKills,'0',teamA.name)
--- a/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/fruit02.lua	Tue Mar 29 22:36:59 2016 +0300
+++ b/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/fruit02.lua	Mon Apr 25 22:10:06 2016 +0300
@@ -398,13 +398,13 @@
 function heroDeath(gear)
 	if not ended then
 		SendStat(siGameResult, loc("Hog Solo lost, try again!"))
-		SendStat(siCustomAchievement, loc("To win the game, Hog Solo has to get the bottom crates and come back to the surface"))
-		SendStat(siCustomAchievement, loc("You can use the other 2 hogs to assist you"))
-		SendStat(siCustomAchievement, loc("Do not destroy the crates"))
+		SendStat(siCustomAchievement, loc("To win the game, Hog Solo has to get the bottom crates and come back to the surface."))
+		SendStat(siCustomAchievement, loc("You can use the other 2 hogs to assist you."))
+		SendStat(siCustomAchievement, loc("Do not destroy the crates!"))
 		if tookPartInBattle then
-			SendStat(siCustomAchievement, loc("You'll have to eliminate the Strawberry Assassins at the end"))
+			SendStat(siCustomAchievement, loc("You'll have to eliminate the Strawberry Assassins at the end."))
 		else
-			SendStat(siCustomAchievement, loc("You'll have to eliminate Captain Lime at the end"))
+			SendStat(siCustomAchievement, loc("You'll have to eliminate Captain Lime at the end."))
 		SendStat(siCustomAchievement, loc("Don't eliminate Captain Lime before collecting the last crate!"))
 		end
 		SendStat(siPlayerKills,'0',teamA.name)
@@ -455,8 +455,8 @@
 	-- hero win in scenario of escape in 1st part
 	saveCompletedStatus(3)
 	SendStat(siGameResult, loc("Congratulations, you won!"))
-	SendStat(siCustomAchievement, loc("You retrieved the lost part"))
-	SendStat(siCustomAchievement, loc("You defended yourself against Captain Lime"))
+	SendStat(siCustomAchievement, loc("You retrieved the lost part."))
+	SendStat(siCustomAchievement, loc("You defended yourself against Captain Lime."))
 	SendStat(siPlayerKills,'1',teamA.name)
 	SendStat(siPlayerKills,'0',teamB.name)
 	EndGame()
@@ -466,8 +466,8 @@
 	-- hero win in battle scenario
 	saveCompletedStatus(3)
 	SendStat(siGameResult, loc("Congratulations, you won!"))
-	SendStat(siCustomAchievement, loc("You retrieved the lost part"))
-	SendStat(siCustomAchievement, loc("You defended yourself against Strawberry Assassins"))
+	SendStat(siCustomAchievement, loc("You retrieved the lost part."))
+	SendStat(siCustomAchievement, loc("You defended yourself against the Strawberry Assassins."))
 	SendStat(siPlayerKills,'1',teamA.name)
 	SendStat(siPlayerKills,'0',teamC.name)
 	EndGame()
@@ -502,7 +502,7 @@
 	-- DIALOG 01 - Start, Captain Lime helps Hog Solo because he took part in the battle
 	AddSkipFunction(dialog01, Skipanim, {dialog01})
 	table.insert(dialog01, {func = AnimWait, args = {hero.gear, 3000}})
-	table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("Somewhere else on the planet of fruits Captain Lime helps Hog Solo..."), 5000}})
+	table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("Somewhere else on the planet of fruits, Captain Lime helps Hog Solo"), 5000}})
 	table.insert(dialog01, {func = AnimSay, args = {green1.gear, loc("You fought bravely and you helped us win this battle!"), SAY_SAY, 5000}})
 	table.insert(dialog01, {func = AnimSay, args = {green1.gear, loc("So, as promised I have brought you where I think that the device you are looking for is hidden."), SAY_SAY, 7000}})
 	table.insert(dialog01, {func = AnimSay, args = {green1.gear, loc("I know that your resources are low due to the battle but I'll send two of my best hogs to assist you."), SAY_SAY, 7000}})
@@ -512,23 +512,23 @@
 	-- DIALOG02 - Start, Hog Solo escaped from the previous battle
 	AddSkipFunction(dialog02, Skipanim, {dialog02})
 	table.insert(dialog02, {func = AnimWait, args = {hero.gear, 3000}})
-	table.insert(dialog02, {func = AnimCaption, args = {hero.gear, loc("Somewhere else on the planet of fruits Hog Solo gets closer to the device..."), 5000}})
-	table.insert(dialog02, {func = AnimSay, args = {green1.gear, loc("You are the one who fled! So, you are alive..."), SAY_SAY, 4000}})
-	table.insert(dialog02, {func = AnimSay, args = {green1.gear, loc("I'm still low on hogs. If you are not afraid I could use a set of extra hands"), SAY_SAY, 4000}})
+	table.insert(dialog02, {func = AnimCaption, args = {hero.gear, loc("Somewhere else on the planet of fruits Hog Solo gets closer to the device"), 5000}})
+	table.insert(dialog02, {func = AnimSay, args = {green1.gear, loc("You are the one who fled! So, you are alive."), SAY_SAY, 4000}})
+	table.insert(dialog02, {func = AnimSay, args = {green1.gear, loc("I'm still low on hogs. If you are not afraid I could use a set of extra hands."), SAY_SAY, 4000}})
 	table.insert(dialog02, {func = AnimWait, args = {hero.gear, 8000}})
-	table.insert(dialog02, {func = AnimSay, args = {hero.gear, loc("I am sorry but I was looking for a device that may be hidden somewhere around here"), SAY_SAY, 4500}})
+	table.insert(dialog02, {func = AnimSay, args = {hero.gear, loc("I am sorry but I was looking for a device that may be hidden somewhere around here."), SAY_SAY, 4500}})
 	table.insert(dialog02, {func = AnimWait, args = {green1.gear, 12500}})
 	table.insert(dialog02, {func = AnimSay, args = {green1.gear, loc("Many long forgotten things can be found in the same tunnels that we are about to explore!"), SAY_SAY, 7000}})
-	table.insert(dialog02, {func = AnimSay, args = {green1.gear, loc("If you help us you can keep the device if you find it but we'll keep everything else"), SAY_SAY, 7000}})
+	table.insert(dialog02, {func = AnimSay, args = {green1.gear, loc("If you help us you can keep the device if you find it but we'll keep everything else."), SAY_SAY, 7000}})
 	table.insert(dialog02, {func = AnimSay, args = {green1.gear, loc("What do you say? Are you in?"), SAY_SAY, 3000}})
 	table.insert(dialog02, {func = AnimWait, args = {hero.gear, 1800}})
-	table.insert(dialog02, {func = AnimSay, args = {hero.gear, loc("Ok then!"), SAY_SAY, 2000}})
+	table.insert(dialog02, {func = AnimSay, args = {hero.gear, loc("Okay then!"), SAY_SAY, 2000}})
 	table.insert(dialog02, {func = AnimSwitchHog, args = {hero.gear}})
 	-- DIALOG03 - At crates, hero learns that Captain Lime is bad
 	AddSkipFunction(dialog03, Skipanim, {dialog03})
 	table.insert(dialog03, {func = AnimWait, args = {hero.gear, 4000}})
 	table.insert(dialog03, {func = FollowGear, args = {hero.gear}})
-	table.insert(dialog03, {func = AnimSay, args = {hero.gear, loc("Hoorah! I've found it, now I have to get back to Captain Lime!"), SAY_SAY, 4000}})
+	table.insert(dialog03, {func = AnimSay, args = {hero.gear, loc("Hooray! I've found it, now I have to get back to Captain Lime!"), SAY_SAY, 4000}})
 	table.insert(dialog03, {func = AnimWait, args = {green1.gear, 4000}})
 	table.insert(dialog03, {func = AnimSay, args = {green1.gear, loc("This Hog Solo is so naive! When he returns I'll shoot him and keep that device for myself!"), SAY_THINK, 4000}})
 	table.insert(dialog03, {func = goToThesurface, args = {hero.gear}})
@@ -536,7 +536,7 @@
 	AddSkipFunction(dialog04, Skipanim, {dialog04})
 	table.insert(dialog04, {func = AnimWait, args = {hero.gear, 4000}})
 	table.insert(dialog04, {func = FollowGear, args = {hero.gear}})
-	table.insert(dialog04, {func = AnimSay, args = {hero.gear, loc("Hoorah! I've found it, now I have to get back to Captain Lime!"), SAY_SAY, 4000}})
+	table.insert(dialog04, {func = AnimSay, args = {hero.gear, loc("Hooray! I've found it, now I have to get back to Captain Lime!"), SAY_SAY, 4000}})
 	table.insert(dialog04, {func = AnimWait, args = {redHedgehogs[1].gear, 4000}})
 	table.insert(dialog04, {func = AnimSay, args = {redHedgehogs[1].gear, loc("We have spotted the enemy! We'll attack when the enemies start gathering!"), SAY_THINK, 4000}})
 	table.insert(dialog04, {func = goToThesurface, args = {hero.gear}})
--- a/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/fruit03.lua	Tue Mar 29 22:36:59 2016 +0300
+++ b/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/fruit03.lua	Mon Apr 25 22:10:06 2016 +0300
@@ -13,19 +13,19 @@
 local missionName = loc("Precise shooting")
 local timeLeft = 10000
 local lastWeaponUsed = amSniperRifle
-local challengeObjectives = loc("Use your available weapons in order to eliminate the enemies").."|"..
-	loc("You can only use the Sniper Rifle or the Watermelon bomb").."|"..
-	loc("You'll have only 2 watermelon bombs during the game").."|"..
-	loc("You'll get an extra Sniper Rifle every time you kill an enemy hog with a limit of max 4 rifles").."|"..
-	loc("You'll get an extra Teleport every time you kill an enemy hog with a limit of max 2 teleports").."|"..
-	loc("The first turn will last 25 sec and every other turn 15 sec").."|"..
-	loc("If you skip a turn then the turn time left will be added to your next turn").."|"..
-	loc("Some parts of the land are indestructible")
+local challengeObjectives = loc("Use your available weapons in order to eliminate the enemies.").."|"..
+	loc("You can only use the sniper rifle or the watermelon bomb.").."|"..
+	loc("You'll have only 2 watermelon bombs during the game.").."|"..
+	loc("You'll get an extra sniper rifle every time you kill an enemy hog with a limit of max 4 rifles.").."|"..
+	loc("You'll get an extra teleport every time you kill an enemy hog with a limit of max 2 teleports.").."|"..
+	loc("The first turn will last 25 sec and every other turn 15 sec.").."|"..
+	loc("If you skip a turn then the turn time left will be added to your next turn.").."|"..
+	loc("Some parts of the land are indestructible.")
 -- dialogs
 local dialog01 = {}
 -- mission objectives
 local goals = {
-	[dialog01] = {missionName, loc("Challenge Objectives"), challengeObjectives, 1, 4500},
+	[dialog01] = {missionName, loc("Challenge objectives"), challengeObjectives, 1, 4500},
 }
 -- hogs
 local hero = {
@@ -107,7 +107,7 @@
 function onGameStart()
 	AnimWait(hero.gear, 3000)
 	FollowGear(hero.gear)
-	ShowMission(missionName, loc("Challenge Objectives"), challengeObjectives, -amSkip, 0)
+	ShowMission(missionName, loc("Challenge objectives"), challengeObjectives, -amSkip, 0)
 
 	AddEvent(onHeroDeath, {hero.gear}, heroDeath, {hero.gear}, 0)
 	AddEvent(onHeroWin, {hero.gear}, heroWin, {hero.gear}, 0)
@@ -203,8 +203,8 @@
 
 function heroDeath(gear)
 	SendStat(siGameResult, loc("Hog Solo lost, try again!"))
-	SendStat(siCustomAchievement, loc("You have to eliminate all the enemies"))
-	SendStat(siCustomAchievement, loc("Read the Challenge Objectives from within the mission for more details"))
+	SendStat(siCustomAchievement, loc("You have to eliminate all the enemies."))
+	SendStat(siCustomAchievement, loc("Read the challenge objectives from within the mission for more details."))
 	SendStat(siPlayerKills,'1',teamB.name)
 	SendStat(siPlayerKills,'0',teamA.name)
 	EndGame()
@@ -213,8 +213,8 @@
 function heroWin(gear)
 	saveBonus(2, 1)
 	SendStat(siGameResult, loc("Congratulations, you won!"))
-	SendStat(siCustomAchievement, loc("You complete the mission in "..TotalRounds.." rounds"))
-	SendStat(siCustomAchievement, loc("You will gain some extra ammo from the crates the next time you play the \"Getting to the device\" mission"))
+	SendStat(siCustomAchievement, string.format(loc("You completed the mission in %d rounds."), TotalRounds))
+	SendStat(siCustomAchievement, loc("You will gain some extra ammo from the crates the next time you play the \"Getting to the device\" mission."))
 	SendStat(siPlayerKills,'1',teamA.name)
 	EndGame()
 end
@@ -232,13 +232,13 @@
 	-- DIALOG 01 - Start, game instructions
 	AddSkipFunction(dialog01, Skipanim, {dialog01})
 	table.insert(dialog01, {func = AnimWait, args = {hero.gear, 3000}})
-	table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("Somewhere in the Fruit Planet Hog Solo got lost..."), 5000}})
-	table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("...and got ambushed by the Red Strawberries"), 5000}})
+	table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("Somewhere in the Fruit Planet Hog Solo got lost ..."), 5000}})
+	table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("... and got ambushed by the Red Strawberries"), 5000}})
 	table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("Use your available weapons in order to eliminate the enemies"), 5000}})
-	table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("You can only use the Sniper Rifle or the Watermelon bomb"), 5000}})
+	table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("You can only use the sniper rifle or the watermelon bomb"), 5000}})
 	table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("You'll have only 2 watermelon bombs during the game"), 5000}})
-	table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("You'll get an extra Sniper Rifle every time you kill an enemy hog with a limit of max 4 rifles"), 5000}})
-	table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("You'll get an extra Teleport every time you kill an enemy hog with a limit of max 2 teleports"), 5000}})
+	table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("You'll get an extra sniper rifle every time you kill an enemy hog with a limit of max 4 rifles"), 5000}})
+	table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("You'll get an extra teleport every time you kill an enemy hog with a limit of max 2 teleports"), 5000}})
 	table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("The first turn will last 25 sec and every other turn 15 sec"), 5000}})
 	table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("If you skip the game your time left will be added to your next turn"), 5000}})
 	table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("Some parts of the land are indestructible"), 5000}})
--- a/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/ice01.lua	Tue Mar 29 22:36:59 2016 +0300
+++ b/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/ice01.lua	Mon Apr 25 22:10:06 2016 +0300
@@ -428,9 +428,9 @@
 
 function heroDeath(gear)
 	SendStat(siGameResult, loc("Hog Solo lost, try again!"))
-	SendStat(siCustomAchievement, loc("To win the game you have to go next to Thanta"))
-	SendStat(siCustomAchievement, loc("Most of the time you'll be able to use only the icegun"))
-	SendStat(siCustomAchievement, loc("Use the bazooka and the flying saucer to get the icegun"))
+	SendStat(siCustomAchievement, loc("To win the game you have to stand next to Thanta."))
+	SendStat(siCustomAchievement, loc("Most of the time you'll be able to use the icegun only."))
+	SendStat(siCustomAchievement, loc("Use the bazooka and the flying saucer to get the icegun."))
 	SendStat(siPlayerKills,'1',teamB.name)
 	SendStat(siPlayerKills,'0',teamC.name)
 	EndGame()
@@ -454,10 +454,10 @@
 
 function thantaDeath(gear)
 	SendStat(siGameResult, loc("Hog Solo lost, try again!"))
-	SendStat(siCustomAchievement, loc("Noooo, Thanta has to stay alive!"))
-	SendStat(siCustomAchievement, loc("To win the game you have to go next to Thanta"))
-	SendStat(siCustomAchievement, loc("Most of the time you'll be able to use only the icegun"))
-	SendStat(siCustomAchievement, loc("Use the bazooka and the flying saucer to get the icegun"))
+	SendStat(siCustomAchievement, loc("Noo, Thanta has to stay alive!"))
+	SendStat(siCustomAchievement, loc("To win the game you have to go next to Thanta."))
+	SendStat(siCustomAchievement, loc("Most of the time you'll be able to use the icegun only."))
+	SendStat(siCustomAchievement, loc("Use the bazooka and the flying saucer to get the icegun."))
 	SendStat(siPlayerKills,'1',teamB.name)
 	SendStat(siPlayerKills,'0',teamC.name)
 	EndGame()
@@ -490,29 +490,29 @@
 	-- DIALOG 01 - Start, welcome to moon
 	AddSkipFunction(dialog01, Skipanim, {dialog01})
 	table.insert(dialog01, {func = AnimWait, args = {hero.gear, 3000}})
-	table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("On the Ice Planet, where ice rules..."), 5000}})
-	table.insert(dialog01, {func = AnimSay, args = {ally.gear, loc("Finally you are here..."), SAY_SAY, 2000}})
+	table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("On the Ice Planet, where ice rules ..."), 5000}})
+	table.insert(dialog01, {func = AnimSay, args = {ally.gear, loc("Finally you are here!"), SAY_SAY, 2000}})
 	table.insert(dialog01, {func = AnimWait, args = {hero.gear, 2000}})
-	table.insert(dialog01, {func = AnimSay, args = {hero.gear, loc("Hi! Nice to meet you"), SAY_SAY, 3000}})
+	table.insert(dialog01, {func = AnimSay, args = {hero.gear, loc("Hi! Nice to meet you."), SAY_SAY, 3000}})
 	table.insert(dialog01, {func = AnimWait, args = {ally.gear, 2000}})
-	table.insert(dialog01, {func = AnimSay, args = {ally.gear, loc("Listen carefully! The bandit leader, Thanta, has recently found a very strange device"), SAY_SAY, 4000}})
-	table.insert(dialog01, {func = AnimSay, args = {ally.gear, loc("He doesn't know it but this device is a part of the anti-gravity device"), SAY_SAY, 2500}})
+	table.insert(dialog01, {func = AnimSay, args = {ally.gear, loc("Listen carefully! The bandit leader, Thanta, has recently found a very strange device."), SAY_SAY, 4000}})
+	table.insert(dialog01, {func = AnimSay, args = {ally.gear, loc("He doesn't know it but this device is a part of the anti-gravity device."), SAY_SAY, 2500}})
 	table.insert(dialog01, {func = AnimWait, args = {hero.gear, 8000}})
 	table.insert(dialog01, {func = AnimSay, args = {hero.gear, loc("Nice, then I should get the part as soon as possible!"), SAY_SAY, 4000}})
 	table.insert(dialog01, {func = AnimWait, args = {ally.gear, 4000}})
-	table.insert(dialog01, {func = AnimSay, args = {ally.gear, loc("Be careful, your gadgets won't work in the bandit area. You should get an ice gun"), SAY_SAY, 7000}})
+	table.insert(dialog01, {func = AnimSay, args = {ally.gear, loc("Be careful, your gadgets won't work in the bandit area. You should get an ice gun."), SAY_SAY, 7000}})
 	table.insert(dialog01, {func = AnimSay, args = {ally.gear, loc("There is one below us!"), SAY_SAY, 4000}})
 	table.insert(dialog01, {func = AnimWait, args = {hero.gear, 500}})
 	table.insert(dialog01, {func = AnimSwitchHog, args = {hero.gear}})
 	-- DIALOG 02 - Hero got to Thant2
 	AddSkipFunction(dialog02, Skipanim, {dialog02})
 	table.insert(dialog02, {func = AnimWait, args = {hero.gear, 3000}})
-	table.insert(dialog02, {func = AnimCaption, args = {hero.gear, loc("Congratulations, now you can take Thanta's device part..."), 5000}})
+	table.insert(dialog02, {func = AnimCaption, args = {hero.gear, loc("Congratulations, now you can take Thanta's device part!"), 5000}})
 	table.insert(dialog02, {func = AnimSay, args = {bandit1.gear, loc("Oh! Please spare me. You can take all my treasures!"), SAY_SAY, 3000}})
 	table.insert(dialog02, {func = AnimWait, args = {hero.gear, 5000}})
 	table.insert(dialog02, {func = AnimSay, args = {hero.gear, loc("I just want the strange device you found!"), SAY_SAY, 3000}})
 	table.insert(dialog02, {func = AnimWait, args = {bandit1.gear, 4000}})
-	table.insert(dialog02, {func = AnimSay, args = {bandit1.gear, loc("Here! Take it..."), SAY_SAY, 3000}})
+	table.insert(dialog02, {func = AnimSay, args = {bandit1.gear, loc("Here! Take it!"), SAY_SAY, 3000}})
 	table.insert(dialog02, {func = actionsOnWin, args = {}})
 end
 
@@ -521,7 +521,7 @@
 function actionsOnWin()
 	saveCompletedStatus(4)
 	SendStat(siGameResult, loc("Congratulations, you acquired the device part!"))
-	SendStat(siCustomAchievement, loc("At the end of the game your health was ")..GetHealth(hero.gear))
+	SendStat(siCustomAchievement, string.format(loc("At the end of the game your health was %d."), GetHealth(hero.gear)))
 	-- maybe add number of tries for each part?
 	SendStat(siPlayerKills,'1',teamC.name)
 	SendStat(siPlayerKills,'0',teamB.name)
--- a/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/ice02.lua	Tue Mar 29 22:36:59 2016 +0300
+++ b/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/ice02.lua	Mon Apr 25 22:10:06 2016 +0300
@@ -22,7 +22,7 @@
 local challengeObjectives = loc("To win the game you have to pass into the rings in time")..
 	"|"..loc("You'll get extra time in case you need it when you pass a ring").."|"..
 	loc("Every 2 rings, the ring color will be green and you'll get an extra flying saucer").."|"..
-	loc("Use space button twice to change flying saucer while floating in mid-air")
+	loc("Use the attack key twice to change the flying saucer while floating in mid-air")
 -- dialogs
 local dialog01 = {}
 -- mission objectives
@@ -99,7 +99,7 @@
 function onGameStart()
 	AnimWait(hero.gear, 3000)
 	FollowGear(hero.gear)
-	ShowMission(missionName, loc("Challenge Objectives"), challengeObjectives, -amSkip, 0)
+	ShowMission(missionName, loc("Challenge objectives"), challengeObjectives, -amSkip, 0)
 
 	AddEvent(onHeroDeath, {hero.gear}, heroDeath, {hero.gear}, 0)
 
@@ -138,10 +138,10 @@
 			totalTime = totalTime / 1000
 			local saucersLeft = GetAmmoCount(hero.gear, amJetpack)
 			local saucersUsed = totalSaucers - saucersLeft
-			SendStat(siGameResult, loc("Hoorah! You are a champion!"))
-			SendStat(siCustomAchievement, loc("You completed the mission in "..totalTime.." seconds"))
-			SendStat(siCustomAchievement, loc("You have used "..saucersUsed.." flying saucers"))
-			SendStat(siCustomAchievement, loc("You had "..saucersLeft.." more flying saucers left"))
+			SendStat(siGameResult, loc("Hooray! You are a champion!"))
+			SendStat(siCustomAchievement, string.format(loc("You completed the mission in %.3f seconds.", totalTime)))
+			SendStat(siCustomAchievement, string.format(loc("You have used %d flying saucers.", saucersUsed)))
+			SendStat(siCustomAchievement, string.format(loc("You had %d additional flying saucers left"), saucersLeft))
 			SendStat(siPlayerKills,'1',teamA.name)
 			EndGame()
 		end
@@ -188,13 +188,13 @@
 	-- DIALOG 01 - Start, some story telling
 	AddSkipFunction(dialog01, Skipanim, {dialog01})
 	table.insert(dialog01, {func = AnimWait, args = {hero.gear, 3000}})
-	table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("In the Ice Planet flying saucer stadium..."), 5000}})
-	table.insert(dialog01, {func = AnimSay, args = {ally.gear, loc("This is the Olympic stadium of saucer flying..."), SAY_SAY, 4000}})
+	table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("In the Ice Planet Flying Saucer Stadium ..."), 5000}})
+	table.insert(dialog01, {func = AnimSay, args = {ally.gear, loc("This is the Olympic stadium of saucer flying."), SAY_SAY, 4000}})
 	table.insert(dialog01, {func = AnimSay, args = {ally.gear, loc("All the saucer pilots dream to come here one day in order to compete with the best!"), SAY_SAY, 5000}})
-	table.insert(dialog01, {func = AnimSay, args = {ally.gear, loc("Now you have the chance to try and claim the place that you deserve among the best..."), SAY_SAY, 6000}})
-	table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("Use the saucer and pass through the rings..."), 5000}})
+	table.insert(dialog01, {func = AnimSay, args = {ally.gear, loc("Now you have the chance to try and claim the place that you deserve among the best."), SAY_SAY, 6000}})
+	table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("Use the saucer and pass through the rings."), 5000}})
 	table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("Pause the game by pressing the pause key (default \"P\") for more details"), 5000}})
-	table.insert(dialog01, {func = AnimSay, args = {ally.gear, loc("... can you do it?"), SAY_SAY, 2000}})
+	table.insert(dialog01, {func = AnimSay, args = {ally.gear, loc("Can you do it?"), SAY_SAY, 2000}})
 	table.insert(dialog01, {func = AnimWait, args = {hero.gear, 500}})
 	table.insert(dialog01, {func = startFlying, args = {hero.gear}})
 end
@@ -260,10 +260,10 @@
 
 function heroLost()
 	SendStat(siGameResult, loc("Oh man! Learn how to fly!"))
-	SendStat(siCustomAchievement, loc("To win the game you have to pass into the rings in time"))
-	SendStat(siCustomAchievement, loc("You'll get extra time in case you need it when you pass a ring"))
-	SendStat(siCustomAchievement, loc("Every 2 rings you'll get extra flying saucers"))
-	SendStat(siCustomAchievement, loc("Use space button twice to change flying saucer while being on air"))
+	SendStat(siCustomAchievement, loc("To win the game you have to pass into the rings in time."))
+	SendStat(siCustomAchievement, loc("You'll get extra time in case you need it when you pass a ring."))
+	SendStat(siCustomAchievement, loc("Every 2 rings you'll get extra flying saucers."))
+	SendStat(siCustomAchievement, loc("Use the attack key twice to change the flying saucer while being in air."))
 	SendStat(siPlayerKills,'0',teamA.name)
 	EndGame()
 end
--- a/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/moon01.lua	Tue Mar 29 22:36:59 2016 +0300
+++ b/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/moon01.lua	Mon Apr 25 22:10:06 2016 +0300
@@ -330,7 +330,7 @@
 
 function heroDeath(gear)
 	SendStat(siGameResult, loc("Hog Solo lost, try again!"))
-	SendStat(siCustomAchievement, loc("You have to get the weapons and rescue the PAotH researchers"))
+	SendStat(siCustomAchievement, loc("You have to get the weapons and rescue the PAotH researchers."))
 	SendStat(siPlayerKills,'1',teamC.name)
 	SendStat(siPlayerKills,'0',teamD.name)
 	EndGame()
@@ -348,7 +348,7 @@
 
 function professorHit(gear)
 	if currentHedgehog ~= hero.gear then
-		AnimSay(professor.gear,loc("Don't hit me you fools!"), SAY_SHOUT, 2000)
+		AnimSay(professor.gear,loc("Don't hit me, you fools!"), SAY_SHOUT, 2000)
 	end
 end
 
@@ -366,8 +366,8 @@
 
 	saveCompletedStatus(1)
 	SendStat(siGameResult, loc("Hog Solo wins, congratulations!"))
-	SendStat(siCustomAchievement, loc("Eliminated the Professor Hogevil"))
-	SendStat(siCustomAchievement, loc("Drove the minions away"))
+	SendStat(siCustomAchievement, loc("You have eliminated Professor Hogevil."))
+	SendStat(siCustomAchievement, loc("You drove the minions away."))
 	SendStat(siPlayerKills,'1',teamD.name)
 	SendStat(siPlayerKills,'0',teamC.name)
 	SaveCampaignVar("CosmosCheckPoint", "5") -- hero got fuels
@@ -383,8 +383,8 @@
 
 	saveCompletedStatus(1)
 	SendStat(siGameResult, loc("Congratulations, you won!"))
-	SendStat(siCustomAchievement, loc("Eliminated the evil minions"))
-	SendStat(siCustomAchievement, loc("Drove the Professor away"))
+	SendStat(siCustomAchievement, loc("You have eliminated the evil minions."))
+	SendStat(siCustomAchievement, loc("You drove Professor Hogevil away."))
 	SendStat(siPlayerKills,'1',teamD.name)
 	SendStat(siPlayerKills,'0',teamC.name)
 	SaveCampaignVar("CosmosCheckPoint", "5") -- hero got fuels
@@ -410,36 +410,36 @@
 	-- DIALOG 01 - Start, welcome to moon
 	AddSkipFunction(dialog01, Skipanim, {dialog01})
 	table.insert(dialog01, {func = AnimWait, args = {hero.gear, 3000}})
-	table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("Near PAotH base at moon..."),  4000}})
-	table.insert(dialog01, {func = AnimSay, args = {paoth1.gear, loc("Hey Hog Solo! Finally you have come..."), SAY_SAY, 2000}})
+	table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("Near a PAotH base on the moon ..."),  4000}})
+	table.insert(dialog01, {func = AnimSay, args = {paoth1.gear, loc("Hey, Hog Solo! Finally you have come!"), SAY_SAY, 2000}})
 	table.insert(dialog01, {func = AnimSay, args = {paoth1.gear, loc("It seems that Professor Hogevil has prepared for your arrival!"), SAY_SAY, 4000}})
 	table.insert(dialog01, {func = AnimSay, args = {paoth1.gear, loc("He has captured the rest of the PAotH team and awaits to capture you!"), SAY_SAY, 5000}})
 	table.insert(dialog01, {func = AnimSay, args = {paoth1.gear, loc("We have to hurry! Are you armed?"), SAY_SAY, 4300}})
 	table.insert(dialog01, {func = AnimWait, args = {hero.gear, 450}})
-	table.insert(dialog01, {func = AnimSay, args = {hero.gear, loc("No, I am afraid I had to travel light"), SAY_SAY, 2500}})
+	table.insert(dialog01, {func = AnimSay, args = {hero.gear, loc("No, I am afraid I had to travel light."), SAY_SAY, 2500}})
 	table.insert(dialog01, {func = AnimWait, args = {paoth1.gear, 3200}})
-	table.insert(dialog01, {func = AnimSay, args = {paoth1.gear, loc("Ok, then you have to go and take some of the weapons we have hidden in case of an emergency!"), SAY_SAY, 7000}})
+	table.insert(dialog01, {func = AnimSay, args = {paoth1.gear, loc("Okay, then you have to go and take some of the weapons we have hidden in case of an emergency!"), SAY_SAY, 7000}})
 	table.insert(dialog01, {func = AnimSay, args = {paoth1.gear, loc("They are up there! Take this rope and hurry!"), SAY_SAY, 7000}})
-	table.insert(dialog01, {func = AnimSay, args = {hero.gear, loc("Ehm... ok..."), SAY_SAY, 2500}})
+	table.insert(dialog01, {func = AnimSay, args = {hero.gear, loc("Ehm, okay ..."), SAY_SAY, 2500}})
 	table.insert(dialog01, {func = AnimSwitchHog, args = {hero.gear}})
 	-- DIALOG 02 - To the weapons platform
 	AddSkipFunction(dialog02, Skipanim, {dialog02})
 	table.insert(dialog02, {func = AnimCaption, args = {hero.gear, loc("Checkpoint reached!"),  4000}})
-	table.insert(dialog02, {func = AnimSay, args = {hero.gear, loc("I've made it! YEAAAAAH!"), SAY_SHOUT, 4000}})
+	table.insert(dialog02, {func = AnimSay, args = {hero.gear, loc("I've made it! Yeah!"), SAY_SHOUT, 4000}})
 	table.insert(dialog02, {func = AnimSay, args = {paoth1.gear, loc("Nice! Now hurry and get down! You have to rescue my friends!"), SAY_SHOUT, 7000}})
 	table.insert(dialog02, {func = setAfterDialog02, args = {}})
 	table.insert(dialog02, {func = AnimSwitchHog, args = {hero.gear}})
 	-- DIALOG 03 - Hero spotted and has no weapons
 	AddSkipFunction(dialog03, Skipanim, {dialog03})
 	table.insert(dialog03, {func = AnimCaption, args = {hero.gear, loc("Get ready to fight!"), 4000}})
-	table.insert(dialog03, {func = AnimSay, args = {minion1.gear, loc("Look boss! There is the target!"), SAY_SHOUT, 4000}})
+	table.insert(dialog03, {func = AnimSay, args = {minion1.gear, loc("Look, boss! There is the target!"), SAY_SHOUT, 4000}})
 	table.insert(dialog03, {func = AnimSay, args = {professor.gear, loc("Prepare for battle!"), SAY_SHOUT, 4000}})
 	table.insert(dialog03, {func = AnimSay, args = {hero.gear, loc("Oops, I've been spotted and I have no weapons! I am doomed!"), SAY_THINK, 4000}})
 	table.insert(dialog03, {func = startCombat, args = {hero.gear}})
 	-- DIALOG 04 - Hero spotted and *HAS* weapons
 	AddSkipFunction(dialog04, Skipanim, {dialog04})
 	table.insert(dialog04, {func = AnimCaption, args = {hero.gear, loc("Get ready to fight!"), 4000}})
-	table.insert(dialog04, {func = AnimSay, args = {minion1.gear, loc("Look boss! There is the target!"), SAY_SHOUT, 4000}})
+	table.insert(dialog04, {func = AnimSay, args = {minion1.gear, loc("Look, boss! There is the target!"), SAY_SHOUT, 4000}})
 	table.insert(dialog04, {func = AnimSay, args = {professor.gear, loc("Prepare for battle!"), SAY_SHOUT, 4000}})
 	table.insert(dialog04, {func = AnimSay, args = {hero.gear, loc("Here we go!"), SAY_THINK, 4000}})
 	table.insert(dialog04, {func = startCombat, args = {hero.gear}})
--- a/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/moon02.lua	Tue Mar 29 22:36:59 2016 +0300
+++ b/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/moon02.lua	Mon Apr 25 22:10:06 2016 +0300
@@ -20,7 +20,7 @@
 local dialog02 = {}
 -- mission objectives
 local goals = {
-	[dialog01] = {missionName, loc("Challenge Objectives"), challengeObjectives, 1, 4500},
+	[dialog01] = {missionName, loc("Challenge objectives"), challengeObjectives, 1, 4500},
 }
 -- hogs
 local hero = {
@@ -79,7 +79,7 @@
 function onGameStart()
 	AnimWait(hero.gear, 3000)
 	FollowGear(hero.gear)
-	ShowMission(missionName, loc("Challenge Objectives"), challengeObjectives, -amSkip, 0)
+	ShowMission(missionName, loc("Challenge objectives"), challengeObjectives, -amSkip, 0)
 
 	AddEvent(onHeroDeath, {hero.gear}, heroDeath, {hero.gear}, 0)
 
@@ -158,10 +158,10 @@
 	-- DIALOG 01 - Start, game instructions
 	AddSkipFunction(dialog01, Skipanim, {dialog01})
 	table.insert(dialog01, {func = AnimWait, args = {hero.gear, 3200}})
-	table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("On the other side of the moon..."), 5000}})
-	table.insert(dialog01, {func = AnimSay, args = {runner.gear, loc("So you are interested in Professor Hogevil"), SAY_SAY, 3000}})
-	table.insert(dialog01, {func = AnimSay, args = {runner.gear, loc("We'll play a game first"), SAY_SAY, 3000}})
-	table.insert(dialog01, {func = AnimSay, args = {runner.gear, loc("I'll let you know whatever I know about him if you manage to catch me 3 times"), SAY_SAY, 4000}})
+	table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("On the other side of the moon ..."), 5000}})
+	table.insert(dialog01, {func = AnimSay, args = {runner.gear, loc("So you are interested in Professor Hogevil, huh?"), SAY_SAY, 3000}})
+	table.insert(dialog01, {func = AnimSay, args = {runner.gear, loc("We'll play a game first."), SAY_SAY, 3000}})
+	table.insert(dialog01, {func = AnimSay, args = {runner.gear, loc("I'll let you know whatever I know about him if you manage to catch me 3 times."), SAY_SAY, 4000}})
 	table.insert(dialog01, {func = AnimSay, args = {runner.gear, loc("Let's go!"), SAY_SAY, 2000}})
 	table.insert(dialog01, {func = moveRunner, args = {}})
 	-- DIALOG 02 - Hog Solo story
@@ -169,14 +169,14 @@
 	table.insert(dialog02, {func = AnimWait, args = {hero.gear, 3200}})
 	table.insert(dialog02, {func = AnimCaption, args = {hero.gear, loc("The truth about Professor Hogevil"), 5000}})
 	table.insert(dialog02, {func = AnimSay, args = {runner.gear, loc("Amazing! I was never beaten in a race before!"), SAY_SAY, 4000}})
-	table.insert(dialog02, {func = AnimSay, args = {runner.gear, loc("So, let me tell you what I know about Professor Hogevil..."), SAY_SAY, 4000}})
-	table.insert(dialog02, {func = AnimSay, args = {runner.gear, loc("Professor Hogevil, then known as James Hogus, worked for PAotH back in my time"), SAY_SAY, 4000}})
-	table.insert(dialog02, {func = AnimSay, args = {runner.gear, loc("He was the lab assistant of Dr. Goodhogan, the inventor of the anti-gravity device"), SAY_SAY, 5000}})
-	table.insert(dialog02, {func = AnimSay, args = {runner.gear, loc("During the final testing of the device an accident happened"), SAY_SAY, 5000}})
-	table.insert(dialog02, {func = AnimSay, args = {runner.gear, loc("In this accident Professor Hogevil lost all his spines on his head!"), SAY_SAY, 5000}})
-	table.insert(dialog02, {func = AnimSay, args = {runner.gear, loc("That's why he always wears a hat since then"), SAY_SAY, 4000}})
-	table.insert(dialog02, {func = AnimSay, args = {runner.gear, loc("After that incident he went underground and started working on his plan to steal the device"), SAY_SAY, 5000}})
-	table.insert(dialog02, {func = AnimSay, args = {runner.gear, loc("He is a very tough and very determined hedgehog. I would be extremely careful if I were you"), SAY_SAY, 5000}})
+	table.insert(dialog02, {func = AnimSay, args = {runner.gear, loc("So, let me tell you what I know about Professor Hogevil."), SAY_SAY, 4000}})
+	table.insert(dialog02, {func = AnimSay, args = {runner.gear, loc("Professor Hogevil, then known as James Hogus, worked for PAotH back in my time."), SAY_SAY, 4000}})
+	table.insert(dialog02, {func = AnimSay, args = {runner.gear, loc("He was the lab assistant of Dr. Goodhogan, the inventor of the anti-gravity device."), SAY_SAY, 5000}})
+	table.insert(dialog02, {func = AnimSay, args = {runner.gear, loc("During the final testing of the device an accident happened."), SAY_SAY, 5000}})
+	table.insert(dialog02, {func = AnimSay, args = {runner.gear, loc("In this accident, Professor Hogevil lost all his spines on his head!"), SAY_SAY, 5000}})
+	table.insert(dialog02, {func = AnimSay, args = {runner.gear, loc("That's why he always wears a hat since then."), SAY_SAY, 4000}})
+	table.insert(dialog02, {func = AnimSay, args = {runner.gear, loc("After that incident he went underground and started working on his plan to steal the device."), SAY_SAY, 5000}})
+	table.insert(dialog02, {func = AnimSay, args = {runner.gear, loc("He is a very tough and very determined hedgehog. I would be extremely careful if I were you."), SAY_SAY, 5000}})
 	table.insert(dialog02, {func = AnimSay, args = {runner.gear, loc("I should go now, goodbye!"), SAY_SAY, 3000}})
 	table.insert(dialog02, {func = win, args = {}})
 end
@@ -208,8 +208,8 @@
 		if currentPosition ~= 1 then
 			PlaySound(sndVictory)
 			if currentPosition > 1 and currentPosition < 4 then
-				AnimCaption(hero.gear, loc("Go get him again"), 3000)
-				AnimSay(runner.gear, loc("You got me"), SAY_SAY, 3000)
+				AnimCaption(hero.gear, loc("Go, get him again!"), 3000)
+				AnimSay(runner.gear, loc("You got me!"), SAY_SAY, 3000)
 			end
 			previousTimeLeft = TurnTimeLeft
 		end
@@ -221,18 +221,18 @@
 end
 
 function lose()
-	SendStat(siGameResult, loc("Too slow! Try again..."))
-	SendStat(siCustomAchievement, loc("You have to catch the other hog 3 times"))
-	SendStat(siCustomAchievement, loc("The time that you have left when you reach the blue hedgehog will be added to the next turn"))
-	SendStat(siCustomAchievement, loc("Each turn you'll have only one rope to use"))
-	SendStat(siCustomAchievement, loc("You'll lose if you die or if your time is up"))
+	SendStat(siGameResult, loc("Too slow! Try again ..."))
+	SendStat(siCustomAchievement, loc("You have to catch the other hog 3 times."))
+	SendStat(siCustomAchievement, loc("The time that you have left when you reach the blue hedgehog will be added to the next turn."))
+	SendStat(siCustomAchievement, loc("Each turn you'll have only one rope to use."))
+	SendStat(siCustomAchievement, loc("You'll lose if you die or if your time is up."))
 	SendStat(siPlayerKills,'0',teamA.name)
 	EndGame()
 end
 
 function win()
 	SendStat(siGameResult, loc("Congratulations, you are the fastest!"))
-	SendStat(siCustomAchievement, loc("You have managed to catch the blue hedgehog in time"))
+	SendStat(siCustomAchievement, loc("You have managed to catch the blue hedgehog in time."))
 	SendStat(siPlayerKills,'1',teamA.name)
 	EndGame()
 end
--- a/share/hedgewars/Data/Missions/Training/User_Mission_-_RCPlane_Challenge.lua	Tue Mar 29 22:36:59 2016 +0300
+++ b/share/hedgewars/Data/Missions/Training/User_Mission_-_RCPlane_Challenge.lua	Mon Apr 25 22:10:06 2016 +0300
@@ -487,4 +487,8 @@
 
 function onAmmoStoreInit()
 	SetAmmo(amRCPlane, 9, 0, 0, 0)
-end
\ No newline at end of file
+end
+
+function onNewTurn()
+ 	SetWeapon(amRCPlane)
+end
--- a/share/hedgewars/Data/Missions/Training/User_Mission_-_Rope_Knock_Challenge.lua	Tue Mar 29 22:36:59 2016 +0300
+++ b/share/hedgewars/Data/Missions/Training/User_Mission_-_Rope_Knock_Challenge.lua	Mon Apr 25 22:10:06 2016 +0300
@@ -4,6 +4,7 @@
 local missionWon = nil
 local endTimer = 1000
 local hogsKilled = 0
+local finishTime
 
 local HogData =	{
 					{"Bufon", 			"ShaggyYeti",false},
@@ -57,21 +58,33 @@
 				}
 
 function GenericEnd()
-	DismissTeam(loc("Wannabe Shoppsta"))
-	DismissTeam(loc("Unsuspecting Louts"))
-	DismissTeam(loc("Unlucky Sods"))
+	EndGame()
 end
 
 function GameOverMan()
 	missionWon = false
-	ShowMission(loc("ROPE-KNOCKING"), loc("MISSION FAILED"), loc("Oh no! Just try again!"), -amSkip, 0)
+	ShowMission(loc("Rope-knocking Challenge"), loc("Challenge over!"), loc("Oh no! Just try again!"), -amSkip, 0)
+	SendStat(siGameResult, loc("Challenge over!"))
+	local score = math.ceil((hogsKilled / 16)*6000)
+	SendStat(siCustomAchievement, string.format(loc("You have killed %d of 16 hedgehogs (+%d points)."), hogsKilled, score))
+	SendStat(siPointType, "points")
+	SendStat(siPlayerKills, tostring(score), loc("Wannabe Shoppsta"))
 	PlaySound(sndHellish)
 end
 
 function GG()
 	missionWon = true
-	ShowMission(loc("ROPE-KNOCKING"), loc("MISSION SUCCESS"), loc("Congratulations!") .. "|" .. loc("COMPLETION TIME") .. ": " .. (TurnTime - TurnTimeLeft) / 1000, 0, 0)
+	local completeTime = (TurnTime - finishTime) / 1000
+	ShowMission(loc("Rope-knocking Challenge"), loc("Challenge completed!"), loc("Congratulations!") .. "|" .. string.format(loc("Completion time: %.2fs"), completeTime), 0, 0)
 	PlaySound(sndHomerun)
+	SendStat(siGameResult, loc("Challenge completed!"))
+	local hogScore = math.ceil((hogsKilled / 16)*6000)
+	local timeScore = math.ceil((finishTime/TurnTime)*6000)
+	local score = hogScore + timeScore
+	SendStat(siCustomAchievement, string.format(loc("You have killed %d of 16 hedgehogs (+%d points)."), hogsKilled, hogScore))
+	SendStat(siCustomAchievement, string.format(loc("You have completed this challenge in %.2f s (+%d points)."), completeTime, timeScore))
+	SendStat(siPointType, "points")
+	SendStat(siPlayerKills, tostring(score), loc("Wannabe Shoppsta"))
 end
 
 function AssignCharacter(p)
@@ -114,16 +127,16 @@
 	MinesNum = 0
 	Explosives = 0
 
-	AddTeam(loc("Wannabe Shoppsta"), 1175851, "Simple", "Island", "Default", "Hedgewars")
+	AddTeam(loc("Wannabe Shoppsta"), 0x11F12B, "Simple", "Island", "Default", "cm_shoppa")
 	hhs[0] = AddHog(loc("Ace"), 0, 1, "Gasmask")
 	SetGearPosition(player, 1380, 1500)
 
-	AddTeam(loc("Unsuspecting Louts"), 14483456, "Simple", "Island", "Default", "Hedgewars")
+	AddTeam(loc("Unsuspecting Louts"), 0xDD0000, "Simple", "Island", "Default", "cm_face")
 	for i = 1, 8 do
 		hhs[i] = AddHog("generic", 0, 1, "NoHat")
 	end
 
-	AddTeam(loc("Unlucky Sods"), 14483456, "Simple", "Island", "Default", "Hedgewars")
+	AddTeam(loc("Unlucky Sods"), 0xDD0000, "Simple", "Island", "Default", "cm_balrog")
 	for i = 9, 16 do
 		hhs[i] = AddHog("generic", 0, 1, "NoHat")
 	end
@@ -133,14 +146,16 @@
 
 
 function onGameStart()
+	SendHealthStatsOff()
 
 	ShowMission     (
-                        loc("ROPE-KNOCKING"),
-                        loc("a Hedgewars challenge"),
+                        loc("Rope-knocking Challenge"),
+                        loc("Challenge"),
                         loc("Use the rope to knock your enemies to their doom.") .. "|" ..
+                        loc("Finish this challenge as fast as possible to earn bonus points."),
+                        -amRope, 4000)
 
-						"", -amRope, 4000
-					)
+	PlaceGirder(46,1783, 0)
 
 	SetGearPosition(hhs[0], 2419, 1769)
 	SetGearPosition(hhs[1], 3350, 570)
@@ -180,9 +195,9 @@
 		end
 
 		if missionWon == true then
-			AddCaption(loc("GG!"), 0xffba00ff,capgrpGameState)
+			AddCaption(loc("Victory!"), 0xFFFFFFFF,capgrpGameState)
 		else
-			AddCaption(loc("Ouch!"), 0xffba00ff,capgrpGameState)
+			AddCaption(loc("Challenge over!"), 0xFFFFFFFF,capgrpGameState)
 		end
 
 	end
@@ -191,16 +206,18 @@
 
 function onGearDamage(gear, damage)
 
-	if gear ~= hhs[0] then
+	if gear ~= hhs[0] and GetGearType(gear) == gtHedgehog then
 
 		AddVisualGear(GetX(gear), GetY(gear), vgtBigExplosion, 0, false)
 		DeleteGear(gear)
 		PlaySound(sndExplosion)
+		AddCaption(string.format(knockTaunt(), GetHogName(gear)), 0xFFFFFFFF, capgrpMessage)
 
 		hogsKilled = hogsKilled +1
 		if hogsKilled == 15 then
 			PlaySound(sndRideOfTheValkyries)
 		elseif hogsKilled == 16 then
+			finishTime = TurnTimeLeft
 			GG()
 		end
 
@@ -208,6 +225,37 @@
 
 end
 
+function knockTaunt()
+	local r = math.random(0,23)
+	local taunt
+	if r == 0 then taunt =		loc("%s has been knocked out.")
+	elseif r == 1 then taunt =	loc("%s hit the ground.")
+	elseif r == 2 then taunt =	loc("%s splatted.")
+	elseif r == 3 then taunt =	loc("%s was smashed.")
+	elseif r == 4 then taunt =	loc("%s felt unstable.")
+	elseif r == 5 then taunt =	loc("%s exploded.")
+	elseif r == 6 then taunt =	loc("%s fell from a high cliff.")
+	elseif r == 7 then taunt =	loc("%s goes the way of the lemming.")
+	elseif r == 8 then taunt =	loc("%s was knocked away.")
+	elseif r == 9 then taunt =	loc("%s was really unlucky.")
+	elseif r == 10 then taunt =	loc("%s felt victim to rope-knocking.")
+	elseif r == 11 then taunt =	loc("%s had no chance.")
+	elseif r == 12 then taunt =	loc("%s was a good target.")
+	elseif r == 13 then taunt =	loc("%s spawned at a really bad position.")
+	elseif r == 14 then taunt =	loc("%s was doomed from the beginning.")
+	elseif r == 15 then taunt =	loc("%s has fallen victim to gravity.")
+	elseif r == 16 then taunt =	loc("%s hates Newton.")		-- Isaac Newton
+	elseif r == 17 then taunt =	loc("%s had it coming.")
+	elseif r == 18 then taunt =	loc("%s is eliminated!")
+	elseif r == 19 then taunt =	loc("%s fell too fast.")
+	elseif r == 20 then taunt =	loc("%s flew like a rock.")
+	elseif r == 21 then taunt =	loc("%s stumpled.")
+	elseif r == 22 then taunt =	loc("%s was shoved away.")
+	elseif r == 23 then taunt =	loc("%s didn't expect that.")
+	end
+	return taunt
+end
+
 function onGearDelete(gear)
 
 	if (gear == hhs[0]) and (missionWon == nil) then
@@ -219,3 +267,7 @@
 function onAmmoStoreInit()
 	SetAmmo(amRope, 9, 0, 0, 0)
 end
+
+function onNewTurn()
+ 	SetWeapon(amRope)
+end
--- a/share/hedgewars/Data/Missions/Training/portal.lua	Tue Mar 29 22:36:59 2016 +0300
+++ b/share/hedgewars/Data/Missions/Training/portal.lua	Mon Apr 25 22:10:06 2016 +0300
@@ -2,13 +2,13 @@
 HedgewarsScriptLoad("/Scripts/Utils.lua")
 
 local MineArray = {}
-local player 
+local player
 local adviceGiven = false
 local adviceGiven2 = false
 
 function onGameInit()
 	Seed = 0 -- The base number for the random number generator
-	GameFlags = gfInfAttack +gfBorder +gfDisableWind +gfSolidLand 
+	GameFlags = gfInfAttack +gfBorder +gfDisableWind +gfSolidLand
 	TurnTime = 1500000 -- The time the player has to move each round (in ms)
 	CaseFreq = 0 -- The frequency of crate drops
 	MinesNum = 0 -- The number of mines being placed
@@ -16,32 +16,32 @@
 	Delay = 10 -- The delay between each round
 	Map = "portal" -- The map to be played
 	Theme = "Hell" -- The theme to be used
-	Goals = loc("Use the portal to move fast and far, use it to kill, use it with caution!")  --the goal ...
-	
-	
-----AddTeam(teamname, color, grave, fort, voicepack, flag)--
-	AddTeam(loc("Subject"), 14483406, "Simple", "Island", "Default", "cm_star")
-	player = AddHog(loc("player"), 0, 10, "Terminator_Glasses")
+	-- Disable Sudden Death
+	HealthDecrease = 0
+	WaterRise = 0
+
+	AddTeam(loc("Subjects"), 0xFFFF01, "Simple", "Island", "Default", "cm_test")
+	player = AddHog(loc("Subject 1"), 0, 10, "Terminator_Glasses")
 
-	AddTeam(loc("Hell Army"), 1170801, "Simple", "Island", "Default", "cm_galaxy")
-	enemy1 = AddHog(loc("Lucifer"), 1, 200, "thinkingcap")
-	enemy2 = AddHog(loc("voldemort"), 1, 150, "WizardHat")
-	enemy3 = AddHog(loc("zombi"), 1, 100, "zombi")
-	enemy4 = AddHog(loc("Predator"), 1, 14, "predator")
-	enemy5 = AddHog(loc("oneye"), 1, 50, "cyclops")
-	enemy6 = AddHog(loc("razac"), 1, 50, "plaguemask")
+	AddTeam(loc("Hell Army"), 0xFF0402, "skull", "Island", "Default", "cm_hellish")
+	enemy1 = AddHog(loc("Lucifer"), 1, 200, "InfernalHorns")
+	enemy2 = AddHog(loc("Voldemort"), 1, 150, "WizardHat")
+	enemy3 = AddHog(loc("Zombi"), 1, 100, "Zombi")
+	enemy4 = AddHog(loc("Predator"), 1, 14, "anzac")
+	enemy5 = AddHog(loc("Oneye"), 1, 50, "cyclops")
+	enemy6 = AddHog(loc("Razac"), 1, 50, "Evil")
 	enemy7 = AddHog(loc("C-2"), 1, 50, "cyborg1")
 	enemy8 = AddHog(loc("Rider"), 1, 50, "scif_SparkssHelmet")
 
-	AddTeam(loc("badmad"), 1170801, "Simple", "Island", "Default", "cm_jupiter")
+	AddTeam(loc("Badmad"), 0xFF0402, "skull", "Island", "Default", "cm_pentagram")
 	enemy9 = AddHog(loc("C-1"), 1, 50, "cyborg2")
-	enemy10 = AddHog(loc("hiden"), 1, 40, "daftpunkguymanuel")
-	enemy11 = AddHog(loc("ronald"), 1, 70, "clown")
-	enemy12 = AddHog(loc("phosphatoglucidique"), 1, 50, "chef")
-	enemy13 = AddHog(loc("Lestat"), 1, 30, "draculakz")
+	enemy10 = AddHog(loc("Hidden"), 1, 40, "bushhider")
+	enemy11 = AddHog(loc("Ronald"), 1, 70, "clown")
+	enemy12 = AddHog(loc("Phosphat"), 1, 50, "chef")
+	enemy13 = AddHog(loc("Lestat"), 1, 30, "vampirichog")
 
 	SetGearPosition(player, 350, 1820)
-    SetGearPosition(enemy1, 2037, 1313)
+	SetGearPosition(enemy1, 2037, 1313)
 	SetGearPosition(enemy2, 1369, 1605)
 	SetGearPosition(enemy3, 1750, 1937)
 	SetGearPosition(enemy4, 3125, 89)
@@ -55,8 +55,6 @@
 	SetGearPosition(enemy12, 2666, 950)
 	SetGearPosition(enemy13, 3306, 1205)
 
-
-
 end
 
 function onAmmoStoreInit()
@@ -80,11 +78,7 @@
 
 function onGameStart()
 
-	SetWind(100)-- SetWind(windSpeed) Sets the current wind in the range of -100 to 100. Use together with gfDisableWind for full control.
-                -- -100to0 is to the left, and 0to100 is to the right  (of course more its far from 0, more the speed is high
-				--  -100.............................0..................................+100
-				-- <<<<<<<<--<<--<<<<<<<<<<<<<--<<<<<|||-->>>>>>>>-->>>>>>>>>>>>>>>-->>>>>>          =  wind direction
-
+	SetWind(100)
 
 	MineArray[0] = AddGear(840, 1847, gtMine, 0, 0, 0, 0)
 	MineArray[1] = AddGear(900, 1847, gtMine, 0, 0, 0, 0)
@@ -124,16 +118,14 @@
 	MineArray[34] = AddGear(1311, 1785, gtMine, 0, 0, 0, 0)
 
 	MineArray[35] = AddGear(4029, 89, gtMine, 0, 0, 0, 120)
-	--MineArray[36] = AddGear(3376, 1947, gtMine, 0, 0, 0, 10)
 
-		for i = 0,#MineArray do
-			SetTimer(MineArray[i],050)
-			SetState(MineArray[i],544)
-		end
-				--needed this MineArray cause timer didn't work, its was always 3sec, i wanna instant mines
+	for i = 0,#MineArray do
+		SetTimer(MineArray[i],050)
+		SetState(MineArray[i],544)
+	end
+	--needed this MineArray cause timer didn't work, its was always 3sec, i wanna instant mines
 
-
-				--UTILITY CRATE--
+	--UTILITY CRATE--
 	parachute = SpawnUtilityCrate(1670, 1165, amParachute)
 	girder = SpawnUtilityCrate(2101, 1297, amGirder)
 	SpawnUtilityCrate(3965, 625, amBlowTorch)
@@ -144,9 +136,9 @@
 	SpawnUtilityCrate(130, 600, amPickHammer)
 	SpawnUtilityCrate(1660,1820, amLaserSight)
 	SpawnUtilityCrate(4070,1840, amLaserSight)
-	
-	
-				--AMMO CRATE--
+
+
+	--AMMO CRATE--
 	portalgun = SpawnAmmoCrate(505, 1943, amPortalGun, 1000)
 	extratime = SpawnAmmoCrate(4020, 785, amExtraTime, 2)
 	SpawnAmmoCrate(425, 613, amSnowball)
@@ -159,77 +151,55 @@
 	SpawnAmmoCrate(2900, 1400, amRope)
 	SpawnAmmoCrate(4025, 1117, amFirePunch)
 
-	
-				--HEALTH CRATE--
+	--HEALTH CRATE--
 	SpawnHealthCrate(2000, 780)
-	
-				--GIRDER--
+
+	--GIRDER--
 	PlaceGirder(3363, 1323, 4)
 
-
-	ShowMission (loc("Portal mission"), loc("training"), "", -amPortalGun, 5000)
-	HogSay(player, loc("I should get myself a portal gun, maybe this crate has one"), SAY_THINK)
-	
-
-
+	ShowMission (loc("Portal Mind Challenge"), loc("Mission"),
+		loc("Defeat all enemies!") .. "|" .. loc("In this mission you have infinite time."),
+		-amPortalGun, 5000)
+	HogSay(player, loc("I should get myself a portal device, maybe this crate has one."), SAY_THINK)
 
 end
 
 function onGameTick()
 
-    if (player ~= nil)  then
+	if (player ~= nil)  then
 		if (gearIsInBox(player, 1650, 1907, 200, 60) and (adviceGiven == false)) then
 			adviceGiven = true
-				HogSay(player, loc("Hmmm, I'll have to find some way of moving him off this anti-portal surface..."), SAY_THINK)
+			HogSay(player, loc("Hmmm, I’ll have to find some way of moving him off this anti-portal surface."), SAY_THINK)
 		elseif (gearIsInBox(player, 2960, 790, 200, 60) and (adviceGiven2 == false)) then
 			adviceGiven2 = true
-				HogSay(player, loc("The anti-portal zone is all over the floor, and I have nothing to kill him...Droping something could hurt him enough to kill him..."), SAY_THINK)
- end
- end
-	
+			HogSay(player, loc("The anti-portal surface is all over the floor, and I have nothing to kill him. Dropping something could hurt him enough to kill him."), SAY_THINK)
+		end
 	end
-	
-
 
-
-
-function onNewturn()
-end
-
-
-function onGearAdd(gear)
 end
 
 function onGearDelete(gear)
+	-- Check gear collection
+	if CurrentHedgehog == player and (band(GetGearMessage(gear), gmDestroy) ~= 0) then
+		if gear == portalgun then
+			HogSay(player, loc("Great! Let’s kill all these enemies, using portals."), SAY_THINK)
+		end
 
-	if gear == portalgun then
-		--AddAmmo(player, amPortalGun, 10000)
-		HogSay(player, loc("GREAT ! Let's kill all this enemies, using portals"), SAY_THINK)
+		if gear == girder then
+			HogSay(player, loc("This will be useful when I need a new platform or if I want to rise."), SAY_THINK)
+		end
+
+		if gear == parachute then
+			HogSay(player, loc("You can’t open a portal on the blue surface."), SAY_THINK)
+		end
+
+		if gear == extratime then
+			HogSay(player, loc("What?! For all this struggle I just win some ... time? Oh dear!"), SAY_SHOUT)
+		end
 	end
 
-	if gear == girder then 
-		HogSay(player, loc("Will be useful if I need a new plateform or if I want to rise...."), SAY_THINK)
-	end
-	
-	if gear == parachute then
-		HogSay(player, loc("You can't fire a portal on the blue surface"), SAY_THINK)
+	if gear == player then
+		player = nil
 	end
---if you wanted to check for collection only
---you could probably say
---if (gear == myParachuteGear) and (band(GetGearMessage(gear), gmDestroy) ~= 0) then
-
-	if gear == extratime then
-		HogSay(player, loc(" What !! For all of this struggle i just win some ... TIME o0"), SAY_SHOUT)
-	end
-
-	
-	if gear == player then
-        player = nil
-    end
 end
 
-
-
-
-
-
--- a/share/hedgewars/Data/Scripts/Multiplayer/HedgeEditor.lua	Tue Mar 29 22:36:59 2016 +0300
+++ b/share/hedgewars/Data/Scripts/Multiplayer/HedgeEditor.lua	Mon Apr 25 22:10:06 2016 +0300
@@ -279,6 +279,9 @@
 -- HEDGE EDITOR, SCRIPT BEGINS (Hey yo, it's about time)
 ---------------------------------------------------------
 
+-- Tell other scripts that we exist
+HedgeEditor = true
+
 HedgewarsScriptLoad("/Scripts/Locale.lua")
 HedgewarsScriptLoad("/Scripts/Tracker.lua")
 HedgewarsScriptLoad("/Scripts/Params.lua")
@@ -830,12 +833,14 @@
  "sprKnife", "sprStar", "sprIceTexture", "sprIceGun", "sprFrozenHog", "sprAmRubber", "sprBoing"}
 
  local reducedSpriteIDArray = {
-  sprBigDigit, sprTarget, sprKowtow, sprBee, sprAmGirder, sprExplosion50, sprGirder,sprCustom1,sprCustom2
-  }
-
-  local reducedSpriteTextArray = {
-  "sprBigDigit", "sprTarget", "sprKowtow", "sprBee", "sprAmGirder", "sprExplosion50", "sprGirder","sprCustom1","sprCustom2"
-  }
+  sprAmRubber, sprAmGirder, sprAMSlot, sprAMAmmos, sprAMAmmosBW, sprAMCorners, sprHHTelepMask, sprTurnsLeft,
+  sprSpeechCorner, sprSpeechEdge, sprSpeechTail, sprThoughtCorner, sprThoughtEdge, sprThoughtTail, sprShoutCorner,
+  sprShoutEdge, sprShoutTail, sprBotlevels, sprIceTexture, sprCustom1, sprCustom2, }
+
+ local reducedSpriteTextArray = {
+  "sprAmRubber", "sprAmGirder", "sprAMSlot", "sprAMAmmos", "sprAMAmmosBW", "sprAMCorners", "sprHHTelepMask", "sprTurnsLeft",
+  "sprSpeechCorner", "sprSpeechEdge", "sprSpeechTail", "sprThoughtCorner", "sprThoughtEdge", "sprThoughtTail", "sprShoutCorner",
+  "sprShoutEdge", "sprShoutTail", "sprBotlevels", "sprIceTexture", "sprCustom1", "sprCustom2", }
 
 ----------------------------
 -- placement shite
@@ -1637,10 +1642,16 @@
 	elseif cat[cIndex] == loc("Health Modification Mode") then
 
 		sGear = GetClosestGear()
-		if (sGear ~= nil) and (GetGearType(sGear) == gtHedgehog) then
-			SetHealth(sGear, pMode[pIndex])
+		local gt = GetGearType(sGear)
+		if gt == gtHedgehog or gt == gtExplosives or (gt == gtCase and GetGearPos(sGear) == 0x2) then
+			if pMode[pIndex][2] == "set" then
+				SetHealth(sGear, pMode[pIndex][1])
+			elseif pMode[pIndex][2] == "mod" then
+				local newHealth = math.max(1, GetHealth(sGear) + tonumber(pMode[pIndex][1]))
+				SetHealth(sGear, newHealth)
+			end
 		else
-			AddCaption(loc("Please click on a hedgehog."),0xffba00ff,capgrpVolume)
+			AddCaption(loc("Please click on a hedgehog, barrel or health crate."),0xffba00ff,capgrpVolume)
 		end
 
 	elseif cat[cIndex] == loc("Sprite Modification Mode") then
@@ -1759,7 +1770,7 @@
 	elseif cat[cIndex] == loc("Cleaver Placement Mode") then
 		pMode = {loc("Standard Cleaver")}
 	elseif cat[cIndex] == loc("Barrel Placement Mode") then
-		pMode = {1,50,75,100}
+		pMode = {1,50,60,75,100,120}
 	elseif cat[cIndex] == loc("Health Crate Placement Mode") then
 		pMode = {25,50,75,100}
 	elseif cat[cIndex] == loc("Weapon Crate Placement Mode") then
@@ -1786,7 +1797,8 @@
 	elseif cat[cIndex] == loc("Team Identity Mode") then
 		pMode = {"Clowns","Street Fighters","Cybernetic Empire","Color Squad","Fruit","The Police","The Ninja-Samurai Alliance","Pokemon","The Zoo","The Devs","Mushroom Kingdom","Pirates","Gangsters","Twenty-Twenty","Monsters","The Iron Curtain","The Hospital"}
 	elseif cat[cIndex] == loc("Health Modification Mode") then
-		pMode = {1, 25, 30, 50, 75, 100, 120, 150, 200, 1000}
+		pMode = { {1, "set"}, {25, "set"}, {30, "set"}, {50, "set"}, {75, "set"}, {100, "set"}, {120, "set"}, {150, "set"}, {200, "set"}, {1000, "set"},
+			{"+1", "mod"}, {"+10", "mod"}, {"+100", "mod"}, {"-1", "mod"}, {"-10", "mod"}, {"-100", "mod"} } 
 	elseif cat[cIndex] == loc("Sprite Modification Mode") then
 		--pMode = {"Sprite Selection Mode","LandFlag Modification Mode","Sprite Erasure Mode"}
 		pMode = {loc("LandFlag Modification Mode"),loc("Sprite Erasure Mode")}
@@ -3180,7 +3192,7 @@
 
 		ShowMission	(
 				loc("HEALTH MODIFICATION MODE"),
-				loc("Use this mode to set the health of hogs."),
+				loc("Use this mode to set the health of hogs, health crates and barrels."),
 				loc("Set Health: [Left Click]") .. "|" ..
 				loc("[Left], [Right]: Change health value.") .. "|" ..
 				" " .. "|" ..
@@ -3324,7 +3336,13 @@
 			-- update display selection criteria
 			if (curWep == amGirder) or (curWep == amRubber) or (curWep == amAirAttack) then
 				AddCaption(cat[cIndex],0xffba00ff,capgrpMessage)
-				AddCaption(pMode[pIndex],0xffba00ff,capgrpMessage2)
+				local caption2
+				if type(pMode[pIndex]) == "table" then
+					caption2 = tostring(pMode[pIndex][1])
+				else
+					caption2 = tostring(pMode[pIndex])
+				end
+				AddCaption(caption2,0xffba00ff,capgrpMessage2)
 				if superDelete == true then
 					AddCaption(loc("Warning: Deletition Mode Active"),0xffba00ff,capgrpAmmoinfo)
 				end
--- a/share/hedgewars/Data/Scripts/Multiplayer/Racer.lua	Tue Mar 29 22:36:59 2016 +0300
+++ b/share/hedgewars/Data/Scripts/Multiplayer/Racer.lua	Mon Apr 25 22:10:06 2016 +0300
@@ -1,6 +1,6 @@
 
 ------------------------------------------
--- RACER 0.6
+-- RACER 0.8
 -- map-independant racing script
 -- by mikade
 -----------------------------------------
@@ -73,6 +73,11 @@
 
 -- switch to first available weapon if starting race with no weapon selected
 
+-------
+-- 0.8
+-------
+-- allow different boost directions
+
 -----------------------------
 -- SCRIPT BEGINS
 -----------------------------
@@ -151,6 +156,10 @@
 local lastRound
 local RoundHasChanged
 
+local boostX = 0
+local boostY = 0
+local boostValue = 1
+
 -------------------
 -- general methods
 -------------------
@@ -224,6 +233,31 @@
 -- RACER METHODS
 -----------------
 
+function onLeft()
+	boostX = boostX +boostValue
+end
+function onLeftUp()
+	boostX = boostX -boostValue
+end
+function onRight()
+	boostX = boostX -boostValue
+end
+function onRightUp()
+	boostX = boostX +boostValue
+end
+function onUp()
+	boostY = boostY +boostValue
+end
+function onUpUp()
+	boostY = boostY -boostValue
+end
+function onDown()
+	boostY = boostY -boostValue
+end
+function onDownUp()
+	boostY = boostY +boostValue
+end
+
 function CheckWaypoints()
 
         trackFinished = true
@@ -658,7 +692,7 @@
                                 trackTime = 0
 
                                 SetGearPosition(CurrentHedgehog, wpX[0], wpY[0])
-                                AddGear(GetX(CurrentHedgehog), GetY(CurrentHedgehog), gtGrenade, 0, 0, 0, 1)
+                                AddGear(GetX(CurrentHedgehog)+boostX, GetY(CurrentHedgehog)+boostY, gtGrenade, 0, 0, 0, 1)
                                 FollowGear(CurrentHedgehog)
 
                                 HideMission()
--- a/share/hedgewars/Data/Scripts/TechMaps.lua	Tue Mar 29 22:36:59 2016 +0300
+++ b/share/hedgewars/Data/Scripts/TechMaps.lua	Mon Apr 25 22:10:06 2016 +0300
@@ -88,6 +88,9 @@
 end
 
 function onPreviewInit()
+	if HedgeEditor == true then
+		return
+	end
 
 	if mapID == nil then
 		mapID = 2 + GetRandom(7)