Merge
authorWolfgang Steffens <WolfgangSteff@gmail.com>
Mon, 25 Jun 2012 10:44:27 +0200
changeset 7288 5d0704f23a2a
parent 7188 580cd247511e (current diff)
parent 7285 a9016b157535 (diff)
child 7291 ad4b6c2b09e8
Merge
hedgewars/options.inc
hedgewars/uGearsRender.pas
hedgewars/uTypes.pas
hedgewars/uVariables.pas
hedgewars/uWorld.pas
share/hedgewars/Data/Scripts/plist/Balanced Random Weapon.plist
share/hedgewars/Data/Scripts/plist/Capture the Flag.plist
share/hedgewars/Data/Scripts/plist/Highlander.plist
share/hedgewars/Data/Scripts/plist/No Jumping.plist
share/hedgewars/Data/Scripts/plist/Normal.plist
share/hedgewars/Data/Scripts/plist/Racer.plist
share/hedgewars/Data/Scripts/plist/Random Weapon.plist
share/hedgewars/Data/Scripts/plist/Space Invasion.plist
share/hedgewars/Data/Scripts/plist/The Specialists.plist
share/hedgewars/Data/Scripts/plist/Tumbler.plist
--- a/CMakeLists.txt	Tue Jun 05 22:37:36 2012 +0200
+++ b/CMakeLists.txt	Mon Jun 25 10:44:27 2012 +0200
@@ -4,9 +4,9 @@
 #initialise cmake environment
 cmake_minimum_required(VERSION 2.6.0 FATAL_ERROR)
 FOREACH(policy CMP0003 CMP0012)
-	IF(POLICY ${policy})
-		CMAKE_POLICY(SET ${policy} NEW)
-	ENDIF()
+    IF(POLICY ${policy})
+        CMAKE_POLICY(SET ${policy} NEW)
+    ENDIF()
 ENDFOREACH()
 set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules)
 
@@ -15,26 +15,26 @@
 set(version_suffix "-dev") #UNSET THIS VARIABLE AT RELEASE TIME
 set(HGCHANGED "")
 IF(version_suffix MATCHES "-dev")
-	set(HW_DEV true)
-	IF (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.hg)
-		FIND_PROGRAM(HGCOMMAND hg)
-		IF(HGCOMMAND)
-			exec_program(${HGCOMMAND}
-				     ARGS identify -in ${CMAKE_CURRENT_SOURCE_DIR}
-				     OUTPUT_VARIABLE version_suffix
-				     )
-			STRING(REGEX REPLACE "[^+]" "" HGCHANGED ${version_suffix})
-			STRING(REGEX REPLACE "([0-9a-zA-Z]+)(.*) ([0-9]+)(.*)" "\\3-\\1" version_suffix ${version_suffix})
-			IF (HGCHANGED)
-				MESSAGE(STATUS "Building revision ${version_suffix} (SOURCE CODE MODIFIED)")
-			ELSE()
-				MESSAGE(STATUS "Building revision ${version_suffix}")
-			ENDIF()
-			set(version_suffix "-${version_suffix}")
-		ENDIF()
-	ENDIF()
+    set(HW_DEV true)
+    IF (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.hg)
+        FIND_PROGRAM(HGCOMMAND hg)
+        IF(HGCOMMAND)
+            exec_program(${HGCOMMAND}
+                     ARGS identify -in ${CMAKE_CURRENT_SOURCE_DIR}
+                     OUTPUT_VARIABLE version_suffix
+                     )
+            STRING(REGEX REPLACE "[^+]" "" HGCHANGED ${version_suffix})
+            STRING(REGEX REPLACE "([0-9a-zA-Z]+)(.*) ([0-9]+)(.*)" "\\3-\\1" version_suffix ${version_suffix})
+            IF (HGCHANGED)
+                MESSAGE(STATUS "Building revision ${version_suffix} (SOURCE CODE MODIFIED)")
+            ELSE()
+                MESSAGE(STATUS "Building revision ${version_suffix}")
+            ENDIF()
+            set(version_suffix "-${version_suffix}")
+        ENDIF()
+    ENDIF()
 ELSE()
-	set(HW_DEV false)
+    set(HW_DEV false)
 ENDIF()
 
 
@@ -47,108 +47,107 @@
 
 
 #set some safe values
-IF(NOT WITH_SERVER)
-	SET(WITH_SERVER 0)
-ENDIF(NOT WITH_SERVER)
 IF(NOT BUILD_ENGINE_LIBRARY)
-	SET(BUILD_ENGINE_LIBRARY 0)
+    SET(BUILD_ENGINE_LIBRARY 0)
 ENDIF(NOT BUILD_ENGINE_LIBRARY)
 set(target_dir "bin")
 
-
 #bundle .app setup
-if(APPLE)
-	set(CMAKE_FIND_FRAMEWORK "FIRST")
+if(APPLE OR CROSSAPPLE)
+    #paths for creating the bundle
+    set(bundle_name Hedgewars.app)
+    set(frameworks_dir ${bundle_name}/Contents/Frameworks/)
+    set(CMAKE_INSTALL_PREFIX ${bundle_name}/Contents/MacOS/)
+    set(DATA_INSTALL_DIR "../Resources/")
+    set(target_dir ".")
+    set(minimum_macosx_version "10.6")
+endif()
 
-	#paths for creating the bundle
-	set(bundle_name Hedgewars.app)
-	set(frameworks_dir ${bundle_name}/Contents/Frameworks/)
-	set(CMAKE_INSTALL_PREFIX ${bundle_name}/Contents/MacOS/)
-	set(DATA_INSTALL_DIR "../Resources/")
-	set(target_dir ".")
+if(APPLE)
+    set(CMAKE_FIND_FRAMEWORK "FIRST")
 
-	#what system are we building for
-	set(minimum_macosx_version $ENV{MACOSX_DEPLOYMENT_TARGET})
+    #what system are we building for
+    set(minimum_macosx_version $ENV{MACOSX_DEPLOYMENT_TARGET})
 
-	#detect on which system we are: if sw_vers cannot be found for any reason (re)use minimum_macosx_version
-	find_program(sw_vers sw_vers)
-	if(sw_vers)
-		exec_program(${sw_vers} ARGS "-productVersion" OUTPUT_VARIABLE current_macosx_version)
-		string(REGEX REPLACE "([0-9]+.[0-9]+).[0-9]+" "\\1" current_macosx_version ${current_macosx_version})
+    #detect on which system we are: if sw_vers cannot be found for any reason (re)use minimum_macosx_version
+    find_program(sw_vers sw_vers)
+    if(sw_vers)
+        exec_program(${sw_vers} ARGS "-productVersion" OUTPUT_VARIABLE current_macosx_version)
+        string(REGEX REPLACE "([0-9]+.[0-9]+).[0-9]+" "\\1" current_macosx_version ${current_macosx_version})
+        else()
+        if(NOT minimum_macosx_version)
+            message(FATAL_ERROR "sw_vers not found! Need explicit MACOSX_DEPLOYMENT_TARGET variable set")
         else()
-		if(NOT minimum_macosx_version)
-			message(FATAL_ERROR "sw_vers not found! Need explicit MACOSX_DEPLOYMENT_TARGET variable set")
-		else()
-			set(current_macosx_version ${minimum_macosx_version})
-		endif()
-	endif()
+            set(current_macosx_version ${minimum_macosx_version})
+        endif()
+    endif()
 
-	#if nothing is set, we deploy only for the current system
-	if(NOT minimum_macosx_version)
-		set(minimum_macosx_version ${current_macosx_version})
-	endif()
+    #if nothing is set, we deploy only for the current system
+    if(NOT minimum_macosx_version)
+        set(minimum_macosx_version ${current_macosx_version})
+    endif()
 
-	#lower systems don't have enough processing power anyways
-	if (minimum_macosx_version LESS "10.4")
-		message(FATAL_ERROR "Hedgewars is not supported on Mac OS X pre-10.4")
-	endif()
+    #lower systems don't have enough processing power anyways
+    if (minimum_macosx_version LESS "10.4")
+        message(FATAL_ERROR "Hedgewars is not supported on Mac OS X pre-10.4")
+    endif()
 
-	#workaround for http://playcontrol.net/ewing/jibberjabber/big_behind-the-scenes_chang.html#SDL_mixer (Update 2)
-	if(current_macosx_version MATCHES "10.4")
-		find_package(SDL_mixer REQUIRED)
-		set(DYLIB_SMPEG "-dylib_file @loader_path/Frameworks/smpeg.framework/Versions/A/smpeg:${SDLMIXER_LIBRARY}/Versions/A/Frameworks/smpeg.framework/Versions/A/smpeg")
-		set(DYLIB_MIKMOD "-dylib_file @loader_path/Frameworks/mikmod.framework/Versions/A/mikmod:${SDLMIXER_LIBRARY}/Versions/A/Frameworks/mikmod.framework/Versions/A/mikmod")
-		set(pascal_flags "-k${DYLIB_SMPEG}" "-k${DYLIB_MIKMOD}" ${pascal_flags})
-		set(CMAKE_C_FLAGS "${DYLIB_SMPEG}" "${DYLIB_MIKMOD}" ${CMAKE_C_FLAGS})
-	endif()
+    #workaround for http://playcontrol.net/ewing/jibberjabber/big_behind-the-scenes_chang.html#SDL_mixer (Update 2)
+    if(current_macosx_version MATCHES "10.4")
+        find_package(SDL_mixer REQUIRED)
+        set(DYLIB_SMPEG "-dylib_file @loader_path/Frameworks/smpeg.framework/Versions/A/smpeg:${SDLMIXER_LIBRARY}/Versions/A/Frameworks/smpeg.framework/Versions/A/smpeg")
+        set(DYLIB_MIKMOD "-dylib_file @loader_path/Frameworks/mikmod.framework/Versions/A/mikmod:${SDLMIXER_LIBRARY}/Versions/A/Frameworks/mikmod.framework/Versions/A/mikmod")
+        set(pascal_flags "-k${DYLIB_SMPEG}" "-k${DYLIB_MIKMOD}" ${pascal_flags})
+        set(CMAKE_C_FLAGS "${DYLIB_SMPEG}" "${DYLIB_MIKMOD}" ${CMAKE_C_FLAGS})
+    endif()
 
-	#CMAKE_OSX_ARCHITECTURES and CMAKE_OSX_SYSROOT need to be set for universal binary and correct linking
-	if(NOT CMAKE_OSX_ARCHITECTURES)
-		if(current_macosx_version LESS "10.6")
-			if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "powerpc*")
-				set(CMAKE_OSX_ARCHITECTURES "ppc7400")
-			else()
-				set(CMAKE_OSX_ARCHITECTURES "i386")
-			endif()
-		else()
-			set(CMAKE_OSX_ARCHITECTURES "x86_64")
-		endif()
-	endif()
+    #CMAKE_OSX_ARCHITECTURES and CMAKE_OSX_SYSROOT need to be set for universal binary and correct linking
+    if(NOT CMAKE_OSX_ARCHITECTURES)
+        if(current_macosx_version LESS "10.6")
+            if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "powerpc*")
+                set(CMAKE_OSX_ARCHITECTURES "ppc7400")
+            else()
+                set(CMAKE_OSX_ARCHITECTURES "i386")
+            endif()
+        else()
+            set(CMAKE_OSX_ARCHITECTURES "x86_64")
+        endif()
+    endif()
 
-	#CMAKE_OSX_SYSROOT is set at the system version we are supposed to build on
-	#we need to provide the correct one when host and target differ
-	if(NOT ${minimum_macosx_version} MATCHES ${current_macosx_version})
-		if(minimum_macosx_version MATCHES "10.4")
-			set(CMAKE_OSX_SYSROOT "/Developer/SDKs/MacOSX10.4u.sdk/")
-			set(CMAKE_C_COMPILER "gcc-4.0")
-			set(CMAKE_CXX_COMPILER "g++-4.0")
-		else()
-			string(REGEX REPLACE "([0-9]+.[0-9]+).[0-9]+" "\\1" sdk_version ${minimum_macosx_version})
-			set(CMAKE_OSX_SYSROOT "/Developer/SDKs/MacOSX${sdk_version}.sdk/")
-		endif()
-	endif()
+    #CMAKE_OSX_SYSROOT is set at the system version we are supposed to build on
+    #we need to provide the correct one when host and target differ
+    if(NOT ${minimum_macosx_version} MATCHES ${current_macosx_version})
+        if(minimum_macosx_version MATCHES "10.4")
+            set(CMAKE_OSX_SYSROOT "/Developer/SDKs/MacOSX10.4u.sdk/")
+            set(CMAKE_C_COMPILER "gcc-4.0")
+            set(CMAKE_CXX_COMPILER "g++-4.0")
+        else()
+            string(REGEX REPLACE "([0-9]+.[0-9]+).[0-9]+" "\\1" sdk_version ${minimum_macosx_version})
+            set(CMAKE_OSX_SYSROOT "/Developer/SDKs/MacOSX${sdk_version}.sdk/")
+        endif()
+    endif()
 
-	#add user framework directory, other paths can be passed via FPFLAGS
-	set(pascal_flags "-Ff~/Library/Frameworks" ${pascal_flags})
-	#set deployment target
-	set(pascal_flags "-k-macosx_version_min" "-k${minimum_macosx_version}" "-XR${CMAKE_OSX_SYSROOT}" ${pascal_flags})
+    #add user framework directory, other paths can be passed via FPFLAGS
+    set(pascal_flags "-Ff~/Library/Frameworks" ${pascal_flags})
+    #set deployment target
+    set(pascal_flags "-k-macosx_version_min" "-k${minimum_macosx_version}" "-XR${CMAKE_OSX_SYSROOT}" ${pascal_flags})
 
-	message(STATUS "Build system: Mac OS X ${current_macosx_version} with GCC:${CMAKE_C_COMPILER}")
-	message(STATUS "Target system: Mac OS X ${minimum_macosx_version} for architecture(s):${CMAKE_OSX_ARCHITECTURES}")
+    message(STATUS "Build system: Mac OS X ${current_macosx_version} with GCC:${CMAKE_C_COMPILER}")
+    message(STATUS "Target system: Mac OS X ${minimum_macosx_version} for architecture(s):${CMAKE_OSX_ARCHITECTURES}")
 endif(APPLE)
 
 
 #build Debug only when explicitally set
 if (NOT CMAKE_BUILD_TYPE)
-	set (CMAKE_BUILD_TYPE RELEASE CACHE STRING "Choose the type of build, options are: Debug Release." FORCE)
+    set (CMAKE_BUILD_TYPE RELEASE CACHE STRING "Choose the type of build, options are: Debug Release." FORCE)
 endif (NOT CMAKE_BUILD_TYPE)
 
 if(CMAKE_BUILD_TYPE MATCHES DEBUG OR CMAKE_BUILD_TYPE MATCHES "Debug" OR CMAKE_BUILD_TYPE MATCHES "debug")
-	message(STATUS "Building Debug")
-	set(Optz false)
+    message(STATUS "Building Debug")
+    set(Optz false)
 else()
-	message(STATUS "Building Release")
-	set(Optz true)
+    message(STATUS "Building Release")
+    set(Optz true)
 endif()
 
 
@@ -161,66 +160,76 @@
 set(CMAKE_CXX_FLAGS_DEBUG ${CMAKE_C_FLAGS_DEBUG})
 
 separate_arguments(fpflags_full UNIX_COMMAND ${FPFLAGS})
-set(pascal_flags ${fpflags_full} "-B" "-FE../bin" "-Cs2000000" "-vewn" ${pascal_flags})
+set(pascal_flags ${fpflags_full} "-B" "-FE../bin" "-Cs2000000" "-vewn" "-dDEBUGFILE" ${pascal_flags})
 separate_arguments(ghflags_full UNIX_COMMAND ${GHFLAGS})
 set(haskell_flags "-O2" ${haskell_flags} ${ghflags_full})
 
 if(Optz)
-#	set(pascal_flags "-O3" "-OpPENTIUM4" "-CfSSE3" "-Xs" "-Si" ${pascal_flags})
-	set(pascal_flags "-Os" "-Ooregvar" "-Xs" "-Si" ${pascal_flags})
-	set(haskell_flags "-w" "-fno-warn-unused-do-bind" ${haskell_flags})
+#    set(pascal_flags "-O3" "-OpPENTIUM4" "-CfSSE3" "-Xs" "-Si" ${pascal_flags})
+    set(pascal_flags "-Os" "-Ooregvar" "-Xs" "-Si" ${pascal_flags})
+    set(haskell_flags "-w" "-fno-warn-unused-do-bind" ${haskell_flags})
 else(Optz)
-	set(pascal_flags "-O-" "-g" "-gl" "-gv" "-Ct" "-dDEBUGFILE" ${pascal_flags})
-	set(haskell_flags "-Wall" "-debug" "-dcore-lint" "-fno-warn-unused-do-bind" ${haskell_flags})
+    set(pascal_flags "-O-" "-g" "-gl" "-gv" "-Ct" ${pascal_flags})
+    set(haskell_flags "-Wall" "-debug" "-dcore-lint" "-fno-warn-unused-do-bind" ${haskell_flags})
 endif(Optz)
 
 
 if(DEFINED DATA_INSTALL_DIR)
-	set(SHAREPATH ${DATA_INSTALL_DIR}/hedgewars/)
+    set(SHAREPATH ${DATA_INSTALL_DIR}/hedgewars/)
 else()
-	set(SHAREPATH share/hedgewars/)
+    set(SHAREPATH share/hedgewars/)
 endif()
 set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
 
 
-if(WITH_SERVER)
-	if(GHC)
-		set(ghc_executable ${GHC})
-	else()
-		find_program(ghc_executable ghc)
-	endif()
+if(NOT NOSERVER)
+    if(GHC)
+        set(ghc_executable ${GHC})
+    else()
+        find_program(ghc_executable ghc)
+    endif()
 
-	if(ghc_executable)
-		set(HAVE_NETSERVER true)
-		add_subdirectory(gameServer)
-	else()
-		message(STATUS "No GHC executable found, server will *not* be built")
-		set(HAVE_NETSERVER false)
-	endif()
-else(WITH_SERVER)
-	set(HAVE_NETSERVER false)
-endif(WITH_SERVER)
+    if(ghc_executable)
+        set(HAVE_NETSERVER true)
+        add_subdirectory(gameServer)
+    else()
+        message(STATUS "No GHC executable found, server will not be built")
+        set(HAVE_NETSERVER false)
+    endif()
+else()
+    message(STATUS "Server will not be built per user request")
+    set(HAVE_NETSERVER false)
+endif()
 
 find_package(Lua)
-if(NOT ${LUA_FOUND})
-        message(STATUS "Lua library not found, building bundled dependency")
-	add_subdirectory(misc/liblua)
-	#link with liblua.a (which requires system readline)
-	set(pascal_flags "-k${CMAKE_BINARY_DIR}/bin/liblua.a" "-k-lreadline" ${pascal_flags})
+if(LUA_FOUND)
+    message(STATUS "Lua library is present on your system (${LUA_DEFAULT})")
+else()
+    message(STATUS "Lua library not found, building bundled dependency")
+    add_subdirectory(misc/liblua)
+    #linking with liblua.a requires system readline -- this works everywhere, right?
+    if(WIN32)
+        set(pascal_flags "-k${CMAKE_BINARY_DIR}/bin/liblua.dll.a" "-k-lreadline" ${pascal_flags})
+    else()
+        set(pascal_flags "-k${CMAKE_BINARY_DIR}/bin/liblua.a" "-k-lreadline" ${pascal_flags})
+    endif()
 endif()
+
 add_subdirectory(hedgewars)
 
+
 #run cmake -DANDROID=1 to enable this
 if(ANDROID)
-	add_subdirectory(project_files/Android-build)
+    add_subdirectory(project_files/Android-build)
 endif()
 
+
 if(NOT (BUILD_ENGINE_LIBRARY OR ANDROID))
-	add_subdirectory(bin)
-	add_subdirectory(misc/quazip)
-	add_subdirectory(QTfrontend)
-	add_subdirectory(share)
-	add_subdirectory(tools)
+    add_subdirectory(bin)
+    add_subdirectory(misc/quazip)
+    add_subdirectory(QTfrontend)
+    add_subdirectory(share)
+    add_subdirectory(tools)
 endif()
 
 
@@ -235,74 +244,74 @@
 set(CPACK_PACKAGE_INSTALL_DIRECTORY "Hedgewars ${HEDGEWARS_VERSION}")
 
 if(WIN32 AND NOT UNIX)
-	set(CPACK_NSIS_DISPLAY_NAME "Hedgewars")
-	set(CPACK_NSIS_HELP_LINK "http://www.hedgewars.org/")
-	set(CPACK_NSIS_URL_INFO_ABOUT "http://www.hedgewars.org/")
-	set(CPACK_NSIS_CONTACT "unC0Rr@gmail.com")
-	set(CPACK_NSIS_MODIFY_PATH OFF)
-	set(CPACK_GENERATOR "ZIP;NSIS")
-	set(CPACK_PACKAGE_INSTALL_REGISTRY_KEY "hedgewars")
+    set(CPACK_NSIS_DISPLAY_NAME "Hedgewars")
+    set(CPACK_NSIS_HELP_LINK "http://www.hedgewars.org/")
+    set(CPACK_NSIS_URL_INFO_ABOUT "http://www.hedgewars.org/")
+    set(CPACK_NSIS_CONTACT "unC0Rr@gmail.com")
+    set(CPACK_NSIS_MODIFY_PATH OFF)
+    set(CPACK_GENERATOR "ZIP;NSIS")
+    set(CPACK_PACKAGE_INSTALL_REGISTRY_KEY "hedgewars")
 else(WIN32 AND NOT UNIX)
-	set(CPACK_STRIP_FILES "bin/hedgewars;bin/hwengine")
+    set(CPACK_STRIP_FILES "bin/hedgewars;bin/hwengine")
 endif(WIN32 AND NOT UNIX)
 
 set(CPACK_SOURCE_IGNORE_FILES
-	"~"
-	"\\\\.hg"
-	"\\\\.svn"
-	"\\\\.exe$"
-	"\\\\.a$"
-	"\\\\.dll$"
-	"\\\\.xcf$"
-	"\\\\.cxx$"
-	"\\\\.db$"
-	"\\\\.dof$"
-	"\\\\.layout$"
-	"\\\\.zip$"
-	"\\\\.gz$"
-	"\\\\.bz2$"
-	"\\\\.tmp$"
-	"\\\\.core$"
-	"\\\\.sh$"
-	"\\\\.sifz$"
-	"\\\\.svg$"
-	"\\\\.svgz$"
-	"\\\\.ppu$"
-	"\\\\.psd$"
-	"\\\\.o$"
-	"Makefile"
-	"Doxyfile"
-	"CMakeFiles"
-	"debug"
-	"release$"
-	"Debug$"
-	"Release$"
-	"proto\\\\.inc$"
-	"hwconsts\\\\.cpp$"
-	"playlist\\\\.inc$"
-	"CPack"
-	"cmake_install\\\\.cmake$"
-	"config\\\\.inc$"
-	"hwengine\\\\.desktop$"
-	"CMakeCache\\\\.txt$"
-#	"^${CMAKE_CURRENT_SOURCE_DIR}/misc/libopenalbridge"
-#	"^${CMAKE_CURRENT_SOURCE_DIR}/misc/libfreetype"
-	"^${CMAKE_CURRENT_SOURCE_DIR}/misc/liblua"
-#	"^${CMAKE_CURRENT_SOURCE_DIR}/misc/libtremor"
-	"^${CMAKE_CURRENT_SOURCE_DIR}/project_files/HedgewarsMobile/"
-	"^${CMAKE_CURRENT_SOURCE_DIR}/bin/[a-z]"
-	"^${CMAKE_CURRENT_SOURCE_DIR}/tools/templates"
-	"^${CMAKE_CURRENT_SOURCE_DIR}/doc"
-	"^${CMAKE_CURRENT_SOURCE_DIR}/templates"
-	"^${CMAKE_CURRENT_SOURCE_DIR}/Graphics"
-	"^${CMAKE_CURRENT_SOURCE_DIR}/realtest"
-	"^${CMAKE_CURRENT_SOURCE_DIR}/tmp"
-	"^${CMAKE_CURRENT_SOURCE_DIR}/utils"
-	"^${CMAKE_CURRENT_SOURCE_DIR}/share/hedgewars/Data/Maps/test"
-	"^${CMAKE_CURRENT_SOURCE_DIR}/share/hedgewars/Data/Themes/ethereal"
-	"^${CMAKE_CURRENT_SOURCE_DIR}/install_manifest.txt"
-	"^${CMAKE_CURRENT_SOURCE_DIR}/CMakeCache.txt"
-	"^${CMAKE_CURRENT_SOURCE_DIR}/hedgewars\\\\."
+    "~"
+    "\\\\.hg"
+    "\\\\.svn"
+    "\\\\.exe$"
+    "\\\\.a$"
+    "\\\\.dll$"
+    "\\\\.xcf$"
+    "\\\\.cxx$"
+    "\\\\.db$"
+    "\\\\.dof$"
+    "\\\\.layout$"
+    "\\\\.zip$"
+    "\\\\.gz$"
+    "\\\\.bz2$"
+    "\\\\.tmp$"
+    "\\\\.core$"
+    "\\\\.sh$"
+    "\\\\.sifz$"
+    "\\\\.svg$"
+    "\\\\.svgz$"
+    "\\\\.ppu$"
+    "\\\\.psd$"
+    "\\\\.o$"
+    "Makefile"
+    "Doxyfile"
+    "CMakeFiles"
+    "debug"
+    "release$"
+    "Debug$"
+    "Release$"
+    "proto\\\\.inc$"
+    "hwconsts\\\\.cpp$"
+    "playlist\\\\.inc$"
+    "CPack"
+    "cmake_install\\\\.cmake$"
+    "config\\\\.inc$"
+    "hwengine\\\\.desktop$"
+    "CMakeCache\\\\.txt$"
+#    "^${CMAKE_CURRENT_SOURCE_DIR}/misc/libopenalbridge"
+#    "^${CMAKE_CURRENT_SOURCE_DIR}/misc/libfreetype"
+    "^${CMAKE_CURRENT_SOURCE_DIR}/misc/liblua"
+#    "^${CMAKE_CURRENT_SOURCE_DIR}/misc/libtremor"
+    "^${CMAKE_CURRENT_SOURCE_DIR}/project_files/HedgewarsMobile/"
+    "^${CMAKE_CURRENT_SOURCE_DIR}/bin/[a-z]"
+    "^${CMAKE_CURRENT_SOURCE_DIR}/tools/templates"
+    "^${CMAKE_CURRENT_SOURCE_DIR}/doc"
+    "^${CMAKE_CURRENT_SOURCE_DIR}/templates"
+    "^${CMAKE_CURRENT_SOURCE_DIR}/Graphics"
+    "^${CMAKE_CURRENT_SOURCE_DIR}/realtest"
+    "^${CMAKE_CURRENT_SOURCE_DIR}/tmp"
+    "^${CMAKE_CURRENT_SOURCE_DIR}/utils"
+    "^${CMAKE_CURRENT_SOURCE_DIR}/share/hedgewars/Data/Maps/test"
+    "^${CMAKE_CURRENT_SOURCE_DIR}/share/hedgewars/Data/Themes/ethereal"
+    "^${CMAKE_CURRENT_SOURCE_DIR}/install_manifest.txt"
+    "^${CMAKE_CURRENT_SOURCE_DIR}/CMakeCache.txt"
+    "^${CMAKE_CURRENT_SOURCE_DIR}/hedgewars\\\\."
 )
 
 include(CPack)
--- a/QTfrontend/CMakeLists.txt	Tue Jun 05 22:37:36 2012 +0200
+++ b/QTfrontend/CMakeLists.txt	Mon Jun 25 10:44:27 2012 +0200
@@ -11,7 +11,9 @@
 set(QT_USE_QTMAIN TRUE)
 
 find_package(Qt4 REQUIRED)
-include(${QT_USE_FILE})
+if (NOT CROSSAPPLE)
+    include(${QT_USE_FILE})
+endif()
 
 # Check if we need zlib
 check_library_exists("${QT_QTCORE_LIBRARY}" inflateInit2_ ${QT_LIBRARY_DIR} QT_PROVIDES_ZLIB_FUNCTIONS)
@@ -140,7 +142,7 @@
 qt4_wrap_cpp(hwfr_moc_srcs ${hwfr_moc_hdrs})
 
 
-if(APPLE)
+if(APPLE OR CROSSAPPLE)
     set(hwfr_src ${hwfr_src} InstallController.cpp CocoaInitializer.mm M3Panel.mm M3InstallController.m NSWorkspace_RBAdditions.m)
     set(HW_LINK_LIBS IOKit ${HW_LINK_LIBS})
 
@@ -186,7 +188,11 @@
 endif()
 
 
-target_link_libraries(hedgewars ${HW_LINK_LIBS})
+if (CROSSAPPLE)
+    add_dependencies(hedgewars quazip)
+else()
+    target_link_libraries(hedgewars ${HW_LINK_LIBS})
+endif()
 
 
 install(PROGRAMS "${EXECUTABLE_OUTPUT_PATH}/hedgewars${CMAKE_EXECUTABLE_SUFFIX}" DESTINATION ${target_dir})
--- a/QTfrontend/game.cpp	Tue Jun 05 22:37:36 2012 +0200
+++ b/QTfrontend/game.cpp	Mon Jun 25 10:44:27 2012 +0200
@@ -21,6 +21,7 @@
 #include <QUuid>
 #include <QColor>
 #include <QStringListModel>
+#include <QTextStream>
 
 #include "game.h"
 #include "hwconsts.h"
@@ -29,8 +30,7 @@
 #include "teamselect.h"
 #include "KB.h"
 #include "proto.h"
-
-#include <QTextStream>
+#include "ThemeModel.h"
 
 QString training, campaign; // TODO: Cleaner solution?
 
@@ -98,7 +98,7 @@
             HWProto::addStringToBuffer(buf, QString("eammprob %1").arg(ammostr.mid(cAmmoNumber, cAmmoNumber)));
             HWProto::addStringToBuffer(buf, QString("eammdelay %1").arg(ammostr.mid(2 * cAmmoNumber, cAmmoNumber)));
             HWProto::addStringToBuffer(buf, QString("eammreinf %1").arg(ammostr.mid(3 * cAmmoNumber, cAmmoNumber)));
-            if(!gamecfg->schemeData(21).toBool()) HWProto::addStringToBuffer(buf, QString("eammstore"));
+            if(gamecfg->schemeData(15).toBool() || !gamecfg->schemeData(21).toBool()) HWProto::addStringToBuffer(buf, QString("eammstore"));
             HWProto::addStringListToBuffer(buf,
                                            team.teamGameConfig(gamecfg->getInitHealth()));
             ;
--- a/QTfrontend/hwconsts.cpp.in	Tue Jun 05 22:37:36 2012 +0200
+++ b/QTfrontend/hwconsts.cpp.in	Mon Jun 25 10:44:27 2012 +0200
@@ -72,19 +72,3 @@
 
 int season = SEASON_NONE;
 int years_since_foundation = 0;
-
-QStandardItemModel * colorsModel;
-
-void hwConstsInit()
-{
-    colorsModel = new QStandardItemModel();
-
-    int i = 0;
-    while(colors[i])
-    {
-        QStandardItem * item = new QStandardItem();
-        item->setData(QColor(colors[i]));
-        colorsModel->appendRow(item);
-        ++i;
-    }
-}
--- a/QTfrontend/hwconsts.h	Tue Jun 05 22:37:36 2012 +0200
+++ b/QTfrontend/hwconsts.h	Mon Jun 25 10:44:27 2012 +0200
@@ -44,8 +44,7 @@
 extern int cAmmoNumber;
 extern QList< QPair<QString, QString> > cDefaultAmmos;
 
-//extern unsigned int colors[];
-extern QStandardItemModel * colorsModel;
+extern unsigned int colors[];
 
 extern QString * netHost;
 extern quint16 netPort;
@@ -60,8 +59,6 @@
 //Could be used to implement a text/graphic like "This is the xxth birthday of hedgewars" or similar
 extern int years_since_foundation;
 
-void hwConstsInit();
-
 #endif
 
 #define HEDGEHOGS_PER_TEAM           8
--- a/QTfrontend/main.cpp	Tue Jun 05 22:37:36 2012 +0200
+++ b/QTfrontend/main.cpp	Mon Jun 25 10:44:27 2012 +0200
@@ -104,8 +104,6 @@
 {
     HWApplication app(argc, argv);
 
-    hwConstsInit();
-
     app.setAttribute(Qt::AA_DontShowIconsInMenus,false);
 
     QStringList arguments = app.arguments();
--- a/QTfrontend/model/GameStyleModel.cpp	Tue Jun 05 22:37:36 2012 +0200
+++ b/QTfrontend/model/GameStyleModel.cpp	Mon Jun 25 10:44:27 2012 +0200
@@ -21,6 +21,8 @@
  * @brief GameStyleModel class implementation
  */
 
+#include <QTextStream>
+
 #include "GameStyleModel.h"
 
 
--- a/QTfrontend/model/roomslistmodel.cpp	Tue Jun 05 22:37:36 2012 +0200
+++ b/QTfrontend/model/roomslistmodel.cpp	Mon Jun 25 10:44:27 2012 +0200
@@ -21,12 +21,13 @@
  * @brief RoomsListModel class implementation
  */
 
-#include "roomslistmodel.h"
-
 #include <QBrush>
 #include <QColor>
 #include <QIcon>
 
+#include "roomslistmodel.h"
+#include "MapModel.h"
+
 RoomsListModel::RoomsListModel(QObject *parent) :
     QAbstractTableModel(parent),
     c_nColumns(8)
--- a/QTfrontend/team.cpp	Tue Jun 05 22:37:36 2012 +0200
+++ b/QTfrontend/team.cpp	Mon Jun 25 10:44:27 2012 +0200
@@ -26,6 +26,7 @@
 
 #include "team.h"
 #include "hwform.h"
+#include "DataManager.h"
 
 HWTeam::HWTeam(const QString & teamname) :
     QObject(0)
@@ -150,9 +151,9 @@
         m_fort = other.m_fort;
         m_flag = other.m_flag;
         m_voicepack = other.m_voicepack;
-//        m_hedgehogs = other.m_hedgehogs;
+        m_hedgehogs = other.m_hedgehogs;
         m_difficulty = other.m_difficulty;
-//        m_binds = other.m_binds;
+        m_binds = other.m_binds;
         m_numHedgehogs = other.m_numHedgehogs;
         m_color = other.m_color;
         m_isNetTeam = other.m_isNetTeam;
@@ -351,12 +352,12 @@
 
 QColor HWTeam::qcolor() const
 {
-    return colorsModel->item(m_color)->data().value<QColor>();
+    return DataManager::instance().colorsModel()->item(m_color)->data().value<QColor>();
 }
 
 void HWTeam::setColor(int color)
 {
-    m_color = color % colorsModel->rowCount();
+    m_color = color % DataManager::instance().colorsModel()->rowCount();
 }
 
 
--- a/QTfrontend/ui/page/pageeditteam.cpp	Tue Jun 05 22:37:36 2012 +0200
+++ b/QTfrontend/ui/page/pageeditteam.cpp	Mon Jun 25 10:44:27 2012 +0200
@@ -26,12 +26,13 @@
 #include <QGroupBox>
 #include <QToolBox>
 #include <QMessageBox>
-
-#include "sdlkeys.h"
+#include <QStandardItemModel>
+#include <QDebug>
 #include "SquareLabel.h"
 #include "HWApplication.h"
 
 #include "DataManager.h"
+#include "HatModel.h"
 
 #include "pageeditteam.h"
 
@@ -196,9 +197,9 @@
         l->setText(HWApplication::translate("binds", cbinds[i].name));
         l->setAlignment(Qt::AlignRight);
         pagelayout->addWidget(l, num, 0);
+
         CBBind[i] = new QComboBox(curW);
-        for(int j = 0; sdlkeys[j][1][0] != '\0'; j++)
-            CBBind[i]->addItem(HWApplication::translate("binds (keys)", sdlkeys[j][1]).contains(": ") ? HWApplication::translate("binds (keys)", sdlkeys[j][1]) : HWApplication::translate("binds (keys)", "Keyboard") + QString(": ") + HWApplication::translate("binds (keys)", sdlkeys[j][1]), sdlkeys[j][0]);
+        CBBind[i]->setModel(DataManager::instance().bindsModel());
         pagelayout->addWidget(CBBind[i++], num++, 1);
     }
 
@@ -422,9 +423,15 @@
     CBFort->setCurrentIndex(CBFort->findText(team.fort()));
     CBVoicepack->setCurrentIndex(CBVoicepack->findText(team.voicepack()));
 
+    QStandardItemModel * binds = DataManager::instance().bindsModel();
     for(int i = 0; i < BINDS_NUMBER; i++)
     {
-        CBBind[i]->setCurrentIndex(CBBind[i]->findData(team.keyBind(i)));
+        QModelIndexList mdl = binds->match(binds->index(0, 0), Qt::UserRole + 1, team.keyBind(i), 1, Qt::MatchExactly);
+
+        if(mdl.size() == 1)
+            CBBind[i]->setCurrentIndex(mdl[0].row());
+        else
+            qDebug() << "Binds: cannot find" << team.keyBind(i);
     }
 }
 
@@ -450,9 +457,10 @@
     team.setVoicepack(CBVoicepack->currentText());
     team.setFlag(CBFlag->itemData(CBFlag->currentIndex()).toString());
 
+    QStandardItemModel * binds = DataManager::instance().bindsModel();
     for(int i = 0; i < BINDS_NUMBER; i++)
     {
-        team.bindKey(i,CBBind[i]->itemData(CBBind[i]->currentIndex()).toString());
+        team.bindKey(i, binds->index(CBBind[i]->currentIndex(), 0).data(Qt::UserRole + 1).toString());
     }
 
     return team;
--- a/QTfrontend/ui/widget/frameTeam.cpp	Tue Jun 05 22:37:36 2012 +0200
+++ b/QTfrontend/ui/widget/frameTeam.cpp	Mon Jun 25 10:44:27 2012 +0200
@@ -25,6 +25,7 @@
 #include "frameTeam.h"
 #include "teamselhelper.h"
 #include "hwconsts.h"
+#include "DataManager.h"
 
 FrameTeams::FrameTeams(QWidget* parent) :
     QFrame(parent), maxHedgehogsPerGame(48), overallHedgehogs(0), mainLayout(this), nonInteractive(false)
@@ -54,12 +55,12 @@
 
 void FrameTeams::resetColors()
 {
-    currentColor = colorsModel->rowCount() - 1; // ensure next color is the first one
+    currentColor = DataManager::instance().colorsModel()->rowCount() - 1; // ensure next color is the first one
 }
 
 int FrameTeams::getNextColor()
 {
-    currentColor = (currentColor + 1) % colorsModel->rowCount();
+    currentColor = (currentColor + 1) % DataManager::instance().colorsModel()->rowCount();
     return currentColor;
 }
 
--- a/QTfrontend/ui/widget/gamecfgwidget.cpp	Tue Jun 05 22:37:36 2012 +0200
+++ b/QTfrontend/ui/widget/gamecfgwidget.cpp	Mon Jun 25 10:44:27 2012 +0200
@@ -32,6 +32,7 @@
 #include "hwconsts.h"
 #include "ammoSchemeModel.h"
 #include "proto.h"
+#include "GameStyleModel.h"
 
 GameCFGWidget::GameCFGWidget(QWidget* parent) :
     QGroupBox(parent)
--- a/QTfrontend/ui/widget/mapContainer.cpp	Tue Jun 05 22:37:36 2012 +0200
+++ b/QTfrontend/ui/widget/mapContainer.cpp	Mon Jun 25 10:44:27 2012 +0200
@@ -36,6 +36,7 @@
 #include "mapContainer.h"
 #include "igbox.h"
 #include "HWApplication.h"
+#include "ThemeModel.h"
 
 HWMapContainer::HWMapContainer(QWidget * parent) :
     QWidget(parent),
--- a/QTfrontend/ui/widget/mapContainer.h	Tue Jun 05 22:37:36 2012 +0200
+++ b/QTfrontend/ui/widget/mapContainer.h	Mon Jun 25 10:44:27 2012 +0200
@@ -31,6 +31,7 @@
 
 #include "hwmap.h"
 #include "drawmapscene.h"
+#include "MapModel.h"
 
 class QPushButton;
 class IconedGroupBox;
--- a/QTfrontend/ui/widget/teamselhelper.cpp	Tue Jun 05 22:37:36 2012 +0200
+++ b/QTfrontend/ui/widget/teamselhelper.cpp	Mon Jun 25 10:44:27 2012 +0200
@@ -28,6 +28,7 @@
 #include "hwconsts.h"
 #include "frameTeam.h"
 #include "colorwidget.h"
+#include "DataManager.h"
 
 void TeamLabel::teamButtonClicked()
 {
@@ -69,7 +70,7 @@
     if(m_isPlaying)
     {
         // team color
-        colorWidget = new ColorWidget(colorsModel, this);
+        colorWidget = new ColorWidget(DataManager::instance().colorsModel(), this);
         colorWidget->setMinimumWidth(26);
         colorWidget->setMaximumWidth(26);
         colorWidget->setMinimumHeight(26);
--- a/QTfrontend/util/DataManager.cpp	Tue Jun 05 22:37:36 2012 +0200
+++ b/QTfrontend/util/DataManager.cpp	Mon Jun 25 10:44:27 2012 +0200
@@ -23,13 +23,19 @@
 
 #include <QMap>
 #include <QStringList>
-
+#include <QStandardItemModel>
 #include <QFileInfo>
 
 #include "hwconsts.h"
+#include "HWApplication.h"
+#include "sdlkeys.h"
 
 #include "DataManager.h"
 
+#include "GameStyleModel.h"
+#include "HatModel.h"
+#include "MapModel.h"
+#include "ThemeModel.h"
 
 DataManager::DataManager()
 {
@@ -42,6 +48,8 @@
     m_hatModel = NULL;
     m_mapModel = NULL;
     m_themeModel = NULL;
+    m_colorsModel = NULL;
+    m_bindsModel = NULL;
 }
 
 
@@ -154,6 +162,43 @@
     return m_themeModel;
 }
 
+QStandardItemModel * DataManager::colorsModel()
+{
+    if(m_colorsModel == NULL)
+    {
+        m_colorsModel = new QStandardItemModel();
+
+        int i = 0;
+        while(colors[i])
+        {
+            QStandardItem * item = new QStandardItem();
+            item->setData(QColor(colors[i]));
+            m_colorsModel->appendRow(item);
+            ++i;
+        }
+    }
+
+    return m_colorsModel;
+}
+
+QStandardItemModel * DataManager::bindsModel()
+{
+    if(m_bindsModel == NULL)
+    {
+        m_bindsModel = new QStandardItemModel();
+
+        for(int j = 0; sdlkeys[j][1][0] != '\0'; j++)
+        {
+            QStandardItem * item = new QStandardItem();
+            item->setData(HWApplication::translate("binds (keys)", sdlkeys[j][1]).contains(": ") ? HWApplication::translate("binds (keys)", sdlkeys[j][1]) : HWApplication::translate("binds (keys)", "Keyboard") + QString(": ") + HWApplication::translate("binds (keys)", sdlkeys[j][1]), Qt::DisplayRole);
+            item->setData(sdlkeys[j][0], Qt::UserRole + 1);
+            m_bindsModel->appendRow(item);
+        }
+    }
+
+    return m_bindsModel;
+}
+
 void DataManager::reload()
 {
     m_gameStyleModel->loadGameStyles();
--- a/QTfrontend/util/DataManager.h	Tue Jun 05 22:37:36 2012 +0200
+++ b/QTfrontend/util/DataManager.h	Mon Jun 25 10:44:27 2012 +0200
@@ -26,21 +26,13 @@
 
 #include <QDir>
 #include <QFile>
-
 #include <QStringList>
 
-#include "GameStyleModel.h"
-#include "HatModel.h"
-#include "MapModel.h"
-#include "ThemeModel.h"
-
-class QDir;
-class QFile;
-class QStringList;
 class GameStyleModel;
 class HatModel;
 class MapModel;
 class ThemeModel;
+class QStandardItemModel;
 
 /**
  * @brief Offers access to the data files of hedgewars.
@@ -135,6 +127,9 @@
          */
         ThemeModel * themeModel();
 
+        QStandardItemModel * colorsModel();
+        QStandardItemModel * bindsModel();
+
     public slots:
         /// Reloads data from storage.
         void reload();
@@ -163,6 +158,8 @@
         HatModel * m_hatModel; ///< hat model instance
         MapModel * m_mapModel; ///< map model instance
         ThemeModel * m_themeModel; ///< theme model instance
+        QStandardItemModel * m_colorsModel;
+        QStandardItemModel * m_bindsModel;
 };
 
 #endif // HEDGEWARS_DATAMANAGER_H
--- a/cmake_modules/FindLua.cmake	Tue Jun 05 22:37:36 2012 +0200
+++ b/cmake_modules/FindLua.cmake	Mon Jun 25 10:44:27 2012 +0200
@@ -20,8 +20,8 @@
             FIND_LIBRARY(LUA_DEFAULT NAMES lua51 lua5.1 lua-5.1 lua PATHS /lib /usr/lib /usr/local/lib /usr/pkg/lib)
             IF(${LUA_DEFAULT} MATCHES "LUA_DEFAULT-NOTFOUND")
 	        set(LUA_DEFAULT lua)
+            ELSE()
                 set(LUA_FOUND true)
-            ELSE()
                 message(STATUS "LibLua 5.1 found at ${LUA_DEFAULT}")
                 #remove the path (fpc doesn't like it - why?)
                 GET_FILENAME_COMPONENT(LUA_DEFAULT ${LUA_DEFAULT} NAME)
--- a/gameServer/ClientIO.hs	Tue Jun 05 22:37:36 2012 +0200
+++ b/gameServer/ClientIO.hs	Mon Jun 25 10:44:27 2012 +0200
@@ -48,6 +48,7 @@
         listenLoop s chan ci >> return "Connection closed")
         `Exception.catch` (\(e :: Exception.IOException) -> return . B.pack . show $ e)
         `Exception.catch` (\(e :: ShutdownThreadException) -> return . B.pack . show $ e)
+        `Exception.catch` (\(e :: Exception.SomeException) -> return . B.pack . show $ e)
         >>= clientOff >> remove
     where
         clientOff msg = writeChan chan $ ClientMessage (ci, ["QUIT", msg])
--- a/gameServer/HWProtoInRoomState.hs	Tue Jun 05 22:37:36 2012 +0200
+++ b/gameServer/HWProtoInRoomState.hs	Mon Jun 25 10:44:27 2012 +0200
@@ -158,8 +158,8 @@
     cl <- thisClient
     chans <- roomClientsChans
     return [
+        ModifyRoom (\r -> r{readyPlayers = readyPlayers r + (if isReady cl then -1 else 1)}),
         ModifyClient (\c -> c{isReady = not $ isReady cl}),
-        ModifyRoom (\r -> r{readyPlayers = readyPlayers r + (if isReady cl then -1 else 1)}),
         AnswerClients chans $ if clientProto cl < 38 then
                 [if isReady cl then "NOT_READY" else "READY", nick cl]
                 else
--- a/hedgewars/CMakeLists.txt	Tue Jun 05 22:37:36 2012 +0200
+++ b/hedgewars/CMakeLists.txt	Mon Jun 25 10:44:27 2012 +0200
@@ -171,13 +171,15 @@
     if(${PNG_FOUND})
         message(STATUS "PNG screenshots enabled (library found at ${PNG_LIBRARY})")
         set(pascal_flags "-dPNG_SCREENSHOTS" ${pascal_flags})
-        if(APPLE)  # need to explictly link with the static lib
+        if(APPLE)  # need to explictly link with the static lib -- maybe windows too?
             string(REGEX REPLACE "(.*)libpng.*" "\\1" PNG_LIBDIR "${PNG_LIBRARY}")
             set(pascal_flags "-k${PNG_LIBDIR}/libpng.a" ${pascal_flags})
         endif()
     else()
         message(STATUS "PNG library not found, switching to screenshots in BMP format")
     endif()
+else()
+    message(STATUS "PNG screenshots disabled per user request, using BMP format")
 endif()
 
 set(fpc_flags ${noexecstack_flags} ${pascal_flags} ${hwengine_project})
@@ -215,7 +217,7 @@
 add_custom_target(${engine_output_name} ALL DEPENDS "${EXECUTABLE_OUTPUT_PATH}/${engine_output_name}${CMAKE_EXECUTABLE_SUFFIX}")
 
 #when system Lua is not found we need to compile it before engine
-if(NOT ${LUA_FOUND})
+if(NOT LUA_FOUND)
     add_dependencies(${engine_output_name} lua)
 endif()
 
--- a/hedgewars/GSHandlers.inc	Tue Jun 05 22:37:36 2012 +0200
+++ b/hedgewars/GSHandlers.inc	Mon Jun 25 10:44:27 2012 +0200
@@ -1025,7 +1025,9 @@
         else
             AmmoShove(Gear, Gear^.Timer, 20);
         CheckGearDrowning(Gear);
-        dec(i) until (i = 0) or (Gear^.Damage > Gear^.Health) or ((Gear^.State and gstDrowning) <> 0);
+        dec(i) 
+    until (i = 0) or (Gear^.Damage > Gear^.Health) or ((Gear^.State and gstDrowning) <> 0);
+
     if Gear^.Damage > 0 then
         begin
         DrawTunnel(oX, oY, Gear^.dX, Gear^.dY, 82 - i, 1);
@@ -2112,19 +2114,37 @@
         end
     else
         begin 
-        if Gear^.Timer = 0 then
-        begin
+        if Gear^.Timer = 500 then
+            begin
 (* Can't make sparkles team coloured without working out what the next team is going to be. This should be solved, really, since it also screws up
    voices. Reinforcements voices is heard for active team, not team-to-be.  Either that or change crate spawn from end of turn to start, although that
    has its own complexities. *)
-        sparkles:= AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtDust, 1);
-        if sparkles <> nil then
+            // Abuse a couple of gear values to track origin
+            Gear^.Angle:= hwRound(Gear^.X);
+            Gear^.Power:= hwRound(Gear^.Y);
+            Gear^.Tag:= random(2);
+            inc(Gear^.Timer)
+            end;
+        if Gear^.Timer < 1833 then inc(Gear^.Timer);
+        if Gear^.Timer = 1000 then
             begin
-            sparkles^.Tint:= $FAB22CFF
+            sparkles:= AddVisualGear(Gear^.Angle, Gear^.Power, vgtDust, 1);
+            if sparkles <> nil then
+                begin
+                sparkles^.dX:= 0;
+                sparkles^.dY:= 0;
+                sparkles^.Angle:= 270;
+                if Gear^.Tag = 1 then 
+                    sparkles^.Tint:= $3744D7FF
+                else sparkles^.Tint:= $FAB22CFF
+                end;
+            end;
+        if Gear^.Timer < 1000 then 
+            begin
+            AllInactive:= false;
+            exit
             end
         end;
-        if (GameTicks and $1 = 0) and (Gear^.Timer < 255) then inc(Gear^.Timer)
-        end;
 
     if (Gear^.Damage > 0) or exBoom then
         begin
@@ -2766,7 +2786,7 @@
             CurrentTeam^.CurrHedgehog := Succ(CurrentTeam^.CurrHedgehog) mod (CurrentTeam^.HedgehogsNumber);
         until (CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog].Gear <> nil) and (CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog].Gear^.Damage = 0);
 
-        CurrentHedgehog := @CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog];
+        SwitchCurrentHedgehog(@CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog]);
         AmmoMenuInvalidated:= true; 
 
         HHGear := CurrentHedgehog^.Gear;
@@ -3085,7 +3105,7 @@
         begin
         Gear^.Tag := 0;
         Gear^.X := Gear^.X + int2hwFloat(xx);
-        if not TestCollisionY(Gear, yyn) then
+        if TestCollisionYwithGear(Gear, yyn) = 0 then
             begin
             Gear^.Y := Gear^.Y + int2hwFloat(yyn);
             NextAngle(Gear, dA)
@@ -3163,8 +3183,7 @@
 
     HHGear := Gear^.Hedgehog^.Gear;
     HHGear^.Message := HHGear^.Message and (not gmAttack);
-    DeleteCI(HHGear);
-    Gear^.IntersectGear:= nil;
+    Gear^.CollisionMask:= $FF7F;
 
     FollowGear := Gear;
 
@@ -3438,7 +3457,7 @@
         PlaySound(sndGun);
         end;
 
-    if (Gear^.Timer = 0) or (HHGear^.Damage <> 0) then
+    if (Gear^.Timer = 0) or ((HHGear^.State and gstHHDriven) = 0) then
         begin
         DeleteGear(Gear);
         AfterAttack
@@ -4024,12 +4043,12 @@
         gear^.RenderTimer := true;
 
     // abort if there is no other portal connected to this one
-    if (Gear^.IntersectGear = nil) then
+    if (Gear^.LinkedGear = nil) then
         exit;
-    if ((Gear^.IntersectGear^.Tag and 1) = 0) then // or if it's still moving;
+    if ((Gear^.LinkedGear^.Tag and 1) = 0) then // or if it's still moving;
         exit;
 
-    conPortal := Gear^.IntersectGear;
+    conPortal := Gear^.LinkedGear;
 
     // check all gears for stuff to port through
     iterator := nil;
@@ -4412,8 +4431,8 @@
         if not Gear^.dX.isNegative then
             Gear^.DirAngle := 180-Gear^.DirAngle;
 
-        if ((Gear^.IntersectGear = nil)
-        or (hwRound(Distance(Gear^.X - Gear^.IntersectGear^.X,Gear^.Y-Gear^.IntersectGear^.Y)) >=Gear^.Radius*2)) then
+        if ((Gear^.LinkedGear = nil)
+        or (hwRound(Distance(Gear^.X - Gear^.LinkedGear^.X,Gear^.Y-Gear^.LinkedGear^.Y)) >=Gear^.Radius*2)) then
             begin
             loadNewPortalBall(Gear, false);
             inc(Gear^.Tag);
@@ -4455,7 +4474,7 @@
     newPortal^.dX := newPortal^.dX * s;
     newPortal^.dY := newPortal^.dY * s;
 
-    newPortal^.IntersectGear := nil;
+    newPortal^.LinkedGear := nil;
 
     if CurrentHedgehog <> nil then
         with CurrentHedgehog^ do
@@ -4484,8 +4503,8 @@
                         else
                             begin
                             // link portals with each other
-                            newPortal^.IntersectGear := iterator;
-                            iterator^.IntersectGear := newPortal;
+                            newPortal^.LinkedGear := iterator;
+                            iterator^.LinkedGear := newPortal;
                             iterator^.Health := newPortal^.Health;
                             end;
                         end;
@@ -4738,7 +4757,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 procedure doStepFlamethrowerWork(Gear: PGear);
 var 
-    HHGear: PGear;
+    HHGear, flame: PGear;
     rx, ry, speed: hwFloat;
     i, gX, gY: LongInt;
 begin
@@ -4776,14 +4795,18 @@
             ry := rndSign(getRandomf * _0_1);
             speed := _0_5 * (_10 / Gear^.Tag);
     
-            AddGear(gx, gy, gtFlame, gstTmpFlag,
+            flame:= AddGear(gx, gy, gtFlame, gstTmpFlag,
                     SignAs(AngleSin(HHGear^.Angle) * speed, HHGear^.dX) + rx,
                     AngleCos(HHGear^.Angle) * ( - speed) + ry, 0);
+            flame^.CollisionMask:= $FF7F;
             
             if (Gear^.Health mod 30) = 0 then
-                AddGear(gx, gy, gtFlame, 0,
+                begin
+                flame:= AddGear(gx, gy, gtFlame, 0,
                         SignAs(AngleSin(HHGear^.Angle) * speed, HHGear^.dX) + rx,
                         AngleCos(HHGear^.Angle) * ( - speed) + ry, 0);
+                flame^.CollisionMask:= $FF7F;
+                end
             end;
         Gear^.Timer:= Gear^.Tag
         end;
@@ -4819,7 +4842,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 procedure doStepLandGunWork(Gear: PGear);
 var 
-    HHGear: PGear;
+    HHGear, land: PGear;
     rx, ry, speed: hwFloat;
     i, gX, gY: LongInt;
 begin
@@ -4856,9 +4879,10 @@
         ry := rndSign(getRandomf * _0_1);
         speed := (_3 / Gear^.Tag);
 
-        AddGear(gx, gy, gtFlake, gstTmpFlag, 
+        land:= AddGear(gx, gy, gtFlake, gstTmpFlag, 
                 SignAs(AngleSin(HHGear^.Angle) * speed, HHGear^.dX) + rx, 
                 AngleCos(HHGear^.Angle) * ( - speed) + ry, 0);
+        land^.CollisionMask:= $FF7F;
             
         Gear^.Timer:= Gear^.Tag
         end;
@@ -4938,7 +4962,7 @@
                 ApplyDamage(tmp, CurrentHedgehog, tmp^.Health div 3, dsUnknown);
             //DrawTunnel(tmp^.X, tmp^.Y - _1, _0, _0_5, cHHRadius * 6, cHHRadius * 3);
             tmp2:= AddGear(hwRound(tmp^.X), hwRound(tmp^.Y), gtHammerHit, 0, _0, _0, 0);
-            tmp2^.IntersectGear:= tmp;
+            tmp2^.LinkedGear:= tmp;
             SetAllToActive
             end
         else
@@ -4957,7 +4981,7 @@
     HitGear: PGear;
 begin
     AllInactive := false;
-    HitGear := Gear^.IntersectGear;
+    HitGear := Gear^.LinkedGear;
     dec(Gear^.Timer);
     if (HitGear = nil) or (Gear^.Timer = 0) or ((Gear^.Message and gmDestroy) <> 0) then
         begin
--- a/hedgewars/SDLh.pas	Tue Jun 05 22:37:36 2012 +0200
+++ b/hedgewars/SDLh.pas	Mon Jun 25 10:44:27 2012 +0200
@@ -270,6 +270,19 @@
     AShift = 0;
 {$ENDIF}
 
+    KMOD_NONE   = $0000;
+    KMOD_LSHIFT = $0001;
+    KMOD_RSHIFT = $0002;
+    KMOD_LCTRL  = $0040;
+    KMOD_RCTRL  = $0080;
+    KMOD_LALT   = $0400;
+    KMOD_RALT   = $0800;
+    KMOD_LMETA  = $0400;
+    KMOD_RMETA  = $0800;
+    KMOD_NUM    = $1000;
+    KMOD_CAPS   = $2000;
+    KMOD_MODE   = $4000;
+
     {* SDL_mixer *}
     MIX_MAX_VOLUME = 128;
     MIX_INIT_FLAC  = $00000001;
@@ -968,9 +981,6 @@
 function SDL_getenv(const text: PChar): PChar; cdecl; external SDLLibName;
 {$ENDIF}
 
-{$IFDEF ANDROID}
-function Android_JNI_getDensity(): Single; cdecl; external SDLLibName;
-{$ENDIF}
 
 {* Compatibility between SDL-1.2 and SDL-1.3 *}
 procedure SDL_WarpMouse(x, y: Word); {$IFDEF SDL13}inline{$ELSE}cdecl; external SDLLibName{$ENDIF};
--- a/hedgewars/VGSHandlers.inc	Tue Jun 05 22:37:36 2012 +0200
+++ b/hedgewars/VGSHandlers.inc	Mon Jun 25 10:44:27 2012 +0200
@@ -90,10 +90,16 @@
             if round(X) > cRightScreenBorder then
                 X:= X - cScreenSpace;
             // if round(Y) < (LAND_HEIGHT - 1024 - 75) then Y:= Y + 25.0; // For if flag is set for flakes rising upwards?
-            if (Gear^.Layer = 2) and (round(Y) - 225 > LAND_HEIGHT) then
-                Y:= Y - (1024 + 300) // TODO - configure in theme (jellies for example could use limited range)
-            else if (Gear^.Layer <> 2) and (round(Y) + 50 > LAND_HEIGHT) then
-                Y:= Y - (1024 + 25);
+        if (Gear^.Layer = 2) and (round(Y) - 225 > LAND_HEIGHT) then
+            begin
+            X:= cLeftScreenBorder + random(cScreenSpace);
+            Y:= Y - (1024 + 250 + random(50)) // TODO - configure in theme (jellies for example could use limited range)
+            end
+        else if (Gear^.Layer <> 2) and (round(Y) + 50 > LAND_HEIGHT) then
+            begin
+            X:= cLeftScreenBorder + random(cScreenSpace);
+            Y:= Y - (1024 + random(25))
+            end;
         Timer:= 0;
         tdX:= 0;
         tdY:= 0
--- a/hedgewars/options.inc	Tue Jun 05 22:37:36 2012 +0200
+++ b/hedgewars/options.inc	Mon Jun 25 10:44:27 2012 +0200
@@ -16,42 +16,44 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
  *)
 
-{$IFDEF FPC}
-    {$WRITEABLECONST OFF}
-    {$IMPLICITEXCEPTIONS OFF}
-    {$VARSTRINGCHECKS ON}
-    {$MODE OBJFPC}
-{$ELSE}
-    {$ERROR Only Free Pascal supported!}
+{$IFNDEF FPC}
+    {$ERROR Only FreePascal Compiler is supported!}
 {$ENDIF}
 
 {$MACRO ON}
+{$MODE OBJFPC}
 {$DEFINE GLunit:=GL}
+{$WRITEABLECONST OFF}
+{$IMPLICITEXCEPTIONS OFF}
+{$VARSTRINGCHECKS ON}
+
+{$DEFINE USE_LUA_SCRIPT}
+
 
 {$DEFINE GL2}
 
 {$IFDEF ANDROID}
+    {$DEFINE MOBILE}
+    {$DEFINE USE_SDLTHREADS}
+    {$DEFINE USE_CONTEXT_RESTORE}
+    {$DEFINE Java_Prefix:= 'Java_org_hedgewars_hedgeroid_EngineProtocol_PascalExports_'}
+{$ENDIF}
+
+{$IFDEF IPHONEOS}
+    {$DEFINE MOBILE}
+{$ENDIF}
+
+{$IFDEF MOBILE}
     {$DEFINE SDL13}
     {$DEFINE HWLIBRARY}
     {$DEFINE S3D_DISABLED}
     {$DEFINE GLunit:=gles11}
-    {$DEFINE MOBILE}
-    {$DEFINE Java_Prefix:= 'Java_org_hedgewars_hedgeroid_EngineProtocol_PascalExports_'}
-    {$DEFINE USE_SDLTHREADS}
-    {$DEFINE USE_CONTEXT_RESTORE}
     {$DEFINE USE_LANDSCAPE_AMMOMENU}
     {$DEFINE USE_TOUCH_INTERFACE}
+{$ELSE}
+    {$DEFINE USE_AM_NUMCOLUMN}
 {$ENDIF}
 
-{$IFDEF IPHONEOS}
-    {$DEFINE SDL13}
-    {$DEFINE HWLIBRARY}
-    {$DEFINE S3D_DISABLED}
-    {$DEFINE GLunit:=gles11}
-    {$DEFINE MOBILE}
-    {$DEFINE USE_LANDSCAPE_AMMOMENU}
-    {$DEFINE USE_TOUCH_INTERFACE}
-{$ENDIF}
 
 {$IFDEF GL2}
     {$DEFINE S3D_DISABLED}
@@ -61,21 +63,12 @@
     {$DEFINE USE_CONTEXT_RESTORE}
 {$ENDIF}
 
-{$IFNDEF IPHONEOS}
-    {$IFDEF DARWIN}
+{$IFDEF DARWIN}
+    {$IFNDEF IPHONEOS}
         {$DEFINE USE_CONTEXT_RESTORE}
     {$ENDIF}
-    // not needed on ios because DEBUGFILE is switched from command line
-    {$DEFINE DEBUGFILE}
-    //{$DEFINE TRACEAIACTIONS}
-    //{$DEFINE COUNTTICKS}
 {$ENDIF}
 
-{$IFNDEF MOBILE}
-    {$DEFINE USE_AM_NUMCOLUMN}
-{$ENDIF}
-
-{$DEFINE USE_LUA_SCRIPT}
 
 {$IFDEF PAS2C}
     {$DEFINE NOCONSOLE}
@@ -84,3 +77,7 @@
 
 {$DEFINE _S:=}
 {$DEFINE _P:=}
+
+//{$DEFINE TRACEAIACTIONS}
+//{$DEFINE COUNTTICKS}
+
--- a/hedgewars/uAI.pas	Tue Jun 05 22:37:36 2012 +0200
+++ b/hedgewars/uAI.pas	Mon Jun 25 10:44:27 2012 +0200
@@ -111,7 +111,7 @@
 procedure TestAmmos(var Actions: TActions; Me: PGear; isMoved: boolean);
 var BotLevel: Byte;
     ap: TAttackParams;
-    Score, i: LongInt;
+    Score, i, dAngle: LongInt;
     a, aa: TAmmoType;
 begin
 BotLevel:= Me^.Hedgehog^.BotLevel;
@@ -153,29 +153,45 @@
                     
                     if (ap.Time <> 0) then
                         AddAction(BestActions, aia_Timer, ap.Time div 1000, 400, 0, 0);
+                        
                     if (Ammoz[a].Ammo.Propz and ammoprop_NoCrosshair) = 0 then
                         begin
-                        ap.Angle:= LongInt(Me^.Angle) - Abs(ap.Angle);
-                        if ap.Angle > 0 then
+                        dAngle:= LongInt(Me^.Angle) - Abs(ap.Angle);
+                        if dAngle > 0 then
                             begin
                             AddAction(BestActions, aia_Up, aim_push, 300 + random(250), 0, 0);
-                            AddAction(BestActions, aia_Up, aim_release, ap.Angle, 0, 0)
+                            AddAction(BestActions, aia_Up, aim_release, dAngle, 0, 0)
                             end
-                        else if ap.Angle < 0 then
+                        else if dAngle < 0 then
                             begin
                             AddAction(BestActions, aia_Down, aim_push, 300 + random(250), 0, 0);
-                            AddAction(BestActions, aia_Down, aim_release, -ap.Angle, 0, 0)
+                            AddAction(BestActions, aia_Down, aim_release, -dAngle, 0, 0)
                             end
                         end;
+                        
                     if (Ammoz[a].Ammo.Propz and ammoprop_NeedTarget) <> 0 then
                         begin
                         AddAction(BestActions, aia_Put, 0, 1, ap.AttackPutX, ap.AttackPutY)
                         end;
-                    if (Ammoz[a].Ammo.Propz and ammoprop_AttackingPut) = 0 then
+                        
+                    if (Ammoz[a].Ammo.Propz and ammoprop_OscAim) <> 0 then
                         begin
-                        AddAction(BestActions, aia_attack, aim_push, 650 + random(300), 0, 0);
-                        AddAction(BestActions, aia_attack, aim_release, ap.Power, 0, 0);
-                        end;
+                        AddAction(BestActions, aia_attack, aim_push, 350 + random(200), 0, 0);
+                        AddAction(BestActions, aia_attack, aim_release, 1, 0, 0);
+                                                
+                        AddAction(BestActions, aia_Down, aim_push, 100 + random(150), 0, 0);
+                        AddAction(BestActions, aia_Down, aim_release, 32, 0, 0);
+                        
+                        AddAction(BestActions, aia_waitAngle, ap.Angle, 250, 0, 0);
+                        AddAction(BestActions, aia_attack, aim_push, 1, 0, 0);
+                        AddAction(BestActions, aia_attack, aim_release, 1, 0, 0);
+                        end else
+                        if (Ammoz[a].Ammo.Propz and ammoprop_AttackingPut) = 0 then
+                            begin
+                            AddAction(BestActions, aia_attack, aim_push, 650 + random(300), 0, 0);
+                            AddAction(BestActions, aia_attack, aim_release, ap.Power, 0, 0);
+                            end;
+                            
                     if ap.ExplR > 0 then
                         AddAction(BestActions, aia_AwareExpl, ap.ExplR, 10, ap.ExplX, ap.ExplY);
                     end
@@ -218,81 +234,92 @@
 BestRate:= RatePlace(Me);
 BaseRate:= Max(BestRate, 0);
 
+// switch to 'skip' if we can't move because of mouse cursor being shown
 if (Ammoz[Me^.Hedgehog^.CurAmmoType].Ammo.Propz and ammoprop_NeedTarget) <> 0 then
     AddAction(Actions, aia_Weapon, Longword(amSkip), 100 + random(200), 0, 0);
-
-tmp:= random(2) + 1;
-Push(0, Actions, Me^, tmp);
-Push(0, Actions, Me^, tmp xor 3);
     
-while (Stack.Count > 0) and (not StopThinking) and (GameFlags and gfArtillery = 0) do
+if ((CurrentHedgehog^.MultiShootAttacks = 0) or ((Ammoz[Me^.Hedgehog^.CurAmmoType].Ammo.Propz and ammoprop_NoMoveAfter) = 0)) 
+    and (GameFlags and gfArtillery = 0) then
     begin
-    Pop(ticks, Actions, Me^);
+    tmp:= random(2) + 1;
+    Push(0, Actions, Me^, tmp);
+    Push(0, Actions, Me^, tmp xor 3);
+    
+    while (Stack.Count > 0) and (not StopThinking) do
+        begin
+        Pop(ticks, Actions, Me^);
 
-    AddAction(Actions, Me^.Message, aim_push, 250, 0, 0);
-    if (Me^.Message and gmLeft) <> 0 then
-        AddAction(Actions, aia_WaitXL, hwRound(Me^.X), 0, 0, 0)
-    else
-        AddAction(Actions, aia_WaitXR, hwRound(Me^.X), 0, 0, 0);
-    
-    steps:= 0;
+        AddAction(Actions, Me^.Message, aim_push, 250, 0, 0);
+        if (Me^.Message and gmLeft) <> 0 then
+            AddAction(Actions, aia_WaitXL, hwRound(Me^.X), 0, 0, 0)
+        else
+            AddAction(Actions, aia_WaitXR, hwRound(Me^.X), 0, 0, 0);
+        
+        steps:= 0;
 
-    while (not StopThinking) do
-        begin
-{$HINTS OFF}
-        CanGo:= HHGo(Me, @AltMe, GoInfo);
-{$HINTS ON}
-        inc(ticks, GoInfo.Ticks);
-        if ticks > maxticks then
-            break;
+        while (not StopThinking) do
+            begin
+    {$HINTS OFF}
+            CanGo:= HHGo(Me, @AltMe, GoInfo);
+    {$HINTS ON}
+            inc(ticks, GoInfo.Ticks);
+            if ticks > maxticks then
+                break;
 
-        if (BotLevel < 5) and (GoInfo.JumpType = jmpHJump) then // hjump support
-            if Push(ticks, Actions, AltMe, Me^.Message) then
-                with Stack.States[Pred(Stack.Count)] do
-                    begin
-                    if Me^.dX.isNegative then
-                        AddAction(MadeActions, aia_LookRight, 0, 200, 0, 0)
-                    else
-                        AddAction(MadeActions, aia_LookLeft, 0, 200, 0, 0);
+            if (BotLevel < 5) and (GoInfo.JumpType = jmpHJump) then // hjump support
+                if Push(ticks, Actions, AltMe, Me^.Message) then
+                    with Stack.States[Pred(Stack.Count)] do
+                        begin
+                        if Me^.dX.isNegative then
+                            AddAction(MadeActions, aia_LookRight, 0, 200, 0, 0)
+                        else
+                            AddAction(MadeActions, aia_LookLeft, 0, 200, 0, 0);
+                            
+                        AddAction(MadeActions, aia_HJump, 0, 305 + random(50), 0, 0);
+                        AddAction(MadeActions, aia_HJump, 0, 350, 0, 0);
                         
-                    AddAction(MadeActions, aia_HJump, 0, 305 + random(50), 0, 0);
-                    AddAction(MadeActions, aia_HJump, 0, 350, 0, 0);
-                    
-                    if Me^.dX.isNegative then
-                        AddAction(MadeActions, aia_LookLeft, 0, 200, 0, 0)
-                    else
-                        AddAction(MadeActions, aia_LookRight, 0, 200, 0, 0);
-                    end;
-        if (BotLevel < 3) and (GoInfo.JumpType = jmpLJump) then // ljump support
-            if Push(ticks, Actions, AltMe, Me^.Message) then
-                with Stack.States[Pred(Stack.Count)] do
-                    AddAction(MadeActions, aia_LJump, 0, 305 + random(50), 0, 0);
+                        if Me^.dX.isNegative then
+                            AddAction(MadeActions, aia_LookLeft, 0, 200, 0, 0)
+                        else
+                            AddAction(MadeActions, aia_LookRight, 0, 200, 0, 0);
+                        end;
+            if (BotLevel < 3) and (GoInfo.JumpType = jmpLJump) then // ljump support
+                begin
+                // push current position so we proceed from it after checking jump opportunities
+                if CanGo then Push(ticks, Actions, Me^, Me^.Message);
+                // first check where we go after jump
+                if Push(ticks, Actions, AltMe, Me^.Message) then
+                    with Stack.States[Pred(Stack.Count)] do
+                        AddAction(MadeActions, aia_LJump, 0, 305 + random(50), 0, 0);
+                break
+                end;
 
-        // 'not CanGO' means we can't go straight, possible jumps are checked above
-        if not CanGo then
-            break;
-        
-         inc(steps);
-         Actions.actions[Pred(Actions.Count)].Param:= hwRound(Me^.X);
-         Rate:= RatePlace(Me);
-         if Rate > BestRate then
-            begin
-            BestActions:= Actions;
-            BestActions.isWalkingToABetterPlace:= true;
-            BestRate:= Rate;
-            Me^.State:= Me^.State or gstAttacked // we have better place, go there and do not use ammo
-            end
-        else if Rate < BestRate then
-            break;
-        if ((Me^.State and gstAttacked) = 0) and ((steps mod 4) = 0) then
-            TestAmmos(Actions, Me, true);
-        if GoInfo.FallPix >= FallPixForBranching then
-            Push(ticks, Actions, Me^, Me^.Message xor 3); // aia_Left xor 3 = aia_Right
-        end {while};
+            // 'not CanGO' means we can't go straight, possible jumps are checked above
+            if not CanGo then
+                break;
+            
+             inc(steps);
+             Actions.actions[Pred(Actions.Count)].Param:= hwRound(Me^.X);
+             Rate:= RatePlace(Me);
+             if Rate > BestRate then
+                begin
+                BestActions:= Actions;
+                BestActions.isWalkingToABetterPlace:= true;
+                BestRate:= Rate;
+                Me^.State:= Me^.State or gstAttacked // we have better place, go there and do not use ammo
+                end
+            else if Rate < BestRate then
+                break;
+            if ((Me^.State and gstAttacked) = 0) and ((steps mod 4) = 0) then
+                TestAmmos(Actions, Me, true);
+            if GoInfo.FallPix >= FallPixForBranching then
+                Push(ticks, Actions, Me^, Me^.Message xor 3); // aia_Left xor 3 = aia_Right
+            end {while};
 
-    if BestRate > BaseRate then
-        exit
+        if BestRate > BaseRate then
+            exit
         end {while}
+    end {if}
 end;
 
 function Think(Me: Pointer): ptrint;
@@ -414,6 +441,8 @@
 AddFileLog('Thread started');
 end;
 
+//var scoreShown: boolean = false;
+
 procedure ProcessBot;
 const cStopThinkTime = 40;
 begin
@@ -430,16 +459,27 @@
                     StopMessages(Gear^.Message);
                     TryDo((Gear^.Message and gmAllStoppable) = 0, 'Engine bug: AI may break demos playing', true);
                     end;
+                    
                 if Gear^.Message <> 0 then
                     exit;
+                    
+                //scoreShown:= false;   
                 StartThink(Gear);
                 StartTicks:= GameTicks
                 
-                end else
-                    ProcessAction(BestActions, Gear)
+            end else
+                begin
+                (*
+                if not scoreShown then
+                    begin
+                    if BestActions.Score > 0 then ParseCommand('/say Expected score = ' + inttostr(BestActions.Score div 1024), true);
+                    scoreShown:= true
+                    end;*)
+                ProcessAction(BestActions, Gear)
+                end
         else if ((GameTicks - StartTicks) > cMaxAIThinkTime)
-        or (TurnTimeLeft <= cStopThinkTime) then
-            StopThinking:= true
+            or (TurnTimeLeft <= cStopThinkTime) then
+                StopThinking:= true
 end;
 
 procedure initModule;
--- a/hedgewars/uAIActions.pas	Tue Jun 05 22:37:36 2012 +0200
+++ b/hedgewars/uAIActions.pas	Mon Jun 25 10:44:27 2012 +0200
@@ -43,6 +43,7 @@
     aia_Skip       = $8008;
     aia_Wait       = $8009;
     aia_Put        = $800A;
+    aia_waitAngle  = $800B;
     
     aim_push       = $8000;
     aim_release    = $8001;
@@ -70,7 +71,7 @@
 var PrevX: LongInt = 0;
     timedelta: Longword = 0;
 
-const ActionIdToStr: array[0..7] of string[16] = (
+const ActionIdToStr: array[0..8] of string[16] = (
 {aia_none}           '',
 {aia_Left}           'left',
 {aia_Right}          'right',
@@ -78,7 +79,8 @@
 {aia_attack}         'attack',
 {aia_Up}             'up',
 {aia_Down}           'down',
-{aia_Switch}         'switch'
+{aia_Switch}         'switch',
+{aia_waitAngle}      'waitAngle'
                      );
 
 {$IFDEF TRACEAIACTIONS}
@@ -150,6 +152,7 @@
 begin
 repeat
 if Actions.Pos >= Actions.Count then exit;
+
 with Actions.actions[Actions.Pos] do
     begin
     if Time > GameTicks then
@@ -160,74 +163,77 @@
     if (Action and ai_specmask) <> 0 then
         case Action of
             aia_Weapon: 
-            SetWeapon(TAmmoType(Param));
+                SetWeapon(TAmmoType(Param));
             
             aia_WaitXL: 
-            if hwRound(Me^.X) = Param then
-                begin
-                Action:= aia_LookLeft;
-                Time:= GameTicks;
-                exit
-                end
-                else if hwRound(Me^.X) < Param then
+                if hwRound(Me^.X) = Param then
                     begin
-                    //OutError('AI: WaitXL assert (' + IntToStr(hwRound(Me^.X)) + ' < ' + IntToStr(Param) + ')', false);
-                    FreeActionsList;
+                    Action:= aia_LookLeft;
+                    Time:= GameTicks;
+                    exit
+                    end
+                    else if hwRound(Me^.X) < Param then
+                        begin
+                        //OutError('AI: WaitXL assert (' + IntToStr(hwRound(Me^.X)) + ' < ' + IntToStr(Param) + ')', false);
+                        FreeActionsList;
+                        exit
+                        end
+                    else
+                        begin 
+                        CheckHang(Me);
+                        exit
+                        end;
+                            
+            aia_WaitXR: 
+                if hwRound(Me^.X) = Param then
+                    begin
+                    Action:= aia_LookRight;
+                    Time:= GameTicks;
+                    exit
+                    end
+                    else if hwRound(Me^.X) > Param then
+                        begin
+                        //OutError('AI: WaitXR assert (' + IntToStr(hwRound(Me^.X)) + ' > ' + IntToStr(Param) + ')', false);
+                        FreeActionsList;
+                        exit
+                        end
+                    else
+                        begin 
+                        CheckHang(Me);
+                        exit
+                        end;
+            aia_LookLeft:
+                if not Me^.dX.isNegative then
+                    begin
+                    ParseCommand('+left', true);
                     exit
                     end
                 else
-                    begin 
-                    CheckHang(Me);
-                    exit
-                    end;
-                            
-            aia_WaitXR: 
-            if hwRound(Me^.X) = Param then
-                begin
-                Action:= aia_LookRight;
-                Time:= GameTicks;
-                exit
-                end
-                else if hwRound(Me^.X) > Param then
+                    ParseCommand('-left', true);
+            aia_LookRight:
+                if Me^.dX.isNegative then
                     begin
-                    //OutError('AI: WaitXR assert (' + IntToStr(hwRound(Me^.X)) + ' > ' + IntToStr(Param) + ')', false);
-                    FreeActionsList;
+                    ParseCommand('+right', true);
                     exit
                     end
-                else
-                    begin 
-                    CheckHang(Me);
-                    exit
-                    end;
-            aia_LookLeft:
-            if not Me^.dX.isNegative then
-                begin
-                ParseCommand('+left', true);
-                exit
-                end
-            else
-                ParseCommand('-left', true);
-            aia_LookRight:
-            if Me^.dX.isNegative then
-                begin
-                ParseCommand('+right', true);
-                exit
-                end
-            else ParseCommand('-right', true);
+                else ParseCommand('-right', true);
             aia_AwareExpl:
-            AwareOfExplosion(X, Y, Param);
+                AwareOfExplosion(X, Y, Param);
             
             aia_HJump:
-            ParseCommand('hjump', true);
+                ParseCommand('hjump', true);
             
             aia_LJump:
-            ParseCommand('ljump', true);
+                ParseCommand('ljump', true);
             
             aia_Skip:
-            ParseCommand('skip', true);
+                ParseCommand('skip', true);
             
             aia_Put:
-            doPut(X, Y, true);
+                doPut(X, Y, true);
+                
+            aia_waitAngle:
+                if Me^.Angle <> Abs(Param) then exit;
             end
         else
             begin
--- a/hedgewars/uAIAmmoTests.pas	Tue Jun 05 22:37:36 2012 +0200
+++ b/hedgewars/uAIAmmoTests.pas	Mon Jun 25 10:44:27 2012 +0200
@@ -43,6 +43,7 @@
 function TestMortar(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
 function TestShotgun(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
 function TestDesertEagle(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
+function TestSniperRifle(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
 function TestBaseballBat(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
 function TestFirePunch(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
 function TestWhip(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
@@ -97,7 +98,7 @@
             (proc: nil;              flags: 0), // amExtraTime
             (proc: nil;              flags: 0), // amLaserSight
             (proc: nil;              flags: 0), // amVampiric
-            (proc: nil;              flags: 0), // amSniperRifle
+            (proc: @TestSniperRifle; flags: 0), // amSniperRifle
             (proc: nil;              flags: 0), // amJetpack
             (proc: @TestMolotov;     flags: 0), // amMolotov
             (proc: nil;              flags: 0), // amBirdy
@@ -160,7 +161,8 @@
             dX:= dX + windSpeed;
             dY:= dY + cGravityf;
             dec(t)
-        until TestCollExcludingMe(Me, trunc(x), trunc(y), 5) or (t <= 0);
+        until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or 
+               ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me, trunc(x), trunc(y), 5))) or (t <= 0);
         
         EX:= trunc(x);
         EY:= trunc(y);
@@ -218,7 +220,8 @@
             dX:= dX + windSpeed;
             dY:= dY + cGravityf;
             dec(t)
-        until TestCollExcludingMe(Me, trunc(x), trunc(y), 5) or (t <= 0);
+        until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or 
+               ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me, trunc(x), trunc(y), 5))) or (t <= 0);
         EX:= trunc(x);
         EY:= trunc(y);
 
@@ -268,7 +271,8 @@
             y:= y + dY;
             dY:= dY + cGravityf;
             dec(t)
-        until TestCollExcludingMe(Me, trunc(x), trunc(y), 7) or (t = 0);
+        until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 6)) or 
+               ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me, trunc(x), trunc(y), 6))) or (t = 0);
         EX:= trunc(x);
         EY:= trunc(y);
         if t < 50 then
@@ -320,7 +324,8 @@
             y:= y + dY;
             dY:= dY + cGravityf;
             dec(t)
-        until TestCollExcludingMe(Me, trunc(x), trunc(y), 5) or (t = 0);
+        until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or 
+               ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me, trunc(x), trunc(y), 5))) or (t = 0);
     EX:= trunc(x);
     EY:= trunc(y);
     if t < 50 then 
@@ -379,7 +384,8 @@
         y:= y + dY;
         dY:= dY + cGravityf;
         dec(t)
-    until TestCollExcludingMe(Me, trunc(x), trunc(y), 5) or (t = 0);
+    until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 5)) or 
+           ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me, trunc(x), trunc(y), 5))) or (t = 0);
     EX:= trunc(x);
     EY:= trunc(y);
     if t < 50 then 
@@ -431,7 +437,8 @@
             y:= y + dY;
             dY:= dY + cGravityf;
             dec(t)
-        until TestCollExcludingMe(Me, trunc(x), trunc(y), 7) or (t = 0);
+       until (((Me = CurrentHedgehog^.Gear) and TestColl(trunc(x), trunc(y), 6)) or 
+               ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me, trunc(x), trunc(y), 6))) or (t = 0);
         
         EX:= trunc(x);
         EY:= trunc(y);
@@ -510,7 +517,8 @@
         dY:= dY + cGravityf;
         EX:= trunc(x);
         EY:= trunc(y);
-    until TestCollExcludingMe(Me, EX, EY, 5) or (EY > cWaterLine);
+    until (((Me = CurrentHedgehog^.Gear) and TestColl(EX, EY, 4)) or 
+           ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me, EX, EY, 4))) or (EY > cWaterLine);
 
     if (EY < cWaterLine) and (dY >= 0) then
         begin
@@ -563,7 +571,8 @@
     y:= y + vY;
     rx:= trunc(x);
     ry:= trunc(y);
-    if TestCollExcludingMe(Me, rx, ry, 2) then
+    if ((Me = CurrentHedgehog^.Gear) and TestColl(rx, ry, 2)) or 
+        ((Me <> CurrentHedgehog^.Gear) and TestCollExcludingMe(Me, rx, ry, 2)) then
     begin
         x:= x + vX * 8;
         y:= y + vY * 8;
@@ -602,7 +611,56 @@
     TestDesertEagle:= BadTurn;
     exit(BadTurn);
     end;
-t:= 0.5 / sqrt(sqr(Targ.X - x)+sqr(Targ.Y-y));
+t:= 2 / sqrt(sqr(Targ.X - x)+sqr(Targ.Y-y));
+Vx:= (Targ.X - x) * t;
+Vy:= (Targ.Y - y) * t;
+ap.Angle:= DxDy2AttackAnglef(Vx, -Vy);
+d:= 0;
+
+repeat
+    x:= x + vX;
+    y:= y + vY;
+    if ((trunc(x) and LAND_WIDTH_MASK) = 0)and((trunc(y) and LAND_HEIGHT_MASK) = 0)
+    and (Land[trunc(y), trunc(x)] <> 0) then
+        inc(d);
+until (Abs(Targ.X - trunc(x)) + Abs(Targ.Y - trunc(y)) < 5)
+    or (x < 0)
+    or (y < 0)
+    or (trunc(x) > LAND_WIDTH)
+    or (trunc(y) > LAND_HEIGHT)
+    or (d > 50);
+
+if Abs(Targ.X - trunc(x)) + Abs(Targ.Y - trunc(y)) < 5 then
+    begin
+    fallDmg:= TraceShoveFall(Targ.X, Targ.Y, vX * 0.00125 * 20, vY * 0.00125 * 20);
+    if fallDmg < 0 then
+        valueResult:= 204800
+    else valueResult:= Max(0, (4 - d div 50) * trunc((7+fallDmg)*dmgMod) * 1024)
+    end
+else
+    valueResult:= BadTurn;
+TestDesertEagle:= valueResult
+end;
+
+
+function TestSniperRifle(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
+var Vx, Vy, x, y, t, dmg, dmgMod: real;
+    d: Longword;
+    fallDmg, valueResult: LongInt;
+begin
+dmgMod:= 0.01 * hwFloat2Float(cDamageModifier) * cDamagePercent;
+Level:= Level; // avoid compiler hint
+ap.ExplR:= 0;
+ap.Time:= 0;
+ap.Power:= 1;
+x:= hwFloat2Float(Me^.X);
+y:= hwFloat2Float(Me^.Y);
+if Abs(trunc(x) - Targ.X) + Abs(trunc(y) - Targ.Y) < 40 then
+    exit(BadTurn);
+
+dmg:= sqrt(sqr(Targ.X - x)+sqr(Targ.Y-y));
+t:= 1.5 / dmg;
+dmg:= dmg * 0.025; // div 40
 Vx:= (Targ.X - x) * t;
 Vy:= (Targ.Y - y) * t;
 ap.Angle:= DxDy2AttackAnglef(Vx, -Vy);
@@ -619,149 +677,172 @@
     or (y < 0)
     or (trunc(x) > LAND_WIDTH)
     or (trunc(y) > LAND_HEIGHT)
-    or (d > 200);
+    or (d > 23);
 
-if Abs(Targ.X - trunc(x)) + Abs(Targ.Y - trunc(y)) < 3 then
+if Abs(Targ.X - trunc(x)) + Abs(Targ.Y - trunc(y)) < 4 then
     begin
-    fallDmg:= TraceShoveFall(Me, Targ.X, Targ.Y, vX * 0.005 * 20, vY * 0.005 * 20);
+    fallDmg:= TraceShoveFall(Targ.X, Targ.Y, vX * 0.00166 * dmg, vY * 0.00166 * dmg);
     if fallDmg < 0 then
-        valueResult:= 204800
-    else valueResult:= Max(0, (4 - d div 50) * trunc((7+fallDmg)*dmgMod) * 1024)
+        TestSniperRifle:= BadTurn
+    else 
+        TestSniperRifle:= Max(0, trunc((dmg + fallDmg) * dmgMod) * 1024)
     end
 else
-    valueResult:= BadTurn;
-TestDesertEagle:= valueResult
+    TestSniperRifle:= BadTurn
 end;
 
+
 function TestBaseballBat(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
-var valueResult: LongInt;
-    x, y: real;
+var valueResult, a, v1, v2: LongInt;
+    x, y: LongInt;
+    dx, dy: real;
 begin
-Level:= Level; // avoid compiler hint
-TestBaseballBat:= BadTurn;
-ap.ExplR:= 0;
-x:= hwFloat2Float(Me^.X);
-y:= hwFloat2Float(Me^.Y);
-if (Level > 2) then
-    exit(BadTurn);
+    Level:= Level; // avoid compiler hint
+    ap.ExplR:= 0;
+    ap.Time:= 0;
+    ap.Power:= 1;
+    x:= hwRound(Me^.X);
+    y:= hwRound(Me^.Y);
+
+    a:= 0;
+    valueResult:= 0;
+
+    while a <= cMaxAngle div 2 do
+        begin
+        dx:= sin(a / cMaxAngle * pi) * 0.5;
+        dy:= cos(a / cMaxAngle * pi) * 0.5;
 
-ap.Time:= 0;
-ap.Power:= 1;
-if (Targ.X) - trunc(x) >= 0 then
-    ap.Angle:=   cMaxAngle div 4
-else
-    ap.Angle:= - cMaxAngle div 4;
+        v1:= RateShove(Me, x - 10, y
+                , 33, 30, 115
+                , -dx, -dy, afTrackFall);
+        v2:= RateShove(Me, x + 10, y
+                , 33, 30, 115
+                , dx, -dy, afTrackFall);
+        if (v1 > valueResult) or (v2 > valueResult) then
+            if (v2 > v1) 
+                or {don't encourage turning for no gain}((v2 = v1) and (not Me^.dX.isNegative)) then
+                begin
+                ap.Angle:= a;
+                valueResult:= v2
+                end
+            else 
+                begin
+                ap.Angle:= -a;
+                valueResult:= v1
+                end;
 
-valueResult:= RateShove(Me, trunc(x) + LongWord(10*hwSignf(Targ.X - x)), trunc(y), 15, 30, 115, hwSign(Me^.dX)*0.353, -0.353, afTrackFall);
-if valueResult <= 0 then
-    valueResult:= BadTurn
-else
-    inc(valueResult);
-TestBaseballBat:= valueResult;
+        a:= a + 15 + random(cMaxAngle div 16)
+        end;
+   
+    if valueResult <= 0 then
+        valueResult:= BadTurn;
+
+    TestBaseballBat:= valueResult;
 end;
 
 function TestFirePunch(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
-var val1, val2, i, t: LongInt;
-    x, y: real;
+var valueResult, v1, v2, i: LongInt;
+    x, y: LongInt;
 begin
-Level:= Level; // avoid compiler hint
-TestFirePunch:= BadTurn;
-ap.ExplR:= 0;
-ap.Time:= 0;
-ap.Power:= 1;
-ap.Angle:= hwSign(Me^.dX);
-x:= hwFloat2Float(Me^.X);
-y:= hwFloat2Float(Me^.Y);
-{
-// this block is for digging with firepunch when blocked close to walls (notice TestColl check)
-if (Abs(trunc(x) - Targ.X) > 25)
-    or (Abs(trunc(y) + 50 - Targ.Y) > 50) then
-    begin
-    if TestColl(trunc(x), trunc(y) - 16, 6) and 
-       (RateShove(Me, trunc(x) + LongWord(10 * hwSign(Me^.dX)), 
-                      trunc(y) - 40, 30, 30, 40, hwSign(Me^.dX)*0.45, -0.9,  1) >= 0) then
-        val1:= Succ(BadTurn)
-    else
-        val1:= BadTurn;
-    exit(val1);
-    end;
-    }
-// and this is actual try to attack
-val1:= 0;
-for i:= 0 to 4 do
-    begin
-    t:= RateShove(Me, trunc(x) + 10 * hwSignf(Targ.X - x), trunc(y) - 20 * i - 5, 10, 30, 40, hwSign(Me^.dX)*0.45, -0.9, afTrackFall);
-    if (val1 < 0) or (t < 0) then val1:= BadTurn
-    else if t > 0 then val1:= t;
-    end;
+    Level:= Level; // avoid compiler hint
+    ap.ExplR:= 0;
+    ap.Time:= 0;
+    ap.Power:= 1;
+    x:= hwRound(Me^.X);
+    y:= hwRound(Me^.Y);
+
+    v1:= 0;
+    for i:= 0 to 8 do
+        begin
+        v1:= v1 + RateShove(Me, x - 10, y - 10 * i
+                , 18, 30, 40
+                , -0.45, -0.9, afTrackFall or afSetSkip);
+        end;
+    v1:= v1 + RateShove(Me, x - 10, y - 90
+            , 18, 30, 40
+            , -0.45, -0.9, afTrackFall);
+
 
-val2:= 0;
-for i:= 0 to 4 do
-    begin
-    t:= RateShove(Me, trunc(x) + 10 * hwSignf(Targ.X - x), trunc(y) - 20 * i - 5, 10, 30, 40, -hwSign(Me^.dX)*0.45, -0.9, afTrackFall);
-    if (val2 < 0) or (t < 0) then val2:= BadTurn
-    else if t > 0 then val2:= t;
-    end;
-if (val1 > val2) and (val1 > 0) then 
-    TestFirePunch:= val1
-else if (val2 > val1) and (val2 > 0) then
-    begin
-    ap.Angle:= -hwSign(Me^.dX);
-    TestFirePunch:= val2
-    end
-else TestFirePunch:= BadTurn;
+    // now try opposite direction
+    v2:= 0;
+    for i:= 0 to 8 do
+        begin
+        v2:= v2 + RateShove(Me, x + 10, y - 10 * i
+                , 18, 30, 40
+                , 0.45, -0.9, afTrackFall or afSetSkip);
+        end;
+    v2:= v2 + RateShove(Me, x + 10, y - 90
+            , 18, 30, 40
+            , 0.45, -0.9, afTrackFall);
+
+    if (v2 > v1) 
+        or {don't encourage turning for no gain}((v2 = v1) and (not Me^.dX.isNegative)) then
+        begin
+        ap.Angle:= 1;
+        valueResult:= v2
+        end
+    else 
+        begin
+        ap.Angle:= -1;
+        valueResult:= v1
+        end;
+    
+    if valueResult <= 0 then
+        valueResult:= BadTurn;
+
+    TestFirePunch:= valueResult;
 end;
 
 
 function TestWhip(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
 var valueResult, v1, v2: LongInt;
-    x, y: real;
+    x, y: LongInt;
 begin
-Level:= Level; // avoid compiler hint
-ap.ExplR:= 0;
-ap.Time:= 0;
-ap.Power:= 1;
-x:= hwFloat2Float(Me^.X);
-y:= hwFloat2Float(Me^.Y);
+    Level:= Level; // avoid compiler hint
+    ap.ExplR:= 0;
+    ap.Time:= 0;
+    ap.Power:= 1;
+    x:= hwRound(Me^.X);
+    y:= hwRound(Me^.Y);
 
-// check left direction
-{first RateShove checks fartherest of two whip's AmmoShove attacks 
-to encourage distant attacks (damaged hog is excluded from view of second 
-RateShove call)}
-v1:= RateShove(Me, trunc(x) - 15, trunc(y)
-        , 30, 30, 40
-        , -1, -0.8, afTrackFall or afSetSkip);
-v1:= v1 +
-    RateShove(Me, trunc(x), trunc(y)
-        , 30, 30, 40
-        , -1, -0.8, afTrackFall);
-// now try opposite direction
-v2:= RateShove(Me, trunc(x) + 15, trunc(y)
-        , 30, 30, 40
-        , 1, -0.8, afTrackFall or afSetSkip);
-v2:= v2 +
-    RateShove(Me, trunc(x), trunc(y)
-        , 30, 30, 40
-        , 1, -0.8, afTrackFall);
+    // check left direction
+    {first RateShove checks farthermost of two whip's AmmoShove attacks 
+    to encourage distant attacks (damaged hog is excluded from view of second 
+    RateShove call)}
+    v1:= RateShove(Me, x - 15, y
+            , 30, 30, 25
+            , -1, -0.8, afTrackFall or afSetSkip);
+    v1:= v1 +
+        RateShove(Me, x, y
+            , 30, 30, 25
+            , -1, -0.8, afTrackFall);
+    // now try opposite direction
+    v2:= RateShove(Me, x + 15, y
+            , 30, 30, 25
+            , 1, -0.8, afTrackFall or afSetSkip);
+    v2:= v2 +
+        RateShove(Me, x, y
+            , 30, 30, 25
+            , 1, -0.8, afTrackFall);
 
-if (v2 > v1) 
-    or {don't encourage turning for no gain}((v2 = v1) and (not Me^.dX.isNegative)) then
-    begin
-    ap.Angle:= 1;
-    valueResult:= v2
-    end
-else 
-    begin
-    ap.Angle:= -1;
-    valueResult:= v1
-    end;
-   
-if valueResult <= 0 then
-    valueResult:= BadTurn
-else
-    inc(valueResult);
+    if (v2 > v1) 
+        or {don't encourage turning for no gain}((v2 = v1) and (not Me^.dX.isNegative)) then
+        begin
+        ap.Angle:= 1;
+        valueResult:= v2
+        end
+    else 
+        begin
+        ap.Angle:= -1;
+        valueResult:= v1
+        end;
+    
+    if valueResult <= 0 then
+        valueResult:= BadTurn
+    else
+        inc(valueResult);
 
-TestWhip:= valueResult;
+    TestWhip:= valueResult;
 end;
 
 function TestHammer(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt;
--- a/hedgewars/uAIMisc.pas	Tue Jun 05 22:37:36 2012 +0200
+++ b/hedgewars/uAIMisc.pas	Mon Jun 25 10:44:27 2012 +0200
@@ -59,8 +59,9 @@
 
 function  RatePlace(Gear: PGear): LongInt;
 function  TestColl(x, y, r: LongInt): boolean; inline;
+function  TestCollExcludingObjects(x, y, r: LongInt): boolean; inline;
 function  TestCollExcludingMe(Me: PGear; x, y, r: LongInt): boolean; inline;
-function  TraceShoveFall(Me: PGear; x, y, dX, dY: Real): LongInt;
+function  TraceShoveFall(x, y, dX, dY: Real): LongInt;
 
 function  RateExplosion(Me: PGear; x, y, r: LongInt): LongInt; inline;
 function  RateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord): LongInt;
@@ -80,7 +81,7 @@
         end;
 
 implementation
-uses uCollisions, uVariables, uUtils, uDebug;
+uses uCollisions, uVariables, uUtils, uDebug, uLandTexture;
 
 const KillScore = 200;
 
@@ -236,22 +237,44 @@
     TestCollExcludingMe:= TestColl(x, y, r)
 end;
 
-function TestColl(x, y, r: LongInt): boolean; inline;
+function TestCollExcludingObjects(x, y, r: LongInt): boolean; inline;
 var b: boolean;
 begin
-    b:= (((x-r) and LAND_WIDTH_MASK) = 0) and (((y-r) and LAND_HEIGHT_MASK) = 0) and (Land[y-r, x-r] <> 0);
+    b:= (((x-r) and LAND_WIDTH_MASK) = 0) and (((y-r) and LAND_HEIGHT_MASK) = 0) and (Land[y-r, x-r] and $FF00 <> 0);
+    if b then
+        exit(true);
+    
+    b:= (((x-r) and LAND_WIDTH_MASK) = 0) and (((y+r) and LAND_HEIGHT_MASK) = 0) and (Land[y+r, x-r] and $FF00 <> 0);
+    if b then
+        exit(true);
+    
+    b:= (((x+r) and LAND_WIDTH_MASK) = 0) and (((y-r) and LAND_HEIGHT_MASK) = 0) and (Land[y-r, x+r] and $FF00 <> 0);
+    if b then
+        exit(true);
+    
+    b:= (((x+r) and LAND_WIDTH_MASK) = 0) and (((y+r) and LAND_HEIGHT_MASK) = 0) and (Land[y+r, x+r] and $FF00 <> 0);
     if b then
         exit(true);
     
-    b:= (((x-r) and LAND_WIDTH_MASK) = 0) and (((y+r) and LAND_HEIGHT_MASK) = 0) and (Land[y+r, x-r] <> 0);
+    TestCollExcludingObjects:= false;
+end;
+
+function TestColl(x, y, r: LongInt): boolean; inline;
+var b: boolean;
+begin
+    b:= (((x-r) and LAND_WIDTH_MASK) = 0) and (((y-r) and LAND_HEIGHT_MASK) = 0) and (Land[y-r, x-r] and $FF7F <> 0);
     if b then
         exit(true);
     
-    b:= (((x+r) and LAND_WIDTH_MASK) = 0) and (((y-r) and LAND_HEIGHT_MASK) = 0) and (Land[y-r, x+r] <> 0);
+    b:= (((x-r) and LAND_WIDTH_MASK) = 0) and (((y+r) and LAND_HEIGHT_MASK) = 0) and (Land[y+r, x-r] and $FF7F <> 0);
     if b then
         exit(true);
     
-    b:= (((x+r) and LAND_WIDTH_MASK) = 0) and (((y+r) and LAND_HEIGHT_MASK) = 0) and (Land[y+r, x+r] <> 0);
+    b:= (((x+r) and LAND_WIDTH_MASK) = 0) and (((y-r) and LAND_HEIGHT_MASK) = 0) and (Land[y-r, x+r] and $FF7F <> 0);
+    if b then
+        exit(true);
+    
+    b:= (((x+r) and LAND_WIDTH_MASK) = 0) and (((y+r) and LAND_HEIGHT_MASK) = 0) and (Land[y+r, x+r] and $FF7F <> 0);
     if b then
         exit(true);
     
@@ -311,16 +334,25 @@
     end;
 end;
 
-function TraceShoveFall(Me: PGear; x, y, dX, dY: Real): LongInt;
-var dmg: LongInt;
+function TraceShoveFall(x, y, dX, dY: Real): LongInt;
+var dmg, v: LongInt;
 begin
+v:= random($FFFFFFFF);
     while true do
     begin
         x:= x + dX;
         y:= y + dY;
         dY:= dY + cGravityf;
+(*
+        if ((trunc(y) and LAND_HEIGHT_MASK) = 0) and ((trunc(x) and LAND_WIDTH_MASK) = 0) then 
+            begin
+            LandPixels[trunc(y), trunc(x)]:= v;
+            UpdateLandTexture(trunc(X), 1, trunc(Y), 1, true);
+            end;
+*)
+
         // consider adding dX/dY calc here for fall damage
-        if TestCollExcludingMe(Me, trunc(x), trunc(y), cHHRadius) then
+        if TestCollExcludingObjects(trunc(x), trunc(y), cHHRadius) then
         begin
             if 0.4 < dY then
             begin
@@ -398,8 +430,8 @@
     dX, dY, dmgMod: real;
 begin
 fallDmg:= 0;
-dX:= gdX * 0.005 * kick;
-dY:= gdY * 0.005 * kick;
+dX:= gdX * 0.01 * kick;
+dY:= gdY * 0.01 * kick;
 dmgMod:= 0.01 * hwFloat2Float(cDamageModifier) * cDamagePercent;
 rate:= 0;
 for i:= 0 to Pred(Targets.Count) do
@@ -410,15 +442,13 @@
         begin
         dmg:= 0;
         if abs(Point.x - x) + abs(Point.y - y) < r then
-            begin
             dmg:= r - trunc(sqrt(sqr(Point.x - x)+sqr(Point.y - y)));
-            dmg:= trunc(dmg * dmgMod);
-            end;
+
         if dmg > 0 then
             begin
             if (Flags and afSetSkip <> 0) then skip:= true;
-            if (Flags and afTrackFall <> 0) then 
-                fallDmg:= trunc(TraceShoveFall(Me, Point.x, Point.y - 2, dX, dY) * dmgMod);
+            if (Flags and afTrackFall <> 0) and (Score > 0) then 
+                fallDmg:= trunc(TraceShoveFall(Point.x, Point.y - 2, dX, dY) * dmgMod);
             if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI
                 if Score > 0 then
                     inc(rate, KillScore + Score div 10)   // Add a bit of a bonus for bigger hog drownings
@@ -504,17 +534,17 @@
 
 for i:= 0 to Pred(Targets.Count) do
     with Targets.ar[i] do
-        begin
          // hammer hit radius is 8, shift is 10
         if abs(Point.x - x) + abs(Point.y - y) < 18 then
+            begin
             r:= trunc(sqrt(sqr(Point.x - x)+sqr(Point.y - y)));
 
-        if r <= 18 then
-            if Score > 0 then 
-                inc(rate, Score div 3)
-            else 
-                inc(rate, Score div 3 * friendlyfactor div 100)
-        end;
+            if r <= 18 then
+                if Score > 0 then 
+                    inc(rate, Score div 3)
+                else
+                    inc(rate, Score div 3 * friendlyfactor div 100)
+            end;
 RateHammer:= rate * 1024;
 end;
 
--- a/hedgewars/uCollisions.pas	Tue Jun 05 22:37:36 2012 +0200
+++ b/hedgewars/uCollisions.pas	Mon Jun 25 10:44:27 2012 +0200
@@ -82,7 +82,7 @@
     X:= hwRound(Gear^.X);
     Y:= hwRound(Gear^.Y);
     Radius:= Gear^.Radius;
-    ChangeRoundInLand(X, Y, Radius - 1, true);
+    ChangeRoundInLand(X, Y, Radius - 1, true, Gear = CurrentHedgehog^.Gear);
     cGear:= Gear
     end;
 Gear^.CollisionIndex:= Count;
@@ -103,7 +103,7 @@
 if Gear^.CollisionIndex >= 0 then
     begin
     with cinfos[Gear^.CollisionIndex] do
-        ChangeRoundInLand(X, Y, Radius - 1, false);
+        ChangeRoundInLand(X, Y, Radius - 1, false, Gear = CurrentHedgehog^.Gear);
     cinfos[Gear^.CollisionIndex]:= cinfos[Pred(Count)];
     cinfos[Gear^.CollisionIndex].cGear^.CollisionIndex:= Gear^.CollisionIndex;
     Gear^.CollisionIndex:= -1;
@@ -138,17 +138,11 @@
 var x, y, i: LongInt;
     TestWord: LongWord;
 begin
-if Gear^.IntersectGear <> nil then
-    with Gear^ do
-        if (hwRound(IntersectGear^.X) + IntersectGear^.Radius < hwRound(X) - Radius)
-        or (hwRound(IntersectGear^.X) - IntersectGear^.Radius > hwRound(X) + Radius) then
-            begin
-            IntersectGear:= nil;
-            TestWord:= 0
-            end
-        else
-            TestWord:= 255
-    else TestWord:= 0;
+// Special case to emulate the old intersect gear clearing, but with a bit of slop for pixel overlap
+if (Gear^.CollisionMask = $FF7F) and (Gear^.Hedgehog <> nil) and (Gear^.Hedgehog^.Gear <> nil) and
+    ((hwRound(Gear^.Hedgehog^.Gear^.X) + Gear^.Hedgehog^.Gear^.Radius + 4 < hwRound(Gear^.X) - Gear^.Radius) or
+     (hwRound(Gear^.Hedgehog^.Gear^.X) - Gear^.Hedgehog^.Gear^.Radius - 4 > hwRound(Gear^.X) + Gear^.Radius)) then
+    Gear^.CollisionMask:= $FFFF;
 
 x:= hwRound(Gear^.X);
 if Dir < 0 then
@@ -163,7 +157,7 @@
     i:= y + Gear^.Radius * 2 - 2;
     repeat
         if (y and LAND_HEIGHT_MASK) = 0 then
-            if Land[y, x] > TestWord then
+            if Land[y, x] and Gear^.CollisionMask <> 0 then
                 exit;
         inc(y)
     until (y > i);
@@ -175,36 +169,30 @@
 var x, y, i: LongInt;
     TestWord: LongWord;
 begin
-if Gear^.IntersectGear <> nil then
-    with Gear^ do
-        if (hwRound(IntersectGear^.Y) + IntersectGear^.Radius < hwRound(Y) - Radius) or
-            (hwRound(IntersectGear^.Y) - IntersectGear^.Radius > hwRound(Y) + Radius) then
-                begin
-                IntersectGear:= nil;
-                TestWord:= 0
-                end
-        else
-            TestWord:= 255
-else
-    TestWord:= 0;
+// Special case to emulate the old intersect gear clearing, but with a bit of slop for pixel overlap
+if (Gear^.CollisionMask = $FF7F) and (Gear^.Hedgehog <> nil) and (Gear^.Hedgehog^.Gear <> nil) and
+    ((hwRound(Gear^.Hedgehog^.Gear^.Y) + Gear^.Hedgehog^.Gear^.Radius + 4 < hwRound(Gear^.Y) - Gear^.Radius) or
+     (hwRound(Gear^.Hedgehog^.Gear^.Y) - Gear^.Hedgehog^.Gear^.Radius - 4 > hwRound(Gear^.Y) + Gear^.Radius)) then
+    Gear^.CollisionMask:= $FFFF;
 
 y:= hwRound(Gear^.Y);
 if Dir < 0 then
     y:= y - Gear^.Radius
 else
     y:= y + Gear^.Radius;
+
 if (y and LAND_HEIGHT_MASK) = 0 then
     begin
     x:= hwRound(Gear^.X) - Gear^.Radius + 1;
     i:= x + Gear^.Radius * 2 - 2;
     repeat
         if (x and LAND_WIDTH_MASK) = 0 then
-            if Land[y, x] > TestWord then
-            begin
+            if Land[y, x] and Gear^.CollisionMask <> 0 then
+                begin
                 TestCollisionYwithGear:= Land[y, x];
                 exit;
-            end;
-     inc(x)
+                end;
+        inc(x)
     until (x > i);
     end;
 TestCollisionYwithGear:= 0
--- a/hedgewars/uCommandHandlers.pas	Tue Jun 05 22:37:36 2012 +0200
+++ b/hedgewars/uCommandHandlers.pas	Mon Jun 25 10:44:27 2012 +0200
@@ -436,7 +436,7 @@
         end
     else
         TryDo(checksum = lastTurnChecksum, 'Desync detected', true);
-    AddFileLog('Doing SwitchHedgehog: time '+inttostr(GameTicks));
+    AddFileLog('Next turn: time '+inttostr(GameTicks));
 end;
 
 procedure chTimer(var s: shortstring);
@@ -763,7 +763,8 @@
 
 procedure chGameFlags(var s: shortstring);
 begin
-GameFlags:= StrToInt(s)
+GameFlags:= StrToInt(s);
+if GameFlags and gfSharedAmmo <> 0 then GameFlags:= GameFlags and not gfPerHogAmmo
 end;
 
 procedure chHedgehogTurnTime(var s: shortstring);
--- a/hedgewars/uConsts.pas	Tue Jun 05 22:37:36 2012 +0200
+++ b/hedgewars/uConsts.pas	Mon Jun 25 10:44:27 2012 +0200
@@ -147,6 +147,7 @@
     cBlowTorchC    = 6;
 
     cKeyMaxIndex = 1023;
+    cKbdMaxIndex = 65536;//need more room for the modifier keys
 
     cHHFileName = 'Hedgehog';
     cCHFileName = 'Crosshair';
@@ -259,6 +260,8 @@
     ammoprop_Effect       = $00002000;
     ammoprop_SetBounce    = $00004000;
     ammoprop_NeedUpDown   = $00008000;//Used by TouchInterface to show or hide up/down widgets 
+    ammoprop_OscAim       = $00010000;
+    ammoprop_NoMoveAfter  = $00020000;
     ammoprop_NoRoundEnd   = $10000000;
 
     AMMO_INFINITE = 100;
--- a/hedgewars/uGearsHedgehog.pas	Tue Jun 05 22:37:36 2012 +0200
+++ b/hedgewars/uGearsHedgehog.pas	Mon Jun 25 10:44:27 2012 +0200
@@ -395,6 +395,7 @@
             newGear^.Target.X:= TargetPoint.X;
             newGear^.Target.Y:= TargetPoint.Y
             end;
+        if newGear <> nil then newGear^.CollisionMask:= $FF7F;
 
         // Clear FollowGear if using on a rope/parachute/saucer etc so focus stays with the hog's movement
         if altUse then
@@ -707,12 +708,10 @@
     if (Gear^.Message and gmLeft  )<>0 then
         Gear^.dX:= -cLittle else
     if (Gear^.Message and gmRight )<>0 then
-        Gear^.dX:=  cLittle else exit;
+        Gear^.dX:=  cLittle 
+        else exit;
 
-    if (Gear^.Message and (gmLeft or gmRight)) <> 0 then
-        begin
-        StepSoundTimer:= cHHStepTicks;
-        end;
+    StepSoundTimer:= cHHStepTicks;
    
     GHStepTicks:= cHHStepTicks;
     if PrevdX <> hwSign(Gear^.dX) then
@@ -837,6 +836,7 @@
     if (CurrentHedgehog^.Gear = Gear)
         and (hwSqr(Gear^.dX) + hwSqr(Gear^.dY) > _0_003) then 
         begin
+        // TODO: why so aggressive at setting FollowGear when falling?
         FollowGear:= Gear;
         end;
     if isUnderwater then
--- a/hedgewars/uGearsList.pas	Tue Jun 05 22:37:36 2012 +0200
+++ b/hedgewars/uGearsList.pas	Mon Jun 25 10:44:27 2012 +0200
@@ -100,15 +100,14 @@
 gear^.Density:= _1;
 // Define ammo association, if any.
 gear^.AmmoType:= GearKindAmmoTypeMap[Kind];
+gear^.CollisionMask:= $FFFF;
+
+if CurrentHedgehog <> nil then gear^.Hedgehog:= CurrentHedgehog;
+
 if Ammoz[Gear^.AmmoType].Ammo.Propz and ammoprop_NeedTarget <> 0 then
     gear^.Z:= cHHZ+1
 else gear^.Z:= cUsualZ;
 
-if CurrentHedgehog <> nil then
-    begin
-    gear^.Hedgehog:= CurrentHedgehog;
-    gear^.IntersectGear:= CurrentHedgehog^.Gear
-    end;
     
 case Kind of
      gtGrenade,
@@ -247,7 +246,7 @@
                 gear^.nImpactSounds:= 1;
                 gear^.Radius:= 16;
                 gear^.Elasticity:= _0_3;
-                gear^.Timer:= 0
+                gear^.Timer:= 500
                 end;
   gtExplosives: begin
                 gear^.ImpactSound:= sndGrenadeImpact;
@@ -483,9 +482,9 @@
 // make sure that portals have their link removed before deletion
 if (Gear^.Kind = gtPortal) then
     begin
-    if (Gear^.IntersectGear <> nil) then
-        if (Gear^.IntersectGear^.IntersectGear = Gear) then
-            Gear^.IntersectGear^.IntersectGear:= nil;
+    if (Gear^.LinkedGear <> nil) then
+        if (Gear^.LinkedGear^.LinkedGear = Gear) then
+            Gear^.LinkedGear^.LinkedGear:= nil;
     end
 else if Gear^.Kind = gtHedgehog then
     (*
--- a/hedgewars/uGearsRender.pas	Tue Jun 05 22:37:36 2012 +0200
+++ b/hedgewars/uGearsRender.pas	Mon Jun 25 10:44:27 2012 +0200
@@ -946,8 +946,8 @@
        gtBall: DrawSpriteRotatedF(sprBalls, x, y, Gear^.Tag,0, Gear^.DirAngle);
 
        gtPortal: if ((Gear^.Tag and 1) = 0) // still moving?
-                 or (Gear^.IntersectGear = nil) or (Gear^.IntersectGear^.IntersectGear <> Gear) // not linked&backlinked?
-                 or ((Gear^.IntersectGear^.Tag and 1) = 0) then // linked portal still moving?
+                 or (Gear^.LinkedGear = nil) or (Gear^.LinkedGear^.LinkedGear <> Gear) // not linked&backlinked?
+                 or ((Gear^.LinkedGear^.Tag and 1) = 0) then // linked portal still moving?
                       DrawSpriteRotatedF(sprPortal, x, y, Gear^.Tag, hwSign(Gear^.dX), Gear^.DirAngle)
                  else DrawSpriteRotatedF(sprPortal, x, y, 4 + Gear^.Tag div 2, hwSign(Gear^.dX), Gear^.DirAngle);
 
@@ -988,30 +988,36 @@
                        else DrawSpriteRotated(sprMineDead, x, y, 0, Gear^.DirAngle);
                        
             gtCase: begin
-                    if Gear^.Timer < 255 then Tint($FF, $FF, $FF, Gear^.Timer);
-                    if ((Gear^.Pos and posCaseAmmo) <> 0) then
-                        begin
-                        i:= (GameTicks shr 6) mod 64;
-                        if i > 18 then
-                            i:= 0;
-                        DrawSprite(sprCase, x - 24, y - 24, i);
-                        end
-                    else if ((Gear^.Pos and posCaseHealth) <> 0) then
+                    if Gear^.Timer > 1000 then
                         begin
-                        i:= ((GameTicks shr 6) + 38) mod 64;
-                        if i > 13 then
-                            i:= 0;
-                        DrawSprite(sprFAid, x - 24, y - 24, i);
-                        end
-                    else if ((Gear^.Pos and posCaseUtility) <> 0) then
+                        if ((Gear^.Pos and posCaseAmmo) <> 0) then
+                            begin
+                            i:= (GameTicks shr 6) mod 64;
+                            if i > 18 then
+                                i:= 0;
+                            DrawSprite(sprCase, x - 24, y - 24, i);
+                            end
+                        else if ((Gear^.Pos and posCaseHealth) <> 0) then
+                            begin
+                            i:= ((GameTicks shr 6) + 38) mod 64;
+                            if i > 13 then
+                                i:= 0;
+                            DrawSprite(sprFAid, x - 24, y - 24, i);
+                            end
+                        else if ((Gear^.Pos and posCaseUtility) <> 0) then
+                            begin
+                            i:= (GameTicks shr 6) mod 70;
+                            if i > 23 then
+                                i:= 0;
+                            i:= i mod 12;
+                            DrawSprite(sprUtility, x - 24, y - 24, i);
+                            end;
+                        end;
+                    if Gear^.Timer <= 1833 then
                         begin
-                        i:= (GameTicks shr 6) mod 70;
-                        if i > 23 then
-                            i:= 0;
-                        i:= i mod 12;
-                        DrawSprite(sprUtility, x - 24, y - 24, i);
-                        end;
-                    if Gear^.Timer < 255 then Tint($FF, $FF, $FF, $FF);
+                        DrawTextureRotatedF(SpritesData[sprPortal].texture, min(abs(1.25 - (Gear^.Timer mod 1333) / 400), 1.25), 0, 0,
+                                            Gear^.Angle+WorldDx, Gear^.Power+WorldDy-16, 4+Gear^.Tag, 1, 32, 32, 270);
+                        end
                     end;
       gtExplosives: begin
                     if ((Gear^.State and gstDrowning) <> 0) then
--- a/hedgewars/uGearsUtils.pas	Tue Jun 05 22:37:36 2012 +0200
+++ b/hedgewars/uGearsUtils.pas	Mon Jun 25 10:44:27 2012 +0200
@@ -107,7 +107,7 @@
                         tdX:= Gear^.X-fX;
                         tdY:= Gear^.Y-fY;
                         if hwRound(hwAbs(tdX)+hwAbs(tdY)) < dmgBase then
-                            dmg:= dmgBase - max(hwRound(Distance(tdX, tdY)),Gear^.Radius);
+                            dmg:= dmgBase - hwRound(Distance(tdX, tdY));
                         if dmg > 1 then
                             begin
                             dmg:= ModifyDamage(min(dmg div 2, Radius), Gear);
@@ -483,13 +483,13 @@
     RecountTeamHealth(tempTeam);
 end;
 
-function CountNonZeroz(x, y, r, c: LongInt): LongInt;
+function CountNonZeroz(x, y, r, c: LongInt; mask: LongWord): LongInt;
 var i: LongInt;
     count: LongInt = 0;
 begin
     if (y and LAND_HEIGHT_MASK) = 0 then
         for i:= max(x - r, 0) to min(x + r, LAND_WIDTH - 4) do
-            if Land[y, i] <> 0 then
+            if Land[y, i] and mask <> 0 then
             begin
                 inc(count);
                 if count = c then
@@ -531,9 +531,10 @@
     ar2: array[0..1023] of TPoint;
     cnt, cnt2: Longword;
     delta: LongInt;
-    reallySkip, tryAgain: boolean;
+    ignoreNearObjects, ignoreOverlap, tryAgain: boolean;
 begin
-reallySkip:= false; // try not skipping proximity at first
+ignoreNearObjects:= false; // try not skipping proximity at first
+ignoreOverlap:= false; // this not only skips proximity, but allows overlapping objects (barrels, mines, hogs, crates).  Saving it for a 3rd pass.  With this active, winning AI Survival goes back to virtual impossibility
 tryAgain:= true;
 while tryAgain do
     begin
@@ -549,23 +550,27 @@
                 begin
                 repeat
                     inc(y, 2);
-                until (y >= cWaterLine) or (CountNonZeroz(x, y, Gear^.Radius - 1, 1) = 0);
+                until (y >= cWaterLine) or
+                        (not ignoreOverlap and (CountNonZeroz(x, y, Gear^.Radius - 1, 1, $FFFF) = 0)) or 
+                        (ignoreOverlap and (CountNonZeroz(x, y, Gear^.Radius - 1, 1, $FF00) = 0));
 
                 sy:= y;
 
                 repeat
                     inc(y);
-                until (y >= cWaterLine) or (CountNonZeroz(x, y, Gear^.Radius - 1, 1) <> 0);
+                until (y >= cWaterLine) or
+                        (not ignoreOverlap and (CountNonZeroz(x, y, Gear^.Radius - 1, 1, $FFFF) <> 0)) or 
+                        (ignoreOverlap and (CountNonZeroz(x, y, Gear^.Radius - 1, 1, $FF00) <> 0)); 
 
                 if (y - sy > Gear^.Radius * 2)
                     and (((Gear^.Kind = gtExplosives)
                     and (y < cWaterLine)
-                    and (reallySkip or NoGearsToAvoid(x, y - Gear^.Radius, 60, 60))
-                    and (CountNonZeroz(x, y+1, Gear^.Radius - 1, Gear^.Radius+1) > Gear^.Radius))
+                    and (ignoreNearObjects or NoGearsToAvoid(x, y - Gear^.Radius, 60, 60))
+                    and (CountNonZeroz(x, y+1, Gear^.Radius - 1, Gear^.Radius+1, $FFFF) > Gear^.Radius))
                 or
                     ((Gear^.Kind <> gtExplosives)
                     and (y < cWaterLine)
-                    and (reallySkip or NoGearsToAvoid(x, y - Gear^.Radius, 110, 110))
+                    and (ignoreNearObjects or NoGearsToAvoid(x, y - Gear^.Radius, 110, 110))
                     )) then
                     begin
                     ar[cnt].X:= x;
@@ -590,10 +595,12 @@
 
         dec(Delta, 60)
     until (cnt2 > 0) or (Delta < 70);
-    if (cnt2 = 0) and skipProximity and (not reallySkip) then
+    // if either of these has not been tried, do another pass
+    if (cnt2 = 0) and skipProximity and (not ignoreOverlap) then
         tryAgain:= true
     else tryAgain:= false;
-    reallySkip:= true;
+    if ignoreNearObjects then ignoreOverlap:= true;
+    ignoreNearObjects:= true;
     end;
 
 if cnt2 > 0 then
--- a/hedgewars/uInputHandler.pas	Tue Jun 05 22:37:36 2012 +0200
+++ b/hedgewars/uInputHandler.pas	Mon Jun 25 10:44:27 2012 +0200
@@ -25,7 +25,9 @@
 procedure initModule;
 procedure freeModule;
 
-function  KeyNameToCode(name: shortstring): word;
+function  KeyNameToCode(name: shortstring; Modifier: shortstring = ''): LongInt;
+procedure MaskModifier(var code: LongInt; modifier: LongWord);
+procedure MaskModifier(Modifier: shortstring; var code: LongInt);
 procedure ProcessMouse(event: TSDL_MouseButtonEvent; ButtonDown: boolean);
 procedure ProcessKey(event: TSDL_KeyboardEvent); inline;
 procedure ProcessKey(code: LongInt; KeyDown: boolean);
@@ -45,37 +47,79 @@
 implementation
 uses uConsole, uCommands, uMisc, uVariables, uConsts, uUtils, uDebug;
 
-var tkbd: array[0..cKeyMaxIndex] of boolean;
+const
+    LSHIFT = $0200;
+    RSHIFT = $0400;
+    LALT   = $0800;
+    RALT   = $1000;
+    LCTRL  = $2000;
+    RCTRL  = $4000; 
+
+var tkbd: array[0..cKbdMaxIndex] of boolean;
     quitKeyCode: Byte;
     KeyNames: array [0..cKeyMaxIndex] of string[15];
     CurrentBinds: TBinds;
 
-function KeyNameToCode(name: shortstring): word;
-var code: Word;
+function KeyNameToCode(name: shortstring; Modifier: shortstring): LongInt;
+var code: LongInt;
 begin
     name:= LowerCase(name);
     code:= cKeyMaxIndex;
     while (code > 0) and (KeyNames[code] <> name) do dec(code);
+
+    MaskModifier(Modifier, code);
     KeyNameToCode:= code;
 end;
 
+procedure MaskModifier(var code: LongInt; Modifier: LongWord);
+begin
+    if(Modifier and KMOD_LSHIFT) <> 0 then code:= code or LSHIFT; 
+    if(Modifier and KMOD_RSHIFT) <> 0 then code:= code or LSHIFT; 
+    if(Modifier and KMOD_LALT) <> 0 then code:= code or LALT; 
+    if(Modifier and KMOD_RALT) <> 0 then code:= code or LALT; 
+    if(Modifier and KMOD_LCTRL) <> 0 then code:= code or LCTRL; 
+    if(Modifier and KMOD_RCTRL) <> 0 then code:= code or LCTRL; 
+end;
+
+procedure MaskModifier(Modifier: shortstring; var code: LongInt);
+var mod_ : shortstring;
+    ModifierCount, i: LongInt;
+begin
+if Modifier = '' then exit;
+ModifierCount:= 0;
+
+for i:= 1 to Length(Modifier) do
+    if(Modifier[i] = ':') then inc(ModifierCount);
+
+SplitByChar(Modifier, mod_, ':');//remove the first mod: part
+Modifier:= mod_;
+for i:= 0 to ModifierCount do
+    begin 
+    mod_:= '';
+    SplitByChar(Modifier, mod_, ':');
+    if (Modifier = 'lshift')                    then code:= code or LSHIFT;
+    if (Modifier = 'rshift')                    then code:= code or RSHIFT;
+    if (Modifier = 'lalt')                      then code:= code or LALT;
+    if (Modifier = 'ralt')                      then code:= code or RALT;
+    if (Modifier = 'lctrl') or (mod_ = 'lmeta') then code:= code or LCTRL;
+    if (Modifier = 'rctrl') or (mod_ = 'rmeta') then code:= code or RCTRL;
+    Modifier:= mod_;
+    end;
+end;
+
 procedure ProcessKey(code: LongInt; KeyDown: boolean);
 var
     Trusted: boolean;
     s      : string;
 begin
-
 if not(tkbd[code] xor KeyDown) then exit;
 tkbd[code]:= KeyDown;
 
-
 hideAmmoMenu:= false;
 Trusted:= (CurrentTeam <> nil)
           and (not CurrentTeam^.ExtDriven)
           and (CurrentHedgehog^.BotLevel = 0);
 
-
-
 // ctrl/cmd + q to close engine and frontend
 if(KeyDown and (code = quitKeyCode)) then
     begin
@@ -109,8 +153,11 @@
 end;
 
 procedure ProcessKey(event: TSDL_KeyboardEvent); inline;
+var code: LongInt;
 begin
-    ProcessKey(event.keysym.sym, event.type_ = SDL_KEYDOWN);
+    code:= event.keysym.sym;
+    //MaskModifier(code, event.keysym.modifier);
+    ProcessKey(code, event.type_ = SDL_KEYDOWN);
 end;
 
 procedure ProcessMouse(event: TSDL_MouseButtonEvent; ButtonDown: boolean);
@@ -132,7 +179,7 @@
 procedure ResetKbd;
 var t: LongInt;
 begin
-for t:= 0 to cKeyMaxIndex do
+for t:= 0 to cKbdMaxIndex do
     if tkbd[t] then
         ProcessKey(t, False);
 end;
@@ -248,7 +295,7 @@
     binds:= binds; // avoid hint
     CurrentBinds:= DefaultBinds;
 {$ELSE}
-for t:= 0 to cKeyMaxIndex do
+for t:= 0 to cKbdMaxIndex do
     if (CurrentBinds[t] <> binds[t]) and tkbd[t] then
         ProcessKey(t, False);
 
--- a/hedgewars/uLandGraphics.pas	Tue Jun 05 22:37:36 2012 +0200
+++ b/hedgewars/uLandGraphics.pas	Mon Jun 25 10:44:27 2012 +0200
@@ -36,10 +36,11 @@
 procedure DrawHLinesExplosions(ar: PRangeArray; Radius: LongInt; y, dY: LongInt; Count: Byte);
 procedure DrawTunnel(X, Y, dX, dY: hwFloat; ticks, HalfWidth: LongInt);
 procedure FillRoundInLand(X, Y, Radius: LongInt; Value: Longword);
-procedure ChangeRoundInLand(X, Y, Radius: LongInt; doSet: boolean);
+procedure ChangeRoundInLand(X, Y, Radius: LongInt; doSet, isCurrent: boolean);
 function  LandBackPixel(x, y: LongInt): LongWord;
 procedure DrawLine(X1, Y1, X2, Y2: LongInt; Color: Longword);
 procedure DrawThickLine(X1, Y1, X2, Y2, radius: LongInt; color: Longword);
+procedure DumpLandToLog(x, y, r: LongInt);
 
 function TryPlaceOnLand(cpX, cpY: LongInt; Obj: TSprite; Frame: LongInt; doPlace: boolean; indestructible: boolean): boolean;
 
@@ -98,46 +99,62 @@
             Land[y - dx, i]:= Value;
 end;
 
-procedure ChangeCircleLines(x, y, dx, dy: LongInt; doSet: boolean);
+procedure ChangeCircleLines(x, y, dx, dy: LongInt; doSet, isCurrent: boolean);
 var i: LongInt;
 begin
 if not doSet then
     begin
     if ((y + dy) and LAND_HEIGHT_MASK) = 0 then
         for i:= Max(x - dx, 0) to Min(x + dx, LAND_WIDTH - 1) do
-            if (Land[y + dy, i] > 0) and (Land[y + dy, i] < 256) then
-                dec(Land[y + dy, i]); // check > 0 because explosion can erase collision data
+            if isCurrent then 
+                Land[y + dy, i]:= Land[y + dy, i] and $FF7F
+            else if Land[y + dy, i] and $007F > 0 then
+                Land[y + dy, i]:= (Land[y + dy, i] and $FF80) or ((Land[y + dy, i] and $7F) - 1);
     if ((y - dy) and LAND_HEIGHT_MASK) = 0 then
         for i:= Max(x - dx, 0) to Min(x + dx, LAND_WIDTH - 1) do
-            if (Land[y - dy, i] > 0) and (Land[y - dy, i] < 256) then
-                dec(Land[y - dy, i]);
+            if isCurrent then 
+                Land[y - dy, i]:= Land[y - dy, i] and $FF7F
+            else if Land[y - dy, i] and $007F > 0 then
+                Land[y - dy, i]:= (Land[y - dy, i] and $FF80) or ((Land[y - dy, i] and $7F) - 1);
     if ((y + dx) and LAND_HEIGHT_MASK) = 0 then
         for i:= Max(x - dy, 0) to Min(x + dy, LAND_WIDTH - 1) do
-            if (Land[y + dx, i] > 0) and (Land[y + dx, i] < 256) then
-                dec(Land[y + dx, i]);
+            if isCurrent then 
+                Land[y + dx, i]:= Land[y + dx, i] and $FF7F
+            else if Land[y + dx, i] and $007F > 0 then
+                Land[y + dx, i]:= (Land[y + dx, i] and $FF80) or ((Land[y + dx, i] and $7F) - 1);
     if ((y - dx) and LAND_HEIGHT_MASK) = 0 then
         for i:= Max(x - dy, 0) to Min(x + dy, LAND_WIDTH - 1) do
-            if (Land[y - dx, i] > 0) and (Land[y - dx, i] < 256) then
-                dec(Land[y - dx, i]);
+            if isCurrent then 
+                Land[y - dx, i]:= Land[y - dx, i] and $FF7F
+            else if Land[y - dx, i] and $007F > 0 then
+                Land[y - dx, i]:= (Land[y - dx, i] and $FF80) or ((Land[y - dx, i] and $7F) - 1)
     end
 else
     begin
     if ((y + dy) and LAND_HEIGHT_MASK) = 0 then
         for i:= Max(x - dx, 0) to Min(x + dx, LAND_WIDTH - 1) do
-            if (Land[y + dy, i] < 256) then
-                inc(Land[y + dy, i]);
-    if ((y - dy) and LAND_HEIGHT_MASK) = 0 then
-        for i:= Max(x - dx, 0) to Min(x + dx, LAND_WIDTH - 1) do
-            if (Land[y - dy, i] < 256) then
-                inc(Land[y - dy, i]);
-    if ((y + dx) and LAND_HEIGHT_MASK) = 0 then
-        for i:= Max(x - dy, 0) to Min(x + dy, LAND_WIDTH - 1) do
-            if (Land[y + dx, i] < 256) then
-                inc(Land[y + dx, i]);
-    if ((y - dx) and LAND_HEIGHT_MASK) = 0 then
-        for i:= Max(x - dy, 0) to Min(x + dy, LAND_WIDTH - 1) do
-            if (Land[y - dx, i] < 256) then
-                inc(Land[y - dx, i]);
+            if isCurrent then 
+                Land[y + dy, i]:= Land[y + dy, i] or $80
+            else if Land[y + dy, i] and $007F < 127 then
+                Land[y + dy, i]:= (Land[y + dy, i] and $FF80) or ((Land[y + dy, i] and $7F) + 1);
+    if ((y - dy) and LAND_HEIGHT_MASK) = 0 then                                                   
+        for i:= Max(x - dx, 0) to Min(x + dx, LAND_WIDTH - 1) do                                  
+            if isCurrent then                                                                     
+                Land[y - dy, i]:= Land[y - dy, i] or $80                                          
+            else if Land[y - dy, i] and $007F < 127 then                                          
+                Land[y - dy, i]:= (Land[y - dy, i] and $FF80) or ((Land[y - dy, i] and $7F) + 1);
+    if ((y + dx) and LAND_HEIGHT_MASK) = 0 then                                                   
+        for i:= Max(x - dy, 0) to Min(x + dy, LAND_WIDTH - 1) do                                  
+            if isCurrent then                                                                     
+                Land[y + dx, i]:= Land[y + dx, i] or $80                                          
+            else if Land[y + dx, i] and $007F < 127 then                                          
+                Land[y + dx, i]:= (Land[y + dx, i] and $FF80) or ((Land[y + dx, i] and $7F) + 1);
+    if ((y - dx) and LAND_HEIGHT_MASK) = 0 then                                                   
+        for i:= Max(x - dy, 0) to Min(x + dy, LAND_WIDTH - 1) do                                  
+            if isCurrent then                                                                     
+                Land[y - dx, i]:= Land[y - dx, i] or $80                                          
+            else if Land[y - dx, i] and $007F < 127 then                                          
+                Land[y - dx, i]:= (Land[y - dx, i] and $FF80) or ((Land[y - dx, i] and $7F) + 1)
     end
 end;
 
@@ -163,7 +180,7 @@
     FillCircleLines(x, y, dx, dy, Value);
 end;
 
-procedure ChangeRoundInLand(X, Y, Radius: LongInt; doSet: boolean);
+procedure ChangeRoundInLand(X, Y, Radius: LongInt; doSet, isCurrent: boolean);
 var dx, dy, d: LongInt;
 begin
 dx:= 0;
@@ -171,7 +188,7 @@
 d:= 3 - 2 * Radius;
 while (dx < dy) do
     begin
-    ChangeCircleLines(x, y, dx, dy, doSet);
+    ChangeCircleLines(x, y, dx, dy, doSet, isCurrent);
     if (d < 0) then
         d:= d + 4 * dx + 6
     else
@@ -182,7 +199,7 @@
     inc(dx)
     end;
 if (dx = dy) then
-    ChangeCircleLines(x, y, dx, dy, doSet)
+    ChangeCircleLines(x, y, dx, dy, doSet, isCurrent)
 end;
 
 procedure FillLandCircleLines0(x, y, dx, dy: LongInt);
@@ -1157,4 +1174,28 @@
         DrawLines(x1, y1, x2, y2, dx, dy, color);
 end;
 
+
+procedure DumpLandToLog(x, y, r: LongInt);
+var xx, yy, dx: LongInt;
+    s: shortstring;
+begin
+    s[0]:= char(r * 2 + 1);
+    for yy:= y - r to y + r do
+        begin
+        for dx:= 0 to r*2 do
+            begin
+            xx:= dx - r + x;
+            if (xx = x) and (yy = y) then
+                s[dx + 1]:= 'X'
+            else if Land[yy, xx] > 255 then
+                s[dx + 1]:= 'O'
+            else if Land[yy, xx] > 0 then
+                s[dx + 1]:= '*'
+            else
+                s[dx + 1]:= '.'
+            end;
+        AddFileLog('Land dump: ' + s);
+        end;
+end;
+
 end.
--- a/hedgewars/uLandPainted.pas	Tue Jun 05 22:37:36 2012 +0200
+++ b/hedgewars/uLandPainted.pas	Mon Jun 25 10:44:27 2012 +0200
@@ -27,7 +27,7 @@
 procedure freeModule;
 
 implementation
-uses uLandGraphics, uConsts, uUtils, SDLh, uCommands, uDebug;
+uses uLandGraphics, uConsts, uVariables, uUtils, SDLh, uCommands, uDebug;
 
 type PointRec = packed record
     X, Y: SmallInt;
@@ -57,6 +57,10 @@
         rec:= prec^;
         rec.X:= SDLNet_Read16(@rec.X);
         rec.Y:= SDLNet_Read16(@rec.Y);
+        if rec.X < -323 then rec.X:= -323;
+        if rec.X > LAND_WIDTH+323 then rec.X:= LAND_WIDTH+323;
+        if rec.Y < -323 then rec.Y:= -323;
+        if rec.Y > LAND_HEIGHT+323 then rec.Y:= LAND_HEIGHT+323;
 
         new(pe);
         if pointsListLast = nil then
--- a/hedgewars/uMobile.pas	Tue Jun 05 22:37:36 2012 +0200
+++ b/hedgewars/uMobile.pas	Mon Jun 25 10:44:27 2012 +0200
@@ -28,6 +28,7 @@
 interface
 
 function  isPhone: Boolean; inline;
+function  getScreenDPI: Single; inline;
 procedure performRumble; inline;
 
 procedure GameLoading; inline;
@@ -47,6 +48,10 @@
 procedure AudioServicesPlaySystemSound(num: LongInt); cdecl; external;
 {$ENDIF}
 
+{$IFDEF ANDROID}
+function Android_JNI_getDensity(): Single; cdecl; external;
+{$ENDIF}
+
 // this function is just to determine whether we are running on a limited screen device
 function isPhone: Boolean; inline;
 begin
@@ -61,6 +66,15 @@
 {$ENDIF}
 end;
 
+function getScreenDPI: Single; inline;
+begin
+{$IFDEF ANDROID}
+    getScreenDPI:= Android_JNI_getDensity();
+{$ELSE}
+    getScreenDPI:= 1;
+{$ENDIF}
+end;
+
 // this function should make the device vibrate in some way
 procedure PerformRumble; inline;
 {$IFDEF IPHONEOS}const kSystemSoundID_Vibrate = $00000FFF;{$ENDIF}
--- a/hedgewars/uScript.pas	Tue Jun 05 22:37:36 2012 +0200
+++ b/hedgewars/uScript.pas	Mon Jun 25 10:44:27 2012 +0200
@@ -973,10 +973,9 @@
             prevgear^.Z := cHHZ;
             RemoveGearFromList(prevgear);
             InsertGearToList(prevgear);
-
-            CurrentHedgehog := gear^.Hedgehog;
-// yes, this will muck up turn sequence
-            CurrentTeam := gear^.Hedgehog^.Team;
+            
+            SwitchCurrentHedgehog(gear^.Hedgehog);
+            CurrentTeam:= CurrentHedgehog^.Team;
 
             gear^.State:= gear^.State or gstHHDriven;
             gear^.Active := true;
--- a/hedgewars/uTeams.pas	Tue Jun 05 22:37:36 2012 +0200
+++ b/hedgewars/uTeams.pas	Mon Jun 25 10:44:27 2012 +0200
@@ -35,6 +35,7 @@
 procedure RestoreTeamsFromSave;
 function  CheckForWin: boolean;
 procedure TeamGoneEffect(var Team: TTeam);
+procedure SwitchCurrentHedgehog(newHog: PHedgehog);
 
 implementation
 uses uLocale, uAmmos, uChat, uVariables, uUtils, uIO, uCaptions, uCommands, uDebug, uScript,
@@ -184,7 +185,7 @@
         end
 until (CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog].Gear <> nil);
 
-CurrentHedgehog:= @(CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog]);
+SwitchCurrentHedgehog(@(CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog]));
 {$IFDEF USE_TOUCH_INTERFACE}
 if (Ammoz[CurrentHedgehog^.CurAmmoType].Ammo.Propz and ammoprop_NoCrosshair) = 0 then
     begin
@@ -488,7 +489,7 @@
 with CurrentTeam^ do
     begin
     SplitBySpace(id, s);
-    CurrentHedgehog:= @Hedgehogs[HedgehogsNumber];
+    SwitchCurrentHedgehog(@Hedgehogs[HedgehogsNumber]);
     val(id, CurrentHedgehog^.BotLevel, c);
     Gear:= AddGear(0, 0, gtHedgehog, 0, _0, _0, 0);
     SplitBySpace(s, id);
@@ -552,22 +553,33 @@
 end;
 
 procedure chBind(var id: shortstring);
-var s: shortstring;
+var KeyName, Modifier, tmp: shortstring;
     b: LongInt;
 begin
-s:= '';
+KeyName:= '';
+Modifier:= '';
+
 if CurrentTeam = nil then
     exit;
-SplitBySpace(id, s);
-if s[1]='"' then
-    Delete(s, 1, 1);
-if s[byte(s[0])]='"' then
-    Delete(s, byte(s[0]), 1);
-b:= KeyNameToCode(id);
+
+if(Pos('mod:', id) <> 0)then
+    begin
+    tmp:= '';
+    SplitBySpace(id, tmp);
+    Modifier:= id;
+    id:= tmp;
+    end;
+
+SplitBySpace(id, KeyName);
+if KeyName[1]='"' then
+    Delete(KeyName, 1, 1);
+if KeyName[byte(KeyName[0])]='"' then
+    Delete(KeyName, byte(KeyName[0]), 1);
+b:= KeyNameToCode(id, Modifier);
 if b = 0 then
     OutError(errmsgUnknownVariable + ' "' + id + '"', false)
 else
-    CurrentTeam^.Binds[b]:= s
+    CurrentTeam^.Binds[b]:= KeyName;
 end;
 
 procedure chTeamGone(var s:shortstring);
@@ -607,6 +619,21 @@
 RecountAllTeamsHealth();
 end;
 
+procedure SwitchCurrentHedgehog(newHog: PHedgehog);
+var oldCI, newCI: boolean;
+    oldHH: PHedgehog;
+begin
+    oldCI:= (CurrentHedgehog <> nil) and (CurrentHedgehog^.Gear <> nil) and (CurrentHedgehog^.Gear^.CollisionIndex >= 0);
+    newCI:= (newHog^.Gear <> nil) and (newHog^.Gear^.CollisionIndex >= 0);
+    if oldCI then DeleteCI(CurrentHedgehog^.Gear);
+    if newCI then DeleteCI(newHog^.Gear);
+    oldHH:= CurrentHedgehog;
+    CurrentHedgehog:= newHog;
+    if oldCI then AddGearCI(oldHH^.Gear);
+    if newCI then AddGearCI(newHog^.Gear)
+end;
+
+
 procedure initModule;
 begin
 RegisterVariable('addhh', @chAddHH, false);
--- a/hedgewars/uTouch.pas	Tue Jun 05 22:37:36 2012 +0200
+++ b/hedgewars/uTouch.pas	Mon Jun 25 10:44:27 2012 +0200
@@ -22,7 +22,7 @@
 
 interface
 
-uses SysUtils, uConsole, uVariables, SDLh, uFloat, uConsts, uCommands, uIO, GLUnit, uTypes, uCaptions, uAmmos, uWorld;
+uses SysUtils, uConsole, uVariables, SDLh, uFloat, uConsts, uCommands, uIO, GLUnit, uTypes, uCaptions, uAmmos, uWorld, uMobile;
 
 
 procedure initModule;
@@ -557,7 +557,7 @@
     isOnCrosshair:= isOnRect((x-HalfRectSize), (y-HalfRectSize), RectSize, RectSize, finger);
     printFinger(finger);
     WriteLnToConsole(inttostr(finger.x) + '   ' + inttostr(x));
-    WriteLnToConsole(inttostr(x) + '  ' + inttostr(y) + '   ' + inttostr(round(Android_JNI_getDensity() * 10)));
+    WriteLnToConsole(inttostr(x) + '  ' + inttostr(y) + '   ' + inttostr(round(uMobile.getScreenDPI * 10)));
 end;
 
 function isOnCurrentHog(finger: TTouch_Data): boolean;
@@ -632,7 +632,6 @@
 var
     index: Longword;
     //uRenderCoordScaleX, uRenderCoordScaleY: Longword;
-    density: Single;
 begin
     buttonsDown:= 0;
 
@@ -640,13 +639,7 @@
     for index := 0 to High(fingers) do 
         fingers[index].id := nilFingerId;
 
-{$IFDEF ANDROID}
-    density:= Android_JNI_getDensity();
-{$ELSE}
-    density:= 1.0;
-{$ENDIF}
-
-    rectSize:= round(baseRectSize * density);
+    rectSize:= round(baseRectSize * uMobile.getScreenDPI);
     halfRectSize:= rectSize shl 1;
 end;
 
--- a/hedgewars/uTypes.pas	Tue Jun 05 22:37:36 2012 +0200
+++ b/hedgewars/uTypes.pas	Mon Jun 25 10:44:27 2012 +0200
@@ -267,7 +267,8 @@
             Tag: LongInt;
             Tex: PTexture;
             Z: Longword;
-            IntersectGear: PGear;
+            CollisionMask: Word;
+            LinkedGear: PGear;
             FlightTime: Longword;
             uid: Longword;
             ImpactSound: TSound; // first sound, others have to be after it in the sounds def.
@@ -326,7 +327,7 @@
         TeamDamage : Longword;
         end;
 
-    TBinds = array[0..cKeyMaxIndex] of shortstring;
+    TBinds = array[0..cKbdMaxIndex] of shortstring;
     TKeyboardState = array[0..cKeyMaxIndex] of Byte;
 
     PVoicepack = ^TVoicepack;
--- a/hedgewars/uUtils.pas	Tue Jun 05 22:37:36 2012 +0200
+++ b/hedgewars/uUtils.pas	Mon Jun 25 10:44:27 2012 +0200
@@ -24,6 +24,7 @@
 uses uTypes, uFloat, GLunit;
 
 procedure SplitBySpace(var a, b: shortstring);
+procedure SplitByChar(var a, b: shortstring; c: char);
 procedure SplitByChar(var a, b: ansistring; c: char);
 
 {$IFNDEF PAS2C}
@@ -83,11 +84,16 @@
 {$ENDIF}
 var CharArray: array[byte] of Char;
 
+procedure SplitBySpace(var a,b: shortstring);
+begin
+SplitByChar(a,b,' ');
+end;
+
 // should this include "strtolower()" for the split string?
-procedure SplitBySpace(var a, b: shortstring);
+procedure SplitByChar(var a, b: shortstring; c : char);
 var i, t: LongInt;
 begin
-i:= Pos(' ', a);
+i:= Pos(c, a);
 if i > 0 then
     begin
     for t:= 1 to Pred(i) do
--- a/hedgewars/uVariables.pas	Tue Jun 05 22:37:36 2012 +0200
+++ b/hedgewars/uVariables.pas	Mon Jun 25 10:44:27 2012 +0200
@@ -1829,7 +1829,9 @@
             NameTex: nil;
             Probability: 20;
             NumberInCase: 2;
-            Ammo: (Propz: ammoprop_NeedUpDown;
+            Ammo: (Propz: ammoprop_NeedUpDown or 
+                    ammoprop_OscAim or
+                    ammoprop_NoMoveAfter;
                 Count: 2;
                 NumPerTurn: 1;
                 Timer: 0;
--- a/hedgewars/uVisualGears.pas	Tue Jun 05 22:37:36 2012 +0200
+++ b/hedgewars/uVisualGears.pas	Mon Jun 25 10:44:27 2012 +0200
@@ -642,7 +642,7 @@
                   vgtSmoke: DrawTextureF(SpritesData[sprSmoke].Texture, Gear^.scale, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, 7 - Gear^.Frame, 1, SpritesData[sprSmoke].Width, SpritesData[sprSmoke].Height);
                   vgtSmokeWhite: DrawSprite(sprSmokeWhite, round(Gear^.X) + WorldDx - 11, round(Gear^.Y) + WorldDy - 11, 7 - Gear^.Frame);
                   vgtDust: if Gear^.State = 1 then
-                               DrawSprite(sprSnowDust, round(Gear^.X) + WorldDx - 11, round(Gear^.Y) + WorldDy - 11, 7 - Gear^.Frame)
+                               DrawSpriteRotatedF(sprSnowDust, round(Gear^.X) + WorldDx - 11, round(Gear^.Y) + WorldDy - 11, 7 - Gear^.Frame, 1, Gear^.Angle)
                            else
                                DrawSprite(sprDust, round(Gear^.X) + WorldDx - 11, round(Gear^.Y) + WorldDy - 11, 7 - Gear^.Frame);
                   vgtFire: if (Gear^.State and gstTmpFlag) = 0 then
--- a/hedgewars/uWorld.pas	Tue Jun 05 22:37:36 2012 +0200
+++ b/hedgewars/uWorld.pas	Mon Jun 25 10:44:27 2012 +0200
@@ -215,11 +215,7 @@
 {$IFDEF USE_TOUCH_INTERFACE}
 
 //positioning of the buttons
-{$IFDEF ANDROID}
-buttonScale:= Android_JNI_getDensity()/cDefaultZoomLevel;
-{$ELSE}
-buttonScale:= 1.5/cDefaultZoomLevel;
-{$ENDIF}
+buttonScale:= uMobile.getScreenDPI/cDefaultZoomLevel;
 
 
 with JumpWidget do
@@ -1490,9 +1486,6 @@
             DrawTexture((cScreenWidth shr 1) - 60 - offsetY, offsetX, fpsTexture);
         end;
 
-    if CountTicks >= 1000 then
-        CountTicks:= 0;
-
     // lag warning (?)
     inc(SoundTimerTicks, Lag);
 end;
@@ -1584,7 +1577,10 @@
 {$ENDIF}
 z:= round(200/zoom);
 if not PlacingHogs and (FollowGear <> nil) and (not isCursorVisible) and (not bShowAmmoMenu) and (not fastUntilLag) then
-    if (not autoCameraOn) or ((abs(CursorPoint.X - prevPoint.X) + abs(CursorPoint.Y - prevpoint.Y)) > 4) then
+    if (not autoCameraOn) then
+        FollowGear:= nil
+    else        
+    if ((abs(CursorPoint.X - prevPoint.X) + abs(CursorPoint.Y - prevpoint.Y)) > 4) then
         begin
         FollowGear:= nil;
         prevPoint:= CursorPoint;
@@ -1634,7 +1630,7 @@
     EdgesDist:= cGearScrEdgesDist;
 
 // this generates the border around the screen that moves the camera when cursor is near it
-if isCursorVisible or (FollowGear <> nil) then
+if isCursorVisible or ((FollowGear <> nil) and autoCameraOn) then
     begin
     if CursorPoint.X < - cScreenWidth div 2 + EdgesDist then
         begin
--- a/misc/liblua/CMakeLists.txt	Tue Jun 05 22:37:36 2012 +0200
+++ b/misc/liblua/CMakeLists.txt	Mon Jun 25 10:44:27 2012 +0200
@@ -7,6 +7,8 @@
     add_definitions(-DLUA_BUILD_AS_DLL)
     add_library(lua SHARED ${lua_src})
 
+    set(LUA_LIBRARY lua.dll)
+
     set_target_properties(lua PROPERTIES PREFIX "")
     install(TARGETS lua RUNTIME DESTINATION ${target_dir})
 else(WIN32)
--- a/misc/quazip/CMakeLists.txt	Tue Jun 05 22:37:36 2012 +0200
+++ b/misc/quazip/CMakeLists.txt	Mon Jun 25 10:44:27 2012 +0200
@@ -1,7 +1,9 @@
 set(QT_USE_QTCORE TRUE)
 
 find_package(Qt4 REQUIRED)
-include(${QT_USE_FILE})
+if(NOT CROSSAPPLE)
+    include(${QT_USE_FILE})
+endif()
 
 
 file(GLOB SRCS "*.c" "*.cpp")
--- a/project_files/HedgewarsMobile/Classes/DefinesAndMacros.h	Tue Jun 05 22:37:36 2012 +0200
+++ b/project_files/HedgewarsMobile/Classes/DefinesAndMacros.h	Mon Jun 25 10:44:27 2012 +0200
@@ -67,7 +67,7 @@
 #define MISSIONS_DIRECTORY()    [[[NSBundle mainBundle] resourcePath] stringByAppendingString:@"/Data/Missions/Maps/"]
 #define TRAININGS_DIRECTORY()   [[[NSBundle mainBundle] resourcePath] stringByAppendingString:@"/Data/Missions/Training/"]
 #define LOCALE_DIRECTORY()      [[[NSBundle mainBundle] resourcePath] stringByAppendingString:@"/Data/Locale/"]
-#define SCRIPTS_DIRECTORY()     [[[NSBundle mainBundle] resourcePath] stringByAppendingString:@"/Data/Scripts/plist/"]
+#define SCRIPTS_DIRECTORY()     [[[NSBundle mainBundle] resourcePath] stringByAppendingString:@"/Data/Scripts/Multiplayer/"]
 
 #define MSG_MEMCLEAN()          DLog(@"has cleaned up some memory");
 #define MSG_DIDUNLOAD()         DLog(@"unloaded");
--- a/project_files/HedgewarsMobile/Classes/MapPreviewButtonView.m	Tue Jun 05 22:37:36 2012 +0200
+++ b/project_files/HedgewarsMobile/Classes/MapPreviewButtonView.m	Mon Jun 25 10:44:27 2012 +0200
@@ -85,7 +85,7 @@
 
     // launch the preview here so that we're sure the tcp channel is open
     pthread_t thread_id;
-    pthread_create(&thread_id, NULL, (void *)GenLandPreview, (void *)port);
+    pthread_create(&thread_id, NULL, (void *(*)(void *))GenLandPreview, (void *)port);
     pthread_detach(thread_id);
 
     DLog(@"Waiting for a client on port %d", port);
--- a/project_files/HedgewarsMobile/Classes/SchemeWeaponConfigViewController.m	Tue Jun 05 22:37:36 2012 +0200
+++ b/project_files/HedgewarsMobile/Classes/SchemeWeaponConfigViewController.m	Mon Jun 25 10:44:27 2012 +0200
@@ -72,7 +72,8 @@
 
 -(NSArray *)listOfScripts {
     if (listOfScripts == nil)
-        self.listOfScripts = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:SCRIPTS_DIRECTORY() error:NULL];
+        self.listOfScripts = [[[NSFileManager defaultManager] contentsOfDirectoryAtPath:SCRIPTS_DIRECTORY() error:NULL]
+                              filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"SELF ENDSWITH '.lua'"]];
     return listOfScripts;
 }
 
@@ -202,11 +203,9 @@
             self.lastIndexPath_we = indexPath;
         }
     } else {
-        cell.textLabel.text = [[self.listOfScripts objectAtIndex:row] stringByDeletingPathExtension];
-        NSString *str = [NSString stringWithFormat:@"%@/%@",SCRIPTS_DIRECTORY(),[self.listOfScripts objectAtIndex:row]];
-        NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:str];
-        cell.detailTextLabel.text = [dict objectForKey:@"description"];
-        [dict release];
+        cell.textLabel.text = [[[self.listOfScripts objectAtIndex:row] stringByDeletingPathExtension]
+                               stringByReplacingOccurrencesOfString:@"_" withString:@" "];
+        //cell.detailTextLabel.text = ;
         if ([[self.listOfScripts objectAtIndex:row] isEqualToString:self.selectedScript]) {
             UIImageView *checkbox = [[UIImageView alloc] initWithImage:[UIImage imageWithContentsOfFile:@"checkbox.png"]];
             cell.accessoryView = checkbox;
@@ -223,11 +222,11 @@
     return cell;
 }
 
--(CGFloat) tableView:(UITableView *)aTableView heightForHeaderInSection:(NSInteger)section {
+-(CGFloat) tableView:(UITableView *)aTableView heightForHeaderInSection:(NSInteger) section {
     return IS_IPAD() ? 0 : 50;
 }
 
--(UIView *)tableView:(UITableView *)aTableView viewForHeaderInSection:(NSInteger)section {
+-(UIView *)tableView:(UITableView *)aTableView viewForHeaderInSection:(NSInteger) section {
     if (IS_IPAD())
         return nil;
     UIView *theView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 30)];
@@ -239,6 +238,32 @@
     return [theView autorelease];
 }
 
+-(CGFloat) tableView:(UITableView *)aTableView heightForFooterInSection:(NSInteger) section {
+    return 40;
+}
+
+-(UIView *)tableView:(UITableView *)aTableView viewForFooterInSection:(NSInteger) section {
+    NSInteger height = 40;
+    UIView *footer = [[UIView alloc] initWithFrame:CGRectMake(0, 0, aTableView.frame.size.width, height)];
+    footer.backgroundColor = [UIColor clearColor];
+    footer.autoresizingMask = UIViewAutoresizingFlexibleWidth;
+
+    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, aTableView.frame.size.width*80/100, height)];
+    label.center = CGPointMake(aTableView.frame.size.width/2, height/2);
+    label.textAlignment = UITextAlignmentCenter;
+    label.font = [UIFont italicSystemFontOfSize:12];
+    label.textColor = [UIColor whiteColor];
+    label.numberOfLines = 2;
+    label.backgroundColor = [UIColor clearColor];
+    label.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
+
+    label.text = NSLocalizedString(@"Setting a Style might force a particular Scheme or Weapon configuration.",@"");
+
+    [footer addSubview:label];
+    [label release];
+    return [footer autorelease];
+}
+
 #pragma mark -
 #pragma mark Table view delegate
 -(void) tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
@@ -287,29 +312,30 @@
             self.selectedScript = [self.listOfScripts objectAtIndex:newRow];
 
             // some styles disable or force the choice of a particular scheme/weaponset
-            NSString *path = [[NSString alloc] initWithFormat:@"%@/%@",SCRIPTS_DIRECTORY(),self.selectedScript];
-            NSDictionary *scriptDict = [[NSDictionary alloc] initWithContentsOfFile:path];
+            NSString *path = [[NSString alloc] initWithFormat:@"%@/%@.cfg",SCRIPTS_DIRECTORY(),[self.selectedScript stringByDeletingPathExtension]];
+            NSString *configFile = [[NSString alloc] initWithContentsOfFile:path];
             [path release];
-            self.scriptCommand = [scriptDict objectForKey:@"command"];
-            NSString *scheme = [scriptDict objectForKey:@"scheme"];
-            if ([scheme isEqualToString:@""]) {
+            NSArray *scriptOptions = [configFile componentsSeparatedByString:@"\n"];
+            [configFile release];
+
+            self.scriptCommand = [NSString stringWithFormat:@"escript Scripts/Multiplayer/%@",self.selectedScript];
+            NSString *scheme = [scriptOptions objectAtIndex:0];
+            if ([scheme isEqualToString:@"locked"]) {
                 self.selectedScheme = @"Default.plist";
                 [self.topControl setEnabled:NO forSegmentAtIndex:0];
             } else {
-                self.selectedScheme = scheme;
+                self.selectedScheme = [NSString stringWithFormat:@"%@.plist",scheme];
                 [self.topControl setEnabled:YES forSegmentAtIndex:0];
             }
 
-            NSString *weapon = [scriptDict objectForKey:@"weapon"];
-            if ([weapon isEqualToString:@""]) {
+            NSString *weapon = [scriptOptions objectAtIndex:1];
+            if ([weapon isEqualToString:@"locked"]) {
                 self.selectedWeapon = @"Default.plist";
                 [self.topControl setEnabled:NO forSegmentAtIndex:1];
             } else {
-                self.selectedWeapon = weapon;
+                self.selectedWeapon = [NSString stringWithFormat:@"%@.plist",weapon];
                 [self.topControl setEnabled:YES forSegmentAtIndex:1];
             }
-
-            [scriptDict release];
         }
 
         [aTableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionNone];
--- a/project_files/HedgewarsMobile/Hedgewars.xcodeproj/project.pbxproj	Tue Jun 05 22:37:36 2012 +0200
+++ b/project_files/HedgewarsMobile/Hedgewars.xcodeproj/project.pbxproj	Mon Jun 25 10:44:27 2012 +0200
@@ -1472,7 +1472,7 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
-			shellScript = "#copy new stuff over old stuff\nrm -rf ${PROJECT_DIR}/Data\n\n#create config.inc\necho \"Updating config file...\"\nPROTO=`cat ${PROJECT_DIR}/../../CMakeLists.txt | grep HEDGEWARS_PROTO_VER | cut -d ' ' -f 2 | cut -d ')' -f 1`\nMAJN=`cat ${PROJECT_DIR}/../../CMakeLists.txt | grep CPACK_PACKAGE_VERSION_MAJOR | xargs | cut -d ' ' -f 2 |cut -d ')' -f 1`\nMINN=`cat ${PROJECT_DIR}/../../CMakeLists.txt | grep CPACK_PACKAGE_VERSION_MINOR | xargs | cut -d ' ' -f 2 |cut -d ')' -f 1`\nPATN=`cat ${PROJECT_DIR}/../../CMakeLists.txt | grep CPACK_PACKAGE_VERSION_PATCH | xargs | cut -d ' ' -f 2 |cut -d '$' -f 1`\nREVN=-`/usr/local/bin/hg id -n ${PROJECT_DIR}/../../`\necho \"const cNetProtoVersion = $PROTO; const cVersionString = '${MAJN}.${MINN}.${PATN}${REVN}'; const cLuaLibrary = '';\" > ${PROJECT_DIR}/config.inc\n\necho \"Copying Data...\"\ncp -R ${PROJECT_DIR}/../../share/hedgewars/Data ${PROJECT_DIR}/Data\n\n#copy some files from QTfrontend/res\necho \"Fetching additional graphics from QTfrontend...\"\nmkdir ${PROJECT_DIR}/Data/Graphics/Icons\ncp    ${PROJECT_DIR}/../../QTfrontend/res/{btn*,icon*,StatsMedal*,ammopic*}.png  ${PROJECT_DIR}/Data/Graphics/Icons/\n\necho \"Removing text and dummy files...\"\n#delete all CMakeLists.txt and image source files\nfind ${PROJECT_DIR}/Data -name CMakeLists.txt -delete\nfind ${PROJECT_DIR}/Data -name *.svg* -delete\nfind ${PROJECT_DIR}/Data -name *.psd -delete\nfind ${PROJECT_DIR}/Data -name *.sifz -delete\nfind ${PROJECT_DIR}/Data -name *.xcf -delete\nfind ${PROJECT_DIR}/Data -name *.orig -delete\nfind ${PROJECT_DIR}/Data -name *.ts -delete\n\n#delete dummy maps and hats, misc stuff\nrm -rf ${PROJECT_DIR}/Data/Maps/test*\nrm -rf ${PROJECT_DIR}/Data/Graphics/Hats/{TeamCap,TeamHeadband,TeamHair}\nrm -rf ${PROJECT_DIR}/Data/misc/\n\n#delete forbidden maps and WIP themes (remember to check that no Map uses them)\nrm -rf ${PROJECT_DIR}/Data/Maps/{Cheese,FlightJoust}\nrm -rf ${PROJECT_DIR}/Data/Themes/{Beach,Digital}\n\n#delete all names, reserved hats and unused fonts\nrm -rf ${PROJECT_DIR}/Data/Names/\nrm -rf ${PROJECT_DIR}/Data/Graphics/Hats/Reserved/\nrm -rf ${PROJECT_DIR}/Data/Fonts/{wqy-zenhei.ttc,DroidSansFallback.ttf}\n\necho \"Handling audio files...\"\n#copy mono audio\ncp -R ${PROJECT_DIR}/../AudioMono/* ${PROJECT_DIR}/Data/\n#delete the Classic voice\nrm -rf ${PROJECT_DIR}/Data/Sounds/voices/Classic\n#delete the main theme file\nrm -rf ${PROJECT_DIR}/Data/Music/main_theme.ogg\n\n#remove unused voices\nfor i in {Amazing,Brilliant,Bugger,Bungee,Cutitout,Drat,Excellent,Fire,FlawlessPossibility,Gonnagetyou,Grenade,Hmm,Justyouwait,Leavemealone,Ohdear,Ouch,Perfect,Revenge,Runaway,Solong,Thisoneismine,VictoryPossibility,Watchthis,Whatthe,Whoopsee}; do find Data/Sounds/voices/ -name $i.ogg -delete; done\n\necho \"Tweaking Data contents...\"\n#move Lua maps in Missions\nmkdir ${PROJECT_DIR}/Data/Missions/Maps/\nfor i in `ls ${PROJECT_DIR}/Data/Maps/`;\ndo \n    if [[ `ls -f ${PROJECT_DIR}/Data/Maps/$i/map.lua 2> /dev/null` != '' ]];\n    then\n        mv ${PROJECT_DIR}/Data/Maps/$i ${PROJECT_DIR}/Data/Missions/Maps/;\n    fi;\ndone;\n\n#workaround for missing map in CTF_Blizzard\nln -s ../../../Maps/Blizzard/map.png ${PROJECT_DIR}/Data/Missions/Maps/CTF_Blizzard/map.png\n#remove cfg files since we have plists\nfind ${PROJECT_DIR}/Data/Scripts -name *.cfg -delete\nif ((`ls ${PROJECT_DIR}/Data/Scripts/Multiplayer/*.lua|wc -l` >= `ls ${PROJECT_DIR}/Data/Scripts/plist/*.plist|wc -l` ))\nthen\necho \"${PROJECT_DIR}/Data/Scripts/Multiplayer/Normal.plist:0: warning, missing plist implementation of a Multiplayer script file\"\nfi\n\n#reduce the number of flakes for City\nsed -i -e 's/1500/50/' ${PROJECT_DIR}/Data/Themes/City/theme.cfg\n\necho \"Done\"";
+			shellScript = "#copy new stuff over old stuff\nrm -rf ${PROJECT_DIR}/Data\n\n#create config.inc\necho \"Updating config file...\"\nPROTO=`cat ${PROJECT_DIR}/../../CMakeLists.txt | grep HEDGEWARS_PROTO_VER | cut -d ' ' -f 2 | cut -d ')' -f 1`\nMAJN=`cat ${PROJECT_DIR}/../../CMakeLists.txt | grep CPACK_PACKAGE_VERSION_MAJOR | xargs | cut -d ' ' -f 2 |cut -d ')' -f 1`\nMINN=`cat ${PROJECT_DIR}/../../CMakeLists.txt | grep CPACK_PACKAGE_VERSION_MINOR | xargs | cut -d ' ' -f 2 |cut -d ')' -f 1`\nPATN=`cat ${PROJECT_DIR}/../../CMakeLists.txt | grep CPACK_PACKAGE_VERSION_PATCH | xargs | cut -d ' ' -f 2 |cut -d '$' -f 1`\nREVN=-`/usr/local/bin/hg id -n ${PROJECT_DIR}/../../`\necho \"const cNetProtoVersion = $PROTO; const cVersionString = '${MAJN}.${MINN}.${PATN}${REVN}'; const cLuaLibrary = '';\" > ${PROJECT_DIR}/config.inc\n\necho \"Copying Data...\"\ncp -R ${PROJECT_DIR}/../../share/hedgewars/Data ${PROJECT_DIR}/Data\n\n#copy some files from QTfrontend/res\necho \"Fetching additional graphics from QTfrontend...\"\nmkdir ${PROJECT_DIR}/Data/Graphics/Icons\ncp    ${PROJECT_DIR}/../../QTfrontend/res/{btn*,icon*,StatsMedal*,ammopic*}.png  ${PROJECT_DIR}/Data/Graphics/Icons/\n\necho \"Removing text and dummy files...\"\n#delete all CMakeLists.txt and image source files\nfind ${PROJECT_DIR}/Data -name CMakeLists.txt -delete\nfind ${PROJECT_DIR}/Data -name *.svg* -delete\nfind ${PROJECT_DIR}/Data -name *.psd -delete\nfind ${PROJECT_DIR}/Data -name *.sifz -delete\nfind ${PROJECT_DIR}/Data -name *.xcf -delete\nfind ${PROJECT_DIR}/Data -name *.orig -delete\nfind ${PROJECT_DIR}/Data -name *.ts -delete\n\n#delete dummy maps and hats, misc stuff\nrm -rf ${PROJECT_DIR}/Data/Maps/test*\nrm -rf ${PROJECT_DIR}/Data/Graphics/Hats/{TeamCap,TeamHeadband,TeamHair}\nrm -rf ${PROJECT_DIR}/Data/misc/\n\n#delete forbidden maps and WIP themes (remember to check that no Map uses them)\nrm -rf ${PROJECT_DIR}/Data/Maps/{Cheese,FlightJoust}\nrm -rf ${PROJECT_DIR}/Data/Themes/{Beach,Digital}\n\n#delete all names, reserved hats and unused fonts\nrm -rf ${PROJECT_DIR}/Data/Names/\nrm -rf ${PROJECT_DIR}/Data/Graphics/Hats/Reserved/\nrm -rf ${PROJECT_DIR}/Data/Fonts/{wqy-zenhei.ttc,DroidSansFallback.ttf}\n\necho \"Handling audio files...\"\n#copy mono audio\ncp -R ${PROJECT_DIR}/../AudioMono/* ${PROJECT_DIR}/Data/\n#delete the Classic voice\nrm -rf ${PROJECT_DIR}/Data/Sounds/voices/Classic\n#delete the main theme file\nrm -rf ${PROJECT_DIR}/Data/Music/main_theme.ogg\n\n#remove unused voices\nfor i in {Amazing,Brilliant,Bugger,Bungee,Cutitout,Drat,Excellent,Fire,FlawlessPossibility,Gonnagetyou,Grenade,Hmm,Justyouwait,Leavemealone,Ohdear,Ouch,Perfect,Revenge,Runaway,Solong,Thisoneismine,VictoryPossibility,Watchthis,Whatthe,Whoopsee}; do find Data/Sounds/voices/ -name $i.ogg -delete; done\n\necho \"Tweaking Data contents...\"\n#move Lua maps in Missions\nmkdir ${PROJECT_DIR}/Data/Missions/Maps/\nfor i in `ls ${PROJECT_DIR}/Data/Maps/`;\ndo \n    if [[ `ls -f ${PROJECT_DIR}/Data/Maps/$i/map.lua 2> /dev/null` != '' ]];\n    then\n        mv ${PROJECT_DIR}/Data/Maps/$i ${PROJECT_DIR}/Data/Missions/Maps/;\n    fi;\ndone;\n\n#workaround for missing map in CTF_Blizzard\nln -s ../../../Maps/Blizzard/map.png ${PROJECT_DIR}/Data/Missions/Maps/CTF_Blizzard/map.png\n\n#reduce the number of flakes for City\nsed -i -e 's/1500/50/' ${PROJECT_DIR}/Data/Themes/City/theme.cfg\n\necho \"Done\"";
 			showEnvVarsInLog = 0;
 		};
 		9283011B0F10CB2D00CC5A3C /* Build libfpc.a */ = {
@@ -1740,7 +1740,6 @@
 				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
 				GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES;
 				GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
-				GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO;
 				GCC_WARN_ABOUT_RETURN_TYPE = YES;
 				GCC_WARN_CHECK_SWITCH_STATEMENTS = YES;
 				GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES;
@@ -1749,14 +1748,11 @@
 				GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES;
 				GCC_WARN_PEDANTIC = YES;
 				GCC_WARN_SHADOW = YES;
-				GCC_WARN_SIGN_COMPARE = YES;
 				GCC_WARN_STRICT_SELECTOR_MATCH = YES;
 				GCC_WARN_UNDECLARED_SELECTOR = YES;
-				GCC_WARN_UNINITIALIZED_AUTOS = NO;
 				GCC_WARN_UNKNOWN_PRAGMAS = YES;
 				GCC_WARN_UNUSED_FUNCTION = YES;
 				GCC_WARN_UNUSED_LABEL = YES;
-				GCC_WARN_UNUSED_PARAMETER = NO;
 				GCC_WARN_UNUSED_VALUE = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
 				HEADER_SEARCH_PATHS = (
@@ -1850,7 +1846,6 @@
 				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
 				GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES;
 				GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
-				GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO;
 				GCC_WARN_ABOUT_RETURN_TYPE = YES;
 				GCC_WARN_CHECK_SWITCH_STATEMENTS = YES;
 				GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES;
@@ -1859,14 +1854,11 @@
 				GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES;
 				GCC_WARN_PEDANTIC = YES;
 				GCC_WARN_SHADOW = YES;
-				GCC_WARN_SIGN_COMPARE = YES;
 				GCC_WARN_STRICT_SELECTOR_MATCH = YES;
 				GCC_WARN_UNDECLARED_SELECTOR = YES;
-				GCC_WARN_UNINITIALIZED_AUTOS = NO;
 				GCC_WARN_UNKNOWN_PRAGMAS = YES;
 				GCC_WARN_UNUSED_FUNCTION = YES;
 				GCC_WARN_UNUSED_LABEL = YES;
-				GCC_WARN_UNUSED_PARAMETER = NO;
 				GCC_WARN_UNUSED_VALUE = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
 				HEADER_SEARCH_PATHS = (
@@ -2002,7 +1994,6 @@
 				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
 				GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES;
 				GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
-				GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO;
 				GCC_WARN_ABOUT_RETURN_TYPE = YES;
 				GCC_WARN_CHECK_SWITCH_STATEMENTS = YES;
 				GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES;
@@ -2011,14 +2002,11 @@
 				GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES;
 				GCC_WARN_PEDANTIC = YES;
 				GCC_WARN_SHADOW = YES;
-				GCC_WARN_SIGN_COMPARE = YES;
 				GCC_WARN_STRICT_SELECTOR_MATCH = YES;
 				GCC_WARN_UNDECLARED_SELECTOR = YES;
-				GCC_WARN_UNINITIALIZED_AUTOS = NO;
 				GCC_WARN_UNKNOWN_PRAGMAS = YES;
 				GCC_WARN_UNUSED_FUNCTION = YES;
 				GCC_WARN_UNUSED_LABEL = YES;
-				GCC_WARN_UNUSED_PARAMETER = NO;
 				GCC_WARN_UNUSED_VALUE = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
 				HEADER_SEARCH_PATHS = (
@@ -2076,7 +2064,6 @@
 				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
 				GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES;
 				GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
-				GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO;
 				GCC_WARN_ABOUT_RETURN_TYPE = YES;
 				GCC_WARN_CHECK_SWITCH_STATEMENTS = YES;
 				GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES;
@@ -2085,14 +2072,11 @@
 				GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES;
 				GCC_WARN_PEDANTIC = YES;
 				GCC_WARN_SHADOW = YES;
-				GCC_WARN_SIGN_COMPARE = YES;
 				GCC_WARN_STRICT_SELECTOR_MATCH = YES;
 				GCC_WARN_UNDECLARED_SELECTOR = YES;
-				GCC_WARN_UNINITIALIZED_AUTOS = NO;
 				GCC_WARN_UNKNOWN_PRAGMAS = YES;
 				GCC_WARN_UNUSED_FUNCTION = YES;
 				GCC_WARN_UNUSED_LABEL = YES;
-				GCC_WARN_UNUSED_PARAMETER = NO;
 				GCC_WARN_UNUSED_VALUE = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
 				HEADER_SEARCH_PATHS = (
--- a/share/CMakeLists.txt	Tue Jun 05 22:37:36 2012 +0200
+++ b/share/CMakeLists.txt	Mon Jun 25 10:44:27 2012 +0200
@@ -1,6 +1,6 @@
 add_subdirectory(hedgewars)
 
-IF(APPLE)
+IF(APPLE OR CROSSAPPLE)
 	#needed for CFBundleVersion and CFBundleShortVersionString
 	FIND_PROGRAM(HGCOMMAND hg)
 	IF (HGCOMMAND AND (EXISTS ${hedgewars_SOURCE_DIR}/.hg))
@@ -24,4 +24,4 @@
 		DESTINATION ../Resources/)
 	install(PROGRAMS "${hedgewars_SOURCE_DIR}/share/dsa_pub.pem"
 		DESTINATION ../Resources/)
-ENDIF(APPLE)
+ENDIF(APPLE OR CROSSAPPLE)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/share/hedgewars/Data/Scripts/Multiplayer/Highlander.cfg	Mon Jun 25 10:44:27 2012 +0200
@@ -0,0 +1,2 @@
+Default
+Default
--- a/share/hedgewars/Data/Scripts/Multiplayer/Space_Invasion.lua	Tue Jun 05 22:37:36 2012 +0200
+++ b/share/hedgewars/Data/Scripts/Multiplayer/Space_Invasion.lua	Mon Jun 25 10:44:27 2012 +0200
@@ -1608,7 +1608,7 @@
 
 		vType[i] = "generic"
 		vCounter[i] = 0
-		vCounterLim[i] = 3000
+		vCounterLim[i] = 150
 		vCircScore[i] = 0
 		vCircHealth[i] = 1
 
@@ -1801,7 +1801,7 @@
 			vType[i] = "drone"
 			vCircRadMin[i] = 50	*5
 			vCircRadMax[i] = 90	*5
-			vCounterLim[i] = 3000
+			vCounterLim[i] = 150
 			vCircScore[i] = 10
 			vCircHealth[i] = 1
 		--else
@@ -1826,7 +1826,7 @@
 			vCircRadMin[i] = 100*5
 			vCircRadMax[i] = 180*5
 			vCircWidth[i] = 1
-			vCounterLim[i] = 2000
+			vCounterLim[i] = 100
 			vCircScore[i] = 30
 			vCircHealth[i] = 3
 		else
@@ -1998,7 +1998,7 @@
 		end
 
 	-- if player is hit by circle bazooka
-	elseif (GetGearType(gear) == gtShell) then --or (GetGearType(gear) == gtBall) then
+	elseif (GetGearType(gear) == gtShell) and (CurrentHedgehog ~= nil) then --or (GetGearType(gear) == gtBall) then
 
 		dist = GetDistFromGearToGear(gear, CurrentHedgehog)
 
@@ -2387,17 +2387,19 @@
 		--WriteLnToConsole("I just got the velocity of the shell. It is dx: " .. dx .. "; dy: " .. dy)
 		--WriteLnToConsole("CurrentHedgehog is at X: " .. GetX(CurrentHedgehog) .. "; Y: " .. GetY(CurrentHedgehog) )
 
-		if GetX(gear) > GetX(CurrentHedgehog) then
-			dx = dx - turningSpeed--0.1
-		else
-			dx = dx + turningSpeed--0.1
-		end
-
-		if GetY(gear) > GetY(CurrentHedgehog) then
-			dy = dy - turningSpeed--0.1
-		else
-			dy = dy + turningSpeed--0.1
-		end
+        if CurrentHedgehog ~= nil then
+            if GetX(gear) > GetX(CurrentHedgehog) then
+                dx = dx - turningSpeed--0.1
+            else
+                dx = dx + turningSpeed--0.1
+            end
+
+            if GetY(gear) > GetY(CurrentHedgehog) then
+                dy = dy - turningSpeed--0.1
+            else
+                dy = dy + turningSpeed--0.1
+            end
+        end
 
 
 		if (GetGearType(gear) == gtShell) then
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/share/hedgewars/Data/Scripts/Multiplayer/The_Specialists.cfg	Mon Jun 25 10:44:27 2012 +0200
@@ -0,0 +1,2 @@
+Default
+Default
--- a/share/hedgewars/Data/Scripts/plist/Balanced Random Weapon.plist	Tue Jun 05 22:37:36 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>command</key>
-	<string>escript Scripts/Multiplayer/Balanced_Random_Weapon.lua</string>
-	<key>description</key>
-	<string></string>
-	<key>scheme</key>
-	<string>Default.plist</string>
-	<key>weapon</key>
-	<string></string>
-</dict>
-</plist>
--- a/share/hedgewars/Data/Scripts/plist/Capture the Flag.plist	Tue Jun 05 22:37:36 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>command</key>
-	<string>escript Scripts/Multiplayer/Capture_the_Flag.lua</string>
-	<key>description</key>
-	<string></string>
-	<key>scheme</key>
-	<string>Default.plist</string>
-	<key>weapon</key>
-	<string>Default.plist</string>
-</dict>
-</plist>
--- a/share/hedgewars/Data/Scripts/plist/Highlander.plist	Tue Jun 05 22:37:36 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>command</key>
-	<string>escript Scripts/Multiplayer/Highlander.lua</string>
-	<key>description</key>
-	<string></string>
-	<key>scheme</key>
-	<string>Default.plist</string>
-	<key>weapon</key>
-	<string>Default.plist</string>
-</dict>
-</plist>
--- a/share/hedgewars/Data/Scripts/plist/No Jumping.plist	Tue Jun 05 22:37:36 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>command</key>
-	<string>escript Scripts/Multiplayer/No_Jumping.lua</string>
-	<key>description</key>
-	<string></string>
-	<key>scheme</key>
-	<string>Default.plist</string>
-	<key>weapon</key>
-	<string>Default.plist</string>
-</dict>
-</plist>
--- a/share/hedgewars/Data/Scripts/plist/Normal.plist	Tue Jun 05 22:37:36 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>command</key>
-	<string></string>
-	<key>description</key>
-	<string></string>
-	<key>scheme</key>
-	<string>Default.plist</string>
-	<key>weapon</key>
-	<string>Default.plist</string>
-</dict>
-</plist>
--- a/share/hedgewars/Data/Scripts/plist/Racer.plist	Tue Jun 05 22:37:36 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>command</key>
-	<string>escript Scripts/Multiplayer/Racer.lua</string>
-	<key>description</key>
-	<string></string>
-	<key>scheme</key>
-	<string>Shoppa.plist</string>
-	<key>weapon</key>
-	<string>Shoppa.plist</string>
-</dict>
-</plist>
--- a/share/hedgewars/Data/Scripts/plist/Random Weapon.plist	Tue Jun 05 22:37:36 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>command</key>
-	<string>escript Scripts/Multiplayer/Balanced_Random_Weapon.lua</string>
-	<key>description</key>
-	<string></string>
-	<key>scheme</key>
-	<string>Default.plist</string>
-	<key>weapon</key>
-	<string></string>
-</dict>
-</plist>
--- a/share/hedgewars/Data/Scripts/plist/Space Invasion.plist	Tue Jun 05 22:37:36 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>command</key>
-	<string>escript Scripts/Multiplayer/Space_Invasion.lua</string>
-	<key>description</key>
-	<string></string>
-	<key>scheme</key>
-	<string>Default.plist</string>
-	<key>weapon</key>
-	<string>Default.plist</string>
-</dict>
-</plist>
--- a/share/hedgewars/Data/Scripts/plist/The Specialists.plist	Tue Jun 05 22:37:36 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>command</key>
-	<string>escript Scripts/Multiplayer/The_Specialists.lua</string>
-	<key>description</key>
-	<string></string>
-	<key>scheme</key>
-	<string></string>
-	<key>weapon</key>
-	<string></string>
-</dict>
-</plist>
--- a/share/hedgewars/Data/Scripts/plist/Tumbler.plist	Tue Jun 05 22:37:36 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>command</key>
-	<string>escript Scripts/Multiplayer/Tumbler.lua</string>
-	<key>description</key>
-	<string></string>
-	<key>scheme</key>
-	<string>Default.plist</string>
-	<key>weapon</key>
-	<string>Default.plist</string>
-</dict>
-</plist>
--- a/tools/pas2c.hs	Tue Jun 05 22:37:36 2012 +0200
+++ b/tools/pas2c.hs	Mon Jun 25 10:44:27 2012 +0200
@@ -89,8 +89,8 @@
     s <- flip execStateT initState $ f fn
     renderCFiles s
     where
-    printLn = liftIO . hPutStrLn stderr
-    print = liftIO . hPutStr stderr
+    printLn = liftIO . hPutStrLn stdout
+    print = liftIO . hPutStr stdout
     initState = Map.empty
     f :: String -> StateT (Map.Map String PascalUnit) IO ()
     f fileName = do
@@ -122,7 +122,7 @@
 renderCFiles units = do
     let u = Map.toList units
     let nss = Map.map (toNamespace nss) units
-    hPutStrLn stderr $ "Units: " ++ (show . Map.keys . Map.filter (not . Map.null) $ nss)
+    --hPutStrLn stderr $ "Units: " ++ (show . Map.keys . Map.filter (not . Map.null) $ nss)
     --writeFile "pas2c.log" $ unlines . map (\t -> show (fst t) ++ "\n" ++ (unlines . map ((:) '\t' . show) . snd $ t)) . Map.toList $ nss
     mapM_ (toCFiles nss) u
     where
@@ -166,7 +166,7 @@
 toCFiles :: Map.Map String Records -> (String, PascalUnit) -> IO ()
 toCFiles _ (_, System _) = return ()
 toCFiles ns p@(fn, pu) = do
-    hPutStrLn stderr $ "Rendering '" ++ fn ++ "'..."
+    hPutStrLn stdout $ "Rendering '" ++ fn ++ "'..."
     toCFiles' p
     where
     toCFiles' (fn, p@(Program {})) = writeFile (fn ++ ".c") $ (render2C initialState . pascal2C) p