# HG changeset patch # User sheepluva # Date 1447184593 -3600 # Node ID ed5a6478e71019ab54dc67d9c003ce0d263d4ffd # Parent 31570b766315e7b4658f384ec374ff02b8495fbf# Parent 852bf1e052f4b243f049f0169d441c99c709cd64 merge default diff -r 31570b766315 -r ed5a6478e710 .hgignore --- a/.hgignore Tue Nov 10 18:16:35 2015 +0100 +++ b/.hgignore Tue Nov 10 20:43:13 2015 +0100 @@ -26,7 +26,7 @@ glob:*.diff glob:vittorio.* glob:project_files/HedgewarsMobile/Data/ -glob:project_files/HedgewarsMobile/build/ +glob:project_files/HedgewarsMobile/Build/ glob:gameServer/dist/ glob:misc/liblua/Xcode/build/ glob:misc/libphysfs/Xcode/build/ @@ -40,6 +40,8 @@ glob:*.orig glob:*.bak glob:*.rej +glob:project_files/hwc/*.c +glob:project_files/hwc/*.h glob:project_files/Android-build/SDL-android-project/jni/** glob:project_files/Android-build/SDL-android-project/obj glob:project_files/Android-build/SDL-android-project/libs/armeabi* @@ -63,3 +65,18 @@ glob:*.tar.* glob:*.or glob:*.res +glob:Hedgewars.app/* +glob:tools/CreateMacBundle.cmake +glob:share/Info.plist +glob:CTestTestfile.cmake +glob:arch.c +glob:*.swp +glob:*~.nib +glob:*.pbxuser +glob:*.perspective +glob:*.perspectivev3 +glob:*.project.xcworkspace +glob:*.xcuserdata +glob:xcuserdata +glob:*.mode1v3 +glob:*.mode2v3 diff -r 31570b766315 -r ed5a6478e710 .hgtags --- a/.hgtags Tue Nov 10 18:16:35 2015 +0100 +++ b/.hgtags Tue Nov 10 20:43:13 2015 +0100 @@ -60,3 +60,13 @@ 0000000000000000000000000000000000000000 0.9.18-release 2fc02902c7cbf3c29bfe08a50e5f37983582b251 0.9.18-release 1617149e01a4fa25637e2ab655d0287ef9c21b7c 0.9.19-release +af0520a6bf0061b27f8321514d35fcd2b1ef5f9c 0.9.20-release +7e55468ffe384a3065524c483eb5e3cdb1658fd5 0.9.21-release +7e55468ffe384a3065524c483eb5e3cdb1658fd5 fab746a3597e +0f5961910e2712582b162abd08ae3eed330cc978 Nice one +d9622394ec9c2974a84b9b4d9e6c0ac26c4060ff 0.9.22-RC +0f5961910e2712582b162abd08ae3eed330cc978 Nice one +0000000000000000000000000000000000000000 Nice one +4c4f22cc3fa4e6c1e5cd6cce35350dd93478415f 0.9.22-release +4c4f22cc3fa4e6c1e5cd6cce35350dd93478415f 0.9.22-release +9621fdcad96589b3fd78713a0f31e72f26f068bb 0.9.22-release diff -r 31570b766315 -r ed5a6478e710 .travis.yml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.travis.yml Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,31 @@ +language: c +branches: + except: + gh-pages +compiler: + - gcc + - clang +env: + - BUILD_ARGS="-DCMAKE_BUILD_TYPE=Release" + - BUILD_ARGS="-DCMAKE_BUILD_TYPE=Debug" + - BUILD_ARGS="-DNOSERVER=1 -DBUILD_ENGINE_C=1" + - BUILD_ARGS="-DNOSERVER=1 -DNOVIDEOREC=1 -DNOPNG=1" + - BUILD_ARGS="-DNOSERVER=1 -DLUA_SYSTEM=0 -DPHYSFS_SYSTEM=0" +matrix: + allow_failures: + # Failures we expect here +before_install: + - sudo apt-get update -qq + - sudo apt-get install debhelper cmake dpkg-dev libqt4-dev qt4-qmake libphysfs-dev libsdl1.2-dev libsdl-ttf2.0-dev libsdl-mixer1.2-dev libsdl-image1.2-dev libsdl-net1.2-dev bzip2 ghc libghc-mtl-dev libghc-parsec3-dev libghc-bytestring-show-dev libghc-vector-dev libghc-zlib-dev libghc-random-dev libghc-stm-dev libghc-network-dev libghc-dataenc-dev libghc-hslogger-dev libghc-utf8-string-dev libghc-sha-dev libghc-entropy-dev liblua5.1-0-dev imagemagick fpc fp-compiler fp-units-misc libpng-dev fp-units-gfx libavcodec-dev libavformat-dev freeglut3-dev libglew1.6-dev +script: + - mkdir build && cd build && cmake $BUILD_ARGS .. && make VERBOSE=1 && make test_verbose +notifications: + email: false + irc: + channels: + - "chat.freenode.net#hedgewars" + template: + - "hw-build #%{build_number} (%{commit} by %{author}): %{message}" + - "See details at %{build_url}" + on_success: change + on_failure: always diff -r 31570b766315 -r ed5a6478e710 CMakeLists.txt --- a/CMakeLists.txt Tue Nov 10 18:16:35 2015 +0100 +++ b/CMakeLists.txt Tue Nov 10 20:43:13 2015 +0100 @@ -12,18 +12,18 @@ include(${CMAKE_MODULE_PATH}/utils.cmake) #possible cmake configuration -option(NOSERVER "Disable gameServer build (off)]" OFF) +option(NOSERVER "Disable gameServer build (off)" OFF) option(NOPNG "Disable screenshoot compression (off)" OFF) option(NOVIDEOREC "Disable video recording (off)" OFF) #libraries are built shared unless explicitly added as a static option(BUILD_SHARED_LIBS "Build libraries as shared modules (on)" ON) -#set this to ON when 2.1.0 becomes more widespread (and only for linux) -option(PHYSFS_SYSTEM "Use system physfs (off)" OFF) if(WIN32 OR APPLE) + option(PHYSFS_SYSTEM "Use system physfs (off)" OFF) option(LUA_SYSTEM "Use system lua (off)" OFF) else() + option(PHYSFS_SYSTEM "Use system physfs (on)" ON) option(LUA_SYSTEM "Use system lua (on)" ON) endif() @@ -32,18 +32,28 @@ option(MINIMAL_FLAGS "Respect system flags as much as possible (off)" OFF) option(NOAUTOUPDATE "Disable OS X Sparkle update checking (off)" OFF) +option(SKIPBUNDLE "Do not create relocate bundle (off)" OFF) + +option(BUILD_ENGINE_C "Compile hwengine as native C (off)" OFF) +option(GL2 "Enable OpenGL 2 rendering !!!EXPERIMENTAL - DO NOT USE!!! [default: off)" OFF) set(GHFLAGS "" CACHE STRING "Additional Haskell flags") if(UNIX AND NOT APPLE) set(DATA_INSTALL_DIR "share/hedgewars" CACHE STRING "Resource folder path") endif() +option(NOVERSIONINFOUPDATE "Disable update of version_info.txt. To be used if source is in a git/repo that is NOT the hedgewars repo" OFF) + +#system paths for finding required fonts (see share/hedgewars/Data/fonts) +#subdirectories will NOT be searched. +#all fonts that can't be found will be bundled with hedgewars +set(FONTS_DIRS "" CACHE STRING "Additional paths to folders where required fonts can be found ( ; is separator)") #versioning set(CPACK_PACKAGE_VERSION_MAJOR 0) set(CPACK_PACKAGE_VERSION_MINOR 9) -set(CPACK_PACKAGE_VERSION_PATCH 20) -set(HEDGEWARS_PROTO_VER 46) +set(CPACK_PACKAGE_VERSION_PATCH 23) +set(HEDGEWARS_PROTO_VER 52) set(HEDGEWARS_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}") include(${CMAKE_MODULE_PATH}/revinfo.cmake) @@ -53,20 +63,24 @@ include(${CMAKE_MODULE_PATH}/paths.cmake) #general utilities include(${CMAKE_MODULE_PATH}/utils.cmake) +#paths initialization +include(${CMAKE_MODULE_PATH}/paths.cmake) #platform specific init code include(${CMAKE_MODULE_PATH}/platform.cmake) #when build type is not specified, assume Debug/Release according to build version information -if (CMAKE_BUILD_TYPE) - string (TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE) - if ( NOT( (CMAKE_BUILD_TYPE MATCHES "RELEASE") OR (CMAKE_BUILD_TYPE MATCHES "DEBUG") ) ) - set (CMAKE_BUILD_TYPE ${default_build_type} CACHE STRING "Build type (Debug/Release)" FORCE) - message (STATUS "Unknown build type, using default (${default_build_type})") - endif () -else (CMAKE_BUILD_TYPE) - set (CMAKE_BUILD_TYPE ${default_build_type} CACHE STRING "Build type (Debug/Release)" FORCE) -endif (CMAKE_BUILD_TYPE) +if(CMAKE_BUILD_TYPE) + string(TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE) + if(NOT((CMAKE_BUILD_TYPE MATCHES "RELEASE") OR + (CMAKE_BUILD_TYPE MATCHES "DEBUG") OR + (CMAKE_BUILD_TYPE MATCHES "RELWITHDEBINFO"))) + set(CMAKE_BUILD_TYPE ${default_build_type} CACHE STRING "Build type (Debug/Release/RelWithDebInfo)" FORCE) + message(STATUS "Unknown build type ${CMAKE_BUILD_TYPE}, using default (${default_build_type})") + endif() +else(CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE ${default_build_type} CACHE STRING "Build type (Debug/Release/RelWithDebInfo)" FORCE) +endif(CMAKE_BUILD_TYPE) #perform safe check that enable/disable compilation features @@ -74,17 +88,14 @@ #set default compiler flags add_flag_append(CMAKE_C_FLAGS "-Wall -pipe") -add_flag_append(CMAKE_C_FLAGS_RELEASE "-Os") +add_flag_append(CMAKE_C_FLAGS_RELEASE "-O2") add_flag_append(CMAKE_C_FLAGS_DEBUG "-Wextra -O0") add_flag_append(CMAKE_CXX_FLAGS "-Wall -pipe") -add_flag_append(CMAKE_CXX_FLAGS_RELEASE "-Os") +add_flag_append(CMAKE_CXX_FLAGS_RELEASE "-O2") add_flag_append(CMAKE_CXX_FLAGS_DEBUG "-Wextra -O0") -add_flag_append(CMAKE_Pascal_FLAGS "-Cs2000000") -add_flag_append(CMAKE_Pascal_FLAGS_DEBUG "-O- -gv") -add_flag_append(CMAKE_Pascal_FLAGS_RELEASE "-Os -Xs") #CMake adds a lot of additional configuration flags, so let's clear them up -if(${MINIMAL_FLAGS}) +if(MINIMAL_FLAGS) unset(CMAKE_C_FLAGS_RELEASE) unset(CMAKE_C_FLAGS_DEBUG) unset(CMAKE_CXX_FLAGS_RELEASE) @@ -97,7 +108,7 @@ if(${CMAKE_VERSION} VERSION_GREATER 2.6) separate_arguments(ghflags_parsed UNIX_COMMAND ${GHFLAGS}) else() - message(${WARNING} "GHFLAGS are available only when using CMake >= 2.8") + message("*** GHFLAGS are available only when using CMake >= 2.8 ***") endif() endif() @@ -109,6 +120,7 @@ list(APPEND haskell_flags "-Wall" # all warnings "-debug" # debug mode "-dcore-lint" # internal sanity check + "-fno-warn-unused-do-bind" ) else() list(APPEND haskell_flags "-w" # no warnings @@ -116,14 +128,32 @@ endif() +#build engine without freepascal +if(BUILD_ENGINE_C) + find_package(Clang REQUIRED) + + if(${CLANG_VERSION} VERSION_LESS "3.0") + message(FATAL_ERROR "LLVM/Clang compiler required version is 3.0 but version ${CLANG_VERSION} was found!") + endif() + + set(CMAKE_C_COMPILER ${CLANG_EXECUTABLE}) + set(CMAKE_CXX_COMPILER ${CLANG_EXECUTABLE}) +endif() + + +#server +if(NOT NOSERVER) + add_subdirectory(gameServer) +endif() + + #lua discovery -if (${LUA_SYSTEM}) - if (NOT LUA_LIBRARY OR NOT LUA_INCLUDE_DIR) +if(LUA_SYSTEM) + if(NOT LUA_LIBRARY OR NOT LUA_INCLUDE_DIR) find_package(Lua) endif() - if (LUA_LIBRARY AND LUA_INCLUDE_DIR) - set(LUA_FOUND TRUE) + if(LUA_LIBRARY AND LUA_INCLUDE_DIR) #use an IMPORTED tharget so that we can just use 'lua' to link add_library(lua UNKNOWN IMPORTED) set_target_properties(lua PROPERTIES IMPORTED_LOCATION ${LUA_LIBRARY}) @@ -131,7 +161,7 @@ message(FATAL_ERROR "Missing Lua! Rerun cmake with -DLUA_SYSTEM=off to build the internal version") endif() else() - if (NOT LUA_LIBRARY OR NOT LUA_INCLUDE_DIR) + if(NOT LUA_LIBRARY OR NOT LUA_INCLUDE_DIR) message(STATUS "LUA will be provided by the bundled sources") endif() set(lua_output_name "hwlua") @@ -140,8 +170,8 @@ #physfs discovery -if (${PHYSFS_SYSTEM}) - if (NOT PHYSFS_LIBRARY OR NOT PHYSFS_INCLUDE_DIR) +if(PHYSFS_SYSTEM) + if(NOT PHYSFS_LIBRARY OR NOT PHYSFS_INCLUDE_DIR) find_package(PhysFS) endif() @@ -155,54 +185,71 @@ string(REGEX MATCH "([0-9]+)" physfs_patchversion "${physfs_patchversion}") set(physfs_detected_ver "${physfs_majorversion}.${physfs_minorversion}.${physfs_patchversion}") - if (physfs_detected_ver VERSION_LESS "2.1.0") - message(FATAL_ERROR "PhysFS version is too old (dected ${physfs_detected_ver}, required 2.1.0)") - set(physfs_too_old true) + if(${physfs_detected_ver} VERSION_LESS 2.0.0) + message(FATAL_ERROR "PhysFS version is too old (detected ${physfs_detected_ver}, required 2.0.0)\n" + "Perform an update or rerun cmake with -DPHYSFS_SYSTEM=off to build the internal version") endif() endif() - if (NOT PHYSFS_LIBRARY OR NOT PHYSFS_INCLUDE_DIR) - message(FATAL_ERROR "Missing PhysFS! Rerun cmake with -DPHYSFS_SYSTEM=off to build the internal version") - else() + if(PHYSFS_LIBRARY AND PHYSFS_INCLUDE_DIR) #use an IMPORTED tharget so that we can just use 'physfs' to link add_library(physfs UNKNOWN IMPORTED) set_target_properties(physfs PROPERTIES IMPORTED_LOCATION ${PHYSFS_LIBRARY}) + else() + message(FATAL_ERROR "Missing PhysFS! Rerun cmake with -DPHYSFS_SYSTEM=off to build the internal version") endif() else() - if (NOT PHYSFS_LIBRARY OR NOT PHYSFS_INCLUDE_DIR) + if(NOT PHYSFS_LIBRARY OR NOT PHYSFS_INCLUDE_DIR) message(STATUS "PhysFS will be provided by the bundled sources") endif() set(physfs_output_name "hwphysfs") add_subdirectory(misc/libphysfs) endif() -find_package_or_disable_msg(FFMPEG NOVIDEOREC "Video recording will not be built") +find_package_or_disable_msg(LIBAV NOVIDEOREC "Video recording will not be built") #physfs helper library add_subdirectory(misc/libphyslayer) -#server -if(NOT NOSERVER) - add_subdirectory(gameServer) +#maybe this could be merged inside hedgewars/CMakeLists.txt +if(BUILD_ENGINE_C) + #pascal to c converter + add_subdirectory(tools/pas2c) + add_subdirectory(project_files/hwc) +else() + #main pascal engine + add_subdirectory(hedgewars) endif() -#main engine -add_subdirectory(hedgewars) - #Android related build scripts +#TODO: when ANDROID, BUILD_ENGINE_LIBRARY should be set if(ANDROID) - #run cmake -DANDROID=1 to enable this add_subdirectory(project_files/Android-build) -endif() - -#TODO: when ANDROID, BUILD_ENGINE_LIBRARY should be set -if(NOT ANDROID) +else(ANDROID) add_subdirectory(bin) add_subdirectory(QTfrontend) add_subdirectory(share) add_subdirectory(tools) -endif() - +endif(ANDROID) include(${CMAKE_MODULE_PATH}/cpackvars.cmake) +enable_testing() + +add_custom_target(test_normal COMMAND ${CMAKE_CTEST_COMMAND} -E '^todo/' --timeout 300 --schedule-random) +add_custom_target(test_verbose COMMAND ${CMAKE_CTEST_COMMAND} -E '^todo/' --timeout 300 --schedule-random -V) + +set(LUATESTS_DIR "${CMAKE_SOURCE_DIR}/tests/lua") +set(TESTSDATA_DIR "${CMAKE_SOURCE_DIR}/share/hedgewars/Data") + +# set set this to "" if you want to see what's going on +# TODO: engine should do this implicitly when running tests, +# unless some env var like HWENGINE_SHOWTESTS is set or something +set(STATSONLYFLAG "--stats-only") + +# add all lua tests +file(GLOB_RECURSE luatests RELATIVE "${LUATESTS_DIR}" "${LUATESTS_DIR}/*.lua") +foreach(luatest ${luatests}) + add_test("${luatest}" "bin/hwengine" "--prefix" "${TESTSDATA_DIR}" "--nosound" "--nomusic" "${STATSONLYFLAG}" "--lua-test" "${LUATESTS_DIR}/${luatest}") +endforeach(luatest) + diff -r 31570b766315 -r ed5a6478e710 COPYING --- a/COPYING Tue Nov 10 18:16:35 2015 +0100 +++ b/COPYING Tue Nov 10 20:43:13 2015 +0100 @@ -2,7 +2,7 @@ Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. @@ -305,7 +305,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. diff -r 31570b766315 -r ed5a6478e710 CREDITS --- a/CREDITS Tue Nov 10 18:16:35 2015 +0100 +++ b/CREDITS Tue Nov 10 20:43:13 2015 +0100 @@ -25,6 +25,7 @@ - Lortinak -> OldMan (2010), ShortHair (2010) - chujoii -> BrainSlug (2010), Dragon (2010), Ladle (2010), Laminaria (2010), Pantsu (2010), Pig (2010), Plunger (2010), SauceBoat (2010), ShaggyYeti (2010), SleepWalker (2010), SunWukong (2010), Teapot (2010), Teacup (2010), Zombi (2010) - Randy Broda -> Cyclops (2011), Soldier (2011) +- Wohlstand -> PoliceGirl [based on policecap and sm_daisy] (2014) ========== = GRAVESTONES @@ -45,6 +46,8 @@ ========== - John Dum -> Nature theme - Jonatan Nilsson -> Pirate theme, City theme, Oriental theme, Snow theme +- yd - http://opengameart.org/users/yd -> "oriented", used as Olympics SD theme +- Kevin MacLeod - http://incompetech.com/ -> "hitman", used as basis for preliminary default SD theme ========== = THEMES diff -r 31570b766315 -r ed5a6478e710 ChangeLog.txt --- a/ChangeLog.txt Tue Nov 10 18:16:35 2015 +0100 +++ b/ChangeLog.txt Tue Nov 10 20:43:13 2015 +0100 @@ -1,9 +1,131 @@ + features * bugfixes -0.9.19 -> ???: - * increase precision in damage calcs; extra damage affects fire properly now - * visual enhancements for whip +0.9.22 -> 0.9.23 + * Hammer damage is now rounded down. This means it will cause NO DAMAGE to a hedgehog with less than 3 hp. + * Fixed bee not being affected by wrap world edge while still being thrown + * Fixed turn not ending when sticky mine was trapped on rubberband + * Various other fixes + +0.9.21 -> 0.9.22 + + New Weapon / Map object: AirMine (floating mine that will follow nearby hedgehogs) + + Extensive changes to TechRacer: Variable terrain types, enhanced parameters, hwmap interpreter, fuel limiter, etc. + + HedgeEditor - create missions/etc. in-game! see http://hedgewars.org/HedgeEditor + + Map previews can now take script parameters into account and preview waypoints in TechRacer + + Added a couple new flags + + Various tweaks to the interface and in-game chat + + Divided teams options will now just be ignored when more/less than 2 teams/clans, instead of displaying a fatal error + + Added 6 TechRacer maps to TechMaps + + Added 3 SpeedShoppa Challenges: Shoppa Love, Ropes and Crates, The Customer is King + + Hammer damage is now rounded up. This means it can be used to execute hedgehogs with only 1 hp. + + Improved "Art" theme. + * Generated bridges/girders are now connected better to the land mass + * Fixed rubberband sprite + * Fixed Wind-Indicator being wrong in certain situations + * Melon Bomb Pieces now bounce on Rubberband + * Reduced menu music volume + * The game will now fallback to default voicepack if a team's voicepack is not locally installed. (Instead of rendering team voiceless) + * Hammer now does more damage when the Extra-Damage utility is used + * Many other bug fixes + +Lua-API: + + New map parameter: MapFeatureSize -- numeric representation of detail slider below map preview; use within onGameInit()/onPreviewInit() + + New function: SetMaxBuildDistance([ distInPx ]) -- specify how many pixels away a hedgehog can still place girders/etc. set to 0 for no limit; call with no param to reset to default + + New hook: onSuddenDeath() -- called by engine when sudden death begins + * Previously missing gear states are now available (gstSubmersible, gstFrozen and gstNoGravity) + * Fixed OnHogAttack giving the incorrect AmmoType (amNothing) under certain conditions + +0.9.20 -> 0.9.21: + + New type of randomly generated maps: Perlin Maps. + + Old Random generated maps are more diverse now. + + Slider for adjusting land generation detail. + + Highlander gamemode can now be used with custom weapon schemes (1-8=How probable to get this weapon. 9=All hogs get it) + + New playable themes: "Hoggywood" and "Cake" + + New gameplay mode "Construction Mode" + + New gameplay mode "TechRacer" + + New game play mode "DiagonalMaze" (generates a simple diagonal maze) + + Add 7 target practice missions, now with simple scoring + + Update RC Plane Challenge: Stats screen reworked and shows now several facts, simple ranking system based on used planes, some taunts in the game + + New training/multiplayer mission: "Climb Home" + + Game scheme screen has a "Script parameter" field now. This allows to make more customizable scripts/modes. + + Network game rejoining. Note: Your team(s) will vanish after 3 turns. + + Visual and gameplay changes to "sea" - world edge, visual change to wrap world edge to allow seeing through the wrap, visual change to bounce worldedge + + The map of the Basketball Mission can be selected for regular games again ("BasketballField") + + New engine command: /togglechat will disable/enable chat display (does not affect chat history display) + + Change to Racer: first weapon/utility available will be automatically selected on start + + Added some visual feedback to failed girder placement. + + Various performance tweaks, especially for very large maps. + + Allow switching through hogs in reverse order with PRECISE+HOGSWITCH (left shift + tab, by default) + + Added support for custom Sudden Death music to theme.cfg (e.g. sd-music=hell.ogg ). + + New Hats: policegirl, fr_tomato, cratehider + * Fixed drill rockets sometimes exploding on impact. + * Fixed trainings broken due to indestructable targets/crates. + * Fixes and tweaks for low qualily rendering. + * Sinegun won't shoot through -solid- land anymore + * Many bug fixes and tweaks. + +Frontend / Netgame: + + High resolution previews! + + Preview for dynamic maps generated by game style scripts (e.g. "ShoppaMap))! + + Moved room status filter to top left of rooms list. + +Lua API: + + New library: Params, makes parsing of script parameters easier + + New library: TargetPractice, used to generate target practice missions (the newly added missions use it) + + More helpful syntax error messages. + + New hooks: + onParameters(paramString) -- called when script parameters are configured. the parameter contains the parameter(s) as text string + onPreviewInit() -- called during map preview initialization + onGearWaterSkip(gearUid) -- called when a gear skims the water without drowning (when hitting it with high speed at low angle). By checking gearUid you can figure out which gear that was. + + New functions: + DismissTeam(teamname) -- removes a team from the game (note: if you used loc() on teamnames, don't forget to the translated teamname here too) + GetGameFlag(gameflag) -- returns true/false + PlaceSprite(x, y, sprite, frameIdx [, landFlag, ... ]) -- sprite refers to an id from the TSprite list + SetWaterLine(waterline) -- moves water level to the specified y. the current value is in read-only global waterline + SetNextWeapon() -- make current hedgehog switch to next weapon. e.g. use in trainings to preselect weapon + SetWeapon(ammoType) -- decide which weapon the current hedgehog should equip + + Map Drawing: + -- to be used in onGameInit() -- first set MapGen to mgDrawn and then use the commands below + AddPoint(x, y [, width [, erase] ]) -- takes x,y location, a width (means start of a new line) and erase (if line should erase, not draw) + FlushPoints() -- makes sure that all the points/lines specified using the command above are actually applied to the map + + New global enumerations: + Mapgens: mgRandom, mgMaze, mgPerlin, mgDrawn + TSprite values + LandFlags: lfIndestructible, lfIce, lfBouncy + + Changed functions: + HogSay(gearUid, text, manner [, vgState]) -- now also allows you to make NON-Hedgehog gears speak, e.g. barrels... wait what?! + + Changed hooks: + onHogAttack() can now be hooked with new parameter: onHogAttack(ammoType) - to conveniently find out which ammo/weapon is being used + * Fixes: + gfResetHealth is now a available like the other GameFlags +0.9.19 -> 0.9.20: + + New campaign, A Space Adventure! + + Password protected rooms + + Shapes on drawn maps (ellipses, rectangles) - constrain dimensions with ctrl, as with straight line tool. + + New rubber utility, lfBouncy mask (green) for maps. lfBouncy is also anti-portal. + + Lazy loading of many aspects of frontend to improve startup time under Windows + + Set hog/team/health label defaults in config, toggle team health display using delete (left shift + delete for labels now) + + Usernames next to teams when playing online. + + Can now filter rooms by game style (such as Highlander). Filtering simplified since it is mostly unused. + + AFK mode. Press p when not your turn online to trigger autoskip of your turn. + + Russian localisation of Default voice. + + Map edges can wrap or bounce. Also a silly "connect to the sea" mode + + Sticky fire kicks you a bit less, fire interacts with frozen land/ice + + Generated map stays same if the template is the same between groups (all/large for example) + + Visual enhancements for whip and crosshair + + Option to draw maps with a "shoppa" border - used by ShoppaMap lua at present + + New hats + + Translation updates + + New lua script to control gravity. May have unpredictable effects. Try zero g shoppa. Changes to allow lua to spawn poison clouds without interrupting turn. + + Speech bubbles are now echoed to chat for logging purposes with the hog's name. + * You should now thaw on your turn, not enemy's. AI frozen/unfrozen crate movement fix. Blowtorch can thaw frozen hogs. + * Prevent target crosshair moving around unpredictably when doing multiple airstrikes + * Rope should kick along surfaces more reliably, fix rope aim speed if you miss a shot, firing rope does not freeze timer, fix aiming on last rope + * Remember bounce/timer in reset wep modes like Highlander + * Increase precision in damage calcs; extra damage affects fire properly now + * Fixed video recording resolution + * Fixed context menu/cursor in text areas + * Many bugfixes. Keypad enter in chat, hog sliding freezing game, team name flaws in Windows, localisation of tips, crasher in slots with no weapons, frontend holiday css. 0.9.18 -> 0.9.19: + New Freezer weapon - freezes terrain, water, hedgehogs, mines, cases, explosives diff -r 31570b766315 -r ed5a6478e710 INSTALL --- a/INSTALL Tue Nov 10 18:16:35 2015 +0100 +++ b/INSTALL Tue Nov 10 20:43:13 2015 +0100 @@ -1,14 +1,14 @@ To compile and install you need: - CMake >= 2.6.0 - - FreePascal >= 2.2.0 - - Qt >= 4.5.0 + - FreePascal >= 2.2.4 + - Qt >= 4.7.0 - SDL >= 2.0 - SDL_net >= 2.0 - SDL_mixer >= 2.0 - SDL_image >= 2.0 - SDL_ttf >= 2.0 - - Lua >= 5.1.0 - - Physfs >= 2.1.0 + - Lua = 5.1.0 + - Physfs >= 2.0.0 For server: - Glasgow Haskell Compiler >= 6.10 - bytestring-show package @@ -16,7 +16,6 @@ - hslogger package For videorecording: - FFmpeg or LibAV - - GLUT (when SDL < 2) For compressed screenshots: - libpng diff -r 31570b766315 -r ed5a6478e710 QTfrontend/CMakeLists.txt --- a/QTfrontend/CMakeLists.txt Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/CMakeLists.txt Tue Nov 10 20:43:13 2015 +0100 @@ -1,5 +1,5 @@ # Configure for Qt4 -set(QT_MIN_VERSION "4.5.0") +set(QT_MIN_VERSION "4.7.0") include(CheckLibraryExists) set(QT_USE_QTCORE TRUE) @@ -13,10 +13,11 @@ find_package(Qt4 REQUIRED) include(${QT_USE_FILE}) +# https://bugreports.qt-project.org/browse/QTBUG-17333 if(APPLE AND ${QTVERSION} VERSION_GREATER "4.7.0" AND ${QTVERSION} VERSION_LESS "4.7.4") - message(FATAL_ERROR "This version of QT is known *not* to work, please update or use a lower version") + message(FATAL_ERROR "This version of Qt is known *not* to work, please update or use a lower version") endif() find_package(SDL2 REQUIRED) @@ -24,10 +25,10 @@ include_directories(${SDL2_INCLUDE_DIR}) include_directories(${SDL2MIXER_INCLUDE_DIR}) -if(${FFMPEG_FOUND}) +if(LIBAV_FOUND) add_definitions(-DVIDEOREC -D__STDC_CONSTANT_MACROS) - include_directories(${FFMPEG_INCLUDE_DIR}) - list(APPEND HW_LINK_LIBS ${FFMPEG_LIBRARIES}) + include_directories(${LIBAV_INCLUDE_DIR}) + list(APPEND HW_LINK_LIBS ${LIBAV_LIBRARIES}) endif() # server messages localization @@ -61,9 +62,9 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/ui/widget) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/util) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/util/platform) -include_directories(${PHYSFS_INCLUDE_DIR}) -include_directories(${PHYSLAYER_INCLUDE_DIR}) - +include_directories(BEFORE ${PHYSFS_INCLUDE_DIR}) +include_directories(BEFORE ${PHYSLAYER_INCLUDE_DIR}) +include_directories(${LUA_INCLUDE_DIR}) #brought by physlayer hwpacksmounter.h if(UNIX) # HACK: in freebsd cannot find iconv.h included via SDL.h @@ -152,10 +153,15 @@ set(hwfr_rez hedgewars.qrc) -if(${BUILD_ENGINE_LIBRARY}) +if(BUILD_ENGINE_LIBRARY) add_definitions(-DHWLIBRARY=1) set(hwlibname "${EXECUTABLE_OUTPUT_PATH}/${CMAKE_SHARED_LIBRARY_PREFIX}hwengine${CMAKE_SHARED_LIBRARY_SUFFIX}") list(APPEND HW_LINK_LIBS ${hwlibname}) + + if(LIBAV_FOUND) +# add_subdirectory(avwrapper) + list(APPEND HW_LINK_LIBS avwrapper) + endif() endif() qt4_add_resources(hwfr_rez_src ${hwfr_rez}) @@ -184,9 +190,9 @@ #when debugging, always prompt a console to see fronted messages #TODO: check it doesn't interfere on UNIX -if(CMAKE_BUILD_TYPE MATCHES "RELEASE") +if(CMAKE_BUILD_TYPE MATCHES "RELEASE" OR CMAKE_BUILD_TYPE MATCHES "RELWITHDEBINFO") set(console_access "WIN32") -endif(CMAKE_BUILD_TYPE MATCHES "RELEASE") +endif(CMAKE_BUILD_TYPE MATCHES "RELEASE" OR CMAKE_BUILD_TYPE MATCHES "RELWITHDEBINFO") add_executable(hedgewars ${console_access} ${hwfr_src} @@ -204,7 +210,7 @@ ${SDL2_LIBRARY} ${SDL2MIXER_LIBRARY} ) - + if(WIN32 AND NOT UNIX) if(NOT SDL_LIBRARY) list(APPEND HW_LINK_LIBS SDL) @@ -218,6 +224,10 @@ ) endif() +if(CMAKE_CXX_COMPILER MATCHES "clang*") + list(APPEND HW_LINK_LIBS stdc++ m) +endif() + target_link_libraries(hedgewars ${HW_LINK_LIBS}) diff -r 31570b766315 -r ed5a6478e710 QTfrontend/HWApplication.cpp --- a/QTfrontend/HWApplication.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/HWApplication.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -13,14 +13,13 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "HWApplication.h" #include #include -#include "hwform.h" #include "MessageDialog.h" #if !defined(Q_OS_WIN) diff -r 31570b766315 -r ed5a6478e710 QTfrontend/HWApplication.h --- a/QTfrontend/HWApplication.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/HWApplication.h Tue Nov 10 20:43:13 2015 +0100 @@ -13,13 +13,14 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef HWAPP_H #define HWAPP_H #include +#include "hwform.h" class HWForm; class QEvent; diff -r 31570b766315 -r ed5a6478e710 QTfrontend/achievements.cpp --- a/QTfrontend/achievements.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/achievements.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff -r 31570b766315 -r ed5a6478e710 QTfrontend/achievements.h --- a/QTfrontend/achievements.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/achievements.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef ACHIEVEMENTS_H diff -r 31570b766315 -r ed5a6478e710 QTfrontend/binds.cpp --- a/QTfrontend/binds.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/binds.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "binds.h" @@ -46,7 +46,7 @@ {"timer 5", "5", QT_TRANSLATE_NOOP("binds", "timer 5 sec"), NULL, NULL}, {"+attack", "space", QT_TRANSLATE_NOOP("binds", "attack"), NULL, QT_TRANSLATE_NOOP("binds (descriptions)", "Fire your selected weapon or trigger an utility item:")}, {"put", "mousel", QT_TRANSLATE_NOOP("binds", "put"), NULL, QT_TRANSLATE_NOOP("binds (descriptions)", "Pick a weapon or a target location under the cursor:")}, - {"findhh", "h", QT_TRANSLATE_NOOP("binds", "find hedgehog"), QT_TRANSLATE_NOOP("binds (categories)", "Camera"), QT_TRANSLATE_NOOP("binds (descriptions)", "Move the camera to the active hog:")}, + {"findhh", "h", QT_TRANSLATE_NOOP("binds", "autocam / find hedgehog"),QT_TRANSLATE_NOOP("binds (categories)", "Camera"), QT_TRANSLATE_NOOP("binds (descriptions)", "Toggle automatic camera / refocus on active hedgehog:")}, {"+cur_u", "[8]", QT_TRANSLATE_NOOP("binds", "up"), NULL, QT_TRANSLATE_NOOP("binds (descriptions)", "Move the cursor or camera without using the mouse:")}, {"+cur_l", "[4]", QT_TRANSLATE_NOOP("binds", "left"), NULL, NULL}, {"+cur_r", "[6]", QT_TRANSLATE_NOOP("binds", "right"), NULL, NULL}, @@ -65,6 +65,7 @@ {"mute", "8", QT_TRANSLATE_NOOP("binds", "mute audio"), NULL, NULL}, {"fullscr", "f12", QT_TRANSLATE_NOOP("binds", "change mode"), NULL, QT_TRANSLATE_NOOP("binds (descriptions)", "Toggle fullscreen mode:")}, {"capture", "c", QT_TRANSLATE_NOOP("binds", "capture"), NULL, QT_TRANSLATE_NOOP("binds (descriptions)", "Take a screenshot:")}, + {"+speedup", "s", QT_TRANSLATE_NOOP("binds", "speed up replay"), NULL, QT_TRANSLATE_NOOP("binds (descriptions)", "Demo replay:")}, {"rotmask", "delete", QT_TRANSLATE_NOOP("binds", "hedgehog info"), NULL, QT_TRANSLATE_NOOP("binds (descriptions)", "Toggle labels above hedgehogs:")}, #ifdef VIDEOREC {"record", "r", QT_TRANSLATE_NOOP("binds", "record"), NULL, QT_TRANSLATE_NOOP("binds (descriptions)", "Record video:")} diff -r 31570b766315 -r ed5a6478e710 QTfrontend/binds.h --- a/QTfrontend/binds.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/binds.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef BINDS_H @@ -22,9 +22,9 @@ #include #ifdef VIDEOREC -#define BINDS_NUMBER 46 +#define BINDS_NUMBER 47 #else -#define BINDS_NUMBER 45 +#define BINDS_NUMBER 46 #endif struct BindAction diff -r 31570b766315 -r ed5a6478e710 QTfrontend/campaign.cpp --- a/QTfrontend/campaign.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/campaign.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "campaign.h" @@ -26,14 +26,31 @@ QList getCampMissionList(QString & campaignName, QString & teamName) { QList missionInfoList; - QSettings teamfile(cfgdir->absolutePath() + "/Teams/" + teamName + ".hwt", QSettings::IniFormat, 0); + QSettings teamfile(cfgdir->absolutePath() + "/Teams/" + teamName + ".hwt", QSettings::IniFormat, 0); teamfile.setIniCodec("UTF-8"); + + // if entry not found check if there is written without _ + // if then is found rename it to use _ + QString spaceCampName = campaignName; + spaceCampName = spaceCampName.replace(QString("_"),QString(" ")); + if (!teamfile.childGroups().contains("Campaign " + campaignName) and + teamfile.childGroups().contains("Campaign " + spaceCampName)){ + teamfile.beginGroup("Campaign " + spaceCampName); + QStringList keys = teamfile.childKeys(); + teamfile.endGroup(); + for (int i=0;i=0 and unlockedMissions==0) { - for(unsigned int i=progress+1;i>0;i--) - { - MissionInfo missionInfo; - missionInfo.name = campfile.value(QString("Mission %1/Name").arg(i)).toString(); - QString script = campfile.value(QString("Mission %1/Script").arg(i)).toString(); + for(unsigned int i=progress+1;i>0;i--) + { + MissionInfo missionInfo; + missionInfo.name = campfile.value(QString("Mission %1/Name").arg(i)).toString(); + QString script = campfile.value(QString("Mission %1/Script").arg(i)).toString(); missionInfo.script = script; - missionInfo.description = m_info.value(campaignName+"-"+ script.replace(QString(".lua"),QString("")) + ".desc", + missionInfo.description = m_info.value(campaignName+"-"+ script.replace(QString(".lua"),QString("")) + ".desc", QObject::tr("No description available")).toString(); QString image = campfile.value(QString("Mission %1/Script").arg(i)).toString().replace(QString(".lua"),QString(".png")); missionInfo.image = ":/res/campaign/"+campaignName+"/"+image; if (!QFile::exists(missionInfo.image)) - missionInfo.image = ":/res/CampaignDefault.png"; - missionInfoList.append(missionInfo); - } - } - else if(unlockedMissions>0) - { - for(int i=1;i<=unlockedMissions;i++) - { - QString missionNum = QString("%1").arg(i); - int missionNumber = teamfile.value("Campaign " + campaignName + "/Mission"+missionNum, -1).toInt(); - MissionInfo missionInfo; - missionInfo.name = campfile.value(QString("Mission %1/Name").arg(missionNumber)).toString(); - QString script = campfile.value(QString("Mission %1/Script").arg(missionNumber)).toString(); + missionInfo.image = ":/res/CampaignDefault.png"; + missionInfoList.append(missionInfo); + } + } + else if(unlockedMissions>0) + { + for(int i=1;i<=unlockedMissions;i++) + { + QString missionNum = QString("%1").arg(i); + int missionNumber = teamfile.value("Campaign " + campaignName + "/Mission"+missionNum, -1).toInt(); + MissionInfo missionInfo; + missionInfo.name = campfile.value(QString("Mission %1/Name").arg(missionNumber)).toString(); + QString script = campfile.value(QString("Mission %1/Script").arg(missionNumber)).toString(); missionInfo.script = script; - missionInfo.description = m_info.value(campaignName+"-"+ script.replace(QString(".lua"),QString("")) + ".desc", + missionInfo.description = m_info.value(campaignName+"-"+ script.replace(QString(".lua"),QString("")) + ".desc", QObject::tr("No description available")).toString(); QString image = campfile.value(QString("Mission %1/Script").arg(missionNumber)).toString().replace(QString(".lua"),QString(".png")); missionInfo.image = ":/res/campaign/"+campaignName+"/"+image; if (!QFile::exists(missionInfo.image)) - missionInfo.image = ":/res/CampaignDefault.png"; - missionInfoList.append(missionInfo); - } - } - return missionInfoList; + missionInfo.image = ":/res/CampaignDefault.png"; + missionInfoList.append(missionInfo); + } + } + return missionInfoList; } diff -r 31570b766315 -r ed5a6478e710 QTfrontend/campaign.h --- a/QTfrontend/campaign.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/campaign.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef CAMPAIGN_H @@ -23,11 +23,11 @@ class MissionInfo { - public: - QString name; - QString description; - QString script; - QString image; + public: + QString name; + QString description; + QString script; + QString image; }; QList getCampMissionList(QString & campaignName, QString & teamName); diff -r 31570b766315 -r ed5a6478e710 QTfrontend/drawmapscene.cpp --- a/QTfrontend/drawmapscene.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/drawmapscene.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include @@ -304,6 +304,8 @@ void DrawMapScene::decode(QByteArray data) { + hideCursor(); + bool erasing = m_isErasing; oldItems.clear(); @@ -324,7 +326,7 @@ data.remove(0, 2); quint8 flags = *(quint8 *)data.data(); data.remove(0, 1); - qDebug() << px << py; + //qDebug() << px << py; if(flags & 0x80) { isSpecial = false; @@ -386,7 +388,7 @@ int i = 1; while(i < points.size()) { - if( (i != points.size() - 1) + if( ((i != points.size() - 1) || (prevPoint == points[i])) && (sqr(prevPoint.x() - points[i].x()) + sqr(prevPoint.y() - points[i].y()) < 1000) ) points.removeAt(i); @@ -459,7 +461,7 @@ l.append(center); } else { - qreal angleDelta = qMax(0.1, qMin(0.7, 120 / r)); + qreal angleDelta = qMax(static_cast (0.1), qMin(static_cast (0.7), 120 / r)); for(qreal angle = 0.0; angle < 2*M_PI; angle += angleDelta) l.append(center + QPointF(rx * cos(angle), ry * sin(angle))); l.append(l.first()); @@ -485,3 +487,51 @@ return point; } + +void DrawMapScene::optimize() +{ + if(!paths.size()) return; + + // break paths into segments + Paths pth; + + foreach(const PathParams & pp, paths) + { + int l = pp.points.size(); + + if(l == 1) + { + pth.prepend(pp); + } else + { + for(int i = l - 2; i >= 0; --i) + { + PathParams p = pp; + p.points = QList() << p.points[i] << p.points[i + 1]; + pth.prepend(pp); + } + } + } + + // clear the scene + oldItems.clear(); + oldPaths.clear(); + clear(); + paths.clear(); + m_specialPoints.clear(); + + // render the result + foreach(const PathParams & p, pth) + { + if(p.erasing) + m_pen.setBrush(m_eraser); + else + m_pen.setBrush(m_brush); + + m_pen.setWidth(deserializePenWidth(p.width)); + + addPath(pointsToPath(p.points), m_pen); + } + + emit pathChanged(); +} diff -r 31570b766315 -r ed5a6478e710 QTfrontend/drawmapscene.h --- a/QTfrontend/drawmapscene.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/drawmapscene.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef DRAWMAPSCENE_H @@ -58,6 +58,7 @@ void undo(); void clearMap(); void simplifyLast(); + void optimize(); void setErasing(bool erasing); void showCursor(); void hideCursor(); diff -r 31570b766315 -r ed5a6478e710 QTfrontend/game.cpp --- a/QTfrontend/game.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/game.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,9 +13,12 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include +#include + #include #include #include @@ -60,6 +63,9 @@ lastGameCfg = gamecfg; lastGameAmmo = ammo; lastGameTeamSel = pTeamSelWidget; + + gameState = gsNotStarted; + gameType = gtNone; } HWGame::~HWGame() @@ -142,6 +148,7 @@ HWProto::addStringToBuffer(teamscfg, "eseed " + QUuid::createUuid().toString()); HWProto::addStringToBuffer(teamscfg, "e$template_filter 2"); + HWProto::addStringToBuffer(teamscfg, "e$feature_size "+QString::number(rand()%18+4)); HWTeam team1; team1.setDifficulty(0); @@ -245,9 +252,27 @@ case 'E': { int size = msg.size(); - emit ErrorMessage(QString("Last two engine messages:\n") + QString().append(msg.mid(2)).left(size - 4)); + emit ErrorMessage( + tr("A Fatal ERROR occured! - The game engine had to stop.\n\n" + "We are very sorry for the inconvenience :(\n\n" + "If this keeps happening, please click the '%1' button in the main menu!\n\n" + "Last two engine messages:\n%2") + .arg("Feedback") + .arg(QString::fromUtf8(msg.mid(2).left(size - 4)))); return; } + case 'y': + { + // copy string to clipboard + QApplication::clipboard()->setText(QString::fromUtf8(msg.mid(2))); + break; + } + case 'Y': + { + // paste clipboard to game + SendIPC(QString("Y").toAscii() + QApplication::clipboard()->text().toUtf8().left(250).replace('\n', ' ')); + break; + } case 'i': { emit GameStats(msg.at(2), QString::fromUtf8(msg.mid(3))); @@ -303,6 +328,13 @@ config->Form->ui.pageOptions->windowHeightEdit->setValue(wh[1].toInt()); break; } + case '~': + { + int size = msg.size(); + QString msgbody = QString::fromUtf8(msg.mid(2).left(size - 4)); + emit SendConsoleCommand(msgbody); + break; + } default: { if (gameType == gtNet && !netSuspend) diff -r 31570b766315 -r ed5a6478e710 QTfrontend/game.h --- a/QTfrontend/game.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/game.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef GAME_H @@ -99,6 +99,7 @@ void HaveRecord(RecordType type, const QByteArray & record); void ErrorMessage(const QString &); void CampStateChanged(int); + void SendConsoleCommand(const QString & command); public slots: void FromNet(const QByteArray & msg); diff -r 31570b766315 -r ed5a6478e710 QTfrontend/gameuiconfig.cpp --- a/QTfrontend/gameuiconfig.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/gameuiconfig.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff -r 31570b766315 -r ed5a6478e710 QTfrontend/gameuiconfig.h --- a/QTfrontend/gameuiconfig.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/gameuiconfig.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef GAMECONFIG_H diff -r 31570b766315 -r ed5a6478e710 QTfrontend/hedgewars.qrc --- a/QTfrontend/hedgewars.qrc Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/hedgewars.qrc Tue Nov 10 20:43:13 2015 +0100 @@ -124,7 +124,11 @@ res/iconHealth.png res/iconSuddenDeath.png res/iconDamage.png + res/iconDamageLockG.png + res/iconDamageLockR.png res/iconTime.png + res/iconTimeLockG.png + res/iconTimeLockR.png res/iconMine.png res/iconDud.png res/iconRope.png @@ -179,7 +183,6 @@ res/chat/ingame.png res/splash.png res/html/about.html - res/xml/tips.xml res/chat/hedgehogcontributor.png res/chat/hedgehogcontributor_gray.png res/chat/roomadmincontributor.png diff -r 31570b766315 -r ed5a6478e710 QTfrontend/hwconsts.cpp.in --- a/QTfrontend/hwconsts.cpp.in Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/hwconsts.cpp.in Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include @@ -37,7 +37,7 @@ bool custom_data = false; int cMaxTeams = 8; -int cMinServerVersion = 1; +int cMinServerVersion = 3; QString * cDefaultAmmoStore = new QString( AMMOLINE_DEFAULT_QT AMMOLINE_DEFAULT_PROB AMMOLINE_DEFAULT_DELAY AMMOLINE_DEFAULT_CRATE ); @@ -67,6 +67,15 @@ << qMakePair(QString("One of Everything"), QString( AMMOLINE_ONEEVERY_QT AMMOLINE_ONEEVERY_PROB AMMOLINE_ONEEVERY_DELAY AMMOLINE_ONEEVERY_CRATE )) + << qMakePair(QString("Highlander"), QString( + AMMOLINE_HIGHLANDER_QT AMMOLINE_HIGHLANDER_PROB + AMMOLINE_HIGHLANDER_DELAY AMMOLINE_HIGHLANDER_CRATE )) + << qMakePair(QString("Construction Mode"), QString( + AMMOLINE_CONSTRUCTION_QT AMMOLINE_CONSTRUCTION_PROB + AMMOLINE_CONSTRUCTION_DELAY AMMOLINE_CONSTRUCTION_CRATE )) + << qMakePair(QString("Shoppa Pro"), QString( + AMMOLINE_SHOPPAPRO_QT AMMOLINE_SHOPPAPRO_PROB + AMMOLINE_SHOPPAPRO_DELAY AMMOLINE_SHOPPAPRO_CRATE )) ; unsigned int colors[] = HW_TEAMCOLOR_ARRAY; diff -r 31570b766315 -r ed5a6478e710 QTfrontend/hwconsts.h --- a/QTfrontend/hwconsts.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/hwconsts.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined(TARGET_OS_IPHONE) diff -r 31570b766315 -r ed5a6478e710 QTfrontend/hwform.cpp --- a/QTfrontend/hwform.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/hwform.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include @@ -164,14 +164,12 @@ ui.pageVideos->init(config); #endif -#ifdef __APPLE__ +#if defined(__APPLE__) && defined(SPARKLE_ENABLED) if (config->isAutoUpdateEnabled()) { AutoUpdater* updater = NULL; -#ifdef SPARKLE_ENABLED updater = new SparkleAutoUpdater(); -#endif if (updater) { updater->checkForUpdates(); @@ -1675,7 +1673,7 @@ connect(game, SIGNAL(CampStateChanged(int)), this, SLOT(UpdateCampaignPageProgress(int))); connect(game, SIGNAL(GameStateChanged(GameState)), this, SLOT(GameStateChanged(GameState))); connect(game, SIGNAL(GameStats(char, const QString &)), ui.pageGameStats, SLOT(GameStats(char, const QString &))); - connect(game, SIGNAL(ErrorMessage(const QString &)), this, SLOT(ShowErrorMessage(const QString &)), Qt::QueuedConnection); + connect(game, SIGNAL(ErrorMessage(const QString &)), this, SLOT(ShowFatalErrorMessage(const QString &)), Qt::QueuedConnection); connect(game, SIGNAL(HaveRecord(RecordType, const QByteArray &)), this, SLOT(GetRecord(RecordType, const QByteArray &))); m_lastDemo = QByteArray(); } @@ -1753,6 +1751,7 @@ connect(game, SIGNAL(SendNet(const QByteArray &)), hwnet, SLOT(SendNet(const QByteArray &))); connect(game, SIGNAL(SendChat(const QString &)), hwnet, SLOT(chatLineToNet(const QString &))); + connect(game, SIGNAL(SendConsoleCommand(const QString&)), hwnet, SLOT(consoleCommand(const QString&))); connect(game, SIGNAL(SendTeamMessage(const QString &)), hwnet, SLOT(SendTeamMessage(const QString &))); connect(hwnet, SIGNAL(chatStringFromNet(const QString &)), game, SLOT(FromNetChat(const QString &)), Qt::QueuedConnection); @@ -1831,14 +1830,14 @@ if (hwnet) { NetAmmoSchemeModel * netAmmo = new NetAmmoSchemeModel(hwnet); - connect(hwnet, SIGNAL(netSchemeConfig(QStringList &)), netAmmo, SLOT(setNetSchemeConfig(QStringList &))); + connect(hwnet, SIGNAL(netSchemeConfig(QStringList)), netAmmo, SLOT(setNetSchemeConfig(QStringList))); ui.pageNetGame->pGameCFG->GameSchemes->setModel(netAmmo); ui.pageNetGame->setRoomName(hwnet->getRoom()); ui.pageNetGame->pGameCFG->GameSchemes->view()->disconnect(hwnet); - connect(hwnet, SIGNAL(netSchemeConfig(QStringList &)), + connect(hwnet, SIGNAL(netSchemeConfig(QStringList)), this, SLOT(selectFirstNetScheme())); } @@ -1903,15 +1902,15 @@ Q_UNUSED(index); HWTeam team(ui.pageCampaign->CBTeam->currentText()); QString campaignName = ui.pageCampaign->CBCampaign->currentText().replace(QString(" "),QString("_")); - QString tName = team.name(); - - campaignMissionInfo = getCampMissionList(campaignName,tName); - ui.pageCampaign->CBMission->clear(); - + QString tName = team.name(); + + campaignMissionInfo = getCampMissionList(campaignName,tName); + ui.pageCampaign->CBMission->clear(); + for(int i=0;iCBMission->addItem(QString(campaignMissionInfo[i].name), QString(campaignMissionInfo[i].name)); - } + } } void HWForm::UpdateCampaignPageMission(int index) @@ -1923,7 +1922,7 @@ if(index > -1 && index < campaignMissionInfo.count()) { ui.pageCampaign->lbltitle->setText("

"+ui.pageCampaign->CBMission->currentText()+"

"); ui.pageCampaign->lbldescription->setText(campaignMissionInfo[index].description); - ui.pageCampaign->btnPreview->setIcon(QIcon(campaignMissionInfo[index].image)); + ui.pageCampaign->btnPreview->setIcon(QIcon(campaignMissionInfo[index].image)); } } @@ -1935,12 +1934,12 @@ UpdateCampaignPage(0); for(int i=0;iCBMission->count();i++) { - if (ui.pageCampaign->CBMission->itemText(i)==missionTitle) - { - ui.pageCampaign->CBMission->setCurrentIndex(i); - break; - } - } + if (ui.pageCampaign->CBMission->itemText(i)==missionTitle) + { + ui.pageCampaign->CBMission->setCurrentIndex(i); + break; + } + } } // used for --set-everything [screen width] [screen height] [color dept] [volume] [enable music] [enable sounds] [language file] [full screen] [show FPS] [alternate damage] [timer value] [reduced quality] @@ -2094,9 +2093,9 @@ } } -void HWForm::ShowErrorMessage(const QString & msg) +void HWForm::ShowFatalErrorMessage(const QString & msg) { - MessageDialog::ShowErrorMessage(msg, this); + MessageDialog::ShowFatalMessage(msg, this); } void HWForm::showFeedbackDialog() diff -r 31570b766315 -r ed5a6478e710 QTfrontend/hwform.h --- a/QTfrontend/hwform.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/hwform.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef HWFORM_H @@ -120,7 +120,7 @@ void StartMPGame(); void GameStateChanged(GameState gameState); void ForcedDisconnect(const QString & reason); - void ShowErrorMessage(const QString &); + void ShowFatalErrorMessage(const QString &); void GetRecord(RecordType type, const QByteArray & record); void CreateNetGame(); void UpdateWeapons(); @@ -196,7 +196,7 @@ AmmoSchemeModel * ammoSchemeModel; QStack PagesStack; QString previousCampaignName; - QString previousTeamName; + QString previousTeamName; QList campaignMissionInfo; QTime eggTimer; BGWidget * wBackground; diff -r 31570b766315 -r ed5a6478e710 QTfrontend/main.cpp --- a/QTfrontend/main.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/main.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "HWApplication.h" @@ -125,6 +125,28 @@ } } +QString getUsage() +{ + return QString( +"%1: hedgewars [%2...] [%3]\n" +"\n" +"%4:\n" +" --help %5\n" +" --config-dir=PATH %6\n" +" --data-dir=PATH %7\n" +"\n" +"%8" +"\n" +).arg(HWApplication::tr("Usage", "command-line")) +.arg(HWApplication::tr("OPTION", "command-line")) +.arg(HWApplication::tr("CONNECTSTRING", "command-line")) +.arg(HWApplication::tr("Options", "command-line")) +.arg(HWApplication::tr("Display this help", "command-line")) +.arg(HWApplication::tr("Custom path for configuration data and user data", "command-line")) +.arg(HWApplication::tr("Custom path to the game data folder", "command-line")) +.arg(HWApplication::tr("Hedgewars can use a %1 (e.g. \"%2\") to connect on start.", "command-line").arg(HWApplication::tr("CONNECTSTRING", "command-line")).arg(QString("hwplay://") + NETGAME_DEFAULT_SERVER)); +} + int main(int argc, char *argv[]) { // Since we're calling this first, closeResources() will be the last thing called after main() returns. @@ -137,8 +159,87 @@ SDLInteraction::instance(); HWApplication app(argc, argv); + app.setAttribute(Qt::AA_DontShowIconsInMenus,false); + // file engine and splash. to be initialized later + engine = NULL; QLabel *splash = NULL; + + // parse arguments + + QStringList arguments = app.arguments(); + QMap parsedArgs; + { + QList::iterator i = arguments.begin(); + while(i != arguments.end()) + { + QString arg = *i; + + + QRegExp opt("--(\\S+)=(.+)"); + if(opt.exactMatch(arg)) + { + parsedArgs[opt.cap(1)] = opt.cap(2); + i = arguments.erase(i); + } + else + { + if(arg.startsWith("--")) { + if(arg == "--help") + { + printf("%s", getUsage().toUtf8().constData()); + return 0; + } + // argument is something wrong + fprintf(stderr, "%s\n\n%s", + HWApplication::tr("Malformed option argument: %1", "command-line").arg(arg).toUtf8().constData(), + getUsage().toUtf8().constData()); + return 1; + } + + // if not starting with --, then always skip + // (because we can't determine if executable path/call or not - on windows) + ++i; + } + } + } + + if(parsedArgs.contains("data-dir")) + { + QFileInfo f(parsedArgs["data-dir"]); + parsedArgs.remove("data-dir"); + if(!f.exists()) + { + qWarning() << "WARNING: Cannot open DATA_PATH=" << f.absoluteFilePath(); + } + *cDataDir = f.absoluteFilePath(); + custom_data = true; + } + + if(parsedArgs.contains("config-dir")) + { + QFileInfo f(parsedArgs["config-dir"]); + parsedArgs.remove("config-dir"); + cfgdir->setPath(f.absoluteFilePath()); + custom_config = true; + } + else + { + cfgdir->setPath(QDir::homePath()); + custom_config = false; + } + + if (!parsedArgs.isEmpty()) { + foreach (const QString & key, parsedArgs.keys()) + { + fprintf(stderr, "%s\n", HWApplication::tr("Unknown option argument: %1", "command-line").arg(QString("--") + key).toUtf8().constData()); + } + fprintf(stderr, "\n%s", getUsage().toUtf8().constData()); + return 1; + } + + // end of parameter parsing + #if defined Q_OS_WIN QPixmap pixmap(":res/splash.png"); splash = new QLabel(0, Qt::FramelessWindowHint|Qt::WindowStaysOnTopHint); @@ -150,55 +251,6 @@ splash->setPixmap(pixmap); splash->show(); #endif - - engine = new FileEngineHandler(argv[0]); - - app.setAttribute(Qt::AA_DontShowIconsInMenus,false); - - QStringList arguments = app.arguments(); - QMap parsedArgs; - { - QList::iterator i = arguments.begin(); - while(i != arguments.end()) - { - QString arg = *i; - - QRegExp opt("--(\\S+)=(.+)"); - if(opt.exactMatch(arg)) - { - parsedArgs[opt.cap(1)] = opt.cap(2); - i = arguments.erase(i); - } - else - { - ++i; - } - } - } - - if(parsedArgs.contains("data-dir")) - { - QFileInfo f(parsedArgs["data-dir"]); - if(!f.exists()) - { - qWarning() << "WARNING: Cannot open DATA_PATH=" << f.absoluteFilePath(); - } - *cDataDir = f.absoluteFilePath(); - custom_data = true; - } - - if(parsedArgs.contains("config-dir")) - { - QFileInfo f(parsedArgs["config-dir"]); - cfgdir->setPath(f.absoluteFilePath()); - custom_config = true; - } - else - { - cfgdir->setPath(QDir::homePath()); - custom_config = false; - } - app.setStyle(new QPlastiqueStyle()); QDateTime now = QDateTime::currentDateTime(); @@ -259,6 +311,7 @@ } // setup PhysFS + engine = new FileEngineHandler(argv[0]); engine->mount(datadir->absolutePath()); engine->mount(cfgdir->absolutePath() + "/Data"); engine->mount(cfgdir->absolutePath()); @@ -284,6 +337,7 @@ if (!Translator.load(QString("physfs://Locale/hedgewars_%1").arg(cc))) qWarning("Failed to install translation (%s)", qPrintable(cc)); app.installTranslator(&Translator); + app.setLayoutDirection(QLocale(cc).textDirection()); } #ifdef _WIN32 diff -r 31570b766315 -r ed5a6478e710 QTfrontend/model/GameStyleModel.cpp --- a/QTfrontend/model/GameStyleModel.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/model/GameStyleModel.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /** diff -r 31570b766315 -r ed5a6478e710 QTfrontend/model/GameStyleModel.h --- a/QTfrontend/model/GameStyleModel.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/model/GameStyleModel.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /** diff -r 31570b766315 -r ed5a6478e710 QTfrontend/model/HatModel.cpp --- a/QTfrontend/model/HatModel.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/model/HatModel.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /** diff -r 31570b766315 -r ed5a6478e710 QTfrontend/model/HatModel.h --- a/QTfrontend/model/HatModel.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/model/HatModel.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /** diff -r 31570b766315 -r ed5a6478e710 QTfrontend/model/MapModel.cpp --- a/QTfrontend/model/MapModel.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/model/MapModel.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /** @@ -30,6 +30,7 @@ MapModel::MapInfo MapModel::MapInfoRandom = {MapModel::GeneratedMap, "+rnd+", "", 0, "", "", "", false}; MapModel::MapInfo MapModel::MapInfoMaze = {MapModel::GeneratedMaze, "+maze+", "", 0, "", "", "", false}; +MapModel::MapInfo MapModel::MapInfoPerlin = {MapModel::GeneratedMaze, "+perlin+", "", 0, "", "", "", false}; MapModel::MapInfo MapModel::MapInfoDrawn = {MapModel::HandDrawnMap, "+drawn+", "", 0, "", "", "", false}; diff -r 31570b766315 -r ed5a6478e710 QTfrontend/model/MapModel.h --- a/QTfrontend/model/MapModel.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/model/MapModel.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /** @@ -49,6 +49,7 @@ Invalid, GeneratedMap, GeneratedMaze, + GeneratedPerlin, HandDrawnMap, MissionMap, StaticMap @@ -98,7 +99,7 @@ QStandardItem * getMap(const QString & map); // Static MapInfos for drawn and generated maps - static MapInfo MapInfoRandom, MapInfoMaze, MapInfoDrawn; + static MapInfo MapInfoRandom, MapInfoMaze, MapInfoPerlin, MapInfoDrawn; /// Loads the maps bool loadMaps(); diff -r 31570b766315 -r ed5a6478e710 QTfrontend/model/ThemeModel.cpp --- a/QTfrontend/model/ThemeModel.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/model/ThemeModel.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /** @@ -62,7 +62,7 @@ void ThemeModel::loadThemes() const { - qDebug("[LAZINESS ThemeModel::loadThemes()]"); + qDebug("[LAZINESS] ThemeModel::loadThemes()"); m_themesLoaded = true; diff -r 31570b766315 -r ed5a6478e710 QTfrontend/model/ThemeModel.h --- a/QTfrontend/model/ThemeModel.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/model/ThemeModel.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /** diff -r 31570b766315 -r ed5a6478e710 QTfrontend/model/ammoSchemeModel.cpp --- a/QTfrontend/model/ammoSchemeModel.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/model/ammoSchemeModel.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include @@ -58,13 +58,15 @@ << QVariant(4) // mines number 32 << QVariant(0) // mine dud pct 33 << QVariant(2) // explosives 34 - << QVariant(35) // health case pct 35 - << QVariant(25) // health case amt 36 - << QVariant(47) // water rise amt 37 - << QVariant(5) // health dec amt 38 - << QVariant(100) // rope modfier 39 - << QVariant(100) // get away time 40 - << QVariant(0) // world edge 41 + << QVariant(0) // air mines 35 + << QVariant(35) // health case pct 36 + << QVariant(25) // health case amt 37 + << QVariant(47) // water rise amt 38 + << QVariant(5) // health dec amt 39 + << QVariant(100) // rope modfier 40 + << QVariant(100) // get away time 41 + << QVariant(0) // world edge 42 + << QVariant() // scriptparam 43 ; AmmoSchemeModel::AmmoSchemeModel(QObject* parent, const QString & fileName) : @@ -83,6 +85,7 @@ << "Timeless" << "Thinking with Portals" << "King Mode" + << "Construction Mode" ; numberOfDefaultSchemes = predefSchemesNames.size(); @@ -123,13 +126,15 @@ << "minesnum" // 32 << "minedudpct" // 33 << "explosives" // 34 - << "healthprobability" // 35 - << "healthcaseamount" // 36 - << "waterrise" // 37 - << "healthdecrease" // 38 - << "ropepct" // 39 - << "getawaytime" // 40 - << "worldedge" // 41 + << "airmines" // 35 + << "healthprobability" // 36 + << "healthcaseamount" // 37 + << "waterrise" // 38 + << "healthdecrease" // 39 + << "ropepct" // 40 + << "getawaytime" // 41 + << "worldedge" // 42 + << "scriptparam" // scriptparam 43 ; QList proMode; @@ -169,13 +174,15 @@ << QVariant(0) // mines number 32 << QVariant(0) // mine dud pct 33 << QVariant(2) // explosives 34 - << QVariant(35) // health case pct 35 - << QVariant(25) // health case amt 36 - << QVariant(47) // water rise amt 37 - << QVariant(5) // health dec amt 38 - << QVariant(100) // rope modfier 39 - << QVariant(100) // get away time 40 - << QVariant(0) // world edge 41 + << QVariant(0) // air mines 35 + << QVariant(35) // health case pct 36 + << QVariant(25) // health case amt 37 + << QVariant(47) // water rise amt 38 + << QVariant(5) // health dec amt 39 + << QVariant(100) // rope modfier 40 + << QVariant(100) // get away time 41 + << QVariant(0) // world edge 42 + << QVariant() // scriptparam 43 ; QList shoppa; @@ -211,17 +218,19 @@ << QVariant(100) // init health 28 << QVariant(50) // sudden death 29 << QVariant(1) // case prob 30 - << QVariant(3) // mines time 31 + << QVariant(0) // mines time 31 << QVariant(0) // mines number 32 << QVariant(0) // mine dud pct 33 << QVariant(0) // explosives 34 - << QVariant(0) // health case pct 35 - << QVariant(25) // health case amt 36 - << QVariant(47) // water rise amt 37 - << QVariant(5) // health dec amt 38 - << QVariant(100) // rope modfier 39 - << QVariant(100) // get away time 40 - << QVariant(0) // world edge 41 + << QVariant(8) // air mines 35 + << QVariant(0) // health case pct 36 + << QVariant(25) // health case amt 37 + << QVariant(47) // water rise amt 38 + << QVariant(5) // health dec amt 39 + << QVariant(100) // rope modfier 40 + << QVariant(100) // get away time 41 + << QVariant(0) // world edge 42 + << QVariant() // scriptparam 43 ; QList cleanslate; @@ -261,13 +270,15 @@ << QVariant(4) // mines number 32 << QVariant(0) // mine dud pct 33 << QVariant(2) // explosives 34 - << QVariant(35) // health case pct 35 - << QVariant(25) // health case amt 36 - << QVariant(47) // water rise amt 37 - << QVariant(5) // health dec amt 38 - << QVariant(100) // rope modfier 39 - << QVariant(100) // get away time 40 - << QVariant(0) // world edge 41 + << QVariant(0) // air mines 35 + << QVariant(35) // health case pct 36 + << QVariant(25) // health case amt 37 + << QVariant(47) // water rise amt 38 + << QVariant(5) // health dec amt 39 + << QVariant(100) // rope modfier 40 + << QVariant(100) // get away time 41 + << QVariant(0) // world edge 42 + << QVariant() // scriptparam 43 ; QList minefield; @@ -304,16 +315,18 @@ << QVariant(15) // sudden death 29 << QVariant(0) // case prob 30 << QVariant(0) // mines time 31 - << QVariant(80) // mines number 32 + << QVariant(200) // mines number 32 << QVariant(0) // mine dud pct 33 << QVariant(0) // explosives 34 - << QVariant(35) // health case pct 35 - << QVariant(25) // health case amt 36 - << QVariant(47) // water rise amt 37 - << QVariant(5) // health dec amt 38 - << QVariant(100) // rope modfier 39 - << QVariant(100) // get away time 40 - << QVariant(0) // world edge 41 + << QVariant(0) // air mines 35 + << QVariant(35) // health case pct 36 + << QVariant(25) // health case amt 37 + << QVariant(47) // water rise amt 38 + << QVariant(5) // health dec amt 39 + << QVariant(100) // rope modfier 40 + << QVariant(100) // get away time 41 + << QVariant(0) // world edge 42 + << QVariant() // scriptparam 43 ; QList barrelmayhem; @@ -352,14 +365,16 @@ << QVariant(0) // mines time 31 << QVariant(0) // mines number 32 << QVariant(0) // mine dud pct 33 - << QVariant(80) // explosives 34 - << QVariant(35) // health case pct 35 - << QVariant(25) // health case amt 36 - << QVariant(47) // water rise amt 37 - << QVariant(5) // health dec amt 38 - << QVariant(100) // rope modfier 39 - << QVariant(100) // get away time 40 - << QVariant(0) // world edge 41 + << QVariant(200) // explosives 34 + << QVariant(0) // air mines 35 + << QVariant(35) // health case pct 36 + << QVariant(25) // health case amt 37 + << QVariant(47) // water rise amt 38 + << QVariant(5) // health dec amt 39 + << QVariant(100) // rope modfier 40 + << QVariant(100) // get away time 41 + << QVariant(0) // world edge 42 + << QVariant() // scriptparam 43 ; QList tunnelhogs; @@ -399,13 +414,15 @@ << QVariant(10) // mines number 32 << QVariant(10) // mine dud pct 33 << QVariant(10) // explosives 34 - << QVariant(35) // health case pct 35 - << QVariant(25) // health case amt 36 - << QVariant(47) // water rise amt 37 - << QVariant(5) // health dec amt 38 - << QVariant(100) // rope modfier 39 - << QVariant(100) // get away time 40 - << QVariant(0) // world edge 41 + << QVariant(4) // air mines 35 + << QVariant(35) // health case pct 36 + << QVariant(25) // health case amt 37 + << QVariant(47) // water rise amt 38 + << QVariant(5) // health dec amt 39 + << QVariant(100) // rope modfier 40 + << QVariant(100) // get away time 41 + << QVariant(0) // world edge 42 + << QVariant() // scriptparam 43 ; QList forts; @@ -445,13 +462,15 @@ << QVariant(0) // mines number 32 << QVariant(0) // mine dud pct 33 << QVariant(0) // explosives 34 - << QVariant(35) // health case pct 35 - << QVariant(25) // health case amt 36 - << QVariant(47) // water rise amt 37 - << QVariant(5) // health dec amt 38 - << QVariant(100) // rope modfier 39 - << QVariant(100) // get away time 40 - << QVariant(0) // world edge 41 + << QVariant(0) // air mines 35 + << QVariant(35) // health case pct 36 + << QVariant(25) // health case amt 37 + << QVariant(47) // water rise amt 38 + << QVariant(5) // health dec amt 39 + << QVariant(100) // rope modfier 40 + << QVariant(100) // get away time 41 + << QVariant(0) // world edge 42 + << QVariant() // scriptparam 43 ; QList timeless; @@ -491,13 +510,15 @@ << QVariant(5) // mines number 32 << QVariant(10) // mine dud pct 33 << QVariant(2) // explosives 34 - << QVariant(35) // health case pct 35 - << QVariant(30) // health case amt 36 - << QVariant(0) // water rise amt 37 - << QVariant(0) // health dec amt 38 - << QVariant(100) // rope modfier 39 - << QVariant(100) // get away time 40 - << QVariant(0) // world edge 41 + << QVariant(0) // air mines 35 + << QVariant(35) // health case pct 36 + << QVariant(30) // health case amt 37 + << QVariant(0) // water rise amt 38 + << QVariant(0) // health dec amt 39 + << QVariant(100) // rope modfier 40 + << QVariant(100) // get away time 41 + << QVariant(0) // world edge 42 + << QVariant() // scriptparam 43 ; QList thinkingportals; @@ -537,13 +558,15 @@ << QVariant(5) // mines number 32 << QVariant(0) // mine dud pct 33 << QVariant(5) // explosives 34 - << QVariant(25) // health case pct 35 - << QVariant(25) // health case amt 36 - << QVariant(47) // water rise amt 37 - << QVariant(5) // health dec amt 38 - << QVariant(100) // rope modfier 39 - << QVariant(100) // get away time 40 - << QVariant(0) // world edge 41 + << QVariant(4) // air mines 35 + << QVariant(25) // health case pct 36 + << QVariant(25) // health case amt 37 + << QVariant(47) // water rise amt 38 + << QVariant(5) // health dec amt 39 + << QVariant(100) // rope modfier 40 + << QVariant(100) // get away time 41 + << QVariant(0) // world edge 42 + << QVariant() // scriptparam 43 ; QList kingmode; @@ -583,16 +606,65 @@ << QVariant(4) // mines number 32 << QVariant(0) // mine dud pct 33 << QVariant(2) // explosives 34 - << QVariant(35) // health case pct 35 - << QVariant(25) // health case amt 36 - << QVariant(47) // water rise amt 37 - << QVariant(5) // health dec amt 38 - << QVariant(100) // rope modfier 39 - << QVariant(100) // get away time 40 - << QVariant(0) // world edge 41 + << QVariant(0) // air mines 35 + << QVariant(35) // health case pct 36 + << QVariant(25) // health case amt 37 + << QVariant(47) // water rise amt 38 + << QVariant(5) // health dec amt 39 + << QVariant(100) // rope modfier 40 + << QVariant(100) // get away time 41 + << QVariant(0) // world edge 42 + << QVariant() // scriptparam 43 ; - + QList construction; + construction + << predefSchemesNames[11] // name 0 + << QVariant(false) // fortsmode 1 + << QVariant(false) // team divide 2 + << QVariant(false) // solid land 3 + << QVariant(false) // border 4 + << QVariant(false) // low gravity 5 + << QVariant(false) // laser sight 6 + << QVariant(false) // invulnerable 7 + << QVariant(false) // reset health 8 + << QVariant(false) // vampiric 9 + << QVariant(false) // karma 10 + << QVariant(false) // artillery 11 + << QVariant(true) // random order 12 + << QVariant(false) // king 13 + << QVariant(false) // place hog 14 + << QVariant(false) // shared ammo 15 + << QVariant(true) // disable girders 16 + << QVariant(true) // disable land objects 17 + << QVariant(false) // AI survival 18 + << QVariant(true) // inf. attack 19 + << QVariant(false) // reset weps 20 + << QVariant(true) // per hog ammo 21 + << QVariant(false) // no wind 22 + << QVariant(false) // more wind 23 + << QVariant(false) // tag team 24 + << QVariant(false) // bottom border 25 + << QVariant(100) // damage modfier 26 + << QVariant(45) // turn time 27 + << QVariant(100) // init health 28 + << QVariant(15) // sudden death 29 + << QVariant(5) // case prob 30 + << QVariant(3) // mines time 31 + << QVariant(0) // mines number 32 + << QVariant(0) // mine dud pct 33 + << QVariant(0) // explosives 34 + << QVariant(0) // air mines 35 + << QVariant(35) // health case pct 36 + << QVariant(25) // health case amt 37 + << QVariant(47) // water rise amt 38 + << QVariant(5) // health dec amt 39 + << QVariant(100) // rope modfier 40 + << QVariant(100) // get away time 41 + << QVariant(0) // world edge 42 + << QVariant() // scriptparam 43 + ; + schemes.append(defaultScheme); schemes.append(proMode); schemes.append(shoppa); @@ -604,6 +676,7 @@ schemes.append(timeless); schemes.append(thinkingportals); schemes.append(kingmode); + schemes.append(construction); int size = fileConfig.beginReadArray("schemes"); @@ -688,7 +761,7 @@ else { QList newScheme = schemes[row]; - newScheme[0] = QVariant(tr("copy of") + " " + newScheme[0].toString()); + newScheme[0] = QVariant(tr("copy of %1").arg(newScheme[0].toString())); schemes.insert(schemes.size(), newScheme); } @@ -785,7 +858,7 @@ return netScheme[index.column()]; } -void NetAmmoSchemeModel::setNetSchemeConfig(QStringList & cfg) +void NetAmmoSchemeModel::setNetSchemeConfig(QStringList cfg) { if(cfg.size() != netScheme.size()) { @@ -793,6 +866,8 @@ return; } + cfg[cfg.size()-1] = cfg[cfg.size()-1].mid(1); + for(int i = 0; i < cfg.size(); ++i) netScheme[i] = QVariant(cfg[i]); diff -r 31570b766315 -r ed5a6478e710 QTfrontend/model/ammoSchemeModel.h --- a/QTfrontend/model/ammoSchemeModel.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/model/ammoSchemeModel.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _AMMO_SCHEME_MODEL_INCLUDED @@ -70,7 +70,7 @@ QVariant data(const QModelIndex &index, int role) const; public slots: - void setNetSchemeConfig(QStringList & cfg); + void setNetSchemeConfig(QStringList cfg); private: QList netScheme; diff -r 31570b766315 -r ed5a6478e710 QTfrontend/model/netserverslist.cpp --- a/QTfrontend/model/netserverslist.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/model/netserverslist.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff -r 31570b766315 -r ed5a6478e710 QTfrontend/model/netserverslist.h --- a/QTfrontend/model/netserverslist.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/model/netserverslist.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _NET_SERVERSLIST_INCLUDED diff -r 31570b766315 -r ed5a6478e710 QTfrontend/model/playerslistmodel.cpp --- a/QTfrontend/model/playerslistmodel.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/model/playerslistmodel.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -237,6 +237,7 @@ << index.data(InGame).toBool() << index.data(RoomFilterRole).toBool() << index.data(InRoom).toBool() + << index.data(Contributor).toBool() ; for(int i = flags.size() - 1; i >= 0; --i) diff -r 31570b766315 -r ed5a6478e710 QTfrontend/model/playerslistmodel.h --- a/QTfrontend/model/playerslistmodel.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/model/playerslistmodel.h Tue Nov 10 20:43:13 2015 +0100 @@ -23,6 +23,8 @@ InGame = Qt::UserRole + 6, InRoom = Qt::UserRole + 7, Contributor = Qt::UserRole + 8 + // if you add a role that will affect the player icon, + // then also add it to the flags Qlist in updateIcon()! }; enum SpecialRoles { diff -r 31570b766315 -r ed5a6478e710 QTfrontend/model/roomslistmodel.cpp --- a/QTfrontend/model/roomslistmodel.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/model/roomslistmodel.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /** @@ -108,22 +108,38 @@ if (role == Qt::DecorationRole) { const QIcon roomBusyIcon(":/res/iconDamage.png"); + const QIcon roomBusyIconGreen(":/res/iconDamageLockG.png"); + const QIcon roomBusyIconRed(":/res/iconDamageLockR.png"); const QIcon roomWaitingIcon(":/res/iconTime.png"); + const QIcon roomWaitingIconGreen(":/res/iconTimeLockG.png"); + const QIcon roomWaitingIconRed(":/res/iconTimeLockR.png"); + + QString flags = m_data.at(row).at(StateColumn); - if (m_data.at(row).at(0).isEmpty()) - return QVariant(roomWaitingIcon); + if (flags.contains("g")) + { + if (flags.contains("j")) + return QVariant(roomBusyIconRed); + else if (flags.contains("p")) + return QVariant(roomBusyIconGreen); + else + return QVariant(roomBusyIcon); + } else - return QVariant(roomBusyIcon); + { + if (flags.contains("j")) + return QVariant(roomWaitingIconRed); + else if (flags.contains("p")) + return QVariant(roomWaitingIconGreen); + else + return QVariant(roomWaitingIcon); + } } QString content = m_data.at(row).at(column); if (role == Qt::DisplayRole) { - // supply in progress flag as bool - if (column == 0) - return QVariant(QString(!content.isEmpty())); - // display room names if (column == 5) { @@ -132,6 +148,7 @@ { if (content == "+rnd+") return tr("Random Map"); if (content == "+maze+") return tr("Random Maze"); + if (content == "+perlin+") return tr("Random Perlin"); if (content == "+drawn+") return tr("Hand-drawn"); } @@ -149,6 +166,7 @@ { if (content == "+rnd+" || content == "+maze+" || + content == "+perlin+" || content == "+drawn+" || m_staticMapModel->mapExists(content) || m_missionMapModel->mapExists(content)) @@ -188,7 +206,7 @@ l.append(rooms[i + t]); } - m_data.append(roomInfo2RoomRecord(l)); + m_data.append(l); } endResetModel(); @@ -199,7 +217,7 @@ { beginInsertRows(QModelIndex(), 0, 0); - m_data.prepend(roomInfo2RoomRecord(info)); + m_data.prepend(info); endInsertRows(); } @@ -248,24 +266,7 @@ if (i < 0) return; - m_data[i] = roomInfo2RoomRecord(info); + m_data[i] = info; emit dataChanged(index(i, 0), index(i, columnCount(QModelIndex()) - 1)); } - - -QStringList RoomsListModel::roomInfo2RoomRecord(const QStringList & info) -{ - QStringList result; - - result = info; - - // for matters of less memory usage and quicker access store - // the boolean string as either "t" or empty - if (info[StateColumn].toLower() == "true") - result[StateColumn] = "t"; - else - result[StateColumn] = QString(); - - return result; -} diff -r 31570b766315 -r ed5a6478e710 QTfrontend/model/roomslistmodel.h --- a/QTfrontend/model/roomslistmodel.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/model/roomslistmodel.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /** @@ -66,8 +66,6 @@ QStringList m_headerData; MapModel * m_staticMapModel; MapModel * m_missionMapModel; - - QStringList roomInfo2RoomRecord(const QStringList & info); }; #endif // HEDGEWARS_ROOMSLISTMODEL_H diff -r 31570b766315 -r ed5a6478e710 QTfrontend/net/hwmap.cpp --- a/QTfrontend/net/hwmap.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/net/hwmap.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,7 +1,7 @@ /* * Hedgewars, a free turn based strategy game * Copyright (c) 2006-2007 Ulyanov Igor - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,15 +14,23 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include +#include +#include + #include "hwconsts.h" #include "hwmap.h" HWMap::HWMap(QObject * parent) : TCPBase(false, parent) { + templateFilter = 0; + m_mapgen = MAPGEN_REGULAR; + m_maze_size = 0; + m_feature_size = 50; } HWMap::~HWMap() @@ -34,12 +42,15 @@ return !m_hasStarted; } -void HWMap::getImage(const QString & seed, int filter, MapGenerator mapgen, int maze_size, const QByteArray & drawMapData) +void HWMap::getImage(const QString & seed, int filter, MapGenerator mapgen, int maze_size, const QByteArray & drawMapData, QString & script, QString & scriptparam, int feature_size) { m_seed = seed; + m_script = script; + m_scriptparam = scriptparam; templateFilter = filter; m_mapgen = mapgen; m_maze_size = maze_size; + m_feature_size = feature_size; if(mapgen == MAPGEN_DRAWN) m_drawMapData = drawMapData; Start(true); } @@ -52,19 +63,57 @@ arguments << QString("%1").arg(ipc_port); arguments << "--user-prefix"; arguments << cfgdir->absolutePath(); + arguments << "--prefix"; + arguments << datadir->absolutePath(); arguments << "--landpreview"; return arguments; } void HWMap::onClientDisconnect() -{ +{ + QLinearGradient linearGrad(QPoint(128, 0), QPoint(128, 128)); + linearGrad.setColorAt(1, QColor(0, 0, 192)); + linearGrad.setColorAt(0, QColor(66, 115, 225)); + if (readbuffer.size() == 128 * 32 + 1) { quint8 *buf = (quint8*) readbuffer.constData(); QImage im(buf, 256, 128, QImage::Format_Mono); im.setNumColors(2); + + QPixmap px(QSize(256, 128)); + QPixmap pxres(px.size()); + QPainter p(&pxres); + + px.fill(Qt::yellow); + QBitmap bm = QBitmap::fromImage(im); + px.setMask(bm); + + p.fillRect(pxres.rect(), linearGrad); + p.drawPixmap(0, 0, px); + emit HHLimitReceived(buf[128 * 32]); - emit ImageReceived(im); + emit ImageReceived(px); + } else if (readbuffer.size() == 128 * 256 + 1) + { + QVector colorTable; + colorTable.resize(256); + for(int i = 0; i < 256; ++i) + colorTable[i] = qRgba(255, 255, 0, i); + + const quint8 *buf = (const quint8*) readbuffer.constData(); + QImage im(buf, 256, 128, QImage::Format_Indexed8); + im.setColorTable(colorTable); + + QPixmap px = QPixmap::fromImage(im, Qt::ColorOnly); + QPixmap pxres(px.size()); + QPainter p(&pxres); + + p.fillRect(pxres.rect(), linearGrad); + p.drawPixmap(0, 0, px); + + emit HHLimitReceived(buf[128 * 256]); + emit ImageReceived(px); } } @@ -73,10 +122,17 @@ SendIPC(QString("eseed %1").arg(m_seed).toUtf8()); SendIPC(QString("e$template_filter %1").arg(templateFilter).toUtf8()); SendIPC(QString("e$mapgen %1").arg(m_mapgen).toUtf8()); + SendIPC(QString("e$feature_size %1").arg(m_feature_size).toUtf8()); + if (!m_script.isEmpty()) + { + SendIPC(QString("escript Scripts/Multiplayer/%1.lua").arg(m_script).toUtf8()); + SendIPC(QString("e$scriptparam %1").arg(m_scriptparam).toUtf8()); + } switch (m_mapgen) { case MAPGEN_MAZE: + case MAPGEN_PERLIN: SendIPC(QString("e$maze_size %1").arg(m_maze_size).toUtf8()); break; diff -r 31570b766315 -r ed5a6478e710 QTfrontend/net/hwmap.h --- a/QTfrontend/net/hwmap.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/net/hwmap.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,7 +1,7 @@ /* * Hedgewars, a free turn based strategy game * Copyright (c) 2006 Igor Ulyanov - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _HWMAP_INCLUDED @@ -22,16 +22,17 @@ #include #include -#include +#include #include "tcpBase.h" enum MapGenerator { - MAPGEN_REGULAR, - MAPGEN_MAZE, - MAPGEN_DRAWN, - MAPGEN_MAP + MAPGEN_REGULAR = 0, + MAPGEN_MAZE = 1, + MAPGEN_PERLIN = 2, + MAPGEN_DRAWN = 3, + MAPGEN_MAP = 4 }; class HWMap : public TCPBase @@ -41,7 +42,7 @@ public: HWMap(QObject *parent = 0); virtual ~HWMap(); - void getImage(const QString & seed, int templateFilter, MapGenerator mapgen, int maze_size, const QByteArray & drawMapData); + void getImage(const QString & seed, int templateFilter, MapGenerator mapgen, int maze_size, const QByteArray & drawMapData, QString & script, QString & scriptparam, int feature_size); bool couldBeRemoved(); protected: @@ -50,14 +51,17 @@ virtual void SendToClientFirst(); signals: - void ImageReceived(const QImage newImage); + void ImageReceived(const QPixmap & newImage); void HHLimitReceived(int hhLimit); private: QString m_seed; + QString m_script; + QString m_scriptparam; int templateFilter; MapGenerator m_mapgen; - int m_maze_size; + int m_maze_size; // going to try and deprecate this one + int m_feature_size; QByteArray m_drawMapData; private slots: diff -r 31570b766315 -r ed5a6478e710 QTfrontend/net/hwmapoptimizer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/QTfrontend/net/hwmapoptimizer.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,54 @@ +#include "hwmapoptimizer.h" +#include "hwconsts.h" + +HWMapOptimizer::HWMapOptimizer(QObject *parent) : + TCPBase(parent) +{ +} + +bool HWMapOptimizer::couldBeRemoved() +{ + return !m_hasStarted; +} + +void HWMapOptimizer::optimizeMap(const Paths &paths) +{ + m_paths = paths; + + Start(true); +} + +QStringList HWMapOptimizer::getArguments() +{ + QStringList arguments; + arguments << "--internal"; + arguments << "--port"; + arguments << QString("%1").arg(ipc_port); + arguments << "--user-prefix"; + arguments << cfgdir->absolutePath(); + arguments << "--prefix"; + arguments << datadir->absolutePath(); + arguments << "--landpreview"; + return arguments; +} + +void HWMapOptimizer::onClientDisconnect() +{ + +} + +void HWMapOptimizer::SendToClientFirst() +{ + SendIPC("e$mapgen 4"); + + /*QByteArray data = m_drawMapData; + while(data.size() > 0) + { + QByteArray tmp = data; + tmp.truncate(200); + SendIPC("edraw " + tmp); + data.remove(0, 200); + } + + SendIPC("!");*/ +} diff -r 31570b766315 -r ed5a6478e710 QTfrontend/net/hwmapoptimizer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/QTfrontend/net/hwmapoptimizer.h Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,30 @@ +#ifndef HWMAPOPTIMIZER_H +#define HWMAPOPTIMIZER_H + +#include "tcpBase.h" +#include "drawmapscene.h" + +class HWMapOptimizer : public TCPBase +{ + Q_OBJECT +public: + explicit HWMapOptimizer(QObject *parent = 0); + + void optimizeMap(const Paths & paths); + bool couldBeRemoved(); + +signals: + void optimizedMap(const Paths & paths); + +public slots: + +protected: + QStringList getArguments(); + void onClientDisconnect(); + void SendToClientFirst(); + +private: + Paths m_paths; +}; + +#endif // HWMAPOPTIMIZER_H diff -r 31570b766315 -r ed5a6478e710 QTfrontend/net/netregister.cpp --- a/QTfrontend/net/netregister.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/net/netregister.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "netregister.h" diff -r 31570b766315 -r ed5a6478e710 QTfrontend/net/netregister.h --- a/QTfrontend/net/netregister.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/net/netregister.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _NET_REGISTER_INCLUDED diff -r 31570b766315 -r ed5a6478e710 QTfrontend/net/netserver.cpp --- a/QTfrontend/net/netserver.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/net/netserver.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,7 +1,7 @@ /* * Hedgewars, a free turn based strategy game * Copyright (c) 2006-2008 Igor Ulyanov - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "hwconsts.h" diff -r 31570b766315 -r ed5a6478e710 QTfrontend/net/netserver.h --- a/QTfrontend/net/netserver.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/net/netserver.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,7 +1,7 @@ /* * Hedgewars, a free turn based strategy game * Copyright (c) 2006-2008 Igor Ulyanov - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _NETSERVER_INCLUDED diff -r 31570b766315 -r ed5a6478e710 QTfrontend/net/netudpserver.cpp --- a/QTfrontend/net/netudpserver.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/net/netudpserver.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,7 +1,7 @@ /* * Hedgewars, a free turn based strategy game * Copyright (c) 2007-2008 Igor Ulyanov - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff -r 31570b766315 -r ed5a6478e710 QTfrontend/net/netudpserver.h --- a/QTfrontend/net/netudpserver.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/net/netudpserver.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,7 +1,7 @@ /* * Hedgewars, a free turn based strategy game * Copyright (c) 2007-2008 Igor Ulyanov - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _NET_UDPSERVER_INCLUDED diff -r 31570b766315 -r ed5a6478e710 QTfrontend/net/netudpwidget.cpp --- a/QTfrontend/net/netudpwidget.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/net/netudpwidget.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,7 +1,7 @@ /* * Hedgewars, a free turn based strategy game * Copyright (c) 2007 Igor Ulyanov - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff -r 31570b766315 -r ed5a6478e710 QTfrontend/net/netudpwidget.h --- a/QTfrontend/net/netudpwidget.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/net/netudpwidget.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,7 +1,7 @@ /* * Hedgewars, a free turn based strategy game * Copyright (c) 2007 Igor Ulyanov - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _NET_UDPWIDGET_INCLUDED diff -r 31570b766315 -r ed5a6478e710 QTfrontend/net/newnetclient.cpp --- a/QTfrontend/net/newnetclient.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/net/newnetclient.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,7 +1,7 @@ /* * Hedgewars, a free turn based strategy game * Copyright (c) 2006-2008 Igor Ulyanov - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,13 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include +#include #include "hwconsts.h" #include "newnetclient.h" @@ -31,14 +32,16 @@ #include "servermessages.h" #include "HWApplication.h" -char delimeter='\n'; +char delimiter='\n'; HWNewNet::HWNewNet() : isChief(false), m_game_connected(false), - loginStep(0), netClientState(Disconnected) { + m_private_game = false; + m_nick_registered = false; + m_roomsListModel = new RoomsListModel(this); m_playersModel = new PlayersListModel(this); @@ -71,7 +74,7 @@ { if (m_game_connected) { - RawSendNet(QString("QUIT%1%2").arg(delimeter).arg("User quit")); + RawSendNet(QString("QUIT%1%2").arg(delimiter).arg("User quit")); emit disconnected(tr("User quit")); } NetSocket.flush(); @@ -88,7 +91,7 @@ void HWNewNet::Disconnect() { if (m_game_connected) - RawSendNet(QString("QUIT%1%2").arg(delimeter).arg("User quit")); + RawSendNet(QString("QUIT%1%2").arg(delimiter).arg("User quit")); m_game_connected = false; NetSocket.disconnectFromHost(); @@ -105,9 +108,9 @@ myroom = room; if(password.isEmpty()) - RawSendNet(QString("CREATE_ROOM%1%2").arg(delimeter).arg(room)); + RawSendNet(QString("CREATE_ROOM%1%2").arg(delimiter).arg(room)); else - RawSendNet(QString("CREATE_ROOM%1%2%1%3").arg(delimeter).arg(room).arg(password)); + RawSendNet(QString("CREATE_ROOM%1%2%1%3").arg(delimiter).arg(room).arg(password)); isChief = true; } @@ -123,29 +126,29 @@ myroom = room; if(password.isEmpty()) - RawSendNet(QString("JOIN_ROOM%1%2").arg(delimeter).arg(room)); + RawSendNet(QString("JOIN_ROOM%1%2").arg(delimiter).arg(room)); else - RawSendNet(QString("JOIN_ROOM%1%2%1%3").arg(delimeter).arg(room).arg(password)); + RawSendNet(QString("JOIN_ROOM%1%2%1%3").arg(delimiter).arg(room).arg(password)); isChief = false; } void HWNewNet::AddTeam(const HWTeam & team) { - QString cmd = QString("ADD_TEAM") + delimeter + - team.name() + delimeter + - QString::number(team.color()) + delimeter + - team.grave() + delimeter + - team.fort() + delimeter + - team.voicepack() + delimeter + - team.flag() + delimeter + + QString cmd = QString("ADD_TEAM") + delimiter + + team.name() + delimiter + + QString::number(team.color()) + delimiter + + team.grave() + delimiter + + team.fort() + delimiter + + team.voicepack() + delimiter + + team.flag() + delimiter + QString::number(team.difficulty()); for(int i = 0; i < HEDGEHOGS_PER_TEAM; ++i) { - cmd.append(delimeter); + cmd.append(delimiter); cmd.append(team.hedgehog(i).Name); - cmd.append(delimeter); + cmd.append(delimiter); cmd.append(team.hedgehog(i).Hat); } RawSendNet(cmd); @@ -153,12 +156,12 @@ void HWNewNet::RemoveTeam(const HWTeam & team) { - RawSendNet(QString("REMOVE_TEAM") + delimeter + team.name()); + RawSendNet(QString("REMOVE_TEAM") + delimiter + team.name()); } void HWNewNet::NewNick(const QString & nick) { - RawSendNet(QString("NICK%1%2").arg(delimeter).arg(nick)); + RawSendNet(QString("NICK%1%2").arg(delimiter).arg(nick)); } void HWNewNet::ToggleReady() @@ -170,7 +173,7 @@ { QString msg = QString(buf.toBase64()); - RawSendNet(QString("EM%1%2").arg(delimeter).arg(msg)); + RawSendNet(QString("EM%1%2").arg(delimiter).arg(msg)); } void HWNewNet::RawSendNet(const QString & str) @@ -238,7 +241,10 @@ void HWNewNet::SendPasswordHash(const QString & hash) { - RawSendNet(QString("PASSWORD%1%2").arg(delimeter).arg(hash)); + // don't send it immediately, only store and check if server asked us for a password + m_passwordHash = hash.toAscii(); + + maybeSendPassword(); } void HWNewNet::ParseCmd(const QStringList & lst) @@ -286,24 +292,46 @@ { // TODO: Warn user, disconnect qWarning() << "Server too old"; - RawSendNet(QString("QUIT%1%2").arg(delimeter).arg("Server too old")); + RawSendNet(QString("QUIT%1%2").arg(delimiter).arg("Server too old")); Disconnect(); emit disconnected(tr("The server is too old. Disconnecting now.")); return; } - RawSendNet(QString("NICK%1%2").arg(delimeter).arg(mynick)); - RawSendNet(QString("PROTO%1%2").arg(delimeter).arg(*cProtoVer)); + RawSendNet(QString("NICK%1%2").arg(delimiter).arg(mynick)); + RawSendNet(QString("PROTO%1%2").arg(delimiter).arg(*cProtoVer)); netClientState = Connected; m_game_connected = true; emit adminAccess(false); return; } + if (lst[0] == "SERVER_AUTH") + { + if(lst.size() < 2) + { + qWarning("Net: Malformed SERVER_AUTH message"); + return; + } + + if(lst[1] != m_serverHash) + { + Error("Server authentication error"); + Disconnect(); + } else + { + // empty m_serverHash variable means no authentication was performed + // or server passed authentication + m_serverHash.clear(); + } + + return; + } + if (lst[0] == "PING") { if (lst.size() > 1) - RawSendNet(QString("PONG%1%2").arg(delimeter).arg(lst[1])); + RawSendNet(QString("PONG%1%2").arg(delimiter).arg(lst[1])); else RawSendNet(QString("PONG")); return; @@ -450,7 +478,7 @@ // flag indicating if a player is contributor case 'c': foreach(const QString & nick, nicks) - m_playersModel->setFlag(nick, PlayersListModel::InRoom, setFlag); + m_playersModel->setFlag(nick, PlayersListModel::Contributor, setFlag); break; // flag indicating if a player has engine running case 'g': @@ -515,6 +543,14 @@ { if (lst[i] == mynick) { + // check if server is authenticated or no authentication was performed at all + if(!m_serverHash.isEmpty()) + { + Error(tr("Server authentication error")); + + Disconnect(); + } + netClientState = InLobby; RawSendNet(QString("LIST")); emit connected(); @@ -545,7 +581,7 @@ m_roomsListModel->updateRoom(roomName, tmp); // keep track of room name so correct name is displayed - if(myroom == roomName) + if(myroom == roomName && myroom != tmp[1]) { myroom = tmp[1]; emit roomNameUpdated(myroom); @@ -578,8 +614,24 @@ if (lst[0] == "ASKPASSWORD") { + // server should send us salt of at least 16 characters + + if(lst.size() < 2 || lst[1].size() < 16) + { + qWarning("Net: Bad ASKPASSWORD message"); + return; + } + emit NickRegistered(mynick); m_nick_registered = true; + + // store server salt + // when this variable is set, it is assumed that server asked us for a password + m_serverSalt = lst[1]; + m_clientSalt = QUuid::createUuid().toString(); + + maybeSendPassword(); + return; } @@ -696,7 +748,8 @@ } QStringList tmp = lst; tmp.removeFirst(); - emit AddNetTeam(tmp); + HWTeam team(tmp); + emit AddNetTeam(team); return; } @@ -820,7 +873,7 @@ { if (isChief) RawSendNet(QString("HH_NUM%1%2%1%3") - .arg(delimeter) + .arg(delimiter) .arg(team.name()) .arg(team.numHedgehogs())); } @@ -829,7 +882,7 @@ { if (isChief) RawSendNet(QString("TEAM_COLOR%1%2%1%3") - .arg(delimeter) + .arg(delimiter) .arg(team.name()) .arg(team.color())); } @@ -839,9 +892,9 @@ if (isChief) RawSendNet( QString("CFG%1%2%1%3") - .arg(delimeter) + .arg(delimiter) .arg(param) - .arg(value.join(QString(delimeter))) + .arg(value.join(QString(delimiter))) ); } @@ -858,7 +911,7 @@ { if(str != "") { - RawSendNet(QString("CHAT") + delimeter + str); + RawSendNet(QString("CHAT") + delimiter + str); QString action = HWProto::chatStringToAction(str); if (action != NULL) emit(roomChatAction(mynick, action)); @@ -871,7 +924,7 @@ { if(str != "") { - RawSendNet(QString("CHAT") + delimeter + str); + RawSendNet(QString("CHAT") + delimiter + str); QString action = HWProto::chatStringToAction(str); if (action != NULL) emit(lobbyChatAction(mynick, action)); @@ -882,7 +935,7 @@ void HWNewNet::SendTeamMessage(const QString& str) { - RawSendNet(QString("TEAMCHAT") + delimeter + str); + RawSendNet(QString("TEAMCHAT") + delimiter + str); } void HWNewNet::askRoomsList() @@ -925,23 +978,23 @@ if (netClientState == InGame) { netClientState = InRoom; - RawSendNet(QString("ROUNDFINISHED%1%2").arg(delimeter).arg(correctly ? "1" : "0")); + RawSendNet(QString("ROUNDFINISHED%1%2").arg(delimiter).arg(correctly ? "1" : "0")); } } void HWNewNet::banPlayer(const QString & nick) { - RawSendNet(QString("BAN%1%2").arg(delimeter).arg(nick)); + RawSendNet(QString("BAN%1%2").arg(delimiter).arg(nick)); } void HWNewNet::banIP(const QString & ip, const QString & reason, int seconds) { - RawSendNet(QString("BANIP%1%2%1%3%1%4").arg(delimeter).arg(ip).arg(reason).arg(seconds)); + RawSendNet(QString("BANIP%1%2%1%3%1%4").arg(delimiter).arg(ip).arg(reason).arg(seconds)); } void HWNewNet::banNick(const QString & nick, const QString & reason, int seconds) { - RawSendNet(QString("BANNICK%1%2%1%3%1%4").arg(delimeter).arg(nick).arg(reason).arg(seconds)); + RawSendNet(QString("BANNICK%1%2%1%3%1%4").arg(delimiter).arg(nick).arg(reason).arg(seconds)); } void HWNewNet::getBanList() @@ -951,31 +1004,31 @@ void HWNewNet::removeBan(const QString & b) { - RawSendNet(QString("UNBAN%1%2").arg(delimeter).arg(b)); + RawSendNet(QString("UNBAN%1%2").arg(delimiter).arg(b)); } void HWNewNet::kickPlayer(const QString & nick) { - RawSendNet(QString("KICK%1%2").arg(delimeter).arg(nick)); + RawSendNet(QString("KICK%1%2").arg(delimiter).arg(nick)); } void HWNewNet::infoPlayer(const QString & nick) { - RawSendNet(QString("INFO%1%2").arg(delimeter).arg(nick)); + RawSendNet(QString("INFO%1%2").arg(delimiter).arg(nick)); } void HWNewNet::followPlayer(const QString & nick) { if (!isInRoom()) { - RawSendNet(QString("FOLLOW%1%2").arg(delimeter).arg(nick)); + RawSendNet(QString("FOLLOW%1%2").arg(delimiter).arg(nick)); isChief = false; } } void HWNewNet::consoleCommand(const QString & cmd) { - RawSendNet(QString("CMD%1%2").arg(delimeter).arg(cmd)); + RawSendNet(QString("CMD%1%2").arg(delimiter).arg(cmd)); } bool HWNewNet::allPlayersReady() @@ -994,7 +1047,7 @@ void HWNewNet::updateRoomName(const QString & name) { - RawSendNet(QString("ROOM_NAME%1%2").arg(delimeter).arg(name)); + RawSendNet(QString("ROOM_NAME%1%2").arg(delimiter).arg(name)); } @@ -1032,17 +1085,17 @@ void HWNewNet::setServerMessageNew(const QString & msg) { - RawSendNet(QString("SET_SERVER_VAR%1MOTD_NEW%1%2").arg(delimeter).arg(msg)); + RawSendNet(QString("SET_SERVER_VAR%1MOTD_NEW%1%2").arg(delimiter).arg(msg)); } void HWNewNet::setServerMessageOld(const QString & msg) { - RawSendNet(QString("SET_SERVER_VAR%1MOTD_OLD%1%2").arg(delimeter).arg(msg)); + RawSendNet(QString("SET_SERVER_VAR%1MOTD_OLD%1%2").arg(delimiter).arg(msg)); } void HWNewNet::setLatestProtocolVar(int proto) { - RawSendNet(QString("SET_SERVER_VAR%1LATEST_PROTO%1%2").arg(delimeter).arg(proto)); + RawSendNet(QString("SET_SERVER_VAR%1LATEST_PROTO%1%2").arg(delimiter).arg(proto)); } void HWNewNet::askServerVars() @@ -1083,3 +1136,34 @@ if(!myroom.isEmpty()) JoinRoom(myroom, password); } + +void HWNewNet::maybeSendPassword() +{ +/* When we got password hash, and server asked us for a password, perform mutual authentication: + * at this point we have salt chosen by server + * client sends client salt and hash of secret (password hash) salted with client salt, server salt, + * and static salt (predefined string + protocol number) + * server should respond with hash of the same set in different order. + */ + + if(m_passwordHash.isEmpty() || m_serverSalt.isEmpty()) + return; + + QString hash = QCryptographicHash::hash( + m_clientSalt.toAscii() + .append(m_serverSalt.toAscii()) + .append(m_passwordHash) + .append(cProtoVer->toAscii()) + .append("!hedgewars") + , QCryptographicHash::Sha1).toHex(); + + m_serverHash = QCryptographicHash::hash( + m_serverSalt.toAscii() + .append(m_clientSalt.toAscii()) + .append(m_passwordHash) + .append(cProtoVer->toAscii()) + .append("!hedgewars") + , QCryptographicHash::Sha1).toHex(); + + RawSendNet(QString("PASSWORD%1%2%1%3").arg(delimiter).arg(hash).arg(m_clientSalt)); +} diff -r 31570b766315 -r ed5a6478e710 QTfrontend/net/newnetclient.h --- a/QTfrontend/net/newnetclient.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/net/newnetclient.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,7 +1,7 @@ /* * Hedgewars, a free turn based strategy game * Copyright (c) 2006-2008 Igor Ulyanov - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _NEW_NETCLIENT_INCLUDED @@ -36,7 +36,7 @@ class QSortFilterProxyModel; class QAbstractItemModel; -extern char delimeter; +extern char delimiter; class HWNewNet : public QObject { @@ -77,6 +77,10 @@ QSortFilterProxyModel * m_lobbyPlayersModel; QSortFilterProxyModel * m_roomPlayersModel; QString m_lastRoom; + QString m_passwordHash; + QString m_serverSalt; + QString m_clientSalt; + QString m_serverHash; QStringList cmdbuf; @@ -85,7 +89,8 @@ void ParseCmd(const QStringList & lst); void handleNotice(int n); - int loginStep; + void maybeSendPassword(); + ClientState netClientState; signals: @@ -106,7 +111,7 @@ void roomNameUpdated(const QString & name); void askForRoomPassword(); - void netSchemeConfig(QStringList &); + void netSchemeConfig(QStringList); void paramChanged(const QString & param, const QStringList & value); void configAsked(); diff -r 31570b766315 -r ed5a6478e710 QTfrontend/net/proto.cpp --- a/QTfrontend/net/proto.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/net/proto.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "proto.h" @@ -58,5 +58,5 @@ if(string.left(4) == "/me ") return string.mid(4); else - return NULL; + return QString(); } diff -r 31570b766315 -r ed5a6478e710 QTfrontend/net/proto.h --- a/QTfrontend/net/proto.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/net/proto.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _PROTO_H diff -r 31570b766315 -r ed5a6478e710 QTfrontend/net/recorder.cpp --- a/QTfrontend/net/recorder.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/net/recorder.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include @@ -37,6 +37,7 @@ { this->config = config; this->prefix = prefix; + item = 0; finished = false; name = prefix + "." + LibavInteraction::instance().getExtension(config->AVFormat()); } @@ -143,3 +144,8 @@ return arguments; } + +bool HWRecorder::simultaneousRun() +{ + return true; +} diff -r 31570b766315 -r ed5a6478e710 QTfrontend/net/recorder.h --- a/QTfrontend/net/recorder.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/net/recorder.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef RECORDER_H @@ -35,6 +35,7 @@ virtual ~HWRecorder(); void EncodeVideo(const QByteArray & record); + bool simultaneousRun(); VideoItem * item; // used by pagevideos QString name; diff -r 31570b766315 -r ed5a6478e710 QTfrontend/net/tcpBase.cpp --- a/QTfrontend/net/tcpBase.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/net/tcpBase.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,7 +1,7 @@ /* * Hedgewars, a free turn based strategy game * Copyright (c) 2006-2007 Igor Ulyanov - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,51 +14,62 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "tcpBase.h" - #include #include #include +#include +#include "tcpBase.h" #include "hwconsts.h" #include "MessageDialog.h" #ifdef HWLIBRARY -extern "C" void Game(char**arguments); -extern "C" void GenLandPreview(int port); +extern "C" { + void RunEngine(int argc, char ** argv); + + int operatingsystem_parameter_argc; + char ** operatingsystem_parameter_argv; +} EngineInstance::EngineInstance(QObject *parent) : QObject(parent) { - port = 0; + } EngineInstance::~EngineInstance() { + qDebug() << "EngineInstance delete" << QThread::currentThreadId(); +} + +void EngineInstance::setArguments(const QStringList & arguments) +{ + m_arguments.clear(); + m_arguments << qApp->arguments().at(0).toUtf8(); + + m_argv.resize(arguments.size() + 1); + m_argv[0] = m_arguments.last().data(); + + int i = 1; + foreach(const QString & s, arguments) + { + m_arguments << s.toUtf8(); + m_argv[i] = m_arguments.last().data(); + ++i; + } } void EngineInstance::start() { -#if 0 - char *args[11]; - args[0] = "65000"; //ipcPort - args[1] = "1024"; //cScreenWidth - args[2] = "768"; //cScreenHeight - args[3] = "0"; //cReducedQuality - args[4] = "en.txt"; //cLocaleFName - args[5] = "koda"; //UserNick - args[6] = "1"; //SetSound - args[7] = "1"; //SetMusic - args[8] = "0"; //cAltDamage - args[9]= datadir->absolutePath().toAscii().data(); //cPathPrefix - args[10]= NULL; //recordFileName - Game(args); -#endif - GenLandPreview(port); + qDebug() << "EngineInstance start" << QThread::currentThreadId(); + + RunEngine(m_argv.size(), m_argv.data()); + + emit finished(); } #endif @@ -68,6 +79,23 @@ TCPBase::~TCPBase() { + if(m_hasStarted) + { + if(IPCSocket) + IPCSocket->close(); + + if(m_connected) + { +#ifdef HWLIBRARY + if(!thread) + qDebug("WTF"); + thread->quit(); + thread->wait(); +#else + process->waitForFinished(1000); +#endif + } + } // make sure this object is not in the server list anymore srvsList.removeOne(this); @@ -80,8 +108,11 @@ QObject(parent), m_hasStarted(false), m_isDemoMode(demoMode), + m_connected(false), IPCSocket(0) { + process = 0; + if(!IPCServer) { IPCServer = new QTcpServer(0); @@ -103,12 +134,23 @@ // connection should be already finished return; } + disconnect(IPCServer, SIGNAL(newConnection()), this, SLOT(NewConnection())); IPCSocket = IPCServer->nextPendingConnection(); + if(!IPCSocket) return; + + m_connected = true; + connect(IPCSocket, SIGNAL(disconnected()), this, SLOT(ClientDisconnect())); connect(IPCSocket, SIGNAL(readyRead()), this, SLOT(ClientRead())); SendToClientFirst(); + + if(simultaneousRun()) + { + srvsList.removeOne(this); + emit isReadyNow(); + } } void TCPBase::RealStart() @@ -117,9 +159,9 @@ IPCSocket = 0; #ifdef HWLIBRARY - QThread *thread = new QThread; - EngineInstance *instance = new EngineInstance; - instance->port = IPCServer->serverPort(); + thread = new QThread(this); + EngineInstance *instance = new EngineInstance(); + instance->setArguments(getArguments()); instance->moveToThread(thread); @@ -129,10 +171,12 @@ connect(instance, SIGNAL(finished()), thread, SLOT(deleteLater())); thread->start(); #else - QProcess * process; - process = new QProcess(); - connect(process, SIGNAL(error(QProcess::ProcessError)), this, SLOT(StartProcessError(QProcess::ProcessError))); - QStringList arguments=getArguments(); + process = new QProcess(this); + connect(process, SIGNAL(error(QProcess::ProcessError)), + this, SLOT(StartProcessError(QProcess::ProcessError))); + connect(process, SIGNAL(finished(int, QProcess::ExitStatus)), + this, SLOT(onEngineDeath(int, QProcess::ExitStatus))); + QStringList arguments = getArguments(); #ifdef QT_DEBUG // redirect everything written on stdout/stderr @@ -149,17 +193,26 @@ disconnect(IPCSocket, SIGNAL(readyRead()), this, SLOT(ClientRead())); onClientDisconnect(); - emit isReadyNow(); + if(!simultaneousRun()) + { +#ifdef HWLIBRARY + thread->quit(); + thread->wait(); +#endif + emit isReadyNow(); + } + IPCSocket->deleteLater(); + IPCSocket = NULL; deleteLater(); } void TCPBase::ClientRead() { - QByteArray readed=IPCSocket->readAll(); - if(readed.isEmpty()) return; - readbuffer.append(readed); + QByteArray read = IPCSocket->readAll(); + if(read.isEmpty()) return; + readbuffer.append(read); onClientRead(); } @@ -169,6 +222,38 @@ ClientDisconnect(); } +void TCPBase::onEngineDeath(int exitCode, QProcess::ExitStatus exitStatus) +{ + Q_UNUSED(exitStatus); + + ClientDisconnect(); + + // show error message if there was an error that was not an engine's + // fatal error - because that one already sent a info via IPC + if ((exitCode != 0) && (exitCode != 2)) + { + // inform user that something bad happened + MessageDialog::ShowFatalMessage( + tr("The game engine died unexpectedly!\n" + "(exit code %1)\n\n" + "We are very sorry for the inconvenience :(\n\n" + "If this keeps happening, please click the '%2' button in the main menu!") + .arg(exitCode) + .arg("Feedback")); + + } + + // cleanup up + if (IPCSocket) + { + IPCSocket->close(); + IPCSocket->deleteLater(); + } + + // plot suicide + deleteLater(); +} + void TCPBase::tcpServerReady() { disconnect(srvsList.first(), SIGNAL(isReadyNow()), this, SLOT(tcpServerReady())); @@ -188,14 +273,15 @@ TCPBase * last = srvsList.last(); if(couldCancelPreviousRequest && last->couldBeRemoved() + && (last->isConnected() || !last->hasStarted()) && (last->parent() == parent())) { srvsList.removeLast(); - last->deleteLater(); + delete last; Start(couldCancelPreviousRequest); } else { - connect(srvsList.last(), SIGNAL(isReadyNow()), this, SLOT(tcpServerReady())); + connect(last, SIGNAL(isReadyNow()), this, SLOT(tcpServerReady())); srvsList.push_back(this); } } @@ -246,3 +332,18 @@ { return false; } + +bool TCPBase::isConnected() +{ + return m_connected; +} + +bool TCPBase::simultaneousRun() +{ + return false; +} + +bool TCPBase::hasStarted() +{ + return m_hasStarted; +} diff -r 31570b766315 -r ed5a6478e710 QTfrontend/net/tcpBase.h --- a/QTfrontend/net/tcpBase.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/net/tcpBase.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,7 +1,7 @@ /* * Hedgewars, a free turn based strategy game * Copyright (c) 2006-2007 Igor Ulyanov - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _TCPBASE_INCLUDED @@ -27,7 +27,10 @@ #include #include #include +#include #include +#include +#include #include @@ -42,6 +45,9 @@ virtual ~TCPBase(); virtual bool couldBeRemoved(); + virtual bool simultaneousRun(); + bool isConnected(); + bool hasStarted(); signals: void isReadyNow(); @@ -67,8 +73,13 @@ private: static QPointer IPCServer; - +#ifdef HWLIBRARY + QThread * thread; +#else + QProcess * process; +#endif bool m_isDemoMode; + bool m_connected; void RealStart(); QPointer IPCSocket; @@ -77,6 +88,7 @@ void ClientDisconnect(); void ClientRead(); void StartProcessError(QProcess::ProcessError error); + void onEngineDeath(int exitCode, QProcess::ExitStatus exitStatus); void tcpServerReady(); }; @@ -89,12 +101,17 @@ EngineInstance(QObject *parent = 0); ~EngineInstance(); - int port; + void setArguments(const QStringList & arguments); + public slots: - void start(void); + void start(); + signals: - void finished(void); + void finished(); + private: + QList m_arguments; + QVector m_argv; }; #endif diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/Background.png Binary file QTfrontend/res/Background.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/BackgroundChristmas.png Binary file QTfrontend/res/BackgroundChristmas.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/BackgroundEaster.png Binary file QTfrontend/res/BackgroundEaster.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/Confetti.png Binary file QTfrontend/res/Confetti.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/Egg.png Binary file QTfrontend/res/Egg.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/Exit.png Binary file QTfrontend/res/Exit.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/Flake.png Binary file QTfrontend/res/Flake.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/LocalPlay.png Binary file QTfrontend/res/LocalPlay.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/NetworkPlayDisabled.png Binary file QTfrontend/res/NetworkPlayDisabled.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/PlaySound.png Binary file QTfrontend/res/PlaySound.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/Save.png Binary file QTfrontend/res/Save.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/Settings.png Binary file QTfrontend/res/Settings.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/Star.png Binary file QTfrontend/res/Star.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/Start.png Binary file QTfrontend/res/Start.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/StatsBestKiller.png Binary file QTfrontend/res/StatsBestKiller.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/StatsBestShot.png Binary file QTfrontend/res/StatsBestShot.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/StatsCustomAchievement.png Binary file QTfrontend/res/StatsCustomAchievement.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/StatsD.png Binary file QTfrontend/res/StatsD.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/StatsH.png Binary file QTfrontend/res/StatsH.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/StatsHedgehogsKilled.png Binary file QTfrontend/res/StatsHedgehogsKilled.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/StatsMedal1.png Binary file QTfrontend/res/StatsMedal1.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/StatsMedal2.png Binary file QTfrontend/res/StatsMedal2.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/StatsMedal3.png Binary file QTfrontend/res/StatsMedal3.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/StatsMedal4.png Binary file QTfrontend/res/StatsMedal4.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/StatsMostSelfDamage.png Binary file QTfrontend/res/StatsMostSelfDamage.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/StatsR.png Binary file QTfrontend/res/StatsR.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/StatsSelfKilled.png Binary file QTfrontend/res/StatsSelfKilled.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/StatsSkipped.png Binary file QTfrontend/res/StatsSkipped.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/Trainings.png Binary file QTfrontend/res/Trainings.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/addfriend.png Binary file QTfrontend/res/addfriend.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/ammopic.png Binary file QTfrontend/res/ammopic.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/botlevels/net0.png Binary file QTfrontend/res/botlevels/net0.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/botlevels/net1.png Binary file QTfrontend/res/botlevels/net1.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/botlevels/net2.png Binary file QTfrontend/res/botlevels/net2.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/botlevels/net3.png Binary file QTfrontend/res/botlevels/net3.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/botlevels/net4.png Binary file QTfrontend/res/botlevels/net4.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/botlevels/net5.png Binary file QTfrontend/res/botlevels/net5.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/btnArtillery.png Binary file QTfrontend/res/btnArtillery.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/btnBorder.png Binary file QTfrontend/res/btnBorder.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/btnDisableLandObjects.png Binary file QTfrontend/res/btnDisableLandObjects.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/btnForts.png Binary file QTfrontend/res/btnForts.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/btnInvulnerable.png Binary file QTfrontend/res/btnInvulnerable.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/btnKarma.png Binary file QTfrontend/res/btnKarma.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/btnKing.png Binary file QTfrontend/res/btnKing.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/btnLaserSight.png Binary file QTfrontend/res/btnLaserSight.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/btnLowGravity.png Binary file QTfrontend/res/btnLowGravity.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/btnMoreWind.png Binary file QTfrontend/res/btnMoreWind.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/btnNoWind.png Binary file QTfrontend/res/btnNoWind.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/btnOverlay.png Binary file QTfrontend/res/btnOverlay.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/btnPlaceHog.png Binary file QTfrontend/res/btnPlaceHog.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/btnRandomOrder.png Binary file QTfrontend/res/btnRandomOrder.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/btnResetWeps.png Binary file QTfrontend/res/btnResetWeps.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/btnSharedAmmo.png Binary file QTfrontend/res/btnSharedAmmo.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/btnTeamsDivide.png Binary file QTfrontend/res/btnTeamsDivide.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/btnVampiric.png Binary file QTfrontend/res/btnVampiric.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/camera.png Binary file QTfrontend/res/camera.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/campaign/A_Classic_Fairytale/backstab.png Binary file QTfrontend/res/campaign/A_Classic_Fairytale/backstab.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/campaign/A_Classic_Fairytale/dragon.png Binary file QTfrontend/res/campaign/A_Classic_Fairytale/dragon.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/campaign/A_Classic_Fairytale/epil.png Binary file QTfrontend/res/campaign/A_Classic_Fairytale/epil.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/campaign/A_Classic_Fairytale/family.png Binary file QTfrontend/res/campaign/A_Classic_Fairytale/family.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/campaign/A_Classic_Fairytale/journey.png Binary file QTfrontend/res/campaign/A_Classic_Fairytale/journey.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/campaign/A_Classic_Fairytale/queen.png Binary file QTfrontend/res/campaign/A_Classic_Fairytale/queen.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/campaign/A_Classic_Fairytale/shadow.png Binary file QTfrontend/res/campaign/A_Classic_Fairytale/shadow.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/campaign/A_Classic_Fairytale/united.png Binary file QTfrontend/res/campaign/A_Classic_Fairytale/united.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/campaign/A_Space_Adventure/cosmos.png Binary file QTfrontend/res/campaign/A_Space_Adventure/cosmos.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/campaign/A_Space_Adventure/death01.png Binary file QTfrontend/res/campaign/A_Space_Adventure/death01.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/campaign/A_Space_Adventure/death02.png Binary file QTfrontend/res/campaign/A_Space_Adventure/death02.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/campaign/A_Space_Adventure/desert02.png Binary file QTfrontend/res/campaign/A_Space_Adventure/desert02.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/campaign/A_Space_Adventure/desert03.png Binary file QTfrontend/res/campaign/A_Space_Adventure/desert03.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/campaign/A_Space_Adventure/ice01.png Binary file QTfrontend/res/campaign/A_Space_Adventure/ice01.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/campaign/A_Space_Adventure/moon01.png Binary file QTfrontend/res/campaign/A_Space_Adventure/moon01.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/chat/friend.png Binary file QTfrontend/res/chat/friend.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/chat/hedgehog.png Binary file QTfrontend/res/chat/hedgehog.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/chat/hedgehog_gray.png Binary file QTfrontend/res/chat/hedgehog_gray.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/chat/hedgehogcontributor.png Binary file QTfrontend/res/chat/hedgehogcontributor.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/chat/hedgehogcontributor_gray.png Binary file QTfrontend/res/chat/hedgehogcontributor_gray.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/chat/ignore.png Binary file QTfrontend/res/chat/ignore.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/chat/ingame.png Binary file QTfrontend/res/chat/ingame.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/chat/lamp.png Binary file QTfrontend/res/chat/lamp.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/chat/lamp_off.png Binary file QTfrontend/res/chat/lamp_off.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/chat/roomadmin.png Binary file QTfrontend/res/chat/roomadmin.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/chat/roomadmin_gray.png Binary file QTfrontend/res/chat/roomadmin_gray.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/chat/roomadmincontributor.png Binary file QTfrontend/res/chat/roomadmincontributor.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/chat/roomadmincontributor_gray.png Binary file QTfrontend/res/chat/roomadmincontributor_gray.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/chat/serveradmin.png Binary file QTfrontend/res/chat/serveradmin.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/chat/serveradmin_gray.png Binary file QTfrontend/res/chat/serveradmin_gray.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/checked.png Binary file QTfrontend/res/checked.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/css/chat.css --- a/QTfrontend/res/css/chat.css Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/res/css/chat.css Tue Nov 10 20:43:13 2015 +0100 @@ -9,7 +9,7 @@ * * In the QTfrontend of hedgewars also display:none; will work for class names * that start with msg_ and .timestamp - as long as they are referenced - * directly and not within any class hierachy. + * directly and not within any class hierarchy. * Note: Will only effect new lines! * ****************************************************************************** diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/css/qt.css diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/delete.png Binary file QTfrontend/res/delete.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/dropdown.png Binary file QTfrontend/res/dropdown.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/edit.png Binary file QTfrontend/res/edit.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/file_demo.png Binary file QTfrontend/res/file_demo.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/file_save.png Binary file QTfrontend/res/file_save.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/follow.png Binary file QTfrontend/res/follow.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/hh25x25.png Binary file QTfrontend/res/hh25x25.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/hh25x25grey.png Binary file QTfrontend/res/hh25x25grey.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/hh_small.png Binary file QTfrontend/res/hh_small.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/html/about.html --- a/QTfrontend/res/html/about.html Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/res/html/about.html Tue Nov 10 20:43:13 2015 +0100 @@ -35,6 +35,7 @@ Keybinds, feedback, maps and hats interfaces: Drew Gottlieb <gottlieb.drew@gmail.com>
Login dialogs, frontend improvements: Ondrej Skopek <skopekondrej@gmail.com>
Icegun weapon: Julia Struchenko <urbertar@gmail.com>
+ iPhone/iPad ports: Anton Malmygin <antonc27@mail.ru>

Art:

@@ -72,17 +73,17 @@ Czech: Petr Řezáček <rezacek@gmail.com>
Chinese: Jie Luo <lililjlj@gmail.com>
English: Andrey Korotaev <unC0Rr@gmail.com>
- Finnish: Nina Kuisma <ninnnu@gmail.com>
+ Finnish: Nina Kuisma <ninnnu@gmail.com>, Janne Uusitupa
French: Antoine Turmel <geekshadow@gmail.com>, Clement Woitrain <sphrixclement@gmail.com>, Matisumi
- German: Peter Hüwe <PeterHuewe@gmx.de>, Mario Liebisch <mario.liebisch@gmail.com>, Richard Karolyi <sheepluva@ercatec.net>
+ German: Peter Hüwe <PeterHuewe@gmx.de>, Mario Liebisch <mario.liebisch@gmail.com>, Richard Karolyi <sheepluva@ercatec.net>, Wuzzy <almikes@aol.com>
Greek: <talos_kriti@yahoo.gr>
- Italian: Luca Bonora <bonora.luca@gmail.com>, Marco Bresciani <m.bresciani@email.it>
+ Italian: Luca Bonora <bonora.luca@gmail.com>, Marco Bresciani <m.bresciani@email.it>, Gianfranco Costamagna <costamagnagianfranco@yahoo.it>
Japanese: ADAM Etienne <etienne.adam@gmail.com>, Marco Bresciani <m.bresciani@email.it>
Korean: Anthony Bellew <anthonyreflected@gmail.com>
Lithuanian: Lukas Urbonas <lukasu08@gmail.com>
Polish: Maciej Mroziński <mynick2@o2.pl>, Wojciech Latkowski <magik17l@gmail.com>, Piotr Mitana, Maciej Górny
Portuguese: Fábio Canário <inufabie@gmail.com>
- Russian: Andrey Korotaev <unC0Rr@gmail.com>, Vitaly Novichkov <admin@wohlnet.ru>
+ Russian: Andrey Korotaev <unC0Rr@gmail.com>, Vitaly Novichkov <admin@wohlnet.ru>, Anton Malmygin <antonc27@mail.ru>
Slovak: Jose Riha
Spanish: Carlos Vives <mail@carlosvives.es>
Swedish: Niklas Grahn <raewolusjoon@yaoo.com>, Henrik Rostedt <henrik.rostedt@gmail.com>
diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/iconBox.png Binary file QTfrontend/res/iconBox.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/iconDamage.png Binary file QTfrontend/res/iconDamage.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/iconDamageLockG.png Binary file QTfrontend/res/iconDamageLockG.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/iconDamageLockR.png Binary file QTfrontend/res/iconDamageLockR.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/iconDud.png Binary file QTfrontend/res/iconDud.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/iconEarth.png Binary file QTfrontend/res/iconEarth.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/iconHealth.png Binary file QTfrontend/res/iconHealth.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/iconMine.png Binary file QTfrontend/res/iconMine.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/iconRope.png Binary file QTfrontend/res/iconRope.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/iconSuddenDeath.png Binary file QTfrontend/res/iconSuddenDeath.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/iconTime.png Binary file QTfrontend/res/iconTime.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/iconTimeLockG.png Binary file QTfrontend/res/iconTimeLockG.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/iconTimeLockR.png Binary file QTfrontend/res/iconTimeLockR.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/ignore.png Binary file QTfrontend/res/ignore.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/infinity.png Binary file QTfrontend/res/infinity.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/info.png Binary file QTfrontend/res/info.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/inverse-corner-bl.png Binary file QTfrontend/res/inverse-corner-bl.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/kick.png Binary file QTfrontend/res/kick.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/lightbulb_off.png Binary file QTfrontend/res/lightbulb_off.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/lightbulb_on.png Binary file QTfrontend/res/lightbulb_on.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/lock.png Binary file QTfrontend/res/lock.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/locks.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/QTfrontend/res/locks.svg Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,147 @@ + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Openclipart + + + Open and closed lock + 2013-11-07T10:50:32 + Set of 2 locks, one opened and one closed. + https://openclipart.org/detail/188421/open-and-closed-lock-by-iyo-188421 + + + Iyo + + + + + closed + lock + locks + open + pic + pictogram + sign + + + + + + + + + + + diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/mapCustom.png Binary file QTfrontend/res/mapCustom.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/mapMaze.png Binary file QTfrontend/res/mapMaze.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/mapMissing.png Binary file QTfrontend/res/mapMissing.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/mapMission.png Binary file QTfrontend/res/mapMission.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/mapRandom.png Binary file QTfrontend/res/mapRandom.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/miscicon.png Binary file QTfrontend/res/miscicon.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/net.png Binary file QTfrontend/res/net.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/new.png Binary file QTfrontend/res/new.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/remfriend.png Binary file QTfrontend/res/remfriend.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/spin_down.png Binary file QTfrontend/res/spin_down.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/spin_up.png Binary file QTfrontend/res/spin_up.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/splash.png Binary file QTfrontend/res/splash.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/unchecked.png Binary file QTfrontend/res/unchecked.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/unignore.png Binary file QTfrontend/res/unignore.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/unlock.png Binary file QTfrontend/res/unlock.png has changed diff -r 31570b766315 -r ed5a6478e710 QTfrontend/res/xml/tips.xml --- a/QTfrontend/res/xml/tips.xml Tue Nov 10 18:16:35 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,62 +0,0 @@ -# This is not xml actually, but it looks and behaves like it. -# Including an xml library would need too much resources. -# Tips between the platform specific tags are shown only on those platforms. -# Do not escape characters or use the CDATA tag. - - Simply pick the same color as a friend to play together as a team. Each of you will still control his or her own hedgehogs but they'll win or lose together. - Some weapons might do only low damage but they can be a lot more devastating in the right situation. Try to use the Desert Eagle to knock multiple hedgehogs into the water. - If you're unsure what to do and don't want to waste ammo, skip one round. But don't let too much time pass as there will be Sudden Death! - Want to save ropes? Release the rope in mid air and then shoot again. As long as you don't touch the ground or miss a shot you'll reuse your rope without wasting ammo! - If you'd like to keep others from using your preferred nickname on the official server, register an account at http://www.hedgewars.org/. - You're bored of default gameplay? Try one of the missions - they'll offer different gameplay depending on the one you picked. - By default the game will always record the last game played as a demo. Select 'Local Game' and pick the 'Demos' button on the lower right corner to play or manage them. - Hedgewars is free software (Open Source) we create in our spare time. If you've got problems, ask on our forums or visit our IRC room! - Hedgewars is free software (Open Source) we create in our spare time. If you like it, help us with a small donation or contribute your own work! - Hedgewars is free software (Open Source) we create in our spare time. Share it with your family and friends as you like! - Hedgewars is free software (Open Source) we create in our spare time, just for fun! Meet the devs in #hedgewars! - From time to time there will be official tournaments. Upcoming events will be announced at http://www.hedgewars.org/ some days in advance. - Hedgewars is available in many languages. If the translation in your language seems to be missing or outdated, feel free to contact us! - Hedgewars can be run on lots of different operating systems including Microsoft Windows, Mac OS X and GNU/Linux. - Always remember you're able to set up your own games in local and network/online play. You're not restricted to the 'Simple Game' option. - Connect one or more gamepads before starting the game to be able to assign their controls to your teams. - Create an account on http://www.hedgewars.org/ to keep others from using your most favourite nickname while playing on the official server. - While playing you should give yourself a short break at least once an hour. - If your graphics card isn't able to provide hardware accelerated OpenGL, try to enable the low quality mode to improve performance. - If your graphics card isn't able to provide hardware accelerated OpenGL, try to update the associated drivers. - We're open to suggestions and constructive feedback. If you don't like something or got a great idea, let us know! - Especially while playing online be polite and always remember there might be some minors playing with or against you as well! - Special game modes such as 'Vampirism' or 'Karma' allow you to develop completely new tactics. Try them in a custom game! - You should never install Hedgewars on computers you don't own (school, university, work, etc.). Please ask the responsible person instead! - Hedgewars can be perfect for short games during breaks. Just ensure you don't add too many hedgehogs or use an huge map. Reducing time and health might help as well. - No hedgehogs were harmed in making this game. - There are three different jumps available. Tap [high jump] twice to do a very high/backwards jump. - Afraid of falling off a cliff? Hold down [precise] to turn [left] or [right] without actually moving. - Some weapons require special strategies or just lots of training, so don't give up on a particular tool if you miss an enemy once. - Most weapons won't work once they touch the water. The Homing Bee as well as the Cake are exceptions to this. - The Old Limbuger only causes a small explosion. However the wind affected smelly cloud can poison lots of hogs at once. - The Piano Strike is the most damaging air strike. You'll lose the hedgehog performing it, so there's a huge downside as well. - The Homing Bee can be tricky to use. Its turn radius depends on its velocity, so try to not use full power. - Sticky Mines are a perfect tool to create small chain reactions knocking enemy hedgehogs into dire situations ... or water. - The Hammer is most effective when used on bridges or girders. Hit hogs will just break through the ground. - If you're stuck behind an enemy hedgehog, use the Hammer to free yourself without getting damaged by an explosion. - The Cake's maximum walking distance depends on the ground it has to pass. Use [attack] to detonate it early. - The Flame Thrower is a weapon but it can be used for tunnel digging as well. - Use the Molotov or Flame Thrower to temporary keep hedgehogs from passing terrain such as tunnels or platforms. - Want to know who's behind the game? Click on the Hedgewars logo in the main menu to see the credits. - Like Hedgewars? Become a fan on Facebook or follow us on Twitter - Feel free to draw your own graves, hats, flags or even maps and themes! But note that you'll have to share them somewhere to use them online. - Keep your video card drivers up to date to avoid issues playing the game. - Heads or tails? Type '/rnd' in lobby and you'll find out. Also '/rnd rock paper scissors' works! - You're able to associate Hedgewars related files (savegames and demo recordings) with the game to launch them right from your favorite file or internet browser. - - The version of Hedgewars supports Xfire. Make sure to add Hedgewars to its game list so your friends can see you playing. - You can find your Hedgewars configuration files under "My Documents\Hedgewars". Create backups or take the files with you, but don't edit them by hand. - - - You can find your Hedgewars configuration files under "Library/Application Support/Hedgewars" in your home directory. Create backups or take the files with you, but don't edit them by hand. - - - lintip - You can find your Hedgewars configuration files under ".hedgewars" in your home directory. Create backups or take the files with you, but don't edit them by hand. - - diff -r 31570b766315 -r ed5a6478e710 QTfrontend/sdlkeys.h --- a/QTfrontend/sdlkeys.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/sdlkeys.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ char sdlkeys[1024][2][128] = diff -r 31570b766315 -r ed5a6478e710 QTfrontend/team.cpp --- a/QTfrontend/team.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/team.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include @@ -291,6 +291,12 @@ return sl; } + +void HWTeam::setNetTeam(bool isNetTeam) +{ + m_isNetTeam = isNetTeam; +} + bool HWTeam::isNetTeam() const { return m_isNetTeam; @@ -444,3 +450,4 @@ { m_wins++; } + diff -r 31570b766315 -r ed5a6478e710 QTfrontend/team.h --- a/QTfrontend/team.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/team.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * Copyright (c) 2007 Igor Ulyanov * * This program is free software; you can redistribute it and/or modify @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TEAM_H @@ -39,6 +39,8 @@ QString Name; QString Hat; int Rounds, Kills, Deaths, Suicides; + + HWHog() : Rounds(0), Kills(0), Deaths(0), Suicides(0){} }; // class representing a team @@ -87,6 +89,7 @@ void setName(const QString & name); void setNumHedgehogs(unsigned char num); void setVoicepack(const QString & voicepack); + void setNetTeam(bool isNetTeam); // increments for statistical info void incRounds(); diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/dialog/ask_quit.cpp --- a/QTfrontend/ui/dialog/ask_quit.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/dialog/ask_quit.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/dialog/ask_quit.h --- a/QTfrontend/ui/dialog/ask_quit.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/dialog/ask_quit.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef ASK_QUIT_H diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/dialog/bandialog.cpp --- a/QTfrontend/ui/dialog/bandialog.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/dialog/bandialog.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -22,16 +22,19 @@ leReason = new QLineEdit(this); cbTime = new QComboBox(this); - cbTime->addItem(HWApplication::tr("%1 minutes", 0, 10).arg("10"), 5 * 60); - cbTime->addItem(HWApplication::tr("%1 minutes", 0, 30).arg("30"), 10 * 60); - cbTime->addItem(HWApplication::tr("%1 hour", 0, 10).arg("10"), 60 * 60); - cbTime->addItem(HWApplication::tr("%1 hours", 0, 3).arg("3"), 3 * 60 * 60); - cbTime->addItem(HWApplication::tr("%1 hours", 0, 5).arg("5"), 5 * 60 * 60); - cbTime->addItem(HWApplication::tr("%1 hours", 0, 12).arg("12"), 12 * 60 * 60); - cbTime->addItem(HWApplication::tr("%1 day", 0, 1).arg("1"), 24 * 60 * 60); - cbTime->addItem(HWApplication::tr("%1 days", 0, 3).arg("3"), 72 * 60 * 60); - cbTime->addItem(HWApplication::tr("%1 days", 0, 7).arg("7"), 168 * 60 * 60); - cbTime->addItem(HWApplication::tr("%1 days", 0, 14).arg("14"), 336 * 60 * 60); + const int min = 60; + const int hour = 60 * min; + const int day = 24 * hour; + cbTime->addItem(HWApplication::tr("%1 minutes", 0, 10).arg(10), 10 * min); + cbTime->addItem(HWApplication::tr("%1 minutes", 0, 30).arg(30), 30 * min); + cbTime->addItem(HWApplication::tr("%1 hour", 0, 1).arg(1), 1 * hour); + cbTime->addItem(HWApplication::tr("%1 hours", 0, 3).arg(3), 3 * hour); + cbTime->addItem(HWApplication::tr("%1 hours", 0, 5).arg(5), 5 * hour); + cbTime->addItem(HWApplication::tr("%1 hours", 0, 12).arg(12), 12 * hour); + cbTime->addItem(HWApplication::tr("%1 day", 0, 1).arg(1), 1 * day); + cbTime->addItem(HWApplication::tr("%1 days", 0, 3).arg(3), 3 * day); + cbTime->addItem(HWApplication::tr("%1 days", 0, 7).arg(7), 7 * day); + cbTime->addItem(HWApplication::tr("%1 days", 0, 14).arg(14), 14 * day); cbTime->addItem(tr("permanent"), 3650 * 24 * 60 * 60); cbTime->setCurrentIndex(0); diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/dialog/input_ip.cpp --- a/QTfrontend/ui/dialog/input_ip.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/dialog/input_ip.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/dialog/input_ip.h --- a/QTfrontend/ui/dialog/input_ip.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/dialog/input_ip.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/dialog/input_password.cpp --- a/QTfrontend/ui/dialog/input_password.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/dialog/input_password.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include @@ -56,7 +56,7 @@ layout->addWidget(cbSave, 5, 0); QDialogButtonBox* dbbButtons = new QDialogButtonBox(this); - pbNewAccount = dbbButtons->addButton(QString("New Account"), QDialogButtonBox::ActionRole); + pbNewAccount = dbbButtons->addButton(tr("New Account"), QDialogButtonBox::ActionRole); QPushButton * pbOK = dbbButtons->addButton(QDialogButtonBox::Ok); QPushButton * pbCancel = dbbButtons->addButton(QDialogButtonBox::Cancel); layout->addWidget(dbbButtons, 6, 0); diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/dialog/input_password.h --- a/QTfrontend/ui/dialog/input_password.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/dialog/input_password.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef INPUT_PASSWORD_H diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/dialog/upload_video.cpp --- a/QTfrontend/ui/dialog/upload_video.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/dialog/upload_video.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/dialog/upload_video.h --- a/QTfrontend/ui/dialog/upload_video.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/dialog/upload_video.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef UPLOAD_VIDEO_H diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/mouseoverfilter.cpp --- a/QTfrontend/ui/mouseoverfilter.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/mouseoverfilter.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -22,6 +22,8 @@ bool MouseOverFilter::eventFilter( QObject *dist, QEvent *event ) { + AbstractPage* abstractpage; + if (event->type() == QEvent::Enter) { QWidget * widget = dynamic_cast(dist); diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/mouseoverfilter.h --- a/QTfrontend/ui/mouseoverfilter.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/mouseoverfilter.h Tue Nov 10 20:43:13 2015 +0100 @@ -20,7 +20,6 @@ private: Ui_HWForm *ui; - AbstractPage* abstractpage; }; diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/page/AbstractPage.cpp --- a/QTfrontend/ui/page/AbstractPage.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/page/AbstractPage.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /** @@ -67,7 +67,7 @@ descLabel->setAlignment(Qt::AlignCenter); descLabel->setWordWrap(true); descLabel->setOpenExternalLinks(true); - descLabel->setFixedHeight(50); + descLabel->setFixedHeight(60); descLabel->setStyleSheet("font-size: 16px"); bottomLeftLayout->addWidget(descLabel); pageLayout->addWidget(descLabel, 1, 1); diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/page/AbstractPage.h --- a/QTfrontend/ui/page/AbstractPage.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/page/AbstractPage.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /** diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/page/pageadmin.cpp --- a/QTfrontend/ui/page/pageadmin.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/page/pageadmin.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/page/pageadmin.h --- a/QTfrontend/ui/page/pageadmin.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/page/pageadmin.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef PAGE_ADMIN_H diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/page/pagecampaign.cpp --- a/QTfrontend/ui/page/pagecampaign.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/page/pagecampaign.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include @@ -45,7 +45,7 @@ btnPreview = formattedButton(":/res/campaign/A_Classic_Fairytale/first_blood.png", true); infoLayout->setAlignment(btnPreview, Qt::AlignHCenter | Qt::AlignVCenter); - lbldescription = new QLabel(); + lbldescription = new QLabel(this); lbldescription->setAlignment(Qt::AlignHCenter| Qt::AlignTop); lbldescription->setWordWrap(true); diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/page/pagecampaign.h --- a/QTfrontend/ui/page/pagecampaign.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/page/pagecampaign.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef PAGE_CAMPAIGN_H diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/page/pageconnecting.cpp --- a/QTfrontend/ui/page/pageconnecting.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/page/pageconnecting.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/page/pageconnecting.h --- a/QTfrontend/ui/page/pageconnecting.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/page/pageconnecting.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef PAGE_CONNECTING_H diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/page/pagedata.cpp --- a/QTfrontend/ui/page/pagedata.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/page/pagedata.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include @@ -26,6 +26,7 @@ #include #include #include +#include #include "pagedata.h" #include "databrowser.h" @@ -48,10 +49,23 @@ return pageLayout; } +QLayout * PageDataDownload::footerLayoutDefinition() +{ + QHBoxLayout * bottomLayout = new QHBoxLayout(); + bottomLayout->setStretch(0, 1); + + pbOpenDir = addButton(tr("Open packages directory"), bottomLayout, 1, false); + + bottomLayout->setStretch(2, 1); + + return bottomLayout; +} + void PageDataDownload::connectSignals() { connect(web, SIGNAL(anchorClicked(QUrl)), this, SLOT(request(const QUrl&))); connect(this, SIGNAL(goBack()), this, SLOT(onPageLeave())); + connect(pbOpenDir, SIGNAL(clicked()), this, SLOT(openPackagesDir())); } PageDataDownload::PageDataDownload(QWidget* parent) : AbstractPage(parent) @@ -193,3 +207,9 @@ //DataManager::instance().reload(); } } + +void PageDataDownload::openPackagesDir() +{ + QString path = QDir::toNativeSeparators(cfgdir->absolutePath() + "/Data"); + QDesktopServices::openUrl(QUrl("file:///" + path)); +} diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/page/pagedata.h --- a/QTfrontend/ui/page/pagedata.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/page/pagedata.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef PAGE_DATA_H @@ -27,6 +27,7 @@ class QNetworkReply; class QVBoxLayout; + class PageDataDownload : public AbstractPage { Q_OBJECT @@ -39,12 +40,14 @@ protected: QLayout * bodyLayoutDefinition(); + QLayout * footerLayoutDefinition(); void connectSignals(); private: DataBrowser *web; QHash progressBars; QVBoxLayout *progressBarsLayout; + QPushButtonWithSound * pbOpenDir; bool m_contentDownloaded; ///< true if something was downloaded since last page leave @@ -54,6 +57,7 @@ void pageDownloaded(); void fileDownloaded(); void downloadProgress(qint64, qint64); + void openPackagesDir(); void onPageLeave(); }; diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/page/pagedrawmap.cpp --- a/QTfrontend/ui/page/pagedrawmap.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/page/pagedrawmap.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include @@ -44,11 +44,13 @@ rbPolyline->setChecked(true); pbClear = addButton(tr("Clear"), pageLayout, 5, 0); - pbLoad = addButton(tr("Load"), pageLayout, 6, 0); - pbSave = addButton(tr("Save"), pageLayout, 7, 0); + pbOptimize = addButton(tr("Optimize"), pageLayout, 6, 0); + pbOptimize->setVisible(false); + pbLoad = addButton(tr("Load"), pageLayout, 7, 0); + pbSave = addButton(tr("Save"), pageLayout, 8, 0); drawMapWidget = new DrawMapWidget(this); - pageLayout->addWidget(drawMapWidget, 0, 1, 9, 1); + pageLayout->addWidget(drawMapWidget, 0, 1, 10, 1); return pageLayout; } @@ -58,6 +60,7 @@ connect(cbEraser, SIGNAL(toggled(bool)), drawMapWidget, SLOT(setErasing(bool))); connect(pbUndo, SIGNAL(clicked()), drawMapWidget, SLOT(undo())); connect(pbClear, SIGNAL(clicked()), drawMapWidget, SLOT(clear())); + connect(pbOptimize, SIGNAL(clicked()), drawMapWidget, SLOT(optimize())); connect(pbLoad, SIGNAL(clicked()), this, SLOT(load())); connect(pbSave, SIGNAL(clicked()), this, SLOT(save())); diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/page/pagedrawmap.h --- a/QTfrontend/ui/page/pagedrawmap.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/page/pagedrawmap.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef PAGE_DRAWMAP_H @@ -42,6 +42,7 @@ QPushButton * pbClear; QPushButton * pbLoad; QPushButton * pbSave; + QPushButton * pbOptimize; QCheckBox * cbEraser; QRadioButton * rbPolyline; QRadioButton * rbRectangle; diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/page/pageeditteam.cpp --- a/QTfrontend/ui/page/pageeditteam.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/page/pageeditteam.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/page/pageeditteam.h --- a/QTfrontend/ui/page/pageeditteam.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/page/pageeditteam.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef PAGE_EDITTEAM_H diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/page/pagegamestats.cpp --- a/QTfrontend/ui/page/pagegamestats.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/page/pagegamestats.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include @@ -40,13 +40,13 @@ QLayout * PageGameStats::bodyLayoutDefinition() { - kindOfPoints = QString(""); - defaultGraphTitle = true; + kindOfPoints = QString(""); + defaultGraphTitle = true; QGridLayout * pageLayout = new QGridLayout(); pageLayout->setSpacing(20); pageLayout->setColumnStretch(0, 1); pageLayout->setColumnStretch(1, 1); - pageLayout->setRowStretch(0, 1); + pageLayout->setRowStretch(0, 1); pageLayout->setRowStretch(1, 20); //pageLayout->setRowStretch(1, -1); this should work but there is unnecessary empty space betwin lines if used pageLayout->setContentsMargins(7, 7, 7, 0); @@ -106,11 +106,11 @@ QLayout * PageGameStats::footerLayoutDefinition() { QHBoxLayout * bottomLayout = new QHBoxLayout(); - + mainNote = new QLabel(this); mainNote->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); mainNote->setWordWrap(true); - + bottomLayout->addWidget(mainNote, 0); bottomLayout->setStretch(0,1); @@ -159,41 +159,41 @@ void PageGameStats::renderStats() { - graphic->show(); - labelGraphTitle-> show(); - if(defaultGraphTitle) { - labelGraphTitle->setText("

" + PageGameStats::tr("Health graph") + "

"); - } else { - defaultGraphTitle = true; - } - // if not health data sent - if(healthPoints.size() == 0) { - labelGraphTitle->hide(); - graphic->hide(); - } else { - QGraphicsScene * scene = new QGraphicsScene(); + graphic->show(); + labelGraphTitle-> show(); + if(defaultGraphTitle) { + labelGraphTitle->setText("

" + PageGameStats::tr("Health graph") + "

"); + } else { + defaultGraphTitle = true; + } + // if not health data sent + if(healthPoints.size() == 0) { + labelGraphTitle->hide(); + graphic->hide(); + } else { + QGraphicsScene * scene = new QGraphicsScene(); - QMap >::const_iterator i = healthPoints.constBegin(); - while (i != healthPoints.constEnd()) - { - quint32 c = i.key(); - //QColor clanColor = QColor(qRgb((c >> 16) & 255, (c >> 8) & 255, c & 255)); - QVector hps = i.value(); + QMap >::const_iterator i = healthPoints.constBegin(); + while (i != healthPoints.constEnd()) + { + quint32 c = i.key(); + //QColor clanColor = QColor(qRgb((c >> 16) & 255, (c >> 8) & 255, c & 255)); + QVector hps = i.value(); - QPainterPath path; - if (hps.size()) - path.moveTo(0, hps[0]); + QPainterPath path; + if (hps.size()) + path.moveTo(0, hps[0]); - for(int t = 1; t < hps.size(); ++t) - path.lineTo(t, hps[t]); + for(int t = 1; t < hps.size(); ++t) + path.lineTo(t, hps[t]); - scene->addPath(path, QPen(c)); - ++i; - } + scene->addPath(path, QPen(c)); + ++i; + } - graphic->setScene(scene); - graphic->fitInView(graphic->sceneRect()); - } + graphic->setScene(scene); + graphic->fitInView(graphic->sceneRect()); + } } void PageGameStats::GameStats(char type, const QString & info) @@ -208,7 +208,8 @@ case 'D' : { int i = info.indexOf(' '); - QString message = "

" + PageGameStats::tr("The best shot award was won by %1 with %2 pts.").arg(info.mid(i + 1), info.left(i)) + "

"; + int num = info.left(i).toInt(); + QString message = "

" + PageGameStats::tr("The best shot award was won by %1 with %2 pts.", "", num).arg(info.mid(i + 1), info.left(i)) + "

"; AddStatText(message); break; } @@ -237,9 +238,9 @@ } case 'g' : { - // TODO: change default picture or add change pic capability - defaultGraphTitle = false; - labelGraphTitle->setText("

" + info + "

"); + // TODO: change default picture or add change pic capability + defaultGraphTitle = false; + labelGraphTitle->setText("

" + info + "

"); break; } case 'T': // local team stats @@ -257,7 +258,7 @@ } break; } - case 'p' : + case 'p' : { kindOfPoints = info; break; @@ -300,11 +301,11 @@ QString message; QString killstring; if(kindOfPoints.compare("") == 0) { - killstring = PageGameStats::tr("(%1 kill)", "", kills).arg(kills); - } else { - killstring = PageGameStats::tr("(%1 %2)", "", kills).arg(kills).arg(kindOfPoints); - kindOfPoints = QString(""); - } + killstring = PageGameStats::tr("(%1 kill)", "", kills).arg(kills); + } else { + killstring = PageGameStats::tr("(%1 %2)", "", kills).arg(kills).arg(kindOfPoints); + kindOfPoints = QString(""); + } message = QString("

%1 %2. %3 ").arg(image, QString::number(playerPosition), playername, clanColor.name()) + killstring + "

"; diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/page/pagegamestats.h --- a/QTfrontend/ui/page/pagegamestats.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/page/pagegamestats.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef STATSPAGE_H diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/page/pageinfo.cpp --- a/QTfrontend/ui/page/pageinfo.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/page/pageinfo.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/page/pageinfo.h --- a/QTfrontend/ui/page/pageinfo.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/page/pageinfo.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef PAGE_INFO_H diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/page/pageingame.cpp --- a/QTfrontend/ui/page/pageingame.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/page/pageingame.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/page/pageingame.h --- a/QTfrontend/ui/page/pageingame.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/page/pageingame.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef PAGE_INGAME_H diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/page/pagemain.cpp --- a/QTfrontend/ui/page/pagemain.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/page/pagemain.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include @@ -21,10 +21,12 @@ #include #include #include +#include #include "pagemain.h" #include "hwconsts.h" #include "hwform.h" +#include "DataManager.h" QLayout * PageMain::bodyLayoutDefinition() { @@ -119,6 +121,9 @@ void PageMain::connectSignals() { +#ifndef QT_DEBUG + connect(this, SIGNAL(pageEnter()), this, SLOT(updateTip())); +#endif connect(BtnNet, SIGNAL(clicked()), this, SLOT(toggleNetworkChoice())); //connect(BtnNetLocal, SIGNAL(clicked()), this, SLOT(toggleNetworkChoice())); //connect(BtnNetOfficial, SIGNAL(clicked()), this, SLOT(toggleNetworkChoice())); @@ -132,16 +137,19 @@ if(frontendEffects) setAttribute(Qt::WA_NoSystemBackground, true); mainNote->setOpenExternalLinks(true); - #ifdef QT_DEBUG setDefaultDescription(QLabel::tr("This development build is 'work in progress' and may not be compatible with other versions of the game, while some features might be broken or incomplete!")); #else setDefaultDescription(QLabel::tr("Tip: %1").arg(randomTip())); #endif - } -QString PageMain::randomTip() const +void PageMain::updateTip() +{ + setDefaultDescription(QLabel::tr("Tip: %1").arg(randomTip())); +} + +QString PageMain::randomTip() { #ifdef _WIN32 int platform = 1; @@ -150,35 +158,62 @@ #else int platform = 3; #endif - QStringList Tips; - QFile file(":/res/xml/tips.xml"); - file.open(QIODevice::ReadOnly); - QTextStream in(&file); - QString line = in.readLine(); - int tip_platform = 0; - while (!line.isNull()) { - if(line.contains("", Qt::CaseSensitive)) - tip_platform = 1; - if(line.contains("", Qt::CaseSensitive)) - tip_platform = 2; - if(line.contains("", Qt::CaseSensitive)) - tip_platform = 3; - if(line.contains("", Qt::CaseSensitive) || - line.contains("", Qt::CaseSensitive) || - line.contains("", Qt::CaseSensitive)) { - tip_platform = 0; + if(!Tips.length()) + { + DataManager & dataMgr = DataManager::instance(); + + // get locale + QSettings settings(dataMgr.settingsFileName(), + QSettings::IniFormat); + + QString loc = settings.value("misc/locale", "").toString(); + if (loc.isEmpty()) + loc = QLocale::system().name(); + + QString tipFile = QString("physfs://Locale/tips_" + loc + ".xml"); + + // if file is non-existant try with language only + if (!QFile::exists(tipFile)) + tipFile = QString("physfs://Locale/tips_" + loc.remove(QRegExp("_.*$")) + ".xml"); + + // fallback if file for current locale is non-existant + if (!QFile::exists(tipFile)) + tipFile = QString("physfs://Locale/tips_en.xml"); + + QFile file(tipFile); + file.open(QIODevice::ReadOnly); + QTextStream in(&file); + in.setCodec("UTF-8"); + QString line = in.readLine(); + int tip_platform = 0; + while (!line.isNull()) { + if(line.contains("", Qt::CaseSensitive)) + tip_platform = 1; + if(line.contains("", Qt::CaseSensitive)) + tip_platform = 2; + if(line.contains("", Qt::CaseSensitive)) + tip_platform = 3; + if(line.contains("", Qt::CaseSensitive) || + line.contains("", Qt::CaseSensitive) || + line.contains("", Qt::CaseSensitive)) { + tip_platform = 0; + } + QStringList split_string = line.split(QRegExp("")); + if((tip_platform == platform || tip_platform == 0) && split_string.size() != 1) + Tips << split_string[1]; + line = in.readLine(); } - QStringList split_string = line.split(QRegExp("")); - if((tip_platform == platform || tip_platform == 0) && split_string.size() != 1) - Tips << tr(split_string[1].toLatin1().data(), "Tips"); - line = in.readLine(); + // The following tip will require links to app store entries first. + //Tips << tr("Want to play Hedgewars any time? Grab the Mobile version for %1 and %2.", "Tips").arg("").arg(""); + // the ios version is located here: http://itunes.apple.com/us/app/hedgewars/id391234866 + + file.close(); } - // The following tip will require links to app store entries first. - //Tips << tr("Want to play Hedgewars any time? Grab the Mobile version for %1 and %2.", "Tips").arg("").arg(""); - // the ios version is located here: http://itunes.apple.com/us/app/hedgewars/id391234866 - file.close(); - return Tips[QTime(0, 0, 0).secsTo(QTime::currentTime()) % Tips.length()]; + if(Tips.length()) + return Tips[QTime(0, 0, 0).secsTo(QTime::currentTime()) % Tips.length()]; + else + return QString(); } void PageMain::toggleNetworkChoice() diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/page/pagemain.h --- a/QTfrontend/ui/page/pagemain.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/page/pagemain.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef PAGE_MAIN_H @@ -48,10 +48,12 @@ void connectSignals(); QIcon originalNetworkIcon, disabledNetworkIcon; - QString randomTip() const; + QString randomTip(); + QStringList Tips; private slots: void toggleNetworkChoice(); + void updateTip(); }; #endif diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/page/pagemultiplayer.cpp --- a/QTfrontend/ui/page/pagemultiplayer.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/page/pagemultiplayer.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /** diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/page/pagemultiplayer.h --- a/QTfrontend/ui/page/pagemultiplayer.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/page/pagemultiplayer.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef PAGE_MULTIPLAYER_H diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/page/pagenet.cpp --- a/QTfrontend/ui/page/pagenet.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/page/pagenet.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/page/pagenet.h --- a/QTfrontend/ui/page/pagenet.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/page/pagenet.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef PAGE_NET_H diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/page/pagenetgame.cpp --- a/QTfrontend/ui/page/pagenetgame.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/page/pagenetgame.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/page/pagenetgame.h --- a/QTfrontend/ui/page/pagenetgame.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/page/pagenetgame.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef PAGE_NETGAME_H diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/page/pagenetserver.cpp --- a/QTfrontend/ui/page/pagenetserver.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/page/pagenetserver.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include @@ -124,7 +124,7 @@ // This function assumes that the user wants to share his server while connected to // the Internet and that he/she is using direct access (eg no NATs). To determine the -// IP we briefly connect to Hedgewars website and fallback to user intervention +// IP we briefly connect to Hedgewars website and fallback to user intervention // after 4 seconds of timeout. void PageNetServer::copyUrl() { diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/page/pagenetserver.h --- a/QTfrontend/ui/page/pagenetserver.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/page/pagenetserver.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef PAGE_NETSERVER_H diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/page/pageoptions.cpp --- a/QTfrontend/ui/page/pageoptions.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/page/pageoptions.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include @@ -397,7 +397,7 @@ tagsLayout->addWidget(CBHogTag, 0); tagsLayout->addWidget(CBHealthTag, 0); tagsLayout->addWidget(CBTagOpacity, 0); - tagsLayout->addStretch(1); + tagsLayout->addStretch(1); } { // group: frontend diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/page/pageoptions.h --- a/QTfrontend/ui/page/pageoptions.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/page/pageoptions.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef PAGE_OPTIONS_H diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/page/pageplayrecord.cpp --- a/QTfrontend/ui/page/pageplayrecord.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/page/pageplayrecord.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "pageplayrecord.h" diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/page/pageplayrecord.h --- a/QTfrontend/ui/page/pageplayrecord.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/page/pageplayrecord.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef PLAYRECORDPAGE_H diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/page/pageroomslist.cpp --- a/QTfrontend/ui/page/pageroomslist.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/page/pageroomslist.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include @@ -53,6 +53,8 @@ QLayout * PageRoomsList::bodyLayoutDefinition() { + // TODO move stylesheet stuff into css/qt.css + QVBoxLayout * pageLayout = new QVBoxLayout(); pageLayout->setSpacing(0); @@ -60,10 +62,37 @@ topLayout->setSpacing(0); pageLayout->addLayout(topLayout, 0); + // State button + + QPushButton * btnState = new QPushButton(tr("Room state")); + btnState->setStyleSheet("QPushButton { background-color: #F6CB1C; border-color: #F6CB1C; color: #130F2A; padding: 1px 3px 3px 3px; margin: 0px; border-bottom: none; border-radius: 0px; border-top-left-radius: 10px; } QPushButton:hover { background-color: #FFEB3C; border-color: #F6CB1C; color: #000000 } QPushButton:pressed { background-color: #FFEB3C; border-color: #F6CB1C; color: #000000; }"); + btnState->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); + + // State menu + + QMenu * stateMenu = new QMenu(btnState); + showGamesInLobby = new QAction(QAction::tr("Show games in lobby"), stateMenu); + showGamesInLobby->setCheckable(true); + showGamesInLobby->setChecked(true); + showGamesInProgress = new QAction(QAction::tr("Show games in-progress"), stateMenu); + showGamesInProgress->setCheckable(true); + showGamesInProgress->setChecked(true); + showPassword = new QAction(QAction::tr("Show password protected"), stateMenu); + showPassword->setCheckable(true); + showPassword->setChecked(true); + showJoinRestricted = new QAction(QAction::tr("Show join restricted"), stateMenu); + showJoinRestricted->setCheckable(true); + showJoinRestricted->setChecked(true); + stateMenu->addAction(showGamesInLobby); + stateMenu->addAction(showGamesInProgress); + stateMenu->addAction(showPassword); + stateMenu->addAction(showJoinRestricted); + btnState->setMenu(stateMenu); + // Help/prompt message at top QLabel * lblDesc = new QLabel(tr("Search for a room:")); lblDesc->setObjectName("lblDesc"); - lblDesc->setStyleSheet("#lblDesc { color: #130F2A; background: #F6CB1C; border: solid 4px #F6CB1C; border-top-left-radius: 10px; padding: 4px 10px;}"); + lblDesc->setStyleSheet("#lblDesc { color: #130F2A; background: #F6CB1C; border: solid 4px #F6CB1C; padding: 5px 10px 3px 6px;}"); lblDesc->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); lblDesc->setFixedHeight(24); lblDesc->setMinimumWidth(0); @@ -97,16 +126,17 @@ BtnJoin->setEnabled(false); // Add widgets to top layout - topLayout->addWidget(lblDesc, 1, 0); - topLayout->addWidget(searchContainer, 1, 1); - topLayout->addWidget(corner, 1, 2, Qt::AlignBottom); - topLayout->addWidget(BtnCreate, 0, 4, 2, 1); - topLayout->addWidget(BtnJoin, 0, 5, 2, 1); + topLayout->addWidget(btnState, 1, 0); + topLayout->addWidget(lblDesc, 1, 1); + topLayout->addWidget(searchContainer, 1, 2); + topLayout->addWidget(corner, 1, 3, Qt::AlignBottom); + topLayout->addWidget(BtnCreate, 0, 5, 2, 1); + topLayout->addWidget(BtnJoin, 0, 6, 2, 1); // Top layout stretch topLayout->setRowStretch(0, 1); topLayout->setRowStretch(1, 0); - topLayout->setColumnStretch(3, 1); + topLayout->setColumnStretch(4, 1); // Rooms list and chat with splitter m_splitter = new QSplitter(); @@ -132,43 +162,6 @@ roomsList->setFocusPolicy(Qt::NoFocus); roomsLayout->addWidget(roomsList, 200); - // Room filters container - - QWidget * filtersContainer = new QWidget(); - filtersContainer->setMaximumWidth(800); - filtersContainer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); - - roomsLayout->addSpacing(7); - roomsLayout->addWidget(filtersContainer, 0, Qt::AlignHCenter); - roomsLayout->addSpacing(7); - - QHBoxLayout * filterLayout = new QHBoxLayout(filtersContainer); - filterLayout->setSpacing(0); - filterLayout->setMargin(0); - - const int filterSpacing = 20; - - // State button - - QPushButton * btnState = new QPushButton(tr("Room state")); - btnState->setStyleSheet("QPushButton { padding: 2px 4px; } QPushButton:pressed { background-color: #ffcc00; border-color: #ffcc00; border-bottom-left-radius: 0px; border-bottom-right-radius: 0px; color: #11084A; }"); - btnState->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); - filterLayout->addWidget(btnState); - filterLayout->addSpacing(filterSpacing); - - // State menu - - QMenu * stateMenu = new QMenu(btnState); - showGamesInLobby = new QAction(QAction::tr("Show games in lobby"), stateMenu); - showGamesInLobby->setCheckable(true); - showGamesInLobby->setChecked(true); - showGamesInProgress = new QAction(QAction::tr("Show games in-progress"), stateMenu); - showGamesInProgress->setCheckable(true); - showGamesInProgress->setChecked(true); - stateMenu->addAction(showGamesInLobby); - stateMenu->addAction(showGamesInProgress); - btnState->setMenu(stateMenu); - // Lobby chat chatWidget = new HWChatWidget(this, false); @@ -201,6 +194,8 @@ connect(roomsList, SIGNAL(clicked (const QModelIndex &)), searchText, SLOT(setFocus())); connect(showGamesInLobby, SIGNAL(triggered()), this, SLOT(onFilterChanged())); connect(showGamesInProgress, SIGNAL(triggered()), this, SLOT(onFilterChanged())); + connect(showPassword, SIGNAL(triggered()), this, SLOT(onFilterChanged())); + connect(showJoinRestricted, SIGNAL(triggered()), this, SLOT(onFilterChanged())); connect(searchText, SIGNAL(textChanged (const QString &)), this, SLOT(onFilterChanged())); connect(this, SIGNAL(askJoinConfirmation (const QString &)), this, SLOT(onJoinConfirmation(const QString &)), Qt::QueuedConnection); @@ -645,13 +640,29 @@ bool stateLobby = showGamesInLobby->isChecked(); bool stateProgress = showGamesInProgress->isChecked(); + bool statePassword = showPassword->isChecked(); + bool stateJoinRestricted = showJoinRestricted->isChecked(); - if (stateLobby && stateProgress) - stateFilteredModel->setFilterFixedString(QString()); // "any" - else if (stateLobby != stateProgress) - stateFilteredModel->setFilterFixedString(QString(stateProgress)); + QString filter; + if (!stateLobby && !stateProgress) + filter = "O_o"; + else if (stateLobby && stateProgress && statePassword && stateJoinRestricted) + filter = ""; else - stateFilteredModel->setFilterFixedString(QString("none")); // Basically, none. + { + QString exclude = "[^"; + if (!stateProgress) exclude += "g"; + if (!statePassword) exclude += "p"; + if (!stateJoinRestricted) exclude += "j"; + exclude += "]*"; + if (stateProgress && statePassword && stateJoinRestricted) exclude = ".*"; + filter = "^" + exclude; + if (!stateLobby) filter += "g" + exclude; + filter += "$"; + } + //qDebug() << filter; + + stateFilteredModel->setFilterRegExp(filter); } void PageRoomsList::setSettings(QSettings *settings) diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/page/pageroomslist.h --- a/QTfrontend/ui/page/pageroomslist.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/page/pageroomslist.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef PAGE_ROOMLIST_H @@ -96,6 +96,8 @@ QSortFilterProxyModel * stateFilteredModel; QAction * showGamesInLobby; QAction * showGamesInProgress; + QAction * showPassword; + QAction * showJoinRestricted; QSplitter * m_splitter; AmmoSchemeModel * ammoSchemeModel; diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/page/pagescheme.cpp --- a/QTfrontend/ui/page/pagescheme.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/page/pagescheme.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include @@ -335,7 +335,7 @@ l->setPixmap(QPixmap(":/res/iconMine.png")); // TODO: icon glBSLayout->addWidget(l,11,1,1,1); SB_Mines = new QSpinBox(gbBasicSettings); - SB_Mines->setRange(0, 80); + SB_Mines->setRange(0, 200); SB_Mines->setValue(0); SB_Mines->setSingleStep(5); glBSLayout->addWidget(SB_Mines,11,2,1,1); @@ -363,40 +363,69 @@ l->setPixmap(QPixmap(":/res/iconDamage.png")); glBSLayout->addWidget(l,13,1,1,1); SB_Explosives = new QSpinBox(gbBasicSettings); - SB_Explosives->setRange(0, 40); + SB_Explosives->setRange(0, 200); SB_Explosives->setValue(0); - SB_Explosives->setSingleStep(1); + SB_Explosives->setSingleStep(3); glBSLayout->addWidget(SB_Explosives,13,2,1,1); l = new QLabel(gbBasicSettings); - l->setText(QLabel::tr("% Get Away Time")); + l->setText(QLabel::tr("Air Mines")); l->setWordWrap(true); glBSLayout->addWidget(l,14,0,1,1); l = new QLabel(gbBasicSettings); l->setFixedSize(32,32); + l->setPixmap(QPixmap(":/res/iconMine.png")); // TODO: icon + glBSLayout->addWidget(l,14,1,1,1); + SB_AirMines = new QSpinBox(gbBasicSettings); + SB_AirMines->setRange(0, 200); + SB_AirMines->setValue(0); + SB_AirMines->setSingleStep(5); + glBSLayout->addWidget(SB_AirMines,14,2,1,1); + + l = new QLabel(gbBasicSettings); + l->setText(QLabel::tr("% Get Away Time")); + l->setWordWrap(true); + glBSLayout->addWidget(l,15,0,1,1); + l = new QLabel(gbBasicSettings); + l->setFixedSize(32,32); l->setPixmap(QPixmap(":/res/iconTime.png")); - glBSLayout->addWidget(l,14,1,1,1); + glBSLayout->addWidget(l,15,1,1,1); SB_GetAwayTime = new QSpinBox(gbBasicSettings); SB_GetAwayTime->setRange(0, 999); SB_GetAwayTime->setValue(100); SB_GetAwayTime->setSingleStep(25); - glBSLayout->addWidget(SB_GetAwayTime,14,2,1,1); + glBSLayout->addWidget(SB_GetAwayTime,15,2,1,1); l = new QLabel(gbBasicSettings); l->setText(QLabel::tr("World Edge")); l->setWordWrap(true); - glBSLayout->addWidget(l,15,0,1,1); + glBSLayout->addWidget(l,16,0,1,1); l = new QLabel(gbBasicSettings); l->setFixedSize(32,32); l->setPixmap(QPixmap(":/res/iconEarth.png")); - glBSLayout->addWidget(l,15,1,1,1); + glBSLayout->addWidget(l,16,1,1,1); + CB_WorldEdge = new QComboBox(gbBasicSettings); CB_WorldEdge->insertItem(0, tr("None (Default)")); CB_WorldEdge->insertItem(1, tr("Wrap (World wraps)")); CB_WorldEdge->insertItem(2, tr("Bounce (Edges reflect)")); CB_WorldEdge->insertItem(3, tr("Sea (Edges connect to sea)")); /* CB_WorldEdge->insertItem(4, tr("Skybox")); */ - glBSLayout->addWidget(CB_WorldEdge,15,2,1,1); + glBSLayout->addWidget(CB_WorldEdge,16,2,1,1); + + + l = new QLabel(gbBasicSettings); + l->setText(QLabel::tr("Script parameter")); + l->setWordWrap(true); + glBSLayout->addWidget(l,17,0,1,1); + l = new QLabel(gbBasicSettings); + l->setFixedSize(32,32); + l->setPixmap(QPixmap(":/res/iconBox.png")); + glBSLayout->addWidget(l,17,1,1,1); + + LE_ScriptParam = new QLineEdit(gbBasicSettings); + LE_ScriptParam->setMaxLength(240); + glBSLayout->addWidget(LE_ScriptParam,17,2,1,1); l = new QLabel(gbBasicSettings); @@ -482,13 +511,15 @@ mapper->addMapping(SB_Mines, 32); mapper->addMapping(SB_MineDuds, 33); mapper->addMapping(SB_Explosives, 34); - mapper->addMapping(SB_HealthCrates, 35); - mapper->addMapping(SB_CrateHealth, 36); - mapper->addMapping(SB_WaterRise, 37); - mapper->addMapping(SB_HealthDecrease, 38); - mapper->addMapping(SB_RopeModifier, 39); - mapper->addMapping(SB_GetAwayTime, 40); - mapper->addMapping(CB_WorldEdge, 41, "currentIndex"); + mapper->addMapping(SB_AirMines, 35); + mapper->addMapping(SB_HealthCrates, 36); + mapper->addMapping(SB_CrateHealth, 37); + mapper->addMapping(SB_WaterRise, 38); + mapper->addMapping(SB_HealthDecrease, 39); + mapper->addMapping(SB_RopeModifier, 40); + mapper->addMapping(SB_GetAwayTime, 41); + mapper->addMapping(CB_WorldEdge, 42, "currentIndex"); + mapper->addMapping(LE_ScriptParam, 43); mapper->toFirst(); } diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/page/pagescheme.h --- a/QTfrontend/ui/page/pagescheme.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/page/pagescheme.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef PAGE_SCHEME_H @@ -87,12 +87,14 @@ QSpinBox * SB_CrateHealth; QSpinBox * SB_MinesTime; QSpinBox * SB_Mines; + QSpinBox * SB_AirMines; QSpinBox * SB_MineDuds; QSpinBox * SB_Explosives; QSpinBox * SB_RopeModifier; QSpinBox * SB_GetAwayTime; QComboBox * CB_WorldEdge; QLineEdit * LE_name; + QLineEdit * LE_ScriptParam; QGroupBox * gbGameModes; QGroupBox * gbBasicSettings; diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/page/pageselectweapon.cpp --- a/QTfrontend/ui/page/pageselectweapon.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/page/pageselectweapon.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/page/pageselectweapon.h --- a/QTfrontend/ui/page/pageselectweapon.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/page/pageselectweapon.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef PAGE_SELECTWEAPON_H diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/page/pagesingleplayer.cpp --- a/QTfrontend/ui/page/pagesingleplayer.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/page/pagesingleplayer.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/page/pagesingleplayer.h --- a/QTfrontend/ui/page/pagesingleplayer.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/page/pagesingleplayer.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef PAGE_SINGLE_PLAYER_H diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/page/pagetraining.cpp --- a/QTfrontend/ui/page/pagetraining.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/page/pagetraining.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/page/pagetraining.h --- a/QTfrontend/ui/page/pagetraining.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/page/pagetraining.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef PAGE_TRAINING_H diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/page/pagevideos.cpp --- a/QTfrontend/ui/page/pagevideos.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/page/pagevideos.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include @@ -99,6 +99,7 @@ pUploading = NULL; lastSizeUpdate = 0; progress = 0; + seen = false; } VideoItem::~VideoItem() diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/page/pagevideos.h --- a/QTfrontend/ui/page/pagevideos.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/page/pagevideos.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/FreqSpinBox.cpp --- a/QTfrontend/ui/widget/FreqSpinBox.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/FreqSpinBox.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /** diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/FreqSpinBox.h --- a/QTfrontend/ui/widget/FreqSpinBox.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/FreqSpinBox.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /** diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/HistoryLineEdit.cpp --- a/QTfrontend/ui/widget/HistoryLineEdit.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/HistoryLineEdit.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,7 +1,7 @@ /* * Hedgewars, a free turn based strategy game * Copyright (c) 2006-2007 Igor Ulyanov - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /** diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/HistoryLineEdit.h --- a/QTfrontend/ui/widget/HistoryLineEdit.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/HistoryLineEdit.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,7 +1,7 @@ /* * Hedgewars, a free turn based strategy game * Copyright (c) 2006-2007 Igor Ulyanov - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /** diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/SmartLineEdit.cpp --- a/QTfrontend/ui/widget/SmartLineEdit.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/SmartLineEdit.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,7 +1,7 @@ /* * Hedgewars, a free turn based strategy game * Copyright (c) 2006-2007 Igor Ulyanov - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /** diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/SmartLineEdit.h --- a/QTfrontend/ui/widget/SmartLineEdit.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/SmartLineEdit.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,7 +1,7 @@ /* * Hedgewars, a free turn based strategy game * Copyright (c) 2006-2007 Igor Ulyanov - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /** diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/SquareLabel.cpp --- a/QTfrontend/ui/widget/SquareLabel.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/SquareLabel.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/SquareLabel.h --- a/QTfrontend/ui/widget/SquareLabel.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/SquareLabel.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _SQUARELABEL_H diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/about.cpp --- a/QTfrontend/ui/widget/about.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/about.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include @@ -35,7 +35,9 @@ #ifdef VIDEOREC extern "C" { -#include "libavutil/avutil.h" + #include "libavcodec/version.h" + #include "libavformat/version.h" + #include "libavutil/avutil.h" // version.h only from 51.36.0 } #endif @@ -166,7 +168,15 @@ libinfo.append(QString("Qt version: %1
").arg(QT_VERSION_STR)); #ifdef VIDEOREC - libinfo.append(QString("Libav version: %1.%2.%3
") + libinfo.append(QString("libavcodec version: %1.%2.%3
") + .arg(LIBAVCODEC_VERSION_MAJOR) + .arg(LIBAVCODEC_VERSION_MINOR) + .arg(LIBAVCODEC_VERSION_MICRO)); + libinfo.append(QString("libavformat version: %1.%2.%3
") + .arg(LIBAVFORMAT_VERSION_MAJOR) + .arg(LIBAVFORMAT_VERSION_MINOR) + .arg(LIBAVFORMAT_VERSION_MICRO)); + libinfo.append(QString("libavutil version: %1.%2.%3
") .arg(LIBAVUTIL_VERSION_MAJOR) .arg(LIBAVUTIL_VERSION_MINOR) .arg(LIBAVUTIL_VERSION_MICRO)); diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/about.h --- a/QTfrontend/ui/widget/about.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/about.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _ABOUT_H diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/bgwidget.cpp --- a/QTfrontend/ui/widget/bgwidget.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/bgwidget.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,7 +1,7 @@ /* * Hedgewars, a free turn based strategy game * Copyright (c) 2009 Kristian Lehmann - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "bgwidget.h" diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/bgwidget.h --- a/QTfrontend/ui/widget/bgwidget.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/bgwidget.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,7 +1,7 @@ /* * Hedgewars, a free turn based strategy game * Copyright (c) 2009 Kristian Lehmann - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef BGWIDGET_H diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/chatwidget.cpp --- a/QTfrontend/ui/widget/chatwidget.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/chatwidget.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,7 +1,7 @@ /* * Hedgewars, a free turn based strategy game * Copyright (c) 2007 Igor Ulyanov - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include @@ -179,9 +179,14 @@ this->gameSettings = NULL; this->notify = notify; + m_usersModel = NULL; + m_isAdmin = false; m_autoKickEnabled = false; + m_scrollToBottom = false; + m_scrollBarPos = 0; + QStringList vpList = QStringList() << "Classic" << "Default" << "Mobster" << "Russian"; @@ -406,26 +411,27 @@ void HWChatWidget::printChatString( const QString & nick, const QString & str, const QString & cssClassPart, bool highlight) { - QSortFilterProxyModel * playersSortFilterModel = qobject_cast(chatNicks->model()); - if(!playersSortFilterModel) - return; - - PlayersListModel * players = qobject_cast(playersSortFilterModel->sourceModel()); - - if(!players) + if(!m_usersModel) return; // don't show chat lines that are from ignored nicks - if (players->isFlagSet(nick, PlayersListModel::Ignore)) + if (m_usersModel->isFlagSet(nick, PlayersListModel::Ignore)) return; - bool isFriend = (!nick.isEmpty()) && players->isFlagSet(nick, PlayersListModel::Friend); + bool isFriend = (!nick.isEmpty()) && m_usersModel->isFlagSet(nick, PlayersListModel::Friend); QString cssClass = (isFriend ? "msg_Friend" : "msg_User") + cssClassPart; addLine(cssClass, str, highlight); } +bool HWChatWidget::isInGame() { + if (!m_usersModel) + return false; + + return m_usersModel->isFlagSet(m_userNick, PlayersListModel::InGame); +} + void HWChatWidget::addLine(const QString & cssClass, QString line, bool isHighlight) { if (s_displayNone->contains(cssClass)) @@ -449,7 +455,8 @@ { line = QString("%1").arg(line); SDLInteraction::instance().playSoundFile(m_hilightSound); - HWApplication::alert(this, 800); + if (!isInGame()) + HWApplication::alert(this, 800); } chatStrings.append(line); @@ -544,7 +551,8 @@ QString hlRegExp("^(.* )?%1[^-a-z0-9_]*( .*)?$"); QRegExp whitespace("\\s"); - m_highlights.append(QRegExp(hlRegExp.arg(m_userNick.toLower()))); + if (!m_userNick.isEmpty()) + m_highlights.append(QRegExp(hlRegExp.arg(QRegExp::escape(m_userNick.toLower())))); QFile file(cfgdir->absolutePath() + "/" + m_userNick.toLower() + "_highlight.txt"); @@ -589,9 +597,10 @@ { addLine("msg_PlayerInfo", QString(" >>> %1 - %2 %3 %4") .arg(linkedNick(nick)) - .arg(ip) - .arg(version) - .arg(roomInfo)); + .arg(Qt::escape(ip == "[]"?"":ip)) + .arg(Qt::escape(version)) + .arg(Qt::escape(roomInfo)) + ); } void HWChatWidget::onKick() @@ -717,14 +726,14 @@ void HWChatWidget::adminAccess(bool b) { chatNicks->removeAction(acKick); - chatNicks->removeAction(acBan); + //chatNicks->removeAction(acBan); m_isAdmin = b; if(b) { chatNicks->insertAction(0, acKick); - chatNicks->insertAction(0, acBan); + //chatNicks->insertAction(0, acBan); } } @@ -848,6 +857,12 @@ chatNicks->setModel(model); chatNicks->setModelColumn(0); + + QSortFilterProxyModel * sfpModel = qobject_cast(model); + if (sfpModel) + m_usersModel = qobject_cast(sfpModel->sourceModel()); + else + m_usersModel = qobject_cast(model); } void HWChatWidget::nicksContextMenuRequested(const QPoint &pos) diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/chatwidget.h --- a/QTfrontend/ui/widget/chatwidget.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/chatwidget.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,7 +1,7 @@ /* * Hedgewars, a free turn based strategy game * Copyright (c) 2007 Igor Ulyanov - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _CHAT_WIDGET_INCLUDED @@ -32,6 +32,7 @@ #include "SDLInteraction.h" #include "SmartLineEdit.h" +#include "playerslistmodel.h" class QTextBrowser; class QLineEdit; @@ -87,6 +88,7 @@ QString linkedNick(const QString & nickname); void beforeContentAdd(); void afterContentAdd(); + bool isInGame(); /** * @brief Checks whether the message contains a highlight. @@ -132,6 +134,7 @@ void consoleCommand(const QString & command); private: + PlayersListModel* m_usersModel; bool m_isAdmin; QHBoxLayout mainLayout; QTextBrowser* chatText; diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/databrowser.cpp --- a/QTfrontend/ui/widget/databrowser.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/databrowser.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /** diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/databrowser.h --- a/QTfrontend/ui/widget/databrowser.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/databrowser.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /** diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/drawmapwidget.cpp --- a/QTfrontend/ui/widget/drawmapwidget.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/drawmapwidget.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include @@ -118,6 +118,11 @@ if(m_scene) m_scene->clearMap(); } +void DrawMapWidget::optimize() +{ + if(m_scene) m_scene->optimize(); +} + void DrawMapWidget::setErasing(bool erasing) { if(m_scene) m_scene->setErasing(erasing); diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/drawmapwidget.h --- a/QTfrontend/ui/widget/drawmapwidget.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/drawmapwidget.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef DRAWMAPWIDGET_H @@ -97,6 +97,7 @@ public slots: void undo(); void clear(); + void optimize(); void setErasing(bool erasing); void save(const QString & fileName); void load(const QString & fileName); diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/feedbackdialog.cpp --- a/QTfrontend/ui/widget/feedbackdialog.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/feedbackdialog.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include @@ -268,7 +268,7 @@ number_of_cores += QString::number(sysconf(_SC_NPROCESSORS_ONLN)) + "\n"; quint32 pages = sysconf(_SC_PHYS_PAGES); quint32 page_size = sysconf(_SC_PAGE_SIZE); - quint32 total = pages * page_size / 1024 / 1024; + quint64 total = (quint64)pages * page_size / 1024 / 1024; total_ram += QString::number(total) + " MB\n"; os_version += "GNU/Linux or BSD\n"; #endif diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/feedbackdialog.h --- a/QTfrontend/ui/widget/feedbackdialog.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/feedbackdialog.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef FEEDBACKDIALOG_H diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/fpsedit.cpp --- a/QTfrontend/ui/widget/fpsedit.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/fpsedit.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "fpsedit.h" diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/fpsedit.h --- a/QTfrontend/ui/widget/fpsedit.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/fpsedit.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _FPSEDIT_H diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/frameTeam.cpp --- a/QTfrontend/ui/widget/frameTeam.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/frameTeam.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,7 +1,7 @@ /* * Hedgewars, a free turn based strategy game * Copyright (c) 2006-2007 Igor Ulyanov - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include @@ -28,7 +28,7 @@ #include "DataManager.h" FrameTeams::FrameTeams(QWidget* parent) : - QFrame(parent), maxHedgehogsPerGame(48), overallHedgehogs(0), mainLayout(this), nonInteractive(false) + QFrame(parent), mainLayout(this), nonInteractive(false) { QPalette newPalette = palette(); newPalette.setColor(QPalette::Window, QColor(0x00, 0x00, 0x00)); @@ -122,7 +122,7 @@ bool FrameTeams::isFullTeams() const { - return overallHedgehogs==maxHedgehogsPerGame; + return teamToWidget.size() >= 8; } void FrameTeams::emitTeamColorChanged(const HWTeam& team) diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/frameTeam.h --- a/QTfrontend/ui/widget/frameTeam.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/frameTeam.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,7 +1,7 @@ /* * Hedgewars, a free turn based strategy game * Copyright (c) 2006-2007 Igor Ulyanov - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _FRAME_TEAM_INCLUDED @@ -53,8 +53,6 @@ void removeTeam(HWTeam team); private: - const int maxHedgehogsPerGame; - int overallHedgehogs; int currentColor; void emitTeamColorChanged(const HWTeam& team); diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/gamecfgwidget.cpp --- a/QTfrontend/ui/widget/gamecfgwidget.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/gamecfgwidget.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include @@ -163,6 +163,7 @@ connect(pMapContainer, SIGNAL(mapChanged(const QString &)), this, SLOT(mapChanged(const QString &))); connect(pMapContainer, SIGNAL(mapgenChanged(MapGenerator)), this, SLOT(mapgenChanged(MapGenerator))); connect(pMapContainer, SIGNAL(mazeSizeChanged(int)), this, SLOT(maze_sizeChanged(int))); + connect(pMapContainer, SIGNAL(mapFeatureSizeChanged(int)), this, SLOT(slMapFeatureSizeChanged(int))); connect(pMapContainer, SIGNAL(themeChanged(const QString &)), this, SLOT(themeChanged(const QString &))); connect(pMapContainer, SIGNAL(newTemplateFilter(int)), this, SLOT(templateFilterChanged(int))); connect(pMapContainer, SIGNAL(drawMapRequested()), this, SIGNAL(goToDrawMap())); @@ -315,21 +316,25 @@ bcfg << QString("e$minesnum %1").arg(schemeData(32).toInt()).toUtf8(); bcfg << QString("e$minedudpct %1").arg(schemeData(33).toInt()).toUtf8(); bcfg << QString("e$explosives %1").arg(schemeData(34).toInt()).toUtf8(); - bcfg << QString("e$healthprob %1").arg(schemeData(35).toInt()).toUtf8(); - bcfg << QString("e$hcaseamount %1").arg(schemeData(36).toInt()).toUtf8(); - bcfg << QString("e$waterrise %1").arg(schemeData(37).toInt()).toUtf8(); - bcfg << QString("e$healthdec %1").arg(schemeData(38).toInt()).toUtf8(); - bcfg << QString("e$ropepct %1").arg(schemeData(39).toInt()).toUtf8(); - bcfg << QString("e$getawaytime %1").arg(schemeData(40).toInt()).toUtf8(); - bcfg << QString("e$worldedge %1").arg(schemeData(41).toInt()).toUtf8(); + bcfg << QString("e$airmines %1").arg(schemeData(35).toInt()).toUtf8(); + bcfg << QString("e$healthprob %1").arg(schemeData(36).toInt()).toUtf8(); + bcfg << QString("e$hcaseamount %1").arg(schemeData(37).toInt()).toUtf8(); + bcfg << QString("e$waterrise %1").arg(schemeData(38).toInt()).toUtf8(); + bcfg << QString("e$healthdec %1").arg(schemeData(39).toInt()).toUtf8(); + bcfg << QString("e$ropepct %1").arg(schemeData(40).toInt()).toUtf8(); + bcfg << QString("e$getawaytime %1").arg(schemeData(41).toInt()).toUtf8(); + bcfg << QString("e$worldedge %1").arg(schemeData(42).toInt()).toUtf8(); bcfg << QString("e$template_filter %1").arg(pMapContainer->getTemplateFilter()).toUtf8(); + bcfg << QString("e$feature_size %1").arg(pMapContainer->getFeatureSize()).toUtf8(); bcfg << QString("e$mapgen %1").arg(mapgen).toUtf8(); - + if(!schemeData(43).isNull()) + bcfg << QString("e$scriptparam %1").arg(schemeData(43).toString()).toUtf8(); switch (mapgen) { case MAPGEN_MAZE: + case MAPGEN_PERLIN: bcfg << QString("e$maze_size %1").arg(pMapContainer->getMazeSize()).toUtf8(); break; @@ -400,6 +405,10 @@ mapgenChanged(pMapContainer->get_mapgen()); maze_sizeChanged(pMapContainer->getMazeSize()); + slMapFeatureSizeChanged(pMapContainer->getFeatureSize()); + + if(pMapContainer->get_mapgen() == 2) + onDrawnMapChanged(pMapContainer->getDrawnMapData()); // map must be the last QString map = pMapContainer->getCurrentMap(); @@ -437,6 +446,11 @@ pMapContainer->setMapgen((MapGenerator)value.toUInt()); return; } + if (param == "FEATURE_SIZE") + { + pMapContainer->setFeatureSize(value.toUInt()); + return; + } if (param == "MAZE_SIZE") { pMapContainer->setMazeSize(value.toUInt()); @@ -445,6 +459,7 @@ if (param == "SCRIPT") { Scripts->setCurrentIndex(Scripts->findText(value)); + pMapContainer->setScript(Scripts->itemData(Scripts->currentIndex(), GameStyleModel::ScriptRole).toString().toUtf8(), schemeData(43).toString()); return; } if (param == "DRAWNMAP") @@ -463,18 +478,19 @@ } } - if (slValue.size() == 5) + if (slValue.size() == 6) { if (param == "FULLMAPCONFIG") { - QString seed = slValue[3]; + QString seed = slValue[4]; pMapContainer->setAllMapParameters( - slValue[0], - (MapGenerator)slValue[1].toUInt(), - slValue[2].toUInt(), + slValue[1], + (MapGenerator)slValue[2].toUInt(), + slValue[3].toUInt(), seed, - slValue[4].toUInt() + slValue[5].toUInt(), + slValue[0].toUInt() ); return; } @@ -512,8 +528,8 @@ int num = GameSchemes->findText(pMapContainer->getCurrentScheme()); if (num != -1) GameSchemes->setCurrentIndex(num); - else - GameSchemes->setCurrentIndex(GameSchemes->findText("Default")); + //else + // GameSchemes->setCurrentIndex(GameSchemes->findText("Default")); } if (pMapContainer->getCurrentWeapons() == "locked") @@ -527,8 +543,8 @@ int num = WeaponsName->findText(pMapContainer->getCurrentWeapons()); if (num != -1) WeaponsName->setCurrentIndex(num); - else - WeaponsName->setCurrentIndex(WeaponsName->findText("Default")); + //else + // WeaponsName->setCurrentIndex(WeaponsName->findText("Default")); } if (pMapContainer->getCurrentScheme() != "locked" && pMapContainer->getCurrentWeapons() != "locked") @@ -569,7 +585,11 @@ for(int i = 0; i < size; ++i) sl << schemeData(i).toString(); - if (sl.size()!=1) emit paramChanged("SCHEME", sl); // this is a stupid hack for the fact that SCHEME is being sent once, empty. Still need to find out why. + if (sl.size() >= 42) + { + sl[sl.size()-1].prepend('!'); + emit paramChanged("SCHEME", sl); // this is a stupid hack for the fact that SCHEME is being sent once, empty. Still need to find out why. + } if (isEnabled() && bindEntries->isEnabled() && bindEntries->isChecked()) { @@ -586,6 +606,7 @@ } } } + pMapContainer->setScript(Scripts->itemData(Scripts->currentIndex(), GameStyleModel::ScriptRole).toString().toUtf8(), schemeData(43).toString()); } void GameCFGWidget::scriptChanged(int index) @@ -609,8 +630,8 @@ int num = GameSchemes->findText(scheme); if (num != -1) GameSchemes->setCurrentIndex(num); - else - GameSchemes->setCurrentIndex(GameSchemes->findText("Default")); + //else + // GameSchemes->setCurrentIndex(GameSchemes->findText("Default")); } if (weapons == "locked") @@ -624,8 +645,8 @@ int num = WeaponsName->findText(weapons); if (num != -1) WeaponsName->setCurrentIndex(num); - else - WeaponsName->setCurrentIndex(WeaponsName->findText("Default")); + //else + // WeaponsName->setCurrentIndex(WeaponsName->findText("Default")); } if (scheme != "locked" && weapons != "locked") @@ -639,6 +660,14 @@ WeaponsName->setEnabled(true); bindEntries->setEnabled(true); } + if (!index) + { + pMapContainer->setScript(QString(""), QString("")); + } + else + { + pMapContainer->setScript(Scripts->itemData(index, GameStyleModel::ScriptRole).toString().toUtf8(), schemeData(43).toString()); + } emit paramChanged("SCRIPT", QStringList(name)); } @@ -652,6 +681,11 @@ emit paramChanged("MAZE_SIZE", QStringList(QString::number(s))); } +void GameCFGWidget::slMapFeatureSizeChanged(int s) +{ + emit paramChanged("FEATURE_SIZE", QStringList(QString::number(s))); +} + void GameCFGWidget::resendSchemeData() { schemeChanged(GameSchemes->currentIndex()); diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/gamecfgwidget.h --- a/QTfrontend/ui/widget/gamecfgwidget.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/gamecfgwidget.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef GAMECONFIGWIDGET_H @@ -48,7 +48,6 @@ QComboBox * GameSchemes; QComboBox * WeaponsName; HWMapContainer* pMapContainer; - QTableView * tv; QVariant schemeData(int column) const; bool isMaster(); @@ -77,6 +76,7 @@ void jumpToWeapons(); void mapgenChanged(MapGenerator m); void maze_sizeChanged(int s); + void slMapFeatureSizeChanged(int s); void onDrawnMapChanged(const QByteArray & data); void updateModelViews(); diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/hatbutton.cpp --- a/QTfrontend/ui/widget/hatbutton.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/hatbutton.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/hatbutton.h --- a/QTfrontend/ui/widget/hatbutton.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/hatbutton.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef HATBUTTON_H diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/hatprompt.cpp --- a/QTfrontend/ui/widget/hatprompt.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/hatprompt.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/hatprompt.h --- a/QTfrontend/ui/widget/hatprompt.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/hatprompt.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef HATPROMPT_H diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/hedgehogerWidget.cpp --- a/QTfrontend/ui/widget/hedgehogerWidget.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/hedgehogerWidget.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,7 +1,7 @@ /* * Hedgewars, a free turn based strategy game * Copyright (c) 2006-2008 Ulyanov Igor - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "hedgehogerWidget.h" diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/hedgehogerWidget.h --- a/QTfrontend/ui/widget/hedgehogerWidget.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/hedgehogerWidget.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,7 +1,7 @@ /* * Hedgewars, a free turn based strategy game * Copyright (c) 2006-2007 Ulyanov Igor - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _HEDGEHOGER_WIDGET @@ -46,7 +46,6 @@ private: CHedgehogerWidget(); - FrameTeams* pOurFrameTeams; }; #endif // _HEDGEHOGER_WIDGET diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/igbox.cpp --- a/QTfrontend/ui/widget/igbox.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/igbox.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/igbox.h --- a/QTfrontend/ui/widget/igbox.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/igbox.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _IGBOX_H diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/itemNum.cpp --- a/QTfrontend/ui/widget/itemNum.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/itemNum.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "itemNum.h" diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/itemNum.h --- a/QTfrontend/ui/widget/itemNum.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/itemNum.h Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/keybinder.cpp --- a/QTfrontend/ui/widget/keybinder.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/keybinder.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "keybinder.h" diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/keybinder.h --- a/QTfrontend/ui/widget/keybinder.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/keybinder.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _KEY_BINDER_H diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/lineeditcursor.cpp --- a/QTfrontend/ui/widget/lineeditcursor.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/lineeditcursor.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/lineeditcursor.h --- a/QTfrontend/ui/widget/lineeditcursor.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/lineeditcursor.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef LINEEDITCURSOR_H diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/mapContainer.cpp --- a/QTfrontend/ui/widget/mapContainer.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/mapContainer.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -13,30 +13,31 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include +#include #include -#include -#include -#include -#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include #include #include +#include #include +#include +#include +#include +#include +#include +#include #include +#include +#include +#include +#include +#include +#include +#include #include "hwconsts.h" #include "mapContainer.h" @@ -59,6 +60,9 @@ m_previewEnabled = false; m_missionsViewSetup = false; m_staticViewSetup = false; + m_script = QString(); + m_prevMapFeatureSize = 12; + m_mapFeatureSize = 12; hhSmall.load(":/res/hh_small.png"); hhLimit = 18; @@ -104,6 +108,7 @@ cType->insertItem(2, tr("Hand-drawn"), MapModel::HandDrawnMap); cType->insertItem(3, tr("Randomly generated"), MapModel::GeneratedMap); cType->insertItem(4, tr("Random maze"), MapModel::GeneratedMaze); + cType->insertItem(5, tr("Random perlin"), MapModel::GeneratedPerlin); connect(cType, SIGNAL(currentIndexChanged(int)), this, SLOT(mapTypeChanged(int))); m_childWidgets << cType; @@ -145,7 +150,7 @@ mapPreview = new QPushButton(this); mapPreview->setObjectName("mapPreview"); mapPreview->setFlat(true); - mapPreview->setFixedSize(256, 128); + mapPreview->setFixedSize(256 + 6, 128 + 6); mapPreview->setContentsMargins(0, 0, 0, 0); leftLayout->addWidget(mapPreview, 0); connect(mapPreview, SIGNAL(clicked()), this, SLOT(previewClicked())); @@ -157,12 +162,12 @@ /* Map list label */ - lblMapList = new QLabel(); + lblMapList = new QLabel(this); rightLayout->addWidget(lblMapList, 0); /* Static maps list */ - staticMapList = new QListView; + staticMapList = new QListView(this); rightLayout->addWidget(staticMapList, 1); m_childWidgets << staticMapList; @@ -194,7 +199,7 @@ /* Generator style list */ - generationStyles = new QListWidget(); + generationStyles = new QListWidget(this); new QListWidgetItem(tr("All"), generationStyles); new QListWidgetItem(tr("Small"), generationStyles); new QListWidgetItem(tr("Medium"), generationStyles); @@ -207,7 +212,7 @@ /* Maze style list */ - mazeStyles = new QListWidget(); + mazeStyles = new QListWidget(this); new QListWidgetItem(tr("Small tunnels"), mazeStyles); new QListWidgetItem(tr("Medium tunnels"), mazeStyles); new QListWidgetItem(tr("Large tunnels"), mazeStyles); @@ -218,6 +223,18 @@ m_childWidgets << mazeStyles; rightLayout->addWidget(mazeStyles, 1); + mapFeatureSize = new QSlider(Qt::Horizontal, this); + mapFeatureSize->setObjectName("mapFeatureSize"); + //mapFeatureSize->setTickPosition(QSlider::TicksBelow); + mapFeatureSize->setMaximum(25); + mapFeatureSize->setMinimum(1); + //mapFeatureSize->setFixedWidth(259); + mapFeatureSize->setValue(m_mapFeatureSize); + mapFeatureSize->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + bottomLeftLayout->addWidget(mapFeatureSize, 0); + connect(mapFeatureSize, SIGNAL(valueChanged(int)), this, SLOT(setFeatureSize(int))); + m_childWidgets << mapFeatureSize; + /* Mission description */ lblDesc = new QLabel(); @@ -233,8 +250,10 @@ /* Theme chooser */ - btnTheme = new QPushButton(); + btnTheme = new QPushButton(this); btnTheme->setFlat(true); + btnTheme->setIconSize(QSize(30, 30)); + btnTheme->setFixedHeight(30); connect(btnTheme, SIGNAL(clicked()), this, SLOT(showThemePrompt())); m_childWidgets << btnTheme; bottomLeftLayout->addWidget(btnTheme, 0); @@ -254,20 +273,9 @@ changeMapType(MapModel::GeneratedMap); } -void HWMapContainer::setImage(const QImage newImage) +void HWMapContainer::setImage(const QPixmap &newImage) { - QPixmap px(m_previewSize); - QPixmap pxres(px.size()); - QPainter p(&pxres); - - px.fill(Qt::yellow); - QBitmap bm = QBitmap::fromImage(newImage); - px.setMask(bm); - - p.fillRect(pxres.rect(), linearGrad); - p.drawPixmap(0, 0, px); - - addInfoToPreview(pxres); + addInfoToPreview(newImage); pMap = 0; cType->setEnabled(isMaster()); @@ -279,43 +287,47 @@ } // Should this add text to identify map size? -void HWMapContainer::addInfoToPreview(QPixmap image) +void HWMapContainer::addInfoToPreview(const QPixmap &image) { QPixmap finalImage = QPixmap(image.size()); - finalImage.fill(QColor(0, 0, 0, 0)); +//finalImage.fill(QColor(0, 0, 0, 0)); QPainter p(&finalImage); - p.drawPixmap(image.rect(), image); + p.fillRect(finalImage.rect(), linearGrad); + p.drawPixmap(finalImage.rect(), image); //p.setPen(QColor(0xf4,0x9e,0xe9)); p.setPen(QColor(0xff,0xcc,0x00)); p.setBrush(QColor(0, 0, 0)); - p.drawRect(image.rect().width() - hhSmall.rect().width() - 28, 3, 40, 20); + p.drawRect(finalImage.rect().width() - hhSmall.rect().width() - 28, 3, 40, 20); p.setFont(QFont("MS Shell Dlg", 10)); QString text = (hhLimit > 0) ? QString::number(hhLimit) : "?"; - p.drawText(image.rect().width() - hhSmall.rect().width() - 14 - (hhLimit > 9 ? 10 : 0), 18, text); - p.drawPixmap(image.rect().width() - hhSmall.rect().width() - 5, 5, hhSmall.rect().width(), hhSmall.rect().height(), hhSmall); + p.drawText(finalImage.rect().width() - hhSmall.rect().width() - 14 - (hhLimit > 9 ? 10 : 0), 18, text); + p.drawPixmap(finalImage.rect().width() - hhSmall.rect().width() - 5, 5, hhSmall.rect().width(), hhSmall.rect().height(), hhSmall); // Shrink, crop, and center preview image - QPixmap centered(QSize(m_previewSize.width() - 6, m_previewSize.height() - 6)); + /*QPixmap centered(QSize(m_previewSize.width() - 6, m_previewSize.height() - 6)); QPainter pc(¢ered); pc.fillRect(centered.rect(), linearGrad); - pc.drawPixmap(-3, -3, finalImage); + pc.drawPixmap(-3, -3, finalImage);*/ - mapPreview->setIcon(QIcon(centered)); - mapPreview->setIconSize(centered.size()); + mapPreview->setIcon(QIcon(finalImage)); + mapPreview->setIconSize(finalImage.size()); } void HWMapContainer::askForGeneratedPreview() { pMap = new HWMap(this); - connect(pMap, SIGNAL(ImageReceived(const QImage)), this, SLOT(setImage(const QImage))); + connect(pMap, SIGNAL(ImageReceived(QPixmap)), this, SLOT(setImage(QPixmap))); connect(pMap, SIGNAL(HHLimitReceived(int)), this, SLOT(setHHLimit(int))); connect(pMap, SIGNAL(destroyed(QObject *)), this, SLOT(onPreviewMapDestroyed(QObject *))); pMap->getImage(m_seed, getTemplateFilter(), get_mapgen(), getMazeSize(), - getDrawnMapData() + getDrawnMapData(), + m_script, + m_scriptparam, + m_mapFeatureSize ); setHHLimit(0); @@ -396,6 +408,11 @@ return generationStyles->currentRow(); } +quint32 HWMapContainer::getFeatureSize() const +{ + return m_mapFeatureSize; +} + void HWMapContainer::resizeEvent ( QResizeEvent * event ) { Q_UNUSED(event); @@ -409,7 +426,20 @@ void HWMapContainer::setSeed(const QString & seed) { intSetSeed(seed); - if ((m_mapInfo.type == MapModel::GeneratedMap) || (m_mapInfo.type == MapModel::GeneratedMaze)) + if ((m_mapInfo.type == MapModel::GeneratedMap) + || (m_mapInfo.type == MapModel::GeneratedMaze) + || (m_mapInfo.type == MapModel::GeneratedPerlin)) + updatePreview(); +} + +void HWMapContainer::setScript(const QString & script, const QString & scriptparam) +{ + m_script = script; + m_scriptparam = scriptparam; + if ((m_mapInfo.type == MapModel::GeneratedMap) + || (m_mapInfo.type == MapModel::GeneratedMaze) + || (m_mapInfo.type == MapModel::GeneratedPerlin) + || (m_mapInfo.type == MapModel::HandDrawnMap)) updatePreview(); } @@ -417,15 +447,19 @@ { if (map == "+rnd+") { - changeMapType(MapModel::GeneratedMap); + //changeMapType(MapModel::GeneratedMap); } else if (map == "+maze+") { - changeMapType(MapModel::GeneratedMaze); + //changeMapType(MapModel::GeneratedMaze); + } + else if (map == "+perlin+") + { + //changeMapType(MapModel::GeneratedPerlin); } else if (map == "+drawn+") { - changeMapType(MapModel::HandDrawnMap); + //changeMapType(MapModel::HandDrawnMap); } else if (m_staticMapModel->mapExists(map)) { @@ -465,6 +499,7 @@ { case MapModel::GeneratedMap: case MapModel::GeneratedMaze: + case MapModel::GeneratedPerlin: setRandomTheme(); break; case MapModel::MissionMap: @@ -534,22 +569,31 @@ { mapgen = m; + bool f = false; switch (m) { case MAPGEN_REGULAR: m_mapInfo.type = MapModel::GeneratedMap; + f = true; break; case MAPGEN_MAZE: m_mapInfo.type = MapModel::GeneratedMaze; + f = true; + break; + case MAPGEN_PERLIN: + m_mapInfo.type = MapModel::GeneratedPerlin; + f = true; break; case MAPGEN_DRAWN: m_mapInfo.type = MapModel::HandDrawnMap; + f = true; break; case MAPGEN_MAP: switch (m_mapInfo.type) { case MapModel::GeneratedMap: case MapModel::GeneratedMaze: + case MapModel::GeneratedPerlin: case MapModel::HandDrawnMap: m_mapInfo.type = MapModel::Invalid; default: @@ -558,7 +602,8 @@ break; } - emit mapgenChanged(m); + if(f) + changeMapType(m_mapInfo.type, QModelIndex()); } } @@ -616,7 +661,7 @@ if (pMap) { - disconnect(pMap, 0, this, SLOT(setImage(const QImage))); + disconnect(pMap, 0, this, SLOT(setImage(const QPixmap))); disconnect(pMap, 0, this, SLOT(setHHLimit(int))); pMap = 0; } @@ -631,11 +676,8 @@ mapPreview->setIconSize(failIcon.size()); break; case MapModel::GeneratedMap: - askForGeneratedPreview(); - break; case MapModel::GeneratedMaze: - askForGeneratedPreview(); - break; + case MapModel::GeneratedPerlin: case MapModel::HandDrawnMap: askForGeneratedPreview(); break; @@ -654,7 +696,7 @@ } } -void HWMapContainer::setAllMapParameters(const QString &map, MapGenerator m, int mazesize, const QString &seed, int tmpl) +void HWMapContainer::setAllMapParameters(const QString &map, MapGenerator m, int mazesize, const QString &seed, int tmpl, int featureSize) { intSetMapgen(m); intSetMazeSize(mazesize); @@ -662,6 +704,8 @@ intSetTemplateFilter(tmpl); // this one last because it will refresh the preview intSetMap(map); + intSetMazeSize(mazesize); + intSetFeatureSize(featureSize); } void HWMapContainer::updateModelViews() @@ -706,6 +750,7 @@ lblDesc->hide(); btnLoadMap->hide(); btnEditMap->hide(); + mapFeatureSize->show(); switch (type) { @@ -723,10 +768,18 @@ lblMapList->show(); mazeStyles->show(); break; + case MapModel::GeneratedPerlin: + mapgen = MAPGEN_PERLIN; + setMapInfo(MapModel::MapInfoPerlin); + lblMapList->setText(tr("Style:")); + lblMapList->show(); + mazeStyles->show(); + break; case MapModel::HandDrawnMap: mapgen = MAPGEN_DRAWN; setMapInfo(MapModel::MapInfoDrawn); btnLoadMap->show(); + mapFeatureSize->hide(); btnEditMap->show(); break; case MapModel::MissionMap: @@ -736,6 +789,7 @@ lblMapList->setText(tr("Mission:")); lblMapList->show(); missionMapList->show(); + mapFeatureSize->hide(); lblDesc->setText(m_mapInfo.desc); lblDesc->show(); emit mapChanged(m_curMap); @@ -746,6 +800,7 @@ staticMapChanged(newMap.isValid() ? newMap : staticMapList->currentIndex()); lblMapList->setText(tr("Map:")); lblMapList->show(); + mapFeatureSize->hide(); staticMapList->show(); emit mapChanged(m_curMap); break; @@ -771,9 +826,27 @@ emit mapgenChanged(mapgen); } +void HWMapContainer::intSetFeatureSize(int val) +{ + mapFeatureSize->setValue(val); + emit mapFeatureSizeChanged(val); +} +void HWMapContainer::setFeatureSize(int val) +{ + m_mapFeatureSize = val; + intSetFeatureSize(val); + //m_mapFeatureSize = val>>2<<2; + //if (qAbs(m_prevMapFeatureSize-m_mapFeatureSize) > 4) + { + m_prevMapFeatureSize = m_mapFeatureSize; + updatePreview(); + } +} + +// unused because I needed the space for the slider void HWMapContainer::updateThemeButtonSize() { - if (m_mapInfo.type == MapModel::MissionMap) + if (m_mapInfo.type != MapModel::StaticMap && m_mapInfo.type != MapModel::HandDrawnMap) { btnTheme->setIconSize(QSize(30, 30)); btnTheme->setFixedHeight(30); @@ -804,9 +877,9 @@ m_theme = selectedTheme = current.data(ThemeModel::ActualNameRole).toString(); m_themeID = current.row(); QIcon icon = qVariantValue(current.data(Qt::DecorationRole)); - QSize iconSize = icon.actualSize(QSize(65535, 65535)); - btnTheme->setFixedHeight(64); - btnTheme->setIconSize(iconSize); + //QSize iconSize = icon.actualSize(QSize(65535, 65535)); + //btnTheme->setFixedHeight(64); + //btnTheme->setIconSize(iconSize); btnTheme->setIcon(icon); btnTheme->setText(tr("Theme: %1").arg(current.data(Qt::DisplayRole).toString())); updateThemeButtonSize(); @@ -855,11 +928,8 @@ mapList->scrollTo(map); } - if (map.data(Qt::UserRole + 1).canConvert()) - setMapInfo(map.data(Qt::UserRole + 1).value()); - else - Q_ASSERT(false); // Houston, we have a problem. - + Q_ASSERT(map.data(Qt::UserRole + 1).canConvert()); // Houston, we have a problem. + setMapInfo(map.data(Qt::UserRole + 1).value()); } void HWMapContainer::setMapInfo(MapModel::MapInfo mapInfo) diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/mapContainer.h --- a/QTfrontend/ui/widget/mapContainer.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/mapContainer.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,7 +1,7 @@ /* * Hedgewars, a free turn based strategy game * Copyright (c) 2006-2007 Igor Ulyanov - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,19 +14,20 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _HWMAP_CONTAINER_INCLUDED #define _HWMAP_CONTAINER_INCLUDED -#include -#include -#include +#include #include +#include #include -#include #include +#include +#include +#include #include "DataManager.h" @@ -59,6 +60,7 @@ QString getCurrentScheme() const; QString getCurrentWeapons() const; quint32 getTemplateFilter() const; + quint32 getFeatureSize() const; MapGenerator get_mapgen(void) const; int getMazeSize(void) const; bool getCurrentIsMission() const; @@ -71,13 +73,15 @@ public slots: void askForGeneratedPreview(); void setSeed(const QString & seed); + void setScript(const QString & script, const QString & scriptparam); void setMap(const QString & map); void setTheme(const QString & theme); void setTemplateFilter(int); void setMapgen(MapGenerator m); void setMazeSize(int size); + void setFeatureSize(int size); void setDrawnMapData(const QByteArray & ar); - void setAllMapParameters(const QString & map, MapGenerator m, int mazesize, const QString & seed, int tmpl); + void setAllMapParameters(const QString & map, MapGenerator m, int mazesize, const QString & seed, int tmpl, int featureSize); void updateModelViews(); void onPreviewMapDestroyed(QObject * map); void setMaster(bool master); @@ -89,16 +93,17 @@ void newTemplateFilter(int filter); void mapgenChanged(MapGenerator m); void mazeSizeChanged(int s); + void mapFeatureSizeChanged(int s); void drawMapRequested(); void drawnMapChanged(const QByteArray & data); private slots: - void setImage(const QImage newImage); + void setImage(const QPixmap & newImage); void setHHLimit(int hhLimit); void setRandomSeed(); void setRandomTheme(); void setRandomMap(); - void addInfoToPreview(QPixmap image); + void addInfoToPreview(const QPixmap & image); void setNewSeed(const QString & newSeed); void mapTypeChanged(int); void showThemePrompt(); @@ -116,6 +121,7 @@ private: QVBoxLayout mainLayout; QPushButton* mapPreview; + QSlider* mapFeatureSize; QComboBox* chooseMap; MapModel * m_staticMapModel; MapModel * m_missionMapModel; @@ -124,6 +130,8 @@ ThemeModel * m_themeModel; HWMap* pMap; QString m_seed; + QString m_script; + QString m_scriptparam; QPushButton* seedSet; QLabel* seedLabel; int hhLimit; @@ -159,6 +167,7 @@ void intSetMapgen(MapGenerator m); void intSetTemplateFilter(int); void intSetMazeSize(int size); + void intSetFeatureSize(int size); void intSetIconlessTheme(const QString & name); void mapChanged(const QModelIndex & map, int type, const QModelIndex & old = QModelIndex()); void setMapInfo(MapModel::MapInfo mapInfo); @@ -170,6 +179,8 @@ MapModel::MapInfo m_mapInfo; int m_themeID; + int m_prevMapFeatureSize; + int m_mapFeatureSize; QString m_theme; QString m_curMap; diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/qpushbuttonwithsound.cpp --- a/QTfrontend/ui/widget/qpushbuttonwithsound.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/qpushbuttonwithsound.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/qpushbuttonwithsound.h --- a/QTfrontend/ui/widget/qpushbuttonwithsound.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/qpushbuttonwithsound.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef QPUSHBUTTONWITHSOUND_H diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/roomnameprompt.cpp --- a/QTfrontend/ui/widget/roomnameprompt.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/roomnameprompt.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/roomnameprompt.h --- a/QTfrontend/ui/widget/roomnameprompt.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/roomnameprompt.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef ROOMNAMEPROMPT_H diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/seedprompt.cpp --- a/QTfrontend/ui/widget/seedprompt.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/seedprompt.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/seedprompt.h --- a/QTfrontend/ui/widget/seedprompt.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/seedprompt.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef SEEDPROMPT_H diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/selectWeapon.cpp --- a/QTfrontend/ui/widget/selectWeapon.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/selectWeapon.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,7 +1,7 @@ /* * Hedgewars, a free turn based strategy game * Copyright (c) 2006-2008 Igor Ulyanov - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "selectWeapon.h" @@ -93,7 +93,7 @@ for(int i = 0; i < keys.size(); i++) { if (wconf->value(keys[i]).toString().size() != cDefaultAmmoStore->size()) - wconf->remove(keys[i]); + wconf->setValue(keys[i], fixWeaponSet(wconf->value(keys[i]).toString())); } QString currentState = *cDefaultAmmoStore; @@ -322,14 +322,33 @@ if(wconf->contains(curWeaponsName)) { QString ammo = getWeaponsString(curWeaponsName); - QString newName = tr("copy of") + " " + curWeaponsName; + QString newName = tr("copy of %1").arg(curWeaponsName); if(wconf->contains(newName)) { //name already used -> look for an appropriate name: int i=2; - while(wconf->contains(newName = tr("copy of") + " " + curWeaponsName+QString::number(i++))) ; + while(wconf->contains(newName = tr("copy of %1").arg(curWeaponsName+QString::number(i++)))); } setWeaponsName(newName); setWeapons(ammo); } } + +QString SelWeaponWidget::fixWeaponSet(const QString &s) +{ + int neededLength = cDefaultAmmoStore->size() / 4; + int thisSetLength = s.size() / 4; + + QStringList sl; + sl + << s.left(thisSetLength) + << s.mid(thisSetLength, thisSetLength) + << s.mid(thisSetLength * 2, thisSetLength) + << s.right(thisSetLength) + ; + + for(int i = sl.length() - 1; i >= 0; --i) + sl[i] = sl[i].leftJustified(neededLength, '0', true); + + return sl.join(QString()); +} diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/selectWeapon.h --- a/QTfrontend/ui/widget/selectWeapon.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/selectWeapon.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,7 +1,7 @@ /* * Hedgewars, a free turn based strategy game * Copyright (c) 2006-2008 Igor Ulyanov - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _SELECT_WEAPON_INCLUDED @@ -87,6 +87,8 @@ QGridLayout* p2Layout; QGridLayout* p3Layout; QGridLayout* p4Layout; + + QString fixWeaponSet(const QString & s); }; #endif // _SELECT_WEAPON_INCLUDED diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/teamselect.cpp --- a/QTfrontend/ui/widget/teamselect.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/teamselect.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,7 +1,7 @@ /* * Hedgewars, a free turn based strategy game * Copyright (c) 2006-2007 Igor Ulyanov - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include @@ -121,26 +121,22 @@ void TeamSelWidget::removeNetTeam(const HWTeam& team) { //qDebug() << QString("removeNetTeam: removing team '%1'").arg(team.TeamName); - for(;;) + QList::iterator itPlay=std::find(curPlayingTeams.begin(), curPlayingTeams.end(), team); + if(itPlay==curPlayingTeams.end()) { - QList::iterator itPlay=std::find(curPlayingTeams.begin(), curPlayingTeams.end(), team); - if(itPlay==curPlayingTeams.end()) - { - qWarning() << QString("removeNetTeam: team '%1' not found").arg(team.name()); - break; - } - if(itPlay->isNetTeam()) - { - QObject::disconnect(framePlaying->getTeamWidget(*itPlay), SIGNAL(teamStatusChanged(HWTeam))); - framePlaying->removeTeam(team); - curPlayingTeams.erase(itPlay); - break; - } - else - { - qWarning() << QString("removeNetTeam: team '%1' was actually a local team!").arg(team.name()); - break; - } + qWarning() << QString("removeNetTeam: team '%1' not found").arg(team.name()); + return; + } + + if(itPlay->isNetTeam()) + { + QObject::disconnect(framePlaying->getTeamWidget(*itPlay), SIGNAL(teamStatusChanged(HWTeam))); + framePlaying->removeTeam(team); + curPlayingTeams.erase(itPlay); + } + else + { + qWarning() << QString("removeNetTeam: team '%1' was actually a local team!").arg(team.name()); } emit setEnabledGameStart(curPlayingTeams.size()>1); } diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/teamselect.h --- a/QTfrontend/ui/widget/teamselect.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/teamselect.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,7 +1,7 @@ /* * Hedgewars, a free turn based strategy game * Copyright (c) 2006-2007 Igor Ulyanov - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _TEAM_SELECT_INCLUDED diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/teamselhelper.cpp --- a/QTfrontend/ui/widget/teamselhelper.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/teamselhelper.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,7 +1,7 @@ /* * Hedgewars, a free turn based strategy game * Copyright (c) 2006-2007 Igor Ulyanov - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/teamselhelper.h --- a/QTfrontend/ui/widget/teamselhelper.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/teamselhelper.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,7 +1,7 @@ /* * Hedgewars, a free turn based strategy game * Copyright (c) 2006-2007 Igor Ulyanov - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _TEAMSEL_HELPER_INCLUDED @@ -75,7 +75,7 @@ FrameTeams * m_parentFrameTeams; signals: - void teamStatusChanged(HWTeam team); + void teamStatusChanged(const HWTeam &); void hhNmChanged(const HWTeam&); void teamColorChanged(const HWTeam&); }; diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/themeprompt.cpp --- a/QTfrontend/ui/widget/themeprompt.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/themeprompt.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/themeprompt.h --- a/QTfrontend/ui/widget/themeprompt.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/themeprompt.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef THEMEPROMPT_H diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/togglebutton.cpp --- a/QTfrontend/ui/widget/togglebutton.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/togglebutton.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,7 +1,7 @@ /* * Hedgewars, a free turn based strategy game * Copyright (c) 2009 Kristian Lehmann - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "togglebutton.h" diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/togglebutton.h --- a/QTfrontend/ui/widget/togglebutton.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/togglebutton.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,7 +1,7 @@ /* * Hedgewars, a free turn based strategy game * Copyright (c) 2009 Kristian Lehmann - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TOGGLEBUTTONWIDGET_H diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/vertScrollArea.cpp --- a/QTfrontend/ui/widget/vertScrollArea.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/vertScrollArea.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,7 +1,7 @@ /* * Hedgewars, a free turn based strategy game * Copyright (c) 2006 Igor Ulyanov - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "vertScrollArea.h" diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/vertScrollArea.h --- a/QTfrontend/ui/widget/vertScrollArea.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/vertScrollArea.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,7 +1,7 @@ /* * Hedgewars, a free turn based strategy game * Copyright (c) 2006 Igor Ulyanov - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _VERT_SCROLL_AREA_INCLUDED diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/weaponItem.cpp --- a/QTfrontend/ui/widget/weaponItem.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/weaponItem.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,7 +1,7 @@ /* * Hedgewars, a free turn based strategy game * Copyright (c) 2006-2008 Igor Ulyanov - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "weaponItem.h" diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui/widget/weaponItem.h --- a/QTfrontend/ui/widget/weaponItem.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui/widget/weaponItem.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,7 +1,7 @@ /* * Hedgewars, a free turn based strategy game * Copyright (c) 2006-2008 Igor Ulyanov - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _WEAPON_ITEM diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui_hwform.cpp --- a/QTfrontend/ui_hwform.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui_hwform.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff -r 31570b766315 -r ed5a6478e710 QTfrontend/ui_hwform.h --- a/QTfrontend/ui_hwform.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/ui_hwform.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef UI_HWFORM_H diff -r 31570b766315 -r ed5a6478e710 QTfrontend/util/DataManager.cpp --- a/QTfrontend/util/DataManager.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/util/DataManager.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /** @@ -47,6 +47,7 @@ m_themeModel = NULL; m_colorsModel = NULL; m_bindsModel = NULL; + m_gameStyleModel = NULL; } diff -r 31570b766315 -r ed5a6478e710 QTfrontend/util/DataManager.h --- a/QTfrontend/util/DataManager.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/util/DataManager.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /** diff -r 31570b766315 -r ed5a6478e710 QTfrontend/util/FileEngine.cpp --- a/QTfrontend/util/FileEngine.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/util/FileEngine.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -2,8 +2,8 @@ * TODO: add copyright header, determine license */ +#include "FileEngine.h" #include "hwpacksmounter.h" -#include "FileEngine.h" const QString FileEngineHandler::scheme = "physfs:/"; diff -r 31570b766315 -r ed5a6478e710 QTfrontend/util/FileEngine.h --- a/QTfrontend/util/FileEngine.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/util/FileEngine.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,93 +1,93 @@ -#ifndef _FileEngine_h -#define _FileEngine_h - -#include -#include -#include -#include - -#include "physfs.h" - - - -class FileEngine : public QAbstractFileEngine -{ - public: - FileEngine(const QString& filename); - - virtual ~FileEngine(); - - virtual bool open(QIODevice::OpenMode openMode); - virtual bool close(); - virtual bool flush(); - virtual qint64 size() const; - virtual qint64 pos() const; - virtual bool setSize(qint64 size); - virtual bool seek(qint64 pos); - virtual bool isSequential() const; - virtual bool remove(); - virtual bool mkdir(const QString &dirName, bool createParentDirectories) const; - virtual bool rmdir(const QString &dirName, bool recurseParentDirectories) const; - virtual bool caseSensitive() const; - virtual bool isRelativePath() const; - QAbstractFileEngineIterator *beginEntryList(QDir::Filters filters, const QStringList & filterNames); - virtual QStringList entryList(QDir::Filters filters, const QStringList &filterNames) const; - virtual FileFlags fileFlags(FileFlags type=FileInfoAll) const; - virtual QString fileName(FileName file=DefaultName) const; - virtual QDateTime fileTime(FileTime time) const; - virtual void setFileName(const QString &file); - bool atEnd() const; - - virtual qint64 read(char *data, qint64 maxlen); - virtual qint64 readLine(char *data, qint64 maxlen); - virtual qint64 write(const char *data, qint64 len); - - bool isOpened() const; - - QFile::FileError error() const; - QString errorString() const; - - virtual bool supportsExtension(Extension extension) const; - - private: - PHYSFS_file *m_handle; - qint64 m_size; - FileFlags m_flags; - QString m_fileName; - QDateTime m_date; - bool m_bufferSet; - bool m_readWrite; -}; - -class FileEngineHandler : public QAbstractFileEngineHandler -{ - public: - FileEngineHandler(char * argv0); - ~FileEngineHandler(); - - QAbstractFileEngine *create(const QString &filename) const; - - static void mount(const QString & path); - static void mount(const QString & path, const QString & mountPoint); - static void setWriteDir(const QString & path); - static void mountPacks(); - static QString errorStr(); - -// private: - static const QString scheme; -}; - -class FileEngineIterator : public QAbstractFileEngineIterator -{ -public: - FileEngineIterator(QDir::Filters filters, const QStringList & nameFilters, const QStringList & entries); - - bool hasNext() const; - QString next(); - QString currentFileName() const; -private: - QStringList m_entries; - int m_index; -}; - -#endif +#ifndef _FileEngine_h +#define _FileEngine_h + +#include +#include +#include +#include + +#include "physfs.h" + + + +class FileEngine : public QAbstractFileEngine +{ + public: + FileEngine(const QString& filename); + + virtual ~FileEngine(); + + virtual bool open(QIODevice::OpenMode openMode); + virtual bool close(); + virtual bool flush(); + virtual qint64 size() const; + virtual qint64 pos() const; + virtual bool setSize(qint64 size); + virtual bool seek(qint64 pos); + virtual bool isSequential() const; + virtual bool remove(); + virtual bool mkdir(const QString &dirName, bool createParentDirectories) const; + virtual bool rmdir(const QString &dirName, bool recurseParentDirectories) const; + virtual bool caseSensitive() const; + virtual bool isRelativePath() const; + QAbstractFileEngineIterator *beginEntryList(QDir::Filters filters, const QStringList & filterNames); + virtual QStringList entryList(QDir::Filters filters, const QStringList &filterNames) const; + virtual FileFlags fileFlags(FileFlags type=FileInfoAll) const; + virtual QString fileName(FileName file=DefaultName) const; + virtual QDateTime fileTime(FileTime time) const; + virtual void setFileName(const QString &file); + bool atEnd() const; + + virtual qint64 read(char *data, qint64 maxlen); + virtual qint64 readLine(char *data, qint64 maxlen); + virtual qint64 write(const char *data, qint64 len); + + bool isOpened() const; + + QFile::FileError error() const; + QString errorString() const; + + virtual bool supportsExtension(Extension extension) const; + + private: + PHYSFS_file *m_handle; + qint64 m_size; + FileFlags m_flags; + QString m_fileName; + QDateTime m_date; + bool m_bufferSet; + bool m_readWrite; +}; + +class FileEngineHandler : public QAbstractFileEngineHandler +{ + public: + FileEngineHandler(char * argv0); + ~FileEngineHandler(); + + QAbstractFileEngine *create(const QString &filename) const; + + static void mount(const QString & path); + static void mount(const QString & path, const QString & mountPoint); + static void setWriteDir(const QString & path); + static void mountPacks(); + static QString errorStr(); + +// private: + static const QString scheme; +}; + +class FileEngineIterator : public QAbstractFileEngineIterator +{ +public: + FileEngineIterator(QDir::Filters filters, const QStringList & nameFilters, const QStringList & entries); + + bool hasNext() const; + QString next(); + QString currentFileName() const; +private: + QStringList m_entries; + int m_index; +}; + +#endif diff -r 31570b766315 -r ed5a6478e710 QTfrontend/util/LibavInteraction.cpp --- a/QTfrontend/util/LibavInteraction.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/util/LibavInteraction.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "LibavInteraction.h" @@ -21,7 +21,9 @@ #if VIDEOREC extern "C" { +#include "libavcodec/avcodec.h" #include "libavformat/avformat.h" +#include "libavutil/avutil.h" } #include @@ -30,13 +32,25 @@ #include "HWApplication.h" -#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54, 25, 0) -#define CodecID AVCodecID +// compatibility section +#if LIBAVCODEC_VERSION_MAJOR < 55 +#define av_codec_is_encoder(x) x->encode +#define AVCodecID CodecID +#endif + +#if LIBAVFORMAT_VERSION_MAJOR < 54 +#define avformat_find_stream_info(x, y) av_find_stream_info(x) +#define avformat_close_input(x) av_close_input_file(*(x)) +#endif + +#if LIBAVUTIL_VERSION_MAJOR < 54 +#define AVPixelFormat PixelFormat +#define AV_PIX_FMT_YUV420P PIX_FMT_YUV420P #endif struct Codec { - CodecID id; + AVCodecID id; bool isAudio; QString shortName; // used for identification QString longName; // used for displaying to user @@ -56,7 +70,7 @@ QMap formats; // test if given format supports given codec -bool FormatQueryCodec(AVOutputFormat *ofmt, enum CodecID codec_id) +bool FormatQueryCodec(AVOutputFormat *ofmt, enum AVCodecID codec_id) { #if LIBAVFORMAT_VERSION_MAJOR >= 54 return avformat_query_codec(ofmt, codec_id, FF_COMPLIANCE_NORMAL) == 1; @@ -76,11 +90,7 @@ AVCodec* pCodec = NULL; while ((pCodec = av_codec_next(pCodec))) { -#if LIBAVCODEC_VERSION_MAJOR >= 54 if (!av_codec_is_encoder(pCodec)) -#else - if (!pCodec->encode) -#endif continue; if (pCodec->type != AVMEDIA_TYPE_VIDEO && pCodec->type != AVMEDIA_TYPE_AUDIO) @@ -106,8 +116,8 @@ if (!pCodec->pix_fmts) continue; bool yuv420Supported = false; - for (const PixelFormat* pfmt = pCodec->pix_fmts; *pfmt != -1; pfmt++) - if (*pfmt == PIX_FMT_YUV420P) + for (const enum AVPixelFormat* pfmt = pCodec->pix_fmts; *pfmt != -1; pfmt++) + if (*pfmt == AV_PIX_FMT_YUV420P) { yuv420Supported = true; break; @@ -121,7 +131,7 @@ if (!pCodec->sample_fmts) continue; bool s16Supported = false; - for (const AVSampleFormat* pfmt = pCodec->sample_fmts; *pfmt != -1; pfmt++) + for (const enum AVSampleFormat* pfmt = pCodec->sample_fmts; *pfmt != -1; pfmt++) if (*pfmt == AV_SAMPLE_FMT_S16) { s16Supported = true; @@ -274,11 +284,7 @@ QByteArray utf8path = filepath.toUtf8(); if (avformat_open_input(&pContext, utf8path.data(), NULL, NULL) < 0) return ""; -#if LIBAVFORMAT_VERSION_MAJOR < 53 - if (av_find_stream_info(pContext) < 0) -#else if (avformat_find_stream_info(pContext, NULL) < 0) -#endif return ""; int s = float(pContext->duration)/AV_TIME_BASE; @@ -312,11 +318,7 @@ AVDictionaryEntry* pComment = av_dict_get(pContext->metadata, "comment", NULL, 0); if (pComment) desc += QString("\n") + pComment->value; -#if LIBAVFORMAT_VERSION_MAJOR < 53 - av_close_input_file(pContext); -#else avformat_close_input(&pContext); -#endif return desc; } diff -r 31570b766315 -r ed5a6478e710 QTfrontend/util/LibavInteraction.h --- a/QTfrontend/util/LibavInteraction.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/util/LibavInteraction.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef LIBAV_INTERACTION diff -r 31570b766315 -r ed5a6478e710 QTfrontend/util/MessageDialog.cpp --- a/QTfrontend/util/MessageDialog.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/util/MessageDialog.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,12 +13,14 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "MessageDialog.h" #include "HWApplication.h" + + int MessageDialog::ShowFatalMessage(const QString & msg, QWidget * parent) { return ShowMessage(QMessageBox::tr("Hedgewars - Error"), @@ -45,7 +47,22 @@ int MessageDialog::ShowMessage(const QString & title, const QString & msg, QMessageBox::Icon icon, QWidget * parent) { - QMessageBox msgMsg(parent ? parent : HWApplication::activeWindow()); + // if no parent try to use active window + parent = parent ? parent : HWApplication::activeWindow(); + + // didn't work? make child of hwform (e.g. for style and because modal) + if (!parent) + { + try + { + HWApplication * app = dynamic_cast(HWApplication::instance()); + if (app->form) + parent = app->form; + } + catch (...) { /* nothing */ } + } + + QMessageBox msgMsg(parent); msgMsg.setWindowTitle(title != NULL ? title : "Hedgewars"); msgMsg.setText(msg); msgMsg.setIcon(icon); diff -r 31570b766315 -r ed5a6478e710 QTfrontend/util/MessageDialog.h --- a/QTfrontend/util/MessageDialog.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/util/MessageDialog.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef MESSAGEDIALOG_H diff -r 31570b766315 -r ed5a6478e710 QTfrontend/util/SDLInteraction.cpp --- a/QTfrontend/util/SDLInteraction.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/util/SDLInteraction.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /** @@ -54,6 +54,7 @@ m_music = NULL; m_musicTrack = ""; m_isPlayingMusic = false; + lastchannel = 0; if(SDL_NumJoysticks()) addGameControllerKeys(); SDL_QuitSubSystem(SDL_INIT_JOYSTICK); @@ -174,6 +175,9 @@ SDL_JoystickClose(joy); } + if(i >= 1024) + i = 1023; + // Terminate the list sdlkeys[i][0][0] = '\0'; sdlkeys[i][1][0] = '\0'; @@ -241,7 +245,7 @@ if (m_music == NULL) m_music = Mix_LoadMUS_RW(PHYSFSRWOPS_openRead(m_musicTrack.toLocal8Bit().constData()), 0); - Mix_VolumeMusic(MIX_MAX_VOLUME - 28); + Mix_VolumeMusic(MIX_MAX_VOLUME/4); Mix_FadeInMusic(m_music, -1, 1750); } diff -r 31570b766315 -r ed5a6478e710 QTfrontend/util/SDLInteraction.h --- a/QTfrontend/util/SDLInteraction.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/util/SDLInteraction.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /** diff -r 31570b766315 -r ed5a6478e710 QTfrontend/util/namegen.cpp --- a/QTfrontend/util/namegen.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/util/namegen.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,7 +1,7 @@ /* * Hedgewars, a free turn based strategy game * Copyright (c) 2009 Martin Minarik - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff -r 31570b766315 -r ed5a6478e710 QTfrontend/util/namegen.h --- a/QTfrontend/util/namegen.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/util/namegen.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,7 +1,7 @@ /* * Hedgewars, a free turn based strategy game * Copyright (c) 2009 Martin Minarik - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef NAMEGEN_H diff -r 31570b766315 -r ed5a6478e710 QTfrontend/util/platform/CocoaInitializer.h --- a/QTfrontend/util/platform/CocoaInitializer.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/util/platform/CocoaInitializer.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ // see original example here http://el-tramo.be/blog/mixing-cocoa-and-qt diff -r 31570b766315 -r ed5a6478e710 QTfrontend/util/platform/CocoaInitializer.mm --- a/QTfrontend/util/platform/CocoaInitializer.mm Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/util/platform/CocoaInitializer.mm Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ // see original example here http://el-tramo.be/blog/mixing-cocoa-and-qt diff -r 31570b766315 -r ed5a6478e710 QTfrontend/util/platform/InstallController.cpp --- a/QTfrontend/util/platform/InstallController.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/util/platform/InstallController.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "InstallController.h" diff -r 31570b766315 -r ed5a6478e710 QTfrontend/util/platform/InstallController.h --- a/QTfrontend/util/platform/InstallController.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/util/platform/InstallController.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef INSTALLCONTROLLER_H diff -r 31570b766315 -r ed5a6478e710 QTfrontend/util/platform/M3Panel.h --- a/QTfrontend/util/platform/M3Panel.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/util/platform/M3Panel.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef M3PANEL_H diff -r 31570b766315 -r ed5a6478e710 QTfrontend/util/platform/M3Panel.mm --- a/QTfrontend/util/platform/M3Panel.mm Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/util/platform/M3Panel.mm Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "M3Panel.h" diff -r 31570b766315 -r ed5a6478e710 QTfrontend/util/platform/SparkleAutoUpdater.mm --- a/QTfrontend/util/platform/SparkleAutoUpdater.mm Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/util/platform/SparkleAutoUpdater.mm Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ // see original example here http://el-tramo.be/blog/mixing-cocoa-and-qt diff -r 31570b766315 -r ed5a6478e710 QTfrontend/util/platform/xfire.cpp --- a/QTfrontend/util/platform/xfire.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/util/platform/xfire.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include diff -r 31570b766315 -r ed5a6478e710 QTfrontend/util/platform/xfire.h --- a/QTfrontend/util/platform/xfire.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/util/platform/xfire.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ /* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef XFIRE_H diff -r 31570b766315 -r ed5a6478e710 QTfrontend/weapons.h --- a/QTfrontend/weapons.h Tue Nov 10 18:16:35 2015 +0100 +++ b/QTfrontend/weapons.h Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -22,45 +22,61 @@ //structure------------------------------------------------------------------| -#define AMMOLINE_DEFAULT_QT "93919294221991210322351110012000000002111001010111110001" -#define AMMOLINE_DEFAULT_PROB "04050405416006555465544647765766666661555101011154111111" -#define AMMOLINE_DEFAULT_DELAY "00000000000002055000000400070040000000002200000006000200" -#define AMMOLINE_DEFAULT_CRATE "13111103121111111231141111111111111112111111011111111111" +#define AMMOLINE_DEFAULT_QT "939192942219912103223511100120000000021110010101111100010" +#define AMMOLINE_DEFAULT_PROB "040504054160065554655446477657666666615551010111541111111" +#define AMMOLINE_DEFAULT_DELAY "000000000000020550000004000700400000000022000000060002000" +#define AMMOLINE_DEFAULT_CRATE "131111031211111112311411111111111111121111110111111111111" -#define AMMOLINE_CRAZY_QT "99999999999999999929999999999999992999999999099999929991" -#define AMMOLINE_CRAZY_PROB "11111101111111111111111111111111111111111111011111111111" -#define AMMOLINE_CRAZY_DELAY "00000000000000000000000000000000000000000000000000000000" -#define AMMOLINE_CRAZY_CRATE "13111103121111111231141111111111111112111101011111111111" +#define AMMOLINE_CRAZY_QT "999999999999999999299999999999999929999999990999999299919" +#define AMMOLINE_CRAZY_PROB "111111011111111111111111111111111111111111110111111111111" +#define AMMOLINE_CRAZY_DELAY "000000000000000000000000000000000000000000000000000000000" +#define AMMOLINE_CRAZY_CRATE "131111031211111112311411111111111111121111010111111111111" -#define AMMOLINE_PROMODE_QT "90900090000000000000090000000000000000000000000000000000" -#define AMMOLINE_PROMODE_PROB "00000000000000000000000000000000000000000000000000000000" -#define AMMOLINE_PROMODE_DELAY "00000000000002055000000400070040000000002000000000000200" -#define AMMOLINE_PROMODE_CRATE "11111101111111111111111111111111111111111001011111111111" +#define AMMOLINE_PROMODE_QT "909000900000000000000900000000000000000000000000000000000" +#define AMMOLINE_PROMODE_PROB "000000000000000000000000000000000000000000000000000000000" +#define AMMOLINE_PROMODE_DELAY "000000000000020550000004000700400000000020000000000002000" +#define AMMOLINE_PROMODE_CRATE "111111011111111111111111111111111111111110010111111111111" -#define AMMOLINE_SHOPPA_QT "00000099000000000000000000000000000000000000000000000000" -#define AMMOLINE_SHOPPA_PROB "44444100442444022101121212224220000000020004000100110010" -#define AMMOLINE_SHOPPA_DELAY "00000000000000000000000000000000000000000000000000000000" -#define AMMOLINE_SHOPPA_CRATE "11111101111111111111111111111111111111111011011111111110" +#define AMMOLINE_SHOPPA_QT "000000990000000000000000000000000000000000000000000000000" +#define AMMOLINE_SHOPPA_PROB "444441004424440221011212122242200000000200040001001100101" +#define AMMOLINE_SHOPPA_DELAY "000000000000000000000000000000000000000000000000000000000" +#define AMMOLINE_SHOPPA_CRATE "111111011111111111111111111111111111111110110111111111101" + +#define AMMOLINE_CLEAN_QT "101000900001000001100000000000000000000000000000100000000" +#define AMMOLINE_CLEAN_PROB "040504054160065554655446477657666666615551010111541112111" +#define AMMOLINE_CLEAN_DELAY "000000000000000000000000000000000000000000000000000002000" +#define AMMOLINE_CLEAN_CRATE "131111031211111112311411111111111111121111110111111111111" -#define AMMOLINE_CLEAN_QT "10100090000100000110000000000000000000000000000010000000" -#define AMMOLINE_CLEAN_PROB "04050405416006555465544647765766666661555101011154111211" -#define AMMOLINE_CLEAN_DELAY "00000000000000000000000000000000000000000000000000000200" -#define AMMOLINE_CLEAN_CRATE "13111103121111111231141111111111111112111111011111111111" +#define AMMOLINE_MINES_QT "000000990009000000030000000000000000000000000000000000000" +#define AMMOLINE_MINES_PROB "000000000000000000000000000000000000000000000000000000000" +#define AMMOLINE_MINES_DELAY "000000000000020550000004000700400000000020000000060002000" +#define AMMOLINE_MINES_CRATE "111111011111111111111111111111111111111111110111111111111" -#define AMMOLINE_MINES_QT "00000099000900000003000000000000000000000000000000000000" -#define AMMOLINE_MINES_PROB "00000000000000000000000000000000000000000000000000000000" -#define AMMOLINE_MINES_DELAY "00000000000002055000000400070040000000002000000006000200" -#define AMMOLINE_MINES_CRATE "11111101111111111111111111111111111111111111011111111111" +#define AMMOLINE_PORTALS_QT "900000900200000000210000000000000011000009000000000000000" +#define AMMOLINE_PORTALS_PROB "040504054160065554655446477657666666615551010111541112111" +#define AMMOLINE_PORTALS_DELAY "000000000000020550000004000700400000000020000000060002000" +#define AMMOLINE_PORTALS_CRATE "131111031211111112311411111111111111121111110111111111111" + +#define AMMOLINE_ONEEVERY_QT "111111911111111111111111111111111111111111111111111111111" +#define AMMOLINE_ONEEVERY_PROB "111111011111111111111111111111111111111111111111111111111" +#define AMMOLINE_ONEEVERY_DELAY "000000000000000000000000000000000000000000000000000000000" +#define AMMOLINE_ONEEVERY_CRATE "111111011111111111111111111111111111111111111111111111111" -#define AMMOLINE_PORTALS_QT "90000090020000000021000000000000001100000900000000000000" -#define AMMOLINE_PORTALS_PROB "04050405416006555465544647765766666661555101011154111211" -#define AMMOLINE_PORTALS_DELAY "00000000000002055000000400070040000000002000000006000200" -#define AMMOLINE_PORTALS_CRATE "13111103121111111231141111111111111112111111011111111111" +#define AMMOLINE_HIGHLANDER_QT "111111911111111111110191111111111001011111011110110011010" +#define AMMOLINE_HIGHLANDER_PROB "000000000000000000000000000000000000000000000000000000000" +#define AMMOLINE_HIGHLANDER_DELAY "000000000000000000000000000000000000000000000000000000000" +#define AMMOLINE_HIGHLANDER_CRATE "000000000000000000000000000000000000000000000000000000000" -#define AMMOLINE_ONEEVERY_QT "11111191111111111111111111111111111111111111111111111111" -#define AMMOLINE_ONEEVERY_PROB "11111101111111111111111111111111111111111111111111111111" -#define AMMOLINE_ONEEVERY_DELAY "00000000000000000000000000000000000000000000000000000000" -#define AMMOLINE_ONEEVERY_CRATE "11111101111111111111111111111111111111111111111111111111" +#define AMMOLINE_CONSTRUCTION_QT "110001900000001001000000000000000000000000000000000000000" +#define AMMOLINE_CONSTRUCTION_PROB "111111011111111111111111111111111111111111111111111111110" +#define AMMOLINE_CONSTRUCTION_DELAY "000000000000000000000000000000000000000000000000000000000" +#define AMMOLINE_CONSTRUCTION_CRATE "111111011111111111111111111111111111111111111111111111110" + +#define AMMOLINE_SHOPPAPRO_QT "000000990000000000000000000000000000000000000000000000000" +#define AMMOLINE_SHOPPAPRO_PROB "444440004404440000000000000040000000000000000000000000000" +#define AMMOLINE_SHOPPAPRO_DELAY "000000000000000000000000000000000000000000000000000000000" +#define AMMOLINE_SHOPPAPRO_CRATE "111111011111111111111111111111111111111110110111111112110" + //When adding new weapons also insert one element in cDefaultAmmos list (hwconsts.cpp.in) diff -r 31570b766315 -r ed5a6478e710 README --- a/README Tue Nov 10 18:16:35 2015 +0100 +++ b/README Tue Nov 10 20:43:13 2015 +0100 @@ -1,46 +1,1 @@ -Hedgewars - a turn based strategy game. -======================================= - -Copyright 2004-2013 Andrey Korotaev and others. -See QTfrontend/res/html/about.html and CREDITS for a complete list of authors. - -Licence: --------- -Source code is distributed under the terms of the GNU General Public Licence -version 2; images and sounds are distributed under the terms of the GNU Free -Documentation Licence version 1.2. See the COPYING file for the full text of -the licenses. - -Instructions: -------------- -See our wiki at: https://code.google.com/p/hedgewars/wiki/BuildingHedgewars - -You can find an outline of the necessary dependencies in the INSTALL file. - -Source code: ------------- -Our main repository is located at http://hedgewars.googlecode.com using -Mercurial as DVCS. A Git repository is also available (mirrored daily) -at https://github.com/hedgewars/hw - -Contribute: ------------ -If you see a bug or have any suggestion please use the official bug tracker at -http://code.google.com/p/hedgewars/issues/list or the integrated feedback -button. - -If you want to help or get to know the sources better you can do that with some -easy tasks from http://code.google.com/p/hedgewars/wiki/TODO. We also have an -extended API in LUA to customize your adventures in our wiki at -http://code.google.com/p/hedgewars/wiki/LuaAPI. - -If you know your way through the code feel free to send a patch or open a pull -request. The best LUA scripts get released in the official DLC page and later -integrated in the next version. - -Contact: --------- -* IRC channel - irc://irc.freenode.net/hedgewars -* community forum - http://www.hedgewars.org/forum -* mailing list - https://mail.gna.org/listinfo/hedgewars-dev - +README.md \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 README.md --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/README.md Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,46 @@ +Hedgewars - a turn based strategy game. +======================================= + +Copyright 2004-2015 Andrey Korotaev and others. +See QTfrontend/res/html/about.html and CREDITS for a complete list of authors. + +Licence: +-------- +Source code is distributed under the terms of the GNU General Public Licence +version 2; images and sounds are distributed under the terms of the GNU Free +Documentation Licence version 1.2. See the COPYING file for the full text of +the licenses. + +Instructions: +------------- +See our wiki at: http://hedgewars.org/kb/BuildingHedgewars + +You can find an outline of the necessary dependencies in the INSTALL file. + +Source code: +------------ +Our main repository is located at http://hg.hedgewars.org/hedgewars/ using +Mercurial as DVCS. A Git repository is also available (mirrored daily) +at https://github.com/hedgewars/hw + +Contribute: +----------- +If you see a bug or have any suggestion please use the official bug tracker at +http://code.google.com/p/hedgewars/issues/list or the integrated feedback +button. + +If you want to help or get to know the sources better you can do that with some +easy tasks from http://hedgewars.org/kb/TODO. We also have an +extended API in LUA to customize your adventures in our wiki at +http://hedgewars.org/kb/LuaAPI. + +If you know your way through the code feel free to send a patch or open a pull +request. The best LUA scripts get released in the official DLC page and later +integrated in the next version. + +Contact: +-------- +* IRC channel - irc://irc.freenode.net/hedgewars +* community forum - http://www.hedgewars.org/forum +* mailing list - https://mail.gna.org/listinfo/hedgewars-dev + diff -r 31570b766315 -r ed5a6478e710 cmake_modules/CMakePascalInformation.cmake --- a/cmake_modules/CMakePascalInformation.cmake Tue Nov 10 18:16:35 2015 +0100 +++ b/cmake_modules/CMakePascalInformation.cmake Tue Nov 10 20:43:13 2015 +0100 @@ -9,9 +9,9 @@ include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_BASE_NAME} OPTIONAL) # This section should actually be in Platform/${CMAKE_SYSTME_NAME}-fpc.cmake -set(CMAKE_Pascal_FLAGS_DEBUG_INIT "-g -gl -gp -gh") +set(CMAKE_Pascal_FLAGS_DEBUG_INIT "-O- -g -gl -gp -gh") set(CMAKE_Pascal_FLAGS_MINSIZEREL_INIT "-Os -dNDEBUG") -set(CMAKE_Pascal_FLAGS_RELEASE_INIT "-O3 -dNDEBUG") +set(CMAKE_Pascal_FLAGS_RELEASE_INIT "-O2 -dNDEBUG") set(CMAKE_Pascal_FLAGS_RELWITHDEBINFO_INIT "-O2 -g -gl -gp") # This should be included before the _INIT variables are diff -r 31570b766315 -r ed5a6478e710 cmake_modules/CheckHaskellModuleExists.cmake --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cmake_modules/CheckHaskellModuleExists.cmake Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,52 @@ +# Based on CheckLibraryExists.cmake from CMake +#============================================================================= +# Copyright 2002-2009 Kitware, Inc. +# +# Distributed under the OSI-approved BSD License +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= + +macro(CHECK_HASKELL_MODULE_EXISTS MODULE FUNCTION PARAMCOUNT LIBRARY) + set(VARIABLE "HS_MODULE_${LIBRARY}_${FUNCTION}") + if(${VARIABLE} MATCHES ^${VARIABLE}$) + message(STATUS "Looking for ${FUNCTION} in ${MODULE}") + + set(PARAMETERS "") + + if(PARAMCOUNT GREATER 0) + foreach(__TRASH__ RANGE 1 ${PARAMCOUNT}) + set(PARAMETERS "${PARAMETERS} undefined") + endforeach() + endif() + + set(PARAMETERS "") + + execute_process(COMMAND ${GHC_EXECUTABLE} + "-DMODULE=${MODULE}" + "-DFUNCTION=${FUNCTION}" + "-DPARAMETERS=${PARAMETERS}" + -cpp + -c "${CMAKE_MODULE_PATH}/checkModule.hs" + RESULT_VARIABLE COMMAND_RESULT + ERROR_VARIABLE BUILD_ERROR + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + if(${COMMAND_RESULT} EQUAL 0) + message(STATUS "Looking for ${FUNCTION} in ${MODULE} - found") + set(${VARIABLE} 1 CACHE INTERNAL "Have module ${MODULE}") + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log + "Determining if the function ${FUNCTION} exists in the ${MODULE} passed\n\n") + else() + message(STATUS "Looking for ${FUNCTION} in ${MODULE} - not found") + set(${VARIABLE} "" CACHE INTERNAL "Have module ${MODULE}") + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log + "Determining if the function ${FUNCTION} exists in the ${MODULE} " + "failed with the following output:\n" + "${BUILD_ERROR}\n\n") + message(FATAL_ERROR "Haskell library '${LIBRARY}' required") + endif() + endif() +endmacro() diff -r 31570b766315 -r ed5a6478e710 cmake_modules/FindClang.cmake --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cmake_modules/FindClang.cmake Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,36 @@ +# - Try to find the Clang/LLVM executable +# Once done this will define +# +# CLANG_FOUND - system has Clang +# CLANG_VERSION - Clang version +# CLANG_EXECUTABLE - Clang executable +# +# Copyright (c) 2013, Vittorio Giovara +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +find_program(CLANG_EXECUTABLE + NAMES clang-mp-3.3 clang-mp-3.2 clang-mp-3.1 clang-mp-3.0 clang + PATHS /opt/local/bin /usr/local/bin /usr/bin) + +if (CLANG_EXECUTABLE) + execute_process(COMMAND ${CLANG_EXECUTABLE} --version + OUTPUT_VARIABLE CLANG_VERSION_OUTPUT + ERROR_VARIABLE CLANG_VERSION_ERROR + RESULT_VARIABLE CLANG_VERSION_RESULT + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + + if(${CLANG_VERSION_RESULT} EQUAL 0) + string(REGEX MATCH "[0-9]+\\.[0-9]+" CLANG_VERSION "${CLANG_VERSION_OUTPUT}") + string(REGEX REPLACE "([0-9]+\\.[0-9]+)" "\\1" CLANG_VERSION "${CLANG_VERSION}") + else() + message(SEND_ERROR "Command \"${CLANG_EXECUTABLE} --version\" failed with output: ${CLANG_VERSION_ERROR}") + endif() +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(Clang DEFAULT_MSG CLANG_EXECUTABLE CLANG_VERSION) +mark_as_advanced(CLANG_VERSION) + diff -r 31570b766315 -r ed5a6478e710 cmake_modules/FindFFMPEG.cmake --- a/cmake_modules/FindFFMPEG.cmake Tue Nov 10 18:16:35 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,85 +0,0 @@ -# Find ffmpeg/libav libraries (libavcodec, libavformat and libavutil) -# Once done this will define -# -# FFMPEG_FOUND - system has libavcodec, libavformat, libavutil -# FFMPEG_INCLUDE_DIR - the libav include directories -# FFMPEG_LIBRARIES - the libav libraries -# -# LIBAVCODEC_LIBRARY - the libavcodec library -# LIBAVCODEC_INCLUDE_DIR - the libavcodec include directory -# LIBAVFORMAT_LIBRARY - the libavformat library -# LIBAVUTIL_LIBRARY - the libavutil library -# -# Copyright (c) 2008 Andreas Schneider -# Modified for other libraries by Lasse Kärkkäinen -# Modified for Hedgewars by Stepik777 -# Copyright (c) 2013 Vittorio Giovara -# -# Redistribution and use is allowed according to the terms of the New -# BSD license. -# - -include(FindPackageHandleStandardArgs) - - -# use pkg-config to get the directories and then use these values -# in the FIND_PATH() and FIND_LIBRARY() calls -find_package(PkgConfig) -if(PKG_CONFIG_FOUND) - if(NOT LIBAVCODEC_INCLUDE_DIR OR NOT LIBAVCODEC_LIBRARY) - pkg_check_modules(_FFMPEG_AVCODEC libavcodec) - endif() - if(NOT LIBAVFORMAT_LIBRARY) - pkg_check_modules(_FFMPEG_AVFORMAT libavformat) - endif() - if(NOT LIBAVUTIL_LIBRARY) - pkg_check_modules(_FFMPEG_AVUTIL libavutil) - endif() -endif(PKG_CONFIG_FOUND) - -find_path(LIBAVCODEC_INCLUDE_DIR - NAMES libavcodec/avcodec.h - PATHS ${_FFMPEG_AVCODEC_INCLUDE_DIRS} #pkg-config - /usr/include /usr/local/include #system level - /opt/local/include /sw/include #macports & fink - PATH_SUFFIXES libav ffmpeg -) - -#TODO: add other include paths - -find_library(LIBAVCODEC_LIBRARY - NAMES avcodec - PATHS ${_FFMPEG_AVCODEC_LIBRARY_DIRS} #pkg-config - /usr/lib /usr/local/lib #system level - /opt/local/lib /sw/lib #macports & fink -) - -find_library(LIBAVFORMAT_LIBRARY - NAMES avformat - PATHS ${_FFMPEG_AVFORMAT_LIBRARY_DIRS} #pkg-config - /usr/lib /usr/local/lib #system level - /opt/local/lib /sw/lib #macports & fink -) - -find_library(LIBAVUTIL_LIBRARY - NAMES avutil - PATHS ${_FFMPEG_AVUTIL_LIBRARY_DIRS} #pkg-config - /usr/lib /usr/local/lib #system level - /opt/local/lib /sw/lib #macports & fink -) - -find_package_handle_standard_args(FFMPEG DEFAULT_MSG LIBAVCODEC_LIBRARY LIBAVCODEC_INCLUDE_DIR - LIBAVFORMAT_LIBRARY - LIBAVUTIL_LIBRARY - ) -set(FFMPEG_INCLUDE_DIR ${LIBAVCODEC_INCLUDE_DIR} - #TODO: add other include paths - ) -set(FFMPEG_LIBRARIES ${LIBAVCODEC_LIBRARY} - ${LIBAVFORMAT_LIBRARY} - ${LIBAVUTIL_LIBRARY} - ) - -mark_as_advanced(FFMPEG_INCLUDE_DIR FFMPEG_LIBRARIES LIBAVCODEC_LIBRARY LIBAVCODEC_INCLUDE_DIR LIBAVFORMAT_LIBRARY LIBAVUTIL_LIBRARY) - - diff -r 31570b766315 -r ed5a6478e710 cmake_modules/FindGHC.cmake --- a/cmake_modules/FindGHC.cmake Tue Nov 10 18:16:35 2015 +0100 +++ b/cmake_modules/FindGHC.cmake Tue Nov 10 20:43:13 2015 +0100 @@ -17,7 +17,7 @@ ) if (GHC_EXECUTABLE) - # check Freepascal version + # check ghc version execute_process(COMMAND ${GHC_EXECUTABLE} -V OUTPUT_VARIABLE GHC_VERSION_OUTPUT ERROR_VARIABLE GHC_VERSION_ERROR diff -r 31570b766315 -r ed5a6478e710 cmake_modules/FindGLEW.cmake --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cmake_modules/FindGLEW.cmake Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,39 @@ +# Find GLEW +# +# Once done this will define +# GLEW_FOUND - system has GLEW +# GLEW_INCLUDE_DIR - the GLEW include directory +# GLEW_LIBRARY - The library needed to use GLEW +# Copyright (c) 2013, Vittorio Giovara +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. + +include(FindPackageHandleStandardArgs) + +find_path( GLEW_INCLUDE_DIR GL/glew.h + /usr/include + /usr/local/include + /sw/include + /opt/local/include + $ENV{PROGRAMFILES}/GLEW/include + DOC "The directory where GL/glew.h resides") +find_library( GLEW_LIBRARY + NAMES GLEW glew glew32 glew32s + PATHS + /usr/lib64 + /usr/lib + /usr/local/lib64 + /usr/local/lib + /sw/lib + /opt/local/lib + $ENV{PROGRAMFILES}/GLEW/lib + DOC "The GLEW library") + +find_package_handle_standard_args(GLEW DEFAULT_MSG GLEW_LIBRARY GLEW_INCLUDE_DIR) +mark_as_advanced(GLEW_LIBRARY GLEW_INCLUDE_DIR) + diff -r 31570b766315 -r ed5a6478e710 cmake_modules/FindLIBAV.cmake --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cmake_modules/FindLIBAV.cmake Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,90 @@ +# Find ffmpeg/libav libraries (libavcodec, libavformat and libavutil) +# Once done this will define +# +# LIBAV_FOUND - system has libavcodec, libavformat, libavutil +# LIBAV_INCLUDE_DIR - libav include directories +# LIBAV_LIBRARIES - libav libraries (libavcodec, libavformat, libavutil) +# +# LIBAVCODEC_LIBRARY - libavcodec library +# LIBAVCODEC_INCLUDE_DIR - libavcodec include directory +# LIBAVFORMAT_LIBRARY - libavformat library +# LIBAVUTIL_LIBRARY - libavutil library +# +# Copyright (c) 2008 Andreas Schneider +# Modified for other libraries by Lasse Kärkkäinen +# Modified for Hedgewars by Stepik777 +# Copyright (c) 2013 Vittorio Giovara +# +# Redistribution and use is allowed according to the terms of the New +# BSD license. +# + +include(FindPackageHandleStandardArgs) + + +# use pkg-config to get the directories and then use these values +# in the FIND_PATH() and FIND_LIBRARY() calls +find_package(PkgConfig) +if(PKG_CONFIG_FOUND) + if(NOT LIBAVCODEC_INCLUDE_DIR OR NOT LIBAVCODEC_LIBRARY) + pkg_check_modules(_LIBAV_AVCODEC libavcodec) + endif() + if(NOT LIBAVFORMAT_LIBRARY) + pkg_check_modules(_LIBAV_AVFORMAT libavformat) + endif() + if(NOT LIBAVUTIL_LIBRARY) + pkg_check_modules(_LIBAV_AVUTIL libavutil) + endif() +endif(PKG_CONFIG_FOUND) + +find_path(LIBAVCODEC_INCLUDE_DIR + NAMES libavcodec/avcodec.h + PATHS ${_LIBAV_AVCODEC_INCLUDE_DIRS} #pkg-config + /usr/include /usr/local/include #system level + /opt/local/include /sw/include #macports & fink + PATH_SUFFIXES libav ffmpeg +) + +#TODO: add other include paths + +find_library(LIBAVCODEC_LIBRARY + NAMES avcodec + PATHS ${_LIBAV_AVCODEC_LIBRARY_DIRS} #pkg-config + /usr/lib /usr/local/lib #system level + /opt/local/lib /sw/lib #macports & fink +) + +find_library(LIBAVFORMAT_LIBRARY + NAMES avformat + PATHS ${_LIBAV_AVFORMAT_LIBRARY_DIRS} #pkg-config + /usr/lib /usr/local/lib #system level + /opt/local/lib /sw/lib #macports & fink +) + +find_library(LIBAVUTIL_LIBRARY + NAMES avutil + PATHS ${_LIBAV_AVUTIL_LIBRARY_DIRS} #pkg-config + /usr/lib /usr/local/lib #system level + /opt/local/lib /sw/lib #macports & fink +) + +find_package_handle_standard_args(LIBAV DEFAULT_MSG LIBAVCODEC_LIBRARY + LIBAVCODEC_INCLUDE_DIR + LIBAVFORMAT_LIBRARY + LIBAVUTIL_LIBRARY + ) +set(LIBAV_INCLUDE_DIR ${LIBAVCODEC_INCLUDE_DIR} + #TODO: add other include paths + ) +set(LIBAV_LIBRARIES ${LIBAVCODEC_LIBRARY} + ${LIBAVFORMAT_LIBRARY} + ${LIBAVUTIL_LIBRARY} + ) + +mark_as_advanced(LIBAV_INCLUDE_DIR + LIBAV_LIBRARIES + LIBAVCODEC_LIBRARY + LIBAVCODEC_INCLUDE_DIR + LIBAVFORMAT_LIBRARY + LIBAVUTIL_LIBRARY) + diff -r 31570b766315 -r ed5a6478e710 cmake_modules/FindLua.cmake --- a/cmake_modules/FindLua.cmake Tue Nov 10 18:16:35 2015 +0100 +++ b/cmake_modules/FindLua.cmake Tue Nov 10 20:43:13 2015 +0100 @@ -17,7 +17,7 @@ find_path(LUA_INCLUDE_DIR lua.h PATHS /usr/include /usr/local/include /usr/pkg/include - PATH_SUFFIXES lua5.1 lua51) + PATH_SUFFIXES lua5.1 lua51 lua-5.1) find_library(LUA_LIBRARY NAMES lua51 lua5.1 lua-5.1 lua PATHS /lib /usr/lib /usr/local/lib /usr/pkg/lib) diff -r 31570b766315 -r ed5a6478e710 cmake_modules/TargetArch.cmake --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cmake_modules/TargetArch.cmake Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,142 @@ +# Original file location https://github.com/petroules/solar-cmake/blob/master/TargetArch.cmake +#Copyright (c) 2012 Petroules Corporation. All rights reserved. +#Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: +# +# 1 Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +# 2 Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# Based on the Qt 5 processor detection code, so should be very accurate +# https://qt.gitorious.org/qt/qtbase/blobs/master/src/corelib/global/qprocessordetection.h +# Currently handles arm (v5, v6, v7), x86 (32/64), ia64, and ppc (32/64) + +# Regarding POWER/PowerPC, just as is noted in the Qt source, +# "There are many more known variants/revisions that we do not handle/detect." + +set(archdetect_c_code " +#if defined(__arm__) || defined(__TARGET_ARCH_ARM) + #if defined(__ARM_ARCH_7__) \\ + || defined(__ARM_ARCH_7A__) \\ + || defined(__ARM_ARCH_7R__) \\ + || defined(__ARM_ARCH_7M__) \\ + || (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 7) + #error cmake_ARCH armv7 + #elif defined(__ARM_ARCH_6__) \\ + || defined(__ARM_ARCH_6J__) \\ + || defined(__ARM_ARCH_6T2__) \\ + || defined(__ARM_ARCH_6Z__) \\ + || defined(__ARM_ARCH_6K__) \\ + || defined(__ARM_ARCH_6ZK__) \\ + || defined(__ARM_ARCH_6M__) \\ + || (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 6) + #error cmake_ARCH armv6 + #elif defined(__ARM_ARCH_5TEJ__) \\ + || (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 5) + #error cmake_ARCH armv5 + #else + #error cmake_ARCH arm + #endif +#elif defined(__i386) || defined(__i386__) || defined(_M_IX86) + #error cmake_ARCH i386 +#elif defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(_M_X64) + #error cmake_ARCH x86_64 +#elif defined(__ia64) || defined(__ia64__) || defined(_M_IA64) + #error cmake_ARCH ia64 +#elif defined(__ppc__) || defined(__ppc) || defined(__powerpc__) \\ + || defined(_ARCH_COM) || defined(_ARCH_PWR) || defined(_ARCH_PPC) \\ + || defined(_M_MPPC) || defined(_M_PPC) + #if defined(__ppc64__) || defined(__powerpc64__) || defined(__64BIT__) + #error cmake_ARCH ppc64 + #else + #error cmake_ARCH ppc + #endif +#endif + +#error cmake_ARCH unknown +") + +# Set ppc_support to TRUE before including this file or ppc and ppc64 +# will be treated as invalid architectures since they are no longer supported by Apple + +function(target_architecture output_var) + if(APPLE AND CMAKE_OSX_ARCHITECTURES) + # On OS X we use CMAKE_OSX_ARCHITECTURES *if* it was set + # First let's normalize the order of the values + + # Note that it's not possible to compile PowerPC applications if you are using + # the OS X SDK version 10.6 or later - you'll need 10.4/10.5 for that, so we + # disable it by default + # See this page for more information: + # http://stackoverflow.com/questions/5333490/how-can-we-restore-ppc-ppc64-as-well-as-full-10-4-10-5-sdk-support-to-xcode-4 + + # Architecture defaults to i386 or ppc on OS X 10.5 and earlier, depending on the CPU type detected at runtime. + # On OS X 10.6+ the default is x86_64 if the CPU supports it, i386 otherwise. + + foreach(osx_arch ${CMAKE_OSX_ARCHITECTURES}) + if("${osx_arch}" STREQUAL "ppc" AND ppc_support) + set(osx_arch_ppc TRUE) + elseif("${osx_arch}" STREQUAL "i386") + set(osx_arch_i386 TRUE) + elseif("${osx_arch}" STREQUAL "x86_64") + set(osx_arch_x86_64 TRUE) + elseif("${osx_arch}" STREQUAL "ppc64" AND ppc_support) + set(osx_arch_ppc64 TRUE) + else() + message(FATAL_ERROR "Invalid OS X arch name: ${osx_arch}") + endif() + endforeach() + + # Now add all the architectures in our normalized order + if(osx_arch_ppc) + list(APPEND ARCH ppc) + endif() + + if(osx_arch_i386) + list(APPEND ARCH i386) + endif() + + if(osx_arch_x86_64) + list(APPEND ARCH x86_64) + endif() + + if(osx_arch_ppc64) + list(APPEND ARCH ppc64) + endif() + else() + file(WRITE "${CMAKE_BINARY_DIR}/arch.c" "${archdetect_c_code}") + + enable_language(C) + + # Detect the architecture in a rather creative way... + # This compiles a small C program which is a series of ifdefs that selects a + # particular #error preprocessor directive whose message string contains the + # target architecture. The program will always fail to compile (both because + # file is not a valid C program, and obviously because of the presence of the + # #error preprocessor directives... but by exploiting the preprocessor in this + # way, we can detect the correct target architecture even when cross-compiling, + # since the program itself never needs to be run (only the compiler/preprocessor) + try_run( + run_result_unused + compile_result_unused + "${CMAKE_BINARY_DIR}" + "${CMAKE_BINARY_DIR}/arch.c" + COMPILE_OUTPUT_VARIABLE ARCH + CMAKE_FLAGS CMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES} + ) + + # Parse the architecture name from the compiler output + string(REGEX MATCH "cmake_ARCH ([a-zA-Z0-9_]+)" ARCH "${ARCH}") + + # Get rid of the value marker leaving just the architecture name + string(REPLACE "cmake_ARCH " "" ARCH "${ARCH}") + + # If we are compiling with an unknown architecture this variable should + # already be set to "unknown" but in the case that it's empty (i.e. due + # to a typo in the code), then set it to unknown + if (NOT ARCH) + set(ARCH unknown) + endif() + endif() + + set(${output_var} "${ARCH}" PARENT_SCOPE) +endfunction() diff -r 31570b766315 -r ed5a6478e710 cmake_modules/checkModule.hs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cmake_modules/checkModule.hs Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,5 @@ +module Main where + +import qualified MODULE as M + +main = undefined $ M.FUNCTION PARAMETERS diff -r 31570b766315 -r ed5a6478e710 cmake_modules/compilerchecks.cmake --- a/cmake_modules/compilerchecks.cmake Tue Nov 10 18:16:35 2015 +0100 +++ b/cmake_modules/compilerchecks.cmake Tue Nov 10 20:43:13 2015 +0100 @@ -62,7 +62,7 @@ endif() endif() - if(CMAKE_BUILD_TYPE MATCHES "RELEASE") + if(CMAKE_BUILD_TYPE MATCHES "RELEASE" OR CMAKE_BUILD_TYPE MATCHES "RELWITHDEBINFO") set(CMAKE_REQUIRED_FLAGS "-Wl,--as-needed") check_c_compiler_flag("" HAVE_ASNEEDED) if(HAVE_ASNEEDED) diff -r 31570b766315 -r ed5a6478e710 cmake_modules/cpackvars.cmake --- a/cmake_modules/cpackvars.cmake Tue Nov 10 18:16:35 2015 +0100 +++ b/cmake_modules/cpackvars.cmake Tue Nov 10 20:43:13 2015 +0100 @@ -35,6 +35,7 @@ ".swp" #version control "\\\\.hg" + "\\\\.git" "\\\\.orig$" #output binary/library "\\\\.exe$" @@ -84,11 +85,14 @@ "cmake_uninstall\\\\.cmake$" "CMakeCache\\\\.txt$" "build_windows_.*\\\\.bat$" - "^${CMAKE_CURRENT_SOURCE_DIR}/misc/liblua" + "arch\\\\.c$" +# "^${CMAKE_CURRENT_SOURCE_DIR}/misc/liblua" # "^${CMAKE_CURRENT_SOURCE_DIR}/project_files/frontlib" # "^${CMAKE_CURRENT_SOURCE_DIR}/project_files/cmdlineClient" "^${CMAKE_CURRENT_SOURCE_DIR}/misc/winutils/bin" "^${CMAKE_CURRENT_SOURCE_DIR}/project_files/promotional_art" + "^${CMAKE_CURRENT_SOURCE_DIR}/project_files/AudioMono" + "^${CMAKE_CURRENT_SOURCE_DIR}/project_files/HedgewarsMobile" "^${CMAKE_CURRENT_SOURCE_DIR}/tools/templates" "^${CMAKE_CURRENT_SOURCE_DIR}/tools/drawMapTest" "^${CMAKE_CURRENT_SOURCE_DIR}/doc" diff -r 31570b766315 -r ed5a6478e710 cmake_modules/paths.cmake --- a/cmake_modules/paths.cmake Tue Nov 10 18:16:35 2015 +0100 +++ b/cmake_modules/paths.cmake Tue Nov 10 20:43:13 2015 +0100 @@ -14,14 +14,14 @@ #resource paths if(UNIX AND NOT APPLE) - set(target_binary_install_dir "bin") - set(target_library_install_dir "lib") + set(target_binary_install_dir "bin" CACHE PATH "install dest for binaries") + set(target_library_install_dir "lib${LIB_SUFFIX}" CACHE PATH "install dest for libs") string(SUBSTRING "${DATA_INSTALL_DIR}" 0 1 sharepath_start) - if (NOT (${sharepath_start} MATCHES "/")) + if(${sharepath_start} MATCHES "/") + set(HEDGEWARS_DATADIR "${DATA_INSTALL_DIR}/") + else() set(HEDGEWARS_DATADIR "${CMAKE_INSTALL_PREFIX}/${DATA_INSTALL_DIR}/") - else() - set(HEDGEWARS_DATADIR "${DATA_INSTALL_DIR}/") endif() set(HEDGEWARS_FULL_DATADIR "${HEDGEWARS_DATADIR}") else() @@ -55,14 +55,17 @@ #which point to directories outside the build tree to the install RPATH set(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE) -#paths where to find libraries (final slash not optional): -# - the first is relative to the executable -# - the second is the same directory of the executable (so it runs in bin/) -# - the third one is the full path of the system dir -#source http://www.cmake.org/pipermail/cmake/2008-January/019290.html -set(CMAKE_INSTALL_RPATH "$ORIGIN/../${target_library_install_dir}/:$ORIGIN/:${CMAKE_INSTALL_PREFIX}/${target_library_install_dir}/") - - -#install_name_tool magic for OS X -set(CMAKE_INSTALL_NAME_DIR "@executable_path/../Frameworks") - +if(APPLE) + #@rpath mangling + set(CMAKE_INSTALL_RPATH "@executable_path/../Frameworks") + #install_name_tool for libraries + set(CMAKE_INSTALL_NAME_DIR "@executable_path/../Frameworks") +else(APPLE AND NOT (${CMAKE_INSTALL_PREFIX} MATCHES "/usr")) + #paths where to find libraries (final slash not optional): + # - the first is relative to the executable + # - the second is the same directory of the executable (so it runs in bin/) + # - the third one is the full path of the system dir + #source http://www.cmake.org/pipermail/cmake/2008-January/019290.html + #skip this if the install prefix is the standard one + set(CMAKE_INSTALL_RPATH "$ORIGIN/../${target_library_install_dir}/:$ORIGIN/:${CMAKE_INSTALL_PREFIX}/${target_library_install_dir}/") +endif(APPLE) diff -r 31570b766315 -r ed5a6478e710 cmake_modules/platform.cmake --- a/cmake_modules/platform.cmake Tue Nov 10 18:16:35 2015 +0100 +++ b/cmake_modules/platform.cmake Tue Nov 10 20:43:13 2015 +0100 @@ -31,30 +31,15 @@ set(minimum_macosx_version ${current_macosx_version}) endif() - #lower systems don't have enough processing power anyway - if (minimum_macosx_version VERSION_LESS "10.4") - message(FATAL_ERROR "Hedgewars is not supported on Mac OS X pre-10.4") - endif() - - #gcc is EOL on these systems - if (current_macosx_version VERSION_GREATER "10.8") - set(CMAKE_C_COMPILER clang) - set(CMAKE_CXX_COMPILER clang++) - endif() - - #workaround for http://playcontrol.net/ewing/jibberjabber/big_behind-the-scenes_chang.html#SDL_mixer (Update 2) - if(current_macosx_version VERSION_EQUAL "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") - add_flag_append(CMAKE_C_FLAGS "${DYLIB_SMPEG} ${DYLIB_MIKMOD}") - add_flag_append(CMAKE_CXX_FLAGS "${DYLIB_SMPEG} ${DYLIB_MIKMOD}") - add_flag_append(CMAKE_Pascal_FLAGS "-k${DYLIB_SMPEG} -k${DYLIB_MIKMOD}") + #10.3 systems don't have enough processing power anyway + #10.4 does not have @rpath support (which SDL uses) + if(minimum_macosx_version VERSION_LESS "10.5") + message(FATAL_ERROR "Hedgewars is not supported on your version of Mac OS X") endif() if(NOT CMAKE_OSX_ARCHITECTURES) if(current_macosx_version VERSION_LESS "10.6") - #SDL is only 32 bit on lower OS + #SDL is only 32 bit on older OS version if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "powerpc*") set(CMAKE_OSX_ARCHITECTURES "ppc7400") else() @@ -79,7 +64,7 @@ endif() list(LENGTH CMAKE_OSX_ARCHITECTURES num_of_archs) if(num_of_archs GREATER 1) - message(${WARNING} "Only one architecture in CMAKE_OSX_ARCHITECTURES is currently supported, picking the first one") + message("*** Only one architecture in CMAKE_OSX_ARCHITECTURES is supported, picking the first one ***") endif() elseif(CMAKE_SIZEOF_VOID_P MATCHES "8") #if that variable is not set check if we are on x86_64 and if so force it, else use default @@ -88,24 +73,36 @@ #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} VERSION_EQUAL ${current_macosx_version}) - if(minimum_macosx_version VERSION_EQUAL "10.4") - set(CMAKE_OSX_SYSROOT "/Developer/SDKs/MacOSX10.4u.sdk/") - set(CMAKE_C_COMPILER "/Developer/usr/bin/gcc-4.0") - set(CMAKE_CXX_COMPILER "/Developer/usr/bin/g++-4.0") + if(NOT CMAKE_OSX_SYSROOT AND + NOT ${minimum_macosx_version} VERSION_EQUAL ${current_macosx_version}) + find_program(xcrun xcrun) + if(xcrun) + execute_process(COMMAND ${xcrun} "--show-sdk-path" + OUTPUT_VARIABLE current_sdk_path + OUTPUT_STRIP_TRAILING_WHITESPACE) + string(REPLACE "${current_macosx_version}" + "${minimum_macosx_version}" + CMAKE_OSX_SYSROOT + "${current_sdk_path}") 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/") + message("*** xcrun not found! Build will work on ${current_macosx_version} only ***") endif() + endif() + if(CMAKE_OSX_SYSROOT) add_flag_append(CMAKE_Pascal_FLAGS "-XR${CMAKE_OSX_SYSROOT}") add_flag_append(CMAKE_Pascal_FLAGS "-k-macosx_version_min -k${minimum_macosx_version}") + add_flag_append(CMAKE_Pascal_FLAGS "-k-L${LIBRARY_OUTPUT_PATH} -Fl${LIBRARY_OUTPUT_PATH}") endif() #add user framework directory add_flag_append(CMAKE_Pascal_FLAGS "-Ff~/Library/Frameworks") - #workaround most of the -Fl settings getting lost - add_flag_append(CMAKE_Pascal_FLAGS "-k-L${LIBRARY_OUTPUT_PATH}") + #workaround older cmake versions + if(${CMAKE_VERSION} VERSION_LESS "2.8.12") + add_flag_append(CMAKE_C_LINK_FLAGS "-Wl,-rpath -Wl,${CMAKE_INSTALL_RPATH}") + add_flag_append(CMAKE_CXX_LINK_FLAGS "-Wl,-rpath -Wl,${CMAKE_INSTALL_RPATH}") + add_flag_append(CMAKE_Pascal_LINK_FLAGS "-k-rpath -k${CMAKE_INSTALL_RPATH}") + endif() endif(APPLE) if(MINGW) @@ -123,5 +120,4 @@ if(UNIX) add_flag_append(CMAKE_C_FLAGS "-fPIC") add_flag_append(CMAKE_CXX_FLAGS "-fPIC") - add_flag_append(CMAKE_Pascal_FLAGS "-fPIC") endif(UNIX) diff -r 31570b766315 -r ed5a6478e710 cmake_modules/revinfo.cmake --- a/cmake_modules/revinfo.cmake Tue Nov 10 18:16:35 2015 +0100 +++ b/cmake_modules/revinfo.cmake Tue Nov 10 20:43:13 2015 +0100 @@ -1,11 +1,12 @@ #detect Mercurial revision and init rev/hash information find_program(HGCOMMAND hg) -if(HGCOMMAND AND (EXISTS ${CMAKE_SOURCE_DIR}/.hg)) +find_program(GITCOMMAND git) +if(EXISTS ${CMAKE_SOURCE_DIR}/.hg AND HGCOMMAND AND NOT NOVERSIONINFOUPDATE) execute_process(COMMAND ${HGCOMMAND} identify -in WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} OUTPUT_VARIABLE internal_version - ERROR_QUIET - ) + ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE + ) #check local repo status string(REGEX REPLACE "[^+]" "" HGCHANGED ${internal_version}) string(REGEX REPLACE "[0-9a-zA-Z]+(.*) ([0-9]+)(.*)" "\\2" HEDGEWARS_REVISION ${internal_version}) @@ -14,8 +15,23 @@ if(HGCHANGED) message("*** You have uncommitted changes in your repository ***") endif() + #let's assume that if you have hg you might be interested in debugging set(default_build_type "DEBUG") + + #write down hash and rev for easy picking should hg be missing + file(WRITE "${CMAKE_SOURCE_DIR}/share/version_info.txt" "Hedgewars versioning information, do not modify\nrev ${HEDGEWARS_REVISION}\nhash ${HEDGEWARS_HASH}\n") +elseif(EXISTS ${CMAKE_SOURCE_DIR}/.git AND GITCOMMAND AND NOT NOVERSIONINFOUPDATE) + execute_process(COMMAND ${GITCOMMAND} rev-parse --short HEAD + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + OUTPUT_VARIABLE HEDGEWARS_HASH + ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE + ) + set(HEDGEWARS_REVISION "GIT") + + #let's assume that if you have git you might be interested in debugging + set(default_build_type "DEBUG") + #write down hash and rev for easy picking should hg be missing file(WRITE "${CMAKE_SOURCE_DIR}/share/version_info.txt" "Hedgewars versioning information, do not modify\nrev ${HEDGEWARS_REVISION}\nhash ${HEDGEWARS_HASH}\n") else() @@ -24,7 +40,7 @@ find_file(version_info version_info.txt PATH ${CMAKE_SOURCE_DIR}/share) if(version_info) file(STRINGS ${version_info} internal_version REGEX "rev") - string(REGEX REPLACE "rev ([0-9]*)" "\\1" HEDGEWARS_REVISION ${internal_version}) + string(REGEX REPLACE "rev ([GIT0-9]*)" "\\1" HEDGEWARS_REVISION ${internal_version}) file(STRINGS ${version_info} internal_version REGEX "hash") string(REGEX REPLACE "hash ([a-zA-Z0-9]*)" "\\1" HEDGEWARS_HASH ${internal_version}) else() diff -r 31570b766315 -r ed5a6478e710 doc/protocol.txt --- a/doc/protocol.txt Tue Nov 10 18:16:35 2015 +0100 +++ b/doc/protocol.txt Tue Nov 10 20:43:13 2015 +0100 @@ -18,12 +18,15 @@ 'E' + <текст> сообщение об ошибке ',' /skip 't' + № /taunt № + 'f' + 'team' is uncontrolled + 'g' + 'team' is controlled again (synced msg) фронтенд клиенту: 'e' + <команда> выполнить "/<команда>" 'T' + {L,N,D} тип игры (локальная, сетевая, просмотр демо) 'W' + <текст> сообщение о нефатальной ошибке 'F' + команда team вылетела в сетевой игре + 'G' + 'team' is back (unsynced msg) 'o' stop syncing, game over! Клиент фронтенду: diff -r 31570b766315 -r ed5a6478e710 gameServer/Actions.hs --- a/gameServer/Actions.hs Tue Nov 10 18:16:35 2015 +0100 +++ b/gameServer/Actions.hs Tue Nov 10 20:43:13 2015 +0100 @@ -1,3 +1,21 @@ +{- + * Hedgewars, a free turn based strategy game + * Copyright (c) 2004-2015 Andrey Korotaev + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + \-} + {-# LANGUAGE CPP, OverloadedStrings, ScopedTypeVariables #-} {-# OPTIONS_GHC -fno-warn-orphans #-} module Actions where @@ -33,10 +51,9 @@ import Consts import ConfigFile import EngineInteraction - - -type CmdHandler = [B.ByteString] -> Reader (ClientIndex, IRnC) [Action] - +import FloodDetection +import HWProtoCore +import Votes othersChans :: StateT ServerState IO [ClientChan] othersChans = do @@ -180,6 +197,7 @@ mapM_ processAction [ AnswerClients chans ["JOINED", clNick] , AnswerClients allClientsChans ["CLIENT_FLAGS", "+i", clNick] + , RegisterEvent RoomJoin ] @@ -221,7 +239,10 @@ ri <- clientRoomA rnc <- gets roomsClients specialRoom <- io $ room'sM rnc isSpecial ri - newMasterId <- liftM (\ids -> fromMaybe (listToMaybe . reverse . filter (/= ci) $ ids) $ liftM Just delegateId) . io $ roomClientsIndicesM rnc ri + newMasterId <- if specialRoom then + return delegateId + else + liftM (\ids -> fromMaybe (listToMaybe . reverse . filter (/= ci) $ ids) $ liftM Just delegateId) . io $ roomClientsIndicesM rnc ri newMaster <- io $ client'sM rnc id `DT.mapM` newMasterId oldMasterId <- io $ room'sM rnc masterID ri oldRoomName <- io $ room'sM rnc name ri @@ -327,14 +348,17 @@ thisRoomChans <- liftM (map sendChan) $ roomClientsS ri joinedMidGame <- liftM (filter isJoinedMidGame) $ roomClientsS ri answerRemovedTeams <- io $ - room'sM rnc (\r -> let gi = fromJust $ gameInfo r in - concatMap (\c -> + room'sM rnc (\r -> let gi = fromJust $ gameInfo r in + concatMap (\c -> (answerFullConfigParams c (mapParams r) (params r)) ++ - (map (\t -> AnswerClients [sendChan c] ["REMOVE_TEAM", t]) $ leftTeams gi) + (map (\t -> AnswerClients [sendChan c] ["REMOVE_TEAM", t]) $ leftTeams gi) ) joinedMidGame ) ri + rteams <- io $ room'sM rnc (L.nub . rejoinedTeams . fromJust . gameInfo) ri + mapM_ (processAction . RemoveTeam) rteams + mapM_ processAction $ ( SaveReplay : ModifyRoom @@ -357,8 +381,9 @@ ModifyRoom (\r -> r{ gameInfo = liftM (\g -> g{ teamsInGameNumber = teamsInGameNumber g - 1 - , roundMsgs = (if isJust $ lastFilteredTimedMsg g then (:) (fromJust $ lastFilteredTimedMsg g) else id) - $ rmTeamMsg : roundMsgs g + , lastFilteredTimedMsg = Nothing + , roundMsgs = (if isJust $ lastFilteredTimedMsg g then ((:) rmTeamMsg . (:) (fromJust $ lastFilteredTimedMsg g)) else ((:) rmTeamMsg)) + $ roundMsgs g }) $ gameInfo r }) ] @@ -394,15 +419,25 @@ processAction RemoveClientTeams = do (Just ci) <- gets clientIndex rnc <- gets roomsClients + n <- client's nick removeTeamActions <- io $ do rId <- clientRoomM rnc ci roomTeams <- room'sM rnc teams rId - return . Prelude.map (RemoveTeam . teamname) . Prelude.filter (\t -> teamownerId t == ci) $ roomTeams + return . Prelude.map (RemoveTeam . teamname) . Prelude.filter (\t -> teamowner t == n) $ roomTeams mapM_ processAction removeTeamActions +processAction SetRandomSeed = do + ri <- clientRoomA + thisRoomChans <- liftM (map sendChan) $ roomClientsS ri + seed <- liftM showB $ io $ (randomRIO (0, 10^9) :: IO Int) + mapM_ processAction [ + ModifyRoom (\r -> r{mapParams = Map.insert "SEED" seed $ mapParams r}) + , AnswerClients thisRoomChans ["CFG", "SEED", seed] + ] + processAction CheckRegistered = do (Just ci) <- gets clientIndex @@ -454,12 +489,18 @@ checkerLogin _ False _ = processAction $ ByeClient $ loc "No checker rights" checkerLogin p True _ = do wp <- client's webPassword - processAction $ - if wp == p then ModifyClient $ \c -> c{logonPassed = True} else ByeClient $ loc "Authentication failed" + chan <- client's sendChan + mapM_ processAction $ + if wp == p then + [ModifyClient $ \c -> c{logonPassed = True} + , AnswerClients [chan] ["LOGONPASSED"] + ] + else + [ByeClient $ loc "Authentication failed"] playerLogin p a contr = do - chan <- client's sendChan + cl <- client's id mapM_ processAction [ - AnswerClients [chan] ["ASKPASSWORD"] + AnswerClients [sendChan cl] $ ("ASKPASSWORD") : if clientProto cl < 48 then [] else [serverSalt cl] , ModifyClient (\c -> c{webPassword = p, isAdministrator = a, isContributor = contr}) ] @@ -524,7 +565,7 @@ processAction (BanNick n seconds reason) = do currentTime <- io getCurrentTime - let msg = + let msg = if seconds > 60 * 60 * 24 * 365 then B.concat ["Permanent ban (", reason, ")"] else @@ -562,20 +603,25 @@ si <- gets serverInfo newClId <- io $ do ci <- addClient rnc cl - _ <- Exception.mask (forkIO . clientRecvLoop (clientSocket cl) (coreChan si) (sendChan cl) ci) + _ <- Exception.mask (\x -> forkIO $ clientRecvLoop (clientSocket cl) (coreChan si) (sendChan cl) ci x) infoM "Clients" (show ci ++ ": New client. Time: " ++ show (connectTime cl)) return ci modify (\s -> s{clientIndex = Just newClId}) - mapM_ processAction - [ - AnswerClients [sendChan cl] ["CONNECTED", "Hedgewars server http://www.hedgewars.org/", serverVersion] - , CheckBanned True - , AddIP2Bans (host cl) "Reconnected too fast" (addUTCTime 10 $ connectTime cl) - ] + + jm <- gets joinsMonitor + pass <- io $ joinsSentry jm (host cl) (connectTime cl) + if pass then + mapM_ processAction + [ + CheckBanned True + , AnswerClients [sendChan cl] ["CONNECTED", "Hedgewars server http://www.hedgewars.org/", serverVersion] + ] + else + processAction $ ByeClient $ loc "Reconnected too fast" processAction (AddNick2Bans n reason expiring) = do processAction $ ModifyServerInfo (\s -> s{bans = BanByNick n reason expiring : bans s}) @@ -592,11 +638,11 @@ clNick <- client's nick clHost <- client's host si <- gets serverInfo - let validBans = filter (checkNotExpired clTime) $ bans si + let (validBans, expiredBans) = L.partition (checkNotExpired clTime) $ bans si let ban = L.find (checkBan byIP clHost clNick) $ validBans mapM_ processAction $ - ModifyServerInfo (\s -> s{bans = validBans}) - : [ByeClient (getBanReason $ fromJust ban) | isJust ban] + [ModifyServerInfo (\s -> s{bans = validBans}) | not $ null expiredBans] + ++ [ByeClient (getBanReason $ fromJust ban) | isJust ban] where checkNotExpired testTime (BanByIP _ _ time) = testTime `diffUTCTime` time <= 0 checkNotExpired testTime (BanByNick _ _ time) = testTime `diffUTCTime` time <= 0 @@ -698,12 +744,8 @@ blackList <- liftM (map (recordFileName . fromJust . checkInfo) . filter (isJust . checkInfo)) allClientsS - readyCheckersIds <- io $ do - allci <- allClientsM rnc - filterM (client'sM rnc (isJust . checkInfo)) allci - (cinfo, l) <- io $ loadReplay (fromIntegral p) blackList - when (not . null $ l) $ + when (isJust cinfo) $ mapM_ processAction [ AnswerClients [c] ("REPLAY" : l) , ModifyClient $ \c -> c{checkInfo = cinfo, isReady = False} @@ -711,14 +753,16 @@ processAction (CheckFailed msg) = do - Just (CheckInfo fileName _) <- client's checkInfo + Just (CheckInfo fileName _ _) <- client's checkInfo io $ moveFailedRecord fileName processAction (CheckSuccess info) = do - Just (CheckInfo fileName teams) <- client's checkInfo + Just (CheckInfo fileName teams gameDetails) <- client's checkInfo + p <- client's clientProto si <- gets serverInfo - io $ writeChan (dbQueries si) $ StoreAchievements (B.pack fileName) (map toPair teams) info + when (isJust gameDetails) + $ io $ writeChan (dbQueries si) $ StoreAchievements p (B.pack fileName) (map toPair teams) (fromJust gameDetails) info io $ moveCheckedRecord fileName where toPair t = (teamname t, teamowner t) @@ -759,3 +803,35 @@ , [AnswerClients [c] $ "EM" : roundMsgs'] , [AnswerClients [c] ["KICKED"]] ] + +processAction (SaveRoom rname) = do + rnc <- gets roomsClients + ri <- clientRoomA + rm <- io $ room'sM rnc id ri + liftIO $ writeFile (B.unpack rname) $ show (greeting rm, roomSaves rm) + +processAction (LoadRoom rname) = do + (g, rs) <- liftIO $ liftM read $ readFile (B.unpack rname) + processAction $ ModifyRoom $ \r -> r{greeting = g, roomSaves = rs} + +processAction Cleanup = do + jm <- gets joinsMonitor + + io $ do + t <- getCurrentTime + cleanup jm t + + +processAction (RegisterEvent e) = do + actions <- registerEvent e + mapM_ processAction actions + + +processAction (ReactCmd cmd) = do + (Just ci) <- gets clientIndex + rnc <- gets roomsClients + actions <- liftIO $ withRoomsAndClients rnc (\irnc -> runReader (handleCmd cmd) (ci, irnc)) + forM_ (actions `deepseq` actions) processAction + +processAction CheckVotes = + checkVotes >>= mapM_ processAction \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 gameServer/CMakeLists.txt --- a/gameServer/CMakeLists.txt Tue Nov 10 18:16:35 2015 +0100 +++ b/gameServer/CMakeLists.txt Tue Nov 10 20:43:13 2015 +0100 @@ -3,6 +3,30 @@ find_package_or_disable(GHC NOSERVER) +include(${CMAKE_MODULE_PATH}/CheckHaskellModuleExists.cmake) + +check_haskell_module_exists("Control.Exception" mask 1 base) +check_haskell_module_exists("Data.Map" size 1 containers) +check_haskell_module_exists("Data.Vector" length 1 vector) +check_haskell_module_exists("Data.ByteString" pack 1 bytestring) +check_haskell_module_exists("Text.Show.ByteString" putDigit 1 bytestring-show) +check_haskell_module_exists("Network.BSD" getHostName 0 network) +check_haskell_module_exists("Data.Time" getCurrentTime 0 time) +check_haskell_module_exists("Control.Monad.State" fix 1 mtl) +check_haskell_module_exists("Codec.Binary.Base64" encode 1 dataenc) +check_haskell_module_exists("System.Log.Logger" warningM 1 hslogger) +check_haskell_module_exists("System.Process" createProcess 3 process) +check_haskell_module_exists("Data.ByteString.Lazy.UTF8" decode 1 utf8-string) +check_haskell_module_exists("Data.Digest.Pure.SHA" sha1 1 SHA) +check_haskell_module_exists("System.Entropy" openHandle 0 entropy) +check_haskell_module_exists("Codec.Compression.Zlib" decompress 1 zlib) +check_haskell_module_exists("System.Random" getStdGen 0 random) + +# this one needs type signatures to work +# check_haskell_module_exists("Control.DeepSeq" deepseq 2 deepseq) + + + set(hwserver_sources OfficialServer/DBInteraction.hs Actions.hs @@ -11,11 +35,13 @@ Consts.hs CoreTypes.hs EngineInteraction.hs + FloodDetection.hs HWProtoCore.hs HWProtoInRoomState.hs HWProtoLobbyState.hs HWProtoNEState.hs HandlerUtils.hs + JoinsMonitor.hs NetRoutines.hs Opts.hs RoomsAndClients.hs @@ -23,14 +49,15 @@ ServerState.hs Store.hs Utils.hs + Votes.hs hedgewars-server.hs ) -set(hwserv_main ${hedgewars_SOURCE_DIR}/gameServer/hedgewars-server.hs) +set(hwserv_main ${CMAKE_CURRENT_SOURCE_DIR}/hedgewars-server.hs) set(ghc_flags --make ${hwserv_main} - -i${hedgewars_SOURCE_DIR}/gameServer + -i${CMAKE_CURRENT_SOURCE_DIR} -o ${EXECUTABLE_OUTPUT_PATH}/hedgewars-server${CMAKE_EXECUTABLE_SUFFIX} -odir ${CMAKE_CURRENT_BINARY_DIR} -hidir ${CMAKE_CURRENT_BINARY_DIR} diff -r 31570b766315 -r ed5a6478e710 gameServer/ClientIO.hs --- a/gameServer/ClientIO.hs Tue Nov 10 18:16:35 2015 +0100 +++ b/gameServer/ClientIO.hs Tue Nov 10 20:43:13 2015 +0100 @@ -1,3 +1,21 @@ +{- + * Hedgewars, a free turn based strategy game + * Copyright (c) 2004-2015 Andrey Korotaev + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + \-} + {-# LANGUAGE ScopedTypeVariables, OverloadedStrings, Rank2Types #-} module ClientIO where @@ -37,6 +55,7 @@ unless (B.null recvBS) $ do let (packets, newrecvBuf) = bs2Packets $ B.append recvBuf recvBS forM_ packets sendPacket + when (B.length newrecvBuf > 128 * 1024) $ sendPacket ["QUIT", "Protocol violation"] receiveWithBufferLoop $ B.copy newrecvBuf sendPacket packet = writeChan chan $ ClientMessage (ci, packet) diff -r 31570b766315 -r ed5a6478e710 gameServer/ConfigFile.hs --- a/gameServer/ConfigFile.hs Tue Nov 10 18:16:35 2015 +0100 +++ b/gameServer/ConfigFile.hs Tue Nov 10 20:43:13 2015 +0100 @@ -1,3 +1,21 @@ +{- + * Hedgewars, a free turn based strategy game + * Copyright (c) 2004-2015 Andrey Korotaev + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + \-} + {-# LANGUAGE RankNTypes #-} module ConfigFile where diff -r 31570b766315 -r ed5a6478e710 gameServer/Consts.hs --- a/gameServer/Consts.hs Tue Nov 10 18:16:35 2015 +0100 +++ b/gameServer/Consts.hs Tue Nov 10 20:43:13 2015 +0100 @@ -1,7 +1,25 @@ +{- + * Hedgewars, a free turn based strategy game + * Copyright (c) 2004-2015 Andrey Korotaev + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + \-} + {-# LANGUAGE OverloadedStrings #-} module Consts where import qualified Data.ByteString.Char8 as B serverVersion :: B.ByteString -serverVersion = "2" +serverVersion = "3" diff -r 31570b766315 -r ed5a6478e710 gameServer/CoreTypes.hs --- a/gameServer/CoreTypes.hs Tue Nov 10 18:16:35 2015 +0100 +++ b/gameServer/CoreTypes.hs Tue Nov 10 20:43:13 2015 +0100 @@ -1,4 +1,22 @@ -{-# LANGUAGE CPP, OverloadedStrings, DeriveDataTypeable #-} +{- + * Hedgewars, a free turn based strategy game + * Copyright (c) 2004-2015 Andrey Korotaev + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + \-} + +{-# LANGUAGE CPP, OverloadedStrings, DeriveDataTypeable, GeneralizedNewtypeDeriving #-} module CoreTypes where import Control.Concurrent @@ -16,12 +34,11 @@ ----------------------- import RoomsAndClients - #if __GLASGOW_HASKELL__ < 706 instance NFData B.ByteString #endif -instance NFData (Chan a) +instance NFData (Chan a) where rnf a = a `seq` () instance NFData Action where rnf (AnswerClients chans msg) = chans `deepseq` msg `deepseq` () @@ -78,6 +95,23 @@ | Random [ClientChan] [B.ByteString] | QueryReplay B.ByteString | ShowReplay B.ByteString + | Cleanup + | RegisterEvent Event + | SaveRoom B.ByteString + | LoadRoom B.ByteString + | ReactCmd [B.ByteString] + | CheckVotes + | SetRandomSeed + + +data Event = LobbyChatMessage + | EngineMessage + | RoomJoin + +type EventsInfo = [(Int, UTCTime)] + +newEventsInfo :: EventsInfo +newEventsInfo = [] type ClientChan = Chan [B.ByteString] @@ -85,7 +119,8 @@ CheckInfo { recordFileName :: String, - recordTeams :: [TeamInfo] + recordTeams :: [TeamInfo], + details :: Maybe GameDetails } data ClientInfo = @@ -98,6 +133,7 @@ connectTime :: UTCTime, nick :: B.ByteString, webPassword :: B.ByteString, + serverSalt :: B.ByteString, logonPassed :: Bool, isVisible :: Bool, clientProto :: !Word16, @@ -112,6 +148,9 @@ isJoinedMidGame :: Bool, clientClan :: !(Maybe B.ByteString), checkInfo :: Maybe CheckInfo, + eiLobbyChat, + eiEM, + eiJoin :: EventsInfo, teamsInGame :: Word } @@ -125,7 +164,6 @@ data TeamInfo = TeamInfo { - teamownerId :: ClientIndex, teamowner :: B.ByteString, teamname :: B.ByteString, teamcolor :: B.ByteString, @@ -133,6 +171,7 @@ teamfort :: B.ByteString, teamvoicepack :: B.ByteString, teamflag :: B.ByteString, + isOwnerRegistered :: Bool, difficulty :: Int, hhnum :: Int, hedgehogs :: [HedgehogInfo] @@ -148,11 +187,13 @@ roundMsgs :: [B.ByteString], lastFilteredTimedMsg :: Maybe B.ByteString, leftTeams :: [B.ByteString], + rejoinedTeams :: [B.ByteString], -- for 0.9.21 frontend workaround teamsAtStart :: [TeamInfo], teamsInGameNumber :: Int, allPlayersHaveRegisteredAccounts :: !Bool, giMapParams :: Map.Map B.ByteString B.ByteString, - giParams :: Map.Map B.ByteString [B.ByteString] + giParams :: Map.Map B.ByteString [B.ByteString], + isPaused :: Bool } deriving (Show, Read) newGameInfo :: [TeamInfo] @@ -160,12 +201,15 @@ -> Bool -> Map.Map ByteString ByteString -> Map.Map ByteString [ByteString] + -> Bool -> GameInfo newGameInfo = GameInfo [] Nothing [] + [] + data RoomInfo = RoomInfo @@ -182,10 +226,14 @@ isRestrictedTeams :: Bool, isRegisteredOnly :: Bool, isSpecial :: Bool, + defaultHedgehogsNumber :: Int, + teamsNumberLimit :: Int, greeting :: B.ByteString, + voting :: Maybe Voting, roomBansList :: ![B.ByteString], mapParams :: Map.Map B.ByteString B.ByteString, - params :: Map.Map B.ByteString [B.ByteString] + params :: Map.Map B.ByteString [B.ByteString], + roomSaves :: Map.Map B.ByteString (Map.Map B.ByteString B.ByteString, Map.Map B.ByteString [B.ByteString]) } newRoom :: RoomInfo @@ -203,18 +251,22 @@ False False False + 4 + 8 "" + Nothing [] ( Map.fromList $ Prelude.zip - ["MAP", "MAPGEN", "MAZE_SIZE", "SEED", "TEMPLATE"] - ["+rnd+", "0", "0", "seed", "0"] + ["FEATURE_SIZE", "MAP", "MAPGEN", "MAZE_SIZE", "SEED", "TEMPLATE"] + ["12", "+rnd+", "0", "0", "seed", "0"] ) ( Map.fromList $ Prelude.zip - ["SCHEME", "SCRIPT"] - [["Default"], ["Normal"]] + ["AMMO", "SCHEME", "SCRIPT", "THEME"] + [["Default"], ["Default"], ["Normal"], ["avematan"]] ) + Map.empty data StatisticsInfo = @@ -252,8 +304,8 @@ ServerInfo True "

http://www.hedgewars.org/

" - "

Hedgewars 0.9.19 is out! Please update.

Download page here" - 45 -- latestReleaseVersion + "

Hedgewars 0.9.22 is out! Please update.

Download page here" + 51 -- latestReleaseVersion 41 -- earliestCompatibleVersion 46631 "" @@ -264,6 +316,25 @@ False [] +data Voting = Voting { + voteTTL :: Int, + entitledToVote :: [Unique], + votes :: [(Unique, Bool)], + voteType :: VoteType + } + + +data VoteType = VoteKick B.ByteString + | VoteMap B.ByteString + | VotePause + | VoteNewSeed + | VoteHedgehogsPerTeam Int + + +newVoting :: VoteType -> Voting +newVoting = Voting 2 [] [] + + data AccountInfo = HasAccount B.ByteString Bool Bool | Guest @@ -275,10 +346,21 @@ CheckAccount ClientIndex Int B.ByteString B.ByteString | ClearCache | SendStats Int Int - | StoreAchievements B.ByteString [(B.ByteString, B.ByteString)] [B.ByteString] + | StoreAchievements Word16 B.ByteString [(B.ByteString, B.ByteString)] GameDetails [B.ByteString] | GetReplayName ClientIndex Int B.ByteString deriving (Show, Read) +data GameDetails = + GameDetails { + gameScript :: B.ByteString + , infRope + , isVamp + , infAttacks :: Bool + } deriving (Show, Read) + +instance NFData GameDetails where + rnf (GameDetails a b c d) = a `deepseq` b `deepseq` c `deepseq` d `deepseq` () + data CoreMessage = Accept ClientInfo | ClientMessage (ClientIndex, [B.ByteString]) diff -r 31570b766315 -r ed5a6478e710 gameServer/EngineInteraction.hs --- a/gameServer/EngineInteraction.hs Tue Nov 10 18:16:35 2015 +0100 +++ b/gameServer/EngineInteraction.hs Tue Nov 10 20:43:13 2015 +0100 @@ -1,12 +1,35 @@ -{-# LANGUAGE OverloadedStrings #-} +{- + * Hedgewars, a free turn based strategy game + * Copyright (c) 2004-2015 Andrey Korotaev + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + \-} -module EngineInteraction where +{-# LANGUAGE CPP, OverloadedStrings #-} + +#if defined(OFFICIAL_SERVER) +module EngineInteraction(replayToDemo, checkNetCmd, toEngineMsg, drawnMapData) where +#else +module EngineInteraction(checkNetCmd, toEngineMsg) where +#endif import qualified Data.Set as Set import Control.Monad import qualified Codec.Binary.Base64 as Base64 import qualified Data.ByteString.Char8 as B import qualified Data.ByteString as BW +import qualified Data.ByteString.Lazy as BL import qualified Data.Map as Map import qualified Data.List as L import Data.Word @@ -17,17 +40,39 @@ import CoreTypes import Utils +#if defined(OFFICIAL_SERVER) +{- + this is snippet from http://stackoverflow.com/questions/10043102/how-to-catch-the-decompress-ioerror + because standard 'catch' doesn't seem to catch decompression errors for some reason +-} +import qualified Codec.Compression.Zlib.Internal as Z + +decompressWithoutExceptions :: BL.ByteString -> Either String BL.ByteString +decompressWithoutExceptions = finalise + . Z.foldDecompressStream cons nil err + . Z.decompressWithErrors Z.zlibFormat Z.defaultDecompressParams + where err _ msg = Left msg + nil = Right [] + cons chunk = right (chunk :) + finalise = right BL.fromChunks +{- end snippet -} +#endif toEngineMsg :: B.ByteString -> B.ByteString toEngineMsg msg = B.pack $ Base64.encode (fromIntegral (BW.length msg) : BW.unpack msg) -fromEngineMsg :: B.ByteString -> Maybe B.ByteString +{-fromEngineMsg :: B.ByteString -> Maybe B.ByteString fromEngineMsg msg = liftM BW.pack (Base64.decode (B.unpack msg) >>= removeLength) where removeLength (x:xs) = if length xs == fromIntegral x then Just xs else Nothing - removeLength _ = Nothing + removeLength _ = Nothing-} +em :: B.ByteString -> B.ByteString +em = toEngineMsg + +eml :: [B.ByteString] -> B.ByteString +eml = em . B.concat splitMessages :: B.ByteString -> [B.ByteString] splitMessages = L.unfoldr (\b -> if B.null b then Nothing else Just $ B.splitAt (1 + fromIntegral (BW.head b)) b) @@ -42,21 +87,21 @@ encode = B.pack . Base64.encode . BW.unpack . B.concat isLegal m = (B.length m > 1) && (flip Set.member legalMessages . B.head . B.tail $ m) lft = foldr l Nothing - l m n = let m' = B.head $ B.tail m; tst = flip Set.member in + l m n = let m' = B.head $ B.tail m; tst = flip Set.member in if not $ tst timedMessages m' then n else if '+' /= m' then Just Nothing else Just . Just . B.pack . Base64.encode . BW.unpack $ m isNonEmpty = (/=) '+' . B.head . B.tail - legalMessages = Set.fromList $ "M#+LlRrUuDdZzAaSjJ,sNpPwtghbc12345" ++ slotMessages + legalMessages = Set.fromList $ "M#+LlRrUuDdZzAaSjJ,sNpPwtgfhbc12345" ++ slotMessages slotMessages = "\128\129\130\131\132\133\134\135\136\137\138" - timedMessages = Set.fromList $ "+LlRrUuDdZzAaSjJ,NpPwtgc12345" ++ slotMessages + timedMessages = Set.fromList $ "+LlRrUuDdZzAaSjJ,NpPwtgfc12345" ++ slotMessages - +#if defined(OFFICIAL_SERVER) replayToDemo :: [TeamInfo] -> Map.Map B.ByteString B.ByteString -> Map.Map B.ByteString [B.ByteString] -> [B.ByteString] - -> [B.ByteString] -replayToDemo ti mParams prms msgs = concat [ + -> (Maybe GameDetails, [B.ByteString]) +replayToDemo ti mParams prms msgs = if not sane then (Nothing, []) else (Just $ GameDetails scriptName infRopes vamp infattacks, concat [ [em "TD"] , maybeScript , maybeMap @@ -64,30 +109,42 @@ , [eml ["eseed ", mParams Map.! "SEED"]] , [eml ["e$gmflags ", showB gameFlags]] , schemeFlags + , schemeAdditional , [eml ["e$template_filter ", mParams Map.! "TEMPLATE"]] + , [eml ["e$feature_size ", mParams Map.! "FEATURE_SIZE"]] , [eml ["e$mapgen ", mapgen]] , mapgenSpecific , concatMap teamSetup ti , msgs , [em "!"] - ] + ]) where - em = toEngineMsg - eml = em . B.concat - mapGenTypes = ["+rnd+", "+maze+", "+drawn+"] - maybeScript = let s = head . fromMaybe ["Normal"] $ Map.lookup "SCRIPT" prms in if s == "Normal" then [] else [eml ["escript Scripts/Multiplayer/", s, ".lua"]] + keys1, keys2 :: Set.Set B.ByteString + keys1 = Set.fromList ["FEATURE_SIZE", "MAP", "MAPGEN", "MAZE_SIZE", "SEED", "TEMPLATE"] + keys2 = Set.fromList ["AMMO", "SCHEME", "SCRIPT", "THEME"] + sane = Set.null (keys1 Set.\\ Map.keysSet mParams) + && Set.null (keys2 Set.\\ Map.keysSet prms) + && (not . null . drop 41 $ scheme) + && (not . null . tail $ prms Map.! "AMMO") + && ((B.length . head . tail $ prms Map.! "AMMO") > 200) + mapGenTypes = ["+rnd+", "+maze+", "+drawn+", "+perlin+"] + scriptName = head . fromMaybe ["Normal"] $ Map.lookup "SCRIPT" prms + maybeScript = let s = scriptName in if s == "Normal" then [] else [eml ["escript Scripts/Multiplayer/", spaces2Underlining s, ".lua"]] maybeMap = let m = mParams Map.! "MAP" in if m `elem` mapGenTypes then [] else [eml ["emap ", m]] scheme = tail $ prms Map.! "SCHEME" mapgen = mParams Map.! "MAPGEN" + mazeSizeMsg = eml ["e$maze_size ", mParams Map.! "MAZE_SIZE"] mapgenSpecific = case mapgen of - "+maze+" -> [eml ["e$maze_size ", head $ prms Map.! "MAZE_SIZE"]] - "+drawn" -> drawnMapData . head $ prms Map.! "DRAWNMAP" + "1" -> [mazeSizeMsg] + "2" -> [mazeSizeMsg] + "3" -> let d = head . fromMaybe [""] $ Map.lookup "DRAWNMAP" prms in if BW.length d <= 4 then [] else drawnMapData d _ -> [] gameFlags :: Word32 gameFlags = foldl (\r (b, f) -> if b == "false" then r else r .|. f) 0 $ zip scheme gameFlagConsts schemeFlags = map (\(v, (n, m)) -> eml [n, " ", showB $ (readInt_ v) * m]) $ filter (\(_, (n, _)) -> not $ B.null n) $ zip (drop (length gameFlagConsts) scheme) schemeParams + schemeAdditional = let scriptParam = B.tail $ scheme !! 41 in [eml ["e$scriptparam ", scriptParam] | not $ B.null scriptParam] ammoStr :: B.ByteString ammoStr = head . tail $ prms Map.! "AMMO" ammo = let l = B.length ammoStr `div` 4; ((a, b), (c, d)) = (B.splitAt l . fst &&& B.splitAt l . snd) . B.splitAt (l * 2) $ ammoStr in @@ -106,9 +163,27 @@ ]) $ hedgehogs t ) + infRopes = ammoStr `B.index` 7 == '9' + vamp = gameFlags .&. 0x00000200 /= 0 + infattacks = gameFlags .&. 0x00100000 /= 0 + spaces2Underlining = B.map (\c -> if c == ' ' then '_' else c) drawnMapData :: B.ByteString -> [B.ByteString] -drawnMapData = error "drawnMapData" +drawnMapData = + L.map (\m -> eml ["edraw ", BW.pack m]) + . L.unfoldr by200 + . BL.unpack + . either (const BL.empty) id + . decompressWithoutExceptions + . BL.pack + . L.drop 4 + . fromMaybe [] + . Base64.decode + . B.unpack + where + by200 :: [a] -> Maybe ([a], [a]) + by200 [] = Nothing + by200 m = Just $ L.splitAt 200 m schemeParams :: [(B.ByteString, Int)] schemeParams = [ @@ -127,6 +202,7 @@ , ("e$healthdec", 1) , ("e$ropepct", 1) , ("e$getawaytime", 1) + , ("e$worldedge", 1) ] @@ -158,6 +234,4 @@ , 0x02000000 , 0x04000000 ] - - - +#endif diff -r 31570b766315 -r ed5a6478e710 gameServer/FloodDetection.hs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gameServer/FloodDetection.hs Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,77 @@ +{- + * Hedgewars, a free turn based strategy game + * Copyright (c) 2004-2015 Andrey Korotaev + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + \-} + +{-# LANGUAGE OverloadedStrings, BangPatterns #-} +module FloodDetection where + +import Control.Monad.State.Strict +import Data.Time +import Control.Arrow +---------------- +import ServerState +import CoreTypes +import Utils + +registerEvent :: Event -> StateT ServerState IO [Action] +registerEvent e = do + eventInfo <- client's $ einfo e + if (null eventInfo) || 0 == (fst $ head eventInfo) then doCheck eventInfo else updateInfo + + where + einfo LobbyChatMessage = eiLobbyChat + einfo EngineMessage = eiEM + einfo RoomJoin = eiJoin + + transformField LobbyChatMessage f = \c -> c{eiLobbyChat = f $ eiLobbyChat c} + transformField EngineMessage f = \c -> c{eiEM = f $ eiEM c} + transformField RoomJoin f = \c -> c{eiJoin = f $ eiJoin c} + + boundaries :: Event -> (Int, (NominalDiffTime, Int), (NominalDiffTime, Int), ([Action], [Action])) + boundaries LobbyChatMessage = (3, (10, 2), (30, 3), (chat1, chat2)) + boundaries EngineMessage = (8, (10, 4), (25, 5), (em1, em2)) + boundaries RoomJoin = (2, (10, 2), (35, 3), (join1, join2)) + + chat1 = [Warning $ loc "Warning! Chat flood protection activated"] + chat2 = [ByeClient $ loc "Excess flood"] + em1 = [Warning $ loc "Game messages flood detected - 1"] + em2 = [Warning $ loc "Game messages flood detected - 2"] + join1 = [Warning $ loc "Warning! Joins flood protection activated"] + join2 = [ByeClient $ loc "Excess flood"] + + doCheck ei = do + curTime <- io getCurrentTime + let (numPerEntry, (sec1, num1), (sec2, num2), (ac1, ac2)) = boundaries e + + let nei = takeWhile ((>=) sec2 . diffUTCTime curTime . snd) ei + let l2 = length nei + let l1 = length $ takeWhile ((>=) sec1 . diffUTCTime curTime . snd) nei + + let actions = if l2 >= num2 + 1 || l1 >= num1 + 1 then + ac2 + else + if l1 >= num1 || l2 >= num2 then + ac1 + else + [] + + return $ (ModifyClient . transformField e . const $ (numPerEntry, curTime) : nei) : actions + + updateInfo = return [ + ModifyClient $ transformField e + $ \(h:hs) -> first (flip (-) 1) h : hs + ] diff -r 31570b766315 -r ed5a6478e710 gameServer/HWProtoChecker.hs --- a/gameServer/HWProtoChecker.hs Tue Nov 10 18:16:35 2015 +0100 +++ b/gameServer/HWProtoChecker.hs Tue Nov 10 20:43:13 2015 +0100 @@ -1,3 +1,21 @@ +{- + * Hedgewars, a free turn based strategy game + * Copyright (c) 2004-2015 Andrey Korotaev + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + \-} + {-# LANGUAGE OverloadedStrings #-} module HWProtoChecker where @@ -5,7 +23,6 @@ import Control.Monad.Reader -------------------------------------- import CoreTypes -import Actions import HandlerUtils diff -r 31570b766315 -r ed5a6478e710 gameServer/HWProtoCore.hs --- a/gameServer/HWProtoCore.hs Tue Nov 10 18:16:35 2015 +0100 +++ b/gameServer/HWProtoCore.hs Tue Nov 10 20:43:13 2015 +0100 @@ -1,3 +1,21 @@ +{- + * Hedgewars, a free turn based strategy game + * Copyright (c) 2004-2015 Andrey Korotaev + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + \-} + {-# LANGUAGE OverloadedStrings #-} module HWProtoCore where @@ -6,7 +24,6 @@ import qualified Data.ByteString.Char8 as B -------------------------------------- import CoreTypes -import Actions import HWProtoNEState import HWProtoLobbyState import HWProtoInRoomState @@ -33,12 +50,25 @@ else return [ModifyClient (\c -> c{pingsQueue = pingsQueue c - 1})] -handleCmd ["CMD", parameters] = do - let (cmd, plist) = B.break (== ' ') parameters - let param = B.dropWhile (== ' ') plist - h (upperCase cmd) param +handleCmd cmd = do + (ci, irnc) <- ask + let cl = irnc `client` ci + if logonPassed cl then + if isChecker cl then + handleCmd_checker cmd + else + handleCmd_loggedin cmd + else + handleCmd_NotEntered cmd + + +handleCmd_loggedin ["CMD", parameters] = uncurry h $ extractParameters parameters where h "DELEGATE" n | not $ B.null n = handleCmd ["DELEGATE", n] + h "SAVEROOM" n | not $ B.null n = handleCmd ["SAVEROOM", n] + h "LOADROOM" n | not $ B.null n = handleCmd ["LOADROOM", n] + h "SAVE" n | not $ B.null n = handleCmd ["SAVE", n] + h "DELETE" n | not $ B.null n = handleCmd ["DELETE", n] h "STATS" _ = handleCmd ["STATS"] h "PART" m | not $ B.null m = handleCmd ["PART", m] | otherwise = handleCmd ["PART"] @@ -53,20 +83,18 @@ h "WATCH" f = return [QueryReplay f] h "FIX" _ = handleCmd ["FIX"] h "UNFIX" _ = handleCmd ["UNFIX"] - h "GREETING" msg = handleCmd ["GREETING", msg] - h c p = return [Warning $ B.concat ["Unknown cmd: /", c, p]] + h "GREETING" msg | not $ B.null msg = handleCmd ["GREETING", msg] + h "CALLVOTE" msg | B.null msg = handleCmd ["CALLVOTE"] + | otherwise = let (c, p) = extractParameters msg in + if B.null p then handleCmd ["CALLVOTE", c] else handleCmd ["CALLVOTE", c, p] + h "VOTE" msg | not $ B.null msg = handleCmd ["VOTE", upperCase msg] + h "FORCE" msg | not $ B.null msg = handleCmd ["VOTE", upperCase msg, "FORCE"] + h "MAXTEAMS" n | not $ B.null n = handleCmd ["MAXTEAMS", n] + h "INFO" n | not $ B.null n = handleCmd ["INFO", n] + h "RESTART_SERVER" "YES" = handleCmd ["RESTART_SERVER"] + h c p = return [Warning $ B.concat ["Unknown cmd: /", c, " ", p]] -handleCmd cmd = do - (ci, irnc) <- ask - let cl = irnc `client` ci - if logonPassed cl then - if isChecker cl then - handleCmd_checker cmd - else - handleCmd_loggedin cmd - else - handleCmd_NotEntered cmd - + extractParameters p = let (a, b) = B.break (== ' ') p in (upperCase a, B.dropWhile (== ' ') b) handleCmd_loggedin ["INFO", asknick] = do (_, rnc) <- ask @@ -84,7 +112,7 @@ if teamsInGame cl > 0 then "(playing)" else "(spectating)" else "" - let hostStr = if isAdminAsking then host cl else cutHost $ host cl + let hostStr = if isAdminAsking then host cl else B.empty if noSuchClient then return [] else diff -r 31570b766315 -r ed5a6478e710 gameServer/HWProtoInRoomState.hs --- a/gameServer/HWProtoInRoomState.hs Tue Nov 10 18:16:35 2015 +0100 +++ b/gameServer/HWProtoInRoomState.hs Tue Nov 10 20:43:13 2015 +0100 @@ -1,3 +1,21 @@ +{- + * Hedgewars, a free turn based strategy game + * Copyright (c) 2004-2015 Andrey Korotaev + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + \-} + {-# LANGUAGE OverloadedStrings #-} module HWProtoInRoomState where @@ -9,11 +27,43 @@ import Control.Monad.Reader -------------------------------------- import CoreTypes -import Actions import Utils import HandlerUtils import RoomsAndClients import EngineInteraction +import Votes + +startGame :: Reader (ClientIndex, IRnC) [Action] +startGame = do + (ci, rnc) <- ask + cl <- thisClient + rm <- thisRoom + chans <- roomClientsChans + + let nicks = map (nick . client rnc) . roomClients rnc $ clientRoom rnc ci + let allPlayersRegistered = all isOwnerRegistered $ teams rm + + if (playersIn rm == readyPlayers rm || clientProto cl > 43) && not (isJust $ gameInfo rm) then + if enoughClans rm then + return [ + ModifyRoom + (\r -> r{ + gameInfo = Just $ newGameInfo (teams rm) (length $ teams rm) allPlayersRegistered (mapParams rm) (params rm) False + } + ) + , AnswerClients chans ["RUN_GAME"] + , SendUpdateOnThisRoom + , AnswerClients chans $ "CLIENT_FLAGS" : "+g" : nicks + , ModifyRoomClients (\c -> c{isInGame = True}) + ] + else + return [Warning $ loc "Less than two clans!"] + else + return [] + where + enoughClans = not . null . drop 1 . group . map teamcolor . teams + + handleCmd_inRoom :: CmdHandler @@ -37,37 +87,45 @@ return [Warning $ loc "Restricted"] else if isMaster cl then return [ - ModifyRoom f, + ModifyRoom $ f (clientProto cl), AnswerClients chans ("CFG" : paramName : paramStrs)] else return [ProtocolError $ loc "Not room master"] where - f r = if paramName `Map.member` (mapParams r) then + f clproto r = if paramName `Map.member` (mapParams r) then r{mapParams = Map.insert paramName (head paramStrs) (mapParams r)} else - r{params = Map.insert paramName paramStrs (params r)} + r{params = Map.insert paramName (fixedParamStr clproto) (params r)} + fixedParamStr clproto + | clproto /= 49 = paramStrs + | paramName /= "SCHEME" = paramStrs + | otherwise = L.init paramStrs ++ [B.replicate 50 'X' `B.append` L.last paramStrs] handleCmd_inRoom ("ADD_TEAM" : tName : color : grave : fort : voicepack : flag : difStr : hhsInfo) | length hhsInfo /= 16 = return [ProtocolError $ loc "Corrupted hedgehogs info"] | otherwise = do - (ci, _) <- ask rm <- thisRoom + cl <- thisClient clNick <- clientNick clChan <- thisClientChans othChans <- roomOthersChans roomChans <- roomClientsChans - cl <- thisClient + let isRegistered = (<) 0 . B.length . webPassword $ cl teamColor <- if clientProto cl < 42 then return color else liftM (head . (L.\\) (map B.singleton ['0'..]) . map teamcolor . teams) thisRoom let roomTeams = teams rm - let hhNum = let p = if not $ null roomTeams then minimum [hhnum $ head roomTeams, canAddNumber roomTeams] else 4 in newTeamHHNum roomTeams p - let newTeam = clNick `seq` TeamInfo ci clNick tName teamColor grave fort voicepack flag dif hhNum (hhsList hhsInfo) + let hhNum = newTeamHHNum roomTeams $ + if not $ null roomTeams then + minimum [hhnum $ head roomTeams, canAddNumber roomTeams] + else + defaultHedgehogsNumber rm + let newTeam = clNick `seq` TeamInfo clNick tName teamColor grave fort voicepack flag isRegistered dif hhNum (hhsList hhsInfo) return $ - if not . null . drop (maxTeams rm - 1) $ roomTeams then + if not . null . drop (teamsNumberLimit rm - 1) $ roomTeams then [Warning $ loc "too many teams"] else if canAddNumber roomTeams <= 0 then [Warning $ loc "too many hedgehogs"] @@ -102,6 +160,7 @@ handleCmd_inRoom ["REMOVE_TEAM", tName] = do (ci, _) <- ask r <- thisRoom + clNick <- clientNick let maybeTeam = findTeam r let team = fromJust maybeTeam @@ -109,18 +168,18 @@ return $ if isNothing $ maybeTeam then [Warning $ loc "REMOVE_TEAM: no such team"] - else if ci /= teamownerId team then + else if clNick /= teamowner team then [ProtocolError $ loc "Not team owner!"] else [RemoveTeam tName, ModifyClient (\c -> c{ teamsInGame = teamsInGame c - 1, - clientClan = if teamsInGame c == 1 then Nothing else Just $ anotherTeamClan ci team r + clientClan = if teamsInGame c == 1 then Nothing else Just $ anotherTeamClan clNick team r }) ] where - anotherTeamClan ci team = teamcolor . fromMaybe (error "CHECKPOINT 011") . find (\t -> (teamownerId t == ci) && (t /= team)) . teams + anotherTeamClan clNick team = teamcolor . fromMaybe (error "CHECKPOINT 011") . find (\t -> (teamowner t == clNick) && (t /= team)) . teams findTeam = find (\t -> tName == teamname t) . teams @@ -157,64 +216,45 @@ let maybeTeam = findTeam r let team = fromJust maybeTeam + maybeClientId <- clientByNick $ teamowner team + let teamOwnerId = fromJust maybeClientId return $ if not $ isMaster cl then [ProtocolError $ loc "Not room master"] - else if isNothing maybeTeam then + else if isNothing maybeTeam || isNothing maybeClientId then [] else [ModifyRoom $ modifyTeam team{teamcolor = newColor}, AnswerClients others ["TEAM_COLOR", teamName, newColor], - ModifyClient2 (teamownerId team) (\c -> c{clientClan = Just newColor})] + ModifyClient2 teamOwnerId (\c -> c{clientClan = Just newColor})] where findTeam = find (\t -> teamName == teamname t) . teams handleCmd_inRoom ["TOGGLE_READY"] = do 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}), - AnswerClients chans $ if clientProto cl < 38 then - [if isReady cl then "NOT_READY" else "READY", nick cl] - else - ["CLIENT_FLAGS", if isReady cl then "-r" else "+r", nick cl] - ] - - -handleCmd_inRoom ["START_GAME"] = do - (ci, rnc) <- ask - cl <- thisClient rm <- thisRoom chans <- roomClientsChans - let nicks = map (nick . client rnc) . roomClients rnc $ clientRoom rnc ci - let allPlayersRegistered = all ((<) 0 . B.length . webPassword . client rnc . teamownerId) $ teams rm + (ci, rnc) <- ask + let ri = clientRoom rnc ci + let unreadyClients = filter (not . isReady) . map (client rnc) $ roomClients rnc ri + + gs <- if (not $ isReady cl) && (isSpecial rm) && (unreadyClients == [cl]) then startGame else return [] - if isMaster cl && (playersIn rm == readyPlayers rm || clientProto cl > 43) && not (isJust $ gameInfo rm) then - if enoughClans rm then - return [ - ModifyRoom - (\r -> r{ - gameInfo = Just $ newGameInfo (teams rm) (length $ teams rm) allPlayersRegistered (mapParams rm) (params rm) - } - ) - , AnswerClients chans ["RUN_GAME"] - , SendUpdateOnThisRoom - , AnswerClients chans $ "CLIENT_FLAGS" : "+g" : nicks - , ModifyRoomClients (\c -> c{isInGame = True}) - ] - else - return [Warning $ loc "Less than two clans!"] - else - return [] - where - enoughClans = not . null . drop 1 . group . map teamcolor . teams + return $ + ModifyRoom (\r -> r{readyPlayers = readyPlayers r + (if isReady cl then -1 else 1)}) + : ModifyClient (\c -> c{isReady = not $ isReady cl}) + : (AnswerClients chans $ if clientProto cl < 38 then + [if isReady cl then "NOT_READY" else "READY", nick cl] + else + ["CLIENT_FLAGS", if isReady cl then "-r" else "+r", nick cl]) + : gs +handleCmd_inRoom ["START_GAME"] = roomAdminOnly startGame + handleCmd_inRoom ["EM", msg] = do cl <- thisClient rm <- thisRoom @@ -222,11 +262,11 @@ if teamsInGame cl > 0 && (isJust $ gameInfo rm) && (not $ B.null legalMsgs) then return $ AnswerClients chans ["EM", legalMsgs] - : [ModifyRoom (\r -> r{gameInfo = liftM + : [ModifyRoom (\r -> r{gameInfo = liftM (\g -> g{ roundMsgs = if B.null nonEmptyMsgs then roundMsgs g else nonEmptyMsgs : roundMsgs g , lastFilteredTimedMsg = fromMaybe (lastFilteredTimedMsg g) lastFTMsg}) - $ gameInfo r})] + $ gameInfo r}), RegisterEvent EngineMessage] else return [] where @@ -255,44 +295,26 @@ handleCmd_inRoom ["ROUNDFINISHED"] = handleCmd_inRoom ["ROUNDFINISHED", "1"] -handleCmd_inRoom ["TOGGLE_RESTRICT_JOINS"] = do - cl <- thisClient - return $ - if not $ isMaster cl then - [ProtocolError $ loc "Not room master"] - else - [ModifyRoom (\r -> r{isRestrictedJoins = not $ isRestrictedJoins r})] +handleCmd_inRoom ["TOGGLE_RESTRICT_JOINS"] = roomAdminOnly $ + return [ModifyRoom (\r -> r{isRestrictedJoins = not $ isRestrictedJoins r}), SendUpdateOnThisRoom] -handleCmd_inRoom ["TOGGLE_RESTRICT_TEAMS"] = do - cl <- thisClient - return $ - if not $ isMaster cl then - [ProtocolError $ loc "Not room master"] - else - [ModifyRoom (\r -> r{isRestrictedTeams = not $ isRestrictedTeams r})] +handleCmd_inRoom ["TOGGLE_RESTRICT_TEAMS"] = roomAdminOnly $ + return [ModifyRoom (\r -> r{isRestrictedTeams = not $ isRestrictedTeams r})] -handleCmd_inRoom ["TOGGLE_REGISTERED_ONLY"] = do - cl <- thisClient - return $ - if not $ isMaster cl then - [ProtocolError $ loc "Not room master"] - else - [ModifyRoom (\r -> r{isRegisteredOnly = not $ isRegisteredOnly r})] +handleCmd_inRoom ["TOGGLE_REGISTERED_ONLY"] = roomAdminOnly $ + return [ModifyRoom (\r -> r{isRegisteredOnly = not $ isRegisteredOnly r}), SendUpdateOnThisRoom] -handleCmd_inRoom ["ROOM_NAME", newName] = do +handleCmd_inRoom ["ROOM_NAME", newName] = roomAdminOnly $ do cl <- thisClient rs <- allRoomInfos rm <- thisRoom chans <- sameProtoChans return $ - if not $ isMaster cl then - [ProtocolError $ loc "Not room master"] - else - if illegalName newName then + if illegalName newName then [Warning $ loc "Illegal room name"] else if isSpecial rm then @@ -307,10 +329,9 @@ roomUpdate r = r{name = newName} -handleCmd_inRoom ["KICK", kickNick] = do +handleCmd_inRoom ["KICK", kickNick] = roomAdminOnly $ do (thisClientId, rnc) <- ask maybeClientId <- clientByNick kickNick - master <- liftM isMaster thisClient rm <- thisRoom let kickId = fromJust maybeClientId let kickCl = rnc `client` kickId @@ -318,8 +339,7 @@ let notOnly2Players = (length . group . sort . map teamowner . teams $ rm) > 2 return [KickRoomClient kickId | - master - && isJust maybeClientId + isJust maybeClientId && (kickId /= thisClientId) && sameRoom && ((isNothing $ gameInfo rm) || notOnly2Players || teamsInGame kickCl == 0) @@ -338,7 +358,6 @@ [ChangeMaster (Just newAdminId) | (master || serverAdmin) && isJust maybeClientId - && ((newAdminId /= thisClientId) || (serverAdmin && not master)) && (Just newAdminId /= thisRoomMasterId) && sameRoom] @@ -370,19 +389,120 @@ s <- roomClientsChans return [AnswerClients s ["CHAT", n, B.unwords $ "/rnd" : rs], Random s rs] -handleCmd_inRoom ["FIX"] = do - cl <- thisClient - return [ModifyRoom (\r -> r{isSpecial = True}) | isAdministrator cl] -handleCmd_inRoom ["UNFIX"] = do +handleCmd_inRoom ["MAXTEAMS", n] = roomAdminOnly $ do cl <- thisClient - return [ModifyRoom (\r -> r{isSpecial = False}) | isAdministrator cl] + let m = readInt_ n + if m < 2 || m > 8 then + return [AnswerClients [sendChan cl] ["CHAT", "[server]", loc "/maxteams: specify number from 2 to 8"]] + else + return [ModifyRoom (\r -> r{teamsNumberLimit = m})] + +handleCmd_inRoom ["FIX"] = serverAdminOnly $ + return [ModifyRoom (\r -> r{isSpecial = True})] + +handleCmd_inRoom ["UNFIX"] = serverAdminOnly $ + return [ModifyRoom (\r -> r{isSpecial = False})] handleCmd_inRoom ["GREETING", msg] = do cl <- thisClient rm <- thisRoom return [ModifyRoom (\r -> r{greeting = msg}) | isAdministrator cl || (isMaster cl && (not $ isSpecial rm))] + +handleCmd_inRoom ["CALLVOTE"] = do + cl <- thisClient + return [AnswerClients [sendChan cl] + ["CHAT", "[server]", loc "Available callvote commands: kick , map , pause, newseed, hedgehogs"] + ] + +handleCmd_inRoom ["CALLVOTE", "KICK"] = do + cl <- thisClient + return [AnswerClients [sendChan cl] ["CHAT", "[server]", loc "callvote kick: specify nickname"]] + +handleCmd_inRoom ["CALLVOTE", "KICK", nickname] = do + (thisClientId, rnc) <- ask + cl <- thisClient + rm <- thisRoom + maybeClientId <- clientByNick nickname + let kickId = fromJust maybeClientId + let sameRoom = clientRoom rnc thisClientId == clientRoom rnc kickId + + if isJust $ masterID rm then + return [] + else + if isJust maybeClientId && sameRoom then + startVote $ VoteKick nickname + else + return [AnswerClients [sendChan cl] ["CHAT", "[server]", loc "callvote kick: no such user"]] + + +handleCmd_inRoom ["CALLVOTE", "MAP"] = do + cl <- thisClient + s <- liftM (Map.keys . roomSaves) thisRoom + return [AnswerClients [sendChan cl] ["CHAT", "[server]", B.concat ["callvote map: ", B.intercalate ", " s]]] + + +handleCmd_inRoom ["CALLVOTE", "MAP", roomSave] = do + cl <- thisClient + rm <- thisRoom + + if Map.member roomSave $ roomSaves rm then + startVote $ VoteMap roomSave + else + return [AnswerClients [sendChan cl] ["CHAT", "[server]", loc "callvote map: no such map"]] + + +handleCmd_inRoom ["CALLVOTE", "PAUSE"] = do + cl <- thisClient + rm <- thisRoom + + if isJust $ gameInfo rm then + startVote VotePause + else + return [AnswerClients [sendChan cl] ["CHAT", "[server]", loc "callvote pause: no game in progress"]] + + +handleCmd_inRoom ["CALLVOTE", "NEWSEED"] = do + startVote VoteNewSeed + + +handleCmd_inRoom ["CALLVOTE", "HEDGEHOGS"] = do + cl <- thisClient + return [AnswerClients [sendChan cl] ["CHAT", "[server]", loc "callvote hedgehogs: specify number from 1 to 8"]] + + +handleCmd_inRoom ["CALLVOTE", "HEDGEHOGS", hhs] = do + cl <- thisClient + let h = readInt_ hhs + + if h > 0 && h <= 8 then + startVote $ VoteHedgehogsPerTeam h + else + return [AnswerClients [sendChan cl] ["CHAT", "[server]", loc "callvote hedgehogs: specify number from 1 to 8"]] + + +handleCmd_inRoom ("VOTE" : m : p) = do + cl <- thisClient + let b = if m == "YES" then Just True else if m == "NO" then Just False else Nothing + if isJust b then + voted (p == ["FORCE"]) (fromJust b) + else + return [AnswerClients [sendChan cl] ["CHAT", "[server]", "vote: 'yes' or 'no'"]] + + +handleCmd_inRoom ["SAVE", stateName] = serverAdminOnly $ do + return [ModifyRoom $ \r -> r{roomSaves = Map.insert stateName (mapParams r, params r) (roomSaves r)}] + +handleCmd_inRoom ["DELETE", stateName] = serverAdminOnly $ do + return [ModifyRoom $ \r -> r{roomSaves = Map.delete stateName (roomSaves r)}] + +handleCmd_inRoom ["SAVEROOM", fileName] = serverAdminOnly $ do + return [SaveRoom fileName] + +handleCmd_inRoom ["LOADROOM", fileName] = serverAdminOnly $ do + return [LoadRoom fileName] + handleCmd_inRoom ["LIST"] = return [] -- for old clients (<= 0.9.17) handleCmd_inRoom (s:_) = return [ProtocolError $ "Incorrect command '" `B.append` s `B.append` "' (state: in room)"] diff -r 31570b766315 -r ed5a6478e710 gameServer/HWProtoLobbyState.hs --- a/gameServer/HWProtoLobbyState.hs Tue Nov 10 18:16:35 2015 +0100 +++ b/gameServer/HWProtoLobbyState.hs Tue Nov 10 20:43:13 2015 +0100 @@ -1,3 +1,21 @@ +{- + * Hedgewars, a free turn based strategy game + * Copyright (c) 2004-2015 Andrey Korotaev + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + \-} + {-# LANGUAGE OverloadedStrings #-} module HWProtoLobbyState where @@ -7,7 +25,6 @@ import qualified Data.ByteString.Char8 as B -------------------------------------- import CoreTypes -import Actions import Utils import HandlerUtils import RoomsAndClients @@ -27,7 +44,7 @@ handleCmd_lobby ["CHAT", msg] = do n <- clientNick s <- roomOthersChans - return [AnswerClients s ["CHAT", n, msg]] + return [AnswerClients s ["CHAT", n, msg], RegisterEvent LobbyChatMessage] handleCmd_lobby ["CREATE_ROOM", rName, roomPassword] | illegalName rName = return [Warning $ loc "Illegal room name"] @@ -51,6 +68,7 @@ handleCmd_lobby ["JOIN_ROOM", roomName, roomPassword] = do (_, irnc) <- ask + let ris = allRooms irnc cl <- thisClient let maybeRI = find (\ri -> roomName == name (irnc `room` ri)) ris @@ -62,10 +80,16 @@ let owner = find isMaster jRoomClients let chans = map sendChan (cl : jRoomClients) let isBanned = host cl `elem` roomBansList jRoom + let clTeams = + if (clientProto cl >= 48) && (isJust $ gameInfo jRoom) then + filter (\t -> teamowner t == nick cl) . teamsAtStart . fromJust $ gameInfo jRoom + else + [] + let clTeamsNames = map teamname clTeams return $ if isNothing maybeRI then [Warning $ loc "No such room"] - else if not sameProto then + else if (not sameProto) && (not $ isAdministrator cl) then [Warning $ loc "Room version incompatible to your hedgewars version"] else if isRestrictedJoins jRoom then [Warning $ loc "Joining restricted"] @@ -78,18 +102,26 @@ else ( MoveToRoom jRI - : ModifyClient (\c -> c{isJoinedMidGame = isJust $ gameInfo jRoom}) + : ModifyClient (\c -> c{isJoinedMidGame = isJust $ gameInfo jRoom + , teamsInGame = fromIntegral $ length clTeams + , clientClan = teamcolor `fmap` listToMaybe clTeams}) : AnswerClients chans ["CLIENT_FLAGS", "-r", nick cl] : [(AnswerClients [sendChan cl] $ "JOINED" : nicks) | not $ null nicks] ) + ++ [ModifyRoom (\r -> let (t', g') = moveTeams clTeamsNames . fromJust $ gameInfo r in r{gameInfo = Just g', teams = t'}) | not $ null clTeams] ++ [AnswerClients [sendChan cl] ["CLIENT_FLAGS", "+h", nick $ fromJust owner] | isJust owner] ++ [sendStateFlags cl jRoomClients | not $ null jRoomClients] ++ answerFullConfig cl jRoom ++ answerTeams cl jRoom ++ watchRound cl jRoom chans ++ [AnswerClients [sendChan cl] ["CHAT", "[greeting]", greeting jRoom] | greeting jRoom /= ""] + ++ map (\t -> AnswerClients chans ["EM", toEngineMsg $ 'G' `B.cons` t]) clTeamsNames + ++ [AnswerClients [sendChan cl] ["EM", toEngineMsg "I"] | isPaused `fmap` gameInfo jRoom == Just True] where + moveTeams :: [B.ByteString] -> GameInfo -> ([TeamInfo], GameInfo) + moveTeams cts g = (deleteFirstsBy2 (\a b -> teamname a == b) (teamsAtStart g) (leftTeams g \\ cts) + , g{leftTeams = leftTeams g \\ cts, rejoinedTeams = rejoinedTeams g ++ cts, teamsInGameNumber = teamsInGameNumber g + length cts}) sendStateFlags cl clients = AnswerClients [sendChan cl] . concat . intersperse [""] . filter (not . null) . concat $ [f "+r" ready, f "-r" unready, f "+g" ingame, f "-g" inroomlobby] where @@ -135,65 +167,52 @@ --------------------------- -- Administrator's stuff -- -handleCmd_lobby ["KICK", kickNick] = do +handleCmd_lobby ["KICK", kickNick] = serverAdminOnly $ do (ci, _) <- ask - cl <- thisClient kickId <- clientByNick kickNick - return [KickClient $ fromJust kickId | isAdministrator cl && isJust kickId && fromJust kickId /= ci] + return [KickClient $ fromJust kickId | isJust kickId && fromJust kickId /= ci] -handleCmd_lobby ["BAN", banNick, reason, duration] = do +handleCmd_lobby ["BAN", banNick, reason, duration] = serverAdminOnly $ do (ci, _) <- ask - cl <- thisClient banId <- clientByNick banNick - return [BanClient (readInt_ duration) reason (fromJust banId) | isAdministrator cl && isJust banId && fromJust banId /= ci] + return [BanClient (readInt_ duration) reason (fromJust banId) | isJust banId && fromJust banId /= ci] -handleCmd_lobby ["BANIP", ip, reason, duration] = do - cl <- thisClient - return [BanIP ip (readInt_ duration) reason | isAdministrator cl] +handleCmd_lobby ["BANIP", ip, reason, duration] = serverAdminOnly $ + return [BanIP ip (readInt_ duration) reason] -handleCmd_lobby ["BANNICK", n, reason, duration] = do - cl <- thisClient - return [BanNick n (readInt_ duration) reason | isAdministrator cl] +handleCmd_lobby ["BANNICK", n, reason, duration] = serverAdminOnly $ + return [BanNick n (readInt_ duration) reason] -handleCmd_lobby ["BANLIST"] = do - cl <- thisClient - return [BanList | isAdministrator cl] +handleCmd_lobby ["BANLIST"] = serverAdminOnly $ + return [BanList] -handleCmd_lobby ["UNBAN", entry] = do - cl <- thisClient - return [Unban entry | isAdministrator cl] +handleCmd_lobby ["UNBAN", entry] = serverAdminOnly $ + return [Unban entry] -handleCmd_lobby ["SET_SERVER_VAR", "MOTD_NEW", newMessage] = do - cl <- thisClient - return [ModifyServerInfo (\si -> si{serverMessage = newMessage}) | isAdministrator cl] +handleCmd_lobby ["SET_SERVER_VAR", "MOTD_NEW", newMessage] = serverAdminOnly $ + return [ModifyServerInfo (\si -> si{serverMessage = newMessage})] -handleCmd_lobby ["SET_SERVER_VAR", "MOTD_OLD", newMessage] = do - cl <- thisClient - return [ModifyServerInfo (\si -> si{serverMessageForOldVersions = newMessage}) | isAdministrator cl] +handleCmd_lobby ["SET_SERVER_VAR", "MOTD_OLD", newMessage] = serverAdminOnly $ + return [ModifyServerInfo (\si -> si{serverMessageForOldVersions = newMessage})] -handleCmd_lobby ["SET_SERVER_VAR", "LATEST_PROTO", protoNum] = do - cl <- thisClient - return [ModifyServerInfo (\si -> si{latestReleaseVersion = readNum}) | isAdministrator cl && readNum > 0] +handleCmd_lobby ["SET_SERVER_VAR", "LATEST_PROTO", protoNum] = serverAdminOnly $ + return [ModifyServerInfo (\si -> si{latestReleaseVersion = readNum}) | readNum > 0] where readNum = readInt_ protoNum -handleCmd_lobby ["GET_SERVER_VAR"] = do - cl <- thisClient - return [SendServerVars | isAdministrator cl] +handleCmd_lobby ["GET_SERVER_VAR"] = serverAdminOnly $ + return [SendServerVars] -handleCmd_lobby ["CLEAR_ACCOUNTS_CACHE"] = do - cl <- thisClient - return [ClearAccountsCache | isAdministrator cl] +handleCmd_lobby ["CLEAR_ACCOUNTS_CACHE"] = serverAdminOnly $ + return [ClearAccountsCache] -handleCmd_lobby ["RESTART_SERVER"] = do - cl <- thisClient - return [RestartServer | isAdministrator cl] +handleCmd_lobby ["RESTART_SERVER"] = serverAdminOnly $ + return [RestartServer] -handleCmd_lobby ["STATS"] = do - cl <- thisClient - return [Stats | isAdministrator cl] +handleCmd_lobby ["STATS"] = serverAdminOnly $ + return [Stats] handleCmd_lobby _ = return [ProtocolError "Incorrect command (state: in lobby)"] diff -r 31570b766315 -r ed5a6478e710 gameServer/HWProtoNEState.hs --- a/gameServer/HWProtoNEState.hs Tue Nov 10 18:16:35 2015 +0100 +++ b/gameServer/HWProtoNEState.hs Tue Nov 10 20:43:13 2015 +0100 @@ -1,13 +1,33 @@ +{- + * Hedgewars, a free turn based strategy game + * Copyright (c) 2004-2015 Andrey Korotaev + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + \-} + {-# LANGUAGE OverloadedStrings, CPP #-} module HWProtoNEState where import Control.Monad.Reader +import qualified Data.ByteString.Lazy as BL import qualified Data.ByteString.Char8 as B +import Data.Digest.Pure.SHA -------------------------------------- import CoreTypes -import Actions import Utils import RoomsAndClients +import HandlerUtils handleCmd_NotEntered :: CmdHandler @@ -42,12 +62,29 @@ (ci, irnc) <- ask let cl = irnc `client` ci - if passwd == webPassword cl then + if clientProto cl < 48 && passwd == webPassword cl then return $ JoinLobby : [AnswerClients [sendChan cl] ["ADMIN_ACCESS"] | isAdministrator cl] else return [ByeClient "Authentication failed"] +handleCmd_NotEntered ["PASSWORD", passwd, clientSalt] = do + (ci, irnc) <- ask + let cl = irnc `client` ci + + let clientHash = h [clientSalt, serverSalt cl, webPassword cl, showB $ clientProto cl, "!hedgewars"] + let serverHash = h [serverSalt cl, clientSalt, webPassword cl, showB $ clientProto cl, "!hedgewars"] + + if passwd == clientHash then + return [ + AnswerClients [sendChan cl] ["SERVER_AUTH", serverHash] + , JoinLobby + ] + else + return [ByeClient "Authentication failed"] + where + h = B.pack . showDigest . sha1 . BL.fromChunks + #if defined(OFFICIAL_SERVER) handleCmd_NotEntered ["CHECKER", protoNum, newNick, password] = do (ci, irnc) <- ask diff -r 31570b766315 -r ed5a6478e710 gameServer/HandlerUtils.hs --- a/gameServer/HandlerUtils.hs Tue Nov 10 18:16:35 2015 +0100 +++ b/gameServer/HandlerUtils.hs Tue Nov 10 20:43:13 2015 +0100 @@ -1,3 +1,21 @@ +{- + * Hedgewars, a free turn based strategy game + * Copyright (c) 2004-2015 Andrey Korotaev + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + \-} + module HandlerUtils where import Control.Monad.Reader @@ -8,6 +26,8 @@ import CoreTypes +type CmdHandler = [B.ByteString] -> Reader (ClientIndex, IRnC) [Action] + thisClient :: Reader (ClientIndex, IRnC) ClientInfo thisClient = do (ci, rnc) <- ask @@ -66,3 +86,10 @@ let allClientIDs = allClients rnc return $ find (\clId -> let cl = client rnc clId in n == nick cl && not (isChecker cl)) allClientIDs + +roomAdminOnly :: Reader (ClientIndex, IRnC) [Action] -> Reader (ClientIndex, IRnC) [Action] +roomAdminOnly h = thisClient >>= \cl -> if isMaster cl then h else return [] + + +serverAdminOnly :: Reader (ClientIndex, IRnC) [Action] -> Reader (ClientIndex, IRnC) [Action] +serverAdminOnly h = thisClient >>= \cl -> if isAdministrator cl then h else return [] diff -r 31570b766315 -r ed5a6478e710 gameServer/JoinsMonitor.hs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gameServer/JoinsMonitor.hs Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,61 @@ +{- + * Hedgewars, a free turn based strategy game + * Copyright (c) 2004-2015 Andrey Korotaev + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + \-} + +{-# LANGUAGE BangPatterns #-} + +module JoinsMonitor( + JoinsMonitor + , newJoinMonitor + , cleanup + , joinsSentry + ) where + +import qualified Data.Map as Map +import Data.Time +import Data.IORef +import qualified Data.ByteString as B +import Data.Maybe +import Control.Monad + +newtype JoinsMonitor = JoinsMonitor (IORef (Map.Map B.ByteString [UTCTime])) + + +newJoinMonitor :: IO JoinsMonitor +newJoinMonitor = do + ioref <- newIORef Map.empty + return (JoinsMonitor ioref) + + +cleanup :: JoinsMonitor -> UTCTime -> IO () +cleanup (JoinsMonitor ref) time = modifyIORef ref f + where + f = Map.mapMaybe (\v -> let v' = takeWhile (\t -> diffUTCTime time t < 60*60) v in if null v' then Nothing else Just v') + + +joinsSentry :: JoinsMonitor -> B.ByteString -> UTCTime -> IO Bool +joinsSentry (JoinsMonitor ref) host time = do + m <- readIORef ref + let lastJoins = map (diffUTCTime time) $ Map.findWithDefault [] host m + let last30sec = length $ takeWhile (< 30) lastJoins + let last2min = length $ takeWhile (< 120) lastJoins + let last10min = length $ takeWhile (< 600) lastJoins + let pass = last30sec < 2 && last2min < 3 && last10min < 5 + + when pass $ writeIORef ref $ Map.alter (Just . (:) time . fromMaybe []) host m + + return pass diff -r 31570b766315 -r ed5a6478e710 gameServer/NetRoutines.hs --- a/gameServer/NetRoutines.hs Tue Nov 10 18:16:35 2015 +0100 +++ b/gameServer/NetRoutines.hs Tue Nov 10 20:43:13 2015 +0100 @@ -1,3 +1,21 @@ +{- + * Hedgewars, a free turn based strategy game + * Copyright (c) 2004-2015 Andrey Korotaev + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + \-} + {-# LANGUAGE ScopedTypeVariables, OverloadedStrings #-} module NetRoutines where @@ -6,16 +24,23 @@ import Data.Time import Control.Monad import Data.Unique +import qualified Codec.Binary.Base64 as Base64 +import qualified Data.ByteString as BW +import qualified Data.ByteString.Char8 as B +import qualified Control.Exception as E +import System.Entropy +import Data.Either ----------------------------- import CoreTypes import Utils -import RoomsAndClients + acceptLoop :: Socket -> Chan CoreMessage -> IO () -acceptLoop servSock chan = forever $ - do - (sock, sockAddr) <- Network.Socket.accept servSock - +acceptLoop servSock chan = E.bracket openHandle closeHandle (forever . f) + where + f ch = E.try (Network.Socket.accept servSock) >>= \v -> case v of + Left (e :: E.IOException) -> return () + Right (sock, sockAddr) -> do clientHost <- sockAddr2String sockAddr currentTime <- getCurrentTime @@ -23,6 +48,7 @@ sendChan' <- newChan uid <- newUnique + salt <- liftM (B.pack . Base64.encode . BW.unpack) $ hGetEntropy ch 18 let newClient = (ClientInfo @@ -33,6 +59,7 @@ currentTime "" "" + salt False False 0 @@ -47,6 +74,9 @@ False Nothing Nothing + newEventsInfo + newEventsInfo + newEventsInfo 0 ) diff -r 31570b766315 -r ed5a6478e710 gameServer/OfficialServer/DBInteraction.hs --- a/gameServer/OfficialServer/DBInteraction.hs Tue Nov 10 18:16:35 2015 +0100 +++ b/gameServer/OfficialServer/DBInteraction.hs Tue Nov 10 20:43:13 2015 +0100 @@ -1,3 +1,21 @@ +{- + * Hedgewars, a free turn based strategy game + * Copyright (c) 2004-2015 Andrey Korotaev + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + \-} + {-# LANGUAGE CPP, ScopedTypeVariables, OverloadedStrings #-} module OfficialServer.DBInteraction ( diff -r 31570b766315 -r ed5a6478e710 gameServer/OfficialServer/GameReplayStore.hs --- a/gameServer/OfficialServer/GameReplayStore.hs Tue Nov 10 18:16:35 2015 +0100 +++ b/gameServer/OfficialServer/GameReplayStore.hs Tue Nov 10 20:43:13 2015 +0100 @@ -1,4 +1,22 @@ -{-# LANGUAGE ScopedTypeVariables #-} +{- + * Hedgewars, a free turn based strategy game + * Copyright (c) 2004-2015 Andrey Korotaev + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + \-} + +{-# LANGUAGE ScopedTypeVariables, OverloadedStrings #-} module OfficialServer.GameReplayStore where import Data.Time @@ -12,6 +30,7 @@ import Data.List import qualified Data.ByteString as B import System.Directory +import Control.DeepSeq --------------- import CoreTypes import EngineInteraction @@ -19,13 +38,13 @@ pickReplayFile :: Int -> [String] -> IO String pickReplayFile p blackList = do - files <- liftM (filter (\f -> sameProto f && notBlacklisted f)) $ getDirectoryContents "replays" + files <- liftM (filter (\f -> sameProto f && notBlacklisted ("replays/" ++ f))) $ getDirectoryContents "replays" if (not $ null files) then return $ "replays/" ++ head files else return "" where - sameProto = (isSuffixOf ('.' : show p)) + sameProto = isSuffixOf ('.' : show p) notBlacklisted = flip notElem blackList saveReplay :: RoomInfo -> IO () @@ -51,11 +70,12 @@ where loadFile :: String -> IO (Maybe CheckInfo, [B.ByteString]) loadFile fileName = E.handle (\(e :: SomeException) -> - warningM "REPLAYS" ("Problems reading " ++ fileName ++ ": " ++ show e) >> return (Nothing, [])) $ do + warningM "REPLAYS" ("Problems reading " ++ fileName ++ ": " ++ show e) >> return (Just $ CheckInfo fileName [] Nothing, [])) $ do (teams, params1, params2, roundMsgs) <- liftM read $ readFile fileName - return $ ( - Just (CheckInfo fileName teams) - , replayToDemo teams (Map.fromList params1) (Map.fromList params2) (reverse roundMsgs) + let d = replayToDemo teams (Map.fromList params1) (Map.fromList params2) (reverse roundMsgs) + d `deepseq` return $ ( + Just (CheckInfo fileName teams (fst d)) + , snd d ) moveFailedRecord :: String -> IO () diff -r 31570b766315 -r ed5a6478e710 gameServer/OfficialServer/checker.hs --- a/gameServer/OfficialServer/checker.hs Tue Nov 10 18:16:35 2015 +0100 +++ b/gameServer/OfficialServer/checker.hs Tue Nov 10 20:43:13 2015 +0100 @@ -1,3 +1,21 @@ +{- + * Hedgewars, a free turn based strategy game + * Copyright (c) 2004-2015 Andrey Korotaev + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + \-} + {-# LANGUAGE CPP, ScopedTypeVariables, OverloadedStrings #-} module Main where @@ -12,7 +30,7 @@ import Control.Concurrent import Network import Network.BSD -import Network.Socket hiding (recv) +import Network.Socket hiding (recv, sClose) import Network.Socket.ByteString import qualified Data.ByteString.Char8 as B import qualified Data.ByteString as BW @@ -28,7 +46,7 @@ readInt_ str = case B.readInt str of Just (i, t) | B.null t -> fromIntegral i - _ -> 0 + _ -> 0 data Message = Packet [B.ByteString] | CheckFailed B.ByteString @@ -36,7 +54,7 @@ deriving Show serverAddress = "netserver.hedgewars.org" -protocolNumber = "45" +protocolNumber = "49" getLines :: Handle -> IO [B.ByteString] getLines h = g @@ -69,18 +87,18 @@ "ACHIEVEMENT" : typ : teamname : location : value : ps bs ps _ = [] -checkReplay :: Chan Message -> [B.ByteString] -> IO () -checkReplay coreChan msgs = do +checkReplay :: String -> String -> String -> Chan Message -> [B.ByteString] -> IO () +checkReplay home exe prefix coreChan msgs = do tempDir <- getTemporaryDirectory (fileName, h) <- openBinaryTempFile tempDir "checker-demo" B.hPut h . BW.pack . concat . map (fromMaybe [] . Base64.decode . B.unpack) $ msgs hFlush h hClose h - (_, _, Just hOut, _) <- createProcess (proc "/usr/home/unC0Rr/Sources/Hedgewars/Releases/0.9.19/bin/hwengine" + (_, _, Just hOut, _) <- createProcess (proc exe [fileName - , "--user-prefix", "/usr/home/unC0Rr/.hedgewars" - , "--prefix", "/usr/home/unC0Rr/Sources/Hedgewars/Releases/0.9.19/share/hedgewars/Data" + , "--user-prefix", home + , "--prefix", prefix , "--nomusic" , "--nosound" , "--stats-only" @@ -121,8 +139,8 @@ sendPacket packet = writeChan chan $ Packet packet -session :: B.ByteString -> B.ByteString -> Socket -> IO () -session l p s = do +session :: B.ByteString -> B.ByteString -> String -> String -> String -> Socket -> IO () +session l p home exe prefix s = do noticeM "Core" "Connected" coreChan <- newChan forkIO $ recvLoop s coreChan @@ -148,10 +166,10 @@ onPacket :: Chan Message -> [B.ByteString] -> IO () onPacket _ ("CONNECTED":_) = do answer ["CHECKER", protocolNumber, l, p] - answer ["READY"] onPacket _ ["PING"] = answer ["PONG"] + onPacket _ ["LOGONPASSED"] = answer ["READY"] onPacket chan ("REPLAY":msgs) = do - checkReplay chan msgs + checkReplay home exe prefix chan msgs warningM "Check" "Started check" onPacket _ ("BYE" : xs) = error $ show xs onPacket _ _ = return () @@ -169,18 +187,24 @@ updateGlobalLogger "Check" (setLevel DEBUG) updateGlobalLogger "Engine" (setLevel DEBUG) + d <- getHomeDirectory Right (login, password) <- runErrorT $ do - d <- liftIO $ getHomeDirectory conf <- join . liftIO . CF.readfile CF.emptyCP $ d ++ "/.hedgewars/settings.ini" l <- CF.get conf "net" "nick" p <- CF.get conf "net" "passwordhash" return (B.pack l, B.pack p) + Right (exeFullname, dataPrefix) <- runErrorT $ do + conf <- join . liftIO . CF.readfile CF.emptyCP $ d ++ "/.hedgewars/checker.ini" + l <- CF.get conf "engine" "exe" + p <- CF.get conf "engine" "prefix" + return (l, p) + Exception.bracket setupConnection (\s -> noticeM "Core" "Shutting down" >> sClose s) - (session login password) + (session login password (d ++ "/.hedgewars") exeFullname dataPrefix) where setupConnection = do noticeM "Core" "Connecting to the server..." diff -r 31570b766315 -r ed5a6478e710 gameServer/OfficialServer/extdbinterface.hs --- a/gameServer/OfficialServer/extdbinterface.hs Tue Nov 10 18:16:35 2015 +0100 +++ b/gameServer/OfficialServer/extdbinterface.hs Tue Nov 10 20:43:13 2015 +0100 @@ -1,3 +1,21 @@ +{- + * Hedgewars, a free turn based strategy game + * Copyright (c) 2004-2015 Andrey Korotaev + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + \-} + {-# LANGUAGE ScopedTypeVariables, OverloadedStrings #-} module Main where @@ -7,17 +25,20 @@ import Control.Exception import System.IO import Data.Maybe -import Database.HDBC -import Database.HDBC.MySQL -import Data.List (lookup) +import Database.MySQL.Simple +import Database.MySQL.Simple.QueryResults +import Database.MySQL.Simple.Result +import Data.List (lookup, elem) import qualified Data.ByteString.Char8 as B +import Data.Word +import Data.Int -------------------------- import CoreTypes import Utils dbQueryAccount = - "SELECT users.pass, \ + "SELECT CASE WHEN users.status = 1 THEN users.pass ELSE '' END, \ \ (SELECT COUNT(users_roles.rid) FROM users_roles WHERE users.uid = users_roles.uid AND users_roles.rid = 3), \ \ (SELECT COUNT(users_roles.rid) FROM users_roles WHERE users.uid = users_roles.uid AND users_roles.rid = 13) \ \ FROM users WHERE users.name = ?" @@ -26,9 +47,18 @@ "INSERT INTO gameserver_stats (players, rooms, last_update) VALUES (?, ?, UNIX_TIMESTAMP())" dbQueryAchievement = - "INSERT INTO achievements (time, typeid, userid, value, filename, location) \ + "INSERT INTO achievements (time, typeid, userid, value, filename, location, protocol) \ \ VALUES (?, (SELECT id FROM achievement_types WHERE name = ?), (SELECT uid FROM users WHERE name = ?), \ - \ ?, ?, ?)" + \ ?, ?, ?, ?)" + +dbQueryGamesHistory = + "INSERT INTO rating_games (script, protocol, filename, time, vamp, ropes, infattacks) \ + \ VALUES (?, ?, ?, ?, ?, ?, ?)" + +dbQueryGameId = "SELECT LAST_INSERT_ID()" + +dbQueryGamesHistoryPlaces = "INSERT INTO rating_players (userid, gameid, place) \ + \ VALUES ((SELECT uid FROM users WHERE name = ?), ?, ?)" dbQueryReplayFilename = "SELECT filename FROM achievements WHERE id = ?" @@ -39,67 +69,84 @@ case q of CheckAccount clId clUid clNick _ -> do - statement <- prepare dbConn dbQueryAccount - execute statement [SqlByteString clNick] - result <- fetchRow statement - finish statement - let response = - if isJust result then let [pass, adm, contr] = fromJust result in - ( - clId, - clUid, - HasAccount - (fromSql pass) - (fromSql adm == Just (1 :: Int)) - (fromSql contr == Just (1 :: Int)) - ) - else - (clId, clUid, Guest) + results <- query dbConn dbQueryAccount $ Only clNick + let response = case results of + [(pass, adm, contr)] -> + ( + clId, + clUid, + HasAccount + (pass) + (adm == Just (1 :: Int)) + (contr == Just (1 :: Int)) + ) + _ -> + (clId, clUid, Guest) print response hFlush stdout GetReplayName clId clUid fileId -> do - statement <- prepare dbConn dbQueryReplayFilename - execute statement [SqlByteString fileId] - result <- fetchRow statement - finish statement - let fn = if (isJust result) then fromJust . fromSql . head . fromJust $ result else "" + results <- query dbConn dbQueryReplayFilename $ Only fileId + let fn = if null results then "" else fromOnly $ head results print (clId, clUid, ReplayName fn) hFlush stdout SendStats clients rooms -> - run dbConn dbQueryStats [SqlInt32 $ fromIntegral clients, SqlInt32 $ fromIntegral rooms] >> return () ---StoreAchievements (B.pack fileName) (map toPair teams) info - StoreAchievements fileName teams info -> - mapM_ (run dbConn dbQueryAchievement) $ (parseStats fileName teams) info + void $ execute dbConn dbQueryStats (clients, rooms) + StoreAchievements p fileName teams g info -> + sequence_ $ parseStats dbConn p fileName teams g info -readTime = read . B.unpack . B.take 19 . B.drop 8 - +--readTime = read . B.unpack . B.take 19 . B.drop 8 +readTime = B.take 19 . B.drop 8 -parseStats :: B.ByteString -> [(B.ByteString, B.ByteString)] -> [B.ByteString] -> [[SqlValue]] -parseStats fileName teams = ps +parseStats :: + Connection + -> Word16 + -> B.ByteString + -> [(B.ByteString, B.ByteString)] + -> GameDetails + -> [B.ByteString] + -> [IO Int64] +parseStats dbConn p fileName teams (GameDetails script infRopes vamp infAttacks) = ps where time = readTime fileName + ps :: [B.ByteString] -> [IO Int64] ps [] = [] - ps ("DRAW" : bs) = ps bs - ps ("WINNERS" : n : bs) = ps $ drop (readInt_ n) bs - ps ("ACHIEVEMENT" : typ : teamname : location : value : bs) = - [ SqlUTCTime time - , SqlByteString typ - , SqlByteString $ fromMaybe "" (lookup teamname teams) - , SqlInt32 (readInt_ value) - , SqlByteString fileName - , SqlByteString location - ] : ps bs + ps ("DRAW" : bs) = execute dbConn dbQueryGamesHistory (script, (fromIntegral p) :: Int, fileName, time, vamp, infRopes, infAttacks) + : places (map drawParams teams) + : ps bs + ps ("WINNERS" : n : bs) = let winNum = readInt_ n in execute dbConn dbQueryGamesHistory (script, (fromIntegral p) :: Int, fileName, time, vamp, infRopes, infAttacks) + : places (map (placeParams (take winNum bs)) teams) + : ps (drop winNum bs) + ps ("ACHIEVEMENT" : typ : teamname : location : value : bs) = execute dbConn dbQueryAchievement + ( time + , typ + , fromMaybe "" (lookup teamname teams) + , (readInt_ value) :: Int + , fileName + , location + , (fromIntegral p) :: Int + ) : ps bs ps (b:bs) = ps bs - + drawParams t = (snd t, 0 :: Int) + placeParams winners t = (snd t, if (fst t) `elem` winners then 1 else 2 :: Int) + places :: [(B.ByteString, Int)] -> IO Int64 + places params = do + res <- query_ dbConn dbQueryGameId + let gameId = case res of + [Only a] -> a + _ -> 0 + mapM_ (execute dbConn dbQueryGamesHistoryPlaces . midInsert gameId) params + return 0 + midInsert :: Int -> (a, b) -> (a, Int, b) + midInsert g (a, b) = (a, g, b) dbConnectionLoop mySQLConnectionInfo = - Control.Exception.handle (\(e :: IOException) -> hPutStrLn stderr $ show e) $ handleSqlError $ + Control.Exception.handle (\(e :: SomeException) -> hPutStrLn stderr $ show e) $ bracket - (connectMySQL mySQLConnectionInfo) - disconnect + (connect mySQLConnectionInfo) + close dbInteractionLoop @@ -112,6 +159,11 @@ dbLogin <- getLine dbPassword <- getLine - let mySQLConnectInfo = defaultMySQLConnectInfo {mysqlHost = dbHost, mysqlDatabase = dbName, mysqlUser = dbLogin, mysqlPassword = dbPassword} + let mySQLConnectInfo = defaultConnectInfo { + connectHost = dbHost + , connectDatabase = dbName + , connectUser = dbLogin + , connectPassword = dbPassword + } dbConnectionLoop mySQLConnectInfo diff -r 31570b766315 -r ed5a6478e710 gameServer/Opts.hs --- a/gameServer/Opts.hs Tue Nov 10 18:16:35 2015 +0100 +++ b/gameServer/Opts.hs Tue Nov 10 20:43:13 2015 +0100 @@ -1,3 +1,21 @@ +{- + * Hedgewars, a free turn based strategy game + * Copyright (c) 2004-2015 Andrey Korotaev + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + \-} + {-# LANGUAGE CPP #-} module Opts ( diff -r 31570b766315 -r ed5a6478e710 gameServer/RoomsAndClients.hs --- a/gameServer/RoomsAndClients.hs Tue Nov 10 18:16:35 2015 +0100 +++ b/gameServer/RoomsAndClients.hs Tue Nov 10 20:43:13 2015 +0100 @@ -1,3 +1,21 @@ +{- + * Hedgewars, a free turn based strategy game + * Copyright (c) 2004-2015 Andrey Korotaev + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + \-} + {-# LANGUAGE BangPatterns, GeneralizedNewtypeDeriving #-} module RoomsAndClients( @@ -22,6 +40,7 @@ client'sM, room'sM, allClientsM, + allRoomsM, clientsM, roomsM, roomClientsM, @@ -158,6 +177,9 @@ allClientsM :: MRoomsAndClients r c -> IO [ClientIndex] allClientsM (MRoomsAndClients (_, clients)) = liftM (map ClientIndex) $ indicesM clients +allRoomsM :: MRoomsAndClients r c -> IO [RoomIndex] +allRoomsM (MRoomsAndClients (rooms, _)) = liftM (map RoomIndex) $ indicesM rooms + clientsM :: MRoomsAndClients r c -> IO [c] clientsM (MRoomsAndClients (_, clients)) = indicesM clients >>= mapM (liftM client' . readElem clients) diff -r 31570b766315 -r ed5a6478e710 gameServer/ServerCore.hs --- a/gameServer/ServerCore.hs Tue Nov 10 18:16:35 2015 +0100 +++ b/gameServer/ServerCore.hs Tue Nov 10 20:43:13 2015 +0100 @@ -1,3 +1,21 @@ +{- + * Hedgewars, a free turn based strategy game + * Copyright (c) 2004-2015 Andrey Korotaev + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + \-} + module ServerCore where import Control.Concurrent @@ -6,14 +24,11 @@ import Control.Monad.Reader import Control.Monad.State.Strict import Data.Set as Set -import qualified Data.ByteString.Char8 as B -import Control.DeepSeq import Data.Unique import Data.Maybe -------------------------------------- import CoreTypes import NetRoutines -import HWProtoCore import Actions import OfficialServer.DBInteraction import ServerState @@ -23,13 +38,6 @@ timerLoop tick messagesChan = threadDelay 30000000 >> writeChan messagesChan (TimerAction tick) >> timerLoop (tick + 1) messagesChan -reactCmd :: [B.ByteString] -> StateT ServerState IO () -reactCmd cmd = do - (Just ci) <- gets clientIndex - rnc <- gets roomsClients - actions <- liftIO $ withRoomsAndClients rnc (\irnc -> runReader (handleCmd cmd) (ci, irnc)) - forM_ (actions `deepseq` actions) processAction - mainLoop :: StateT ServerState IO () mainLoop = forever $ do -- get >>= \s -> put $! s @@ -46,7 +54,7 @@ removed <- gets removedClients unless (ci `Set.member` removed) $ do modify (\s -> s{clientIndex = Just ci}) - reactCmd cmd + processAction $ ReactCmd cmd Remove ci -> processAction (DeleteClient ci) @@ -62,7 +70,10 @@ TimerAction tick -> mapM_ processAction $ - PingAll : [StatsAction | even tick] + PingAll + : CheckVotes + : [StatsAction | even tick] + ++ [Cleanup | tick `mod` 100 == 0] startServer :: ServerInfo -> IO () @@ -79,5 +90,6 @@ startDBConnection si rnc <- newRoomsAndClients newRoom + jm <- newJoinMonitor - evalStateT mainLoop (ServerState Nothing si Set.empty rnc) + evalStateT mainLoop (ServerState Nothing si Set.empty rnc jm) diff -r 31570b766315 -r ed5a6478e710 gameServer/ServerState.hs --- a/gameServer/ServerState.hs Tue Nov 10 18:16:35 2015 +0100 +++ b/gameServer/ServerState.hs Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,25 @@ +{- + * Hedgewars, a free turn based strategy game + * Copyright (c) 2004-2015 Andrey Korotaev + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + \-} + module ServerState ( module RoomsAndClients, + module JoinsMonitor, clientRoomA, ServerState(..), client's, @@ -17,12 +36,14 @@ ---------------------- import RoomsAndClients import CoreTypes +import JoinsMonitor data ServerState = ServerState { clientIndex :: !(Maybe ClientIndex), serverInfo :: !ServerInfo, removedClients :: !(Set.Set ClientIndex), - roomsClients :: !MRnC + roomsClients :: !MRnC, + joinsMonitor :: !JoinsMonitor } diff -r 31570b766315 -r ed5a6478e710 gameServer/Store.hs --- a/gameServer/Store.hs Tue Nov 10 18:16:35 2015 +0100 +++ b/gameServer/Store.hs Tue Nov 10 20:43:13 2015 +0100 @@ -1,3 +1,21 @@ +{- + * Hedgewars, a free turn based strategy game + * Copyright (c) 2004-2015 Andrey Korotaev + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + \-} + {-# LANGUAGE BangPatterns, GeneralizedNewtypeDeriving #-} module Store( ElemIndex(), diff -r 31570b766315 -r ed5a6478e710 gameServer/Utils.hs --- a/gameServer/Utils.hs Tue Nov 10 18:16:35 2015 +0100 +++ b/gameServer/Utils.hs Tue Nov 10 20:43:13 2015 +0100 @@ -1,3 +1,21 @@ +{- + * Hedgewars, a free turn based strategy game + * Copyright (c) 2004-2015 Andrey Korotaev + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + \-} + {-# LANGUAGE OverloadedStrings #-} module Utils where @@ -56,9 +74,10 @@ t : replaceTeam tm ts illegalName :: B.ByteString -> Bool -illegalName s = B.null s || B.length s > 40 || B.all isSpace s || isSpace (B.head s) || isSpace (B.last s) || B.any isIllegalChar s +illegalName b = B.null b || length s > 40 || all isSpace s || isSpace (head s) || isSpace (last s) || any isIllegalChar s where - isIllegalChar c = c `List.elem` "$()*+?[]^{|}" + s = UTF8.toString b + isIllegalChar c = c `List.elem` ("$()*+?[]^{|}\x7F" ++ ['\x00'..'\x1F']) protoNumber2ver :: Word16 -> B.ByteString protoNumber2ver v = Map.findWithDefault "Unknown" v vermap @@ -92,6 +111,12 @@ , (44, "0.9.19-dev") , (45, "0.9.19") , (46, "0.9.20-dev") + , (47, "0.9.20") + , (48, "0.9.21-dev") + , (49, "0.9.21") + , (50, "0.9.22-dev") + , (51, "0.9.22") + , (52, "0.9.23-dev") ] askFromConsole :: B.ByteString -> IO B.ByteString @@ -114,7 +139,7 @@ readInt_ str = case B.readInt str of Just (i, t) | B.null t -> fromIntegral i - _ -> 0 + _ -> 0 cutHost :: B.ByteString -> B.ByteString cutHost = B.intercalate "." . flip (++) ["*","*"] . List.take 2 . B.split '.' @@ -126,7 +151,7 @@ upperCase = UTF8.fromString . map Char.toUpper . UTF8.toString roomInfo :: Word16 -> B.ByteString -> RoomInfo -> [B.ByteString] -roomInfo p n r +roomInfo p n r | p < 46 = [ showB $ isJust $ gameInfo r, name r, @@ -137,7 +162,7 @@ head (Map.findWithDefault ["Default"] "SCHEME" (params r)), head (Map.findWithDefault ["Default"] "AMMO" (params r)) ] - | otherwise = [ + | p < 48 = [ showB $ isJust $ gameInfo r, name r, showB $ playersIn r, @@ -148,6 +173,25 @@ head (Map.findWithDefault ["Default"] "SCHEME" (params r)), head (Map.findWithDefault ["Default"] "AMMO" (params r)) ] + | otherwise = [ + B.pack roomFlags, + name r, + showB $ playersIn r, + showB $ length $ teams r, + n, + Map.findWithDefault "+rnd+" "MAP" (mapParams r), + head (Map.findWithDefault ["Normal"] "SCRIPT" (params r)), + head (Map.findWithDefault ["Default"] "SCHEME" (params r)), + head (Map.findWithDefault ["Default"] "AMMO" (params r)) + ] + where + roomFlags = concat [ + "-" + , ['g' | isJust $ gameInfo r] + , ['p' | not . B.null $ password r] + , ['j' | isRestrictedJoins r] + , ['r' | isRegisteredOnly r] + ] answerFullConfigParams :: ClientInfo @@ -160,6 +204,11 @@ ++ (("SCHEME", pr Map.! "SCHEME") : (filter (\(p, _) -> p /= "SCHEME") $ Map.toList pr)) + | clientProto cl < 48 = map (toAnswer cl) $ + ("FULLMAPCONFIG", let l = Map.elems mpr in if length l > 5 then tail l else l) + : ("SCHEME", pr Map.! "SCHEME") + : (filter (\(p, _) -> p /= "SCHEME") $ Map.toList pr) + | otherwise = map (toAnswer cl) $ ("FULLMAPCONFIG", Map.elems mpr) : ("SCHEME", pr Map.! "SCHEME") @@ -182,4 +231,13 @@ loc = id maybeNick :: Maybe ClientInfo -> B.ByteString -maybeNick = fromMaybe "[empty]" . liftM nick +maybeNick = fromMaybe "[]" . liftM nick + +-- borrowed from Data.List, just more general in types +deleteBy2 :: (a -> b -> Bool) -> a -> [b] -> [b] +deleteBy2 _ _ [] = [] +deleteBy2 eq x (y:ys) = if x `eq` y then ys else y : deleteBy2 eq x ys + +deleteFirstsBy2 :: (a -> b -> Bool) -> [a] -> [b] -> [a] +deleteFirstsBy2 eq = foldl (flip (deleteBy2 (flip eq))) + diff -r 31570b766315 -r ed5a6478e710 gameServer/Votes.hs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gameServer/Votes.hs Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,179 @@ +{- + * Hedgewars, a free turn based strategy game + * Copyright (c) 2004-2015 Andrey Korotaev + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + \-} + +{-# LANGUAGE OverloadedStrings #-} +module Votes where + +import Control.Monad.Reader +import Control.Monad.State.Strict +import ServerState +import qualified Data.ByteString.Char8 as B +import qualified Data.List as L +import qualified Data.Map as Map +import Data.Maybe +import Control.Applicative +------------------- +import Utils +import CoreTypes +import HandlerUtils +import EngineInteraction + + +voted :: Bool -> Bool -> Reader (ClientIndex, IRnC) [Action] +voted forced vote = do + cl <- thisClient + rm <- thisRoom + uid <- liftM clUID thisClient + + case voting rm of + Nothing -> + return [AnswerClients [sendChan cl] ["CHAT", "[server]", loc "There's no voting going on"]] + Just voting -> + if (not forced) && (uid `L.notElem` entitledToVote voting) then + return [] + else if (not forced) && (uid `L.elem` map fst (votes voting)) then + return [AnswerClients [sendChan cl] ["CHAT", "[server]", loc "You already have voted"]] + else if forced && (not $ isAdministrator cl) then + return [] + else + ((:) (AnswerClients [sendChan cl] ["CHAT", "[server]", loc "Your vote counted"])) + <$> (actOnVoting $ voting{votes = (uid, vote):votes voting}) + + where + actOnVoting :: Voting -> Reader (ClientIndex, IRnC) [Action] + actOnVoting vt = do + let (pro, contra) = L.partition snd $ votes vt + let totalV = length $ entitledToVote vt + let successV = totalV `div` 2 + 1 + + if (forced && not vote) || (length contra > totalV - successV) then + closeVoting + else if (forced && vote) || (length pro >= successV) then do + a <- act $ voteType vt + c <- closeVoting + return $ c ++ a + else + return [ModifyRoom $ \r -> r{voting = Just vt}] + + closeVoting = do + chans <- roomClientsChans + return [ + AnswerClients chans ["CHAT", "[server]", loc "Voting closed"] + , ModifyRoom (\r -> r{voting = Nothing}) + ] + + act (VoteKick nickname) = do + (thisClientId, rnc) <- ask + maybeClientId <- clientByNick nickname + rm <- thisRoom + let kickId = fromJust maybeClientId + let kickCl = rnc `client` kickId + let sameRoom = clientRoom rnc thisClientId == clientRoom rnc kickId + return + [KickRoomClient kickId | + isJust maybeClientId + && sameRoom + && ((isNothing $ gameInfo rm) || teamsInGame kickCl == 0) + ] + act (VoteMap roomSave) = do + rm <- thisRoom + let rs = Map.lookup roomSave (roomSaves rm) + case rs of + Nothing -> return [] + Just (mp, p) -> do + cl <- thisClient + chans <- roomClientsChans + let a = map (replaceChans chans) $ answerFullConfigParams cl mp p + return $ + (ModifyRoom $ \r -> r{params = p, mapParams = mp}) + : SendUpdateOnThisRoom + : a + where + replaceChans chans (AnswerClients _ msg) = AnswerClients chans msg + replaceChans _ a = a + act (VotePause) = do + rm <- thisRoom + chans <- roomClientsChans + let modifyGameInfo f room = room{gameInfo = fmap f $ gameInfo room} + return [ModifyRoom (modifyGameInfo $ \g -> g{isPaused = not $ isPaused g}), + AnswerClients chans ["CHAT", "[server]", loc "Pause toggled"], + AnswerClients chans ["EM", toEngineMsg "I"]] + act (VoteNewSeed) = + return [SetRandomSeed] + act (VoteHedgehogsPerTeam h) = do + rm <- thisRoom + chans <- roomClientsChans + let answers = concatMap (\t -> + [ModifyRoom $ modifyTeam t{hhnum = h} + , AnswerClients chans ["HH_NUM", teamname t, showB h]] + ) $ if length curteams * h > 48 then [] else curteams + ; + curteams = + if isJust $ gameInfo rm then + teamsAtStart . fromJust . gameInfo $ rm + else + teams rm + + return $ ModifyRoom (\r -> r{defaultHedgehogsNumber = h}) : answers + + +startVote :: VoteType -> Reader (ClientIndex, IRnC) [Action] +startVote vt = do + (ci, rnc) <- ask + --cl <- thisClient + rm <- thisRoom + chans <- roomClientsChans + + let uids = map (clUID . client rnc) . roomClients rnc $ clientRoom rnc ci + + if isJust $ voting rm then + return [] + else + return [ + ModifyRoom (\r -> r{voting = Just (newVoting vt){entitledToVote = uids}}) + , AnswerClients chans ["CHAT", "[server]", B.concat [loc "New voting started", ": ", voteInfo vt]] + , ReactCmd ["VOTE", "YES"] + ] + + +checkVotes :: StateT ServerState IO [Action] +checkVotes = do + rnc <- gets roomsClients + liftM concat $ io $ do + ris <- allRoomsM rnc + mapM (check rnc) ris + where + check rnc ri = do + e <- room'sM rnc voting ri + case e of + Just rv -> do + modifyRoom rnc (\r -> r{voting = if voteTTL rv == 0 then Nothing else Just rv{voteTTL = voteTTL rv - 1}}) ri + if voteTTL rv == 0 then do + chans <- liftM (map sendChan) $ roomClientsM rnc ri + return [AnswerClients chans ["CHAT", "[server]", loc "Voting expired"]] + else + return [] + Nothing -> return [] + + +voteInfo :: VoteType -> B.ByteString +voteInfo (VoteKick n) = B.concat [loc "kick", " ", n] +voteInfo (VoteMap n) = B.concat [loc "map", " ", n] +voteInfo (VotePause) = B.concat [loc "pause"] +voteInfo (VoteNewSeed) = B.concat [loc "new seed"] +voteInfo (VoteHedgehogsPerTeam i) = B.concat [loc "number of hedgehogs in team", " ", showB i] diff -r 31570b766315 -r ed5a6478e710 gameServer/hedgewars-server.cabal --- a/gameServer/hedgewars-server.cabal Tue Nov 10 18:16:35 2015 +0100 +++ b/gameServer/hedgewars-server.cabal Tue Nov 10 20:43:13 2015 +0100 @@ -8,15 +8,16 @@ Maintainer: unC0Rr@hedgewars.org Category: Game Build-type: Simple -Cabal-version: >=1.2 +Cabal-version: >=1.10 Executable hedgewars-server main-is: hedgewars-server.hs + default-language: Haskell2010 + Build-depends: base >= 4.3, - unix, containers, vector, bytestring, @@ -29,6 +30,12 @@ hslogger, process, deepseq, - utf8-string + utf8-string, + SHA, + entropy, + zlib >= 0.5.3 && < 0.6 + + if !os(windows) + build-depends: unix ghc-options: -O2 diff -r 31570b766315 -r ed5a6478e710 gameServer/hedgewars-server.hs --- a/gameServer/hedgewars-server.hs Tue Nov 10 18:16:35 2015 +0100 +++ b/gameServer/hedgewars-server.hs Tue Nov 10 20:43:13 2015 +0100 @@ -1,3 +1,21 @@ +{- + * Hedgewars, a free turn based strategy game + * Copyright (c) 2004-2015 Andrey Korotaev + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + \-} + {-# LANGUAGE CPP, ScopedTypeVariables, OverloadedStrings #-} module Main where @@ -24,6 +42,7 @@ setupLoggers = do updateGlobalLogger "Clients" (setLevel NOTICE) updateGlobalLogger "Core" (setLevel NOTICE) + updateGlobalLogger "REPLAYS" (setLevel NOTICE) server :: ServerInfo -> IO () diff -r 31570b766315 -r ed5a6478e710 gameServer/stresstest.hs --- a/gameServer/stresstest.hs Tue Nov 10 18:16:35 2015 +0100 +++ b/gameServer/stresstest.hs Tue Nov 10 20:43:13 2015 +0100 @@ -1,3 +1,21 @@ +{- + * Hedgewars, a free turn based strategy game + * Copyright (c) 2004-2015 Andrey Korotaev + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + \-} + {-# LANGUAGE CPP #-} module Main where diff -r 31570b766315 -r ed5a6478e710 gameServer/stresstest2.hs --- a/gameServer/stresstest2.hs Tue Nov 10 18:16:35 2015 +0100 +++ b/gameServer/stresstest2.hs Tue Nov 10 20:43:13 2015 +0100 @@ -1,3 +1,21 @@ +{- + * Hedgewars, a free turn based strategy game + * Copyright (c) 2004-2015 Andrey Korotaev + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + \-} + {-# LANGUAGE CPP #-} module Main where diff -r 31570b766315 -r ed5a6478e710 gameServer/stresstest3.hs --- a/gameServer/stresstest3.hs Tue Nov 10 18:16:35 2015 +0100 +++ b/gameServer/stresstest3.hs Tue Nov 10 20:43:13 2015 +0100 @@ -1,3 +1,21 @@ +{- + * Hedgewars, a free turn based strategy game + * Copyright (c) 2004-2015 Andrey Korotaev + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + \-} + {-# LANGUAGE CPP #-} module Main where diff -r 31570b766315 -r ed5a6478e710 hedgewars/ArgParsers.pas --- a/hedgewars/ArgParsers.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/ArgParsers.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,23 +13,44 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) - + {$INCLUDE "options.inc"} unit ArgParsers; interface -{$IFNDEF HWLIBRARY} procedure GetParams; -{$ELSE} -procedure parseCommandLine(argc: LongInt; argv: PPChar); +{$IFDEF HWLIBRARY} +var operatingsystem_parameter_argc: LongInt = 0; export; + operatingsystem_parameter_argv: pointer = nil; export; + operatingsystem_parameter_envp: pointer = nil; export; + +function ParamCount: LongInt; +function ParamStr(i: LongInt): shortstring; {$ENDIF} implementation uses uVariables, uTypes, uUtils, uSound, uConsts; -var isInternal: Boolean {$IFDEF HWLIBRARY} = true{$ENDIF}; +var isInternal: Boolean; + +{$IFDEF HWLIBRARY} + +type PCharArray = array[0..255] of PChar; + PPCharArray = ^PCharArray; + +function ParamCount: LongInt; +begin + ParamCount:= operatingsystem_parameter_argc - 1 +end; + +function ParamStr(i: LongInt): shortstring; +begin + ParamStr:= StrPas(PPCharArray(operatingsystem_parameter_argv)^[i]) +end; + +{$ENDIF} procedure GciEasterEgg; begin @@ -45,7 +66,6 @@ WriteLn(stdout, ' \///////////// \///////// \/////////// '); WriteLn(stdout, ' '); WriteLn(stdout, ' Command Line Parser Implementation by a Google Code-In Student '); - WriteLn(stdout, ' ASCII Art easter egg idea by @sheepluva '); WriteLn(stdout, ' '); end; @@ -112,7 +132,7 @@ end end; -function parseNick(nick: String): String; +function parseNick(nick: shortstring): shortstring; begin if isInternal then parseNick:= DecodeBase64(nick) @@ -147,6 +167,7 @@ // Silence the hint that appears when USE_VIDEO_RECORDING is not defined paramIndex:= paramIndex; {$IFDEF USE_VIDEO_RECORDING} +{$IFNDEF HWLIBRARY} GameType:= gmtRecord; inc(paramIndex); cVideoFramerateNum:= StrToInt(ParamStr(paramIndex)); inc(paramIndex); @@ -157,44 +178,50 @@ cVideoQuality:= StrToInt(ParamStr(paramIndex)); inc(paramIndex); cAudioCodec:= ParamStr(paramIndex); inc(paramIndex); {$ENDIF} +{$ENDIF} end; -function getLongIntParameter(str:String; var paramIndex:LongInt; var wrongParameter:Boolean): LongInt; +function getLongIntParameter(str:shortstring; var paramIndex:LongInt; var wrongParameter:Boolean): LongInt; var tmpInt, c: LongInt; begin inc(paramIndex); +{$IFDEF PAS2C OR HWLIBRARY} + val(str, tmpInt); +{$ELSE} val(str, tmpInt, c); wrongParameter:= c <> 0; if wrongParameter then WriteLn(stderr, 'ERROR: '+ParamStr(paramIndex-1)+' expects a number, you passed "'+str+'"'); +{$ENDIF} getLongIntParameter:= tmpInt; end; -function getStringParameter(str:String; var paramIndex:LongInt; var wrongParameter:Boolean): String; +function getstringParameter(str:shortstring; var paramIndex:LongInt; var wrongParameter:Boolean): shortstring; begin inc(paramIndex); wrongParameter:= (str='') or (Copy(str,1,2) = '--'); + {$IFNDEF HWLIBRARY} if wrongParameter then - WriteLn(stderr, 'ERROR: '+ParamStr(paramIndex-1)+' expects a string, you passed "'+str+'"'); - getStringParameter:= str; + WriteLn(stderr, 'ERROR: '+ParamStr(paramIndex-1)+' expects a string, you passed "'+str+'"'); + {$ENDIF} + getstringParameter:= str; end; - -procedure parseClassicParameter(cmdArray: Array of String; size:LongInt; var paramIndex:LongInt); Forward; +procedure parseClassicParameter(cmdarray: array of string; size:LongInt; var paramIndex:LongInt); forward; -function parseParameter(cmd:String; arg:String; var paramIndex:LongInt): Boolean; -const videoArray: Array [1..5] of String = ('--fullscreen-width','--fullscreen-height', '--width', '--height', '--depth'); - audioArray: Array [1..3] of String = ('--volume','--nomusic','--nosound'); - otherArray: Array [1..3] of String = ('--locale','--fullscreen','--showfps'); - mediaArray: Array [1..10] of String = ('--fullscreen-width', '--fullscreen-height', '--width', '--height', '--depth', '--volume','--nomusic','--nosound','--locale','--fullscreen'); - allArray: Array [1..18] of String = ('--fullscreen-width','--fullscreen-height', '--width', '--height', '--depth','--volume','--nomusic','--nosound','--locale','--fullscreen','--showfps','--altdmg','--frame-interval','--low-quality','--no-teamtag','--no-hogtag','--no-healthtag','--translucent-tags'); - reallyAll: array[0..34] of shortstring = ( +function parseParameter(cmd:string; arg:string; var paramIndex:LongInt): Boolean; +const videoarray: array [0..4] of string = ('--fullscreen-width','--fullscreen-height', '--width', '--height', '--depth'); + audioarray: array [0..2] of string = ('--volume','--nomusic','--nosound'); + otherarray: array [0..2] of string = ('--locale','--fullscreen','--showfps'); + mediaarray: array [0..9] of string = ('--fullscreen-width', '--fullscreen-height', '--width', '--height', '--depth', '--volume','--nomusic','--nosound','--locale','--fullscreen'); + allarray: array [0..17] of string = ('--fullscreen-width','--fullscreen-height', '--width', '--height', '--depth','--volume','--nomusic','--nosound','--locale','--fullscreen','--showfps','--altdmg','--frame-interval','--low-quality','--no-teamtag','--no-hogtag','--no-healthtag','--translucent-tags'); + reallyAll: array[0..35] of shortstring = ( '--prefix', '--user-prefix', '--locale', '--fullscreen-width', '--fullscreen-height', '--width', '--height', '--frame-interval', '--volume','--nomusic', '--nosound', '--fullscreen', '--showfps', '--altdmg', '--low-quality', '--raw-quality', '--stereo', '--nick', {deprecated} '--depth', '--set-video', '--set-audio', '--set-other', '--set-multimedia', '--set-everything', {internal} '--internal', '--port', '--recorder', '--landpreview', - {misc} '--stats-only', '--gci', '--help','--no-teamtag','--no-hogtag','--no-healthtag','--translucent-tags'); + {misc} '--stats-only', '--gci', '--help','--no-teamtag','--no-hogtag','--no-healthtag','--translucent-tags','--lua-test'); var cmdIndex: byte; begin parseParameter:= false; @@ -205,9 +232,9 @@ while (cmdIndex <= High(reallyAll)) and (cmd <> reallyAll[cmdIndex]) do inc(cmdIndex); case cmdIndex of - {--prefix} 0 : PathPrefix := getStringParameter (arg, paramIndex, parseParameter); - {--user-prefix} 1 : UserPathPrefix := getStringParameter (arg, paramIndex, parseParameter); - {--locale} 2 : cLocaleFName := getStringParameter (arg, paramIndex, parseParameter); + {--prefix} 0 : PathPrefix := getstringParameter (arg, paramIndex, parseParameter); + {--user-prefix} 1 : UserPathPrefix := getstringParameter (arg, paramIndex, parseParameter); + {--locale} 2 : cLocaleFName := getstringParameter (arg, paramIndex, parseParameter); {--fullscreen-width} 3 : cFullscreenWidth := max(getLongIntParameter(arg, paramIndex, parseParameter), cMinScreenWidth); {--fullscreen-height} 4 : cFullscreenHeight := max(getLongIntParameter(arg, paramIndex, parseParameter), cMinScreenHeight); {--width} 5 : cWindowedWidth := max(2 * (getLongIntParameter(arg, paramIndex, parseParameter) div 2), cMinScreenWidth); @@ -222,14 +249,14 @@ {--low-quality} 14 : cReducedQuality := $FFFFFFFF xor rqLowRes; {--raw-quality} 15 : cReducedQuality := getLongIntParameter(arg, paramIndex, parseParameter); {--stereo} 16 : setStereoMode ( getLongIntParameter(arg, paramIndex, parseParameter) ); - {--nick} 17 : UserNick := parseNick( getStringParameter(arg, paramIndex, parseParameter) ); + {--nick} 17 : UserNick := parseNick( getstringParameter(arg, paramIndex, parseParameter) ); {deprecated options} {--depth} 18 : setDepth(paramIndex); - {--set-video} 19 : parseClassicParameter(videoArray,5,paramIndex); - {--set-audio} 20 : parseClassicParameter(audioArray,3,paramIndex); - {--set-other} 21 : parseClassicParameter(otherArray,3,paramIndex); - {--set-multimedia} 22 : parseClassicParameter(mediaArray,10,paramIndex); - {--set-everything} 23 : parseClassicParameter(allArray,14,paramIndex); + {--set-video} 19 : parseClassicParameter(videoarray,5,paramIndex); + {--set-audio} 20 : parseClassicParameter(audioarray,3,paramIndex); + {--set-other} 21 : parseClassicParameter(otherarray,3,paramIndex); + {--set-multimedia} 22 : parseClassicParameter(mediaarray,10,paramIndex); + {--set-everything} 23 : parseClassicParameter(allarray,14,paramIndex); {"internal" options} {--internal} 24 : {$IFDEF HWLIBRARY}isInternal:= true{$ENDIF}; {--port} 25 : setIpcPort( getLongIntParameter(arg, paramIndex, parseParameter), parseParameter ); @@ -239,13 +266,14 @@ {--stats-only} 28 : statsOnlyGame(); {--gci} 29 : GciEasterEgg(); {--help} 30 : DisplayUsage(); - {--no-teamtag} 31 : cTagsMask := cTagsMask and not htTeamName; - {--no-hogtag} 32 : cTagsMask := cTagsMask and not htName; - {--no-healthtag} 33 : cTagsMask := cTagsMask and not htHealth; - {--translucent-tags} 34 : cTagsMask := cTagsMask or htTransparent + {--no-teamtag} 31 : cTagsMask := cTagsMask and (not htTeamName); + {--no-hogtag} 32 : cTagsMask := cTagsMask and (not htName); + {--no-healthtag} 33 : cTagsMask := cTagsMask and (not htHealth); + {--translucent-tags} 34 : cTagsMask := cTagsMask or htTransparent; + {--lua-test} 35 : begin cTestLua := true; SetSound(false); cScriptName := getstringParameter(arg, paramIndex, parseParameter); WriteLn(stdout, 'Lua test file specified: ' + cScriptName);end; else begin - //Asusme the first "non parameter" is the replay file, anything else is invalid + //Assume the first "non parameter" is the replay file, anything else is invalid if (recordFileName = '') and (Copy(cmd,1,2) <> '--') then recordFileName := cmd else @@ -257,10 +285,10 @@ end; end; -procedure parseClassicParameter(cmdArray: Array of String; size:LongInt; var paramIndex:LongInt); +procedure parseClassicParameter(cmdarray: array of string; size:LongInt; var paramIndex:LongInt); var index, tmpInt: LongInt; isBool, isValid: Boolean; - cmd, arg, newSyntax: String; + cmd, arg, newSyntax: string; begin WriteLn(stdout, 'WARNING: you are using a deprecated command, which could be removed in a future version!'); WriteLn(stdout, ' Consider updating to the latest syntax, which is much more flexible!'); @@ -273,8 +301,8 @@ begin newSyntax:= ''; inc(paramIndex); - cmd:= cmdArray[index]; - arg:= ParamStr(paramIndex); + cmd:= cmdarray[index]; + arg:= cmdarray[paramIndex]; isValid:= (cmd<>'--depth'); // check if the parameter is a boolean one @@ -287,9 +315,9 @@ if isValid then begin parseParameter(cmd, arg, tmpInt); - newSyntax := newSyntax + cmd + ' '; + newSyntax:= newSyntax + cmd + ' '; if not isBool then - newSyntax := newSyntax + arg + ' '; + newSyntax:= newSyntax + arg + ' '; end; inc(index); end; @@ -299,15 +327,16 @@ WriteLn(stdout, ''); end; -procedure parseCommandLine{$IFDEF HWLIBRARY}(argc: LongInt; argv: PPChar){$ENDIF}; +procedure parseCommandLine; var paramIndex: LongInt; paramTotal: LongInt; index, nextIndex: LongInt; wrongParameter: boolean; //var tmpInt: LongInt; begin + paramIndex:= {$IFDEF HWLIBRARY}0{$ELSE}1{$ENDIF}; - paramTotal:= {$IFDEF HWLIBRARY}argc-1{$ELSE}ParamCount{$ENDIF}; //-1 because pascal enumeration is inclusive + paramTotal:= ParamCount; //-1 because pascal enumeration is inclusive (* WriteLn(stdout, 'total parameters: ' + inttostr(paramTotal)); tmpInt:= 0; @@ -324,23 +353,18 @@ index:= paramIndex; if index = paramTotal then nextIndex:= index else nextIndex:= index+1; - {$IFDEF HWLIBRARY} - wrongParameter:= parseParameter( argv[index], argv[nextIndex], paramIndex); - {$ELSE} wrongParameter:= parseParameter( ParamStr(index), ParamStr(nextIndex), paramIndex); - {$ENDIF} inc(paramIndex); end; if wrongParameter = true then GameType:= gmtSyntax; end; -{$IFNDEF HWLIBRARY} procedure GetParams; begin isInternal:= (ParamStr(1) = '--internal'); - UserPathPrefix := '.'; + UserPathPrefix := _S'.'; PathPrefix := cDefaultPathPrefix; recordFileName := ''; parseCommandLine(); @@ -351,7 +375,7 @@ GameType := gmtSyntax; end; - if (not isInternal) and (recordFileName = '') then + if (not cTestLua) and (not isInternal) and (recordFileName = '') then begin WriteLn(stderr, 'You must specify a replay file'); GameType := gmtSyntax; @@ -367,7 +391,6 @@ WriteLn(stdout,'UserPathPrefix: ' + UserPathPrefix); *) end; -{$ENDIF} end. diff -r 31570b766315 -r ed5a6478e710 hedgewars/CMakeLists.txt --- a/hedgewars/CMakeLists.txt Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/CMakeLists.txt Tue Nov 10 20:43:13 2015 +0100 @@ -6,7 +6,33 @@ find_package(SDL2_ttf REQUIRED) find_package(SDL2_mixer REQUIRED) -include (CheckLibraryExists) +include(CheckLibraryExists) +include(${CMAKE_MODULE_PATH}/utils.cmake) + + +enable_language(Pascal) +add_flag_append(CMAKE_Pascal_FLAGS "-Cs2000000") +add_flag_append(CMAKE_Pascal_FLAGS_DEBUG "-gv") +add_flag_append(CMAKE_Pascal_FLAGS_RELEASE "-Xs") +if(UNIX) + include(TargetArch) + target_architecture(CMAKE_TARGET_ARCHITECTURES) + if(${CMAKE_Pascal_COMPILER_VERSION} VERSION_GREATER 2.7 OR ${CMAKE_TARGET_ARCHITECTURES} MATCHES "x86_64" OR ${CMAKE_TARGET_ARCHITECTURES} MATCHES "i386") + add_flag_append(CMAKE_Pascal_FLAGS "-fPIC") + endif() +endif(UNIX) + +# convert list into pascal array +if(FONTS_DIRS) + list(LENGTH FONTS_DIRS ndirs) + set(FONTS_DIRS_ARRAY "array [0..${ndirs}] of PChar = (") + foreach(fontdir ${FONTS_DIRS}) + set(FONTS_DIRS_ARRAY "${FONTS_DIRS_ARRAY}\n_P'${fontdir}',") + endforeach(fontdir) + set(FONTS_DIRS_ARRAY "${FONTS_DIRS_ARRAY}\nnil);\n") +else(FONTS_DIRS) + set(FONTS_DIRS_ARRAY "array [0..1] of PChar = (nil, nil);") +endif(FONTS_DIRS) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.inc.in ${CMAKE_CURRENT_BINARY_DIR}/config.inc) include_directories(${CMAKE_CURRENT_BINARY_DIR}) @@ -49,6 +75,9 @@ uLandPainted.pas uLandOutline.pas uLandGenMaze.pas + uLandGenPerlin.pas + uLandGenTemplateBased.pas + uLandUtils.pas #this is where dependency tracking becomes hard uStore.pas @@ -79,31 +108,45 @@ #these interact with everything, so compile last uScript.pas - hwengine.pas - - #we also have uTouch.pas - options.inc - ${CMAKE_CURRENT_BINARY_DIR}/config.inc ) -include(${CMAKE_MODULE_PATH}/utils.cmake) - -if (${CMAKE_Pascal_COMPILER_VERSION} VERSION_LESS 2.2 OR # older versions are just ancient - (${CMAKE_Pascal_COMPILER_VERSION} VERSION_LESS 2.6 AND APPLE)) # because of 64bit and opengl bindings +if(${CMAKE_Pascal_COMPILER_VERSION} VERSION_LESS 2.2 OR # older versions are just ancient + (${CMAKE_Pascal_COMPILER_VERSION} VERSION_LESS 2.6 AND APPLE)) # because of 64bit and opengl bindings message(FATAL_ERROR "Your FreePascal installation is too old (fpc ${CMAKE_Pascal_COMPILER_VERSION})!") -elseif(CMAKE_Pascal_COMPILER_VERSION VERSION_GREATER 2.4) +elseif(${CMAKE_Pascal_COMPILER_VERSION} VERSION_GREATER 2.4) #enable INLINE only with a recent version of fpc add_flag_prepend(CMAKE_Pascal_FLAGS_RELEASE -Si) endif() +#generic folder where our libraries reside +add_flag_append(CMAKE_Pascal_FLAGS "-Fl${LIBRARY_OUTPUT_PATH}") -if(FFMPEG_FOUND) +#DEPENDECIES AND EXECUTABLES SECTION +if(APPLE AND (NOT BUILD_ENGINE_LIBRARY)) + #on OSX we need to provide the SDL_main() function when building as + #executable and the entry point too + add_subdirectory(sdlmain) + list(APPEND HW_LINK_LIBS SDLmain) + add_flag_append(CMAKE_Pascal_FLAGS "-k-lsdlmain") + add_flag_append(CMAKE_Pascal_FLAGS "-XMSDL_main") + #OpenGL deps + add_flag_append(CMAKE_Pascal_FLAGS "-k-framework -kCocoa") + add_flag_append(CMAKE_Pascal_FLAGS "-k-framework -kOpenGL") + + #set the correct library or framework style depending on the main SDL + string(FIND "${SDL_LIBRARY}" "dylib" sdl_framework) + if(${sdl_framework} GREATER -1) + add_flag_append(CMAKE_Pascal_FLAGS "-k-lsdl -k-lsdl_image -k-lsdl_mixer -k-lsdl_ttf -k-lsdl_net") + else() + add_flag_append(CMAKE_Pascal_FLAGS "-k-framework -kSDL -k-framework -kSDL_image -k-framework -kSDL_mixer -k-framework -kSDL_net -k-framework -kSDL_net -k-framework -kSDL_ttf") + endif() +endif() + +if(LIBAV_FOUND) add_subdirectory(avwrapper) list(APPEND HW_LINK_LIBS avwrapper) add_definitions(-dUSE_VIDEO_RECORDING) - add_flag_append(CMAKE_Pascal_FLAGS -Fl${LIBRARY_OUTPUT_PATH}) - endif() find_package_or_disable_msg(PNG NOPNG "Screenshots will be saved in BMP") @@ -111,11 +154,11 @@ list(INSERT engine_sources 0 PNGh.pas) list(REMOVE_AT PNG_LIBRARIES 1) #removing the zlib library path get_filename_component(PNG_LIBRARY_DIR ${PNG_LIBRARIES} PATH) - add_flag_append(CMAKE_Pascal_FLAGS -Fl${PNG_LIBRARY_DIR}) + add_flag_append(CMAKE_Pascal_FLAGS "-k-L${PNG_LIBRARY_DIR} -Fl${PNG_LIBRARY_DIR}") add_definitions(-dPNG_SCREENSHOTS) endif() -if(LUA_FOUND AND LUA_SYSTEM) +if(LUA_SYSTEM) get_filename_component(LUA_LIBRARY_DIR ${LUA_LIBRARY} PATH) get_filename_component(LUA_LIBRARY_NAME ${LUA_LIBRARY} NAME) #NAME_WE would strip the .1 (or .2) next to the ".so" @@ -127,27 +170,44 @@ add_flag_append(CMAKE_Pascal_FLAGS "-XLAlua=${lua_output_name}") endif() - -if(NOT PHYSFS_FOUND) +if(PHYSFS_SYSTEM) + get_filename_component(PHYSFS_LIBRARY_DIR ${PHYSFS_LIBRARY} PATH) + add_flag_append(CMAKE_Pascal_FLAGS "-Fl${PHYSFS_LIBRARY}") +else() add_definitions(-dPHYSFS_INTERNAL) list(APPEND HW_LINK_LIBS physfs) #-XLA is a beta fpc flag that renames libraries before passing them to the linker #we also have to pass PHYSFS_INTERNAL to satisfy windows runtime requirements #(should be harmless on other platforms) - add_flag_append(CMAKE_Pascal_FLAGS "-Fl${LIBRARY_OUTPUT_PATH} -XLAphysfs=${physfs_output_name}") + add_flag_append(CMAKE_Pascal_FLAGS "-XLAphysfs=${physfs_output_name}") endif() list(APPEND HW_LINK_LIBS physlayer) + #Mix_Init/Mix_Quit from SDL_mixer 1.2.10 +check_library_exists(${SDL2MIXER_LIBRARY} Mix_Init "" HAVE_MIXINIT) +if(HAVE_MIXINIT) + add_definitions(-dSDL_MIXER_NEWER) +endif(HAVE_MIXINIT) + +#IMG_Init/IMG_Quit from SDL_image 1.2.8 +check_library_exists(${SDL2IMAGE_LIBRARY} IMG_Init "" HAVE_IMGINIT) +if(HAVE_IMGINIT) + add_definitions(-dSDL_IMAGE_NEWER) +endif(HAVE_IMGINIT) + +#opengl 2 +IF(GL2) + add_definitions(-dGL2) +ENDIF(GL2) #needs to be last add_definitions(-dDEBUGFILE) -# make source files objects depend on their predecessors in list +# source files are with full path after this set(sourcefiles_sofar "${CMAKE_CURRENT_SOURCE_DIR}/options.inc" "${CMAKE_CURRENT_BINARY_DIR}/config.inc") foreach(loop_var ${engine_sources}) - SET_SOURCE_FILES_PROPERTIES(${loop_var} PROPERTIES OBJECT_DEPENDS "${sourcefiles_sofar}") list(APPEND sourcefiles_sofar "${CMAKE_CURRENT_SOURCE_DIR}/${loop_var}") endforeach(loop_var) @@ -155,9 +215,11 @@ #SOURCE AND PROGRAMS SECTION if(BUILD_ENGINE_LIBRARY) message("***Engine will be built as library (experimental)***") - if(APPLE AND current_macosx_version VERSION_GREATER "10.5") - # due to compiler/linker issues on Max OS X 10.6 -k-no_order_inits is needed to avoid linking fail - add_flag_prepend(CMAKE_Pascal_FLAGS "-k-no_order_inits") + if(APPLE) + if (${current_macosx_version} VERSION_GREATER "10.5") + # due to compiler/linker issues on Max OS X 10.6 -k-no_order_inits is needed to avoid linking fail + add_flag_prepend(CMAKE_Pascal_FLAGS "-k-no_order_inits") + endif() endif() #workaround for missing support during object generation @@ -166,12 +228,14 @@ add_flag_prepend(CMAKE_Pascal_FLAGS "-o${LIBRARY_OUTPUT_PATH}/${engine_output_name}") add_definitions(-dHWLIBRARY) - add_library(hwengine SHARED ${engine_sources} hwLibrary.pas) + set_source_files_properties(hwLibrary.pas PROPERTIES OBJECT_DEPENDS "${sourcefiles_sofar};${CMAKE_CURRENT_SOURCE_DIR}/hwengine.pas") + add_library(hwengine SHARED hwLibrary.pas) else() # no need to change name here because target has same name set(engine_output_name "hwengine${CMAKE_EXECUTABLE_SUFFIX}") set(destination_dir ${target_binary_install_dir}) - add_executable(hwengine ${engine_sources}) + set_source_files_properties(hwengine.pas PROPERTIES OBJECT_DEPENDS "${sourcefiles_sofar}") + add_executable(hwengine hwengine.pas) endif() #even though not actually used, this will trigger relink if any lib changes diff -r 31570b766315 -r ed5a6478e710 hedgewars/LuaPas.pas --- a/hedgewars/LuaPas.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/LuaPas.pas Tue Nov 10 20:43:13 2015 +0100 @@ -21,7 +21,9 @@ {$ENDIF} type +{$IFNDEF PAS2C} size_t = Cardinal; +{$ENDIF} Psize_t = ^size_t; PPointer = ^Pointer; @@ -55,12 +57,14 @@ @* of a function in debug information. ** CHANGE it if you want a different size. *) + const LUA_IDSIZE = 60; (* @@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system. *) + const LUAL_BUFFERSIZE = 1024; @@ -70,6 +74,7 @@ ** CHANGE them if you want different prompts. (You can also change the ** prompts dynamically, assigning to globals _PROMPT/_PROMPT2.) *) + const LUA_PROMPT = '> '; LUA_PROMPT2 = '>> '; @@ -113,6 +118,7 @@ ** See Copyright Notice at the end of this file *) + const LUA_VERSION = 'Lua 5.1'; LUA_VERSION_NUM = 501; @@ -132,8 +138,10 @@ LUA_ENVIRONINDEX = -10001; LUA_GLOBALSINDEX = -10002; + function lua_upvalueindex(idx : LongInt) : LongInt; // a marco + const (* thread status; 0 is OK *) LUA_YIELD_ = 1; // Note: the ending underscore is needed in Pascal @@ -142,6 +150,7 @@ LUA_ERRMEM = 4; LUA_ERRERR = 5; + type lua_CFunction = function(L : Plua_State) : LongInt; cdecl; @@ -156,6 +165,7 @@ *) lua_Alloc = function (ud, ptr : Pointer; osize, nsize : size_t) : Pointer; cdecl; + const (* ** basic types @@ -181,12 +191,13 @@ (* type for integer functions *) lua_Integer = LUA_INTEGER_; + (* ** state manipulation *) function lua_newstate(f : lua_Alloc; ud : Pointer) : Plua_State; cdecl; external LuaLibName; - + procedure lua_close(L: Plua_State); cdecl; external LuaLibName; function lua_newthread(L : Plua_State) : Plua_State; @@ -201,22 +212,22 @@ *) function lua_gettop(L : Plua_State) : LongInt; cdecl; external LuaLibName; - + procedure lua_settop(L : Plua_State; idx : LongInt); cdecl; external LuaLibName; - + procedure lua_pushvalue(L : Plua_State; idx : LongInt); cdecl; external LuaLibName; - + procedure lua_remove(L : Plua_State; idx : LongInt); cdecl; external LuaLibName; - + procedure lua_insert(L : Plua_State; idx : LongInt); cdecl; external LuaLibName; - + procedure lua_replace(L : Plua_State; idx : LongInt); cdecl; external LuaLibName; - + function lua_checkstack(L : Plua_State; sz : LongInt) : LongBool; cdecl; external LuaLibName; @@ -229,57 +240,55 @@ *) function lua_isnumber(L : Plua_State; idx : LongInt) : LongBool; cdecl; external LuaLibName; - + function lua_isstring(L : Plua_State; idx : LongInt) : LongBool; cdecl; external LuaLibName; - + function lua_iscfunction(L : Plua_State; idx : LongInt) : LongBool; cdecl; external LuaLibName; - + function lua_isuserdata(L : Plua_State; idx : LongInt) : LongBool; cdecl; external LuaLibName; - + function lua_type(L : Plua_State; idx : LongInt) : LongInt; cdecl; external LuaLibName; - + function lua_typename(L : Plua_State; tp : LongInt) : PChar; cdecl; external LuaLibName; - function lua_equal(L : Plua_State; idx1, idx2 : LongInt) : LongBool; cdecl; external LuaLibName; - + function lua_rawequal(L : Plua_State; idx1, idx2 : LongInt) : LongBool; cdecl; external LuaLibName; - + function lua_lessthan(L : Plua_State; idx1, idx2 : LongInt) : LongBool; cdecl; external LuaLibName; function lua_tonumber(L : Plua_State; idx : LongInt) : lua_Number; cdecl; external LuaLibName; - + function lua_tointeger(L : Plua_State; idx : LongInt) : lua_Integer; cdecl; external LuaLibName; - + function lua_toboolean(L : Plua_State; idx : LongInt) : LongBool; cdecl; external LuaLibName; - - + function lua_tolstring(L : Plua_State; idx : LongInt; len : Psize_t) : PChar; cdecl; external LuaLibName; - + function lua_objlen(L : Plua_State; idx : LongInt) : size_t; cdecl; external LuaLibName; - + function lua_tocfunction(L : Plua_State; idx : LongInt) : lua_CFunction; cdecl; external LuaLibName; - + function lua_touserdata(L : Plua_State; idx : LongInt) : Pointer; cdecl; external LuaLibName; - + function lua_tothread(L : Plua_State; idx : LongInt) : Plua_State; cdecl; external LuaLibName; - + function lua_topointer(L : Plua_State; idx : LongInt) : Pointer; cdecl; external LuaLibName; @@ -289,36 +298,35 @@ *) procedure lua_pushnil(L : Plua_State); cdecl; external LuaLibName; - + procedure lua_pushnumber(L : Plua_State; n : lua_Number); cdecl; external LuaLibName; - + procedure lua_pushinteger(L : Plua_State; n : lua_Integer); cdecl; external LuaLibName; - + procedure lua_pushlstring(L : Plua_State; const s : PChar; ls : size_t); cdecl; external LuaLibName; - + procedure lua_pushstring(L : Plua_State; const s : PChar); cdecl; external LuaLibName; - - + function lua_pushvfstring(L : Plua_State; const fmt : PChar; argp : Pointer) : PChar; cdecl; external LuaLibName; - + function lua_pushfstring(L : Plua_State; const fmt : PChar) : PChar; varargs; cdecl; external LuaLibName; - + procedure lua_pushcclosure(L : Plua_State; fn : lua_CFunction; n : LongInt); cdecl; external LuaLibName; - + procedure lua_pushboolean(L : Plua_State; b : LongBool); cdecl; external LuaLibName; - + procedure lua_pushlightuserdata(L : Plua_State; p : Pointer); cdecl; external LuaLibName; - + function lua_pushthread(L : Plua_state) : Cardinal; cdecl; external LuaLibName; @@ -328,25 +336,25 @@ *) procedure lua_gettable(L : Plua_State ; idx : LongInt); cdecl; external LuaLibName; - + procedure lua_getfield(L : Plua_State; idx : LongInt; k : PChar); cdecl; external LuaLibName; - + procedure lua_rawget(L : Plua_State; idx : LongInt); cdecl; external LuaLibName; - + procedure lua_rawgeti(L : Plua_State; idx, n : LongInt); cdecl; external LuaLibName; - + procedure lua_createtable(L : Plua_State; narr, nrec : LongInt); cdecl; external LuaLibName; - + function lua_newuserdata(L : Plua_State; sz : size_t) : Pointer; cdecl; external LuaLibName; - + function lua_getmetatable(L : Plua_State; objindex : LongInt) : LongBool; cdecl; external LuaLibName; - + procedure lua_getfenv(L : Plua_State; idx : LongInt); cdecl; external LuaLibName; @@ -356,19 +364,19 @@ *) procedure lua_settable(L : Plua_State; idx : LongInt); cdecl; external LuaLibName; - + procedure lua_setfield(L : Plua_State; idx : LongInt; const k : PChar); cdecl; external LuaLibName; - + procedure lua_rawset(L : Plua_State; idx : LongInt); cdecl; external LuaLibName; - + procedure lua_rawseti(L : Plua_State; idx , n: LongInt); cdecl; external LuaLibName; - + function lua_setmetatable(L : Plua_State; objindex : LongInt): LongBool; cdecl; external LuaLibName; - + function lua_setfenv(L : Plua_State; idx : LongInt): LongBool; cdecl; external LuaLibName; @@ -377,16 +385,16 @@ *) procedure lua_call(L : Plua_State; nargs, nresults : LongInt); cdecl; external LuaLibName; - + function lua_pcall(L : Plua_State; nargs, nresults, errfunc : LongInt) : LongInt; cdecl; external LuaLibName; - + function lua_cpcall(L : Plua_State; func : lua_CFunction; ud : Pointer) : LongInt; cdecl; external LuaLibName; - + function lua_load(L : Plua_State; reader : lua_Reader; dt : Pointer; const chunkname : PChar) : LongInt; cdecl; external LuaLibName; - + function lua_dump(L : Plua_State; writer : lua_Writer; data: Pointer) : LongInt; cdecl; external LuaLibName; @@ -397,16 +405,17 @@ *) function lua_yield(L : Plua_State; nresults : LongInt) : LongInt; cdecl; external LuaLibName; - + function lua_resume(L : Plua_State; narg : LongInt) : LongInt; cdecl; external LuaLibName; - + function lua_status(L : Plua_State) : LongInt; cdecl; external LuaLibName; (* ** garbage-collection functions and options *) + const LUA_GCSTOP = 0; LUA_GCRESTART = 1; @@ -434,7 +443,7 @@ function lua_getallocf(L : Plua_State; ud : PPointer) : lua_Alloc; cdecl; external LuaLibName; - + procedure lua_setallocf(L : Plua_State; f : lua_Alloc; ud : Pointer); cdecl; external LuaLibName; @@ -467,7 +476,8 @@ procedure lua_setglobal(L : Plua_State; s : PChar); procedure lua_getglobal(L : Plua_State; s : PChar); -function lua_tostring(L : Plua_State; idx : LongInt) : AnsiString; +function lua_tostring(L : Plua_State; idx : LongInt) : shortstring; +function lua_tostringA(L : Plua_State; idx : LongInt) : ansistring; (* @@ -512,17 +522,17 @@ type lua_Debug = packed record - event : LongInt; - name : PChar; (* (n) *) - namewhat : PChar; (* (n) `global', `local', `field', `method' *) - what : PChar; (* (S) `Lua', `C', `main', `tail' *) - source : PChar; (* (S) *) - currentline : LongInt; (* (l) *) - nups : LongInt; (* (u) number of upvalues *) - linedefined : LongInt; (* (S) *) + event : LUA_INTEGER_; + name : PChar; (* (n) *) + namewhat : PChar; (* (n) `global', `local', `field', `method' *) + what : PChar; (* (S) `Lua', `C', `main', `tail' *) + source : PChar; (* (S) *) + currentline : LUA_INTEGER_; (* (l) *) + nups : LUA_INTEGER_; (* (u) number of upvalues *) + linedefined : LUA_INTEGER_; (* (S) *) short_src : array [0..LUA_IDSIZE-1] of Char; (* (S) *) (* private part *) - i_ci : LongInt; (* active function *) + i_ci : LUA_INTEGER_; (* active function *) end; Plua_Debug = ^lua_Debug; @@ -532,25 +542,25 @@ function lua_getstack(L : Plua_State; level : LongInt; ar : Plua_Debug) : LongInt; cdecl; external LuaLibName; - + function lua_getinfo(L : Plua_State; const what : PChar; ar: Plua_Debug): LongInt; cdecl; external LuaLibName; - + function lua_getlocal(L : Plua_State; ar : Plua_Debug; n : LongInt) : PChar; cdecl; external LuaLibName; - + function lua_setlocal(L : Plua_State; ar : Plua_Debug; n : LongInt) : PChar; cdecl; external LuaLibName; - + function lua_getupvalue(L : Plua_State; funcindex, n : LongInt) : PChar; cdecl; external LuaLibName; - + function lua_setupvalue(L : Plua_State; funcindex, n : LongInt) : PChar; cdecl; external LuaLibName; function lua_sethook(L : Plua_State; func : lua_Hook; mask, count: LongInt): LongInt; cdecl; external LuaLibName; - + {$IFDEF LUA_GETHOOK} function lua_gethook(L : Plua_State) : lua_Hook; cdecl; external LuaLibName; @@ -558,7 +568,7 @@ function lua_gethookmask(L : Plua_State) : LongInt; cdecl; external LuaLibName; - + function lua_gethookcount(L : Plua_State) : LongInt; cdecl; external LuaLibName; @@ -912,11 +922,18 @@ lua_getfield(L, LUA_GLOBALSINDEX, s); end; -function lua_tostring(L : Plua_State; idx : LongInt) : AnsiString; +function lua_tostring(L : Plua_State; idx : LongInt) : shortstring; begin lua_tostring := StrPas(lua_tolstring(L, idx, nil)); end; +function lua_tostringA(L : Plua_State; idx : LongInt) : ansistring; +var p: PChar; +begin + p:= lua_tolstring(L, idx, nil); + lua_tostringA := ansistring(p); +end; + function lua_open : Plua_State; begin lua_open := luaL_newstate; diff -r 31570b766315 -r ed5a6478e710 hedgewars/PNGh.pas --- a/hedgewars/PNGh.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/PNGh.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} diff -r 31570b766315 -r ed5a6478e710 hedgewars/SDLh.pas --- a/hedgewars/SDLh.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/SDLh.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} @@ -235,11 +235,13 @@ KMOD_MODE = $4000; {* SDL_mixer *} - MIX_MAX_VOLUME = 128; - MIX_INIT_FLAC = $00000001; - MIX_INIT_MOD = $00000002; - MIX_INIT_MP3 = $00000004; - MIX_INIT_OGG = $00000008; + MIX_MAX_VOLUME = 128; + MIX_INIT_FLAC = $00000001; + MIX_INIT_MOD = $00000002; + MIX_INIT_MODPLUG = $00000004; + MIX_INIT_MP3 = $00000008; + MIX_INIT_OGG = $00000010; + MIX_INIT_FLUIDSYNTH = $00000020; {* SDL_TTF *} TTF_STYLE_NORMAL = 0; @@ -266,8 +268,12 @@ SDLK_BACKSPACE = 8; SDLK_RETURN = 13; SDLK_ESCAPE = 27; + SDLK_a = 97; + SDLK_c = 99; SDLK_q = 113; + SDLK_v = 118; SDLK_w = 119; + SDLK_x = 120; SDLK_DELETE = 127; SDLK_KP_ENTER = 271; SDLK_UP = 273; @@ -337,12 +343,23 @@ w, h : LongInt; pitch : LongInt; pixels: Pointer; - userdata: Pointer; - locked: LongInt; - lock_data: Pointer; +{$IFDEF PAS2C} + hwdata : Pointer; clip_rect: TSDL_Rect; - map: Pointer; - refcount: LongInt; + unsed1 : LongWord; + locked : LongWord; + map : Pointer; + format_version: Longword; + refcount : LongInt; + offset : LongInt; +{$ELSE} + userdata : Pointer; + locked : LongInt; + lock_data : Pointer; + clip_rect : TSDL_Rect; + map : Pointer; + refcount : LongInt; +{$ENDIF} end; @@ -650,6 +667,7 @@ TByteArray = array[0..65535] of Byte; PByteArray = ^TByteArray; + TLongWordArray = array[0..16383] of LongWord; PLongWordArray = ^TLongWordArray; @@ -906,6 +924,7 @@ function TTF_OpenFontRW(src: PSDL_RWops; freesrc: LongBool; size: LongInt): PTTF_Font; cdecl; external SDL_TTFLibName; procedure TTF_SetFontStyle(font: PTTF_Font; style: LongInt); cdecl; external SDL_TTFLibName; +procedure TTF_CloseFont(font: PTTF_Font); cdecl; external SDL_TTFLibName; (* SDL_mixer *) function Mix_Init(flags: LongInt): LongInt; {$IFDEF SDL_MIXER_NEWER}cdecl; external SDL_MixerLibName{$ELSE}inline{$ENDIF}; diff -r 31570b766315 -r ed5a6478e710 hedgewars/adler32.pas --- a/hedgewars/adler32.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/adler32.pas Tue Nov 10 20:43:13 2015 +0100 @@ -2,7 +2,6 @@ {ZLib - Adler32 checksum function} - interface (************************************************************************* @@ -66,7 +65,7 @@ Also, the structure was removed to simplify C conversion *) -function Adler32Update ( var adler :longint; Msg :pointer; Len :longint ) : longint; +function Adler32Update (var adler : longint; Msg :Pointer; Len :longint ) : longint; implementation @@ -124,17 +123,19 @@ end; *) -function Adler32Update(var adler: longint; Msg: pointer; Len :longint) : longint; +function Adler32Update(var adler:longint; Msg: Pointer; Len :longint) : longint; {-update Adler32 with Msg data} const BASE = 65521; {max. prime < 65536 } NMAX = 3854; {max. n with 255n(n+1)/2 + (n+1)(BASE-1) < 2^31} var - s1, s2: longint; - i, n: integer; + s1, s2 : longint; + i, n : integer; + m : PByte; begin - s1 := adler and $FFFF; - s2 := adler shr 16; + m := PByte(Msg); + s1 := Longword(adler) and $FFFF; + s2 := Longword(adler) shr 16; while Len>0 do begin if Len + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include @@ -21,13 +21,12 @@ #include #include #include + +#include "libavcodec/avcodec.h" #include "libavformat/avformat.h" +#include "libavutil/avutil.h" #include "libavutil/mathematics.h" -#ifndef AVIO_FLAG_WRITE -#define AVIO_FLAG_WRITE AVIO_WRONLY -#endif - #if (defined _MSC_VER) #define AVWRAP_DECL __declspec(dllexport) #elif ((__GNUC__ >= 3) && (!__EMX__) && (!sun)) @@ -57,15 +56,42 @@ static int g_NumSamples; +// compatibility section #if LIBAVCODEC_VERSION_MAJOR < 54 #define OUTBUFFER_SIZE 200000 static uint8_t g_OutBuffer[OUTBUFFER_SIZE]; +#define avcodec_open2(x, y, z) avcodec_open(x, y) #endif +#if LIBAVCODEC_VERSION_MAJOR < 56 +#define av_frame_alloc avcodec_alloc_frame +#define av_frame_free av_freep +#endif + +#if LIBAVCODEC_VERSION_MAJOR < 57 +#define AV_CODEC_CAP_DELAY CODEC_CAP_DELAY +#define AV_CODEC_CAP_VARIABLE_FRAME_SIZE CODEC_CAP_VARIABLE_FRAME_SIZE +#define AV_CODEC_FLAG_GLOBAL_HEADER CODEC_FLAG_GLOBAL_HEADER +#define AV_CODEC_FLAG_QSCALE CODEC_FLAG_QSCALE +#endif + +#if LIBAVFORMAT_VERSION_MAJOR < 53 +#define AVIO_FLAG_WRITE AVIO_WRONLY +#endif + +#if LIBAVFORMAT_VERSION_MAJOR < 54 +#define avformat_new_stream(x, y) av_new_stream(x, y->type == AVMEDIA_TYPE_AUDIO) +#endif + +#if LIBAVUTIL_VERSION_MAJOR < 54 +#define AV_PIX_FMT_YUV420P PIX_FMT_YUV420P +#endif + + // pointer to function from hwengine (uUtils.pas) static void (*AddFileLogRaw)(const char* pString); -static void FatalError(const char* pFmt, ...) +static int FatalError(const char* pFmt, ...) { char Buffer[1024]; va_list VaArgs; @@ -77,7 +103,7 @@ AddFileLogRaw("Error in av-wrapper: "); AddFileLogRaw(Buffer); AddFileLogRaw("\n"); - exit(1); + return(-1); } // Function to be called from libav for logging. @@ -105,11 +131,7 @@ static void AddAudioStream() { -#if LIBAVFORMAT_VERSION_MAJOR >= 53 g_pAStream = avformat_new_stream(g_pContainer, g_pACodec); -#else - g_pAStream = av_new_stream(g_pContainer, 1); -#endif if(!g_pAStream) { Log("Could not allocate audio stream\n"); @@ -131,26 +153,22 @@ g_pAudio->bit_rate = 160000; // for codecs that support variable bitrate use it, it should be better - g_pAudio->flags |= CODEC_FLAG_QSCALE; + g_pAudio->flags |= AV_CODEC_FLAG_QSCALE; g_pAudio->global_quality = 1*FF_QP2LAMBDA; // some formats want stream headers to be separate if (g_pFormat->flags & AVFMT_GLOBALHEADER) - g_pAudio->flags |= CODEC_FLAG_GLOBAL_HEADER; + g_pAudio->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; // open it -#if LIBAVCODEC_VERSION_MAJOR >= 53 if (avcodec_open2(g_pAudio, g_pACodec, NULL) < 0) -#else - if (avcodec_open(g_pAudio, g_pACodec) < 0) -#endif { Log("Could not open audio codec %s\n", g_pACodec->long_name); return; } #if LIBAVCODEC_VERSION_MAJOR >= 54 - if (g_pACodec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE) + if (g_pACodec->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE) #else if (g_pAudio->frame_size == 0) #endif @@ -158,7 +176,7 @@ else g_NumSamples = g_pAudio->frame_size; g_pSamples = (int16_t*)av_malloc(g_NumSamples*g_Channels*sizeof(int16_t)); - g_pAFrame = avcodec_alloc_frame(); + g_pAFrame = av_frame_alloc(); if (!g_pAFrame) { Log("Could not allocate frame\n"); @@ -166,13 +184,13 @@ } } -// returns non-zero if there is more sound +// returns non-zero if there is more sound, -1 in case of error static int WriteAudioFrame() { if (!g_pAStream) return 0; - AVPacket Packet = { 0 }; + AVPacket Packet; av_init_packet(&Packet); int NumSamples = fread(g_pSamples, 2*g_Channels, g_NumSamples, g_pSoundFile); @@ -189,7 +207,7 @@ // when NumSamples == 0 we still need to call encode_audio2 to flush int got_packet; if (avcodec_encode_audio2(g_pAudio, &Packet, pFrame, &got_packet) != 0) - FatalError("avcodec_encode_audio2 failed"); + return FatalError("avcodec_encode_audio2 failed"); if (!got_packet) return 0; #else @@ -210,20 +228,16 @@ // Write the compressed frame to the media file. Packet.stream_index = g_pAStream->index; if (av_interleaved_write_frame(g_pContainer, &Packet) != 0) - FatalError("Error while writing audio frame"); + return FatalError("Error while writing audio frame"); return 1; } // add a video output stream -static void AddVideoStream() +static int AddVideoStream() { -#if LIBAVFORMAT_VERSION_MAJOR >= 53 g_pVStream = avformat_new_stream(g_pContainer, g_pVCodec); -#else - g_pVStream = av_new_stream(g_pContainer, 0); -#endif if (!g_pVStream) - FatalError("Could not allocate video stream"); + return FatalError("Could not allocate video stream"); g_pVideo = g_pVStream->codec; @@ -241,20 +255,20 @@ g_pVideo->time_base.den = g_Framerate.num; g_pVideo->time_base.num = g_Framerate.den; //g_pVideo->gop_size = 12; /* emit one intra frame every twelve frames at most */ - g_pVideo->pix_fmt = PIX_FMT_YUV420P; + g_pVideo->pix_fmt = AV_PIX_FMT_YUV420P; // set quality if (g_VQuality > 100) g_pVideo->bit_rate = g_VQuality; else { - g_pVideo->flags |= CODEC_FLAG_QSCALE; + g_pVideo->flags |= AV_CODEC_FLAG_QSCALE; g_pVideo->global_quality = g_VQuality*FF_QP2LAMBDA; } // some formats want stream headers to be separate if (g_pFormat->flags & AVFMT_GLOBALHEADER) - g_pVideo->flags |= CODEC_FLAG_GLOBAL_HEADER; + g_pVideo->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; #if LIBAVCODEC_VERSION_MAJOR < 53 // for some versions of ffmpeg x264 options must be set explicitly @@ -288,38 +302,36 @@ #endif // open the codec -#if LIBAVCODEC_VERSION_MAJOR >= 53 - AVDictionary* pDict = NULL; - if (strcmp(g_pVCodec->name, "libx264") == 0) - av_dict_set(&pDict, "preset", "medium", 0); + if (avcodec_open2(g_pVideo, g_pVCodec, NULL) < 0) + return FatalError("Could not open video codec %s", g_pVCodec->long_name); - if (avcodec_open2(g_pVideo, g_pVCodec, &pDict) < 0) -#else - if (avcodec_open(g_pVideo, g_pVCodec) < 0) -#endif - FatalError("Could not open video codec %s", g_pVCodec->long_name); - - g_pVFrame = avcodec_alloc_frame(); + g_pVFrame = av_frame_alloc(); if (!g_pVFrame) - FatalError("Could not allocate frame"); + return FatalError("Could not allocate frame"); g_pVFrame->linesize[0] = g_Width; g_pVFrame->linesize[1] = g_Width/2; g_pVFrame->linesize[2] = g_Width/2; g_pVFrame->linesize[3] = 0; + return 0; } static int WriteFrame(AVFrame* pFrame) { double AudioTime, VideoTime; - + int ret; // write interleaved audio frame if (g_pAStream) { - VideoTime = (double)g_pVStream->pts.val*g_pVStream->time_base.num/g_pVStream->time_base.den; + VideoTime = (double)g_pVFrame->pts * g_pVStream->time_base.num/g_pVStream->time_base.den; do - AudioTime = (double)g_pAStream->pts.val*g_pAStream->time_base.num/g_pAStream->time_base.den; - while (AudioTime < VideoTime && WriteAudioFrame()); + { + AudioTime = (double)g_pAFrame->pts * g_pAStream->time_base.num/g_pAStream->time_base.den; + ret = WriteAudioFrame(); + } + while (AudioTime < VideoTime && ret); + if (ret < 0) + return ret; } if (!g_pVStream) @@ -341,7 +353,7 @@ Packet.size = sizeof(AVPicture); if (av_interleaved_write_frame(g_pContainer, &Packet) != 0) - FatalError("Error while writing video frame"); + return FatalError("Error while writing video frame"); return 0; } else @@ -349,7 +361,7 @@ #if LIBAVCODEC_VERSION_MAJOR >= 54 int got_packet; if (avcodec_encode_video2(g_pVideo, &Packet, pFrame, &got_packet) < 0) - FatalError("avcodec_encode_video2 failed"); + return FatalError("avcodec_encode_video2 failed"); if (!got_packet) return 0; @@ -360,7 +372,7 @@ #else Packet.size = avcodec_encode_video(g_pVideo, g_OutBuffer, OUTBUFFER_SIZE, pFrame); if (Packet.size < 0) - FatalError("avcodec_encode_video failed"); + return FatalError("avcodec_encode_video failed"); if (Packet.size == 0) return 0; @@ -373,21 +385,21 @@ // write the compressed frame in the media file Packet.stream_index = g_pVStream->index; if (av_interleaved_write_frame(g_pContainer, &Packet) != 0) - FatalError("Error while writing video frame"); + return FatalError("Error while writing video frame"); return 1; } } -AVWRAP_DECL void AVWrapper_WriteFrame(uint8_t* pY, uint8_t* pCb, uint8_t* pCr) +AVWRAP_DECL int AVWrapper_WriteFrame(uint8_t* pY, uint8_t* pCb, uint8_t* pCr) { g_pVFrame->data[0] = pY; g_pVFrame->data[1] = pCb; g_pVFrame->data[2] = pCr; - WriteFrame(g_pVFrame); + return WriteFrame(g_pVFrame); } -AVWRAP_DECL void AVWrapper_Init( +AVWRAP_DECL int AVWrapper_Init( void (*pAddFileLogRaw)(const char*), const char* pFilename, const char* pDesc, @@ -399,6 +411,7 @@ int FramerateNum, int FramerateDen, int VQuality) { + int ret; AddFileLogRaw = pAddFileLogRaw; av_log_set_callback( &LogCallback ); @@ -414,12 +427,12 @@ // find format g_pFormat = av_guess_format(pFormatName, NULL, NULL); if (!g_pFormat) - FatalError("Format \"%s\" was not found", pFormatName); + return FatalError("Format \"%s\" was not found", pFormatName); // allocate the output media context g_pContainer = avformat_alloc_context(); if (!g_pContainer) - FatalError("Could not allocate output context"); + return FatalError("Could not allocate output context"); g_pContainer->oformat = g_pFormat; @@ -442,7 +455,11 @@ g_pAStream = NULL; if (g_pVCodec) - AddVideoStream(); + { + ret = AddVideoStream(); + if (ret < 0) + return ret; + } else Log("Video codec \"%s\" was not found; video will be ignored.\n", pVCodecName); @@ -462,7 +479,7 @@ Log("Audio codec \"%s\" was not found; audio will be ignored.\n", pACodecName); if (!g_pAStream && !g_pVStream) - FatalError("No video, no audio, aborting..."); + return FatalError("No video, no audio, aborting..."); // write format info to log av_dump_format(g_pContainer, 0, g_pContainer->filename, 1); @@ -471,22 +488,36 @@ if (!(g_pFormat->flags & AVFMT_NOFILE)) { if (avio_open(&g_pContainer->pb, g_pContainer->filename, AVIO_FLAG_WRITE) < 0) - FatalError("Could not open output file (%s)", g_pContainer->filename); + return FatalError("Could not open output file (%s)", g_pContainer->filename); } // write the stream header, if any avformat_write_header(g_pContainer, NULL); g_pVFrame->pts = -1; + return 0; } -AVWRAP_DECL void AVWrapper_Close() +AVWRAP_DECL int AVWrapper_Close() { + int ret; // output buffered frames - if (g_pVCodec->capabilities & CODEC_CAP_DELAY) - while( WriteFrame(NULL) ); + if (g_pVCodec->capabilities & AV_CODEC_CAP_DELAY) + { + do + ret = WriteFrame(NULL); + while (ret >= 0); + if (ret < 0) + return ret; + } // output any remaining audio - while( WriteAudioFrame() ); + do + { + ret = WriteAudioFrame(); + } + while(ret >= 0); + if (ret < 0) + return ret; // write the trailer, if any. av_write_trailer(g_pContainer); @@ -501,17 +532,18 @@ avcodec_close(g_pVideo); av_free(g_pVideo); av_free(g_pVStream); - av_free(g_pVFrame); + av_frame_free(&g_pVFrame); } if (g_pAStream) { avcodec_close(g_pAudio); av_free(g_pAudio); av_free(g_pAStream); - av_free(g_pAFrame); + av_frame_free(&g_pAFrame); av_free(g_pSamples); fclose(g_pSoundFile); } av_free(g_pContainer); + return 0; } diff -r 31570b766315 -r ed5a6478e710 hedgewars/config.inc.in --- a/hedgewars/config.inc.in Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/config.inc.in Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) (* @@ -26,3 +26,4 @@ cRevisionString = '${HEDGEWARS_REVISION}'; cHashString = '${HEDGEWARS_HASH}'; cDefaultPathPrefix = '${HEDGEWARS_FULL_DATADIR}/Data'; + cFontsPaths: ${FONTS_DIRS_ARRAY} diff -r 31570b766315 -r ed5a6478e710 hedgewars/hwLibrary.pas --- a/hedgewars/hwLibrary.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/hwLibrary.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} @@ -106,12 +106,12 @@ procedure JNI_HW_GenLandPreview(env: PJNIEnv; c: JClass; port: JInt); cdecl; begin - GenLandPreview(port); + GenLandPreview(port); end; exports - JNI_HW_versionInfoNet name Java_Prefix+'HWversionInfoNetProto', - JNI_HW_versionInfoVersion name Java_Prefix+'HWversionInfoVersion', + JNI_HW_versionInfoNet name Java_Prefix+'HWversionInfoNetProto', + JNI_HW_versionInfoVersion name Java_Prefix+'HWversionInfoVersion', JNI_HW_GenLandPreview name Java_Prefix + 'HWGenLandPreview', HW_getNumberOfweapons name Java_Prefix + 'HWgetNumberOfWeapons', HW_getMaxNumberOfHogs name Java_Prefix + 'HWgetMaxNumberOfHogs', @@ -119,8 +119,7 @@ Game; {$ELSE} exports - Game, - GenLandPreview, + RunEngine, LoadLocaleWrapper, HW_versionInfo, HW_versionString, diff -r 31570b766315 -r ed5a6478e710 hedgewars/hwengine.ico Binary file hedgewars/hwengine.ico has changed diff -r 31570b766315 -r ed5a6478e710 hedgewars/hwengine.pas --- a/hedgewars/hwengine.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/hwengine.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,13 +13,13 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} {$IFDEF WIN32} -{$R hwengine.rc} +{$R res/hwengine.rc} {$ENDIF} {$IFDEF HWLIBRARY} @@ -29,21 +29,21 @@ program hwengine; {$ENDIF} -uses SDLh, uMisc, uConsole, uGame, uConsts, uLand, uAmmos, uVisualGears, uGears, uStore, uWorld, uInputHandler +uses {$IFDEF IPHONEOS}cmem, {$ENDIF} SDLh, uMisc, uConsole, uGame, uConsts, uLand, uAmmos, uVisualGears, uGears, uStore, uWorld, uInputHandler , uSound, uScript, uTeams, uStats, uIO, uLocale, uChat, uAI, uAIMisc, uAILandMarks, uLandTexture, uCollisions , SysUtils, uTypes, uVariables, uCommands, uUtils, uCaptions, uDebug, uCommandHandlers, uLandPainted - , uPhysFSLayer, uCursor, uRandom, ArgParsers, uVisualGearsHandlers, uTextures + , uPhysFSLayer, uCursor, uRandom, ArgParsers, uVisualGearsHandlers, uTextures, uRender {$IFDEF USE_VIDEO_RECORDING}, uVideoRec {$ENDIF} {$IFDEF USE_TOUCH_INTERFACE}, uTouch {$ENDIF} {$IFDEF ANDROID}, GLUnit{$ENDIF} ; {$IFDEF HWLIBRARY} +procedure RunEngine(argc: LongInt; argv: PPChar); cdecl; export; + procedure preInitEverything(); procedure initEverything(complete:boolean); procedure freeEverything(complete:boolean); -procedure Game(argc: LongInt; argv: PPChar); cdecl; export; -procedure GenLandPreview(port: Longint); cdecl; export; implementation {$ELSE} @@ -55,6 +55,7 @@ /////////////////////////////////////////////////////////////////////////////// function DoTimer(Lag: LongInt): boolean; var s: shortstring; + t: LongWord; begin DoTimer:= false; inc(RealTicks, Lag); @@ -74,7 +75,9 @@ SetDefaultBinds; if HasBorder then DisableSomeWeapons; - AddClouds; + // wave "clouds" on underwater theme look weird w/ weSea, esp the blended bottom portion + if (WorldEdge <> weSea) or (Theme <> 'Underwater') then + AddClouds; AddFlakes; SetRandomSeed(cSeed, false); AssignHHCoords; @@ -86,13 +89,19 @@ SetSound(false); FinishProgress; PlayMusic; - SetScale(zoom); + InitZoom(zoom); ScriptCall('onGameStart'); + for t:= 0 to Pred(TeamsCount) do + with TeamsArray[t]^ do + MaxTeamHealth:= TeamHealth; + RecountAllTeamsHealth; GameState:= gsGame; end; gsConfirm, gsGame, gsChat: begin - if not cOnlyStats then DrawWorld(Lag); + if not cOnlyStats then + // never place between ProcessKbd and DoGameTick - bugs due to /put cmd and isCursorVisible + DrawWorld(Lag); DoGameTick(Lag); if not cOnlyStats then ProcessVisualGears(Lag); end; @@ -114,15 +123,23 @@ if flagMakeCapture then begin flagMakeCapture:= false; - s:= '/Screenshots/hw_' + FormatDateTime('YYYY-MM-DD_HH-mm-ss', Now()) + inttostr(GameTicks); + if flagDumpLand then + s:= '/Screenshots/mapdump_' + else s:= '/Screenshots/hw_'; + {$IFDEF PAS2C} + s:= s + inttostr(GameTicks); + {$ELSE} + s:= s + FormatDateTime('YYYY-MM-DD_HH-mm-ss', Now()) + inttostr(GameTicks); + {$ENDIF} // flash playSound(sndShutter); ScreenFade:= sfFromWhite; ScreenFadeValue:= sfMax; ScreenFadeSpeed:= 5; - - if MakeScreenshot(s, 1) then + + if (not flagDumpLand and MakeScreenshot(s, 1, 0)) or + (flagDumpLand and MakeScreenshot(s, 1, 1) and ((cReducedQuality and rqBlurryLand <> 0) or MakeScreenshot(s, 1, 2))) then WriteLnToConsole('Screenshot saved: ' + s) else begin @@ -135,7 +152,7 @@ /////////////////////////////////////////////////////////////////////////////// procedure MainLoop; var event: TSDL_Event; - PrevTime, CurrTime: Longword; + PrevTime, CurrTime: LongWord; isTerminated: boolean; previousGameState: TGameState; begin @@ -149,10 +166,13 @@ begin case event.type_ of SDL_KEYDOWN: - if (GameState = gsChat) then - KeyPressChat(event.key.keysym.sym) - else if (GameState >= gsGame) then - ProcessKey(event.key); + if GameState = gsChat then + begin + // sdl on iphone supports only ashii keyboards and the unicode field is deprecated in sdl 1.3 + KeyPressChat(SDL_GetKeyFromScancode(event.key.keysym.sym), event.key.keysym.sym, event.key.keysym.modifier); + end + else + if GameState >= gsGame then ProcessKey(event.key); SDL_KEYUP: if (GameState <> gsChat) and (GameState >= gsGame) then ProcessKey(event.key); @@ -236,17 +256,19 @@ ScriptOnScreenResize(); InitCameraBorders(); InitTouchInterface(); + InitZoom(zoomValue); SendIPC('W' + IntToStr(cScreenWidth) + 'x' + IntToStr(cScreenHeight)); end; CurrTime:= SDL_GetTicks(); if PrevTime + longword(cTimerInterval) <= CurrTime then begin - isTerminated := isTerminated or DoTimer(CurrTime - PrevTime); - PrevTime:= CurrTime + isTerminated:= isTerminated or DoTimer(CurrTime - PrevTime); + PrevTime:= CurrTime; end else SDL_Delay(1); IPCCheckSock(); + end; end; @@ -284,20 +306,16 @@ {$ENDIF} /////////////////////////////////////////////////////////////////////////////// -procedure Game{$IFDEF HWLIBRARY}(argc: LongInt; argv: PPChar); cdecl; export{$ENDIF}; +procedure Game; //var p: TPathType; var s: shortstring; i: LongInt; begin -{$IFDEF HWLIBRARY} - preInitEverything(); - parseCommandLine(argc, argv); -{$ENDIF} initEverything(true); WriteLnToConsole('Hedgewars engine ' + cVersionString + '-r' + cRevisionString + ' (' + cHashString + ') with protocol #' + inttostr(cNetProtoVersion)); - AddFileLog('Prefix: "' + PathPrefix +'"'); - AddFileLog('UserPrefix: "' + UserPathPrefix +'"'); + AddFileLog('Prefix: "' + shortstring(PathPrefix) +'"'); + AddFileLog('UserPrefix: "' + shortstring(UserPathPrefix) +'"'); for i:= 0 to ParamCount do AddFileLog(inttostr(i) + ': ' + ParamStr(i)); @@ -309,9 +327,12 @@ //SDL_StartTextInput(); SDL_ShowCursor(0); - WriteToConsole('Init SDL_ttf... '); - SDLTry(TTF_Init() <> -1, 'TTF_Init', true); - WriteLnToConsole(msgOK); + if not cOnlyStats then + begin + WriteToConsole('Init SDL_ttf... '); + SDLTry(TTF_Init() <> -1, 'TTF_Init', true); + WriteLnToConsole(msgOK); + end; {$IFDEF USE_VIDEO_RECORDING} if GameType = gmtRecord then @@ -344,13 +365,20 @@ WriteLnToConsole(msgGettingConfig); - if recordFileName = '' then + if cTestLua then begin - InitIPC; - SendIPCAndWaitReply(_S'C'); // ask for game config + ParseCommand('script ' + cScriptName, true); end else - LoadRecordFromFile(recordFileName); + begin + if recordFileName = '' then + begin + InitIPC; + SendIPCAndWaitReply(_S'C'); // ask for game config + end + else + LoadRecordFromFile(recordFileName); + end; ScriptOnGameInit; s:= 'eproto ' + inttostr(cNetProtoVersion); @@ -370,11 +398,14 @@ {$IFDEF USE_VIDEO_RECORDING} if GameType = gmtRecord then - RecorderMainLoop() - else + begin + RecorderMainLoop(); + freeEverything(true); + exit; + end; {$ENDIF} - MainLoop(); + MainLoop; // clean up all the memory allocated freeEverything(true); end; @@ -401,10 +432,11 @@ uLand.initModule; // computes land uLandPainted.initModule; // computes drawn land uIO.initModule; // sets up sockets + uPhysFSLayer.initModule; + uScript.initModule; if complete then begin - uPhysFSLayer.initModule; uTextures.initModule; {$IFDEF ANDROID}GLUnit.initModule;{$ENDIF} {$IFDEF USE_TOUCH_INTERFACE}uTouch.initModule;{$ENDIF} @@ -421,10 +453,10 @@ uInputHandler.initModule; uMisc.initModule; uLandTexture.initModule; //stub - uScript.initModule; uSound.initModule; uStats.initModule; uStore.initModule; + uRender.initModule; uTeams.initModule; uVisualGears.initModule; uVisualGearsHandlers.initModule; @@ -435,7 +467,7 @@ procedure freeEverything (complete:boolean); begin if complete then - begin + begin WriteLnToConsole('Freeing resources...'); uAI.freeModule; // AI things need to be freed first uAIMisc.freeModule; //stub @@ -447,20 +479,19 @@ uInputHandler.freeModule; uStats.freeModule; //stub uSound.freeModule; - uScript.freeModule; uMisc.freeModule; uLandTexture.freeModule; uGears.freeModule; uCollisions.freeModule; //stub uChat.freeModule; uAmmos.freeModule; + uRender.freeModule; uStore.freeModule; // closes SDL {$IFDEF USE_VIDEO_RECORDING}uVideoRec.freeModule;{$ENDIF} {$IFDEF USE_TOUCH_INTERFACE}uTouch.freeModule;{$ENDIF} //stub {$IFDEF ANDROID}GLUnit.freeModule;{$ENDIF} uTextures.freeModule; - uPhysFSLayer.freeModule; - end; + end; uIO.freeModule; uLand.freeModule; @@ -470,23 +501,30 @@ uCommands.freeModule; uVariables.freeModule; uUtils.freeModule; // closes debug file + uPhysFSLayer.freeModule; + uScript.freeModule; end; /////////////////////////////////////////////////////////////////////////////// -procedure GenLandPreview{$IFDEF HWLIBRARY}(port: LongInt); cdecl; export{$ENDIF}; +procedure GenLandPreview; +{$IFDEF MOBILE} var Preview: TPreview; +{$ELSE} +var Preview: TPreviewAlpha; +{$ENDIF} begin initEverything(false); -{$IFDEF HWLIBRARY} - WriteLnToConsole('Preview connecting on port ' + inttostr(port)); - ipcPort:= port; - InitStepsFlags:= cifRandomize; -{$ENDIF} + InitIPC; IPCWaitPongEvent; TryDo(InitStepsFlags = cifRandomize, 'Some parameters not set (flags = ' + inttostr(InitStepsFlags) + ')', true); + ScriptOnPreviewInit; +{$IFDEF MOBILE} GenPreview(Preview); +{$ELSE} + GenPreviewAlpha(Preview); +{$ENDIF} WriteLnToConsole('Sending preview...'); SendIPCRaw(@Preview, sizeof(Preview)); SendIPCRaw(@MaxHedgehogs, sizeof(byte)); @@ -494,14 +532,24 @@ freeEverything(false); end; -{$IFNDEF HWLIBRARY} +{$IFDEF HWLIBRARY} +procedure RunEngine(argc: LongInt; argv: PPChar); cdecl; export; +begin + operatingsystem_parameter_argc:= argc; + operatingsystem_parameter_argv:= argv; +{$ELSE} +begin +{$ENDIF} /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////// m a i n /////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// -begin +{$IFDEF PAS2C} + // workaround for pascal's ParamStr and ParamCount + init(argc, argv); +{$ENDIF} preInitEverything(); - cTagsMask:= htTeamName or htName or htHealth; // this one doesn't fit nicely w/ reset of other variables. suggestions welcome + GetParams(); if GameType = gmtLandPreview then @@ -510,6 +558,34 @@ Game(); // return 1 when engine is not called correctly - halt(LongInt(GameType = gmtSyntax)); + if GameType = gmtSyntax then + {$IFDEF PAS2C} + exit(HaltUsageError); + {$ELSE} + halt(HaltUsageError); + {$ENDIF} + + if cTestLua then + begin + WriteLnToConsole(errmsgLuaTestTerm); + {$IFDEF PAS2C} + exit(HaltTestUnexpected); + {$ELSE} + halt(HaltTestUnexpected); + {$ENDIF} + end; + + {$IFDEF PAS2C} + exit(HaltNoError); + {$ELSE} + {$IFDEF IPHONEOS} + exit; + {$ELSE} + halt(HaltNoError); + {$ENDIF} + {$ENDIF} +{$IFDEF HWLIBRARY} +end; {$ENDIF} + end. diff -r 31570b766315 -r ed5a6478e710 hedgewars/hwengine.rc --- a/hedgewars/hwengine.rc Tue Nov 10 18:16:35 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -MAINICON ICON "hwengine.ico" \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 hedgewars/options.inc --- a/hedgewars/options.inc Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/options.inc Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$IFNDEF FPC} @@ -60,12 +60,9 @@ {$ENDIF} {$ENDIF} - -//TODO: cruft to be removed {$DEFINE _S:=} {$DEFINE _P:=} - //{$DEFINE TRACEAIACTIONS} //{$DEFINE COUNTTICKS} diff -r 31570b766315 -r ed5a6478e710 hedgewars/pas2cRedo.pas --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hedgewars/pas2cRedo.pas Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,116 @@ +redo; +{This file contains functions that are re-implemented} +{pas2c will add prefix fpcrtl_ to all these functions} +type + uinteger = uinteger; + Integer = integer; + LongInt = integer; + LongWord = uinteger; + Cardinal = uinteger; + PtrInt = integer; + Word = uinteger; + Byte = integer; + SmallInt = integer; + ShortInt = integer; + Int64 = integer; + QWord = uinteger; + GLint = integer; + GLuint = integer; + int = integer; + size_t = integer; + + pointer = pointer; + + float = float; + single = float; + double = float; + real = float; + extended = float; + GLfloat = float; + + boolean = boolean; + LongBool = boolean; + + string = string; + shortstring = string; + ansistring = string; + widechar = string; + + char = char; + PChar = ^char; + PPChar = ^Pchar; + + PByte = ^Byte; + PLongInt = ^LongInt; + PLongWord = ^LongWord; + PInteger = ^Integer; + + Handle = integer; + +var + write, writeLn, read, readLn, flush, CreateDir: procedure; + + halt:procedure; + + GetEnumName:function:shortstring; + TypeInfo:function:Integer; + + lo:function:Integer; + + init:procedure; + + StrLen:function : integer; + odd, even : function : boolean; + + Length : function : integer; + + Now : function : integer; + + new, dispose, FillChar, Insert, Delete, Move : procedure; + + trunc, round, ceil : function : integer; + abs, sqr : function : integer; + + StrPas, FormatDateTime, copy, str, PosS, trim, LowerCase : function : shortstring; + pos : function : integer; + StrToInt : function : integer; + SetLength, SetLengthA, val, StrDispose, StrCopy : procedure; + _pchar, _pcharA, StrAlloc : function : PChar; + pchar2str, astr2str : function : string; + pchar2astr, str2astr : function : ansistring; + memcpy : procedure; + StrLength : function : integer; + + min, max:function:integer; + assign, rewrite, rewrite_2, reset, reset_2, flush, BlockWrite, BlockRead, close : procedure; + FileExists, DirectoryExists, eof : function : boolean; + ExtractFileDir : function : string; + ExtractFileName : function : string; + + ParamCount : function : integer; + ParamStr : function : string; + + arctan2, power: function : float; + + //TypeInfo, GetEnumName : function : shortstring; + + UTF8ToUnicode, WrapText: function : shortstring; + + GetMem : function : pointer; + FreeMem : procedure; + + BeginThread, ThreadSwitch : procedure; + InterlockedIncrement, InterlockedDecrement : procedure; + + random : function : integer; + randomize : procedure; + + Assigned : function : boolean; + + //EnumToStr : function : string; + + initParams : procedure; + + Load_GL_VERSION_2_0 : procedure; + + diff -r 31570b766315 -r ed5a6478e710 hedgewars/pas2cSystem.pas --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hedgewars/pas2cSystem.pas Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,139 @@ +system; +{This file contains functions that are external} +type + uinteger = uinteger; + Integer = integer; + LongInt = integer; + LongWord = uinteger; + Cardinal = uinteger; + PtrInt = integer; + Word = uinteger; + Byte = integer; + SmallInt = integer; + ShortInt = integer; + Int64 = integer; + QWord = uinteger; + GLint = integer; + GLuint = integer; + GLenum = integer; + + int = integer; + size_t = integer; + + pointer = pointer; + + float = float; + single = float; + double = float; + real = float; + extended = float; + GLfloat = float; + + boolean = boolean; + LongBool = boolean; + + string = string; + shortstring = string; + ansistring = string; + widechar = string; + + char = char; + PChar = ^char; + PPChar = ^Pchar; + PWideChar = ^WideChar; + + PByte = ^Byte; + PWord = ^Word; + PLongInt = ^LongInt; + PLongWord = ^LongWord; + PInteger = ^Integer; + + Handle = integer; + + png_structp = pointer; + png_size_t = integer; + +var + false, true: boolean; + + ord, Succ, Pred : function : integer; + inc, dec, Low, High, Lo, Hi : function : integer; + + IOResult : integer; + exit, break, halt, continue : procedure; + + TextFile, File : Handle; + FileMode : integer; + exitcode : integer; + stdout, stderr : Handle; + + sqrt, cos, sin: function : float; + pi : float; + + sizeof : function : integer; + + glGetString : function : pchar; + + glBegin, glBindTexture, glBlendFunc, glClear, glClearColor, + glColor4ub, glColorMask, glColorPointer, glDeleteTextures, + glDisable, glDisableClientState, glDrawArrays, glEnable, + glEnableClientState, glEnd, glGenTextures, glGetIntegerv, + glHint, glLineWidth, glLoadIdentity, glMatrixMode, glPopMatrix, + glPushMatrix, glReadPixels, glRotatef, glScalef, glTexCoord2f, + glTexCoordPointer, glTexImage2D, glTexParameterf, + glTexParameteri, glTranslatef, glVertex2d, glVertexPointer, + glViewport, glext_LoadExtension, glDeleteRenderbuffersEXT, + glDeleteFramebuffersEXT, glGenFramebuffersEXT, + glGenRenderbuffersEXT, glBindFramebufferEXT, + glBindRenderbufferEXT, glRenderbufferStorageEXT, + glFramebufferRenderbufferEXT, glFramebufferTexture2DEXT, + glUniformMatrix4fv, glVertexAttribPointer, glCreateShader, + glShaderSource, glCompileShader, glGetShaderiv, glGetShaderInfoLog, + glCreateProgram, glAttachShader, glBindAttribLocation, glLinkProgram, + glDeleteShader, glGetProgramiv, glGetProgramInfoLog, glUseProgram, + glUniform1i, glGetUniformLocation, glEnableVertexAttribArray, + glGetError, glDeleteProgram, glDeleteBuffers, + glGenBuffers, glBufferData, glBindBuffer, glewInit, + glUniform4f, glDisableVertexAttribArray, glTexEnvi, + glLoadMatrixf, glMultMatrixf, glGetFloatv: procedure; + + GL_BGRA, GL_BLEND, GL_CLAMP_TO_EDGE, GL_COLOR_ARRAY, + GL_COLOR_BUFFER_BIT, GL_DEPTH_BUFFER_BIT, GL_DEPTH_COMPONENT, + GL_DITHER, GL_EXTENSIONS, GL_FALSE, GL_FASTEST, GL_LINEAR, + GL_LINE_LOOP, GL_LINES, GL_LINE_SMOOTH, GL_LINE_STRIP, + GL_MAX_TEXTURE_SIZE, GL_MODELVIEW, GL_ONE_MINUS_SRC_ALPHA, + GL_PERSPECTIVE_CORRECTION_HINT, GL_PROJECTION, GL_QUADS, + GL_RENDERER, GL_RGB, GL_RGB8, GL_RGBA, GL_RGBA8, GL_SRC_ALPHA, GL_TEXTURE_2D, + GL_TEXTURE_COORD_ARRAY, GL_TEXTURE_MAG_FILTER, + GL_TEXTURE_MIN_FILTER, GL_TEXTURE_PRIORITY, GL_TEXTURE_WRAP_S, + GL_TEXTURE_WRAP_T, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_TRUE, GL_VENDOR, + GL_VERSION, GL_VERTEX_ARRAY, GLenum, GL_FRAMEBUFFER_EXT, + GL_RENDERBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, + GL_COLOR_ATTACHMENT0_EXT, GL_FLOAT, GL_UNSIGNED_BYTE, GL_COMPILE_STATUS, + GL_INFO_LOG_LENGTH, GL_LINK_STATUS, GL_VERTEX_SHADER, GL_FRAGMENT_SHADER, + GL_NO_ERROR, GL_ARRAY_BUFFER, GL_STATIC_DRAW, GLEW_OK, + GL_AUX_BUFFERS, GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE, GL_ADD, + GL_MODELVIEW_MATRIX: integer; + + TThreadId : function : integer; + + _strconcat, _strappend, _strprepend, _chrconcat : function : string; + _strcompare, _strncompare, _strcomparec, _strncompareA : function : boolean; + _strconcatA, _strappendA : function : ansistring; + + png_structp, png_set_write_fn, png_get_io_ptr, + png_get_libpng_ver, png_create_write_struct, + png_create_info_struct, png_destroy_write_struct, + png_write_row, png_set_ihdr, png_write_info, + png_write_end : procedure; + + clear_filelist_hook, add_file_hook, idb_loader_hook, mainloop_hook, drawworld_hook : procedure; + SDL_InitPatch : procedure; + + PHYSFS_init, PHYSFS_deinit, PHYSFS_mount, PHYSFS_readBytes, PHYSFS_read : function : LongInt; + PHYSFSRWOPS_openRead, PHYSFSRWOPS_openWrite, PHYSFS_openRead : function : pointer; + PHYSFS_eof, PHYSFS_close, PHYSFS_exists : function : boolean; + PHYSFS_getLastError : function : PChar; + + hedgewarsMountPackages, physfsReaderSetBuffer, hedgewarsMountPackage : procedure; + physfsReader : function : pointer; diff -r 31570b766315 -r ed5a6478e710 hedgewars/res/hwengine.ico Binary file hedgewars/res/hwengine.ico has changed diff -r 31570b766315 -r ed5a6478e710 hedgewars/res/hwengine.rc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hedgewars/res/hwengine.rc Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,2 @@ +MAINICON ICON "res/hwengine.ico" + diff -r 31570b766315 -r ed5a6478e710 hedgewars/sdlmain/SDLMain.m --- a/hedgewars/sdlmain/SDLMain.m Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/sdlmain/SDLMain.m Tue Nov 10 20:43:13 2015 +0100 @@ -18,21 +18,21 @@ @end /* Use this flag to determine whether we use SDLMain.nib or not */ -#define SDL_USE_NIB_FILE 0 +#define SDL_USE_NIB_FILE 0 /* Use this flag to determine whether we use CPS (docking) or not */ -#define SDL_USE_CPS 1 +#define SDL_USE_CPS 1 #ifdef SDL_USE_CPS /* Portions of CPS.h */ typedef struct CPSProcessSerNum { - UInt32 lo; - UInt32 hi; + UInt32 lo; + UInt32 hi; } CPSProcessSerNum; -extern OSErr CPSGetCurrentProcess( CPSProcessSerNum *psn); -extern OSErr CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5); -extern OSErr CPSSetFrontProcess( CPSProcessSerNum *psn); +extern OSErr CPSGetCurrentProcess( CPSProcessSerNum *psn); +extern OSErr CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5); +extern OSErr CPSSetFrontProcess( CPSProcessSerNum *psn); #endif /* SDL_USE_CPS */ @@ -198,8 +198,8 @@ /* Replacement for NSApplicationMain */ static void CustomApplicationMain (int argc, char **argv) { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - SDLMain *sdlMain; + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + SDLMain *sdlMain; /* Ensure the application object is initialised */ [SDLApplication sharedApplication]; diff -r 31570b766315 -r ed5a6478e710 hedgewars/uAI.pas --- a/hedgewars/uAI.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uAI.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} @@ -108,9 +108,11 @@ ap: TAttackParams; Score, i, t, n, dAngle: LongInt; a, aa: TAmmoType; + useThisActions: boolean; begin BotLevel:= Me^.Hedgehog^.BotLevel; windSpeed:= hwFloat2Float(cWindSpeed); +useThisActions:= false; for i:= 0 to Pred(Targets.Count) do if (Targets.ar[i].Score >= 0) and (not StopThinking) then @@ -128,12 +130,39 @@ {$HINTS OFF} Score:= AmmoTests[a].proc(Me, Targets.ar[i], BotLevel, ap); {$HINTS ON} - if Actions.Score + Score > BestActions.Score then + if (Score > BadTurn) and (Actions.Score + Score > BestActions.Score) then if (BestActions.Score < 0) or (Actions.Score + Score > BestActions.Score + Byte(BotLevel - 1) * 2048) then begin - BestActions:= Actions; - inc(BestActions.Score, Score); - BestActions.isWalkingToABetterPlace:= false; + if useThisActions then + begin + BestActions.Count:= Actions.Count + end + else + begin + BestActions:= Actions; + BestActions.isWalkingToABetterPlace:= false; + useThisActions:= true + end; + + BestActions.Score:= Actions.Score + Score; + + // if not between shots, activate invulnerability/vampirism if available + if CurrentHedgehog^.MultiShootAttacks = 0 then + begin + if HHHasAmmo(Me^.Hedgehog^, amInvulnerable) > 0 then + begin + AddAction(BestActions, aia_Weapon, Longword(amInvulnerable), 80, 0, 0); + AddAction(BestActions, aia_attack, aim_push, 10, 0, 0); + AddAction(BestActions, aia_attack, aim_release, 10, 0, 0); + end; + + if HHHasAmmo(Me^.Hedgehog^, amExtraDamage) > 0 then + begin + AddAction(BestActions, aia_Weapon, Longword(amExtraDamage), 80, 0, 0); + AddAction(BestActions, aia_attack, aim_push, 10, 0, 0); + AddAction(BestActions, aia_attack, aim_release, 10, 0, 0); + end; + end; AddAction(BestActions, aia_Weapon, Longword(a), 300 + random(400), 0, 0); @@ -251,7 +280,7 @@ AddAction(Actions, aia_Weapon, Longword(amSkip), 100 + random(200), 0, 0); if ((CurrentHedgehog^.MultiShootAttacks = 0) or ((Ammoz[Me^.Hedgehog^.CurAmmoType].Ammo.Propz and ammoprop_NoMoveAfter) = 0)) - and (GameFlags and gfArtillery = 0) then + and (GameFlags and gfArtillery = 0) and (cGravityf <> 0) then begin tmp:= random(2) + 1; Push(0, Actions, Me^, tmp); @@ -359,6 +388,10 @@ if GoInfo.FallPix >= FallPixForBranching then Push(ticks, Actions, Me^, Me^.Message xor 3); // aia_Left xor 3 = aia_Right + + if (StartTicks > GameTicks - 1500) and (not StopThinking) then + SDL_Delay(1000); + end {while}; if BestRate > BaseRate then @@ -370,12 +403,13 @@ function Think(Me: PGear): LongInt; cdecl; export; var BackMe, WalkMe: TGear; switchCount: LongInt; - StartTicks, currHedgehogIndex, itHedgehog, switchesNum, i: Longword; + currHedgehogIndex, itHedgehog, switchesNum, i: Longword; switchImmediatelyAvailable: boolean; Actions: TActions; begin dmgMod:= 0.01 * hwFloat2Float(cDamageModifier) * cDamagePercent; StartTicks:= GameTicks; + currHedgehogIndex:= CurrentTeam^.CurrHedgehog; itHedgehog:= currHedgehogIndex; switchesNum:= 0; @@ -385,7 +419,7 @@ switchCount:= HHHasAmmo(PGear(Me)^.Hedgehog^, amSwitch) else switchCount:= 0; -if ((Me^.State and gstAttacked) = 0) or isInMultiShoot then +if ((Me^.State and gstAttacked) = 0) or isInMultiShoot or bonuses.activity then if Targets.Count > 0 then begin // iterate over current team hedgehogs @@ -397,7 +431,7 @@ Actions.Score:= 0; if switchesNum > 0 then begin - if not switchImmediatelyAvailable then + if (not switchImmediatelyAvailable) then begin // when AI has to use switcher, make it cost smth unless they have a lot of switches if (switchCount < 10) then Actions.Score:= (-27+switchCount*3)*4000; @@ -421,34 +455,40 @@ or (itHedgehog = currHedgehogIndex) or BestActions.isWalkingToABetterPlace; - if (StartTicks > GameTicks - 1500) and (not StopThinking) then - SDL_Delay(1000); + if (StartTicks > GameTicks - 1500) and (not StopThinking) then + SDL_Delay(700); if (BestActions.Score < -1023) and (not BestActions.isWalkingToABetterPlace) then begin BestActions.Count:= 0; - AddAction(BestActions, aia_Skip, 0, 250, 0, 0); + + FillBonuses(false); + + if not bonuses.activity then + AddAction(BestActions, aia_Skip, 0, 250, 0, 0); end; end else SDL_Delay(100) else begin BackMe:= Me^; - i:= 12; + i:= 4; while (not StopThinking) and (BestActions.Count = 0) and (i > 0) do begin + (* // Maybe this would get a bit of movement out of them? Hopefully not *toward* water. Need to check how often he'd choose that strategy if SuddenDeathDmg and ((hwRound(BackMe.Y)+cWaterRise*2) > cWaterLine) then AddBonus(hwRound(BackMe.X), hwRound(BackMe.Y), 250, -40); *) + FillBonuses(true); WalkMe:= BackMe; Actions.Count:= 0; Actions.Pos:= 0; Actions.Score:= 0; Walk(@WalkMe, Actions); - dec(i); + if not bonuses.activity then dec(i); if not StopThinking then SDL_Delay(100) end diff -r 31570b766315 -r ed5a6478e710 hedgewars/uAIActions.pas --- a/hedgewars/uAIActions.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uAIActions.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} @@ -45,7 +45,7 @@ aia_Put = $800A; aia_waitAngle = $800B; aia_waitAmmoXY = $800C; - + aim_push = $8000; aim_release = $8001; ai_specmask = $8000; @@ -55,7 +55,7 @@ X, Y, Param: LongInt; Time: Longword; end; - + TActions = record Count, Pos: Longword; actions: array[0..Pred(MAXACTIONS)] of TAction; @@ -109,7 +109,7 @@ WriteLnToConsole('AI action: '+SpecActionIdToStr[Action.Action]); if (Action.Action = aia_WaitXL) or (Action.Action = aia_WaitXR) then WriteLnToConsole('AI action Wait X = '+IntToStr(Action.Param)+', current X = '+IntToStr(hwRound(Me^.X))) - + else if (Action.Action = aia_AwareExpl) then WriteLnToConsole('Aware X = ' + IntToStr(Action.X) + ', Y = ' + IntToStr(Action.Y)); end @@ -165,10 +165,10 @@ {$ENDIF} if (Action and ai_specmask) <> 0 then case Action of - aia_Weapon: + aia_Weapon: SetWeapon(TAmmoType(Param)); - - aia_WaitXL: + + aia_WaitXL: if hwRound(Me^.X) = Param then begin Action:= aia_LookLeft; @@ -182,12 +182,12 @@ exit end else - begin + begin CheckHang(Me); exit end; - - aia_WaitXR: + + aia_WaitXR: if hwRound(Me^.X) = Param then begin Action:= aia_LookRight; @@ -201,7 +201,7 @@ exit end else - begin + begin CheckHang(Me); exit end; @@ -222,24 +222,24 @@ else ParseCommand('-right', true); aia_AwareExpl: AwareOfExplosion(X, Y, Param); - + aia_HJump: ParseCommand('hjump', true); - + aia_LJump: ParseCommand('ljump', true); - + aia_Skip: ParseCommand('skip', true); - + aia_Put: doPut(X, Y, true); - + aia_waitAngle: if LongInt(Me^.Angle) <> Abs(Param) then exit; aia_waitAmmoXY: - if (CurAmmoGear <> nil) and ((hwRound(CurAmmoGear^.X) <> X) or (hwRound(CurAmmoGear^.Y) <> Y)) then + if (CurAmmoGear <> nil) and ((hwRound(CurAmmoGear^.X) <> X) or (hwRound(CurAmmoGear^.Y) <> Y)) then exit; end else @@ -249,7 +249,7 @@ case Param of aim_push: s:= '+' + s; - + aim_release: s:= '-' + s; end diff -r 31570b766315 -r ed5a6478e710 hedgewars/uAIAmmoTests.pas --- a/hedgewars/uAIAmmoTests.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uAIAmmoTests.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} @@ -122,7 +122,8 @@ (proc: nil; flags: 0), // amLandGun (proc: nil; flags: 0), // amIceGun (proc: nil; flags: 0), // amKnife - (proc: nil; flags: 0) // amGirder + (proc: nil; flags: 0), // amRubber + (proc: nil; flags: 0) // amAirMine ); implementation @@ -211,6 +212,7 @@ rTime:= 350; ap.ExplR:= 0; valueResult:= BadTurn; + timer:= 0; repeat rTime:= rTime + 300 + Level * 50 + random(300); Vx:= - windSpeed * rTime * 0.5 + (Targ.Point.X + AIrndSign(2) - mX) / rTime; @@ -247,13 +249,13 @@ or (y < 0) or (trunc(x) > LAND_WIDTH) or (trunc(y) > LAND_HEIGHT) - or not TestCollExcludingObjects(trunc(x), trunc(y), 5) + or (not TestCollExcludingObjects(trunc(x), trunc(y), 5)) or (timer = 0) end; EX:= trunc(x); EY:= trunc(y); // Try to prevent AI from thinking firing into water will cause a drowning - if (EY < cWaterLine-5) and (Timer > 0) and (Abs(Targ.Point.X - trunc(x)) + Abs(Targ.Point.Y - trunc(y)) > 21) then exit(BadTurn); + if (EY < cWaterLine-5) and (timer > 0) and (Abs(Targ.Point.X - trunc(x)) + Abs(Targ.Point.Y - trunc(y)) > 21) then exit(BadTurn); if Level = 1 then value:= RateExplosion(Me, EX, EY, 101, afTrackFall or afErasesLand) else value:= RateExplosion(Me, EX, EY, 101); @@ -684,7 +686,7 @@ function TestDesertEagle(Me: PGear; Targ: TTarget; Level: LongInt; var ap: TAttackParams): LongInt; var Vx, Vy, x, y, t: real; d: Longword; - {fallDmg, }valueResult: LongInt; + ix, iy, valueResult: LongInt; begin if (Level > 4) or (Targ.Score < 0) or (Targ.Kind <> gtHedgehog) then exit(BadTurn); Level:= Level; // avoid compiler hint @@ -704,20 +706,25 @@ 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.Point.X - trunc(x)) + Abs(Targ.Point.Y - trunc(y)) < 5) - or (x < 0) - or (y < 0) - or (trunc(x) > LAND_WIDTH) - or (trunc(y) > LAND_HEIGHT) - or (d > 48); +ix:= trunc(x); +iy:= trunc(y); -if Abs(Targ.Point.X - trunc(x)) + Abs(Targ.Point.Y - trunc(y)) < 5 then +if ((ix and LAND_WIDTH_MASK) = 0) and ((iy and LAND_HEIGHT_MASK) = 0) then + repeat + if Land[iy, ix] <> 0 then + inc(d); + x:= x + vX; + y:= y + vY; + ix:= trunc(x); + iy:= trunc(y); + until (Abs(Targ.Point.X - ix) + Abs(Targ.Point.Y - iy) < 5) + or (x < 0) + or (y < 0) + or (ix >= LAND_WIDTH) + or (iy >= LAND_HEIGHT) + or (d > 48); + +if Abs(Targ.Point.X - ix) + Abs(Targ.Point.Y - iy) < 5 then begin ap.AttacksNum:= 1 + (d + 8) div 12; valueResult:= RateShove(Me, Targ.Point.X, Targ.Point.Y, 1, 7, 20, vX*0.125, vY*0.125, afTrackFall) - ap.AttacksNum @@ -779,7 +786,7 @@ Targ:= Targ; // avoid compiler hint if Level < 3 then trackFall:= afTrackFall - else trackFall:= 0; + else trackFall:= 0; ap.ExplR:= 0; ap.Time:= 0; @@ -1047,7 +1054,7 @@ begin ap.ExplR:= 0; ap.Time:= 0; -if (Level > 3) then +if (Level > 3) or (cGravityf = 0) then exit(BadTurn); ap.Angle:= 0; @@ -1241,7 +1248,7 @@ x:= x + dx; dy:= dy + cGravityf; y:= y + dy; - + if TestColl(trunc(x), trunc(y), 3) then t:= 0; until t = 0; @@ -1251,7 +1258,7 @@ if Level = 1 then valueResult:= RateExplosion(Me, EX, EY, 76, afTrackFall or afErasesLand) -else +else valueResult:= RateExplosion(Me, EX, EY, 76); if (valueResult > 0) then diff -r 31570b766315 -r ed5a6478e710 hedgewars/uAILandMarks.pas --- a/hedgewars/uAILandMarks.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uAILandMarks.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,7 +1,7 @@ unit uAILandMarks; interface -const +const markWalkedHere = $01; markHJumped = $02; markLJumped = $04; @@ -35,13 +35,13 @@ function checkMark(X, Y: LongInt; mark: byte) : boolean; begin - checkMark:= ((X and LAND_WIDTH_MASK) = 0) - and ((Y and LAND_HEIGHT_MASK) = 0) + checkMark:= ((X and LAND_WIDTH_MASK) = 0) + and ((Y and LAND_HEIGHT_MASK) = 0) and ((marks[Y shr gr, X shr gr] and mark) <> 0) end; procedure clearAllMarks; -var +var Y, X: Longword; begin for Y:= 0 to Pred(HEIGHT) do @@ -50,7 +50,7 @@ end; procedure clearMarks(mark: byte); -var +var Y, X: Longword; begin for Y:= 0 to Pred(HEIGHT) do @@ -62,7 +62,7 @@ begin WIDTH:= LAND_WIDTH shr gr; HEIGHT:= LAND_HEIGHT shr gr; - + SetLength(marks, HEIGHT, WIDTH); end; diff -r 31570b766315 -r ed5a6478e710 hedgewars/uAIMisc.pas --- a/hedgewars/uAIMisc.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uAIMisc.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} @@ -53,7 +53,18 @@ X, Y: LongInt; Radius: LongInt; Score: LongInt; - end; + end; + +TBonuses = record + activity: boolean; + Count : Longword; + ar : array[0..Pred(MAXBONUS)] of TBonus; + end; + +Twalkbonuses = record + Count: Longword; + ar: array[0..Pred(MAXBONUS div 8)] of TBonus; // don't use too many + end; procedure initModule; procedure freeModule; @@ -82,22 +93,16 @@ var ThinkingHH: PGear; Targets: TTargets; - bonuses: record - Count: Longword; - ar: array[0..Pred(MAXBONUS)] of TBonus; - end; + bonuses: TBonuses; - walkbonuses: record - Count: Longword; - ar: array[0..Pred(MAXBONUS div 8)] of TBonus; // don't use too many - end; + walkbonuses: Twalkbonuses; const KillScore = 200; var friendlyfactor: LongInt = 300; var dmgMod: real = 1.0; implementation -uses uCollisions, uVariables, uUtils, uLandTexture, uGearsUtils; +uses uCollisions, uVariables, uUtils, uGearsUtils; var KnownExplosion: record @@ -127,13 +132,13 @@ if (((Gear^.Kind = gtHedgehog) and (Gear <> ThinkingHH) and (Gear^.Health > Gear^.Damage) and - not(Gear^.Hedgehog^.Team^.hasgone)) or + (not Gear^.Hedgehog^.Team^.hasgone)) or ((Gear^.Kind = gtExplosives) and (Gear^.Health > Gear^.Damage)) or ((Gear^.Kind = gtMine) and (Gear^.Health = 0) and (Gear^.Damage < 35)) - ) and + ) and (Targets.Count < 256) then begin with Targets.ar[Targets.Count] do @@ -155,7 +160,7 @@ Score:= Gear^.Damage - Gear^.Health; inc(f) end - else + else begin Score:= Gear^.Health - Gear^.Damage; inc(e) @@ -163,7 +168,7 @@ end else if Gear^.Kind = gtExplosives then Score:= Gear^.Health - Gear^.Damage - else if Gear^.Kind = gtMine then + else if Gear^.Kind = gtMine then Score:= max(0,35-Gear^.Damage); end; inc(Targets.Count) @@ -205,36 +210,70 @@ i: Longint; begin bonuses.Count:= 0; +bonuses.activity:= false; MyClan:= ThinkingHH^.Hedgehog^.Team^.Clan; Gear:= GearsList; while Gear <> nil do begin case Gear^.Kind of + gtGrenade + , gtClusterBomb + , gtGasBomb + , gtShell + , gtAirAttack + , gtMortar + , gtWatermelon + , gtDrill + , gtAirBomb + , gtCluster + , gtMelonPiece + , gtMolotov: bonuses.activity:= true; gtCase: AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y) + 3, 37, 25); gtFlame: if (Gear^.State and gsttmpFlag) <> 0 then AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 20, -50); // avoid mines unless they are very likely to be duds, or are duds. also avoid if they are about to blow - gtMine: + gtMine: begin + if (Gear^.State and gstMoving) <> 0 then bonuses.activity:= true; + if ((Gear^.State and gstAttacking) = 0) and (((cMineDudPercent < 90) and (Gear^.Health <> 0)) or (isAfterAttack and (Gear^.Health = 0) and (Gear^.Damage > 30))) then AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 50, -50) else if (Gear^.State and gstAttacking) <> 0 then AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 100, -50); // mine is on + end; gtExplosives: - if isAfterAttack then - AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 75, -60 + Gear^.Health); + begin + //if (Gear^.State and gstMoving) <> 0 then bonuses.activity:= true; - gtSMine: + if isAfterAttack then + AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 75, -60 + Gear^.Health); + end; + + gtSMine: begin + if (Gear^.State and (gstMoving or gstAttacking)) <> 0 then bonuses.activity:= true; + AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 50, -30); + end; gtDynamite: + begin + bonuses.activity:= true; AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 150, -75); + end; gtHedgehog: begin + if (ThinkingHH <> Gear) + and (((Gear^.State and (gstMoving or gstDrowning or gstHHDeath)) <> 0) + or (Gear^.Health = 0) + or (Gear^.Damage >= Gear^.Health)) + then begin + bonuses.activity:= true; + end; + if Gear^.Damage >= Gear^.Health then AddBonus(hwRound(Gear^.X), hwRound(Gear^.Y), 60, -25) else @@ -249,6 +288,7 @@ end; Gear:= Gear^.NextGear end; + if isAfterAttack and (KnownExplosion.Radius > 0) then with KnownExplosion do AddBonus(X, Y, Radius + 10, -Radius); @@ -384,20 +424,20 @@ dmg := 1 + trunc((dY - 0.4) * 70); exit(dmg) end - else + else begin dxdy:= abs(dX)+abs(dY); - if ((Kind = gtMine) and (dxdy > 0.35)) or - ((Kind = gtExplosives) and + if ((Kind = gtMine) and (dxdy > 0.35)) or + ((Kind = gtExplosives) and (((State and gstTmpFlag <> 0) and (dxdy > 0.35)) or - ((State and gstTmpFlag = 0) and - ((abs(odX) > 0.15) or ((abs(odY) > 0.15) and + ((State and gstTmpFlag = 0) and + ((abs(odX) > 0.15) or ((abs(odY) > 0.15) and (abs(odX) > 0.02))) and (dxdy > 0.35)))) then begin dmg := trunc(dxdy * 25); exit(dmg) end - else if (Kind = gtExplosives) and not((abs(odX) > 0.15) or ((abs(odY) > 0.15) and (abs(odX) > 0.02))) and (dY > 0.2) then + else if (Kind = gtExplosives) and (not(abs(odX) > 0.15) or ((abs(odY) > 0.15) and (abs(odX) > 0.02))) and (dY > 0.2) then begin dmg := trunc(dy * 70); exit(dmg) @@ -405,7 +445,7 @@ end; exit(0) end; - if (y > cWaterLine) or (x > rightX) or (x < leftX) then exit(-1) + if CheckCoordInWater(round(x), round(y)) then exit(-1) end end; @@ -436,20 +476,20 @@ dmg := trunc((dY - 0.4) * 70); exit(dmg); end - else + else begin dxdy:= abs(dX)+abs(dY); - if ((Kind = gtMine) and (dxdy > 0.4)) or - ((Kind = gtExplosives) and + if ((Kind = gtMine) and (dxdy > 0.4)) or + ((Kind = gtExplosives) and (((State and gstTmpFlag <> 0) and (dxdy > 0.4)) or - ((State and gstTmpFlag = 0) and - ((abs(odX) > 0.15) or ((abs(odY) > 0.15) and + ((State and gstTmpFlag = 0) and + ((abs(odX) > 0.15) or ((abs(odY) > 0.15) and (abs(odX) > 0.02))) and (dxdy > 0.35)))) then begin dmg := trunc(dxdy * 50); exit(dmg) end - else if (Kind = gtExplosives) and not((abs(odX) > 0.15) or ((abs(odY) > 0.15) and (abs(odX) > 0.02))) and (dY > 0.2) then + else if (Kind = gtExplosives) and (not(abs(odX) > 0.15) or ((abs(odY) > 0.15) and (abs(odX) > 0.02))) and (dY > 0.2) then begin dmg := trunc(dy * 70); exit(dmg) @@ -457,7 +497,7 @@ end; exit(0) end; - if (y > cWaterLine) or (x > rightX) or (x < leftX) then + if CheckCoordInWater(round(x), round(y)) then // returning -1 for drowning so it can be considered in the Rate routine exit(-1) end; @@ -516,12 +556,13 @@ pX:= Point.x; pY:= Point.y; fallDmg:= 0; + dX:= 0; if (Flags and afTrackFall <> 0) and (Score > 0) and (dmg < Score) then begin dX:= (0.005 * dmg + 0.01) / Density; dY:= dX; - if (Kind = gtExplosives) and (State and gstTmpFlag = 0) and - (((abs(dY) > 0.15) and (abs(dX) < 0.02)) or + if (Kind = gtExplosives) and (State and gstTmpFlag = 0) and + (((abs(dY) >= 0.15) and (abs(dX) < 0.02)) or ((abs(dY) < 0.15) and (abs(dX) < 0.15))) then dX:= 0; @@ -606,8 +647,8 @@ pY:= Point.y-2; fallDmg:= 0; if (Flags and afSetSkip <> 0) then skip:= true; - if not(dead) and (Flags and afTrackFall <> 0) and (Score > 0) and (power < Score) then - if (Kind = gtExplosives) and (State and gstTmpFlag = 0) and + if (not dead) and (Flags and afTrackFall <> 0) and (Score > 0) and (power < Score) then + if (Kind = gtExplosives) and (State and gstTmpFlag = 0) and (((abs(dY) > 0.15) and (abs(dX) < 0.02)) or ((abs(dY) < 0.15) and (abs(dX) < 0.15))) then fallDmg:= trunc(TraceShoveFall(pX, pY, 0, dY, Targets.ar[i]) * dmgMod) @@ -701,17 +742,18 @@ end; if dmg > 0 then begin - if not(dead) and (Score > 0) and (dmg < Score) then + fallDmg:= 0; + pX:= Point.x; + pY:= Point.y; + if (not dead) and (Score > 0) and (dmg < Score) then begin - pX:= Point.x; - pY:= Point.y; dX:= gdX * dmg / Density; dY:= gdY * dmg / Density; if dX < 0 then dX:= dX - 0.01 else dX:= dX + 0.01; - if (Kind = gtExplosives) and (State and gstTmpFlag = 0) and + if (Kind = gtExplosives) and (State and gstTmpFlag = 0) and (((abs(dY) > 0.15) and (abs(dX) < 0.02)) or - ((abs(dY) < 0.15) and (abs(dX) < 0.15))) then + ((abs(dY) < 0.15) and (abs(dX) < 0.15))) then dX:= 0; if (x and LAND_WIDTH_MASK = 0) and ((y+cHHRadius+2) and LAND_HEIGHT_MASK = 0) and (Land[y+cHHRadius+2, x] and lfIndestructible <> 0) then @@ -836,7 +878,7 @@ UpdateLandTexture(hwRound(Gear^.X), 1, hwRound(Gear^.Y), 1, true); end;} - if not (hwRound(Gear^.Y) + cHHRadius < cWaterLine) then + if CheckCoordInWater(hwRound(Gear^.X), hwRound(Gear^.Y) + cHHRadius) then exit(false); if (Gear^.State and gstMoving) <> 0 then begin @@ -901,7 +943,7 @@ pX:= hwRound(Gear^.X); pY:= hwRound(Gear^.Y); - if pY + cHHRadius >= cWaterLine then + if CheckCoordInWater(pX, pY + cHHRadius) then begin if AltGear^.Hedgehog^.BotLevel < 4 then AddWalkBonus(pX, tY, 250, -40); diff -r 31570b766315 -r ed5a6478e710 hedgewars/uAmmos.pas --- a/hedgewars/uAmmos.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uAmmos.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} @@ -43,14 +43,14 @@ procedure SetWeapon(weap: TAmmoType); procedure DisableSomeWeapons; procedure ResetWeapons; -function GetAmmoByNum(num: Longword): PHHAmmo; +function GetAmmoByNum(num: LongInt): PHHAmmo; function GetCurAmmoEntry(var Hedgehog: THedgehog): PAmmo; function GetAmmoEntry(var Hedgehog: THedgehog; am: TAmmoType): PAmmo; -var StoreCnt: Longword; +var StoreCnt: LongInt; implementation -uses uLocale, uVariables, uCommands, uUtils, uCaptions, uDebug; +uses uVariables, uCommands, uUtils, uCaptions, uDebug; type TAmmoCounts = array[TAmmoType] of Longword; TAmmoArray = array[TAmmoType] of TAmmo; @@ -132,26 +132,26 @@ inc(Ammoz[a].SkipTurns,10000); if ((GameFlags and gfPlaceHog) <> 0) and (a = amTeleport) then ammos[a]:= AMMO_INFINITE - end - + end + else ammos[a]:= AMMO_INFINITE; - if ((GameFlags and gfPlaceHog) <> 0) and (a = amTeleport) then + if ((GameFlags and gfPlaceHog) <> 0) and (a = amTeleport) then InitialCounts[Pred(StoreCnt)][a]:= cnt else InitialCounts[Pred(StoreCnt)][a]:= ammos[a]; end; - + for a:= Low(TAmmoType) to High(TAmmoType) do begin newAmmos[a]:= Ammoz[a].Ammo; newAmmos[a].Count:= ammos[a] end; - + FillAmmoStore(StoresList[Pred(StoreCnt)], newAmmos) end; -function GetAmmoByNum(num: Longword): PHHAmmo; +function GetAmmoByNum(num: LongInt): PHHAmmo; begin TryDo(num < StoreCnt, 'Invalid store number', true); GetAmmoByNum:= StoresList[num] @@ -272,7 +272,7 @@ Ammo^[Slot, ami]:= Ammo^[Slot, ami + 1]; Ammo^[Slot, ami + 1].Count:= 0 end; - until not b; + until (not b); AmmoMenuInvalidated:= true; end; @@ -311,7 +311,7 @@ if (AmmoType = Ammo) then if Hedgehog.Team^.Clan^.TurnNumber > Ammoz[AmmoType].SkipTurns then exit(Count) - else + else exit(0); inc(ami) end; @@ -366,12 +366,11 @@ end; TryDo(slot <= cMaxSlotIndex, 'Ammo slot index overflow', true); CurAmmoType:= Ammo^[slot, ammoidx].AmmoType; - if CurAmmoType = amKnife then LoadHedgehogHat(Hedgehog, 'Reserved/chef') end end; procedure ApplyAmmoChanges(var Hedgehog: THedgehog); -var s: shortstring; +var s: ansistring; CurWeapon: PAmmo; begin TargetPoint.X:= NoPointX; @@ -395,18 +394,18 @@ begin s:= trammo[Ammoz[AmmoType].NameId]; if (Count <> AMMO_INFINITE) and (not (Hedgehog.Team^.ExtDriven or (Hedgehog.BotLevel > 0))) then - s:= s + ' (' + IntToStr(Count) + ')'; + s:= s + ansistring(' (' + IntToStr(Count) + ')'); if (Propz and ammoprop_Timerable) <> 0 then - s:= s + ', ' + IntToStr(Timer div 1000) + ' ' + trammo[sidSeconds]; + s:= s + ansistring(', ' + IntToStr(Timer div 1000) + ' ') + trammo[sidSeconds]; AddCaption(s, Team^.Clan^.Color, capgrpAmmoinfo); if (Propz and ammoprop_NeedTarget) <> 0 then begin - if Gear <> nil then Gear^.State:= Gear^.State or gstHHChooseTarget; + if Gear <> nil then Gear^.State:= Gear^.State or gstChooseTarget; isCursorVisible:= true end else begin - if Gear <> nil then Gear^.State:= Gear^.State and (not gstHHChooseTarget); + if Gear <> nil then Gear^.State:= Gear^.State and (not gstChooseTarget); isCursorVisible:= false end; end @@ -482,7 +481,7 @@ for a:= Low(TAmmoType) to High(TAmmoType) do newAmmos[a]:= Ammoz[a].Ammo; - + for i:= 0 to Pred(StoreCnt) do begin for a:= Low(TAmmoType) to High(TAmmoType) do @@ -499,8 +498,8 @@ procedure chAddAmmoStore(var descr: shortstring); begin -descr:= ''; // avoid compiler hint -AddAmmoStore + descr:= ''; // avoid compiler hint + AddAmmoStore end; procedure initModule; diff -r 31570b766315 -r ed5a6478e710 hedgewars/uCaptions.pas --- a/hedgewars/uCaptions.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uCaptions.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,9 +13,9 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) - + {$INCLUDE "options.inc"} unit uCaptions; @@ -23,7 +23,7 @@ interface uses uTypes; -procedure AddCaption(s: shortstring; Color: Longword; Group: TCapGroup); +procedure AddCaption(s: ansistring; Color: Longword; Group: TCapGroup); procedure DrawCaptions; procedure ReloadCaptions(unload: boolean); @@ -36,21 +36,20 @@ type TCaptionStr = record Tex: PTexture; EndTime: LongWord; - Text: shortstring; + Text: ansistring; Color: Longword end; var Captions: array[TCapGroup] of TCaptionStr; -procedure AddCaption(s: shortstring; Color: Longword; Group: TCapGroup); +procedure AddCaption(s: ansistring; Color: Longword; Group: TCapGroup); begin if cOnlyStats then exit; + if Length(s) = 0 then + exit; if Captions[Group].Text <> s then - begin - FreeTexture(Captions[Group].Tex); - Captions[Group].Tex:= nil - end; - + FreeAndNilTexture(Captions[Group].Tex); + if Captions[Group].Tex = nil then begin Captions[Group].Color:= Color; @@ -71,8 +70,8 @@ begin for Group:= Low(TCapGroup) to High(TCapGroup) do if unload then - FreeTexture(Captions[Group].Tex) - else if Captions[Group].Text <> '' then + FreeAndNilTexture(Captions[Group].Tex) + else if length(Captions[Group].Text) > 0 then Captions[Group].Tex:= RenderStringTex(Captions[Group].Text, Captions[Group].Color, fntBig) end; @@ -95,9 +94,8 @@ inc(offset, Tex^.h + 2); if EndTime <= RealTicks then begin - FreeTexture(Tex); - Tex:= nil; - Text:= ''; + FreeAndNilTexture(Tex); + Text:= ansistring(''); EndTime:= 0 end; end; @@ -112,10 +110,7 @@ var group: TCapGroup; begin for group:= Low(TCapGroup) to High(TCapGroup) do - begin - FreeTexture(Captions[group].Tex); - Captions[group].Tex:= nil - end + FreeAndNilTexture(Captions[group].Tex); end; end. diff -r 31570b766315 -r ed5a6478e710 hedgewars/uChat.pas --- a/hedgewars/uChat.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uChat.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} @@ -29,23 +29,26 @@ procedure CleanupInput; procedure AddChatString(s: shortstring); procedure DrawChat; +procedure KeyPressChat(Key, Sym: Longword; Modifier: Word); procedure SendHogSpeech(s: shortstring); +procedure CopyToClipboard(var newContent: shortstring); -procedure KeyPressChat(Sym: Longword); procedure TextInput(var event: TSDL_TextInputEvent); implementation -uses uInputHandler, uTypes, uVariables, uCommands, uUtils, uTextures, uRender, uIO; +uses uInputHandler, uTypes, uVariables, uCommands, uUtils, uTextures, uRender, uIO, uScript, uRenderUtils; const MaxStrIndex = 27; + MaxInputStrLen = 200; type TChatLine = record Tex: PTexture; Time: Longword; Width: LongInt; s: shortstring; + Color: TSDL_Color; end; - TChatCmd = (quit, pause, finish, showhistory, fullscreen); + TChatCmd = (ccQuit, ccPause, ccFinish, ccShowHistory, ccFullScreen); var Strs: array[0 .. MaxStrIndex] of TChatLine; MStrs: array[0 .. MaxStrIndex] of shortstring; @@ -56,19 +59,29 @@ history: LongInt; visibleCount: LongWord; InputStr: TChatLine; - InputStrL: array[0..260] of char; // for full str + 4-byte utf-8 char ChatReady: boolean; showAll: boolean; + liveLua: boolean; + ChatHidden: boolean; + firstDraw: boolean; + InputLinePrefix: TChatLine; + // cursor + cursorPos, cursorX, selectedPos, selectionDx: LongInt; + LastKeyPressTick: LongWord; + const - colors: array[#0..#6] of TSDL_Color = ( - (r:$FF; g:$FF; b:$FF; a:$FF), // unused, feel free to take it for anything - (r:$FF; g:$FF; b:$FF; a:$FF), // chat message [White] - (r:$FF; g:$00; b:$FF; a:$FF), // action message [Purple] - (r:$90; g:$FF; b:$90; a:$FF), // join/leave message [Lime] - (r:$FF; g:$FF; b:$A0; a:$FF), // team message [Light Yellow] - (r:$FF; g:$00; b:$00; a:$FF), // error messages [Red] - (r:$00; g:$FF; b:$FF; a:$FF) // input line [Light Blue] + colors: array[#0..#9] of TSDL_Color = ( + (r:$FF; g:$FF; b:$FF; a:$FF), // #0 unused, feel free to take it for anything + (r:$FF; g:$FF; b:$FF; a:$FF), // #1 chat message [White] + (r:$FF; g:$00; b:$FF; a:$FF), // #2 action message [Purple] + (r:$90; g:$FF; b:$90; a:$FF), // #3 join/leave message [Lime] + (r:$FF; g:$FF; b:$A0; a:$FF), // #4 team message [Light Yellow] + (r:$FF; g:$00; b:$00; a:$FF), // #5 error messages [Red] + (r:$00; g:$FF; b:$FF; a:$FF), // #6 input line [Light Blue] + (r:$FF; g:$80; b:$80; a:$FF), // #7 team gone [Light Red] + (r:$FF; g:$D0; b:$80; a:$FF), // #8 team back [Light Orange] + (r:$DF; g:$DF; b:$DF; a:$FF) // #9 hog speech [Light Gray] ); ChatCommandz: array [TChatCmd] of record ChatCmd: string[31]; @@ -81,57 +94,160 @@ (ChatCmd: '/fullscreen'; ProcedureCallChatCmd: 'fullscr') ); -procedure SetLine(var cl: TChatLine; str: shortstring; isInput: boolean); -var strSurface, resSurface: PSDL_Surface; - w, h: LongInt; - color: TSDL_Color; - font: THWFont; + +const Padding = 2; + ClHeight = 2 * Padding + 16; // font height + +// relevant for UTF-8 handling +function IsFirstCharByte(c: char): boolean; inline; +begin + // based on https://en.wikipedia.org/wiki/UTF-8#Description + IsFirstCharByte:= (byte(c) and $C0) <> $80; +end; + +function charIsForHogSpeech(c: char): boolean; +begin +exit((c = '"') or (c = '''') or (c = '-')); +end; + +procedure ResetSelection(); begin -if cl.Tex <> nil then - FreeTexture(cl.Tex); + selectedPos:= -1; +end; + +procedure UpdateCursorCoords(); +var font: THWFont; + str : shortstring; + coff, soff: LongInt; +begin + if cursorPos = selectedPos then + ResetSelection(); -cl.s:= str; + // calculate cursor offset + + str:= InputStr.s; + font:= CheckCJKFont(ansistring(str), fnt16); + + // get only substring before cursor to determine length + // SetLength(str, cursorPos); // makes pas2c unhappy + str[0]:= char(cursorPos); + // get render size of text + TTF_SizeUTF8(Fontz[font].Handle, Str2PChar(str), @coff, nil); + + cursorX:= 2 + coff; -if isInput then - begin - color:= colors[#6]; - str:= UserNick + '> ' + str + '_' - end -else - begin - color:= colors[str[1]]; - delete(str, 1, 1) - end; + // calculate selection width on screen + if selectedPos >= 0 then + begin + if selectedPos > cursorPos then + str:= InputStr.s; + // SetLength(str, selectedPos); // makes pas2c unhappy + str[0]:= char(selectedPos); + TTF_SizeUTF8(Fontz[font].Handle, Str2PChar(str), @soff, nil); + selectionDx:= soff - coff; + end + else + selectionDx:= 0; +end; + + +procedure ResetCursor(); +begin + ResetSelection(); + cursorPos:= 0; + UpdateCursorCoords(); +end; -font:= CheckCJKFont(str, fnt16); -w:= 0; h:= 0; // avoid compiler hints -TTF_SizeUTF8(Fontz[font].Handle, Str2PChar(str), @w, @h); +(* This procedure [re]renders a texture showing str for the chat line cl. + * It will use the color stored in cl and update width + *) +procedure RenderChatLineTex(var cl: TChatLine; var str: shortstring); +var strSurface, + resSurface: PSDL_Surface; + dstrect : TSDL_Rect; // destination rectangle for blitting + font : THWFont; +const + shadowint = $80 shl AShift; +begin + +FreeAndNilTexture(cl.Tex); + +font:= CheckCJKFont(ansistring(str), fnt16); + +// get render size of text +TTF_SizeUTF8(Fontz[font].Handle, Str2PChar(str), @cl.Width, nil); -resSurface:= SDL_CreateRGBSurface(0, toPowerOf2(w), toPowerOf2(h), 32, RMask, GMask, BMask, AMask); +// calculate and save size +cl.Width := cl.Width + 2 * Padding; + +// create surface to draw on +resSurface:= SDL_CreateRGBSurface( + 0, toPowerOf2(cl.Width), toPowerOf2(ClHeight), + 32, RMask, GMask, BMask, AMask); -strSurface:= TTF_RenderUTF8_Solid(Fontz[font].Handle, Str2PChar(str), color); -cl.Width:= w + 4; -SDL_UpperBlit(strSurface, nil, resSurface, nil); +// define area we want to draw in +dstrect.x:= 0; +dstrect.y:= 0; +dstrect.w:= cl.Width; +dstrect.h:= ClHeight; + +// draw background +SDL_FillRect(resSurface, @dstrect, shadowint); + +// create and blit text +strSurface:= TTF_RenderUTF8_Blended(Fontz[font].Handle, Str2PChar(str), cl.color); +//SDL_UpperBlit(strSurface, nil, resSurface, @dstrect); +if strSurface <> nil then copyTOXY(strSurface, resSurface, Padding, Padding); SDL_FreeSurface(strSurface); -cl.Time:= RealTicks + 12500; cl.Tex:= Surface2Tex(resSurface, false); SDL_FreeSurface(resSurface) end; +const ClDisplayDuration = 12500; + +procedure SetLine(var cl: TChatLine; str: shortstring; isInput: boolean); +var color : TSDL_Color; +begin +if isInput then + begin + cl.s:= str; + color:= colors[#6]; + str:= str + ' '; + end +else + begin + if str[1] <= High(colors) then + begin + color:= colors[str[1]]; + delete(str, 1, 1); + end + // fallback if invalid color + else + color:= colors[Low(colors)]; + + cl.s:= str; + end; + +cl.color:= color; + +// set texture, note: variables cl.s and str will be different here if isInput +RenderChatLineTex(cl, str); + +cl.Time:= RealTicks + ClDisplayDuration; +end; + // For uStore texture recreation procedure ReloadLines; -var i, t: LongWord; +var i: LongWord; begin if InputStr.s <> '' then SetLine(InputStr, InputStr.s, true); for i:= 0 to MaxStrIndex do if Strs[i].s <> '' then begin - t:= Strs[i].Time; - SetLine(Strs[i], Strs[i].s, false); - Strs[i].Time:= t + RenderChatLineTex(Strs[i], Strs[i].s); end; end; @@ -154,58 +270,145 @@ inc(visibleCount) end; +procedure CheckPasteBuffer(); forward; + +procedure UpdateInputLinePrefix(); +begin +if liveLua then + begin + InputLinePrefix.color:= colors[#1]; + InputLinePrefix.s:= '[Lua] >'; + end +else + begin + InputLinePrefix.color:= colors[#6]; + InputLinePrefix.s:= UserNick + '>'; + end; + +FreeAndNilTexture(InputLinePrefix.Tex); +end; + procedure DrawChat; -var i, t, cnt: Longword; - r: TSDL_Rect; +var i, t, left, top, cnt: LongInt; + selRect: TSDL_Rect; + c: char; begin ChatReady:= true; // maybe move to somewhere else? -if MissedCount <> 0 then // there are chat strings we missed, so print them now - begin - for i:= 0 to MissedCount - 1 do - AddChatString(MStrs[i]); - MissedCount:= 0; - end; -cnt:= 0; -t:= 0; -i:= lastStr; + +if ChatHidden and (not showAll) then + visibleCount:= 0; -r.x:= 6 - cScreenWidth div 2; -r.y:= (visibleCount - t) * 16 + 10; -r.h:= 16; +// draw chat lines with some distance from screen border +left:= 4 - cScreenWidth div 2; +top := 10 + visibleCount * ClHeight; // we start with input line (if any) +// draw chat input line first and under all other lines if (GameState = gsChat) and (InputStr.Tex <> nil) then begin - r.w:= InputStr.Width; - DrawFillRect(r); - Tint($00, $00, $00, $80); - DrawTexture(9 - cScreenWidth div 2, visibleCount * 16 + 11, InputStr.Tex); - untint; - DrawTexture(8 - cScreenWidth div 2, visibleCount * 16 + 10, InputStr.Tex); - end; + CheckPasteBuffer(); + + if InputLinePrefix.Tex = nil then + RenderChatLineTex(InputLinePrefix, InputLinePrefix.s); + + DrawTexture(left, top, InputLinePrefix.Tex); + inc(left, InputLinePrefix.Width); + DrawTexture(left, top, InputStr.Tex); + + if firstDraw then + begin + UpdateCursorCoords(); + firstDraw:= false; + end; + + if selectedPos < 0 then + begin + // draw cursor + if ((RealTicks - LastKeyPressTick) and 512) < 256 then + DrawLineOnScreen(left + cursorX, top + 2, left + cursorX, top + ClHeight - 2, 2.0, $00, $FF, $FF, $FF); + end + else // draw selection + begin + selRect.y:= top + 2; + selRect.h:= clHeight - 4; + if selectionDx < 0 then + begin + selRect.x:= left + cursorX + selectionDx; + selRect.w:= -selectionDx; + end + else + begin + selRect.x:= left + cursorX; + selRect.w:= selectionDx; + end; -dec(r.y, 16); + DrawRect(selRect, $FF, $FF, $FF, $40, true); + end; + + dec(left, InputLinePrefix.Width); + -while (((t < 7) and (Strs[i].Time > RealTicks)) or ((t < MaxStrIndex) and showAll)) -and (Strs[i].Tex <> nil) do + if (Length(InputStr.s) > 0) and ((CursorPos = 1) or (CursorPos = 2)) then + begin + c:= InputStr.s[1]; + if charIsForHogSpeech(c) then + begin + SpeechHogNumber:= 0; + if Length(InputStr.s) > 1 then + begin + c:= InputStr.s[2]; + if (c > '0') and (c < '9') then + SpeechHogNumber:= byte(c) - 48; + end; + // default to current hedgehog (if own) or first hedgehog + if SpeechHogNumber = 0 then + begin + if not CurrentTeam^.ExtDriven then + SpeechHogNumber:= CurrentTeam^.CurrHedgehog + 1 + else + SpeechHogNumber:= 1; + end; + end; + end + else + SpeechHogNumber:= -1; + end +else + SpeechHogNumber:= -1; + +// draw chat lines +if ((not ChatHidden) or showAll) and (UIDisplay <> uiNone) then begin - r.w:= Strs[i].Width; - DrawFillRect(r); - Tint($00, $00, $00, $80); - DrawTexture(9 - cScreenWidth div 2, (visibleCount - t) * 16 - 5, Strs[i].Tex); - untint; - DrawTexture(8 - cScreenWidth div 2, (visibleCount - t) * 16 - 6, Strs[i].Tex); - dec(r.y, 16); + if MissedCount <> 0 then // there are chat strings we missed, so print them now + begin + for i:= 0 to MissedCount - 1 do + AddChatString(MStrs[i]); + MissedCount:= 0; + end; + i:= lastStr; + + cnt:= 0; // count of lines displayed + t := 1; // # of current line processed - if i = 0 then - i:= MaxStrIndex - else - dec(i); + // draw lines in reverse order + while (((t < 7) and (Strs[i].Time > RealTicks)) or ((t <= MaxStrIndex + 1) and showAll)) + and (Strs[i].Tex <> nil) do + begin + top:= top - ClHeight; + // draw chatline only if not offscreen + if top > 0 then + DrawTexture(left, top, Strs[i].Tex); - inc(cnt); - inc(t) + if i = 0 then + i:= MaxStrIndex + else + dec(i); + + inc(cnt); + inc(t) + end; + + visibleCount:= cnt; end; - -visibleCount:= cnt; end; procedure SendHogSpeech(s: shortstring); @@ -214,12 +417,25 @@ ParseCommand('/hogsay '+s, true) end; +procedure SendConsoleCommand(s: shortstring); +begin + Delete(s, 1, 1); + SendIPC('~' + s) +end; + procedure AcceptChatString(s: shortstring); var i: TWave; j: TChatCmd; c, t: LongInt; x: byte; begin +if s <> LocalStrs[localLastStr] then + begin + // put in input history + localLastStr:= (localLastStr + 1) mod MaxStrIndex; + LocalStrs[localLastStr]:= s; + end; + t:= LocalTeam; x:= 0; if (s[1] = '"') and (s[Length(s)] = '"') @@ -231,7 +447,7 @@ else if (s[1] = '-') and (s[Length(s)] = '-') then x:= 3; -if not CurrentTeam^.ExtDriven and (x <> 0) then +if (not CurrentTeam^.ExtDriven) and (x <> 0) then for c:= 0 to Pred(TeamsCount) do if (TeamsArray[c] = CurrentTeam) then t:= c; @@ -248,7 +464,7 @@ if (s[1] = '/') then begin // These 3 are same as above, only are to make the hedgehog say it on next attack - if (copy(s, 1, 5) = '/hsa ') then + if (copy(s, 2, 4) = 'hsa ') then begin if CurrentTeam^.ExtDriven then ParseCommand('/say ' + copy(s, 6, Length(s)-5), true) @@ -257,7 +473,7 @@ exit end; - if (copy(s, 1, 5) = '/hta ') then + if (copy(s, 2, 4) = 'hta ') then begin if CurrentTeam^.ExtDriven then ParseCommand('/say ' + copy(s, 6, Length(s)-5), true) @@ -266,7 +482,7 @@ exit end; - if (copy(s, 1, 5) = '/hya ') then + if (copy(s, 2, 4) = 'hya ') then begin if CurrentTeam^.ExtDriven then ParseCommand('/say ' + copy(s, 6, Length(s)-5), true) @@ -275,18 +491,56 @@ exit end; - if (copy(s, 1, 6) = '/team ') and (length(s) > 6) then + if (copy(s, 2, 5) = 'team ') and (length(s) > 6) then begin ParseCommand(s, true); exit end; - if (copy(s, 1, 4) = '/me ') then + if (copy(s, 2, 3) = 'me ') then begin ParseCommand('/say ' + s, true); exit end; + if (copy(s, 2, 10) = 'togglechat') then + begin + ChatHidden:= (not ChatHidden); + if ChatHidden then + showAll:= false; + exit + end; + + // debugging commands + if (copy(s, 2, 7) = 'debugvl') then + begin + cViewLimitsDebug:= (not cViewLimitsDebug); + UpdateViewLimits(); + exit + end; + + if (copy(s, 2, 3) = 'lua') then + begin + AddFileLog('/lua issued'); + if gameType <> gmtNet then + begin + liveLua:= (not liveLua); + if liveLua then + begin + AddFileLog('[Lua] chat input string parsing enabled'); + AddChatString(#3 + 'Lua parsing: ON'); + end + else + begin + AddFileLog('[Lua] chat input string parsing disabled'); + AddChatString(#3 + 'Lua parsing: OFF'); + end; + UpdateInputLinePrefix(); + end; + exit + end; + + // hedghog animations/taunts and engine commands if (not CurrentTeam^.ExtDriven) and (CurrentTeam^.Hedgehogs[0].BotLevel = 0) then begin for i:= Low(TWave) to High(TWave) do @@ -295,17 +549,25 @@ ParseCommand('/taunt ' + char(i), true); exit end; + end; - for j:= Low(TChatCmd) to High(TChatCmd) do - if (s = ChatCommandz[j].ChatCmd) then - begin - ParseCommand(ChatCommandz[j].ProcedureCallChatCmd, true); - exit - end; - end + for j:= Low(TChatCmd) to High(TChatCmd) do + if (s = ChatCommandz[j].ChatCmd) then + begin + ParseCommand(ChatCommandz[j].ProcedureCallChatCmd, true); + exit + end; + + if (gameType = gmtNet) then + SendConsoleCommand(s) end +else + begin + if liveLua then + LuaParseString(s) else ParseCommand('/say ' + s, true); + end; end; procedure CleanupInput; @@ -317,10 +579,215 @@ ResetKbd; end; +procedure DelBytesFromInputStrBack(endIdx: integer; count: byte); +var startIdx: integer; +begin + // nothing to do if count is 0 + if count = 0 then + exit; + + // first byte to delete + startIdx:= endIdx - (count - 1); + + // delete bytes from string + Delete(InputStr.s, startIdx, count); + + SetLine(InputStr, InputStr.s, true); +end; + +procedure MoveCursorToPreviousChar(); +begin + if cursorPos > 0 then + repeat + dec(cursorPos); + until ((cursorPos = 0) or IsFirstCharByte(InputStr.s[cursorPos + 1])); +end; + +procedure MoveCursorToNextChar(); +var len: integer; +begin + len:= Length(InputStr.s); + if cursorPos < len then + repeat + inc(cursorPos); + until ((cursorPos = len) or IsFirstCharByte(InputStr.s[cursorPos + 1])); +end; + +procedure DeleteLastUTF8CharFromStr(var s: shortstring); +var l: byte; +begin + l:= Length(s); + + while (l > 1) and (not IsFirstCharByte(s[l])) do + begin + dec(l); + end; + + if l > 0 then + dec(l); + + s[0]:= char(l); +end; + +procedure DeleteSelected(); +begin + if (selectedPos >= 0) and (cursorPos <> selectedPos) then + begin + DelBytesFromInputStrBack(max(cursorPos, selectedPos), abs(selectedPos-cursorPos)); + cursorPos:= min(cursorPos, selectedPos); + end; + ResetSelection(); + UpdateCursorCoords(); +end; + +procedure HandleSelection(enabled: boolean); +begin +if enabled then + begin + if selectedPos < 0 then + selectedPos:= cursorPos; + end +else + ResetSelection(); +end; + +type TCharSkip = ( none, wspace, numalpha, special ); + +function GetInputCharSkipClass(index: LongInt): TCharSkip; +var c: char; +begin + c:= InputStr.s[index]; + + // non-ascii counts as letter + if c > #127 then + exit(numalpha); + + // low-ascii whitespaces and DEL + if (c < #33) or (c = #127) then + exit(wspace); + + // low-ascii special chars + if c < #48 then + exit(special); + + // digits + if c < #58 then + exit(numalpha); + + // make c upper-case + if c > #96 then + c:= char(byte(c) - 32); + + // letters + if (c > #64) and (c < #90) then + exit(numalpha); + + // remaining ascii are special chars + exit(special); +end; + +// skip from word to word, similar to Qt +procedure SkipInputChars(skip: TCharSkip; backwards: boolean); +begin +if backwards then + begin + // skip trailing whitespace, similar to Qt + while (skip = wspace) and (cursorPos > 0) do + begin + skip:= GetInputCharSkipClass(cursorPos); + if skip = wspace then + MoveCursorToPreviousChar(); + end; + // skip same-type chars + while (cursorPos > 0) and (GetInputCharSkipClass(cursorPos) = skip) do + MoveCursorToPreviousChar(); + end +else + begin + // skip same-type chars + while cursorPos < Length(InputStr.s) do + begin + MoveCursorToNextChar(); + if (GetInputCharSkipClass(cursorPos) <> skip) then + begin + MoveCursorToPreviousChar(); + break; + end; + end; + // skip trailing whitespace, similar to Qt + while cursorPos < Length(InputStr.s) do + begin + MoveCursorToNextChar(); + if (GetInputCharSkipClass(cursorPos) <> wspace) then + begin + MoveCursorToPreviousChar(); + break; + end; + end; + end; +end; + +procedure CopyToClipboard(var newContent: shortstring); +begin + SendIPC(_S'y' + copy(newContent, 1, 253) + #0); +end; + +procedure CopySelectionToClipboard(); +var selection: shortstring; +begin + if selectedPos >= 0 then + begin + selection:= copy(InputStr.s, min(CursorPos, selectedPos) + 1, abs(CursorPos - selectedPos)); + CopyToClipboard(selection); + end; +end; + +procedure InsertIntoInputStr(s: shortstring); +var limit: integer; +begin + // we check limit for trailing stuff before insertion limit for a reason + // (possible remaining space after too long UTF8-insertion has been shortened) + + // length limit for stuff to that will trail the insertion + limit:= max(cursorPos, MaxInputStrLen-Length(s)); + + while Length(InputStr.s) > limit do + begin + DeleteLastUTF8CharFromStr(InputStr.s); + end; + + // length limit for stuff to insert + limit:= max(0, MaxInputStrLen-cursorPos); + + if limit = 0 then + s:= '' + else while Length(s) > limit do + begin + DeleteLastUTF8CharFromStr(s); + end; + + if Length(s) > 0 then + begin + // insert string truncated to safe length + Insert(s, InputStr.s, cursorPos + 1); + + if Length(InputStr.s) > MaxInputStrLen then + InputStr.s[0]:= char(MaxInputStrLen); + + SetLine(InputStr, InputStr.s, true); + + // move cursor to end of inserted string + inc(cursorPos, Length(s)); + UpdateCursorCoords(); + end; +end; + procedure TextInput(var event: TSDL_TextInputEvent); var s: shortstring; l: byte; begin + DeleteSelected(); + l:= 0; while event.text[l] <> #0 do begin @@ -331,30 +798,83 @@ if byte(InputStr.s[0]) + l > 240 then exit; - InputStrL[byte(InputStr.s[0]) + l]:= InputStr.s[0]; - SetLine(InputStr, InputStr.s + s, true) + InsertIntoInputStr(s); +end; + +procedure PasteFromClipboard(); +begin + SendIPC(_S'Y'); +end; + +procedure CheckPasteBuffer(); +begin + if Length(ChatPasteBuffer) > 0 then + begin + InsertIntoInputStr(ChatPasteBuffer); + ChatPasteBuffer:= ''; + end; end; -procedure KeyPressChat(Sym: Longword); +procedure KeyPressChat(Key, Sym: Longword; Modifier: Word); const firstByteMark: array[0..3] of byte = (0, $C0, $E0, $F0); + nonStateMask = (not (KMOD_NUM or KMOD_CAPS)); var i, btw, index: integer; utf8: shortstring; - action: boolean; + action, selMode, ctrl, ctrlonly: boolean; + skip: TCharSkip; begin + LastKeyPressTick:= RealTicks; action:= true; + + CheckPasteBuffer(); + + selMode:= (modifier and (KMOD_LSHIFT or KMOD_RSHIFT)) <> 0; + ctrl:= (modifier and (KMOD_LCTRL or KMOD_RCTRL)) <> 0; + ctrlonly:= ctrl and ((modifier and nonStateMask and (not (KMOD_LCTRL or KMOD_RCTRL))) = 0); + skip:= none; + case Sym of SDLK_BACKSPACE: begin - if Length(InputStr.s) > 0 then + if selectedPos < 0 then begin - InputStr.s[0]:= InputStrL[byte(InputStr.s[0])]; - SetLine(InputStr, InputStr.s, true) - end + HandleSelection(true); + + // delete more if ctrl is held + if ctrl then + SkipInputChars(GetInputCharSkipClass(cursorPos), true) + else + MoveCursorToPreviousChar(); + + end; + + DeleteSelected(); + UpdateCursorCoords(); + end; + SDLK_DELETE: + begin + if selectedPos < 0 then + begin + HandleSelection(true); + + // delete more if ctrl is held + if ctrl then + SkipInputChars(GetInputCharSkipClass(cursorPos), false) + else + MoveCursorToNextChar(); + + end; + + DeleteSelected(); + UpdateCursorCoords(); end; SDLK_ESCAPE: begin if Length(InputStr.s) > 0 then - SetLine(InputStr, '', true) + begin + SetLine(InputStr, '', true); + ResetCursor(); + end else CleanupInput end; SDLK_RETURN, SDLK_KP_ENTER: @@ -362,7 +882,8 @@ if Length(InputStr.s) > 0 then begin AcceptChatString(InputStr.s); - SetLine(InputStr, '', false) + SetLine(InputStr, '', false); + ResetCursor(); end; CleanupInput end; @@ -372,19 +893,149 @@ if (Sym = SDLK_DOWN) and (history > 0) then dec(history); index:= localLastStr - history + 1; if (index > localLastStr) then - SetLine(InputStr, '', true) - else SetLine(InputStr, LocalStrs[index], true) + begin + SetLine(InputStr, '', true); + end + else + begin + SetLine(InputStr, LocalStrs[index], true); + end; + cursorPos:= Length(InputStr.s); + ResetSelection(); + UpdateCursorCoords(); + end; + SDLK_HOME: + begin + if cursorPos > 0 then + begin + HandleSelection(selMode); + cursorPos:= 0; + end + else if (not selMode) then + ResetSelection(); + + UpdateCursorCoords(); + end; + SDLK_END: + begin + i:= Length(InputStr.s); + if cursorPos < i then + begin + HandleSelection(selMode); + cursorPos:= i; + end + else if (not selMode) then + ResetSelection(); + + UpdateCursorCoords(); end; - SDLK_RIGHT, SDLK_LEFT, SDLK_DELETE, - SDLK_HOME, SDLK_END, + SDLK_LEFT: + begin + if cursorPos > 0 then + begin + + if ctrl then + skip:= GetInputCharSkipClass(cursorPos); + + if selMode or (selectedPos < 0) then + begin + HandleSelection(selMode); + // go to end of previous utf8-char + MoveCursorToPreviousChar(); + end + else // if we're leaving selection mode, jump to its left end + begin + cursorPos:= min(cursorPos, selectedPos); + ResetSelection(); + end; + + if ctrl then + SkipInputChars(skip, true); + + end + else if (not selMode) then + ResetSelection(); + + UpdateCursorCoords(); + end; + SDLK_RIGHT: + begin + if cursorPos < Length(InputStr.s) then + begin + + if selMode or (selectedPos < 0) then + begin + HandleSelection(selMode); + MoveCursorToNextChar(); + end + else // if we're leaving selection mode, jump to its right end + begin + cursorPos:= max(cursorPos, selectedPos); + ResetSelection(); + end; + + if ctrl then + SkipInputChars(GetInputCharSkipClass(cursorPos), false); + + end + else if (not selMode) then + ResetSelection(); + + UpdateCursorCoords(); + end; SDLK_PAGEUP, SDLK_PAGEDOWN: begin // ignore me!!! end; + SDLK_a: + begin + // select all + if ctrlonly then + begin + ResetSelection(); + cursorPos:= 0; + HandleSelection(true); + cursorPos:= Length(InputStr.s); + UpdateCursorCoords(); + end + else + action:= false; + end; + SDLK_c: + begin + // copy + if ctrlonly then + CopySelectionToClipboard() + else + action:= false; + end; + SDLK_v: + begin + // paste + if ctrlonly then + begin + DeleteSelected(); + PasteFromClipboard(); + end + else + action:= false; + end; + SDLK_x: + begin + // cut + if ctrlonly then + begin + CopySelectionToClipboard(); + DeleteSelected(); + end + else + action:= false; + end; else action:= false; end; + // TODO: ctrl+c etc. probably won't work anymore while in text input mode end; procedure chChatMessage(var s: shortstring); @@ -399,11 +1050,7 @@ if copy(s, 1, 4) = '/me ' then s:= #2 + '* ' + UserNick + ' ' + copy(s, 5, Length(s) - 4) else - begin - localLastStr:= (localLastStr + 1) mod MaxStrIndex; - LocalStrs[localLastStr]:= s; s:= #1 + UserNick + ': ' + s; - end; AddChatString(s) end; @@ -418,9 +1065,18 @@ end; procedure chHistory(var s: shortstring); +var i: LongInt; begin s:= s; // avoid compiler hint - showAll:= not showAll + showAll:= not showAll; + // immediatly recount + visibleCount:= 0; + if showAll or (not ChatHidden) then + for i:= 0 to MaxStrIndex do + begin + if (Strs[i].Tex <> nil) and (showAll or (Strs[i].Time > RealTicks)) then + inc(visibleCount); + end; end; procedure chChat(var s: shortstring); @@ -431,7 +1087,11 @@ if length(s) = 0 then SetLine(InputStr, '', true) else - SetLine(InputStr, '/team ', true) + begin + SetLine(InputStr, '/team ', true); + cursorPos:= 6; + UpdateCursorCoords(); + end; end; procedure initModule; @@ -450,18 +1110,28 @@ showAll:= false; ChatReady:= false; missedCount:= 0; + liveLua:= false; + ChatHidden:= false; + firstDraw:= true; + InputLinePrefix.Tex:= nil; + UpdateInputLinePrefix(); + inputStr.s:= ''; inputStr.Tex := nil; for i:= 0 to MaxStrIndex do Strs[i].Tex := nil; + + LastKeyPressTick:= 0; + ResetCursor(); end; procedure freeModule; var i: ShortInt; begin - FreeTexture(InputStr.Tex); + FreeAndNilTexture(InputLinePrefix.Tex); + FreeAndNilTexture(InputStr.Tex); for i:= 0 to MaxStrIndex do - FreeTexture(Strs[i].Tex); + FreeAndNilTexture(Strs[i].Tex); end; end. diff -r 31570b766315 -r ed5a6478e710 hedgewars/uCollisions.pas --- a/hedgewars/uCollisions.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uCollisions.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} @@ -52,9 +52,11 @@ function TestCollisionYwithXYShift(Gear: PGear; ShiftX, ShiftY: LongInt; Dir: LongInt): Word; inline; function TestCollisionYwithXYShift(Gear: PGear; ShiftX, ShiftY: LongInt; Dir: LongInt; withGear: boolean): Word; -function TestRectancleForObstacle(x1, y1, x2, y2: LongInt; landOnly: boolean): boolean; +function TestRectangleForObstacle(x1, y1, x2, y2: LongInt; landOnly: boolean): boolean; -// returns: negative sign if going downhill to left, value is steepness (noslope/error = _0, 45° = _0_5) +function CheckCoordInWater(X, Y: LongInt): boolean; inline; + +// returns: negative sign if going downhill to left, value is steepness (noslope/error = _0, 45 = _0_5) function CalcSlopeBelowGear(Gear: PGear): hwFloat; function CalcSlopeNearGear(Gear: PGear; dirX, dirY: LongInt): hwFloat; function CalcSlopeTangent(Gear: PGear; collisionX, collisionY: LongInt; var outDeltaX, outDeltaY: LongInt; TestWord: LongWord): boolean; @@ -73,9 +75,9 @@ ga: TGearArray; procedure AddCI(Gear: PGear); -var t: PGear; begin -if Gear^.CollisionIndex >= 0 then +if (Gear^.CollisionIndex >= 0) or + ((Count > MAXRECTSINDEX-200) and ((Gear^.Kind = gtMine) or (Gear^.Kind = gtSMine) or (Gear^.Kind = gtKnife))) then exit; TryDo(Count <= MAXRECTSINDEX, 'Collision rects array overflow', true); with cinfos[Count] do @@ -88,15 +90,6 @@ end; Gear^.CollisionIndex:= Count; inc(Count); -// mines are the easiest way to overflow collision -if (Count > (MAXRECTSINDEX-20)) then - begin - t:= GearsList; - while (t <> nil) and (t^.Kind <> gtMine) do - t:= t^.NextGear; - if (t <> nil) then - t^.State:= t^.State or gmDelete - end; end; procedure DeleteCI(Gear: PGear); @@ -104,7 +97,7 @@ if Gear^.CollisionIndex >= 0 then begin with cinfos[Gear^.CollisionIndex] do - ChangeRoundInLand(X, Y, Radius - 1, false, (Gear = CurrentHedgehog^.Gear) or ((Gear^.Kind = gtCase) and (Gear^.State and gstFrozen = 0))); + ChangeRoundInLand(X, Y, Radius - 1, false, ((CurrentHedgehog <> nil) and (Gear = CurrentHedgehog^.Gear)) or ((Gear^.Kind = gtCase) and (Gear^.State and gstFrozen = 0))); cinfos[Gear^.CollisionIndex]:= cinfos[Pred(Count)]; cinfos[Gear^.CollisionIndex].cGear^.CollisionIndex:= Gear^.CollisionIndex; Gear^.CollisionIndex:= -1; @@ -112,6 +105,12 @@ end; end; +function CheckCoordInWater(X, Y: LongInt): boolean; inline; +begin + CheckCoordInWater:= (Y > cWaterLine) + or ((WorldEdge = weSea) and ((X < LongInt(leftX)) or (X > LongInt(rightX)))); +end; + function CheckGearsCollision(Gear: PGear): PGearArray; var mx, my, tr: LongInt; i: Longword; @@ -212,10 +211,15 @@ i:= y + Gear^.Radius * 2 - 2; repeat if (y and LAND_HEIGHT_MASK) = 0 then - if Land[y, x] and Gear^.CollisionMask > 255 then - exit(Land[y, x] and Gear^.CollisionMask) - else if Land[y, x] and Gear^.CollisionMask <> 0 then - pixel:= Land[y, x] and Gear^.CollisionMask; + begin + if Land[y, x] and Gear^.CollisionMask <> 0 then + begin + if Land[y, x] and Gear^.CollisionMask > 255 then + exit(Land[y, x] and Gear^.CollisionMask) + else + pixel:= Land[y, x] and Gear^.CollisionMask; + end; + end; inc(y) until (y > i); end; @@ -234,7 +238,7 @@ for i:= 0 to Pred(Count) do with cinfos[i] do - if (Gear <> cGear) and + if (Gear <> cGear) and ((mx > x) xor (Dir > 0)) and ( ((cGear^.Kind in [gtHedgehog, gtMine, gtKnife]) and ((Gear^.State and gstNotKickable) = 0)) or @@ -275,10 +279,12 @@ repeat if (x and LAND_WIDTH_MASK) = 0 then if Land[y, x] > 0 then + begin if Land[y, x] and Gear^.CollisionMask > 255 then exit(Land[y, x] and Gear^.CollisionMask) - else if Land[y, x] <> 0 then + else // if Land[y, x] <> 0 then pixel:= Land[y, x] and Gear^.CollisionMask; + end; inc(x) until (x > i); end; @@ -300,7 +306,7 @@ if (Gear <> cGear) and ((myr > y) xor (Dir > 0)) and (Gear^.State and gstNotKickable = 0) and - (cGear^.Kind in [gtHedgehog, gtMine, gtKnife, gtExplosives]) and + (cGear^.Kind in [gtHedgehog, gtMine, gtKnife, gtExplosives]) and (sqr(mx - x) + sqr(my - y) <= sqr(Radius + Gear^.Radius + 2)) then begin with cGear^ do @@ -327,7 +333,7 @@ begin Gear^.X:= Gear^.X + ShiftX; Gear^.Y:= Gear^.Y + int2hwFloat(ShiftY); -if withGear then +if withGear then TestCollisionXwithXYShift:= TestCollisionXwithGear(Gear, Dir) else TestCollisionXwithXYShift:= TestCollisionX(Gear, Dir); Gear^.X:= Gear^.X - ShiftX; @@ -394,16 +400,16 @@ TestCollisionYwithXYShift:= TestCollisionYwithGear(Gear, Dir) else TestCollisionYwithXYShift:= TestCollisionY(Gear, Dir); - + Gear^.X:= Gear^.X - int2hwFloat(ShiftX); Gear^.Y:= Gear^.Y - int2hwFloat(ShiftY) end; -function TestRectancleForObstacle(x1, y1, x2, y2: LongInt; landOnly: boolean): boolean; +function TestRectangleForObstacle(x1, y1, x2, y2: LongInt; landOnly: boolean): boolean; var x, y: LongInt; TestWord: LongWord; begin -TestRectancleForObstacle:= true; +TestRectangleForObstacle:= true; if landOnly then TestWord:= 255 @@ -432,7 +438,7 @@ if ((y and LAND_HEIGHT_MASK) = 0) and ((x and LAND_WIDTH_MASK) = 0) and (Land[y, x] > TestWord) then exit; -TestRectancleForObstacle:= false +TestRectangleForObstacle:= false end; function CalcSlopeTangent(Gear: PGear; collisionX, collisionY: LongInt; var outDeltaX, outDeltaY: LongInt; TestWord: LongWord): boolean; @@ -583,7 +589,7 @@ isColl, bSucc: Boolean; begin -if dirY <> 0 then +if dirY <> 0 then begin y:= hwRound(Gear^.Y) + Gear^.Radius * dirY; gx:= hwRound(Gear^.X); diff -r 31570b766315 -r ed5a6478e710 hedgewars/uCommandHandlers.pas --- a/hedgewars/uCommandHandlers.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uCommandHandlers.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} @@ -26,7 +26,8 @@ procedure freeModule; implementation -uses uCommands, uTypes, uVariables, uIO, uDebug, uConsts, uScript, uUtils, SDLh, uRandom, uCaptions +uses uCommands, uTypes, uVariables, uIO, uDebug, uConsts, uScript, uUtils, SDLh, uWorld, uRandom, uCaptions + , uVisualGearsList {$IFDEF USE_VIDEO_RECORDING}, uVideoRec {$ENDIF}; var prevGState: TGameState = gsConfirm; @@ -52,14 +53,12 @@ begin prevGState:= GameState; GameState:= gsConfirm; - SDL_ShowCursor(1) end else if GameState = gsConfirm then - begin GameState:= prevGState; - SDL_ShowCursor(ord(isPaused)) - end + + updateCursorVisibility; end; procedure chForceQuit(var s: shortstring); @@ -119,6 +118,12 @@ ScriptLoad(s) end; +procedure chScriptParam(var s: shortstring); +begin + ScriptSetString('ScriptParam', s); + ScriptCall('onParameters'); +end; + procedure chCurU_p(var s: shortstring); begin s:= s; // avoid compiler hint @@ -170,7 +175,7 @@ procedure chLeft_p(var s: shortstring); begin s:= s; // avoid compiler hint -if CheckNoTeamOrHH or isPaused then +if CheckNoTeamOrHH then exit; if not isExternalSource then SendIPC(_S'L'); @@ -195,7 +200,7 @@ procedure chRight_p(var s: shortstring); begin s:= s; // avoid compiler hint -if CheckNoTeamOrHH or isPaused then +if CheckNoTeamOrHH then exit; if not isExternalSource then SendIPC(_S'R'); @@ -220,7 +225,7 @@ procedure chUp_p(var s: shortstring); begin s:= s; // avoid compiler hint -if CheckNoTeamOrHH or isPaused then +if CheckNoTeamOrHH then exit; if not isExternalSource then SendIPC(_S'U'); @@ -245,7 +250,7 @@ procedure chDown_p(var s: shortstring); begin s:= s; // avoid compiler hint -if CheckNoTeamOrHH or isPaused then +if CheckNoTeamOrHH then exit; if not isExternalSource then SendIPC(_S'D'); @@ -270,7 +275,7 @@ procedure chPrecise_p(var s: shortstring); begin s:= s; // avoid compiler hint -if CheckNoTeamOrHH or isPaused then +if CheckNoTeamOrHH then exit; if not isExternalSource then SendIPC(_S'Z'); @@ -295,7 +300,7 @@ procedure chLJump(var s: shortstring); begin s:= s; // avoid compiler hint -if CheckNoTeamOrHH or isPaused then +if CheckNoTeamOrHH then exit; if not isExternalSource then SendIPC(_S'j'); @@ -308,7 +313,7 @@ procedure chHJump(var s: shortstring); begin s:= s; // avoid compiler hint -if CheckNoTeamOrHH or isPaused then +if CheckNoTeamOrHH then exit; if not isExternalSource then SendIPC(_S'J'); @@ -319,9 +324,10 @@ end; procedure chAttack_p(var s: shortstring); +var inbtwnTrgtAttks: Boolean; begin s:= s; // avoid compiler hint -if CheckNoTeamOrHH or isPaused then +if CheckNoTeamOrHH then exit; bShowFinger:= false; with CurrentHedgehog^.Gear^ do @@ -329,11 +335,13 @@ AddFileLog('/+attack: hedgehog''s Gear^.State = '+inttostr(State)); if ((State and gstHHDriven) <> 0) then begin - FollowGear:= CurrentHedgehog^.Gear; + inbtwnTrgtAttks:= ((GameFlags and gfInfAttack) <> 0) and ((Ammoz[CurrentHedgehog^.CurAmmoType].Ammo.Propz and ammoprop_NeedTarget) <> 0); + if (not inbtwnTrgtAttks) then + FollowGear:= CurrentHedgehog^.Gear; if not isExternalSource then SendIPC(_S'A'); Message:= Message or (gmAttack and InputMask); - ScriptCall('onAttack'); + ScriptCall('onAttack'); // so if I fire airstrike, it doesn't count as attack? fine, fine end end end; @@ -356,7 +364,7 @@ procedure chSwitch(var s: shortstring); begin s:= s; // avoid compiler hint -if CheckNoTeamOrHH or isPaused then +if CheckNoTeamOrHH then exit; if not isExternalSource then SendIPC(_S'S'); @@ -483,7 +491,8 @@ procedure chCapture(var s: shortstring); begin s:= s; // avoid compiler hint -flagMakeCapture:= true +flagMakeCapture:= true; +flagDumpLand:= (LocalMessage and gmPrecise <> 0); end; procedure chRecord(var s: shortstring); @@ -535,7 +544,7 @@ begin s:= s; // avoid compiler hint if CheckNoTeamOrHH then - bShowAmmoMenu:= true + bShowAmmoMenu:= (not bShowAmmoMenu) else begin with CurrentTeam^ do @@ -570,18 +579,18 @@ procedure chFindhh(var s: shortstring); begin s:= s; // avoid compiler hint -if CheckNoTeamOrHH or isPaused then +if CheckNoTeamOrHH then exit; if autoCameraOn then begin FollowGear:= nil; - AddCaption('Auto Camera Off', $CCCCCC, capgrpVolume); + AddCaption(trmsg[sidAutoCameraOff], $CCCCCC, capgrpVolume); autoCameraOn:= false end else begin - AddCaption('Auto Camera On', $CCCCCC, capgrpVolume); + AddCaption(trmsg[sidAutoCameraOn], $CCCCCC, capgrpVolume); bShowFinger:= true; if not CurrentHedgehog^.Unplaced then FollowGear:= CurrentHedgehog^.Gear; @@ -591,8 +600,7 @@ procedure chPause(var s: shortstring); begin -s:= s; // avoid compiler hint -if gameType <> gmtNet then +if (gameType <> gmtNet) or (s = 'server') then isPaused:= not isPaused else if (CurrentTeam^.ExtDriven) or (CurrentHedgehog^.BotLevel > 0) then @@ -600,10 +608,7 @@ else isAFK:= false; // for real ninjas -if isPaused or isAFK then - SDL_ShowCursor(1) - else - SDL_ShowCursor(ord(GameState = gsConfirm)) +updateCursorVisibility; end; procedure chRotateMask(var s: shortstring); @@ -666,7 +671,7 @@ procedure chMapGen(var s: shortstring); begin -cMapGen:= StrToInt(s) +cMapGen:= TMapGen(StrToInt(s)) end; procedure chTemplateFilter(var s: shortstring); @@ -674,6 +679,11 @@ cTemplateFilter:= StrToInt(s) end; +procedure chFeatureSize(var s: shortstring); +begin +cFeatureSize:= StrToInt(s) +end; + procedure chInactDelay(var s: shortstring); begin cInactDelay:= StrToInt(s) @@ -739,6 +749,11 @@ cLandMines:= StrToInt(s) end; +procedure chAirMines(var s: shortstring); +begin +cAirMines:= StrToInt(s) +end; + procedure chExplosives(var s: shortstring); begin cExplosives:= StrToInt(s) @@ -762,7 +777,14 @@ procedure chFastUntilLag(var s: shortstring); begin -fastUntilLag:= StrToInt(s) <> 0 + fastUntilLag:= StrToInt(s) <> 0; + + if not fastUntilLag then + begin + // update health bars and the wind indicator + AddVisualGear(0, 0, vgtTeamHealthSorter); + AddVisualGear(0, 0, vgtSmoothWindBar) + end end; procedure chCampVar(var s:shortstring); @@ -775,6 +797,12 @@ WorldEdge:= TWorldEdge(StrToInt(s)) end; +procedure chAdvancedMapGenMode(var s:shortstring); +begin + s:= s; // avoid compiler hint + cAdvancedMapGenMode:= true; +end; + procedure initModule; begin //////// Begin top sorted by freq analysis not including chatmsg @@ -796,6 +824,7 @@ //////// End top by freq analysis RegisterVariable('gencmd' , @chGenCmd , false); RegisterVariable('script' , @chScript , false); + RegisterVariable('scriptparam', @chScriptParam, false); RegisterVariable('proto' , @chCheckProto , true ); RegisterVariable('spectate', @chFastUntilLag , false); RegisterVariable('capture' , @chCapture , true ); @@ -807,6 +836,7 @@ RegisterVariable('template_filter', @chTemplateFilter, false); RegisterVariable('mapgen' , @chMapGen , false); RegisterVariable('maze_size',@chTemplateFilter, false); + RegisterVariable('feature_size',@chFeatureSize, false); RegisterVariable('delay' , @chInactDelay , false); RegisterVariable('ready' , @chReadyDelay , false); RegisterVariable('casefreq', @chCaseFactor , false); @@ -820,6 +850,7 @@ RegisterVariable('getawaytime' , @chGetAwayTime , false); RegisterVariable('minedudpct',@chMineDudPercent, false); RegisterVariable('minesnum', @chLandMines , false); + RegisterVariable('airmines', @chAirMines , false); RegisterVariable('explosives',@chExplosives , false); RegisterVariable('gmflags' , @chGameFlags , false); RegisterVariable('turntime', @chHedgehogTurnTime, false); @@ -857,6 +888,7 @@ RegisterVariable('campvar' , @chCampVar , true ); RegisterVariable('record' , @chRecord , true ); RegisterVariable('worldedge',@chWorldEdge , false); + RegisterVariable('advmapgen',@chAdvancedMapGenMode, false); end; procedure freeModule; diff -r 31570b766315 -r ed5a6478e710 hedgewars/uCommands.pas --- a/hedgewars/uCommands.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uCommands.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} @@ -106,7 +106,7 @@ begin if TrustedSource or t^.Trusted then begin - if t^.Rand and (not CheckNoTeamOrHH) then + if t^.Rand and (not CheckNoTeamOrHH) then CheckSum:= CheckSum xor LongWord(SDLNet_Read32(@CmdStr)) xor LongWord(s[0]) xor GameTicks; t^.Handler(s); end; @@ -139,7 +139,7 @@ if (Message and gmLeft) <> 0 then ParseCommand('/-left', true) else if (Message and gmRight) <> 0 then - ParseCommand('/-right', true) + ParseCommand('/-right', true) else if (Message and gmUp) <> 0 then ParseCommand('/-up', true) else if (Message and gmDown) <> 0 then diff -r 31570b766315 -r ed5a6478e710 hedgewars/uConsole.pas --- a/hedgewars/uConsole.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uConsole.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} @@ -24,7 +24,6 @@ procedure WriteToConsole(s: shortstring); procedure WriteLnToConsole(s: shortstring); -function ShortStringAsPChar(s: shortstring): PChar; var lastConsoleline : shortstring; @@ -49,20 +48,21 @@ begin {$IFNDEF NOCONSOLE} WriteToConsole(s); - lastConsoleline:= s; {$IFNDEF ANDROID} WriteLn(stderr, ''); {$ENDIF} {$ENDIF} + lastConsoleline:= s; end; - +{$IFDEF ANDROID} function ShortStringAsPChar(s: shortstring) : PChar; begin if Length(s) = High(s) then Dec(s[0]); s[Ord(Length(s))+1] := #0; + // returning pointer to stack, rly? ShortStringAsPChar:= @s[1]; end; - +{$ENDIF} end. diff -r 31570b766315 -r ed5a6478e710 hedgewars/uConsts.pas --- a/hedgewars/uConsts.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uConsts.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} @@ -26,6 +26,19 @@ {$INCLUDE "config.inc"} const + HaltNoError = 0; + HaltUsageError = 1; + HaltFatalError = 2; + HaltStartupError = 3; + HaltFatalErrorNoIPC = 4; + + // for automatic tests + HaltTestSuccess = 0; + HaltTestFailed = 10; + HaltTestLuaError = 11; + HaltTestUnexpected = 12; + + sfMax = 1000; // message constants @@ -36,6 +49,7 @@ errmsgIncorrectUse = 'Incorrect use'; errmsgShouldntRun = 'This program shouldn''t be run manually'; errmsgWrongNumber = 'Wrong parameters number'; + errmsgLuaTestTerm = 'WARNING: Lua test terminated before the test was properly finished with EndLuaTest()!'; msgLoading = 'Loading '; msgOK = 'ok'; @@ -91,20 +105,20 @@ // To allow these to layer, going to treat them as masks. The bottom byte is reserved for objects // TODO - set lfBasic for all solid land, ensure all uses of the flags can handle multiple flag bits // lfObject and lfBasic are only to be different *graphically* in all other ways they should be treated the same - lfBasic = $8000; // white + lfBasic = $8000; // black lfIndestructible = $4000; // red - lfObject = $2000; + lfObject = $2000; // white lfDamaged = $1000; // lfIce = $0800; // blue lfBouncy = $0400; // green lfLandMask = $FF00; // upper byte is used for terrain, not objects. - lfCurrentHog = $0080; // CurrentHog. It is also used to flag crates, for convenience of AI. Since an active hog would instantly collect the crate, this doesn't impact play + lfCurrentHog = $0080; // CurrentHog. It is also used to flag crates, for convenience of AI. Since an active hog would instantly collect the crate, this does not impact play lfNotCurrentMask = $FF7F; // inverse of above. frequently used lfObjMask = $007F; // lower 7 bits used for hogs lfNotObjMask = $FF80; // inverse of above. - // lower byte is for objects. - // consists of 0-127 counted for object checkins and $80 as a bit flag for current hog. + // lower byte is for objects. + // consists of 0-127 counted for object checkins and $80 as a bit flag for current hog. lfAllObjMask = $00FF; // lfCurrentHog or lfObjMask @@ -115,11 +129,13 @@ MAXNAMELEN = 192; MAXROPEPOINTS = 3840; + {$IFNDEF PAS2C} // some opengl headers do not have these macros GL_BGR = $80E0; GL_BGRA = $80E1; GL_CLAMP_TO_EDGE = $812F; GL_TEXTURE_PRIORITY = $8066; + {$ENDIF} cVisibleWater : LongInt = 128; cTeamHealthWidth : LongInt = 128; @@ -137,7 +153,7 @@ cMaxHHIndex = 7; cMaxHHs = 48; - cMaxEdgePoints = 16384; + cMaxEdgePoints = 32768; cHHRadius = 9; cHHStepTicks = 29; @@ -150,11 +166,13 @@ cBlowTorchC = 6; cakeDmg = 75; - cKeyMaxIndex = 1023; + cKeyMaxIndex = 1600; cKbdMaxIndex = 65536;//need more room for the modifier keys cFontBorder = 2; + cDefaultBuildMaxDist = 256; + // do not change this value cDefaultZoomLevel = 2.0; @@ -199,7 +217,7 @@ gstAttacked = $00000008; gstAttacking = $00000010; gstCollision = $00000020; - gstHHChooseTarget = $00000040; + gstChooseTarget = $00000040; gstHHJumping = $00000100; gsttmpFlag = $00000200; gstHHThinking = $00000800; @@ -215,6 +233,7 @@ gstInvisible = $00200000; gstSubmersible = $00400000; gstFrozen = $00800000; + gstNoGravity = $01000000; // gear messages gmLeft = $00000001; @@ -239,11 +258,11 @@ cMaxSlotIndex = 9; cMaxSlotAmmoIndex = 5; - + // ai hints aihUsualProcessing = $00000000; aihDoesntMatter = $00000001; - + // ammo properties ammoprop_Timerable = $00000001; ammoprop_Power = $00000002; @@ -261,7 +280,7 @@ ammoprop_Utility = $00001000; ammoprop_Effect = $00002000; ammoprop_SetBounce = $00004000; - ammoprop_NeedUpDown = $00008000;//Used by TouchInterface to show or hide up/down widgets + ammoprop_NeedUpDown = $00008000;//Used by TouchInterface to show or hide up/down widgets ammoprop_OscAim = $00010000; ammoprop_NoMoveAfter = $00020000; ammoprop_Track = $00040000; @@ -288,6 +307,8 @@ posCaseExplode = $00000010; posCasePoison = $00000020; + cCaseHealthRadius = 14; + // hog tag mask //htNone = $00; htTeamName = $01; @@ -296,10 +317,13 @@ htTransparent = $08; NoPointX = Low(LongInt); - cTargetPointRef : TPoint = (X: NoPointX; Y: 0); + cTargetPointRef : TPoint = (x: NoPointX; y: 0); kSystemSoundID_Vibrate = $00000FFF; + cMinPlayWidth = 200; + cWorldEdgeDist = 200; + implementation end. diff -r 31570b766315 -r ed5a6478e710 hedgewars/uCursor.pas --- a/hedgewars/uCursor.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uCursor.pas Tue Nov 10 20:43:13 2015 +0100 @@ -25,7 +25,7 @@ var x, y: LongInt; begin SDL_GetMouseState(@x, @y); - + if(x <> cScreenWidth div 2) or (y <> cScreenHeight div 2) then begin handlePositionUpdate(x - cScreenWidth div 2, y - cScreenHeight div 2); diff -r 31570b766315 -r ed5a6478e710 hedgewars/uDebug.pas --- a/hedgewars/uDebug.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uDebug.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} @@ -27,13 +27,18 @@ procedure SDLTry(Assert: boolean; Msg: shortstring; isFatal: boolean); implementation -uses SDLh, uConsole, uCommands; +uses SDLh, uConsole, uCommands, uConsts; procedure OutError(Msg: shortstring; isFatalError: boolean); begin WriteLnToConsole(Msg); if isFatalError then + begin ParseCommand('fatal ' + lastConsoleline, true); + // hint for the 'coverity' source analyzer + // this halt is never actually reached because ParseCommands will halt first + halt(HaltFatalError); + end; end; procedure TryDo(Assert: boolean; Msg: shortstring; isFatal: boolean); diff -r 31570b766315 -r ed5a6478e710 hedgewars/uFloat.pas --- a/hedgewars/uFloat.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uFloat.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} @@ -39,7 +39,6 @@ *) interface -{$IFDEF FPC} {$IFDEF ENDIAN_LITTLE} type hwFloat = record isNegative: boolean; @@ -63,7 +62,9 @@ // The implemented operators operator = (const z1, z2: hwFloat) z : boolean; inline; - +{$IFDEF PAS2C} +operator <> (const z1, z2: hwFloat) z : boolean; inline; +{$ENDIF} operator + (const z1, z2: hwFloat) z : hwFloat; inline; operator - (const z1, z2: hwFloat) z : hwFloat; inline; operator - (const z1: hwFloat) z : hwFloat; inline; @@ -83,7 +84,6 @@ function hwRound(const t: hwFloat): LongInt; inline; // Does NOT really round but returns the integer representation of the hwFloat without fractional digits. (-_0_9 -> -0, _1_5 -> _1) function hwAbs(const t: hwFloat): hwFloat; inline; // Returns the value of t with positive sign. function hwSqr(const t: hwFloat): hwFloat; inline; // Returns the square value of parameter t. -function hwPow(const t: hwFloat; p: LongWord): hwFloat; inline; // Returns the power of the value function hwSqrt1(const t: hwFloat): hwFloat; inline; // Returns the the positive square root of parameter t. function hwSqrt(const x: hwFloat): hwFloat; inline; // Returns the the positive square root of parameter t. function Distance(const dx, dy: hwFloat): hwFloat; // Returns the distance between two points in 2-dimensional space, of which the parameters are the horizontal and vertical distance. @@ -95,14 +95,9 @@ function hwSign(r: hwFloat): LongInt; inline; // Returns an integer with value 1 and sign of parameter r. function hwSignf(r: real): LongInt; inline; // Returns an integer with value 1 and sign of parameter r. function isZero(const z: hwFloat): boolean; inline; -{$IFDEF FPC} -{$J-} -{$ENDIF} + {$WARNINGS OFF} - - // some hwFloat constants - const _1div1024: hwFloat = (isNegative: false; QWordValue: 4194304); _1div10000: hwFloat = (isNegative: false; QWordValue: 429496); _1div50000: hwFloat = (isNegative: false; QWordValue: 85899); @@ -150,20 +145,20 @@ _0_999: hwFloat = (isNegative: false; QWordValue: 4290672328); _0: hwFloat = (isNegative: false; QWordValue: 0); _1: hwFloat = (isNegative: false; QWordValue: 4294967296); - _1_2: hwFloat = (isNegative: false; QWordValue: 1288490189*4); + _1_2: hwFloat = (isNegative: false; QWordValue: 4294967296 * 6 div 5 + 1); _1_5: hwFloat = (isNegative: false; QWordValue: 4294967296 * 3 div 2); _1_6: hwFloat = (isNegative: false; QWordValue: 4294967296 * 8 div 5); _1_9: hwFloat = (isNegative: false; QWordValue: 8160437862); _2: hwFloat = (isNegative: false; QWordValue: 4294967296 * 2); _2_4: hwFloat = (isNegative: false; QWordValue: 4294967296 * 12 div 5); _3: hwFloat = (isNegative: false; QWordValue: 4294967296 * 3); - _3_2: hwFloat = (isNegative: false; QWordValue: 3435973837*4); + _3_2: hwFloat = (isNegative: false; QWordValue: 4294967296 * 16 div 5); _PI: hwFloat = (isNegative: false; QWordValue: 13493037704); _4: hwFloat = (isNegative: false; QWordValue: 4294967296 * 4); _4_5: hwFloat = (isNegative: false; QWordValue: 4294967296 * 9 div 2); _5: hwFloat = (isNegative: false; QWordValue: 4294967296 * 5); _6: hwFloat = (isNegative: false; QWordValue: 4294967296 * 6); - _6_4: hwFloat = (isNegative: false; QWordValue: 3435973837 * 8); + _6_4: hwFloat = (isNegative: false; QWordValue: 4294967296 * 32 div 5); _7: hwFloat = (isNegative: false; QWordValue: 4294967296 * 7); _10: hwFloat = (isNegative: false; QWordValue: 4294967296 * 10); _12: hwFloat = (isNegative: false; QWordValue: 4294967296 * 12); @@ -194,18 +189,11 @@ cLittle: hwFloat = (isNegative: false; QWordValue: 1); cHHKick: hwFloat = (isNegative: false; QWordValue: 42949673); // _0_01 {$WARNINGS ON} -{$ENDIF} - -{$IFNDEF FPC} -type hwFloat = Extended; -{$ENDIF} implementation uses uSinTable; -{$IFDEF FPC} - function int2hwFloat (const i: LongInt) : hwFloat; inline; begin int2hwFloat.isNegative:= i < 0; @@ -225,6 +213,13 @@ z:= (z1.isNegative = z2.isNegative) and (z1.QWordValue = z2.QWordValue); end; +{$IFDEF PAS2C} +operator <> (const z1, z2: hwFloat) z : boolean; inline; +begin + z:= (z1.isNegative <> z2.isNegative) or (z1.QWordValue <> z2.QWordValue); +end; +{$ENDIF} + operator + (const z1, z2: hwFloat) z : hwFloat; inline; begin if z1.isNegative = z2.isNegative then @@ -294,163 +289,153 @@ operator - (const z1: hwFloat) z : hwFloat; inline; begin -z:= z1; -z.isNegative:= not z.isNegative + z:= z1; + z.isNegative:= not z.isNegative end; operator * (const z1, z2: hwFloat) z : hwFloat; inline; begin -z.isNegative:= z1.isNegative xor z2.isNegative; -z.QWordValue:= QWord(z1.Round) * z2.Frac + QWord(z1.Frac) * z2.Round + ((QWord(z1.Frac) * z2.Frac) shr 32); -z.Round:= z.Round + QWord(z1.Round) * z2.Round; + z.isNegative:= z1.isNegative xor z2.isNegative; + z.QWordValue:= QWord(z1.Round) * z2.Frac + QWord(z1.Frac) * z2.Round + ((QWord(z1.Frac) * z2.Frac) shr 32); + z.Round:= z.Round + QWord(z1.Round) * z2.Round; end; operator * (const z1: hwFloat; const z2: LongInt) z : hwFloat; inline; begin -z.isNegative:= z1.isNegative xor (z2 < 0); -z.QWordValue:= z1.QWordValue * abs(z2) + z.isNegative:= z1.isNegative xor (z2 < 0); + z.QWordValue:= z1.QWordValue * abs(z2) end; operator / (const z1: hwFloat; z2: hwFloat) z : hwFloat; inline; var t: QWord; begin -z.isNegative:= z1.isNegative xor z2.isNegative; -z.Round:= z1.QWordValue div z2.QWordValue; -t:= z1.QWordValue - z2.QWordValue * z.Round; -z.Frac:= 0; + z.isNegative:= z1.isNegative xor z2.isNegative; + z.Round:= z1.QWordValue div z2.QWordValue; + t:= z1.QWordValue - z2.QWordValue * z.Round; + z.Frac:= 0; -if t <> 0 then - begin - while ((t and $FF00000000000000) = 0) and ((z2.QWordValue and $FF00000000000000) = 0) do + if t <> 0 then begin - t:= t shl 8; - z2.QWordValue:= z2.QWordValue shl 8 - end; + while ((t and $FF00000000000000) = 0) and ((z2.QWordValue and $FF00000000000000) = 0) do + begin + t:= t shl 8; + z2.QWordValue:= z2.QWordValue shl 8 + end; - if z2.Round > 0 then - inc(z.QWordValue, t div z2.Round); - end + if z2.Round > 0 then + inc(z.QWordValue, t div z2.Round); + end end; operator / (const z1: hwFloat; const z2: LongInt) z : hwFloat; inline; begin -z.isNegative:= z1.isNegative xor (z2 < 0); -z.QWordValue:= z1.QWordValue div abs(z2) + z.isNegative:= z1.isNegative xor (z2 < 0); + z.QWordValue:= z1.QWordValue div abs(z2) end; function cstr(const z: hwFloat): shortstring; var tmpstr: shortstring; begin -str(z.Round, cstr); -if z.Frac <> 0 then - begin - str(z.Frac / $100000000, tmpstr); - delete(tmpstr, 1, 2); - cstr:= cstr + '.' + copy(tmpstr, 1, 10) - end; -if z.isNegative then - cstr:= '-' + cstr + str(z.Round, cstr); + if z.Frac <> 0 then + begin + str(z.Frac / $100000000, tmpstr); + delete(tmpstr, 1, 2); + cstr:= cstr + '.' + copy(tmpstr, 1, 10) + end; + if z.isNegative then + cstr:= '-' + cstr end; function hwRound(const t: hwFloat): LongInt; begin -if t.isNegative then - hwRound:= -(t.Round and $7FFFFFFF) -else - hwRound:= t.Round and $7FFFFFFF + if t.isNegative then + hwRound:= -(t.Round and $7FFFFFFF) + else + hwRound:= t.Round and $7FFFFFFF end; function hwAbs(const t: hwFloat): hwFloat; begin -hwAbs:= t; -hwAbs.isNegative:= false + hwAbs:= t; + hwAbs.isNegative:= false end; function hwSqr(const t: hwFloat): hwFloat; inline; begin -hwSqr.isNegative:= false; -hwSqr.QWordValue:= ((QWord(t.Round) * t.Round) shl 32) + QWord(t.Round) * t.Frac * 2 + ((QWord(t.Frac) * t.Frac) shr 32); -end; - -function hwPow(const t: hwFloat;p: LongWord): hwFloat; -begin -hwPow:= t; -if p mod 2 = 0 then hwPow.isNegative:= false; - -while p > 0 do - begin - hwPow.QWordValue:= QWord(hwPow.Round) * t.Frac + QWord(hwPow.Frac) * t.Round + ((QWord(hwPow.Frac) * t.Frac) shr 32); - dec(p) - end + hwSqr.isNegative:= false; + hwSqr.QWordValue:= ((QWord(t.Round) * t.Round) shl 32) + QWord(t.Round) * t.Frac * 2 + ((QWord(t.Frac) * t.Frac) shr 32); end; function hwSqrt1(const t: hwFloat): hwFloat; const pwr = 8; // even value, feel free to adjust - rThreshold = 1 shl (pwr + 32); - lThreshold = 1 shl (pwr div 2 + 32); + rThreshold: QWord = 1 shl (pwr + 32); + lThreshold: QWord = 1 shl (pwr div 2 + 32); var l, r: QWord; c: hwFloat; begin -hwSqrt1.isNegative:= false; + hwSqrt1.isNegative:= false; -if t.Round = 0 then - begin - l:= t.QWordValue; - r:= $100000000 - end -else - begin - if t.QWordValue > $FFFFFFFFFFFF then // t.Round > 65535.9999 + if t.Round = 0 then + begin + l:= t.QWordValue; + r:= $100000000 + end + else begin - l:= $10000000000; // 256 - r:= $FFFFFFFFFFFF; // 65535.9999 - end else - if t.QWordValue >= rThreshold then + if t.QWordValue > $FFFFFFFFFFFF then // t.Round > 65535.9999 begin - l:= lThreshold; - r:= $10000000000; // 256 - end else - begin - l:= $100000000; - r:= lThreshold; - end; + l:= $10000000000; // 256 + r:= $FFFFFFFFFFFF; // 65535.9999 + end + else + if t.QWordValue >= rThreshold then + begin + l:= lThreshold; + r:= $10000000000; // 256 + end + else + begin + l:= $100000000; + r:= lThreshold; + end; end; -repeat - c.QWordValue:= (l + r) shr 1; - if hwSqr(c).QWordValue > t.QWordValue then - r:= c.QWordValue - else - l:= c.QWordValue -until r - l <= 1; + repeat + c.QWordValue:= (l + r) shr 1; + if hwSqr(c).QWordValue > t.QWordValue then + r:= c.QWordValue + else + l:= c.QWordValue + until r - l <= 1; -hwSqrt1.QWordValue:= l + hwSqrt1.QWordValue:= l end; function hwSqrt(const x: hwFloat): hwFloat; var r, t, s, q: QWord; i: integer; begin -hwSqrt.isNegative:= false; + hwSqrt.isNegative:= false; -t:= $4000000000000000; -r:= 0; -q:= x.QWordValue; + t:= $4000000000000000; + r:= 0; + q:= x.QWordValue; -for i:= 0 to 31 do - begin - s:= r + t; - r:= r shr 1; - if s <= q then + for i:= 0 to 31 do begin - dec(q, s); - inc(r, t); + s:= r + t; + r:= r shr 1; + if s <= q then + begin + dec(q, s); + inc(r, t); + end; + t:= t shr 2; end; - t:= t shr 2; - end; -hwSqrt.QWordValue:= r shl 16 + hwSqrt.QWordValue:= r shl 16 end; @@ -458,25 +443,26 @@ function Distance(const dx, dy: hwFloat): hwFloat; var r: QWord; begin -r:= dx.QWordValue or dy.QWordValue; + r:= dx.QWordValue or dy.QWordValue; -if r < $10000 then - begin - Distance.QWordValue:= r; - Distance.isNegative:= false - end else - Distance:= hwSqrt(hwSqr(dx) + hwSqr(dy)) + if r < $10000 then + begin + Distance.QWordValue:= r; + Distance.isNegative:= false + end + else + Distance:= hwSqrt(hwSqr(dx) + hwSqr(dy)) end; function DistanceI(const dx, dy: LongInt): hwFloat; begin -DistanceI:= hwSqrt(int2hwFloat(sqr(dx) + sqr(dy))) + DistanceI:= hwSqrt(int2hwFloat(sqr(dx) + sqr(dy))) end; function SignAs(const num, signum: hwFloat): hwFloat; begin -SignAs.QWordValue:= num.QWordValue; -SignAs.isNegative:= signum.isNegative + SignAs.QWordValue:= num.QWordValue; + SignAs.isNegative:= signum.isNegative end; function hwSign(r: hwFloat): LongInt; @@ -549,6 +535,4 @@ vector2Angle:= c end; -{$ENDIF} - end. diff -r 31570b766315 -r ed5a6478e710 hedgewars/uGame.pas --- a/hedgewars/uGame.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uGame.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} @@ -27,12 +27,12 @@ implementation //////////////////// uses uInputHandler, uTeams, uIO, uAI, uGears, uSound, uLocale, uCaptions, - uTypes, uVariables, uCommands, uConsts, uVisualGearsList + uTypes, uVariables, uCommands, uConsts, uVisualGearsList, uUtils {$IFDEF USE_TOUCH_INTERFACE}, uTouch{$ENDIF}; procedure DoGameTick(Lag: LongInt); var i,j : LongInt; - s: shortstring; + s: ansistring; begin if isPaused then exit; @@ -64,6 +64,10 @@ else if cOnlyStats then Lag:= High(LongInt) end; + +if cTestLua then + Lag:= High(LongInt); + inc(SoundTimerTicks, Lag); if SoundTimerTicks >= 50 then begin @@ -76,8 +80,8 @@ AddCaption(trmsg[sidMute], cWhiteColor, capgrpVolume) else if not isAudioMuted then begin - str(i, s); - AddCaption(Format(trmsg[sidVolume], s), cWhiteColor, capgrpVolume) + s:= ansistring(inttostr(i)); + AddCaption(FormatA(trmsg[sidVolume], s), cWhiteColor, capgrpVolume) end end; end; @@ -98,11 +102,13 @@ if isInLag then case GameType of gmtNet: begin - // just update the health bars + // update health bars and the wind indicator AddVisualGear(0, 0, vgtTeamHealthSorter); + AddVisualGear(0, 0, vgtSmoothWindBar); break; end; gmtDemo, gmtRecord: begin + AddFileLog('End of input, halting now'); GameState:= gsExit; exit end; @@ -116,9 +122,11 @@ AddVisualGear(0, 0, vgtTeamHealthSorter); AddVisualGear(0, 0, vgtSmoothWindBar); {$IFDEF IPHONEOS}InitIPC;{$ENDIF} + {$IFNDEF PAS2C} with mobileRecord do if SaveLoadingEnded <> nil then SaveLoadingEnded(); + {$ENDIF} end; end else ProcessGears diff -r 31570b766315 -r ed5a6478e710 hedgewars/uGears.pas --- a/hedgewars/uGears.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uGears.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} @@ -33,7 +33,7 @@ * effects are called "Visual Gears" and defined in the respective unit! *) interface -uses uConsts, uFloat, uTypes, uChat; +uses uConsts, uFloat, uTypes, uChat, uCollisions; procedure initModule; procedure freeModule; @@ -51,7 +51,7 @@ uses uStore, uSound, uTeams, uRandom, uIO, uLandGraphics, {$IFDEF USE_TOUCH_INTERFACE}uTouch,{$ENDIF} uLocale, uAmmos, uStats, uVisualGears, uScript, uVariables, - uCommands, uUtils, uTextures, uRenderUtils, uGearsRender, uCaptions, uDebug, uLandTexture, + uCommands, uUtils, uTextures, uRenderUtils, uGearsRender, uCaptions, uDebug, uGearsHedgehog, uGearsUtils, uGearsList, uGearsHandlersRope , uVisualGearsList, uGearsHandlersMess, uAI; @@ -127,7 +127,7 @@ tmp:= 0; if Gear^.Hedgehog^.Effects[hePoisoned] <> 0 then begin - inc(tmp, ModifyDamage(5, Gear)); + inc(tmp, ModifyDamage(Gear^.Hedgehog^.Effects[hePoisoned], Gear)); if (GameFlags and gfResetHealth) <> 0 then dec(Gear^.Hedgehog^.InitialHealth) // does not need a minimum check since <= 1 basically disables it end; @@ -166,7 +166,7 @@ procedure ProcessGears; var t: PGear; i, AliveCount: LongInt; - s: shortstring; + s: ansistring; prevtime: LongWord; begin prevtime:= TurnTimeLeft; @@ -215,8 +215,8 @@ begin if curHandledGear^.RenderTimer and (curHandledGear^.Timer > 500) and ((curHandledGear^.Timer mod 1000) = 0) then begin - FreeTexture(curHandledGear^.Tex); - curHandledGear^.Tex:= RenderStringTex(inttostr(curHandledGear^.Timer div 1000), cWhiteColor, fntSmall); + FreeAndNilTexture(curHandledGear^.Tex); + curHandledGear^.Tex:= RenderStringTex(ansistring(inttostr(curHandledGear^.Timer div 1000)), cWhiteColor, fntSmall); end; curHandledGear^.doStep(curHandledGear); // might be useful later @@ -320,20 +320,21 @@ Ammoz[amTardis].Probability:= 0; end; AddCaption(trmsg[sidSuddenDeath], cWhiteColor, capgrpGameState); + ScriptCall('onSuddenDeath'); playSound(sndSuddenDeath); - StopMusic //No SDMusic for now - //ChangeMusic(SDMusic) - end - else if (TotalRounds < cSuddenDTurns) and (not isInMultiShoot) then - begin - i:= cSuddenDTurns - TotalRounds; - s:= inttostr(i); - if i = 1 then - AddCaption(trmsg[sidRoundSD], cWhiteColor, capgrpGameState) - else if (i = 2) or ((i > 0) and ((i mod 50 = 0) or ((i <= 25) and (i mod 5 = 0)))) then - AddCaption(Format(trmsg[sidRoundsSD], s), cWhiteColor, capgrpGameState); - end; + StopMusic; + if SDMusicFN <> '' then PlayMusic + end + else if (TotalRounds < cSuddenDTurns) and (not isInMultiShoot) then + begin + i:= cSuddenDTurns - TotalRounds; + s:= ansistring(inttostr(i)); + if i = 1 then + AddCaption(trmsg[sidRoundSD], cWhiteColor, capgrpGameState) + else if (i = 2) or ((i > 0) and ((i mod 50 = 0) or ((i <= 25) and (i mod 5 = 0)))) then + AddCaption(FormatA(trmsg[sidRoundsSD], s), cWhiteColor, capgrpGameState); end; + end; if bBetweenTurns or isInMultiShoot or (TotalRounds = -1) then @@ -394,7 +395,7 @@ if (CurrentHedgehog^.Gear^.State and gstAttacked <> 0) and (Ammoz[CurrentHedgehog^.CurAmmoType].Ammo.Propz and ammoprop_NeedTarget <> 0) then begin - CurrentHedgehog^.Gear^.State:= CurrentHedgehog^.Gear^.State or gstHHChooseTarget; + CurrentHedgehog^.Gear^.State:= CurrentHedgehog^.Gear^.State or gstChooseTarget; isCursorVisible := true end; CurrentHedgehog^.Gear^.State:= CurrentHedgehog^.Gear^.State and (not gstAttacked); @@ -425,7 +426,7 @@ if CurrentHedgehog^.Gear <> nil then if (((CurrentHedgehog^.Gear^.State and gstAttacking) = 0) or (Ammoz[CurrentHedgehog^.CurAmmoType].Ammo.Propz and ammoprop_DoesntStopTimerWhileAttacking <> 0)) - and not(isInMultiShoot and ((Ammoz[CurrentHedgehog^.CurAmmoType].Ammo.Propz and ammoprop_DoesntStopTimerInMultiShoot) <> 0)) then + and (not(isInMultiShoot and ((Ammoz[CurrentHedgehog^.CurAmmoType].Ammo.Propz and ammoprop_DoesntStopTimerInMultiShoot) <> 0))) then //(CurrentHedgehog^.CurAmmoType in [amShotgun, amDEagle, amSniperRifle]) begin if (TurnTimeLeft = 5000) @@ -462,7 +463,10 @@ end; if (not CurrentTeam^.ExtDriven) or CurrentTeam^.hasGone then + begin + AddFileLog('hiTicks increment (current team is local or gone)'); inc(hiTicks) // we do not recieve a message for this + end end; AddRandomness(CheckSum); TurnClockActive:= prevtime <> TurnTimeLeft; @@ -548,6 +552,9 @@ end; Gear:= Gear^.NextGear end; + +if SpeechHogNumber > 0 then + DrawHHOrder(); end; procedure FreeGearsList; @@ -564,29 +571,106 @@ end; procedure AddMiscGears; -var p,i,j,rx, ry: Longword; +var p,i,j,t,h,unplaced: Longword; + rx, ry: LongInt; rdx, rdy: hwFloat; Gear: PGear; begin AddGear(0, 0, gtATStartGame, 0, _0, _0, 2000); i:= 0; -Gear:= PGear(1); -while (i < cLandMines) {and (Gear <> nil)} do // disable this check until better solution found +unplaced:= 0; +while (i < cLandMines) and (unplaced < 4) do begin Gear:= AddGear(0, 0, gtMine, 0, _0, _0, 0); FindPlace(Gear, false, 0, LAND_WIDTH); + + if Gear = nil then + inc(unplaced) + else + unplaced:= 0; + + inc(i) + end; + +i:= 0; +unplaced:= 0; +while (i < cExplosives) and (unplaced < 4) do + begin + Gear:= AddGear(0, 0, gtExplosives, 0, _0, _0, 0); + FindPlace(Gear, false, 0, LAND_WIDTH); + + if Gear = nil then + inc(unplaced) + else + unplaced:= 0; + inc(i) end; i:= 0; -Gear:= PGear(1); -while (i < cExplosives){ and (Gear <> nil)} do +j:= 0; +p:= 0; // 0 searching, 1 bad position, 2 added. +unplaced:= 0; +if cAirMines > 0 then + Gear:= AddGear(0, 0, gtAirMine, 0, _0, _0, 0); +while (i < cAirMines) and (j < 1000*cAirMines) do begin - Gear:= AddGear(0, 0, gtExplosives, 0, _0, _0, 0); - FindPlace(Gear, false, 0, LAND_WIDTH); - inc(i) + p:= 0; + if hasBorder then + begin + rx:= leftX+GetRandom(rightX-leftX-16)+8; + ry:= topY+GetRandom(LAND_HEIGHT-topY-16)+8 + end + else + begin + rx:= leftX+GetRandom(rightX-leftX+400)-200; + ry:= topY+GetRandom(LAND_HEIGHT-topY+400)-200 + end; + Gear^.X:= int2hwFloat(rx); + Gear^.Y:= int2hwFloat(ry); + if CheckLandValue(rx, ry, $FFFF) and + (TestCollisionYwithGear(Gear,-1) = 0) and + (TestCollisionXwithGear(Gear, 1) = 0) and + (TestCollisionXwithGear(Gear,-1) = 0) and + (TestCollisionYwithGear(Gear, 1) = 0) then + begin + t:= 0; + while (t < TeamsCount) and (p = 0) do + begin + h:= 0; + with TeamsArray[t]^ do + while (h < cMaxHHIndex) and (p = 0) do + begin + if (Hedgehogs[h].Gear <> nil) then + begin + rdx:=Gear^.X-Hedgehogs[h].Gear^.X; + rdy:=Gear^.Y-Hedgehogs[h].Gear^.Y; + if (Gear^.Angle < $FFFFFFFF) and + ((rdx.Round+rdy.Round < Gear^.Angle) and + (hwRound(hwSqr(rdx) + hwSqr(rdy)) < sqr(Gear^.Angle))) then + begin +// Debug line. Remove later +// AddFileLog('Too Close to Hog @ (' + inttostr(rx) + ',' + inttostr(ry) + ')'); + + p:= 1 + end + end; + inc(h) + end; + inc(t) + end; + if p = 0 then + begin + inc(i); + AddFileLog('Placed Air Mine @ (' + inttostr(rx) + ',' + inttostr(ry) + ')'); + if i < cAirMines then + Gear:= AddGear(0, 0, gtAirMine, 0, _0, _0, 0) + end + end; + inc(j) end; +if p <> 0 then DeleteGear(Gear); if (GameFlags and gfLowGravity) <> 0 then begin @@ -626,7 +710,11 @@ if (not hasBorder) and cSnow then for i:= vobCount * Longword(max(LAND_WIDTH,4096)) div 2048 downto 1 do - AddGear(LongInt(GetRandom(snowRight - snowLeft)) + snowLeft, LAND_HEIGHT + LongInt(GetRandom(750)) - 1300, gtFlake, 0, _0, _0, 0); + begin + rx:=GetRandom(snowRight - snowLeft); + ry:=GetRandom(750); + AddGear(rx + snowLeft, LongInt(LAND_HEIGHT) + ry - 1300, gtFlake, 0, _0, _0, 0) + end end; procedure AssignHHCoords; @@ -636,7 +724,7 @@ begin if (GameFlags and gfPlaceHog) <> 0 then PlacingHogs:= true; -if (GameFlags and gfDivideTeams) <> 0 then +if (ClansCount = 2) and ((GameFlags and gfDivideTeams) <> 0) then begin t:= 0; TryDo(ClansCount = 2, 'More or less than 2 clans on map in divided teams mode!', true); @@ -729,6 +817,8 @@ HealthCrate: begin FollowGear^.Pos := posCaseHealth; + // health crate is smaller than the other crates + FollowGear^.Radius := cCaseHealthRadius; FollowGear^.Health := content; AddCaption(GetEventString(eidNewHealthPack), cWhiteColor, capgrpAmmoInfo); end; @@ -767,6 +857,8 @@ HealthCrate: begin FollowGear^.Pos := FollowGear^.Pos + posCaseHealth; + // health crate is smaller than the other crates + FollowGear^.Radius := cCaseHealthRadius; AddCaption(GetEventString(eidNewHealthPack), cWhiteColor, capgrpAmmoInfo); end; AmmoCrate: @@ -837,6 +929,8 @@ t:= byte(s[2]); // team if Length(s) > 2 then h:= byte(s[3]) // target hog + else + h:= 0 end; // allow targetting a hog by specifying a number as the first portion of the text if (x < 4) and (h > byte('0')) and (h < byte('9')) then @@ -847,6 +941,8 @@ text:= copy(s, 3, Length(s) - 1) else text:= copy(s, 2, Length(s) - 1); + if text = '' then text:= '...'; + (* if CheckNoTeamOrHH then begin @@ -886,7 +982,7 @@ Gear^.FrameTicks:= x end; //ParseCommand('/say [' + hh^.Name + '] '+text, true) - AddChatString(#1+'[' + HH^.Name + '] '+text); + AddChatString(#9+'[' + HH^.Name + '] '+text); end end else if (x >= 4) then @@ -902,6 +998,7 @@ @doStepHedgehog, @doStepMine, @doStepCase, + @doStepAirMine, @doStepCase, @doStepBomb, @doStepShell, diff -r 31570b766315 -r ed5a6478e710 hedgewars/uGearsHandlers.pas --- a/hedgewars/uGearsHandlers.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uGearsHandlers.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} @@ -23,7 +23,7 @@ uses uTypes; -procedure cakeStep(Gear: PGear); +function cakeStep(Gear: PGear): boolean; implementation @@ -31,19 +31,24 @@ -const dirs: array[0..3] of TPoint = ((X: 0; Y: -1), (X: 1; Y: 0),(X: 0; Y: 1),(X: -1; Y: 0)); +const dirs: array[0..3] of TPoint = ((x: 0; y: -1), + (x: 1; y: 0), + (x: 0; y: 1), + (x: -1; y: 0)); procedure PrevAngle(Gear: PGear; dA: LongInt); inline; begin + inc(Gear^.WDTimer); Gear^.Angle := (LongInt(Gear^.Angle) - dA) and 3 end; procedure NextAngle(Gear: PGear; dA: LongInt); inline; begin + inc(Gear^.WDTimer); Gear^.Angle := (LongInt(Gear^.Angle) + dA) and 3 end; -procedure cakeStep(Gear: PGear); +function cakeStep(Gear: PGear): boolean; var xx, yy, xxn, yyn: LongInt; dA: LongInt; @@ -57,30 +62,40 @@ if (xx = 0) then if TestCollisionYwithGear(Gear, yy) <> 0 then PrevAngle(Gear, dA) - else - begin - Gear^.Tag := 0; - Gear^.Y := Gear^.Y + int2hwFloat(yy); - if TestCollisionXwithGear(Gear, xxn) = 0 then + else begin - Gear^.X := Gear^.X + int2hwFloat(xxn); - NextAngle(Gear, dA) + Gear^.Tag := 0; + + if TestCollisionXwithGear(Gear, xxn) <> 0 then + Gear^.WDTimer:= 0; + + Gear^.Y := Gear^.Y + int2hwFloat(yy); + if TestCollisionXwithGear(Gear, xxn) = 0 then + begin + Gear^.X := Gear^.X + int2hwFloat(xxn); + NextAngle(Gear, dA) + end end; - end; if (yy = 0) then if TestCollisionXwithGear(Gear, xx) <> 0 then PrevAngle(Gear, dA) - else - begin - Gear^.Tag := 0; - Gear^.X := Gear^.X + int2hwFloat(xx); - if TestCollisionYwithGear(Gear, yyn) = 0 then + else begin - Gear^.Y := Gear^.Y + int2hwFloat(yyn); - NextAngle(Gear, dA) + Gear^.Tag := 0; + + if TestCollisionYwithGear(Gear, yyn) <> 0 then + Gear^.WDTimer:= 0; + + Gear^.X := Gear^.X + int2hwFloat(xx); + if TestCollisionYwithGear(Gear, yyn) = 0 then + begin + Gear^.Y := Gear^.Y + int2hwFloat(yyn); + NextAngle(Gear, dA) + end end; - end; + + cakeStep:= Gear^.WDTimer < 4 end; end. diff -r 31570b766315 -r ed5a6478e710 hedgewars/uGearsHandlersMess.pas --- a/hedgewars/uGearsHandlersMess.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uGearsHandlersMess.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) (* @@ -24,7 +24,7 @@ * should NOT occur! * Use safe functions and data types! (e.g. GetRandom() and hwFloat) *) - + {$INCLUDE "options.inc"} unit uGearsHandlersMess; @@ -57,6 +57,7 @@ procedure doStepBlowTorchWork(Gear: PGear); procedure doStepBlowTorch(Gear: PGear); procedure doStepMine(Gear: PGear); +procedure doStepAirMine(Gear: PGear); procedure doStepSMine(Gear: PGear); procedure doStepDynamite(Gear: PGear); procedure doStepRollingBarrel(Gear: PGear); @@ -208,7 +209,7 @@ if (gi^.Kind = gtHedgehog) then begin d := r - hwRound(Distance(gi^.X - x, gi^.Y - y)); - if (d > 1) and ((gi^.Hedgehog^.Effects[heInvulnerable] = 0)) and (GetRandom(2) = 0) then + if (d > 1) and (gi^.Hedgehog^.Effects[heInvulnerable] = 0) and (GetRandom(2) = 0) then begin if (CurrentHedgehog^.Gear = gi) then PlaySoundV(sndOops, gi^.Hedgehog^.Team^.voicepack) @@ -258,22 +259,49 @@ //////////////////////////////////////////////////////////////////////////////// procedure doStepDrowningGear(Gear: PGear); +var i, d: LongInt; + bubble: PVisualGear; +begin +if Gear^.Timer = 0 then begin - AllInactive := false; - Gear^.Y := Gear^.Y + cDrownSpeed; + d:= 2 * Gear^.Radius; + for i:= (Gear^.Radius * Gear^.Radius) div 4 downto 0 do + begin + bubble := AddVisualGear(hwRound(Gear^.X) - Gear^.Radius + random(d), hwRound(Gear^.Y) - Gear^.Radius + random(d), vgtBubble); + if bubble <> nil then + bubble^.dY:= 0.1 + random(20)/10; + end; + DeleteGear(Gear); + exit; + end; + +AllInactive := false; +dec(Gear^.Timer); + +Gear^.Y := Gear^.Y + cDrownSpeed; + +if cWaterLine > hwRound(Gear^.Y) + Gear^.Radius then + begin + if LongInt(leftX) + Gear^.Radius > hwRound(Gear^.X) then + Gear^.X := Gear^.X - cDrownSpeed + else + Gear^.X := Gear^.X + cDrownSpeed; + end +else Gear^.X := Gear^.X + Gear^.dX * cDrownSpeed; - // Create some bubbles (0.5% might be better but causes too few bubbles sometimes) - if ((not SuddenDeathDmg and (WaterOpacity < $FF)) - or (SuddenDeathDmg and (SDWaterOpacity < $FF))) and ((GameTicks and $1F) = 0) then - if (Gear^.Kind = gtHedgehog) and (Random(4) = 0) then - AddVisualGear(hwRound(Gear^.X) - Gear^.Radius, hwRound(Gear^.Y) - Gear^.Radius, vgtBubble) - else if Random(12) = 0 then - AddVisualGear(hwRound(Gear^.X) - Gear^.Radius, hwRound(Gear^.Y) - Gear^.Radius, vgtBubble); - if (not SuddenDeathDmg and (WaterOpacity > $FE)) - or (SuddenDeathDmg and (SDWaterOpacity > $FE)) - or (hwRound(Gear^.Y) > Gear^.Radius + cWaterLine + cVisibleWater) then - DeleteGear(Gear); - end; + +// Create some bubbles (0.5% might be better but causes too few bubbles sometimes) +if ((not SuddenDeathDmg and (WaterOpacity < $FF)) +or (SuddenDeathDmg and (SDWaterOpacity < $FF))) and ((GameTicks and $1F) = 0) then + if (Gear^.Kind = gtHedgehog) and (Random(4) = 0) then + AddVisualGear(hwRound(Gear^.X) - Gear^.Radius, hwRound(Gear^.Y) - Gear^.Radius, vgtBubble) +else if Random(12) = 0 then + AddVisualGear(hwRound(Gear^.X) - Gear^.Radius, hwRound(Gear^.Y) - Gear^.Radius, vgtBubble); +if (not SuddenDeathDmg and (WaterOpacity > $FE)) +or (SuddenDeathDmg and (SDWaterOpacity > $FE)) +or (hwRound(Gear^.Y) > Gear^.Radius + cWaterLine + cVisibleWater) then + DeleteGear(Gear); +end; //////////////////////////////////////////////////////////////////////////////// procedure doStepFallingGear(Gear: PGear); @@ -283,7 +311,6 @@ tX, tdX, tdY: hwFloat; collV, collH, gX, gY: LongInt; land, xland: word; - boing: PVisualGear; begin tX:= Gear^.X; gX:= hwRound(Gear^.X); @@ -292,16 +319,16 @@ ((TestCollisionXwithGear(Gear, 1) <> 0) or (TestCollisionXwithGear(Gear, -1) <> 0)) then begin Gear^.X:= tX; - Gear^.dX.isNegative:= (gX > leftX+Gear^.Radius*2) + Gear^.dX.isNegative:= (gX > LongInt(leftX) + Gear^.Radius*2) end; // clip velocity at 2 - over 1 per pixel, but really shouldn't cause many actual problems. - if Gear^.dX.Round > 2 then + if Gear^.dX.Round > 1 then Gear^.dX.QWordValue:= 8589934592; - if Gear^.dY.Round > 2 then + if Gear^.dY.Round > 1 then Gear^.dY.QWordValue:= 8589934592; - if (Gear^.State and gstSubmersible <> 0) and (gY > cWaterLine) then + if (Gear^.State and gstSubmersible <> 0) and CheckCoordInWater(gX, gY) then begin Gear^.dX:= Gear^.dX * _0_999; Gear^.dY:= Gear^.dY * _0_999 @@ -320,8 +347,8 @@ if Gear^.dY.isNegative then begin - isFalling := true; land:= TestCollisionYwithGear(Gear, -1); + isFalling := land = 0; if land <> 0 then begin collV := -1; @@ -394,7 +421,7 @@ if xland <> 0 then collH := -hwSign(Gear^.dX) end; //if Gear^.AdvBounce and (collV <>0) and (collH <> 0) and (hwSqr(tdX) + hwSqr(tdY) > _0_08) then - if (collV <> 0) and (collH <> 0) and + if (collV <> 0) and (collH <> 0) and (((Gear^.AdvBounce=1) and ((collV=-1) or ((tdX.QWordValue + tdY.QWordValue) > _0_2.QWordValue)))) then //or ((xland or land) and lfBouncy <> 0)) then begin @@ -410,7 +437,26 @@ Gear^.dY := tdX*cElastic end; - Gear^.dY.isNegative := not tdY.isNegative; + Gear^.dX.isNegative:= tdX.isNegative; + Gear^.dY.isNegative:= tdY.isNegative; + if (collV > 0) and (collH > 0) and (not tdX.isNegative) and (not tdY.isNegative) then + begin + Gear^.dX.isNegative := true; + Gear^.dY.isNegative := true + end + else if (collV > 0) and (collH < 0) and (tdX.isNegative or tdY.isNegative) then + begin + Gear^.dY.isNegative := not tdY.isNegative; + if not tdY.isNegative then Gear^.dX.isNegative := false + end + else if (collV < 0) and (collH > 0) and (not tdX.isNegative) then + begin + Gear^.dX.isNegative := true; + Gear^.dY.isNegative := false + end + else if (collV < 0) and (collH < 0) and tdX.isNegative and tdY.isNegative then + Gear^.dX.isNegative := false; + isFalling := false; Gear^.AdvBounce := 10; end; @@ -420,10 +466,11 @@ if isFalling then begin - Gear^.dY := Gear^.dY + cGravity; + if Gear^.State and gstNoGravity = 0 then + Gear^.dY := Gear^.dY + cGravity; if (GameFlags and gfMoreWind) <> 0 then Gear^.dX := Gear^.dX + cWindSpeed / Gear^.Density - end; + end; Gear^.X := Gear^.X + Gear^.dX; Gear^.Y := Gear^.Y + Gear^.dY; @@ -435,25 +482,15 @@ Gear^.State := Gear^.State or gstMoving; if ((xland or land) and lfBouncy <> 0) and (Gear^.dX.QWordValue < _0_15.QWordValue) and (Gear^.dY.QWordValue < _0_15.QWordValue) then + begin Gear^.State := Gear^.State or gstCollision; - + AddFileLog('no more bounce for you!'); + end; + if ((xland or land) and lfBouncy <> 0) and (Gear^.Radius >= 3) and ((Gear^.dX.QWordValue > _0_15.QWordValue) or (Gear^.dY.QWordValue > _0_15.QWordValue)) then begin - boing:= AddVisualGear(gX, gY, vgtStraightShot, 0, false, 1); - if boing <> nil then - with boing^ do - begin - Angle:= random(360); - dx:= 0; - dy:= 0; - FrameTicks:= 200; - tX:= _0; - tX.QWordValue:= Gear^.dY.QWordValue + Gear^.dX.QWordValue; - Scale:= hwFloat2Float(Gear^.Density * tX) / 1.5; - State:= ord(sprBoing) - end; - PlaySound(sndMelonImpact, true) + AddBounceEffectForGear(Gear); end else if (Gear^.nImpactSounds > 0) and (Gear^.State and gstCollision <> 0) and @@ -673,11 +710,7 @@ or (Gear^.Kind = gtBall) then CalcRotationDirAngle(Gear) else if (GameTicks and $1F) = 0 then - begin - if hwRound(Gear^.Y) > cWaterLine then - AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtBubble) - else AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeTrace) - end + AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeTrace); end; //////////////////////////////////////////////////////////////////////////////// @@ -694,11 +727,7 @@ exit end; if (GameTicks and $3F) = 0 then - begin - if hwRound(Gear^.Y) > cWaterLine then - AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtBubble) - else AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeTrace) - end + AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeTrace); end; //////////////////////////////////////////////////////////////////////////////// @@ -758,9 +787,9 @@ draw:= true; xx:= hwRound(Gear^.X); yy:= hwRound(Gear^.Y); - if draw and (WorldEdge = weWrap) and ((xx < leftX+3) or (xx > rightX-3)) then - begin - if xx < leftX+3 then + if draw and (WorldEdge = weWrap) and ((xx < LongInt(leftX) + 3) or (xx > LongInt(rightX) - 3)) then + begin + if xx < LongInt(leftX) + 3 then xx:= rightX-3 else xx:= leftX+3; Gear^.X:= int2hwFloat(xx) @@ -795,10 +824,12 @@ end; *) // move back to cloud layer - if yy > cWaterLine then + if CheckCoordInWater(xx, yy) then move:= true else if (xx > snowRight) or (xx < snowLeft) then move:=true + else if (cGravity < _0) and (yy < LAND_HEIGHT-1200) then + move:=true // Solid pixel encountered else if ((yy and LAND_HEIGHT_MASK) = 0) and ((xx and LAND_WIDTH_MASK) = 0) and (Land[yy, xx] <> 0) then begin @@ -877,12 +908,15 @@ end else Land[ly, lx]:= lf; if gun then - LandPixels[ry, rx]:= (ExplosionBorderColor and (not AMask)) or (p^[px] and AMask) + LandPixels[ry, rx]:= (Gear^.Tint shr 24 shl RShift) or + (Gear^.Tint shr 16 and $FF shl GShift) or + (Gear^.Tint shr 8 and $FF shl BShift) or + (p^[px] and AMask) else LandPixels[ry, rx]:= addBgColor(LandPixels[ry, rx], p^[px]); end else allpx:= false end; - p:= @(p^[s^.pitch shr 2]) + p:= PLongWordArray(@(p^[s^.pitch shr 2])) end; // Why is this here. For one thing, there's no test on +1 being safe. @@ -912,7 +946,9 @@ end; Gear^.Pos:= 0; Gear^.X:= int2hwFloat(LongInt(GetRandom(snowRight - snowLeft)) + snowLeft); - Gear^.Y:= int2hwFloat(LAND_HEIGHT + LongInt(GetRandom(50)) - 1325); + if (cGravity < _0) and (yy < LAND_HEIGHT-1200) then + Gear^.Y:= int2hwFloat(LAND_HEIGHT - 50 - LongInt(GetRandom(50))) + else Gear^.Y:= int2hwFloat(LAND_HEIGHT + LongInt(GetRandom(50)) - 1250); Gear^.State:= Gear^.State or gstInvisible; end end; @@ -934,16 +970,16 @@ if not Gear^.dY.isNegative then if TestCollisionY(Gear, 1) <> 0 then - begin + begin Gear^.dY := - Gear^.dY * Gear^.Elasticity; if Gear^.dY > - _1div1024 then - begin + begin Gear^.Active := false; exit - end + end else if Gear^.dY < - _0_03 then PlaySound(Gear^.ImpactSound) - end; + end; Gear^.Y := Gear^.Y + Gear^.dY; CheckGearDrowning(Gear); @@ -964,16 +1000,13 @@ gX := hwRound(Gear^.X); gY := hwRound(Gear^.Y); uw := (Gear^.Tag <> 0); // was bee underwater last tick? - nuw := (cWaterLine < gy + Gear^.Radius); // is bee underwater now? + nuw := CheckCoordInWater(gx, gy + Gear^.Radius); // is bee underwater now? // if water entered or left if nuw <> uw then begin - AddVisualGear(gX, cWaterLine, vgtSplash); - AddVisualGear(gX - 3 + Random(6), cWaterLine, vgtDroplet); - AddVisualGear(gX - 3 + Random(6), cWaterLine, vgtDroplet); - AddVisualGear(gX - 3 + Random(6), cWaterLine, vgtDroplet); - AddVisualGear(gX - 3 + Random(6), cWaterLine, vgtDroplet); + if Gear^.Timer <> 5000 then + AddSplashForGear(Gear, false); StopSoundChan(Gear^.SoundChannel); if nuw then begin @@ -1001,12 +1034,8 @@ if (GameTicks and $F) = 0 then begin if (GameTicks and $30) = 0 then - begin - if nuw then - AddVisualGear(gX, gY, vgtBubble) - else - AddVisualGear(gX, gY, vgtBeeTrace); - end; + AddVisualGear(gX, gY, vgtBeeTrace); + Gear^.dX := Gear^.Elasticity * (Gear^.dX + _0_000064 * (Gear^.Target.X - gX)); Gear^.dY := Gear^.Elasticity * (Gear^.dY + _0_000064 * (Gear^.Target.Y - gY)); // make sure new speed isn't higher than original one (which we stored in Friction variable) @@ -1044,6 +1073,7 @@ end; end; DeleteGear(Gear); + exit; end; if (Gear^.Timer > 0) then @@ -1054,7 +1084,7 @@ // no need to display remaining time anymore Gear^.RenderTimer:= false; // bee can drown when timer reached 0 - Gear^.State:= Gear^.State and not gstSubmersible; + Gear^.State:= Gear^.State and (not gstSubmersible); end; end; end; @@ -1064,7 +1094,9 @@ AllInactive := false; Gear^.X := Gear^.X + Gear^.dX; Gear^.Y := Gear^.Y + Gear^.dY; + WorldWrap(Gear); Gear^.dY := Gear^.dY + cGravity; + CheckGearDrowning(Gear); CheckCollision(Gear); if (Gear^.State and gstCollision) <> 0 then begin @@ -1189,7 +1221,7 @@ if (hwRound(Bullet^.X) and LAND_WIDTH_MASK <> 0) or (hwRound(Bullet^.Y) and LAND_HEIGHT_MASK <> 0) then // only extend if not under water - if hwRound(Bullet^.Y) < cWaterLine then + if not CheckCoordInWater(hwRound(Bullet^.X), hwRound(Bullet^.Y)) then begin VGear^.dX := VGear^.dX + max(LAND_WIDTH,4096) * (VGear^.dX - VGear^.X); VGear^.dY := VGear^.dY + max(LAND_WIDTH,4096) * (VGear^.dY - VGear^.Y); @@ -1235,7 +1267,7 @@ if ((y and LAND_HEIGHT_MASK) = 0) and ((x and LAND_WIDTH_MASK) = 0) and (Land[y, x] <> 0) then inc(Gear^.Damage); // let's interrupt before a collision to give portals a chance to catch the bullet - if (Gear^.Damage = 1) and (Gear^.Tag = 0) and not(CheckLandValue(x, y, lfLandMask)) then + if (Gear^.Damage = 1) and (Gear^.Tag = 0) and (not CheckLandValue(x, y, lfLandMask)) then begin Gear^.Tag := 1; Gear^.Damage := 0; @@ -1248,10 +1280,12 @@ Gear^.Tag := 0; if Gear^.Damage > 5 then + begin if Gear^.AmmoType = amDEagle then AmmoShove(Gear, 7, 20) - else - AmmoShove(Gear, Gear^.Timer, 20); + else + AmmoShove(Gear, Gear^.Timer, 20); + end; CheckGearDrowning(Gear); dec(i) until (i = 0) or (Gear^.Damage > Gear^.Health) or ((Gear^.State and gstDrowning) <> 0); @@ -1262,15 +1296,22 @@ dec(Gear^.Health, Gear^.Damage); Gear^.Damage := 0 end; - if ((Gear^.State and gstDrowning) <> 0) and (Gear^.Damage < Gear^.Health) and ((not SuddenDeathDmg and (WaterOpacity < $FF)) or (SuddenDeathDmg and (SDWaterOpacity < $FF))) then - begin - for i:=(Gear^.Health - Gear^.Damage) * 4 downto 0 do + + if ((Gear^.State and gstDrowning) <> 0) and (Gear^.Health > 0) then + begin + // draw bubbles + if (not SuddenDeathDmg and (WaterOpacity < $FF)) or (SuddenDeathDmg and (SDWaterOpacity < $FF)) then begin - if Random(6) = 0 then - AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtBubble); - Gear^.X := Gear^.X + Gear^.dX; - Gear^.Y := Gear^.Y + Gear^.dY; + for i:=(Gear^.Health * 4) downto 0 do + begin + if Random(6) = 0 then + AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtBubble); + Gear^.X := Gear^.X + Gear^.dX; + Gear^.Y := Gear^.Y + Gear^.dY; + end; end; + // bullet dies underwater + Gear^.Health:= 0; end; if (Gear^.Health <= 0) @@ -1283,7 +1324,7 @@ cArtillery := false; // Bullet Hit - if (hwRound(Gear^.X) and LAND_WIDTH_MASK = 0) and (hwRound(Gear^.Y) and LAND_HEIGHT_MASK = 0) then + if ((Gear^.State and gstDrowning) = 0) and (hwRound(Gear^.X) and LAND_WIDTH_MASK = 0) and (hwRound(Gear^.Y) and LAND_HEIGHT_MASK = 0) then begin VGear := AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtBulletHit); if VGear <> nil then @@ -1313,6 +1354,13 @@ begin cArtillery := true; HHGear := Gear^.Hedgehog^.Gear; + + if HHGear = nil then + begin + DeleteGear(gear); + exit + end; + HHGear^.State := HHGear^.State or gstNotKickable; HedgehogChAngle(HHGear); if not cLaserSighting then @@ -1357,6 +1405,7 @@ dec(TurnTimeLeft) else begin + HHGear^.State := HHGear^.State and (not gstNotKickable); DeleteGear(Gear); AfterAttack end; @@ -1456,6 +1505,11 @@ SetLittle(HHGear^.dX); HHGear^.dY := _0; end + else if Gear^.dY.isNegative and (TestCollisionYwithGear(HHGear, -1) <> 0) then + begin + Gear^.dY := cGravity; + HHGear^.dY := cGravity; + end else begin if CheckLandValue(hwRound(Gear^.X), hwRound(Gear^.Y + Gear^.dY + cGravity), lfLandMask) then @@ -1638,10 +1692,12 @@ Gear^.doStep := @doStepBlowTorchWork end; + //////////////////////////////////////////////////////////////////////////////// procedure doStepMine(Gear: PGear); var vg: PVisualGear; dxdy: hwFloat; + dmg: LongWord; begin if Gear^.Health = 0 then dxdy:= hwAbs(Gear^.dX)+hwAbs(Gear^.dY); if (Gear^.State and gstMoving) <> 0 then @@ -1662,7 +1718,11 @@ if (Gear^.Health = 0) then begin if (dxdy > _0_4) and (Gear^.State and gstCollision <> 0) then - inc(Gear^.Damage, hwRound(dxdy * _50)); + begin + dmg:= hwRound(dxdy * _50); + inc(Gear^.Damage, dmg); + ScriptCall('onGearDamage', Gear^.UID, dmg) + end; if ((GameTicks and $FF) = 0) and (Gear^.Damage > random(30)) then begin @@ -1721,6 +1781,176 @@ Gear^.State := Gear^.State or gsttmpFlag; end; +(* +Just keeping track for my own benefit. +Every second, locate new target. Clear if target radius has been set to 0 or no target in range. +Every... 16 milliseconds? Update vector to target. +*) + +procedure doStepAirMine(Gear: PGear); +var i,t,targDist,tmpDist: LongWord; + targ, tmpG: PGear; + trackSpeed, airFriction, tX, tY: hwFloat; + isUnderwater: Boolean; +begin + isUnderwater:= CheckCoordInWater(hwRound(Gear^.X), hwRound(Gear^.Y) + Gear^.Radius); + if Gear^.Pos > 0 then + begin + airFriction:= _1; + if isUnderwater then + dec(airFriction.QWordValue,Gear^.Pos*2) + else + dec(airFriction.QWordValue,Gear^.Pos); + Gear^.dX:= Gear^.dX*airFriction; + Gear^.dY:= Gear^.dY*airFriction + end; + doStepFallingGear(Gear); + if (TurnTimeLeft = 0) and ((Gear^.dX.QWordValue + Gear^.dY.QWordValue) > _0_02.QWordValue) then + AllInactive := false; + + if (TurnTimeLeft = 0) or (Gear^.Angle = 0) or (Gear^.Hedgehog = nil) or (Gear^.Hedgehog^.Gear = nil) then + begin + Gear^.Hedgehog:= nil; + targ:= nil; + end + else if Gear^.Hedgehog <> nil then + targ:= Gear^.Hedgehog^.Gear; + if targ <> nil then + begin + tX:=Gear^.X-targ^.X; + tY:=Gear^.Y-targ^.Y; + // allow escaping - should maybe flag this too + if (GameTicks > Gear^.FlightTime+10000) or + ((tX.Round+tY.Round > Gear^.Angle*6) and + (hwRound(hwSqr(tX) + hwSqr(tY)) > sqr(Gear^.Angle*6))) then + targ:= nil + end; + + // If in ready timer, or after turn, or in first 5 seconds of turn (really a window due to extra time utility) + // or mine is inactive due to lack of gsttmpflag or hunting is disabled due to seek radius of 0 + // then we aren't hunting + if (ReadyTimeLeft > 0) or (TurnTimeLeft = 0) or + ((TurnTimeLeft < cHedgehogTurnTime) and (cHedgehogTurnTime-TurnTimeLeft < 5000)) or + (Gear^.State and gsttmpFlag = 0) or + (Gear^.Angle = 0) then + gear^.State:= gear^.State and (not gstChooseTarget) + else if + // todo, allow not finding new target, set timeout on target retention + (Gear^.State and gstAttacking = 0) and + ((GameTicks and $FF) = 17) and + (GameTicks > Gear^.FlightTime) then // recheck hunted hog + begin + gear^.State:= gear^.State or gstChooseTarget; + if targ <> nil then + targDist:= Distance(Gear^.X-targ^.X,Gear^.Y-targ^.Y).Round + else targDist:= 0; + for t:= 0 to Pred(TeamsCount) do + with TeamsArray[t]^ do + for i:= 0 to cMaxHHIndex do + if Hedgehogs[i].Gear <> nil then + begin + tmpG:= Hedgehogs[i].Gear; + tX:=Gear^.X-tmpG^.X; + tY:=Gear^.Y-tmpG^.Y; + if (Gear^.Angle = $FFFFFFFF) or + ((tX.Round+tY.Round < Gear^.Angle) and + (hwRound(hwSqr(tX) + hwSqr(tY)) < sqr(Gear^.Angle))) then + begin + if targ <> nil then tmpDist:= Distance(tX,tY).Round; + if (targ = nil) or (tmpDist < targDist) then + begin + if targ = nil then targDist:= Distance(tX,tY).Round + else targDist:= tmpDist; + Gear^.Hedgehog:= @Hedgehogs[i]; + targ:= tmpG; + end + end + end; + if targ <> nil then Gear^.FlightTime:= GameTicks + 5000 + end; + if targ <> nil then + begin + trackSpeed:= _0; + if isUnderwater then + trackSpeed.QWordValue:= Gear^.Power div 2 + else + trackSpeed.QWordValue:= Gear^.Power; + if (Gear^.X < targ^.X) and (Gear^.dX < _0_1) then + Gear^.dX:= Gear^.dX+trackSpeed // please leave as an add. I like the effect + else if (Gear^.X > targ^.X) and (Gear^.dX > -_0_1) then + Gear^.dX:= Gear^.dX-trackSpeed; + if (Gear^.Y < targ^.Y) and (Gear^.dY < _0_1) then + Gear^.dY:= Gear^.dY+trackSpeed + else if (Gear^.Y > targ^.Y) and (Gear^.dY > -_0_1) then + Gear^.dY:= Gear^.dY-trackSpeed + end + else Gear^.Hedgehog:= nil; + + if ((Gear^.State and gsttmpFlag) <> 0) and (Gear^.Health <> 0) then + begin + if ((Gear^.State and gstAttacking) = 0) then + begin + if ((GameTicks and $1F) = 0) then + begin + if targ <> nil then + begin + tX:=Gear^.X-targ^.X; + tY:=Gear^.Y-targ^.Y; + if (tX.Round+tY.Round < Gear^.Karma) and + (hwRound(hwSqr(tX) + hwSqr(tY)) < sqr(Gear^.Karma)) then + Gear^.State := Gear^.State or gstAttacking + end + else if (Gear^.Angle > 0) and (CheckGearNear(Gear, gtHedgehog, Gear^.Karma, Gear^.Karma) <> nil) then + Gear^.State := Gear^.State or gstAttacking + end + end + else // gstAttacking <> 0 + begin + AllInactive := false; + if (Gear^.Timer and $FF) = 0 then + PlaySound(sndMineTick); + if Gear^.Timer = 0 then + begin + // recheck + if targ <> nil then + begin + tX:=Gear^.X-targ^.X; + tY:=Gear^.Y-targ^.Y; + if (tX.Round+tY.Round < Gear^.Karma) and + (hwRound(hwSqr(tX) + hwSqr(tY)) < sqr(Gear^.Karma)) then + begin + Gear^.Hedgehog:= CurrentHedgehog; + tmpG:= FollowGear; + doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Karma, Gear^.Hedgehog, EXPLAutoSound); + FollowGear:= tmpG; + DeleteGear(Gear); + exit + end + end + else if (Gear^.Angle > 0) and (CheckGearNear(Gear, gtHedgehog, Gear^.Karma, Gear^.Karma) <> nil) then + begin + Gear^.Hedgehog:= CurrentHedgehog; + doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Karma, Gear^.Hedgehog, EXPLAutoSound); + DeleteGear(Gear); + exit + end; + Gear^.State:= Gear^.State and (not gstAttacking); + Gear^.Timer:= Gear^.WDTimer + end; + if Gear^.Timer > 0 then + dec(Gear^.Timer); + end + end + else // gsttmpFlag = 0 + if (TurnTimeLeft = 0) + or ((GameFlags and gfInfAttack <> 0) and (GameTicks > Gear^.FlightTime)) + or (CurrentHedgehog^.Gear = nil) then + begin + Gear^.FlightTime:= GameTicks; + Gear^.State := Gear^.State or gsttmpFlag + end +end; + //////////////////////////////////////////////////////////////////////////////// procedure doStepSMine(Gear: PGear); var land: Word; @@ -1730,18 +1960,20 @@ if land = 0 then land:= TestCollisionYwithGear(Gear,-2); if land = 0 then land:= TestCollisionXwithGear(Gear,-2); if land = 0 then land:= TestCollisionYwithGear(Gear, 2); - if (land <> 0) and (land and lfBouncy = 0) then - begin - if (not isZero(Gear^.dX)) or (not isZero(Gear^.dY)) then + if (land <> 0) and ((land and lfBouncy = 0) or ((Gear^.State and gstMoving) = 0)) then + begin + if ((Gear^.State and gstMoving) <> 0) or (not isZero(Gear^.dX)) or (not isZero(Gear^.dY)) then begin PlaySound(sndRopeAttach); Gear^.dX:= _0; Gear^.dY:= _0; + Gear^.State:= Gear^.State and (not gstMoving); AddCI(Gear); end; end else begin + Gear^.State:= Gear^.State or gstMoving; DeleteCI(Gear); doStepFallingGear(Gear); AllInactive := false; @@ -1772,7 +2004,7 @@ end end else // gsttmpFlag = 0 - if ((GameFlags and gfInfAttack = 0) and ((TurnTimeLeft = 0) or (Gear^.Hedgehog^.Gear = nil))) + if ((GameFlags and gfInfAttack = 0) and ((TurnTimeLeft = 0) or (Gear^.Hedgehog^.Gear = nil))) or ((GameFlags and gfInfAttack <> 0) and (GameTicks > Gear^.FlightTime)) then Gear^.State := Gear^.State or gsttmpFlag; end; @@ -1799,14 +2031,14 @@ procedure doStepRollingBarrel(Gear: PGear); var - i: LongInt; + i, dmg: LongInt; particle: PVisualGear; dxdy: hwFloat; begin - if (Gear^.dY.QWordValue = 0) and (Gear^.dY.QWordValue = 0) and (TestCollisionYwithGear(Gear, 1) = 0) then + if (Gear^.dX.QWordValue = 0) and (Gear^.dY.QWordValue = 0) and (TestCollisionYwithGear(Gear, 1) = 0) then SetLittle(Gear^.dY); Gear^.State := Gear^.State or gstAnimation; - if Gear^.Health < cBarrelHealth then Gear^.State:= Gear^.State and not gstFrozen; + if Gear^.Health < cBarrelHealth then Gear^.State:= Gear^.State and (not gstFrozen); if ((Gear^.dX.QWordValue <> 0) or (Gear^.dY.QWordValue <> 0)) then @@ -1827,7 +2059,9 @@ particle^.dX := particle^.dX + (Gear^.dX.QWordValue / 21474836480) end end; - inc(Gear^.Damage, hwRound(dxdy * _50)) + dmg:= hwRound(dxdy * _50); + inc(Gear^.Damage, dmg); + ScriptCall('onGearDamage', Gear^.UID, dmg) end; CalcRotationDirAngle(Gear); //CheckGearDrowning(Gear) @@ -1892,7 +2126,7 @@ Gear^.Message := Gear^.Message and (not (gmLJump or gmHJump)); exit end; - if (k = gtExplosives) and (Gear^.Health < cBarrelHealth) then Gear^.State:= Gear^.State and not gstFrozen; + if (k = gtExplosives) and (Gear^.Health < cBarrelHealth) then Gear^.State:= Gear^.State and (not gstFrozen); if ((k <> gtExplosives) and (Gear^.Damage > 0)) or ((k = gtExplosives) and (Gear^.Health<=0)) then begin @@ -1999,10 +2233,10 @@ Gear^.dY := Gear^.dY + cGravity; - if (Gear^.dY.isNegative) and (TestCollisionYwithGear(Gear, -1) <> 0) then - Gear^.dY := _0; - - Gear^.Y := Gear^.Y + Gear^.dY; + if ((not Gear^.dY.isNegative) and (TestCollisionYwithGear(Gear, 1) <> 0)) or + (Gear^.dY.isNegative and (TestCollisionYwithGear(Gear, -1) <> 0)) then + Gear^.dY := _0 + else Gear^.Y := Gear^.Y + Gear^.dY; if (not Gear^.dY.isNegative) and (Gear^.dY > _0_001) then SetAllHHToActive(false); @@ -2116,10 +2350,11 @@ gX,gY,i: LongInt; sticky: Boolean; vgt: PVisualGear; - tdX,tdY: HWFloat; + tdX,tdY, f: HWFloat; landPixel: Word; begin WorldWrap(Gear); + if Gear^.FlightTime > 0 then dec(Gear^.FlightTime); sticky:= (Gear^.State and gsttmpFlag) <> 0; if not sticky then AllInactive := false; @@ -2128,6 +2363,21 @@ begin AllInactive := false; + if (GameTicks and $F = 0) and (Gear^.FlightTime = 0) then + begin + Gear^.Radius := 7; + tdX:= Gear^.dX; + tdY:= Gear^.dY; + Gear^.dX.QWordValue:= 120000000; + Gear^.dY.QWordValue:= 429496730; + Gear^.dX.isNegative:= getrandom(2)<>1; + Gear^.dY.isNegative:= true; + AmmoShove(Gear, 2, 125); + Gear^.dX:= tdX; + Gear^.dY:= tdY; + Gear^.Radius := 1 + end; + if ((GameTicks mod 100) = 0) then begin vgt:= AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtFire, gstTmpFlag); @@ -2139,31 +2389,43 @@ end; end; - - if Gear^.dX.QWordValue > _0_01.QWordValue then - Gear^.dX := Gear^.dX * _0_995; - - Gear^.dY := Gear^.dY + cGravity; - // if sticky then Gear^.dY := Gear^.dY + cGravity; - - if Gear^.dY.QWordValue > _0_2.QWordValue then - Gear^.dY := Gear^.dY * _0_995; - - //if sticky then Gear^.X := Gear^.X + Gear^.dX else - Gear^.X := Gear^.X + Gear^.dX + cWindSpeed * 640; - Gear^.Y := Gear^.Y + Gear^.dY; - - if (hwRound(Gear^.Y) > cWaterLine) then + if (Gear^.dX.QWordValue > _2.QWordValue) + or (Gear^.dY.QWordValue > _2.QWordValue) + then + begin + // norm speed vector to length of 2 for fire particles to keep flying in the same direction + f:= _1_9 / Distance(Gear^.dX, Gear^.dY); + Gear^.dX:= Gear^.dX * f; + Gear^.dY:= Gear^.dY * f; + end + else begin + if Gear^.dX.QWordValue > _0_01.QWordValue then + Gear^.dX := Gear^.dX * _0_995; + + Gear^.dY := Gear^.dY + cGravity; + // if sticky then Gear^.dY := Gear^.dY + cGravity; + + if Gear^.dY.QWordValue > _0_2.QWordValue then + Gear^.dY := Gear^.dY * _0_995; + + //if sticky then Gear^.X := Gear^.X + Gear^.dX else + Gear^.X := Gear^.X + Gear^.dX + cWindSpeed * 640; + Gear^.Y := Gear^.Y + Gear^.dY; + end; + + gX := hwRound(Gear^.X); + gY := hwRound(Gear^.Y); + + if CheckCoordInWater(gX, gY) then begin - gX := hwRound(Gear^.X); for i:= 0 to 3 do - AddVisualGear(gX - 16 + Random(32), cWaterLine - 16 + Random(16), vgtSteam); + AddVisualGear(gX - 8 + Random(16), gY - 8 + Random(16), vgtSteam); PlaySound(sndVaporize); DeleteGear(Gear); exit end end - else + else begin if (Gear^.Timer = 1) and (GameTicks and $3 = 0) then begin @@ -2171,7 +2433,7 @@ if (landPixel and lfIce <> 0) or (TestCollisionYwithGear(Gear, 1) and lfIce <> 0) then begin gX := hwRound(Gear^.X); - gY := hwRound(Gear^.Y)-6; + gY := hwRound(Gear^.Y) - 6; DrawExplosion(gX, gY, 4); PlaySound(sndVaporize); AddVisualGear(gX - 3 + Random(6), gY - 2, vgtSteam); @@ -2230,7 +2492,7 @@ if Gear^.Health > 0 then dec(Gear^.Health); - Gear^.Timer := 450 - Gear^.Tag * 8 + GetRandom(2) + Gear^.Timer := 450 - Gear^.Tag * 8 + LongInt(GetRandom(2)) end else begin @@ -2244,7 +2506,7 @@ end; // This one is interesting. I think I understand the purpose, but I wonder if a bit more fuzzy of kicking could be done with getrandom. - Gear^.Timer := 100 - Gear^.Tag * 3 + GetRandom(2); + Gear^.Timer := 100 - Gear^.Tag * 3 + LongInt(GetRandom(2)); if (Gear^.Damage > 3000+Gear^.Tag*1500) then Gear^.Health := 0 end @@ -2285,7 +2547,7 @@ if hwRound(HHGear^.Y) <= Gear^.Tag - 2 then begin Gear^.Tag := hwRound(HHGear^.Y); - DrawTunnel(HHGear^.X - int2hwFloat(cHHRadius), HHGear^.Y - _1, _0_5, _0, cHHRadius * 4, 2); + DrawTunnel(HHGear^.X - int2hwFloat(cHHRadius), HHGear^.Y - _1, _0_5, _0, cHHRadius * 4+2, 2); HHGear^.State := HHGear^.State or gstNoDamage; Gear^.Y := HHGear^.Y; AmmoShove(Gear, 30, 40); @@ -2293,7 +2555,8 @@ end; HHGear^.dY := HHGear^.dY + cGravity; - if not (HHGear^.dY.isNegative) then + if Gear^.Timer > 0 then dec(Gear^.Timer); + if not (HHGear^.dY.isNegative) or (Gear^.Timer = 0) then begin HHGear^.State := HHGear^.State or gstMoving; DeleteGear(Gear); @@ -2387,7 +2650,11 @@ AfterAttack; - HHGear^.State := HHGear^.State and (not (gstAttacking or gstAttacked or gstMoving)); + // make sure hog doesn't end up facing in wrong direction due to high jump + if (HHGear^.State and gstHHHJump) <> 0 then + HHGear^.dX.isNegative := (not HHGear^.dX.isNegative); + + HHGear^.State := HHGear^.State and (not (gstAttacking or gstAttacked or gstMoving or gstHHJumping or gstHHHJump)); HHGear^.Message := HHGear^.Message and (not gmAttack); Gear^.doStep := @doStepParachuteWork; @@ -2413,7 +2680,9 @@ //4: FollowGear := AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtWaterMelon, 0, cBombsSpeed * // Gear^.Tag, _0, 5000); end; - Gear^.dX := Gear^.dX + int2hwFloat(30 * Gear^.Tag); + Gear^.dX := Gear^.dX + int2hwFloat(Gear^.Damage * Gear^.Tag); + if CheckCoordInWater(hwRound(Gear^.X), hwRound(Gear^.Y)) then + FollowGear^.State:= FollowGear^.State or gstSubmersible; StopSoundChan(Gear^.SoundChannel, 4000); end; @@ -2444,7 +2713,7 @@ end; Gear^.Y := int2hwFloat(topY-300); - Gear^.dX := int2hwFloat(Gear^.Target.X - 5 * Gear^.Tag * 15); + Gear^.dX := int2hwFloat(Gear^.Target.X) - int2hwFloat(Gear^.Tag * Gear^.Health * Gear^.Damage) / 2; // calcs for Napalm Strike, so that it will hit the target (without wind at least :P) if (Gear^.State = 2) then @@ -2454,7 +2723,6 @@ Gear^.dX := Gear^.dX - cBombsSpeed * hwSqrt((int2hwFloat(Gear^.Target.Y) - Gear^.Y) * 2 / cGravity) * Gear^.Tag; - Gear^.Health := 6; Gear^.doStep := @doStepAirAttackWork; Gear^.SoundChannel := LoopSound(sndPlane, 4000); @@ -2470,9 +2738,11 @@ begin doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 30, Gear^.Hedgehog, EXPLAutoSound); DeleteGear(Gear); + {$IFNDEF PAS2C} with mobileRecord do if (performRumble <> nil) and (not fastUntilLag) then performRumble(kSystemSoundID_Vibrate); + {$ENDIF} exit end; if (GameTicks and $3F) = 0 then @@ -2487,6 +2757,8 @@ x, y, tx, ty: hwFloat; rx: LongInt; LandFlags: Word; + warn: PVisualGear; + distFail: boolean; begin AllInactive := false; @@ -2498,20 +2770,27 @@ rx:= hwRound(x); LandFlags:= 0; - if cIce then LandFlags:= lfIce - else if Gear^.AmmoType = amRubber then LandFlags:= lfBouncy; - - if ((Distance(tx - x, ty - y) > _256) and ((WorldEdge <> weWrap) or + if Gear^.AmmoType = amRubber then LandFlags:= lfBouncy + else if cIce then LandFlags:= lfIce; + + distFail:= (cBuildMaxDist > 0) and ((hwRound(Distance(tx - x, ty - y)) > cBuildMaxDist) and ((WorldEdge <> weWrap) or ( - (Distance(tx - int2hwFloat(rightX+(rx-leftX)), ty - y) > _256) and - (Distance(tx - int2hwFloat(leftX-(rightX-rx)), ty - y) > _256) - ))) - or (not TryPlaceOnLand(Gear^.Target.X - SpritesData[Ammoz[Gear^.AmmoType].PosSprite].Width div 2, Gear^.Target.Y - SpritesData[Ammoz[Gear^.AmmoType].PosSprite].Height div 2, Ammoz[Gear^.AmmoType].PosSprite, Gear^.State, true, false, LandFlags)) then + (hwRound(Distance(tx - int2hwFloat(rightX+(rx-leftX)), ty - y)) > cBuildMaxDist) and + (hwRound(Distance(tx - int2hwFloat(leftX-(rightX-rx)), ty - y)) > cBuildMaxDist) + ))); + if distFail + or (not TryPlaceOnLand(Gear^.Target.X - SpritesData[Ammoz[Gear^.AmmoType].PosSprite].Width div 2, Gear^.Target.Y - SpritesData[Ammoz[Gear^.AmmoType].PosSprite].Height div 2, Ammoz[Gear^.AmmoType].PosSprite, Gear^.State, true, LandFlags)) then begin PlaySound(sndDenied); + if not distFail then + begin + warn:= AddVisualGear(Gear^.Target.X, Gear^.Target.Y, vgtNoPlaceWarn, 0, true); + if warn <> nil then + warn^.Tex := GetPlaceCollisionTex(Gear^.Target.X - SpritesData[Ammoz[Gear^.AmmoType].PosSprite].Width div 2, Gear^.Target.Y - SpritesData[Ammoz[Gear^.AmmoType].PosSprite].Height div 2, Ammoz[Gear^.AmmoType].PosSprite, Gear^.State); + end; HHGear^.Message := HHGear^.Message and (not gmAttack); HHGear^.State := HHGear^.State and (not gstAttacking); - HHGear^.State := HHGear^.State or gstHHChooseTarget; + HHGear^.State := HHGear^.State or gstChooseTarget; isCursorVisible := true; DeleteGear(Gear) end @@ -2532,11 +2811,12 @@ HHGear: PGear; begin HHGear := Gear^.Hedgehog^.Gear; - doStepHedgehogMoving(HHGear); + if HHGear <> nil then doStepHedgehogMoving(HHGear); // if not infattack mode wait for hedgehog finish falling to collect cases if ((GameFlags and gfInfAttack) <> 0) + or (HHGear = nil) or ((HHGear^.State and gstMoving) = 0) - or (Gear^.Hedgehog^.Gear^.Damage > 0) + or (HHGear^.Damage > 0) or ((HHGear^.State and gstDrowning) = 1) then begin DeleteGear(Gear); @@ -2546,7 +2826,7 @@ procedure doStepTeleportAnim(Gear: PGear); begin - if (Gear^.Hedgehog^.Gear^.Damage > 0) then + if (Gear^.Hedgehog^.Gear = nil) or (Gear^.Hedgehog^.Gear^.Damage > 0) then begin DeleteGear(Gear); AfterAttack; @@ -2563,21 +2843,52 @@ procedure doStepTeleport(Gear: PGear); var - HHGear: PGear; + lx, ty, y, oy: LongInt; + HHGear : PGear; + valid : Boolean; + warn : PVisualGear; +const + ytol = cHHRadius; begin AllInactive := false; HHGear := Gear^.Hedgehog^.Gear; - if not TryPlaceOnLand(Gear^.Target.X - SpritesData[sprHHTelepMask].Width div 2, - Gear^.Target.Y - SpritesData[sprHHTelepMask].Height div 2, - sprHHTelepMask, 0, false, false) then + if HHGear = nil then + begin + DeleteGear(Gear); + exit + end; + + valid:= false; + + lx:= Gear^.Target.X - SpritesData[sprHHTelepMask].Width div 2; // left + ty:= Gear^.Target.Y - SpritesData[sprHHTelepMask].Height div 2; // top + + // remember original target location + oy:= Gear^.Target.Y; + + for y:= ty downto ty - ytol do + begin + if TryPlaceOnLand(lx, y, sprHHTelepMask, 0, false, not hasBorder, false, false, false, false, 0, $FFFFFFFF) then + begin + valid:= true; + break; + end; + dec(Gear^.Target.Y); + end; + + if not valid then begin HHGear^.Message := HHGear^.Message and (not gmAttack); HHGear^.State := HHGear^.State and (not gstAttacking); - HHGear^.State := HHGear^.State or gstHHChooseTarget; + HHGear^.State := HHGear^.State or gstChooseTarget; + isCursorVisible := true; + warn:= AddVisualGear(Gear^.Target.X, oy, vgtNoPlaceWarn, 0, true); + if warn <> nil then + warn^.Tex := GetPlaceCollisionTex(lx, ty, sprHHTelepMask, 0); DeleteGear(Gear); - isCursorVisible := true; - PlaySound(sndDenied) + PlaySound(sndDenied); + exit end else begin @@ -2594,6 +2905,8 @@ HHGear^.X := int2hwFloat(Gear^.Target.X); HHGear^.Y := int2hwFloat(Gear^.Target.Y); HHGear^.State := HHGear^.State or gstMoving; + if not Gear^.Hedgehog^.Unplaced then + Gear^.State:= Gear^.State or gstAnimation; Gear^.Hedgehog^.Unplaced := false; isCursorVisible := false; playSound(sndWarp) @@ -2607,10 +2920,11 @@ HHGear: PGear; hedgehog: PHedgehog; State: Longword; + switchDir: Longword; begin AllInactive := false; - if ((Gear^.Message and (not gmSwitch)) <> 0) or (TurnTimeLeft = 0) then + if ((Gear^.Message and (not (gmSwitch or gmPrecise))) <> 0) or (TurnTimeLeft = 0) then begin hedgehog := Gear^.Hedgehog; //Msg := Gear^.Message and (not gmSwitch); @@ -2628,6 +2942,16 @@ HHGear := CurrentHedgehog^.Gear; HHGear^.Message := HHGear^.Message and (not gmSwitch); Gear^.Message := Gear^.Message and (not gmSwitch); + + // switching in reverse direction + if (Gear^.Message and gmPrecise) <> 0 then + begin + HHGear^.Message := HHGear^.Message and (not gmPrecise); + switchDir:= CurrentTeam^.HedgehogsNumber - 1; + end + else + switchDir:= 1; + State := HHGear^.State; HHGear^.State := 0; HHGear^.Z := cHHZ; @@ -2637,7 +2961,7 @@ PlaySound(sndSwitchHog); repeat - CurrentTeam^.CurrHedgehog := Succ(CurrentTeam^.CurrHedgehog) mod (CurrentTeam^.HedgehogsNumber); + CurrentTeam^.CurrHedgehog := (CurrentTeam^.CurrHedgehog + switchDir) mod CurrentTeam^.HedgehogsNumber; until (CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog].Gear <> nil) and (CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog].Gear^.Damage = 0) and (CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog].Effects[heFrozen]=0); @@ -2650,6 +2974,9 @@ HHGear^.Active := true; FollowGear := HHGear; HHGear^.Z := cCurrHHZ; + // restore precise key + if (switchDir <> 1) then + HHGear^.Message:= HHGear^.Message or gmPrecise; HHGear^.Message:= HHGear^.Message or gmRemoveFromList or gmAddToList; Gear^.X := HHGear^.X; Gear^.Y := HHGear^.Y @@ -2702,11 +3029,7 @@ end; if (GameTicks and $3F) = 0 then - begin - if hwRound(Gear^.Y) > cWaterLine then - AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtBubble) - else AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeTrace) - end + AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeTrace); end; //////////////////////////////////////////////////////////////////////////////// @@ -2752,6 +3075,14 @@ HHGear^.X := Gear^.X; HHGear^.Y := Gear^.Y; + // check for drowning + if CheckGearDrowning(HHGear) then + begin + AfterAttack; + DeleteGear(Gear); + exit; + end; + inc(Gear^.Damage, 2); // if TestCollisionXwithGear(HHGear, hwSign(Gear^.dX)) @@ -2849,13 +3180,6 @@ //////////////////////////////////////////////////////////////////////////////// -const cakeh = 27; -var - CakePoints: array[0..Pred(cakeh)] of record - x, y: hwFloat; - end; - CakeI: Longword; - procedure doStepCakeExpl(Gear: PGear); begin AllInactive := false; @@ -2904,7 +3228,7 @@ dmg:= dmgBase - max(hwRound(Distance(tdX, tdY)),gi^.Radius); if (dmg > 1) then dmg:= ModifyDamage(min(dmg div 2, cakeDmg), gi); if (dmg > 1) then - if (CurrentHedgehog^.Gear = gi) and ((gi^.Hedgehog^.Effects[heInvulnerable] = 0)) then + if (CurrentHedgehog^.Gear = gi) and (gi^.Hedgehog^.Effects[heInvulnerable] = 0) then gi^.State := gi^.State or gstLoser else gi^.State := gi^.State or gstWinner; @@ -2922,6 +3246,7 @@ procedure doStepCakeWork(Gear: PGear); var tdx, tdy: hwFloat; + cakeData: PCakeData; begin AllInactive := false; @@ -2940,24 +3265,31 @@ Gear^.RenderTimer := false; Gear^.doStep := @doStepCakeDown; exit - end; - - cakeStep(Gear); + end + else if Gear^.Timer < 6000 then + Gear^.RenderTimer:= true; + + if not cakeStep(Gear) then Gear^.doStep:= @doStepCakeFall; if Gear^.Tag = 0 then begin - CakeI := (CakeI + 1) mod cakeh; - tdx := CakePoints[CakeI].x - Gear^.X; - tdy := - CakePoints[CakeI].y + Gear^.Y; - CakePoints[CakeI].x := Gear^.X; - CakePoints[CakeI].y := Gear^.Y; - Gear^.DirAngle := DxDy2Angle(tdx, tdy); + cakeData:= PCakeData(Gear^.Data); + with cakeData^ do + begin + CakeI := (CakeI + 1) mod cakeh; + tdx := CakePoints[CakeI].x - Gear^.X; + tdy := - CakePoints[CakeI].y + Gear^.Y; + CakePoints[CakeI].x := Gear^.X; + CakePoints[CakeI].y := Gear^.Y; + Gear^.DirAngle := DxDy2Angle(tdx, tdy); + end; end; end; procedure doStepCakeUp(Gear: PGear); var i: Longword; + cakeData: PCakeData; begin AllInactive := false; @@ -2968,12 +3300,16 @@ if Gear^.Pos = 6 then begin - for i:= 0 to Pred(cakeh) do + cakeData:= PCakeData(Gear^.Data); + with cakeData^ do begin - CakePoints[i].x := Gear^.X; - CakePoints[i].y := Gear^.Y + for i:= 0 to Pred(cakeh) do + begin + CakePoints[i].x := Gear^.X; + CakePoints[i].y := Gear^.Y + end; + CakeI := 0; end; - CakeI := 0; Gear^.doStep := @doStepCakeWork end else @@ -2996,16 +3332,12 @@ end; procedure doStepCake(Gear: PGear); -var - HHGear: PGear; begin AllInactive := false; - HHGear := Gear^.Hedgehog^.Gear; - HHGear^.Message := HHGear^.Message and (not gmAttack); Gear^.CollisionMask:= lfNotCurrentMask; - FollowGear := Gear; + Gear^.dY:= cMaxWindSpeed * 100; Gear^.doStep := @doStepCakeFall end; @@ -3021,14 +3353,14 @@ begin for i:= 0 to hogs.size - 1 do with hogs.ar^[i]^ do - begin - if hogs.ar^[i] <> CurrentHedgehog^.Gear then + if (hogs.ar^[i] <> CurrentHedgehog^.Gear) and (Hedgehog^.Effects[heFrozen] = 0) then begin dX:= _50 * cGravity * (Gear^.X - X) / _25; dY:= -_450 * cGravity; Active:= true; end - end; + else if Hedgehog^.Effects[heFrozen] > 255 then + Hedgehog^.Effects[heFrozen]:= 255 end ; AfterAttack; DeleteGear(Gear); @@ -3118,6 +3450,18 @@ else exit; + if (WorldEdge = weSea) and (playWidth > cMinPlayWidth) then + begin + inc(leftX); + dec(rightX); + dec(playWidth, 2); + for i:= 0 to LAND_HEIGHT - 1 do + begin + Land[i, leftX] := 0; + Land[i, rightX] := 0; + end; + end; + if cWaterLine > 0 then begin dec(cWaterLine); @@ -3180,6 +3524,7 @@ begin StopSoundChan(Gear^.SoundChannel); Gear^.Tag := 1; + Gear^.AdvBounce:= 50; Gear^.doStep := @doStepDrill end; @@ -3189,7 +3534,7 @@ procedure doStepDrill(Gear: PGear); var t: PGearArray; - oldDx, oldDy: hwFloat; + oldX, oldY, oldDx, oldDy: hwFloat; t2: hwFloat; begin AllInactive := false; @@ -3199,21 +3544,21 @@ oldDx := Gear^.dX; oldDy := Gear^.dY; + oldX := Gear^.X; + oldY := Gear^.Y; doStepFallingGear(Gear); if (GameTicks and $3F) = 0 then - begin - if hwRound(Gear^.Y) > cWaterLine then - AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtBubble) - else AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeTrace) - end; + AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeTrace); if ((Gear^.State and gstCollision) <> 0) then begin //hit Gear^.dX := oldDx; Gear^.dY := oldDy; + Gear^.X := oldX; + Gear^.Y := oldY; if GameTicks > Gear^.FlightTime then t := CheckGearsCollision(Gear) @@ -3238,6 +3583,8 @@ exit; end; + Gear^.X:= Gear^.X+Gear^.dX*4; + Gear^.Y:= Gear^.Y+Gear^.dY*4; Gear^.SoundChannel := LoopSound(sndDrillRocket); Gear^.doStep := @doStepDrillDrilling; @@ -3267,6 +3614,11 @@ AllInactive := false; dec(Gear^.Timer); HHGear := Gear^.Hedgehog^.Gear; + if HHGear = nil then + begin + DeleteGear(gear); + exit + end; HedgehogChAngle(HHGear); gX := hwRound(Gear^.X) + GetLaunchX(amBallgun, hwSign(HHGear^.dX), HHGear^.Angle); gY := hwRound(Gear^.Y) + GetLaunchY(amBallgun, HHGear^.Angle); @@ -3283,6 +3635,7 @@ if (Gear^.Timer = 0) or ((HHGear^.State and gstHHDriven) = 0) then begin + HHGear^.State := HHGear^.State and (not gstNotKickable); DeleteGear(Gear); AfterAttack end @@ -3305,25 +3658,22 @@ var HHGear: PGear; i: LongInt; - dX, dY, X, Y : hwFloat; + dX, dY : hwFloat; fChanged: boolean; trueAngle: Longword; t: PGear; begin - if WorldWrap(Gear) and (WorldEdge <> weWrap) then - begin - Y.isNegative:= false; - Y.QWordValue:= 4294967296 * 112; - X.isNegative:= false; - X.QWordValue:= 4294967296 * 35; - dX.isNegative:= false; - dX.QWordValue:= 4294967296 * 1152; - - dY:=hwAbs(Gear^.dX*4); - dY:= dY + hwPow(dY,3)/_6 + _3 * hwPow(dY,5) / _40 + _5 * hwPow(dY,7) / Y + X * hwPow(dY,9) / dX; - Gear^.Angle:= hwRound(dY*_2048 / _PI); - if not Gear^.dY.isNegative then Gear^.Angle:= 2048-Gear^.Angle; - if Gear^.dX.isNegative then Gear^.Angle:= 4096-Gear^.Angle; + if WorldWrap(Gear) then + begin + if (WorldEdge = weBounce) then // mirror + Gear^.Angle:= 4096 - Gear^.Angle + else if (WorldEdge = weSea) then // rotate 90 degree + begin + // sea-wrapped gears move upwards, so let's mirror angle if needed + if Gear^.Angle < 2048 then + Gear^.Angle:= 4096 - Gear^.Angle; + Gear^.Angle:= (Gear^.Angle + 1024) mod 4096; + end; end; AllInactive := false; @@ -3331,7 +3681,14 @@ FollowGear := Gear; if Gear^.Timer > 0 then + begin + if Gear^.Timer = 1 then + begin + StopSoundChan(Gear^.SoundChannel); + Gear^.SoundChannel:= -1; + end; dec(Gear^.Timer); + end; fChanged := false; if (HHGear = nil) or ((HHGear^.State and gstHHDriven) = 0) or (Gear^.Timer = 0) then @@ -3342,7 +3699,7 @@ else if Gear^.Angle < 2048 then inc(Gear^.Angle) else fChanged := false - end + end else begin if ((Gear^.Message and gmLeft) <> 0) then @@ -3396,7 +3753,7 @@ // pickup bonuses t := CheckGearNear(Gear, gtCase, 36, 36); - if t <> nil then + if (t <> nil) and (HHGear <> nil) then PickUp(HHGear, t); CheckCollision(Gear); @@ -3417,6 +3774,7 @@ AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtFlame, 0, dX, dY, 0); AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtFlame, 0, dX, -dY, 0); end; + if HHGear <> nil then HHGear^.State := HHGear^.State and (not gstNotKickable); DeleteGear(Gear) end; @@ -3430,7 +3788,8 @@ TurnTimeLeft:= 14 * 125; end; - HHGear^.Message := 0; + if HHGear <> nil then + HHGear^.Message := 0; ParseCommand('/taunt ' + #1, true) end end; @@ -3459,7 +3818,7 @@ isUnderwater: Boolean; bubble: PVisualGear; begin - isUnderwater:= cWaterLine < hwRound(Gear^.Y) + Gear^.Radius; + isUnderwater:= CheckCoordInWater(hwRound(Gear^.X), hwRound(Gear^.Y) + Gear^.Radius); if Gear^.Pos > 0 then dec(Gear^.Pos); AllInactive := false; @@ -3539,8 +3898,8 @@ begin Gear^.Damage:= i; //AddCaption('Fuel: '+inttostr(round(Gear^.Health/20))+'%', cWhiteColor, capgrpAmmostate); - FreeTexture(Gear^.Tex); - Gear^.Tex := RenderStringTex(trmsg[sidFuel] + ': ' + inttostr(i) + '%', cWhiteColor, fntSmall) + FreeAndNilTexture(Gear^.Tex); + Gear^.Tex := RenderStringTex(trmsg[sidFuel] + ansistring(': ' + inttostr(i) + '%'), cWhiteColor, fntSmall) end; if (HHGear^.Message and (gmAttack or gmUp or gmLeft or gmRight) <> 0) and @@ -3565,6 +3924,7 @@ if // (Gear^.Health = 0) (HHGear^.Damage <> 0) //or CheckGearDrowning(HHGear) + // drown if too deep under water or (cWaterLine + cVisibleWater * 4 < hwRound(HHGear^.Y)) or (TurnTimeLeft = 0) // allow brief ground touches - to be fair on this, might need another counter @@ -3878,9 +4238,10 @@ // destroy portal if ground it was attached too is gone if (Land[hwRound(Gear^.Y), hwRound(Gear^.X)] <= lfAllObjMask) + or (Land[hwRound(Gear^.Y), hwRound(Gear^.X)] and lfBouncy <> 0) or (Gear^.Timer < 1) or (Gear^.Hedgehog^.Team <> CurrentHedgehog^.Team) - or (hwRound(Gear^.Y) > cWaterLine) then + or CheckCoordInWater(hwRound(Gear^.X), hwRound(Gear^.Y)) then begin deleteGear(Gear); EXIT; @@ -3939,7 +4300,7 @@ or (iterator^.Y > Gear^.Y + r) then continue; - hasdxy := (((iterator^.dX.QWordValue <> 0) or (iterator^.dY.QWordValue <> 0)) or ((iterator^.State or gstMoving) = 0)); + hasdxy := (((iterator^.dX.QWordValue <> 0) or (iterator^.dY.QWordValue <> 0)) or ((iterator^.State and gstMoving) = 0)); // in case the object is not moving, let's asume it's falling towards the portal if not hasdxy then @@ -4163,21 +4524,7 @@ // is it worth adding an arcsin table? Just how often would we end up doing something like this? // SYNCED ANGLE UPDATE if iterator^.Kind = gtRCPlane then - begin - // recycling as temp vars - resety.isNegative:= false; - resety.QWordValue:= 4294967296 * 112; - resetx.isNegative:= false; - resetx.QWordValue:= 4294967296 * 35; - resetdx.isNegative:= false; - resetdx.QWordValue:= 4294967296 * 1152; - - resetdy:=hwAbs(iterator^.dX*4); - resetdy:= resetdy + hwPow(resetdy,3)/_6 + _3 * hwPow(resetdy,5) / _40 + _5 * hwPow(resetdy,7) / resety + resetx * hwPow(resetdy,9) / resetdx; - iterator^.Angle:= hwRound(resetdy*_2048 / _PI); - if not iterator^.dY.isNegative then iterator^.Angle:= 2048-iterator^.Angle; - if iterator^.dX.isNegative then iterator^.Angle:= 4096-iterator^.Angle; - end + iterator^.Angle:= (1024 + vector2Angle(iterator^.dX, iterator^.dY) mod 4096) // VISUAL USE OF ANGLE ONLY else if (CurAmmoGear <> nil) and (CurAmmoGear^.Kind = gtKamikaze) and (CurAmmoGear^.Hedgehog = iterator^.Hedgehog) then begin @@ -4283,7 +4630,7 @@ loadNewPortalBall(Gear, true); end - else if (y > cWaterLine) + else if CheckCoordInWater(x, y) or (y < -max(LAND_WIDTH,4096)) or (x > 2*max(LAND_WIDTH,4096)) or (x < -max(LAND_WIDTH,4096)) then @@ -4471,7 +4818,7 @@ var x, y, rX, rY, t, tmp, initHealth: LongInt; oX, oY, ldX, ldY, sdX, sdY, sine, lx, ly, amp: hwFloat; - justCollided: boolean; + justCollided, justBounced: boolean; begin AllInactive := false; initHealth := Gear^.Health; @@ -4494,6 +4841,8 @@ // used for a work-around detection of area that is within land array, but outside borders justCollided := false; + // this variable is just to ensure we don't run in infinite loop due to precision errors + justBounced:= false; repeat lX := lX + ldX; @@ -4506,7 +4855,6 @@ amp := _128 * (_1 - hwSqr(int2hwFloat(Gear^.Health)/initHealth)); sine := amp * AngleSin(tmp mod 2048); sine.isNegative := (tmp < 2048); - inc(t,Gear^.Health div 313); Gear^.X := lX + (sine * sdX); Gear^.Y := ly + (sine * sdY); Gear^.dX := Gear^.X - oX; @@ -4515,6 +4863,40 @@ x := hwRound(Gear^.X); y := hwRound(Gear^.Y); + if WorldEdge = weWrap then + begin + if x > LongInt(rightX) then + repeat + dec(x, playWidth); + dec(rx, playWidth); + until x <= LongInt(rightX) + else if x < LongInt(leftX) then + repeat + inc(x, playWidth); + inc(rx, playWidth); + until x >= LongInt(leftX); + end + else if (WorldEdge = weBounce) then + begin + if (not justBounced) and ((x > LongInt(rightX)) or (x < LongInt(leftX))) then + begin + // reflect + lX:= lX - ldX + ((oX - lX) * 2); + lY:= lY - ldY; + Gear^.X:= oX; + Gear^.Y:= oY; + ldX.isNegative:= (not ldX.isNegative); + sdX.isNegative:= (not sdX.isNegative); + justBounced:= true; + continue; + end + else + justBounced:= false; + end; + + + inc(t,Gear^.Health div 313); + // if borders are on, stop outside land array if hasBorder and (((x and LAND_WIDTH_MASK) <> 0) or ((y and LAND_HEIGHT_MASK) <> 0)) then begin @@ -4523,21 +4905,22 @@ end else begin - if (rY <= cWaterLine) or (y <= cWaterLine) then + if (not CheckCoordInWater(rX, rY)) or (not CheckCoordInWater(x, y)) then begin if ((y and LAND_HEIGHT_MASK) = 0) and ((x and LAND_WIDTH_MASK) = 0) and (Land[y, x] <> 0) then begin - if justCollided then - begin - Gear^.Damage := 0; - Gear^.Health := 0; - end - else - begin - inc(Gear^.Damage,3); - justCollided := true; - end; + if ((GameFlags and gfSolidLand) <> 0) and (Land[y, x] > 255) then + Gear^.Damage := initHealth + else if justCollided then + begin + Gear^.Damage := initHealth; + end + else + begin + inc(Gear^.Damage,3); + justCollided := true; + end; end else justCollided := false; @@ -4546,26 +4929,46 @@ // if at least 5 collisions occured if Gear^.Damage > 0 then begin - DrawExplosion(rX,rY,Gear^.Radius); + if ((GameFlags and gfSolidLand) = 0) then + begin + DrawExplosion(rX,rY,Gear^.Radius); + end; // kick nearby hogs AmmoShove(Gear, 35, 50); dec(Gear^.Health, Gear^.Damage); - Gear^.Damage := 0; - + + // explode when impacting on solid land/borders + if Gear^.Damage >= initHealth then + begin + // add some random offset to angles + tmp := getRandom(256); + // spawn some flames + for t:= 0 to 3 do + begin + if not isZero(Gear^.dX) then rX := rx - hwSign(Gear^.dX); + if not isZero(Gear^.dY) then rY := ry - hwSign(Gear^.dY); + lX := AngleCos(tmp + t * 512) * _0_25 * (GetRandomf + _1); + lY := AngleSin(tmp + t * 512) * _0_25 * (GetRandomf + _1); + AddGear(rX, rY, gtFlame, 0, lX, lY, 0); + AddGear(rX, rY, gtFlame, 0, lX, -lY, 0); + end; + end // add some fire to the tunnel - if getRandom(6) = 0 then + else if getRandom(6) = 0 then begin tmp:= GetRandom(2 * Gear^.Radius); AddGear(x - Gear^.Radius + tmp, y - GetRandom(Gear^.Radius + 1), gtFlame, gsttmpFlag, _0, _0, 0) - end + end; end; + Gear^.Damage := 0; + if random(100) = 0 then AddVisualGear(x, y, vgtSmokeTrace); end - else dec(Gear^.Health, 5); // if underwater get additional damage + else dec(Gear^.Health, 5); end; dec(Gear^.Health); @@ -4590,7 +4993,6 @@ if (Gear^.Health <= (initHealth div 6)) then dec(Gear^.Radius) end; - until (Gear^.Health <= 0); DeleteGear(Gear); @@ -4614,9 +5016,11 @@ Gear^.dY.isNegative := not Gear^.dY.isNegative; Gear^.doStep := @doStepSineGunShotWork; + {$IFNDEF PAS2C} with mobileRecord do if (performRumble <> nil) and (not fastUntilLag) then performRumble(kSystemSoundID_Vibrate); + {$ENDIF} end; //////////////////////////////////////////////////////////////////////////////// @@ -4628,6 +5032,11 @@ begin AllInactive := false; HHGear := Gear^.Hedgehog^.Gear; + if HHGear = nil then + begin + DeleteGear(gear); + exit + end; HedgehogChAngle(HHGear); gX := hwRound(Gear^.X) + GetLaunchX(amBallgun, hwSign(HHGear^.dX), HHGear^.Angle); gY := hwRound(Gear^.Y) + GetLaunchY(amBallgun, HHGear^.Angle); @@ -4664,6 +5073,7 @@ SignAs(AngleSin(HHGear^.Angle) * speed, HHGear^.dX) + rx, AngleCos(HHGear^.Angle) * ( - speed) + ry, 0); flame^.CollisionMask:= lfNotCurrentMask; + //flame^.FlightTime:= 500; use the default huge value to avoid sticky flame suddenly being damaging as opposed to other flames if (Gear^.Health mod 30) = 0 then begin @@ -4671,6 +5081,7 @@ SignAs(AngleSin(HHGear^.Angle) * speed, HHGear^.dX) + rx, AngleCos(HHGear^.Angle) * ( - speed) + ry, 0); flame^.CollisionMask:= lfNotCurrentMask; + //flame^.FlightTime:= 500; end end; Gear^.Timer:= Gear^.Tag @@ -4678,6 +5089,7 @@ if (Gear^.Health = 0) or ((HHGear^.State and gstHHDriven) = 0) then begin + HHGear^.State := HHGear^.State and (not gstNotKickable); DeleteGear(Gear); AfterAttack end @@ -4687,9 +5099,9 @@ if (i <> Gear^.Damage) and ((GameTicks and $3F) = 0) then begin Gear^.Damage:= i; - FreeTexture(Gear^.Tex); - Gear^.Tex := RenderStringTex(trmsg[sidFuel] + ': ' + inttostr(i) + - '%', cWhiteColor, fntSmall) + FreeAndNilTexture(Gear^.Tex); + Gear^.Tex := RenderStringTex(trmsg[sidFuel] + ansistring(': ' + inttostr(i) + + '%'), cWhiteColor, fntSmall) end end end; @@ -4713,6 +5125,11 @@ begin AllInactive := false; HHGear := Gear^.Hedgehog^.Gear; + if HHGear = nil then + begin + DeleteGear(gear); + exit + end; HedgehogChAngle(HHGear); gX := hwRound(Gear^.X) + GetLaunchX(amBallgun, hwSign(HHGear^.dX), HHGear^.Angle); gY := hwRound(Gear^.Y) + GetLaunchY(amBallgun, HHGear^.Angle); @@ -4755,6 +5172,7 @@ if (Gear^.Health = 0) or ((HHGear^.State and gstHHDriven) = 0) or ((HHGear^.Message and gmAttack) <> 0) then begin HHGear^.Message:= HHGear^.Message and (not gmAttack); + HHGear^.State := HHGear^.State and (not gstNotKickable); DeleteGear(Gear); AfterAttack end @@ -4764,9 +5182,9 @@ if (i <> Gear^.Damage) and ((GameTicks and $3F) = 0) then begin Gear^.Damage:= i; - FreeTexture(Gear^.Tex); - Gear^.Tex := RenderStringTex(trmsg[sidFuel] + ': ' + inttostr(i) + - '%', cWhiteColor, fntSmall) + FreeAndNilTexture(Gear^.Tex); + Gear^.Tex := RenderStringTex(trmsg[sidFuel] + ansistring(': ' + inttostr(i) + + '%'), cWhiteColor, fntSmall) end end end; @@ -4784,7 +5202,9 @@ //////////////////////////////////////////////////////////////////////////////// procedure doStepPoisonCloud(Gear: PGear); begin - WorldWrap(Gear); + // don't bounce + if WorldEdge <> weBounce then + WorldWrap(Gear); if Gear^.Timer = 0 then begin DeleteGear(Gear); @@ -4797,18 +5217,22 @@ Gear^.dY := Gear^.dY + cGravity / 100; if (GameTicks and $FF) = 0 then doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 20, Gear^.Hedgehog, EXPLDontDraw or EXPLNoGfx or EXPLNoDamage or EXPLDoNotTouchAny or EXPLPoisoned); - AllInactive:= false; + if Gear^.State and gstTmpFlag = 0 then + AllInactive:= false; end; //////////////////////////////////////////////////////////////////////////////// procedure doStepHammer(Gear: PGear); var HHGear, tmp, tmp2: PGear; t: PGearArray; - i: LongInt; + i, dmg, d: LongInt; begin HHGear:= Gear^.Hedgehog^.Gear; HHGear^.State:= HHGear^.State or gstNoDamage; DeleteCI(HHGear); +SetLittle(HHGear^.dY); +HHGear^.dY.IsNegative:= true; +HHGear^.State:= HHGear^.State or gstMoving; t:= CheckGearsCollision(Gear); @@ -4823,17 +5247,36 @@ if (tmp^.State and gstNoDamage) = 0 then if (tmp^.Kind = gtHedgehog) or (tmp^.Kind = gtMine) or (tmp^.Kind = gtExplosives) then begin + dmg:= 0; //tmp^.State:= tmp^.State or gstFlatened; - if (tmp^.Hedgehog^.Effects[heInvulnerable] = 0) then - 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^.LinkedGear:= tmp; - SetAllToActive - end - else - begin - end + if (tmp^.Kind <> gtHedgehog) or (tmp^.Hedgehog^.Effects[heInvulnerable] = 0) then + begin + // base damage on remaining health + dmg:= (tmp^.Health - tmp^.Damage); + if dmg > 0 then + begin + // do 1/2 current hp worth of damage if extra damage is enabled (1/3 damage if not) + if cDamageModifier > _1 then + d:= 2 + else + d:= 3; + + // always rounding down + dmg:= dmg div d; + + if dmg > 0 then + ApplyDamage(tmp, CurrentHedgehog, dmg, dsUnknown); + end; + end; + + if (tmp^.Kind <> gtHedgehog) or (dmg > 0) or (tmp^.Health > tmp^.Damage) then + begin + //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^.LinkedGear:= tmp; + SetAllToActive + end; + end; end; HHGear^.State:= HHGear^.State and (not gstNoDamage); @@ -4886,7 +5329,7 @@ begin //Gear^.dY := Gear^.dY + cGravity; //Gear^.Y := Gear^.Y + Gear^.dY; - if hwRound(Gear^.Y) > cWaterLine then + if CheckCoordInWater(hwRound(Gear^.X), hwRound(Gear^.Y)) then Gear^.Timer := 1 end; @@ -4992,7 +5435,7 @@ for i:= 0 to graves.size - 1 do if graves.ar^[i]^.Health > 0 then begin - resgear := AddGear(hwRound(graves.ar^[i]^.X), hwRound(graves.ar^[i]^.Y), gtHedgehog, gstWait, _0, _0, 0); + resgear := AddGear(hwRound(graves.ar^[i]^.X), hwRound(graves.ar^[i]^.Y), gtHedgehog, gstWait, _0, _0, 0,graves.ar^[i]^.Pos); resgear^.Hedgehog := graves.ar^[i]^.Hedgehog; resgear^.Health := graves.ar^[i]^.Health; PHedgehog(graves.ar^[i]^.Hedgehog)^.Gear := resgear; @@ -5354,9 +5797,16 @@ All these effects assume the ray's angle is not changed and that the target type was unchanged over a number of ticks. This is a simplifying assumption for "gun was applying freezing effect to the same target". * When fired at water a layer of ice textured land is added above the water. * When fired at non-ice land (land and lfLandMask and not lfIce) the land is overlaid with a thin layer of ice textured land around that point (say, 1 or 2px into land, 1px above). For attractiveness, a slope would probably be needed. - * When fired at a hog (land and $00FF <> 0), while the hog is targetted, the hog's state is set to frozen. As long as the gun is on the hog, a frozen hog sprite creeps up from the feet to the head. If the effect is interrupted before reaching the top, the freezing state is cleared. -A frozen hog will animate differently. To be decided, but possibly in a similar fashion to a grave when it comes to explosions. The hog might (possibly) not be damaged by explosions. This might make freezing potentially useful for friendlies in a bad position. It might be better to allow damage though. -A frozen hog stays frozen for a certain number of turns. Each turn the frozen overlay becomes fainter, until it fades and the hog animates normally again. + * When fired at a hog (land and $00FF <> 0), while the hog is targetted, the hog's state is set to frozen. + As long as the gun is on the hog, a frozen hog sprite creeps up from the feet to the head. + If the effect is interrupted before reaching the top, the freezing state is cleared. +A frozen hog will animate differently. + To be decided, but possibly in a similar fashion to a grave when it comes to explosions. + The hog might (possibly) not be damaged by explosions. + This might make freezing potentially useful for friendlies in a bad position. + It might be better to allow damage though. +A frozen hog stays frozen for a certain number of turns. + Each turn the frozen overlay becomes fainter, until it fades and the hog animates normally again. *) @@ -5368,9 +5818,9 @@ if (t <> Gear^.Damage) and ((GameTicks and $3F) = 0) then begin Gear^.Damage:= t; - FreeTexture(Gear^.Tex); - Gear^.Tex := RenderStringTex(trmsg[sidFuel] + ': ' + inttostr(t) + - '%', cWhiteColor, fntSmall) + FreeAndNilTexture(Gear^.Tex); + Gear^.Tex := RenderStringTex(trmsg[sidFuel] + ansistring(': ' + inttostr(t) + + '%'), cWhiteColor, fntSmall) end; if Gear^.Message and (gmUp or gmDown) <> 0 then begin @@ -5378,7 +5828,7 @@ Gear^.SoundChannel:= -1; if GameTicks mod 40 = 0 then dec(Gear^.Health) end - else + else begin if Gear^.SoundChannel = -1 then Gear^.SoundChannel := LoopSound(sndIceBeam); @@ -5438,7 +5888,8 @@ ndY:= -AngleCos(HHGear^.Angle) * _4; if (ndX <> dX) or (ndY <> dY) or ((Target.X <> NoPointX) and (Target.X and LAND_WIDTH_MASK = 0) and - (Target.Y and LAND_HEIGHT_MASK = 0) and ((Land[Target.Y, Target.X] = 0))) then + (Target.Y and LAND_HEIGHT_MASK = 0) and ((Land[Target.Y, Target.X] = 0)) and + (not CheckCoordInWater(Target.X, Target.Y))) then begin updateTarget(Gear, ndX, ndY); Timer := iceWaitCollision; @@ -5462,7 +5913,15 @@ Power := GameTicks; end end - else if (target.y >= cWaterLine) then + else if CheckCoordInWater(Target.X, Target.Y) or + ((Target.X and LAND_WIDTH_MASK = 0) and + (Target.Y and LAND_HEIGHT_MASK = 0) and + (Land[Target.Y, Target.X] = lfIce) and + ((Target.Y+iceHeight+5 > cWaterLine) or + ((WorldEdge = weSea) and + ((Target.X+iceHeight+5 > LongInt(rightX)) or + (Target.X-iceHeight-5 < LongInt(leftX))))) + ) then begin if Timer = iceWaitCollision then begin @@ -5479,20 +5938,21 @@ if (Timer = iceCollideWithGround) and ((GameTicks - Power) > groundFreezingTime) then begin - FillRoundInLand(target.x, target.y, iceRadius, icePixel); + FillRoundInLandFT(target.x, target.y, iceRadius, icePixel); landRect.x := min(max(target.x - iceRadius, 0), LAND_WIDTH - 1); landRect.y := min(max(target.y - iceRadius, 0), LAND_HEIGHT - 1); landRect.w := min(2*iceRadius, LAND_WIDTH - landRect.x - 1); landRect.h := min(2*iceRadius, LAND_HEIGHT - landRect.y - 1); UpdateLandTexture(landRect.x, landRect.w, landRect.y, landRect.h, true); - + // Freeze nearby mines/explosives/cases too iter := GearsList; while iter <> nil do begin if (iter^.State and gstFrozen = 0) and - ((iter^.Kind = gtExplosives) or (iter^.Kind = gtCase) or (iter^.Kind = gtMine)) and - (abs(iter^.X.Round-target.x)+abs(iter^.Y.Round-target.y)+2<2*iceRadius) and (Distance(iter^.X-int2hwFloat(target.x),iter^.Y-int2hwFloat(target.y)) groundFreezingTime) then + if (Timer = iceCollideWithWater) and ((GameTicks - Power) > groundFreezingTime div 2) then begin PlaySound(sndHogFreeze); - DrawIceBreak(Target.X, cWaterLine - iceHeight, iceRadius, iceHeight); + if CheckCoordInWater(Target.X, Target.Y) then + DrawIceBreak(Target.X, Target.Y, iceRadius, iceHeight) + else if Target.Y+iceHeight+5 > cWaterLine then + DrawIceBreak(Target.X, Target.Y+iceHeight+5, iceRadius, iceHeight) + else if Target.X+iceHeight+5 > LongInt(rightX) then + DrawIceBreak(Target.X+iceHeight+5, Target.Y, iceRadius, iceHeight) + else + DrawIceBreak(Target.X-iceHeight-5, Target.Y, iceRadius, iceHeight); SetAllHHToActive; Timer := iceWaitCollision; end; @@ -5579,7 +6046,7 @@ end; inc(Pos) end - else if (t > 400) and ((gY > cWaterLine) or + else if (t > 400) and (CheckCoordInWater(gX, gY) or (((gX and LAND_WIDTH_MASK = 0) and (gY and LAND_HEIGHT_MASK = 0)) and (Land[gY, gX] <> 0))) then begin @@ -5619,7 +6086,7 @@ begin with gi^ do CheckSum:= CheckSum xor X.round xor X.frac xor dX.round xor dX.frac xor Y.round xor Y.frac xor dY.round xor dY.frac; AddRandomness(CheckSum); - if gi^.Kind = gtGenericFaller then gi^.State:= gi^.State and not gstTmpFlag; + if gi^.Kind = gtGenericFaller then gi^.State:= gi^.State and (not gstTmpFlag); gi := gi^.NextGear end; AddPickup(Gear^.Hedgehog^, a, Gear^.Power, hwRound(Gear^.X), hwRound(Gear^.Y)); diff -r 31570b766315 -r ed5a6478e710 hedgewars/uGearsHandlersRope.pas --- a/hedgewars/uGearsHandlersRope.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uGearsHandlersRope.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} @@ -28,18 +28,29 @@ uses uConsts, uFloat, uCollisions, uVariables, uGearsList, uSound, uGearsUtils, uAmmos, uDebug, uUtils, uGearsHedgehog, uGearsRender; +const + IsNilHHFatal = false; + procedure doStepRopeAfterAttack(Gear: PGear); -var +var HHGear: PGear; tX: hwFloat; begin HHGear := Gear^.Hedgehog^.Gear; + if HHGear = nil then + begin + OutError('ERROR: doStepRopeAfterAttack called while HHGear = nil', IsNilHHFatal); + DeleteGear(Gear); + exit() + end + else if not CurrentTeam^.ExtDriven and (FollowGear <> nil) then FollowGear := HHGear; + tX:= HHGear^.X; - if WorldWrap(HHGear) and (WorldEdge = weWrap) and + if WorldWrap(HHGear) and (WorldEdge = weWrap) and ((TestCollisionXwithGear(HHGear, 1) <> 0) or (TestCollisionXwithGear(HHGear, -1) <> 0)) then begin HHGear^.X:= tX; - HHGear^.dX.isNegative:= (hwRound(tX) > leftX+HHGear^.Radius*2) + HHGear^.dX.isNegative:= hwRound(tX) > LongInt(leftX) + HHGear^.Radius * 2 end; if (HHGear^.Hedgehog^.CurAmmoType = amParachute) and (HHGear^.dY > _0_39) then @@ -70,7 +81,7 @@ HHGear^.X := HHGear^.X + HHGear^.dX; HHGear^.Y := HHGear^.Y + HHGear^.dY; HHGear^.dY := HHGear^.dY + cGravity; - + if (GameFlags and gfMoreWind) <> 0 then HHGear^.dX := HHGear^.dX + cWindSpeed / HHGear^.Density; @@ -113,7 +124,7 @@ end; procedure doStepRopeWork(Gear: PGear); -var +var HHGear: PGear; len, tx, ty, nx, ny, ropeDx, ropeDy, mdX, mdY: hwFloat; lx, ly, cd: LongInt; @@ -121,22 +132,15 @@ haveDivided: boolean; wrongSide: boolean; begin - if GameTicks mod 4 <> 0 then exit; - HHGear := Gear^.Hedgehog^.Gear; - - tX:= HHGear^.X; - if WorldWrap(HHGear) and (WorldEdge = weWrap) and - ((TestCollisionXwithGear(HHGear, 1) <> 0) or (TestCollisionXwithGear(HHGear, -1) <> 0)) then + if HHGear = nil then begin - PlaySound(sndRopeRelease); - RopeDeleteMe(Gear, HHGear); - HHGear^.X:= tX; - HHGear^.dX.isNegative:= (hwRound(tX) > leftX+HHGear^.Radius*2); - exit - end; + OutError('ERROR: doStepRopeWork called while HHGear = nil', IsNilHHFatal); + DeleteGear(Gear); + exit() + end + else if not CurrentTeam^.ExtDriven and (FollowGear <> nil) then FollowGear := HHGear; - tX:= HHGear^.X; if ((HHGear^.State and gstHHDriven) = 0) or (CheckGearDrowning(HHGear)) or (Gear^.PortalCounter <> 0) then begin @@ -145,6 +149,20 @@ exit end; + if GameTicks mod 4 <> 0 then exit; + + tX:= HHGear^.X; + if WorldWrap(HHGear) and (WorldEdge = weWrap) and + ((TestCollisionXwithGear(HHGear, 1) <> 0) or (TestCollisionXwithGear(HHGear, -1) <> 0)) then + begin + PlaySound(sndRopeRelease); + RopeDeleteMe(Gear, HHGear); + HHGear^.X:= tX; + HHGear^.dX.isNegative:= hwRound(tX) > LongInt(leftX) + HHGear^.Radius * 2; + exit + end; + + tX:= HHGear^.X; HHGear^.dX.QWordValue:= HHGear^.dX.QWordValue shl 2; HHGear^.dY.QWordValue:= HHGear^.dY.QWordValue shl 2; if (Gear^.Message and gmLeft <> 0) and (TestCollisionXwithGear(HHGear, -1) = 0) then @@ -405,15 +423,24 @@ end; procedure doStepRopeAttach(Gear: PGear); -var +var HHGear: PGear; tx, ty, tt: hwFloat; begin + Gear^.X := Gear^.X - Gear^.dX; Gear^.Y := Gear^.Y - Gear^.dY; Gear^.Elasticity := Gear^.Elasticity + _1; HHGear := Gear^.Hedgehog^.Gear; + if HHGear = nil then + begin + OutError('ERROR: doStepRopeAttach called while HHGear = nil', IsNilHHFatal); + DeleteGear(Gear); + exit() + end + else if not CurrentTeam^.ExtDriven and (FollowGear <> nil) then FollowGear := HHGear; + DeleteCI(HHGear); if (HHGear^.State and gstMoving) <> 0 then diff -r 31570b766315 -r ed5a6478e710 hedgewars/uGearsHedgehog.pas --- a/hedgewars/uGearsHedgehog.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uGearsHedgehog.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,14 +13,14 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} unit uGearsHedgehog; interface -uses uTypes, uGearsHandlersMess; +uses uTypes, uGearsHandlersMess; procedure doStepHedgehog(Gear: PGear); procedure AfterAttack; @@ -118,15 +118,8 @@ end; if ammoidx >= 0 then CurAmmoType:= Ammo^[slot, ammoidx].AmmoType; - if (prevAmmo <> CurAmmoType) then - begin - if CurAmmoType = amKnife then - LoadHedgehogHat(HHGear^.Hedgehog^, 'Reserved/chef') - else if prevAmmo = amKnife then - LoadHedgehogHat(HHGear^.Hedgehog^, Hat); - end; // Try again in the next slot - if (CurAmmoType = prevAmmo) and (slot < cMaxSlotIndex) then + if (CurAmmoType = prevAmmo) and (slot < cMaxSlotIndex) then begin inc(slot); HHGear^.MsgParam:= slot; @@ -220,6 +213,7 @@ speech: PVisualGear; newGear: PGear; CurWeapon: PAmmo; + usedAmmoType: TAmmoType; altUse: boolean; elastic: hwFloat; begin @@ -229,7 +223,8 @@ with Gear^, Gear^.Hedgehog^ do begin - if ((State and gstHHDriven) <> 0) and ((State and (gstAttacked or gstHHChooseTarget)) = 0) and (((State and gstMoving) = 0) + usedAmmoType:= CurAmmoType; + if ((State and gstHHDriven) <> 0) and ((State and (gstAttacked or gstChooseTarget)) = 0) and (((State and gstMoving) = 0) or (Power > 0) or (CurAmmoType = amTeleport) or @@ -297,6 +292,7 @@ case CurAmmoType of amGrenade: newGear:= AddGear(hwRound(lx), hwRound(ly), gtGrenade, 0, newDx, newDy, CurWeapon^.Timer); + amAirMine: newGear:= AddGear(hwRound(lx), hwRound(ly), gtAirMine, 0, newDx, newDy, 0); amMolotov: newGear:= AddGear(hwRound(lx), hwRound(ly), gtMolotov, 0, newDx, newDy, 0); amClusterBomb: newGear:= AddGear(hwRound(lx), hwRound(ly), gtClusterBomb, 0, newDx, newDy, CurWeapon^.Timer); amGasBomb: newGear:= AddGear(hwRound(lx), hwRound(ly), gtGasBomb, 0, newDx, newDy, CurWeapon^.Timer); @@ -310,7 +306,7 @@ amPickHammer: newGear:= AddGear(hwRound(lx), hwRound(ly) + cHHRadius, gtPickHammer, 0, _0, _0, 0); amSkip: ParseCommand('/skip', true); amRope: newGear:= AddGear(hwRound(lx), hwRound(ly), gtRope, 0, xx, yy, 0); - amMine: newGear:= AddGear(hwRound(lx) + hwSign(dX) * 7, hwRound(ly), gtMine, gstWait, SignAs(_0_02, dX), _0, 3000); + amMine: newGear:= AddGear(hwRound(lx) + hwSign(dX) * 7, hwRound(ly), gtMine, gstWait, SignAs(_0_02, dX), _0, 0); amSMine: newGear:= AddGear(hwRound(lx), hwRound(ly), gtSMine, 0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, 0); amKnife: begin newGear:= AddGear(hwRound(lx), hwRound(ly), gtKnife, 0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, 0); @@ -416,14 +412,14 @@ amTardis: newGear:= AddGear(hwRound(X), hwRound(Y), gtTardis, 0, _0, _0, 0); amIceGun: newGear:= AddGear(hwRound(X), hwRound(Y), gtIceGun, 0, _0, _0, 0); end; - if altUse and (newGear <> nil) and + if altUse and (newGear <> nil) and ((CurAmmoGear = nil) or (CurAmmoGear^.AmmoType <> amJetpack) or (Gear^.Message and gmPrecise = 0)) then begin newGear^.dX:= newDx / newGear^.Density; newGear^.dY:= newDY / newGear^.Density end; if (CurAmmoGear <> nil) and (CurAmmoGear^.AmmoType = amJetpack) and - (Gear^.Message and gmPrecise <> 0) and (hwRound(Y) > cWaterLine) then + (Gear^.Message and gmPrecise <> 0) and CheckCoordInWater(hwRound(X), hwRound(Y)) then newGear^.State:= newGear^.State or gstSubmersible; case CurAmmoType of @@ -432,7 +428,8 @@ amBazooka, amSnowball, amBee, amSMine, amMortar, amWatermelon, - amHellishBomb, amDrill: FollowGear:= newGear; + amHellishBomb, amDrill, + amAirMine: FollowGear:= newGear; amShotgun, amPickHammer, amRope, amDEagle, @@ -450,9 +447,11 @@ amTardis, amPiano, amIceGun, amRubber: CurAmmoGear:= newGear; end; + if CurAmmoType = amCake then FollowGear:= newGear; + if CurAmmoType = amAirMine then newGear^.Hedgehog:= nil; - if ((CurAmmoType = amMine) or (CurAmmoType = amSMine)) and (GameFlags and gfInfAttack <> 0) then - newGear^.FlightTime:= GameTicks + 1000 + if ((CurAmmoType = amMine) or (CurAmmoType = amSMine) or (CurAmmoType = amAirMine)) and (GameFlags and gfInfAttack <> 0) then + newGear^.FlightTime:= GameTicks + min(TurnTimeLeft,1000) else if CurAmmoType = amDrill then newGear^.FlightTime:= GameTicks + 250; if Ammoz[CurAmmoType].Ammo.Propz and ammoprop_NeedTarget <> 0 then @@ -470,15 +469,15 @@ begin elastic:= int2hwfloat(CurWeapon^.Bounciness) / _1000; - if elastic < _1 then - newGear^.Elasticity:= newGear^.Elasticity * elastic - else if elastic > _1 then - newGear^.Elasticity:= _1 - ((_1-newGear^.Elasticity) / elastic); - (* Experimented with friction modifier. Didn't seem helpful - fric:= int2hwfloat(CurWeapon^.Bounciness) / _250; - if fric < _1 then newGear^.Friction:= newGear^.Friction * fric - else if fric > _1 then newGear^.Friction:= _1 - ((_1-newGear^.Friction) / fric)*) - end; + if elastic < _1 then + newGear^.Elasticity:= newGear^.Elasticity * elastic + else if elastic > _1 then + newGear^.Elasticity:= _1 - ((_1-newGear^.Elasticity) / elastic); +(* Experimented with friction modifier. Didn't seem helpful + fric:= int2hwfloat(CurWeapon^.Bounciness) / _250; + if fric < _1 then newGear^.Friction:= newGear^.Friction * fric + else if fric > _1 then newGear^.Friction:= _1 - ((_1-newGear^.Friction) / fric)*) + end; uStats.AmmoUsed(CurAmmoType); @@ -496,29 +495,30 @@ end; Power:= 0; - if (CurAmmoGear <> nil) - and ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_AltUse) = 0){check for dropping ammo from rope} then + if (CurAmmoGear <> nil) and ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_AltUse) = 0){check for dropping ammo from rope} then begin - if CurAmmoType in [amRope,amResurrector] then Message:= Message or gmAttack; + if CurAmmoType in [amRope,amResurrector] then + Message:= Message or gmAttack; CurAmmoGear^.Message:= Message end else begin - if not CurrentTeam^.ExtDriven - and ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_Power) <> 0) then + if (not CurrentTeam^.ExtDriven) and ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_Power) <> 0) then SendIPC(_S'a'); AfterAttack; end end else Message:= Message and (not gmAttack); - end; + + ScriptCall('onHogAttack', ord(usedAmmoType)); + end; // of with Gear^, Gear^.Hedgehog^ do + TargetPoint.X := NoPointX; - ScriptCall('onHogAttack'); end; procedure AfterAttack; -var s: shortstring; +var s: ansistring; a: TAmmoType; HHGear: PGear; begin @@ -533,8 +533,8 @@ if (Ammoz[a].Ammo.NumPerTurn >= MultiShootAttacks) then begin - s:= inttostr(Ammoz[a].Ammo.NumPerTurn - MultiShootAttacks + 1); - AddCaption(format(trmsg[sidRemaining], s), cWhiteColor, capgrpAmmostate); + s:= ansistring(inttostr(Ammoz[a].Ammo.NumPerTurn - MultiShootAttacks + 1)); + AddCaption(formatA(trmsg[sidRemaining], s), cWhiteColor, capgrpAmmostate); end; if (Ammoz[a].Ammo.NumPerTurn >= MultiShootAttacks) @@ -549,7 +549,7 @@ begin if TagTurnTimeLeft = 0 then TagTurnTimeLeft:= TurnTimeLeft; - if (CurAmmoGear <> nil) and (CurAmmoGear^.State and gstSubmersible <> 0) and (hwRound(CurAmmoGear^.Y) > cWaterLine) then + if (CurAmmoGear <> nil) and (CurAmmoGear^.State and gstSubmersible <> 0) and CheckCoordInWater(hwRound(CurAmmoGear^.X), hwRound(CurAmmoGear^.Y)) then TurnTimeLeft:=(Ammoz[a].TimeAfterTurn * cGetAwayTime) div 25 else TurnTimeLeft:=(Ammoz[a].TimeAfterTurn * cGetAwayTime) div 100; end; @@ -572,6 +572,7 @@ procedure doStepHedgehogDead(Gear: PGear); const frametime = 200; timertime = frametime * 6; +var grave: PGear; begin if Gear^.Hedgehog^.Unplaced then exit; @@ -587,7 +588,10 @@ Gear^.Hedgehog^.Effects[heFrozen]:= 0; Gear^.State:= Gear^.State or gstNoDamage; doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 30, CurrentHedgehog, EXPLAutoSound); - AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtGrave, 0, _0, _0, 0)^.Hedgehog:= Gear^.Hedgehog; + grave:= AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtGrave, 0, _0, _0, 0); + grave^.Hedgehog:= Gear^.Hedgehog; + grave^.Pos:= Gear^.uid; + DeleteGear(Gear); SetAllToActive end @@ -607,6 +611,7 @@ procedure doStepHedgehogGone(Gear: PGear); const frametime = 65; timertime = frametime * 11; +var i: LongInt; begin if Gear^.Hedgehog^.Unplaced then exit; @@ -629,15 +634,27 @@ Gear^.Z:= cCurrHHZ; RemoveGearFromList(Gear); InsertGearToList(Gear); - PlaySoundV(sndByeBye, Gear^.Hedgehog^.Team^.voicepack); - PlaySound(sndWarp); + // only play sound for one alive hedgehog + with Gear^.Hedgehog^.Team^ do + for i:= 0 to cMaxHHIndex do + begin + if (Hedgehogs[i].Gear <> nil) then + begin + if (Hedgehogs[i].Gear = Gear) then + begin + PlaySoundV(sndByeBye, Gear^.Hedgehog^.Team^.voicepack); + PlaySound(sndWarp); + end; + break; + end; + end; Gear^.Pos:= 0; Gear^.Timer:= timertime end end; procedure AddPickup(HH: THedgehog; ammo: TAmmoType; cnt, X, Y: LongWord); -var s: shortstring; +var s: ansistring; vga: PVisualGear; begin if cnt <> 0 then AddAmmo(HH, ammo, cnt) @@ -649,9 +666,9 @@ or (GameType = gmtDemo) then begin if cnt <> 0 then - s:= trammo[Ammoz[ammo].NameId] + ' (+' + IntToStr(cnt) + ')' + s:= trammo[Ammoz[ammo].NameId] + ansistring(' (+' + IntToStr(cnt) + ')') else - s:= trammo[Ammoz[ammo].NameId] + ' (+' + IntToStr(Ammoz[ammo].NumberInCase) + ')'; + s:= trammo[Ammoz[ammo].NameId] + ansistring(' (+' + IntToStr(Ammoz[ammo].NumberInCase) + ')'); AddCaption(s, HH.Team^.Clan^.Color, capgrpAmmoinfo); // show ammo icon @@ -715,7 +732,7 @@ HH^.Hedgehog^.Effects[hePoisoned] := 0; str(Gear^.Health, s); s:= '+' + s; - AddCaption(s, HH^.Hedgehog^.Team^.Clan^.Color, capgrpAmmoinfo); + AddCaption(ansistring(s), HH^.Hedgehog^.Team^.Clan^.Color, capgrpAmmoinfo); RenderHealth(HH^.Hedgehog^); RecountTeamHealth(HH^.Hedgehog^.Team); @@ -738,6 +755,7 @@ procedure HedgehogStep(Gear: PGear); var PrevdX: LongInt; CurWeapon: PAmmo; + portals: PGearArrayS; begin CurWeapon:= GetCurAmmoEntry(Gear^.Hedgehog^); if ((Gear^.State and (gstAttacking or gstMoving)) = 0) then @@ -800,6 +818,12 @@ exit end; + if (Gear^.Message and (gmLeft or gmRight) <> 0) and (Gear^.State and gstMoving = 0) then + begin + // slightly inefficient since it doesn't halt after one portal, maybe could add a param to GearsNear for number desired. + portals:= GearsNear(Gear^.X, Gear^.Y, gtPortal, 26); + if portals.size = 0 then Gear^.PortalCounter:= 0 + end; PrevdX:= hwSign(Gear^.dX); if (Gear^.Message and gmLeft )<>0 then Gear^.dX:= -cLittle else @@ -819,7 +843,9 @@ Gear^.Hedgehog^.visStepPos:= (Gear^.Hedgehog^.visStepPos + 1) and 7; - if (not cArtillery) and ((Gear^.Message and gmPrecise) = 0) then + if (not cArtillery or + ((CurAmmoGear <> nil) and (CurAmmoGear^.Kind = gtBlowTorch))) and + ((Gear^.Message and gmPrecise) = 0) then MakeHedgehogsStep(Gear); SetAllHHToActive(false); @@ -831,7 +857,7 @@ var da: LongWord; begin with HHGear^.Hedgehog^ do - if (((CurAmmoType = amRope) or ((CurAmmoGear <> nil) and (CurAmmoGear^.AmmoType = amRope))) and + if (((CurAmmoType = amRope) or ((CurAmmoGear <> nil) and (CurAmmoGear^.AmmoType = amRope))) and ((HHGear^.State and (gstMoving or gstHHJumping)) = gstMoving)) or ((CurAmmoType = amPortalGun) and ((HHGear^.State and gstMoving) <> 0)) then da:= 2 @@ -851,13 +877,6 @@ var isFalling, isUnderwater: boolean; land: Word; begin -land:= 0; -isUnderwater:= cWaterLine < hwRound(Gear^.Y) + Gear^.Radius; -if Gear^.dX.QWordValue > 8160437862 then - Gear^.dX.QWordValue:= 8160437862; -if Gear^.dY.QWordValue > 8160437862 then - Gear^.dY.QWordValue:= 8160437862; - if Gear^.Hedgehog^.Unplaced then begin Gear^.dY:= _0; @@ -865,6 +884,14 @@ Gear^.State:= Gear^.State and (not gstMoving); exit end; + +land:= 0; +isUnderwater:= CheckCoordInWater(hwRound(Gear^.X), hwRound(Gear^.Y) + Gear^.Radius); +if Gear^.dX.QWordValue > 8160437862 then + Gear^.dX.QWordValue:= 8160437862; +if Gear^.dY.QWordValue > 8160437862 then + Gear^.dY.QWordValue:= 8160437862; + isFalling:= (Gear^.dY.isNegative) or (TestCollisionYKick(Gear, 1) = 0); if isFalling then begin @@ -874,14 +901,16 @@ if land and lfBouncy <> 0 then begin doStepFallingGear(Gear); + Gear^.AdvBounce:= 1; Gear^.dX:= Gear^.dX * _0_8 end; if (land and lfBouncy = 0) or (Gear^.State and gstCollision <> 0) then Gear^.dY:= _0; - Gear^.State:= Gear^.State and not gstCollision + Gear^.State:= Gear^.State and (not gstCollision) end; Gear^.State:= Gear^.State or gstMoving; - if (CurrentHedgehog^.Gear = Gear) and (CurrentHedgehog^.Gear^.State and gstHHDriven <> 0) and + if (Gear^.State and gstHHDriven <> 0) and + (FollowGear <> nil) and (not CurrentTeam^.ExtDriven) and (hwSqr(Gear^.dX) + hwSqr(Gear^.dY) > _0_003) then begin // TODO: why so aggressive at setting FollowGear when falling? @@ -904,8 +933,8 @@ else begin land:= TestCollisionYwithGear(Gear, 1); - if ((Gear^.dX.QWordValue + Gear^.dY.QWordValue) < _0_55.QWordValue) and ((land and lfIce) = 0) - and ((land and lfBouncy = 0) or (Gear^.State and gstCollision <> 0)) + if ((Gear^.dX.QWordValue + Gear^.dY.QWordValue) < _0_55.QWordValue) and ((land and lfIce) = 0) + and ((land and lfBouncy = 0) or (Gear^.State and gstCollision <> 0)) and ((Gear^.State and gstHHJumping) <> 0) then SetLittle(Gear^.dX); @@ -914,6 +943,7 @@ if land and lfBouncy <> 0 then begin doStepFallingGear(Gear); + Gear^.AdvBounce:= 1; // hogs for some reason have very low friction. slippery little buggers Gear^.dX:= Gear^.dX * _0_8 end; @@ -933,7 +963,7 @@ if (land and lfBouncy = 0) or (Gear^.dX.QWordValue < _0_02.QWordValue) then Gear^.dY:= _0 end; - Gear^.State:= Gear^.State and not gstCollision + Gear^.State:= Gear^.State and (not gstCollision) end else Gear^.dY:= Gear^.dY + cGravity; @@ -949,7 +979,7 @@ end end; -if (Gear^.State <> 0) then +if (Gear^.State and (gstMoving or gstHHJumping or gstHHHJump)) <> 0 then DeleteCI(Gear); if isUnderwater then @@ -1029,7 +1059,7 @@ begin Gear^.State:= Gear^.State and (not gstWinner); Gear^.State:= Gear^.State and (not gstMoving); - while (TestCollisionYWithGear(Gear,1) = 0) and (not CheckGearDrowning(Gear)) and (Gear <> nil) do + while (not CheckGearDrowning(Gear)) and (Gear <> nil) and (TestCollisionYWithGear(Gear,1) = 0) do Gear^.Y:= Gear^.Y + _1; // could become nil in CheckGearDrowning if ai's hog fails to respawn in ai survival @@ -1051,6 +1081,7 @@ land:= TestCollisionYwithXYShift(Gear, 0, 1, 1); if land and lfBouncy <> 0 then doStepFallingGear(Gear); + Gear^.AdvBounce:= 1; if (land <> 0) and ((land and lfBouncy = 0) or (Gear^.State and gstCollision <> 0)) then begin @@ -1058,10 +1089,9 @@ Gear^.dY:= _0; Gear^.Y:= Gear^.Y + _1 end; - Gear^.State:= Gear^.State and not gstCollision + Gear^.State:= Gear^.State and (not gstCollision) end; - CheckGearDrowning(Gear); // could become nil if ai's hog fails to respawn in ai survival if Gear = nil then exit; // hide target cursor if current hog is drowning @@ -1098,6 +1128,11 @@ else if Hedgehog^.CurAmmoType in [amShotgun, amDEagle, amSniperRifle] then HHGear^.Message:= 0; +if ((Ammoz[CurrentHedgehog^.CurAmmoType].Ammo.Propz and ammoprop_Utility) <> 0) and isInMultiShoot then + AllInactive:= true +else if not isInMultiShoot then + AllInactive:= false; + if (TurnTimeLeft = 0) or (HHGear^.Damage > 0) then begin if (Hedgehog^.CurAmmoType = amKnife) then @@ -1231,6 +1266,7 @@ //////////////////////////////////////////////////////////////////////////////// procedure doStepHedgehogFree(Gear: PGear); var prevState: Longword; + s: ansistring; begin prevState:= Gear^.State; @@ -1265,7 +1301,8 @@ Gear^.State:= (Gear^.State or gstHHDeath) and (not gstAnimation); Gear^.doStep:= @doStepHedgehogDead; // Death message - AddCaption(Format(GetEventString(eidDied), Gear^.Hedgehog^.Name), cWhiteColor, capgrpMessage); + s:= ansistring(Gear^.Hedgehog^.Name); + AddCaption(FormatA(GetEventString(eidDied), s), cWhiteColor, capgrpMessage); end; end else @@ -1274,7 +1311,8 @@ Gear^.doStep:= @doStepHedgehogGone; // Gone message - AddCaption(Format(GetEventString(eidGone), Gear^.Hedgehog^.Name), cWhiteColor, capgrpMessage); + s:= ansistring(Gear^.Hedgehog^.Name); + AddCaption(FormatA(GetEventString(eidGone), s), cWhiteColor, capgrpMessage); end end; exit @@ -1290,7 +1328,7 @@ begin if Gear^.Timer = 0 then begin - Gear^.State:= Gear^.State and (not (gstWait or gstLoser or gstWinner or gstAttacked or gstNotKickable or gstHHChooseTarget)); + Gear^.State:= Gear^.State and (not (gstWait or gstLoser or gstWinner or gstAttacked or gstNotKickable or gstChooseTarget)); if Gear^.Hedgehog^.Effects[heFrozen] = 0 then Gear^.Active:= false; AddCI(Gear); exit @@ -1340,16 +1378,20 @@ procedure doStepHedgehog(Gear: PGear); var tX: hwFloat; begin +// it might make sense to skip more than just drowning check here +if (not Gear^.Hedgehog^.Unplaced) then + CheckGearDrowning(Gear); +if Gear = nil then exit; tX:= Gear^.X; if WorldWrap(Gear) then begin - if (WorldEdge <> weBounce) and (Gear = CurrentHedgehog^.Gear) and + if (WorldEdge <> weBounce) and (Gear = CurrentHedgehog^.Gear) and (CurAmmoGear <> nil) and (CurAmmoGear^.Kind =gtRope) and (CurAmmoGear^.Elasticity <> _0) then CurAmmoGear^.PortalCounter:= 1; if (WorldEdge = weWrap) and ((TestCollisionXwithGear(Gear, 1) <> 0) or (TestCollisionXwithGear(Gear, -1) <> 0)) then begin Gear^.X:= tX; - Gear^.dX.isNegative:= (hwRound(tX) > leftX+Gear^.Radius*2) + Gear^.dX.isNegative:= (hwRound(tX) > LongInt(leftX) + Gear^.Radius * 2) end end; diff -r 31570b766315 -r ed5a6478e710 hedgewars/uGearsList.pas --- a/hedgewars/uGearsList.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uGearsList.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,16 +13,17 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} unit uGearsList; interface -uses uFloat, uTypes; +uses uFloat, uTypes, SDLh; function AddGear(X, Y: LongInt; Kind: TGearType; State: Longword; dX, dY: hwFloat; Timer: LongWord): PGear; +function AddGear(X, Y: LongInt; Kind: TGearType; State: Longword; dX, dY: hwFloat; Timer, newUid: LongWord): PGear; procedure DeleteGear(Gear: PGear); procedure InsertGearToList(Gear: PGear); procedure RemoveGearFromList(Gear: PGear); @@ -41,6 +42,7 @@ (* gtHedgehog *) , amNothing (* gtMine *) , amMine (* gtCase *) , amNothing +(* gtAirMine *) , amAirMine (* gtExplosives *) , amNothing (* gtGrenade *) , amGrenade (* gtShell *) , amBazooka @@ -143,23 +145,40 @@ procedure RemoveGearFromList(Gear: PGear); begin -TryDo((curHandledGear = nil) or (Gear = curHandledGear), 'You''re doing it wrong', true); +if (Gear <> GearsList) and (Gear <> nil) and (Gear^.NextGear = nil) and (Gear^.PrevGear = nil) then + begin + AddFileLog('Attempted to remove Gear #'+inttostr(Gear^.uid)+' from the list twice.'); + exit + end; +TryDo((Gear = nil) or (curHandledGear = nil) or (Gear = curHandledGear), 'You''re doing it wrong', true); if Gear^.NextGear <> nil then Gear^.NextGear^.PrevGear:= Gear^.PrevGear; if Gear^.PrevGear <> nil then Gear^.PrevGear^.NextGear:= Gear^.NextGear else - GearsList:= Gear^.NextGear + GearsList:= Gear^.NextGear; + +Gear^.NextGear:= nil; +Gear^.PrevGear:= nil end; function AddGear(X, Y: LongInt; Kind: TGearType; State: Longword; dX, dY: hwFloat; Timer: LongWord): PGear; -var gear: PGear; begin -inc(GCounter); +AddGear:= AddGear(X, Y, Kind, State, dX, dY, Timer, 0); +end; +function AddGear(X, Y: LongInt; Kind: TGearType; State: Longword; dX, dY: hwFloat; Timer, newUid: LongWord): PGear; +var gear: PGear; + //c: byte; + cakeData: PCakeData; +begin +if newUid = 0 then + inc(GCounter); + AddFileLog('AddGear: #' + inttostr(GCounter) + ' (' + inttostr(x) + ',' + inttostr(y) + '), d(' + floattostr(dX) + ',' + floattostr(dY) + ') type = ' + EnumToStr(Kind)); + New(gear); FillChar(gear^, sizeof(TGear), 0); gear^.X:= int2hwFloat(X); @@ -173,13 +192,17 @@ gear^.doStep:= doStepHandlers[Kind]; gear^.CollisionIndex:= -1; gear^.Timer:= Timer; -gear^.uid:= GCounter; +if newUid = 0 then + gear^.uid:= GCounter +else gear^.uid:= newUid; gear^.SoundChannel:= -1; gear^.ImpactSound:= sndNone; gear^.Density:= _1; // Define ammo association, if any. gear^.AmmoType:= GearKindAmmoTypeMap[Kind]; gear^.CollisionMask:= $FFFF; +gear^.Tint:= $FFFFFFFF; +gear^.Data:= nil; if CurrentHedgehog <> nil then begin @@ -221,7 +244,11 @@ gear^.Timer:= 3000 end; gtMelonPiece: begin + gear^.AdvBounce:= 1; gear^.Density:= _2; + gear^.Elasticity:= _0_8; + gear^.Friction:= _0_995; + gear^.Radius:= 4 end; gtHedgehog: begin gear^.AdvBounce:= 1; @@ -234,6 +261,18 @@ if (GameFlags and gfAISurvival) <> 0 then if gear^.Hedgehog^.BotLevel > 0 then gear^.Hedgehog^.Effects[heResurrectable] := 1; + // this would presumably be set in the frontend + // if we weren't going to do that yet, would need to reinit GetRandom + // oh, and, randomising slightly R and B might be nice too. + //gear^.Tint:= $fa00efff or ((random(80)+128) shl 16) + //gear^.Tint:= $faa4efff + //gear^.Tint:= (($e0+random(32)) shl 24) or + // ((random(80)+128) shl 16) or + // (($d5+random(32)) shl 8) or $ff + {c:= GetRandom(32); + gear^.Tint:= (($e0+c) shl 24) or + ((GetRandom(90)+128) shl 16) or + (($d5+c) shl 8) or $ff} end; gtShell: begin gear^.Elasticity:= _0_8; @@ -261,16 +300,26 @@ if State and gstTmpFlag = 0 then begin dx.isNegative:= GetRandom(2) = 0; - dx.QWordValue:= $40DA * GetRandom(10000) * 8; + dx.QWordValue:= QWord($40DA) * GetRandom(10000) * 8; dy.isNegative:= false; - dy.QWordValue:= $3AD3 * GetRandom(7000) * 8; + dy.QWordValue:= QWord($3AD3) * GetRandom(7000) * 8; if GetRandom(2) = 0 then - dx := -dx - end; + dx := -dx; + Tint:= $FFFFFFFF + end + else + Tint:= (ExplosionBorderColor shr RShift and $FF shl 24) or + (ExplosionBorderColor shr GShift and $FF shl 16) or + (ExplosionBorderColor shr BShift and $FF shl 8) or $FF; State:= State or gstInvisible; - Health:= random(vobFrameTicks); + // use health field to store current frameticks + if vobFrameTicks > 0 then + Health:= random(vobFrameTicks) + else + Health:= 0; + // use timer to store currently displayed frame index if gear^.Timer = 0 then Timer:= random(vobFramesCount); - Damage:= (random(2) * 2 - 1) * (vobVelocity + random(vobVelocity)) * 8; + Damage:= (random(2) * 2 - 1) * (vobVelocity + random(vobVelocity)) * 8 end end; gtGrave: begin @@ -306,6 +355,8 @@ gear^.Radius:= 3; gear^.Friction:= _450 * _0_01 * cRopePercent; RopePoints.Count:= 0; + gear^.Tint:= $D8D8D8FF; + gear^.Tag:= 0; // normal rope render end; gtMine: begin gear^.ImpactSound:= sndMineImpact; @@ -324,6 +375,28 @@ gear^.Timer:= cMinesTime end end; + gtAirMine: begin + gear^.ImpactSound:= sndDenied; + gear^.nImpactSounds:= 1; + gear^.Health:= 30; + gear^.State:= gear^.State or gstMoving or gstNoGravity or gstSubmersible; + gear^.Radius:= 8; + gear^.Elasticity:= _0_55; + gear^.Friction:= _0_995; + gear^.Density:= _1; + gear^.Angle:= 175; // Radius at which air bombs will start "seeking". $FFFFFFFF = unlimited. check is skipped. + gear^.Power:= cMaxWindSpeed.QWordValue div 2; // hwFloat converted. 1/2 g default. defines the "seek" speed when a gear is in range. + gear^.Pos:= cMaxWindSpeed.QWordValue * 3 div 2; // air friction. slows it down when not hitting stuff + gear^.Karma:= 30; // damage + if gear^.Timer = 0 then + begin + if cMinesTime < 0 then + gear^.Timer:= getrandom(13)*100 + else + gear^.Timer:= cMinesTime div 4 + end; + gear^.WDTimer:= gear^.Timer + end; gtSMine: begin gear^.Health:= 10; gear^.State:= gear^.State or gstMoving; @@ -388,6 +461,7 @@ gear^.Radius:= 1; gear^.Health:= 5; gear^.Density:= _1; + gear^.FlightTime:= 9999999; // determines whether in-air flames do damage. disabled by default if (gear^.dY.QWordValue = 0) and (gear^.dX.QWordValue = 0) then begin gear^.dY:= (getrandomf - _0_8) * _0_03; @@ -395,13 +469,22 @@ end end; gtFirePunch: begin + if gear^.Timer = 0 then gear^.Timer:= 3000; gear^.Radius:= 15; gear^.Tag:= Y end; - gtAirAttack: gear^.Z:= cHHZ+2; + gtAirAttack: begin + gear^.Health:= 6; + gear^.Damage:= 30; + gear^.Z:= cHHZ+2; + gear^.Tint:= gear^.Hedgehog^.Team^.Clan^.Color shl 8 or $FF + end; gtAirBomb: begin + gear^.AdvBounce:= 1; gear^.Radius:= 5; gear^.Density:= _2; + gear^.Elasticity:= _0_55; + gear^.Friction:= _0_995 end; gtBlowTorch: begin gear^.Radius:= cHHRadius + cBlowTorchC; @@ -437,12 +520,14 @@ gear^.Health:= 2048; gear^.Radius:= 7; gear^.Z:= cOnHHZ; - gear^.RenderTimer:= true; + gear^.RenderTimer:= false; gear^.DirAngle:= -90 * hwSign(Gear^.dX); if not dX.isNegative then gear^.Angle:= 1 else - gear^.Angle:= 3 + gear^.Angle:= 3; + New(cakeData); + gear^.Data:= Pointer(cakeData); end; gtHellishBomb: begin gear^.ImpactSound:= sndHellishImpact1; @@ -483,7 +568,8 @@ gtRCPlane: begin if gear^.Timer = 0 then gear^.Timer:= 15000; gear^.Health:= 3; - gear^.Radius:= 8 + gear^.Radius:= 8; + gear^.Tint:= gear^.Hedgehog^.Team^.Clan^.Color shl 8 or $FF end; gtJetpack: begin gear^.Health:= 2000; @@ -491,13 +577,14 @@ gear^.State:= Gear^.State or gstSubmersible end; gtMolotov: begin + gear^.AdvBounce:= 1; gear^.Radius:= 6; - gear^.Density:= _2; + gear^.Density:= _2 end; gtBirdy: begin gear^.Radius:= 16; // todo: check gear^.Health := 2000; - gear^.FlightTime := 2; + gear^.FlightTime := 2 end; gtEgg: begin gear^.AdvBounce:= 1; @@ -511,7 +598,6 @@ gtPortal: begin gear^.ImpactSound:= sndMelonImpact; gear^.nImpactSounds:= 1; - gear^.AdvBounce:= 0; gear^.Radius:= 17; // set color gear^.Tag:= 2 * gear^.Timer; @@ -542,16 +628,17 @@ gtPoisonCloud: begin if gear^.Timer = 0 then gear^.Timer:= 5000; gear^.dY:= int2hwfloat(-4 + longint(getRandom(8))) / 1000; + gear^.Tint:= $C0C000C0 end; gtResurrector: begin gear^.Radius := 100; - gear^.Tag := 0 + gear^.Tag := 0; + gear^.Tint:= $F5DB35FF end; gtWaterUp: begin gear^.Tag := 47; end; gtNapalmBomb: begin - gear^.AdvBounce:= 1; gear^.Elasticity:= _0_8; gear^.Friction:= _0_8; if gear^.Timer = 0 then gear^.Timer:= 1000; @@ -593,14 +680,40 @@ var team: PTeam; t,i: Longword; k: boolean; + cakeData: PCakeData; + iterator: PGear; begin ScriptCall('onGearDelete', gear^.uid); DeleteCI(Gear); -FreeTexture(Gear^.Tex); -Gear^.Tex:= nil; +FreeAndNilTexture(Gear^.Tex); + +// remove potential links to this gear +// currently relevant to: gears linked by hammer +if (Gear^.Kind = gtHedgehog) or (Gear^.Kind = gtMine) or (Gear^.Kind = gtExplosives) then + begin + // check all gears for stuff to port through + iterator := nil; + while true do + begin + + // iterate through GearsList + if iterator = nil then + iterator := GearsList + else + iterator := iterator^.NextGear; + + // end of list? + if iterator = nil then + break; + + if iterator^.LinkedGear = Gear then + iterator^.LinkedGear:= nil; + end; + + end; // make sure that portals have their link removed before deletion if (Gear^.Kind = gtPortal) then @@ -609,6 +722,12 @@ if (Gear^.LinkedGear^.LinkedGear = Gear) then Gear^.LinkedGear^.LinkedGear:= nil; end +else if Gear^.Kind = gtCake then + begin + cakeData:= PCakeData(Gear^.Data); + Dispose(cakeData); + cakeData:= nil; + end else if Gear^.Kind = gtHedgehog then (* This behaviour dates back to revision 4, and I accidentally encountered it with TARDIS. I don't think it must apply to any modern weapon, since if it was actually hit, the best the gear could do would be to destroy itself immediately, and you'd still end up with two graves. I believe it should be removed @@ -621,19 +740,18 @@ end else*) begin - if (Gear <> CurrentHedgehog^.Gear) or (CurAmmoGear = nil) or (CurAmmoGear^.Kind <> gtKamikaze) then + if ((CurrentHedgehog = nil) or (Gear <> CurrentHedgehog^.Gear)) or (CurAmmoGear = nil) or (CurAmmoGear^.Kind <> gtKamikaze) then Gear^.Hedgehog^.Team^.Clan^.Flawless:= false; - if (hwRound(Gear^.Y) >= cWaterLine) then + if CheckCoordInWater(hwRound(Gear^.X), hwRound(Gear^.Y)) then begin t:= max(Gear^.Damage, Gear^.Health); Gear^.Damage:= t; - if ((not SuddenDeathDmg and (WaterOpacity < $FF)) or (SuddenDeathDmg and (WaterOpacity < $FF))) - and (hwRound(Gear^.Y) < cWaterLine + 256) then + if (((not SuddenDeathDmg) and (WaterOpacity < $FF)) or (SuddenDeathDmg and (SDWaterOpacity < $FF))) then spawnHealthTagForHH(Gear, t); end; team:= Gear^.Hedgehog^.Team; - if CurrentHedgehog^.Gear = Gear then + if (CurrentHedgehog <> nil) and (CurrentHedgehog^.Gear = Gear) then begin AttackBar:= 0; FreeActionsList; // to avoid ThinkThread on drawned gear @@ -643,6 +761,7 @@ end; Gear^.Hedgehog^.Gear:= nil; + if Gear^.Hedgehog^.King then begin // are there any other kings left? Just doing nil check. Presumably a mortally wounded king will get reaped soon enough @@ -652,17 +771,19 @@ k:= true; if not k then for i:= 0 to Pred(team^.Clan^.TeamsNumber) do - begin - team^.Clan^.Teams[i]^.hasGone:= true; - TeamGoneEffect(team^.Clan^.Teams[i]^) - end + with team^.Clan^.Teams[i]^ do + for t:= 0 to cMaxHHIndex do + if Hedgehogs[t].Gear <> nil then + Hedgehogs[t].Gear^.Health:= 0 + else if (Hedgehogs[t].GearHidden <> nil) then + Hedgehogs[t].GearHidden^.Health:= 0 // hog is still hidden. if tardis should return though, lua, eh... end; // should be not CurrentHedgehog, but hedgehog of the last gear which caused damage to this hog // same stand for CheckHHDamage - if (Gear^.LastDamage <> nil) then + if (Gear^.LastDamage <> nil) and (CurrentHedgehog <> nil) then uStats.HedgehogDamaged(Gear, Gear^.LastDamage, 0, true) - else + else if CurrentHedgehog <> nil then uStats.HedgehogDamaged(Gear, CurrentHedgehog, 0, true); inc(KilledHHs); @@ -673,8 +794,8 @@ with CurrentHedgehog^ do begin inc(Team^.stats.AIKills); - FreeTexture(Team^.AIKillsTex); - Team^.AIKillsTex := RenderStringTex(inttostr(Team^.stats.AIKills), Team^.Clan^.Color, fnt16); + FreeAndNilTexture(Team^.AIKillsTex); + Team^.AIKillsTex := RenderStringTex(ansistring(inttostr(Team^.stats.AIKills)), Team^.Clan^.Color, fnt16); end end; with Gear^ do @@ -688,7 +809,10 @@ FollowGear:= nil; if lastGearByUID = Gear then lastGearByUID := nil; -RemoveGearFromList(Gear); +if (Gear^.Hedgehog = nil) or (Gear^.Hedgehog^.GearHidden <> Gear) then // hidden hedgehogs shouldn't be in the list + RemoveGearFromList(Gear) +else Gear^.Hedgehog^.GearHidden:= nil; + Dispose(Gear) end; diff -r 31570b766315 -r ed5a6478e710 hedgewars/uGearsRender.pas --- a/hedgewars/uGearsRender.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uGearsRender.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,19 +1,19 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License * - * This program is distributed in the hope that it will be useful, + * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} @@ -23,7 +23,20 @@ interface uses uTypes, uConsts, GLunit, uFloat, SDLh; +type + Tar = record + X, Y: hwFloat; + dLen: hwFloat; + b : boolean; + end; + TRopePoints = record + Count : Longword; + HookAngle : GLfloat; + ar : array[0..MAXROPEPOINTS] of Tar; + rounded : array[0..MAXROPEPOINTS + 2] of TVertex2f; + end; procedure RenderGear(Gear: PGear; x, y: LongInt); +procedure DrawHHOrder(); var RopePoints: record Count: Longword; @@ -41,6 +54,7 @@ uses uRender, uUtils, uVariables, uAmmos, Math, uVisualGearsList; procedure DrawRopeLinesRQ(Gear: PGear); +var n: LongInt; begin with RopePoints do begin @@ -52,24 +66,30 @@ if (RopePoints.Count > 0) or (Gear^.Elasticity.QWordValue > 0) then begin - glDisable(GL_TEXTURE_2D); + EnableTexture(false); //glEnable(GL_LINE_SMOOTH); - glPushMatrix; + + Tint(Gear^.Tint shr 24 div 3, Gear^.Tint shr 16 and $FF div 3, Gear^.Tint shr 8 and $FF div 3, Gear^.Tint and $FF); - glTranslatef(WorldDx, WorldDy, 0); + n:= RopePoints.Count + 2; + + SetVertexPointer(@RopePoints.rounded[0], n); - glLineWidth(4.0); + openglPushMatrix(); + openglTranslatef(WorldDx, WorldDy, 0); - Tint($C0, $C0, $C0, $FF); + glLineWidth(3.0 * cScaleFactor); + glDrawArrays(GL_LINE_STRIP, 0, n); + Tint(Gear^.Tint); + glLineWidth(2.0 * cScaleFactor); + glDrawArrays(GL_LINE_STRIP, 0, n); - glVertexPointer(2, GL_FLOAT, 0, @RopePoints.rounded[0]); - glDrawArrays(GL_LINE_STRIP, 0, RopePoints.Count + 2); untint; - glPopMatrix; + openglPopMatrix(); - glEnable(GL_TEXTURE_2D); + EnableTexture(true); //glDisable(GL_LINE_SMOOTH) end end; @@ -83,6 +103,7 @@ if (X1 = X2) and (Y1 = Y2) then begin //OutError('WARNING: zero length rope line!', false); + DrawRopeLine:= 0; exit end; eX:= 0; @@ -143,14 +164,14 @@ DrawSprite(sprRopeNode, x - 2, y - 2, 0) end end; -DrawRopeLine:= roplen; + DrawRopeLine:= roplen; end; procedure DrawRope(Gear: PGear); -var roplen: LongInt; - i: Longword; +var roplen, i: LongInt; begin - if (cReducedQuality and rqSimpleRope) <> 0 then + if Gear^.Hedgehog^.Gear = nil then exit; + if (Gear^.Tag = 1) or ((cReducedQuality and rqSimpleRope) <> 0) then DrawRopeLinesRQ(Gear) else begin @@ -195,6 +216,48 @@ end; end; +procedure DrawHHOrder(); +var HHGear: PGear; + hh: PHedgehog; + c, i, t, x, y, sprH, sprW, fSprOff: LongInt; +begin +t:= LocalTeam; + +if not CurrentTeam^.ExtDriven then + for i:= 0 to Pred(TeamsCount) do + if (TeamsArray[i] = CurrentTeam) then + t:= i; + +if t < 0 then + exit; + +if TeamsArray[t] <> nil then + begin + sprH:= SpritesData[sprBigDigit].Height; + sprW:= SpritesData[sprBigDigit].Width; + fSprOff:= sprW div 4 + SpritesData[sprFrame].Width div 4 - 1; // - 1 for overlap to avoid artifacts + i:= 0; + c:= 0; + repeat + hh:= @TeamsArray[t]^.Hedgehogs[i]; + inc(i); + if (hh <> nil) and (hh^.Gear <> nil) then + begin + inc(c); + HHGear:= hh^.Gear; + x:= hwRound(HHGear^.X) + WorldDx; + y:= hwRound(HHGear^.Y) + WorldDy - 2; + DrawTextureF(SpritesData[sprFrame].Texture, 0.5, x - fSprOff, y, 0, 1, SpritesData[sprFrame].Width, SpritesData[sprFrame].Height); + DrawTextureF(SpritesData[sprFrame].Texture, 0.5, x + fSprOff, y, 1, 1, SpritesData[sprFrame].Width, SpritesData[sprFrame].Height); + DrawTextureF(SpritesData[sprBigDigit].Texture, 0.5, x, y, c, 1, sprW, sprH); + if SpeechHogNumber = c then + DrawCircle(x, y, 20, 3, 0, $FF, $FF, $80); + end; + until (i > cMaxHHIndex); + end + +end; + procedure DrawHH(Gear: PGear; ox, oy: LongInt); var i, t: LongInt; @@ -206,10 +269,14 @@ CurWeapon: PAmmo; iceOffset:Longint; r:TSDL_Rect; + curhat: PTexture; begin HH:= Gear^.Hedgehog; if HH^.Unplaced then exit; + if (HH^.CurAmmoType = amKnife) and (HH = CurrentHedgehog) then + curhat:= ChefHatTexture + else curhat:= HH^.HatTex; m:= 1; if ((Gear^.State and gstHHHJump) <> 0) and (not cArtillery) then m:= -1; @@ -262,7 +329,7 @@ if HH^.Effects[hePoisoned] <> 0 then begin Tint($00, $FF, $40, $40); - DrawTextureRotatedF(SpritesData[sprSmokeWhite].texture, 2, 0, 0, sx, sy, 0, 1, 22, 22, (RealTicks shr 36) mod 360); + DrawTextureRotatedF(SpritesData[sprSmokeWhite].texture, 2, 0, 0, sx, sy, 0, 1, 22, 22, (RealTicks shr 4) mod 360); untint end; @@ -301,6 +368,8 @@ if ((Gear^.State and (gstHHThinking or gstAnimation)) = 0) and /// If current ammo is active, and current ammo has alt attack and uses a crosshair (rope, basically, right now, with no crosshair for parachute/saucer (((CurAmmoGear <> nil) and //((Ammoz[CurAmmoGear^.AmmoType].Ammo.Propz and ammoprop_AltAttack) <> 0) and + // don't render crosshair/laser during kamikaze + ((CurAmmoGear^.AmmoType <> amKamikaze) or ((Gear^.State and gstAttacking) = 0)) and ((Ammoz[CurAmmoGear^.AmmoType].Ammo.Propz and ammoprop_NoCrossHair) = 0)) or /// If no current ammo is active, and the selected ammo uses a crosshair ((CurAmmoGear = nil) and ((Ammoz[HH^.CurAmmoType].Ammo.Propz and ammoprop_NoCrosshair) = 0) and ((Gear^.State and gstAttacked) = 0))) then @@ -416,14 +485,14 @@ 0, DxDy2Angle(CurAmmoGear^.dY, CurAmmoGear^.dX) + dAngle); with HH^ do - if (HatTex <> nil) then + if (curhat <> nil) then begin - DrawTextureRotatedF(HatTex, 1.0, -1.0, -6.0, ox, oy, 0, i, 32, 32, + DrawTextureRotatedF(curhat, 1.0, -1.0, -6.0, ox, oy, 0, i, 32, 32, i*DxDy2Angle(CurAmmoGear^.dY, CurAmmoGear^.dX) + hAngle); - if HatTex^.w > 64 then + if curhat^.w > 64 then begin Tint(HH^.Team^.Clan^.Color shl 8 or $FF); - DrawTextureRotatedF(HatTex, 1.0, -1.0, -6.0, ox, oy, 32, i, 32, 32, + DrawTextureRotatedF(curhat, 1.0, -1.0, -6.0, ox, oy, 32, i, 32, 32, i*DxDy2Angle(CurAmmoGear^.dY, CurAmmoGear^.dX) + hAngle); untint end @@ -441,9 +510,9 @@ HH^.visStepPos div 2, 0); with HH^ do - if (HatTex <> nil) then + if (curhat <> nil) then begin - DrawTextureF(HatTex, + DrawTextureF(curhat, 1, sx, sy - 5, @@ -451,10 +520,10 @@ sign, 32, 32); - if HatTex^.w > 64 then + if curhat^.w > 64 then begin Tint(HH^.Team^.Clan^.Color shl 8 or $FF); - DrawTextureF(HatTex, + DrawTextureF(curhat, 1, sx, sy - 5, @@ -599,7 +668,7 @@ if ((Gear^.State and gstAnimation) <> 0) then begin - if (TWave(Gear^.Tag) < Low(TWave)) or (TWave(Gear^.Tag) > High(TWave)) then + if (Gear^.Tag < LongInt(ord(Low(TWave)))) or (Gear^.Tag > LongInt(ord(High(TWave)))) then begin Gear^.State:= Gear^.State and (not gstAnimation); end @@ -659,6 +728,7 @@ amHellishBomb: DrawSpriteRotated(sprHandHellish, hx, hy, sign, aangle); amGasBomb: DrawSpriteRotated(sprHandCheese, hx, hy, sign, aangle); amMine: DrawSpriteRotated(sprHandMine, hx, hy, sign, aangle); + amAirMine: DrawSpriteRotated(sprHandAirMine, hx, hy, sign, aangle); amSMine: DrawSpriteRotated(sprHandSMine, hx, hy, sign, aangle); amKnife: DrawSpriteRotatedF(sprHandKnife, hx, hy, 0, sign, aangle); amSeduction: begin @@ -676,32 +746,39 @@ amRubber, amGirder: begin DrawSpriteRotated(sprHandConstruction, hx, hy, sign, aangle); - if WorldEdge = weWrap then + if cBuildMaxDist = cDefaultBuildMaxDist then begin - if hwRound(Gear^.X) < leftX+256 then - DrawSpriteClipped(sprGirder, - rightX+(ox-leftX)-256, - oy-256, - LongInt(topY)+WorldDy, - LongInt(rightX)+WorldDx, - cWaterLine+WorldDy, - LongInt(leftX)+WorldDx); - if hwRound(Gear^.X) > rightX-256 then - DrawSpriteClipped(sprGirder, - leftX-(rightX-ox)-256, - oy-256, - LongInt(topY)+WorldDy, - LongInt(rightX)+WorldDx, - cWaterLine+WorldDy, - LongInt(leftX)+WorldDx) + if WorldEdge = weWrap then + begin + if hwRound(Gear^.X) < LongInt(leftX) + 256 then + DrawSpriteClipped(sprGirder, + rightX+(ox-leftX)-256, + oy-256, + LongInt(topY)+WorldDy, + LongInt(rightX)+WorldDx, + cWaterLine+WorldDy, + LongInt(leftX)+WorldDx); + if hwRound(Gear^.X) > LongInt(rightX) - 256 then + DrawSpriteClipped(sprGirder, + leftX-(rightX-ox)-256, + oy-256, + LongInt(topY)+WorldDy, + LongInt(rightX)+WorldDx, + cWaterLine+WorldDy, + LongInt(leftX)+WorldDx) + end; + DrawSpriteClipped(sprGirder, + ox-256, + oy-256, + LongInt(topY)+WorldDy, + LongInt(rightX)+WorldDx, + cWaterLine+WorldDy, + LongInt(leftX)+WorldDx) + end + else if cBuildMaxDist > 0 then + begin + DrawCircle(hx, hy, cBuildMaxDist, 3, $FF, 0, 0, $80); end; - DrawSpriteClipped(sprGirder, - ox-256, - oy-256, - LongInt(topY)+WorldDy, - LongInt(rightX)+WorldDx, - cWaterLine+WorldDy, - LongInt(leftX)+WorldDx) end; amBee: DrawSpriteRotatedF(sprHandBee, hx, hy, (RealTicks div 125) mod 4, sign, aangle); amFlamethrower: DrawSpriteRotatedF(sprHandFlamethrower, hx, hy, (RealTicks div 125) mod 4, sign, aangle); @@ -772,13 +849,17 @@ if (Gear^.Damage > 0) and (HH^.Effects[heFrozen] = 0) and (hwSqr(Gear^.dX) + hwSqr(Gear^.dY) > _0_003) then begin - DrawHedgehog(sx, sy, - sign, - 2, - 1, - Gear^.DirAngle); - defaultPos:= false - end else + defaultPos:= false; + DrawHedgehog(sx, sy, + sign, + 2, + 1, + Gear^.DirAngle); + if AprilOne and (curhat <> nil) then + DrawTextureRotatedF(curhat, 1.0, -1.0, 0, sx, sy, 18, sign, 32, 32, + sign*Gear^.DirAngle) + end; + if ((Gear^.State and gstHHJumping) <> 0) then begin @@ -795,7 +876,7 @@ begin if defaultPos then begin - if HH^.Team^.hasGone then Tint($FF, $FF, $FF, $80); + if HH^.Team^.hasGone then Tint($FFFFFF80); DrawSpriteRotatedF(sprHHIdle, sx, sy, @@ -813,11 +894,11 @@ if HatVisibility > 0.0 then HatVisibility:= HatVisibility - 0.2; - if (HatTex <> nil) + if (curhat <> nil) and (HatVisibility > 0) then if DefaultPos then begin - DrawTextureF(HatTex, + DrawTextureF(curhat, HatVisibility, sx, sy - 5, @@ -825,10 +906,10 @@ sign, 32, 32); - if HatTex^.w > 64 then + if curhat^.w > 64 then begin Tint(HH^.Team^.Clan^.Color shl 8 or $FF); - DrawTextureF(HatTex, + DrawTextureF(curhat, HatVisibility, sx, sy - 5, @@ -842,7 +923,7 @@ end else begin - DrawTextureF(HatTex, + DrawTextureF(curhat, HatVisibility, sx, sy - 5, @@ -850,10 +931,10 @@ sign*m, 32, 32); - if HatTex^.w > 64 then + if curhat^.w > 64 then begin Tint(HH^.Team^.Clan^.Color shl 8 or $FF); - DrawTextureF(HatTex, + DrawTextureF(curhat, HatVisibility, sx, sy - 5, @@ -929,8 +1010,38 @@ DrawTextureCentered(ox, sy - cHHRadius - 7 - HealthTagTex^.h, HealthTagTex); if bShowFinger and ((Gear^.State and gstHHDriven) <> 0) then - DrawSprite(sprFinger, ox - 16, oy - 64, - GameTicks div 32 mod 16); + begin + ty := oy - 32; + // move finger higher up if tags are above hog + if (cTagsMask and htTeamName) <> 0 then + ty := ty - Team^.NameTagTex^.h - 2; + if (cTagsMask and htName) <> 0 then + ty := ty - NameTagTex^.h - 2; + if (cTagsMask and htHealth) <> 0 then + ty := ty - HealthTagTex^.h - 2; + tx := ox; + + // don't go offscreen + //tx := round(max(((-cScreenWidth + 16) / cScaleFactor) + SpritesData[sprFinger].Width div 2, min(((cScreenWidth - 16) / cScaleFactor) - SpritesData[sprFinger].Width div 2, tx))); + //ty := round(max(cScreenHeight div 2 - ((cScreenHeight - 16) / cScaleFactor) + SpritesData[sprFinger].Height div 2, min(cScreenHeight div 2 - ((-cScreenHeight + SpritesData[sprFinger].Height) / (cScaleFactor)) - SpritesData[sprFinger].Width div 2 - 96, ty))); + t:= 32;//trunc((SpritesData[sprFinger].Width + t) / cScaleFactor); + tx := min(max(tx, ViewLeftX + t), ViewRightX - t); + t:= 32;//trunc((SpritesData[sprFinger].Height + t) / cScaleFactor); + ty := min(ty, ViewBottomY - 96); + // don't overlap with HH or HH tags + if ty < ViewTopY + t then + begin + if abs(tx - ox) < abs(ty - oy) then + ty:= max(ViewTopY + t, oy + t) + else + ty:= max(ViewTopY + t, ty); + end; + + dAngle := DxDy2Angle(int2hwfloat(ty - oy), int2hwfloat(tx - ox)) + 90; + + DrawSpriteRotatedF(sprFinger, tx, ty, RealTicks div 32 mod 16, 1, dAngle); + end; + if (Gear^.State and gstDrowning) = 0 then if (Gear^.State and gstHHThinking) <> 0 then @@ -941,7 +1052,7 @@ if HH^.Effects[hePoisoned] <> 0 then begin Tint($00, $FF, $40, $80); - DrawTextureRotatedF(SpritesData[sprSmokeWhite].texture, 1.5, 0, 0, sx, sy, 0, 1, 22, 22, 360 - (RealTicks shr 37) mod 360); + DrawTextureRotatedF(SpritesData[sprSmokeWhite].texture, 1.5, 0, 0, sx, sy, 0, 1, 22, 22, 360 - (RealTicks shr 5) mod 360); end; if HH^.Effects[heResurrected] <> 0 then begin @@ -965,10 +1076,7 @@ r.y := 96 - iceOffset; r.w := 32; r.h := iceOffset; - if sign = -1 then - DrawTextureFromRectDir(sx + sign*2, sy+16-iceoffset, r.w, r.h, @r, HHTexture, sign) - else - DrawTextureFromRectDir(sx-16 + sign*2, sy+16-iceoffset, r.w, r.h, @r, HHTexture, sign); + DrawTextureFromRectDir(sx - 16 + sign*2, sy + 16 - iceoffset, r.w, r.h, @r, HHTexture, sign); if HH^.Effects[heFrozen] < 150000 then @@ -1019,7 +1127,7 @@ gtRCPlane: begin aangle:= Gear^.Angle * 360 / 4096; if Gear^.Tag < 0 then aangle:= 360-aangle; - Tint(Gear^.Hedgehog^.Team^.Clan^.Color shl 8 or $FF); + Tint(Gear^.Tint); DrawSpriteRotatedF(sprPlane, x, y, 0, Gear^.Tag, aangle - 90); untint; DrawSpriteRotatedF(sprPlane, x, y, 1, Gear^.Tag, aangle - 90) @@ -1063,6 +1171,18 @@ DrawSpriteRotated(sprMineOn, x, y, 0, Gear^.DirAngle) else DrawSpriteRotated(sprMineDead, x, y, 0, Gear^.DirAngle); end; + gtAirMine: if Gear^.State and gstTmpFlag = 0 then // mine is inactive + begin + Tint(150,150,150,255); + DrawSprite(sprAirMine, x-16, y-16, 15); + untint + end + else if (Gear^.Hedgehog <> nil) and (Gear^.Hedgehog^.Gear <> nil) then // mine is chasing a hog + DrawSprite(sprAirMine, x-16, y-16, (RealTicks div 25) mod 16) + else if Gear^.State and gstChooseTarget <> 0 then // mine is seeking for hogs + DrawSprite(sprAirMine, x-16, y-16, (RealTicks div 125) mod 16) + else + DrawSprite(sprAirMine, x-16, y-16, 4); // mine is active but not seeking gtSMine: if (((Gear^.State and gstAttacking) = 0)or((Gear^.Timer and $3FF) < 420)) and (Gear^.Health <> 0) then DrawSpriteRotated(sprSMineOff, x, y, 0, Gear^.DirAngle) @@ -1111,7 +1231,7 @@ end; if Gear^.Timer < 1833 then begin - DrawTextureRotatedF(SpritesData[sprPortal].texture, min(abs(1.25 - (Gear^.Timer mod 1333) / 400), 1.25), 0, 0, + DrawTextureRotatedF(SpritesData[sprPortal].texture, MinD(abs(1.25 - (Gear^.Timer mod 1333) / 400), 1.25), 0, 0, x, LongInt(Gear^.Angle) + WorldDy - 16, 4 + Gear^.Tag, 1, 32, 32, 270); end end; @@ -1141,7 +1261,7 @@ DrawAltWeapon(Gear, x + 1, y - 3) end; gtAirAttack: begin - Tint(Gear^.Hedgehog^.Team^.Clan^.Color shl 8 or $FF); + Tint(Gear^.Tint); DrawSpriteRotatedF(sprAirplane, x, y, 0, Gear^.Tag, 0); untint; DrawSpriteRotatedF(sprAirplane, x, y, 1, Gear^.Tag, 0); @@ -1149,9 +1269,12 @@ gtAirBomb: DrawSpriteRotated(sprAirBomb, x, y, 0, DxDy2Angle(Gear^.dY, Gear^.dX)); gtTeleport: begin HHGear:= Gear^.Hedgehog^.Gear; - if not Gear^.Hedgehog^.Unplaced then - DrawSpriteRotatedF(sprTeleport, x + 1, y - 3, Gear^.Pos, hwSign(Gear^.dX), 0); - DrawSpriteRotatedF(sprTeleport, hwRound(HHGear^.X) + 1 + WorldDx, hwRound(HHGear^.Y) - 3 + WorldDy, 11 - Gear^.Pos, hwSign(HHGear^.dX), 0); + if HHGear <> nil then + begin + if ((Gear^.State and gstAnimation) <> 0) then + DrawSpriteRotatedF(sprTeleport, x + 1, y - 3, Gear^.Pos, hwSign(Gear^.dX), 0); + DrawSpriteRotatedF(sprTeleport, hwRound(HHGear^.X) + 1 + WorldDx, hwRound(HHGear^.Y) - 3 + WorldDy, 11 - Gear^.Pos, hwSign(HHGear^.dX), 0) + end end; gtSwitcher: DrawSprite(sprSwitch, x - 16, y - 56, (GameTicks shr 6) mod 12); gtTarget: begin @@ -1217,27 +1340,24 @@ end; gtPoisonCloud: begin if Gear^.Timer < 1020 then - Tint($C0, $C0, $00, Gear^.Timer div 8) + Tint(Gear^.Tint and $FFFFFF00 or Gear^.Timer div 8) else if Gear^.Timer > 3980 then - Tint($C0, $C0, $00, (5000 - Gear^.Timer) div 8) + Tint(Gear^.Tint and $FFFFFF00 or (5000 - Gear^.Timer) div 8) else - Tint($C0, $C0, $00, $C0); - DrawTextureRotatedF(SpritesData[sprSmokeWhite].texture, 3, 0, 0, x, y, 0, 1, 22, 22, (RealTicks shr 36 + Gear^.UID * 100) mod 360); + Tint(Gear^.Tint); + DrawTextureRotatedF(SpritesData[sprSmokeWhite].texture, 3, 0, 0, x, y, 0, 1, 22, 22, (RealTicks shr 4 + Gear^.UID * 100) mod 360); untint end; gtResurrector: begin DrawSpriteRotated(sprCross, x, y, 0, 0); - Tint($f5, $db, $35, max($00, round($C0 * abs(1 - (GameTicks mod 6000) / 3000)))); + Tint(Gear^.Tint and $FFFFFF00 or max($00, round($C0 * abs(1 - (GameTicks mod 6000) / 3000)))); DrawTexture(x - 108, y - 108, SpritesData[sprVampiric].Texture, 4.5); untint; end; gtNapalmBomb: DrawSpriteRotated(sprNapalmBomb, x, y, 0, DxDy2Angle(Gear^.dY, Gear^.dX)); gtFlake: if Gear^.State and (gstDrowning or gstTmpFlag) <> 0 then begin - Tint((ExplosionBorderColor shr RShift) and $FF, - (ExplosionBorderColor shr GShift) and $FF, - (ExplosionBorderColor shr BShift) and $FF, - $FF); + Tint(Gear^.Tint); // Needs a nicer white texture to tint DrawTextureRotatedF(SpritesData[sprSnowDust].Texture, 1, 0, 0, x, y, 0, 1, 8, 8, Gear^.DirAngle); //DrawSpriteRotated(sprSnowDust, x, y, 0, Gear^.DirAngle); @@ -1248,7 +1368,7 @@ begin if isInLag and (Gear^.FlightTime < 256) then inc(Gear^.FlightTime, 8) - else if not isInLag and (Gear^.FlightTime > 0) then + else if (not isInLag) and (Gear^.FlightTime > 0) then dec(Gear^.FlightTime, 8); if Gear^.FlightTime > 0 then Tint($FF, $FF, $FF, $FF-min(255,Gear^.FlightTime)); @@ -1268,12 +1388,12 @@ Tint(Gear^.Hedgehog^.Team^.Clan^.Color shl 8 or $FF) else Tint(Gear^.Hedgehog^.Team^.Clan^.Color shl 8 or max($00, round(Gear^.Power * (1-abs(0.5 - (GameTicks mod 2000) / 2000))))); - DrawSprite(sprTardis, x-24, y-63,0); + DrawSprite(sprTardis, x-25, y-64,0); if Gear^.Pos = 2 then untint else Tint($FF,$FF,$FF,max($00, round(Gear^.Power * (1-abs(0.5 - (GameTicks mod 2000) / 2000))))); - DrawSprite(sprTardis, x-24, y-63,1); + DrawSprite(sprTardis, x-25, y-64,1); if Gear^.Pos <> 2 then untint (* diff -r 31570b766315 -r ed5a6478e710 hedgewars/uGearsUtils.pas --- a/hedgewars/uGearsUtils.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uGearsUtils.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} @@ -23,7 +23,9 @@ uses uTypes, uFloat; procedure doMakeExplosion(X, Y, Radius: LongInt; AttackingHog: PHedgehog; Mask: Longword); inline; -procedure doMakeExplosion(X, Y, Radius: LongInt; AttackingHog: PHedgehog; Mask: Longword; const Tint: LongWord); +procedure doMakeExplosion(X, Y, Radius: LongInt; AttackingHog: PHedgehog; Mask: Longword; const Tint: LongWord); +procedure AddSplashForGear(Gear: PGear; justSkipping: boolean); +procedure AddBounceEffectForGear(Gear: PGear); function ModifyDamage(dmg: Longword; Gear: PGear): Longword; procedure ApplyDamage(Gear: PGear; AttackerHog: PHedgehog; Damage: Longword; Source: TDamageSource); @@ -47,8 +49,8 @@ procedure ShotgunShot(Gear: PGear); procedure SetAllToActive; -procedure SetAllHHToActive; inline; procedure SetAllHHToActive(Ice: boolean); +procedure SetAllHHToActive(); inline; function GetAmmo(Hedgehog: PHedgehog): TAmmoType; function GetUtility(Hedgehog: PHedgehog): TAmmoType; @@ -64,7 +66,7 @@ implementation uses uSound, uCollisions, uUtils, uConsts, uVisualGears, uAIMisc, uVariables, uLandGraphics, uScript, uStats, uCaptions, uTeams, uStore, - uLocale, uTextures, uRenderUtils, uRandom, SDLh, uDebug, + uLocale, uTextures, uRenderUtils, uRandom, SDLh, uDebug, uGearsList, Math, uVisualGearsList, uGearsHandlersMess, uGearsHedgehog; @@ -79,6 +81,8 @@ fX, fY, tdX, tdY: hwFloat; vg: PVisualGear; i, cnt: LongInt; + wrap: boolean; + bubble: PVisualGear; begin if Radius > 4 then AddFileLog('Explosion: at (' + inttostr(x) + ',' + inttostr(y) + ')'); if Radius > 25 then KickFlakes(Radius, X, Y); @@ -86,7 +90,17 @@ if ((Mask and EXPLNoGfx) = 0) then begin vg:= nil; - if Radius > 50 then vg:= AddVisualGear(X, Y, vgtBigExplosion) + if CheckCoordInWater(X, Y - Radius) then + begin + cnt:= 2 * Radius; + for i:= (Radius * Radius) div 4 downto 0 do + begin + bubble := AddVisualGear(X - Radius + random(cnt), Y - Radius + random(cnt), vgtBubble); + if bubble <> nil then + bubble^.dY:= 0.1 + random(20)/10; + end + end + else if Radius > 50 then vg:= AddVisualGear(X, Y, vgtBigExplosion) else if Radius > 10 then vg:= AddVisualGear(X, Y, vgtExplosion); if vg <> nil then vg^.Tint:= Tint; @@ -99,9 +113,15 @@ dmgRadius:= Radius; dmgBase:= dmgRadius + cHHRadius div 2;*) dmgBase:= Radius shl 1 + cHHRadius div 2; + +// we might have to run twice if weWrap is enabled +wrap:= false; +repeat + fX:= int2hwFloat(X); fY:= int2hwFloat(Y); Gear:= GearsList; + while Gear <> nil do begin dmg:= 0; @@ -118,6 +138,7 @@ gtClusterBomb, // gtCluster, too game breaking I think gtSMine, + gtAirMine, gtCase, gtTarget, gtFlame, @@ -135,7 +156,7 @@ //AddFileLog('Damage: ' + inttostr(dmg)); if (Mask and EXPLNoDamage) = 0 then begin - if Gear^.Hedgehog^.Effects[heInvulnerable] = 0 then + if (Gear^.Kind <> gtHedgehog) or (Gear^.Hedgehog^.Effects[heInvulnerable] = 0) then ApplyDamage(Gear, AttackingHog, dmg, dsExplosion) else Gear^.State:= Gear^.State or gstWinner; @@ -148,29 +169,30 @@ Gear^.State:= (Gear^.State or gstMoving) and (not gstLoser); if Gear^.Kind = gtKnife then Gear^.State:= Gear^.State and (not gstCollision); - if Gear^.Hedgehog^.Effects[heInvulnerable] = 0 then + if (Gear^.Kind = gtHedgehog) and (Gear^.Hedgehog^.Effects[heInvulnerable] = 0) then Gear^.State:= (Gear^.State or gstMoving) and (not gstWinner); Gear^.Active:= true; if Gear^.Kind <> gtFlame then FollowGear:= Gear end; if ((Mask and EXPLPoisoned) <> 0) and (Gear^.Kind = gtHedgehog) and (Gear^.Hedgehog^.Effects[heInvulnerable] = 0) and (Gear^.State and gstHHDeath = 0) then - Gear^.Hedgehog^.Effects[hePoisoned] := 1; + Gear^.Hedgehog^.Effects[hePoisoned] := 5; end; end; - gtGrave: begin + gtGrave: if Mask and EXPLDoNotTouchAny = 0 then // Run the calcs only once we know we have a type that will need damage - tdX:= Gear^.X-fX; - tdY:= Gear^.Y-fY; - if LongInt(tdX.Round + tdY.Round + 2) < dmgBase then - dmg:= dmgBase - hwRound(Distance(tdX, tdY)); - if dmg > 1 then begin - dmg:= ModifyDamage(min(dmg div 2, Radius), Gear); - Gear^.dY:= - _0_004 * dmg; - Gear^.Active:= true - end - end; + tdX:= Gear^.X-fX; + tdY:= Gear^.Y-fY; + if LongInt(tdX.Round + tdY.Round + 2) < dmgBase then + dmg:= dmgBase - hwRound(Distance(tdX, tdY)); + if dmg > 1 then + begin + dmg:= ModifyDamage(min(dmg div 2, Radius), Gear); + Gear^.dY:= - _0_004 * dmg; + Gear^.Active:= true + end + end; end; end; Gear:= Gear^.NextGear @@ -185,6 +207,27 @@ AddVisualGear(X, Y, vgtChunk) end; +if (WorldEdge = weWrap) then + begin + // already wrapped? let's not wrap again! + if wrap then + break; + + // Radius + 5 because that's the actual radius the explosion changes graphically + if X + (Radius + 5) > LongInt(rightX) then + begin + dec(X, playWidth); + wrap:= true; + end + else if X - (Radius + 5) < LongInt(leftX) then + begin + inc(X, playWidth); + wrap:= true; + end; + end; + +until (not wrap); + uAIMisc.AwareOfExplosion(0, 0, 0) end; @@ -198,10 +241,11 @@ i:= _1; if (CurrentHedgehog <> nil) and CurrentHedgehog^.King then i:= _1_5; -if (Gear^.Hedgehog <> nil) and (Gear^.Hedgehog^.King or (Gear^.Hedgehog^.Effects[heFrozen] > 0)) then +if (Gear^.Kind = gtHedgehog) and (Gear^.Hedgehog <> nil) and + (Gear^.Hedgehog^.King or (Gear^.Hedgehog^.Effects[heFrozen] > 0)) then ModifyDamage:= hwRound(cDamageModifier * dmg * i * cDamagePercent * _0_5 * _0_01) else - ModifyDamage:= hwRound(cDamageModifier * dmg * i * cDamagePercent * _0_01) + ModifyDamage:= hwRound(cDamageModifier * dmg * i * cDamagePercent * _0_01); end; procedure ApplyDamage(Gear: PGear; AttackerHog: PHedgehog; Damage: Longword; Source: TDamageSource); @@ -232,7 +276,7 @@ inc(CurrentHedgehog^.Gear^.Health,vampDmg); str(vampDmg, s); s:= '+' + s; - AddCaption(s, CurrentHedgehog^.Team^.Clan^.Color, capgrpAmmoinfo); + AddCaption(ansistring(s), CurrentHedgehog^.Team^.Clan^.Color, capgrpAmmoinfo); RenderHealth(CurrentHedgehog^); RecountTeamHealth(CurrentHedgehog^.Team); i:= 0; @@ -249,20 +293,41 @@ end; end end; - if (GameFlags and gfKarma <> 0) and (GameFlags and gfInvulnerable = 0) and + if (GameFlags and gfKarma <> 0) and (GameFlags and gfInvulnerable = 0) and (CurrentHedgehog^.Effects[heInvulnerable] = 0) then begin // this cannot just use Damage or it interrupts shotgun and gets you called stupid inc(CurrentHedgehog^.Gear^.Karma, tmpDmg); CurrentHedgehog^.Gear^.LastDamage := CurrentHedgehog; spawnHealthTagForHH(CurrentHedgehog^.Gear, tmpDmg); end; - uStats.HedgehogDamaged(Gear, AttackerHog, Damage, false); + uStats.HedgehogDamaged(Gear, AttackerHog, Damage, false); end; + + if AprilOne and (Gear^.Hedgehog^.Hat = 'fr_tomato') and (Damage > 2) then + for i := 0 to random(min(Damage,20))+5 do + begin + vg:= AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtStraightShot); + if vg <> nil then + with vg^ do + begin + dx:= 0.001 * (random(100)+10); + dy:= 0.001 * (random(100)+10); + tdy:= -cGravityf; + if random(2) = 0 then + dx := -dx; + //if random(2) = 0 then + // dy := -dy; + FrameTicks:= random(500) + 1000; + State:= ord(sprBubbles); + //Tint:= $bd2f03ff + Tint:= $ff0000ff + end + end end else //else if Gear^.Kind <> gtStructure then // not gtHedgehog nor gtStructure Gear^.Hedgehog:= AttackerHog; inc(Gear^.Damage, Damage); - + ScriptCall('onGearDamage', Gear^.UID, Damage); end; @@ -275,10 +340,11 @@ AllInactive:= false; HHGear^.Active:= true; end; - + procedure HHHurt(Hedgehog: PHedgehog; Source: TDamageSource); begin if Hedgehog^.Effects[heFrozen] <> 0 then exit; + if (Source = dsFall) or (Source = dsExplosion) then case random(3) of 0: PlaySoundV(sndOoff1, Hedgehog^.Team^.voicepack); @@ -300,8 +366,8 @@ end; procedure CheckHHDamage(Gear: PGear); -var - dmg: Longword; +var + dmg: LongInt; i: LongWord; particle: PVisualGear; begin @@ -314,7 +380,7 @@ if dmg < 1 then exit; - for i:= min(12, (3 + dmg div 10)) downto 0 do + for i:= min(12, 3 + dmg div 10) downto 0 do begin particle := AddVisualGear(hwRound(Gear^.X) - 5 + Random(10), hwRound(Gear^.Y) + 12, vgtDust); if particle <> nil then @@ -338,7 +404,7 @@ procedure CalcRotationDirAngle(Gear: PGear); -var +var dAngle: real; begin // Frac/Round to be kind to JS as of 2012-08-27 where there is yet no int64/uint64 @@ -355,18 +421,182 @@ Gear^.DirAngle := Gear^.DirAngle - 360 end; +procedure AddSplashForGear(Gear: PGear; justSkipping: boolean); +var x, y, i, distL, distR, distB, minDist, maxDrops: LongInt; + splash, particle: PVisualGear; + speed, hwTmp: hwFloat; + vi, vs, tmp: real; // impact speed and sideways speed + isImpactH, isImpactRight: boolean; +const dist2surf = 4; +begin +x:= hwRound(Gear^.X); +y:= hwRound(Gear^.Y); + +// find position for splash and impact speed + +distB:= cWaterline - y; + +if WorldEdge <> weSea then + minDist:= distB +else + begin + distL:= x - leftX; + distR:= rightX - x; + minDist:= min(distB, min(distL, distR)); + end; + +isImpactH:= (minDist <> distB); + +if not isImpactH then + begin + y:= cWaterline - dist2surf; + speed:= hwAbs(Gear^.dY); + end +else + begin + isImpactRight := minDist = distR; + if isImpactRight then + x:= rightX - dist2surf + else + x:= leftX + dist2surf; + speed:= hwAbs(Gear^.dX); + end; + +// splash sound + +if justSkipping then + PlaySound(sndSkip) +else + begin + // adjust water impact sound based on gear speed and density + hwTmp:= hwAbs(Gear^.Density * speed); + + if hwTmp > _1 then + PlaySound(sndSplash) + else if hwTmp > _0_5 then + PlaySound(sndSkip) + else + PlaySound(sndDroplet2); + end; + + +// splash visuals + +if ((cReducedQuality and rqPlainSplash) <> 0) then + exit; + +splash:= AddVisualGear(x, y, vgtSplash); +if splash = nil then + exit; + +if not isImpactH then + vs:= abs(hwFloat2Float(Gear^.dX)) +else + begin + if isImpactRight then + splash^.Angle:= -90 + else + splash^.Angle:= 90; + vs:= abs(hwFloat2Float(Gear^.dY)); + end; + + +vi:= hwFloat2Float(speed); + +with splash^ do + begin + Scale:= abs(hwFloat2Float(Gear^.Density / _3 * speed)); + if Scale > 1 then Scale:= power(Scale,0.3333) + else Scale:= Scale + ((1-Scale) / 2); + if Scale > 1 then Timer:= round(min(Scale*0.0005/cGravityf,4)) + else Timer:= 1; + // Low Gravity + FrameTicks:= FrameTicks*Timer; + end; + + +// eject water drops + +maxDrops := (hwRound(Gear^.Density) * 3) div 2 + round((vi + vs) * hwRound(Gear^.Density) * 6); +for i:= max(maxDrops div 3, min(32, Random(maxDrops))) downto 0 do + begin + if isImpactH then + particle := AddVisualGear(x, y - 3 + Random(7), vgtDroplet) + else + particle := AddVisualGear(x - 3 + Random(7), y, vgtDroplet); + + if particle <> nil then + with particle^ do + begin + // dX and dY were initialized to have a random value on creation (see uVisualGearsList) + if isImpactH then + begin + tmp:= dX; + if isImpactRight then + dX:= dY - vi / 5 + else + dX:= -dy + vi / 5; + dY:= tmp * (1 + vs / 10); + end + else + begin + dX:= dX * (1 + vs / 10); + dY:= dY - vi / 5; + end; + + if splash <> nil then + begin + if splash^.Scale > 1 then + begin + dX:= dX * power(splash^.Scale, 0.3333); // tone down the droplet height further + dY:= dY * power(splash^.Scale, 0.3333); + end + else + begin + dX:= dX * splash^.Scale; + dY:= dY * splash^.Scale; + end; + end; + end + end; + +end; + +procedure DrownGear(Gear: PGear); +begin +Gear^.doStep := @doStepDrowningGear; + +Gear^.Timer := 5000; // how long game should wait +end; + function CheckGearDrowning(var Gear: PGear): boolean; -var +var skipSpeed, skipAngle, skipDecay: hwFloat; - i, maxDrops, X, Y: LongInt; - vdX, vdY: real; - particle, splash: PVisualGear; - isSubmersible: boolean; + tmp, X, Y, dist2Water: LongInt; + isSubmersible, isDirH, isImpact, isSkip: boolean; + s: ansistring; begin // probably needs tweaking. might need to be in a case statement based upon gear type + X:= hwRound(Gear^.X); Y:= hwRound(Gear^.Y); - if cWaterLine < Y + Gear^.Radius then + + dist2Water:= cWaterLine - (Y + Gear^.Radius); + isDirH:= false; + + if WorldEdge = weSea then begin + tmp:= dist2Water; + dist2Water:= min(dist2Water, min(X - Gear^.Radius - LongInt(leftX), LongInt(rightX) - (X + Gear^.Radius))); + // if water on sides is closer than on bottom -> horizontal direction + isDirH:= tmp <> dist2Water; + end; + + isImpact:= false; + + if dist2Water < 0 then + begin + // invisible gears will just be deleted + // unless they are generic fallers, then they will be "respawned" if Gear^.State and gstInvisible <> 0 then begin if Gear^.Kind = gtGenericFaller then @@ -377,27 +607,41 @@ Gear^.dY:= _90-(GetRandomf*_360) end else DeleteGear(Gear); - exit + exit(true) end; isSubmersible:= ((Gear = CurrentHedgehog^.Gear) and (CurAmmoGear <> nil) and (CurAmmoGear^.State and gstSubmersible <> 0)) or (Gear^.State and gstSubmersible <> 0); + skipSpeed := _0_25; skipAngle := _1_9; skipDecay := _0_87; - X:= hwRound(Gear^.X); - vdX:= hwFloat2Float(Gear^.dX); - vdY:= hwFloat2Float(Gear^.dY); - // this could perhaps be a tiny bit higher. - if (cWaterLine + 64 + Gear^.Radius > Y) and (hwSqr(Gear^.dX) + hwSqr(Gear^.dY) > skipSpeed) - and (hwAbs(Gear^.dX) > skipAngle * hwAbs(Gear^.dY)) then + + + // skipping + + if (not isSubmersible) and (hwSqr(Gear^.dX) + hwSqr(Gear^.dY) > skipSpeed) + and ( ((not isDirH) and (hwAbs(Gear^.dX) > skipAngle * hwAbs(Gear^.dY))) + or (isDirH and (hwAbs(Gear^.dY) > skipAngle * hwAbs(Gear^.dX))) ) then begin - Gear^.dY.isNegative := true; + isSkip:= true; + // if skipping we move the gear out of water + if isDirH then + begin + Gear^.dX.isNegative := (not Gear^.dX.isNegative); + Gear^.X:= Gear^.X + Gear^.dX; + end + else + begin + Gear^.dY.isNegative := (not Gear^.dY.isNegative); + Gear^.Y:= Gear^.Y + Gear^.dY; + end; Gear^.dY := Gear^.dY * skipDecay; Gear^.dX := Gear^.dX * skipDecay; CheckGearDrowning := false; - PlaySound(sndSkip) end - else + else // not skipping begin + isImpact:= true; + isSkip:= false; if not isSubmersible then begin CheckGearDrowning := true; @@ -411,85 +655,66 @@ begin // Gear could become nil after this, just exit to skip splashes ResurrectHedgehog(Gear); - exit + exit(true) end else begin - Gear^.doStep := @doStepDrowningGear; + DrownGear(Gear); Gear^.State := Gear^.State and (not gstHHDriven); - AddCaption(Format(GetEventString(eidDrowned), Gear^.Hedgehog^.Name), cWhiteColor, capgrpMessage); + s:= ansistring(Gear^.Hedgehog^.Name); + AddCaption(FormatA(GetEventString(eidDrowned), s), cWhiteColor, capgrpMessage); end end else - Gear^.doStep := @doStepDrowningGear; - if Gear^.Kind = gtFlake then - exit // skip splashes + DrownGear(Gear); + if Gear^.Kind = gtFlake then + exit(true); // skip splashes end - else if (Y > cWaterLine + cVisibleWater*4) and - ((Gear <> CurrentHedgehog^.Gear) or (CurAmmoGear = nil) or (CurAmmoGear^.State and gstSubmersible = 0)) then - Gear^.doStep:= @doStepDrowningGear; - if ((not isSubmersible) and (Y < cWaterLine + 64 + Gear^.Radius)) - or (isSubmersible and (Y < cWaterLine + 2 + Gear^.Radius) and (Gear = CurAmmoGear) and ((CurAmmoGear^.Pos = 0) - and (CurAmmoGear^.dY < _0_01))) then - if Gear^.Density * Gear^.dY > _1 then - PlaySound(sndSplash) - else if Gear^.Density * Gear^.dY > _0_5 then - PlaySound(sndSkip) - else - PlaySound(sndDroplet2); - end; - - if ((cReducedQuality and rqPlainSplash) = 0) - and (((not isSubmersible) and (Y < cWaterLine + 64 + Gear^.Radius)) - or (isSubmersible and (Y < cWaterLine + 2 + Gear^.Radius) and (Gear = CurAmmoGear) and ((CurAmmoGear^.Pos = 0) - and (CurAmmoGear^.dY < _0_01)))) then - begin - splash:= AddVisualGear(X, cWaterLine, vgtSplash); - if splash <> nil then - with splash^ do + else // submersible begin - Scale:= hwFloat2Float(Gear^.Density / _3 * Gear^.dY); - if Scale > 1 then Scale:= power(Scale,0.3333) - else Scale:= Scale + ((1-Scale) / 2); - if Scale > 1 then Timer:= round(min(Scale*0.0005/cGravityf,4)) - else Timer:= 1; - // Low Gravity - FrameTicks:= FrameTicks*Timer; - end; + // drown submersible grears if far below map + if (Y > cWaterLine + cVisibleWater*4) then + begin + DrownGear(Gear); + exit(true); // no splashes needed + end; + + CheckGearDrowning := false; - maxDrops := (hwRound(Gear^.Density) * 3) div 2 + round(vdX * hwRound(Gear^.Density) * 6) + round(vdY * hwRound(Gear^.Density) * 6); - for i:= max(maxDrops div 3, min(32, Random(maxDrops))) downto 0 do - begin - particle := AddVisualGear(X - 3 + Random(7), cWaterLine, vgtDroplet); - if particle <> nil then - with particle^ do + // check if surface was penetrated + + // no penetration if center's water distance not smaller than radius + if abs(dist2Water + Gear^.Radius) >= Gear^.Radius then + isImpact:= false + else + begin + // get distance to water of last tick + if isDirH then begin - dX := dX - vdX / 10; - dY := dY - vdY / 5; - if splash <> nil then - begin - if splash^.Scale > 1 then - begin - dX:= dX * power(splash^.Scale,0.3333); // tone down the droplet height further - dY:= dY * power(splash^.Scale, 0.3333) - end - else - begin - dX:= dX * splash^.Scale; - dY:= dY * splash^.Scale - end - end + tmp:= hwRound(Gear^.X - Gear^.dX); + tmp:= abs(min(tmp - leftX, rightX - tmp)); end - end - end; - if isSubmersible and (Gear = CurAmmoGear) and (CurAmmoGear^.Pos = 0) then - CurAmmoGear^.Pos := 1000 + else + begin + tmp:= hwRound(Gear^.Y - Gear^.dY); + tmp:= abs(cWaterLine - tmp); + end; + + // there was an impact if distance was >= radius + isImpact:= (tmp >= Gear^.Radius) + end; + end; // end of submersible + end; // end of not skipping + + // splash sound animation and droplets + if isImpact or isSkip then + addSplashForGear(Gear, isSkip); + + if isSkip then + ScriptCall('onGearWaterSkip', Gear^.uid); end else - begin - if not (Gear^.Kind in [gtJetpack, gtBee]) then Gear^.State:= Gear^.State and not gstSubmersible; // making it temporary for most gears is more attractive I think CheckGearDrowning := false - end end; @@ -510,11 +735,11 @@ gear^.Hedgehog^.Effects[hePoisoned] := 0; if (CurrentHedgehog^.Effects[heResurrectable] = 0) or ((CurrentHedgehog^.Effects[heResurrectable] <> 0) and (Gear^.Hedgehog^.Team^.Clan <> CurrentHedgehog^.Team^.Clan)) then - with CurrentHedgehog^ do + with CurrentHedgehog^ do begin inc(Team^.stats.AIKills); - FreeTexture(Team^.AIKillsTex); - Team^.AIKillsTex := RenderStringTex(inttostr(Team^.stats.AIKills), Team^.Clan^.Color, fnt16); + FreeAndNilTexture(Team^.AIKillsTex); + Team^.AIKillsTex := RenderStringTex(ansistring(inttostr(Team^.stats.AIKills)), Team^.Clan^.Color, fnt16); end; tempTeam := gear^.Hedgehog^.Team; DeleteCI(gear); @@ -527,7 +752,7 @@ sparkles^.Tint:= tempTeam^.Clan^.Color shl 8 or $FF; //sparkles^.Angle:= random(360); end; - FindPlace(gear, false, 0, LAND_WIDTH, true); + FindPlace(gear, false, 0, LAND_WIDTH, true); if gear <> nil then begin AddVisualGear(hwRound(gear^.X), hwRound(gear^.Y), vgtExplosion); @@ -544,7 +769,7 @@ 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 + for i:= max(x - r, 0) to min(x + r, LAND_WIDTH - 1) do if Land[y, i] and mask <> 0 then begin inc(count); @@ -557,6 +782,28 @@ CountNonZeroz:= count; end; +function isSteadyPosition(x, y, r, c: LongInt; mask: Longword): boolean; +var cnt, i: LongInt; +begin + cnt:= 0; + isSteadyPosition:= false; + + if ((y and LAND_HEIGHT_MASK) = 0) and (x - r >= 0) and (x + r < LAND_WIDTH) then + begin + for i:= r - c + 2 to r do + begin + if (Land[y, x - i] and mask <> 0) then inc(cnt); + if (Land[y, x + i] and mask <> 0) then inc(cnt); + + if cnt >= c then + begin + isSteadyPosition:= true; + exit + end; + end; + end; +end; + function NoGearsToAvoid(mX, mY: LongInt; rX, rY: LongInt): boolean; var t: PGear; @@ -582,9 +829,10 @@ procedure FindPlace(var Gear: PGear; withFall: boolean; Left, Right: LongInt; skipProximity: boolean); var x: LongInt; - y, sy: LongInt; + y, sy, dir: LongInt; ar: array[0..1023] of TPoint; ar2: array[0..2047] of TPoint; + temp: TPoint; cnt, cnt2: Longword; delta: LongInt; ignoreNearObjects, ignoreOverlap, tryAgain: boolean; @@ -592,9 +840,9 @@ 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; -if WorldEdge <> weNone then +if WorldEdge <> weNone then begin - Left:= max(Left,leftX+Gear^.Radius); + Left:= max(Left, LongInt(leftX) + Gear^.Radius); Right:= min(Right,rightX-Gear^.Radius) end; while tryAgain do @@ -602,17 +850,18 @@ delta:= LAND_WIDTH div 16; cnt2:= 0; repeat - x:= Left + max(LAND_WIDTH div 2048, LongInt(GetRandom(Delta))); + if GetRandom(2) = 0 then dir:= -1 else dir:= 1; + x:= max(LAND_WIDTH div 2048, LongInt(GetRandom(Delta))); + if dir = 1 then x:= Left + x else x:= Right - x; repeat - inc(x, Delta); cnt:= 0; - y:= min(1024, topY) - 2 * Gear^.Radius; + y:= min(1024, topY) - Gear^.Radius shl 1; while y < cWaterLine do begin repeat inc(y, 2); until (y >= cWaterLine) or - (not ignoreOverlap and (CountNonZeroz(x, y, Gear^.Radius - 1, 1, $FFFF) = 0)) or + ((not ignoreOverlap) and (CountNonZeroz(x, y, Gear^.Radius - 1, 1, $FFFF) = 0)) or (ignoreOverlap and (CountNonZeroz(x, y, Gear^.Radius - 1, 1, lfLandMask) = 0)); sy:= y; @@ -620,19 +869,19 @@ repeat inc(y); 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, lfLandMask) <> 0)); + ((not ignoreOverlap) and (CountNonZeroz(x, y, Gear^.Radius - 1, 1, $FFFF) <> 0)) or + (ignoreOverlap and (CountNonZeroz(x, y, Gear^.Radius - 1, 1, lfLandMask) <> 0)); - if (y - sy > Gear^.Radius * 2) + if (y - sy > Gear^.Radius * 2) and (y < cWaterLine) and (((Gear^.Kind = gtExplosives) - and (y < cWaterLine) - 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 (ignoreNearObjects or NoGearsToAvoid(x, y - Gear^.Radius, 110, 110)) - )) then + and (ignoreNearObjects or NoGearsToAvoid(x, y - Gear^.Radius, 60, 60)) + and (isSteadyPosition(x, y+1, Gear^.Radius - 1, 3, $FFFF) + or (CountNonZeroz(x, y+1, Gear^.Radius - 1, Gear^.Radius+1, $FFFF) > Gear^.Radius) + )) + or + ((Gear^.Kind <> gtExplosives) + and (ignoreNearObjects or NoGearsToAvoid(x, y - Gear^.Radius, 110, 110)) + )) then begin ar[cnt].X:= x; if withFall then @@ -646,13 +895,17 @@ end; if cnt > 0 then - with ar[GetRandom(cnt)] do + begin + temp := ar[GetRandom(cnt)]; + with temp do begin ar2[cnt2].x:= x; ar2[cnt2].y:= y; inc(cnt2) - end - until (x + Delta > Right); + end; + end; + inc(x, Delta*dir) + until ((dir = 1) and (x > Right)) or ((dir = -1) and (x < Left)); dec(Delta, 60) until (cnt2 > 0) or (Delta < 70); @@ -665,12 +918,15 @@ end; if cnt2 > 0 then - with ar2[GetRandom(cnt2)] do + begin + temp := ar2[GetRandom(cnt2)]; + with temp do begin Gear^.X:= int2hwFloat(x); Gear^.Y:= int2hwFloat(y); AddFileLog('Assigned Gear coordinates (' + inttostr(x) + ',' + inttostr(y) + ')'); end + end else begin OutError('Can''t find place for Gear', false); @@ -716,7 +972,7 @@ if (TestCollisionX(Gear, hwSign(Gear^.dX)) <> 0) or (TestCollisionY(Gear, hwSign(Gear^.dY)) <> 0) then Gear^.State := Gear^.State or gstCollision - else + else Gear^.State := Gear^.State and (not gstCollision) end; @@ -822,7 +1078,7 @@ end; if dmg > 0 then begin - if t^.Hedgehog^.Effects[heInvulnerable] = 0 then + if (t^.Kind <> gtHedgehog) or (t^.Hedgehog^.Effects[heInvulnerable] = 0) then ApplyDamage(t, Gear^.Hedgehog, dmg, dsBullet) else Gear^.State:= Gear^.State or gstWinner; @@ -885,14 +1141,14 @@ begin dec(i); Gear:= t^.ar[i]; - if ((Ammo^.Kind = gtFlame) or (Ammo^.Kind = gtBlowTorch)) and + if ((Ammo^.Kind = gtFlame) or (Ammo^.Kind = gtBlowTorch)) and (Gear^.Kind = gtHedgehog) and (Gear^.Hedgehog^.Effects[heFrozen] > 255) then Gear^.Hedgehog^.Effects[heFrozen]:= max(255,Gear^.Hedgehog^.Effects[heFrozen]-10000); tmpDmg:= ModifyDamage(Damage, Gear); if (Gear^.State and gstNoDamage) = 0 then begin - if (Ammo^.Kind = gtDEagleShot) or (Ammo^.Kind = gtSniperRifleShot) then + if (Ammo^.Kind = gtDEagleShot) or (Ammo^.Kind = gtSniperRifleShot) then begin VGear := AddVisualGear(hwround(Ammo^.X), hwround(Ammo^.Y), vgtBulletHit); if VGear <> nil then @@ -918,7 +1174,7 @@ Ammo^.Timer:= 0; exit; end; - if Gear^.Hedgehog^.Effects[heInvulnerable] = 0 then + if (Gear^.Kind <> gtHedgehog) or (Gear^.Hedgehog^.Effects[heInvulnerable] = 0) then begin if (Ammo^.Kind = gtKnife) and (tmpDmg > 0) then for j:= 1 to max(1,min(3,tmpDmg div 5)) do @@ -943,7 +1199,7 @@ end else Gear^.State:= Gear^.State or gstWinner; - if (Gear^.Kind = gtExplosives) and (Ammo^.Kind = gtBlowtorch) then + if (Gear^.Kind = gtExplosives) and (Ammo^.Kind = gtBlowtorch) then begin if (Ammo^.Hedgehog^.Gear <> nil) then Ammo^.Hedgehog^.Gear^.State:= Ammo^.Hedgehog^.Gear^.State and (not gstNotKickable); @@ -1054,9 +1310,9 @@ s:= 0; SetLength(GearsNearArray, s); t := GearsList; - while t <> nil do + while t <> nil do begin - if (t^.Kind = Kind) + if (t^.Kind = Kind) and ((X - t^.X)*(X - t^.X) + (Y - t^.Y)*(Y-t^.Y) < int2hwFloat(r)) then begin inc(s); @@ -1113,6 +1369,8 @@ FollowGear:= AddGear(0, 0, gtCase, 0, _0, _0, 0); FollowGear^.Health:= cHealthCaseAmount; FollowGear^.Pos:= posCaseHealth; + // health crate is smaller than the other crates + FollowGear^.Radius := cCaseHealthRadius; AddCaption(GetEventString(eidNewHealthPack), cWhiteColor, capgrpAmmoInfo); end else if (t rightX) then +if (hwRound(Gear^.X) < LongInt(leftX)) or + (hwRound(Gear^.X) > LongInt(rightX)) then begin if WorldEdge = weWrap then begin - if (hwRound(Gear^.X)-Gear^.Radius < leftX) then - Gear^.X:= int2hwfloat(rightX-Gear^.Radius) - else Gear^.X:= int2hwfloat(leftX+Gear^.Radius); + if (hwRound(Gear^.X) < LongInt(leftX)) then + Gear^.X:= Gear^.X + int2hwfloat(rightX - leftX) + else Gear^.X:= Gear^.X - int2hwfloat(rightX - leftX); LeftImpactTimer:= 150; RightImpactTimer:= 150 end else if WorldEdge = weBounce then begin - if (hwRound(Gear^.X)-Gear^.Radius < leftX) then + if (hwRound(Gear^.X) - Gear^.Radius < LongInt(leftX)) then begin LeftImpactTimer:= 333; Gear^.dX.isNegative:= false; - Gear^.X:= int2hwfloat(leftX+Gear^.Radius) + Gear^.X:= int2hwfloat(LongInt(leftX) + Gear^.Radius) end - else + else begin RightImpactTimer:= 333; Gear^.dX.isNegative:= true; Gear^.X:= int2hwfloat(rightX-Gear^.Radius) end; if (Gear^.Radius > 2) and (Gear^.dX.QWordValue > _0_001.QWordValue) then - PlaySound(sndMelonImpact) - end + AddBounceEffectForGear(Gear); + end{ else if WorldEdge = weSea then begin if (hwRound(Gear^.Y) > cWaterLine) and (Gear^.State and gstSubmersible <> 0) then - Gear^.State:= Gear^.State and not gstSubmersible + Gear^.State:= Gear^.State and (not gstSubmersible) else begin Gear^.State:= Gear^.State or gstSubmersible; @@ -1262,12 +1520,12 @@ Gear^.dY:= tdx; Gear^.dY.isNegative:= true end - end; + end}; (* * Window in the sky (Gear moved high into the sky, Y is used to determine X) [unfortunately, not a safe thing to do. shame, I thought aerial bombardment would be kinda neat This one would be really easy to freeze game unless it was flagged unfortunately. - else + else begin Gear^.X:= int2hwFloat(PlayWidth)*int2hwFloat(min(max(0,hwRound(Gear^.Y)),PlayHeight))/PlayHeight; Gear^.Y:= -_2048-_256-_256; @@ -1281,4 +1539,21 @@ end; end; +procedure AddBounceEffectForGear(Gear: PGear); +var boing: PVisualGear; +begin + boing:= AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtStraightShot, 0, false, 1); + if boing <> nil then + with boing^ do + begin + Angle:= random(360); + dx:= 0; + dy:= 0; + FrameTicks:= 200; + Scale:= hwFloat2Float(Gear^.Density * hwAbs(Gear^.dY) + hwAbs(Gear^.dX)) / 1.5; + State:= ord(sprBoing) + end; + PlaySound(sndMelonImpact, true) +end; + end. diff -r 31570b766315 -r ed5a6478e710 hedgewars/uIO.pas --- a/hedgewars/uIO.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uIO.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} @@ -51,8 +51,7 @@ loTime: Word; case byte of 1: (len: byte; - cmd: Char; - X, Y: LongInt); + cmd: Char); 2: (str: shortstring); end; @@ -77,7 +76,7 @@ FillChar(command^, sizeof(TCmd), 0); command^.loTime:= Time; command^.str:= str; -if command^.cmd <> 'F' then dec(command^.len, 2); // cut timestamp +if (command^.cmd <> 'F') and (command^.cmd <> 'G') then dec(command^.len, 2); // cut timestamp if headcmd = nil then begin headcmd:= command; @@ -119,9 +118,23 @@ WriteLnToConsole(msgOK) end; +procedure ParseChatCommand(command: shortstring; message: shortstring; + messageStartIndex: Byte); +var + text: shortstring; +begin + text:= copy(message, messageStartIndex, + Length(message) - messageStartIndex + 1); + ParseCommand(command + text, true); + WriteLnToConsole(text) +end; + procedure ParseIPCCommand(s: shortstring); var loTicks: Word; + isProcessed: boolean; begin +isProcessed := true; + case s[1] of '!': begin AddFileLog('Ping? Pong!'); isPonged:= true; end; '?': SendIPC(_S'!'); @@ -140,12 +153,27 @@ 'V': begin if s[2] = '.' then ParseCommand('campvar ' + copy(s, 3, length(s) - 2), true); - end + end; + 'I': ParseCommand('pause server', true); + 's': if gameType = gmtNet then + ParseChatCommand('chatmsg ', s, 2) + else + isProcessed:= false; + 'b': if gameType = gmtNet then + ParseChatCommand('chatmsg ' + #4, s, 2) + else + isProcessed:= false; + 'Y': ChatPasteBuffer:= copy(s, 2, Length(s) - 1); else - loTicks:= SDLNet_Read16(@s[byte(s[0]) - 1]); - AddCmd(loTicks, s); - AddFileLog('[IPC in] ' + sanitizeCharForLog(s[1]) + ' ticks ' + IntToStr(lastcmd^.loTime)); - end + isProcessed:= false; + end; + + if (not isProcessed) then + begin + loTicks:= SDLNet_Read16(@s[byte(s[0]) - 1]); + AddCmd(loTicks, s); + AddFileLog('[IPC in] ' + sanitizeCharForLog(s[1]) + ' ticks ' + IntToStr(lastcmd^.loTime)); + end end; procedure IPCCheckSock; @@ -177,10 +205,10 @@ end; procedure LoadRecordFromFile(fileName: shortstring); -var f: file; - ss: shortstring = ''; - i: LongInt; - s: shortstring; +var f : File; + ss : shortstring = ''; + i : LongInt; + s : shortstring; begin // set RDNLY on file open @@ -188,7 +216,6 @@ {$I-} assign(f, fileName); reset(f, 1); - tryDo(IOResult = 0, 'Error opening file ' + fileName, true); i:= 0; // avoid compiler hints @@ -202,7 +229,7 @@ while (Length(ss) > 1)and(Length(ss) > byte(ss[1])) do begin ParseIPCCommand(copy(ss, 2, byte(ss[1]))); - Delete(ss, 1, Succ(byte(ss[1]))) + Delete(ss, 1, Succ(byte(ss[1]))); end end until i = 0; @@ -221,7 +248,15 @@ function isSyncedCommand(c: char): boolean; begin - isSyncedCommand:= (c in ['+', '#', 'L', 'l', 'R', 'r', 'U', 'u', 'D', 'd', 'Z', 'z', 'A', 'a', 'S', 'j', 'J', ',', 'c', 'N', 'p', 'P', 'w', 't', '1', '2', '3', '4', '5']) or ((c >= #128) and (c <= char(128 + cMaxSlotIndex))) + case c of + '+', '#', 'L', 'l', 'R', 'r', 'U' + , 'u', 'D', 'd', 'Z', 'z', 'A', 'a' + , 'S', 'j', 'J', ',', 'c', 'N', 'p' + , 'P', 'w', 't', '1', '2', '3', '4' + , '5', 'f', 'g': isSyncedCommand:= true; + else + isSyncedCommand:= ((byte(c) >= 128) and (byte(c) <= 128 + cMaxSlotIndex)) + end end; procedure flushBuffer(); @@ -240,20 +275,20 @@ begin if s[0] > #251 then s[0]:= #251; - + SDLNet_Write16(GameTicks, @s[Succ(byte(s[0]))]); - + AddFileLog('[IPC out] '+ sanitizeCharForLog(s[1])); inc(s[0], 2); - + if isSyncedCommand(s[1]) then begin if sendBuffer.count + byte(s[0]) >= cSendBufferSize then flushBuffer(); - + Move(s, sendBuffer.buf[sendBuffer.count], byte(s[0]) + 1); inc(sendBuffer.count, byte(s[0]) + 1); - + if (s[1] = 'N') or (s[1] = '#') then flushBuffer(); end else @@ -302,8 +337,8 @@ begin if sendBuffer.count = 0 then SendIPC(_S'+'); - - flushBuffer() + + flushBuffer() end end; @@ -316,12 +351,13 @@ while (headcmd <> nil) and (tmpflag or (headcmd^.cmd = '#')) // '#' is the only cmd which can be sent within same tick after 'N' - and ((GameTicks = hiTicks shl 16 + headcmd^.loTime) + and ((GameTicks = LongWord(hiTicks shl 16 + headcmd^.loTime)) or (headcmd^.cmd = 's') // for these commands time is not specified or (headcmd^.cmd = 'h') // seems the hedgewars protocol does not allow remote synced commands or (headcmd^.cmd = '#') // must be synced for saves to work or (headcmd^.cmd = 'b') - or (headcmd^.cmd = 'F')) do + or (headcmd^.cmd = 'F') + or (headcmd^.cmd = 'G')) do begin case headcmd^.cmd of '+': ; // do nothing - it is just an empty packet @@ -349,26 +385,20 @@ s:= copy(headcmd^.str, 2, Pred(headcmd^.len)); ParseCommand('gencmd ' + s, true); end; - 's': begin - s:= copy(headcmd^.str, 2, Pred(headcmd^.len)); - ParseCommand('chatmsg ' + s, true); - WriteLnToConsole(s) - end; - 'b': begin - s:= copy(headcmd^.str, 2, Pred(headcmd^.len)); - ParseCommand('chatmsg ' + #4 + s, true); - WriteLnToConsole(s) - end; -// TODO: deprecate 'F' - 'F': ParseCommand('teamgone ' + copy(headcmd^.str, 2, Pred(headcmd^.len)), true); + 's': ParseChatCommand('chatmsg ', headcmd^.str, 2); + 'b': ParseChatCommand('chatmsg ' + #4, headcmd^.str, 2); + 'F': ParseCommand('teamgone u' + copy(headcmd^.str, 2, Pred(headcmd^.len)), true); + 'G': ParseCommand('teamback u' + copy(headcmd^.str, 2, Pred(headcmd^.len)), true); + 'f': ParseCommand('teamgone s' + copy(headcmd^.str, 2, Pred(headcmd^.len)), true); + 'g': ParseCommand('teamback s' + copy(headcmd^.str, 2, Pred(headcmd^.len)), true); 'N': begin tmpflag:= false; lastTurnChecksum:= SDLNet_Read32(@headcmd^.str[2]); AddFileLog('got cmd "N": time '+IntToStr(hiTicks shl 16 + headcmd^.loTime)) end; 'p': begin - x32:= SDLNet_Read32(@(headcmd^.X)); - y32:= SDLNet_Read32(@(headcmd^.Y)); + x32:= SDLNet_Read32(@(headcmd^.str[2])); + y32:= SDLNet_Read32(@(headcmd^.str[6])); doPut(x32, y32, false) end; 'P': begin @@ -377,8 +407,8 @@ // SDLNet_Read16(@(headcmd^.Y)) == cScreenHeight - CursorPoint.Y - WorldDy; if CurrentTeam^.ExtDriven then begin - TargetCursorPoint.X:= LongInt(SDLNet_Read32(@(headcmd^.X))) + WorldDx; - TargetCursorPoint.Y:= cScreenHeight - LongInt(SDLNet_Read32(@(headcmd^.Y))) - WorldDy; + TargetCursorPoint.X:= LongInt(SDLNet_Read32(@(headcmd^.str[2]))) + WorldDx; + TargetCursorPoint.Y:= cScreenHeight - LongInt(SDLNet_Read32(@(headcmd^.str[6]))) - WorldDy; if not bShowAmmoMenu and autoCameraOn then CursorPoint:= TargetCursorPoint end @@ -388,7 +418,7 @@ 'h': ParseCommand('hogsay ' + copy(headcmd^.str, 2, Pred(headcmd^.len)), true); '1'..'5': ParseCommand('timer ' + headcmd^.cmd, true); else - if (headcmd^.cmd >= #128) and (headcmd^.cmd <= char(128 + cMaxSlotIndex)) then + if (byte(headcmd^.cmd) >= 128) and (byte(headcmd^.cmd) <= 128 + cMaxSlotIndex) then ParseCommand('slot ' + char(byte(headcmd^.cmd) - 79), true) else OutError('Unexpected protocol command: ' + headcmd^.cmd, True) @@ -397,7 +427,7 @@ end; if (headcmd <> nil) and tmpflag and (not CurrentTeam^.hasGone) then - TryDo(GameTicks < hiTicks shl 16 + headcmd^.loTime, + TryDo(GameTicks < LongWord(hiTicks shl 16) + headcmd^.loTime, 'oops, queue error. in buffer: ' + headcmd^.cmd + ' (' + IntToStr(GameTicks) + ' > ' + IntToStr(hiTicks shl 16 + headcmd^.loTime) + ')', @@ -405,7 +435,11 @@ isInLag:= (headcmd = nil) and tmpflag and (not CurrentTeam^.hasGone); -if isInLag then fastUntilLag:= false +if isInLag and fastUntilLag then +begin + ParseCommand('spectate 0', true); + fastUntilLag:= false +end; end; procedure chFatalError(var s: shortstring); @@ -413,7 +447,11 @@ SendIPC('E' + s); // TODO: should we try to clean more stuff here? SDL_Quit; - halt(2) + + if IPCSock <> nil then + halt(HaltFatalError) + else + halt(HaltFatalErrorNoIPC); end; procedure doPut(putX, putY: LongInt; fromAI: boolean); @@ -421,7 +459,7 @@ if CheckNoTeamOrHH or isPaused then exit; bShowFinger:= false; -if not CurrentTeam^.ExtDriven and bShowAmmoMenu then +if (not CurrentTeam^.ExtDriven) and bShowAmmoMenu then begin bSelected:= true; exit @@ -429,7 +467,7 @@ with CurrentHedgehog^.Gear^, CurrentHedgehog^ do - if (State and gstHHChooseTarget) <> 0 then + if (State and gstChooseTarget) <> 0 then begin isCursorVisible:= false; if not CurrentTeam^.ExtDriven then @@ -452,7 +490,7 @@ TargetPoint.Y:= putY end; AddFileLog('put: ' + inttostr(TargetPoint.X) + ', ' + inttostr(TargetPoint.Y)); - State:= State and (not gstHHChooseTarget); + State:= State and (not gstChooseTarget); if (Ammoz[CurAmmoType].Ammo.Propz and ammoprop_AttackingPut) <> 0 then Message:= Message or (gmAttack and InputMask); end @@ -471,7 +509,7 @@ lastcmd:= nil; isPonged:= false; SocketString:= ''; - + hiTicks:= 0; flushDelayTicks:= 0; sendBuffer.count:= 0; @@ -483,6 +521,7 @@ SDLNet_FreeSocketSet(fds); SDLNet_TCP_Close(IPCSock); SDLNet_Quit(); + end; end. diff -r 31570b766315 -r ed5a6478e710 hedgewars/uInputHandler.pas --- a/hedgewars/uInputHandler.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uInputHandler.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} @@ -50,7 +50,7 @@ procedure ControllerButtonEvent(joy, button: Byte; pressed: Boolean); implementation -uses uConsole, uCommands, uMisc, uVariables, uConsts, uUtils, uDebug, uPhysFSLayer; +uses uConsole, uCommands, uVariables, uConsts, uUtils, uDebug, uPhysFSLayer; const LSHIFT = $0200; @@ -58,7 +58,7 @@ LALT = $0800; RALT = $1000; LCTRL = $2000; - RCTRL = $4000; + RCTRL = $4000; var tkbd: array[0..cKbdMaxIndex] of boolean; KeyNames: array [0..cKeyMaxIndex] of string[15]; @@ -92,16 +92,16 @@ (* 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; + 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; +var mod_ : shortstring = ''; ModifierCount, i: LongInt; begin if Modifier = '' then exit; @@ -113,7 +113,7 @@ SplitByChar(Modifier, mod_, ':');//remove the first mod: part Modifier:= mod_; for i:= 0 to ModifierCount do - begin + begin mod_:= ''; SplitByChar(Modifier, mod_, ':'); if (Modifier = 'lshift') then code:= code or LSHIFT; @@ -178,11 +178,13 @@ if KeyDown then begin + Trusted:= Trusted and (not isPaused); //releasing keys during pause should be allowed on the other hand + if CurrentBinds[code] = 'switch' then LocalMessage:= LocalMessage or gmSwitch else if CurrentBinds[code] = '+precise' then LocalMessage:= LocalMessage or gmPrecise; - + ParseCommand(CurrentBinds[code], Trusted); if (CurrentTeam <> nil) and (not CurrentTeam^.ExtDriven) and (ReadyTimeLeft > 1) then ParseCommand('gencmd R', true) @@ -190,7 +192,7 @@ else if (CurrentBinds[code][1] = '+') then begin if CurrentBinds[code] = '+precise' then - LocalMessage:= LocalMessage and not(gmPrecise); + LocalMessage:= LocalMessage and (not gmPrecise); s:= CurrentBinds[code]; s[1]:= '-'; ParseCommand(s, Trusted); @@ -200,7 +202,7 @@ else begin if CurrentBinds[code] = 'switch' then - LocalMessage:= LocalMessage and not(gmSwitch) + LocalMessage:= LocalMessage and (not gmSwitch) end end end; @@ -427,10 +429,10 @@ if ControllerNumAxes[j] > 20 then ControllerNumAxes[j]:= 20; //if ControllerNumBalls[j] > 20 then ControllerNumBalls[j]:= 20; - + if ControllerNumHats[j] > 20 then ControllerNumHats[j]:= 20; - + if ControllerNumButtons[j] > 20 then ControllerNumButtons[j]:= 20; @@ -492,6 +494,8 @@ p, l: shortstring; b: byte; begin + if cOnlyStats then exit; + AddFileLog('[BINDS] Loading binds from: ' + s); l:= ''; @@ -509,16 +513,17 @@ i:= 1; while (i <= length(l)) and (l[i] <> '=') do begin - if l[i] <> '%' then - begin - p:= p + l[i]; - inc(i) - end else + if l[i] = '%' then begin l[i]:= '$'; val(copy(l, i, 3), b); p:= p + char(b); inc(i, 3) + end + else + begin + p:= p + l[i]; + inc(i) end; end; @@ -527,6 +532,11 @@ l:= copy(l, i + 1, length(l) - i); if l <> 'default' then begin + if (length(l) = 2) and (l[1] = '\') then + l:= l[1] + '' + else if (l[1] = '"') and (l[length(l)] = '"') then + l:= copy(l, 2, length(l) - 2); + p:= cmd + ' ' + l + ' ' + p; ParseCommand(p, true) end @@ -534,7 +544,7 @@ end; pfsClose(f) - end + end else AddFileLog('[BINDS] file not found'); end; @@ -564,7 +574,7 @@ if b = 0 then OutError(errmsgUnknownVariable + ' "' + id + '"', false) else - begin + begin // add bind: first check if this cmd is already bound, and remove old bind i:= cKbdMaxIndex; repeat diff -r 31570b766315 -r ed5a6478e710 hedgewars/uLand.pas --- a/hedgewars/uLand.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uLand.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,76 +13,70 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} unit uLand; interface -uses SDLh, uLandTemplates, uFloat, uConsts, uTypes, uAILandMarks; +uses SDLh, uLandTemplates, uConsts, uTypes, uAILandMarks; procedure initModule; procedure freeModule; procedure DrawBottomBorder; procedure GenMap; procedure GenPreview(out Preview: TPreview); +procedure GenPreviewAlpha(out Preview: TPreviewAlpha); implementation uses uConsole, uStore, uRandom, uLandObjects, uIO, uLandTexture, SysUtils, uVariables, uUtils, uCommands, adler32, uDebug, uLandPainted, uTextures, - uLandGenMaze, uLandOutline, uPhysFSLayer; + uLandGenMaze, uPhysFSLayer, uScript, uLandGenPerlin, + uLandGenTemplateBased, uLandUtils; var digest: shortstring; + maskOnly: boolean; -procedure ResizeLand(width, height: LongWord); -var potW, potH: LongInt; -begin -potW:= toPowerOf2(width); -potH:= toPowerOf2(height); -if (potW <> LAND_WIDTH) or (potH <> LAND_HEIGHT) then - begin - LAND_WIDTH:= potW; - LAND_HEIGHT:= potH; - LAND_WIDTH_MASK:= not(LAND_WIDTH-1); - LAND_HEIGHT_MASK:= not(LAND_HEIGHT-1); - cWaterLine:= LAND_HEIGHT; - if (cReducedQuality and rqBlurryLand) = 0 then - SetLength(LandPixels, LAND_HEIGHT, LAND_WIDTH) + +procedure PrettifyLandAlpha(); +begin + if (cReducedQuality and rqBlurryLand) <> 0 then + PrettifyAlpha2D(LandPixels, LAND_HEIGHT div 2, LAND_WIDTH div 2) else - SetLength(LandPixels, LAND_HEIGHT div 2, LAND_WIDTH div 2); - - SetLength(Land, LAND_HEIGHT, LAND_WIDTH); - SetLength(LandDirty, (LAND_HEIGHT div 32), (LAND_WIDTH div 32)); - // 0.5 is already approaching on unplayable - if (width div 4096 >= 2) or (height div 2048 >= 2) then cMaxZoomLevel:= 0.5; - cMinMaxZoomLevelDelta:= cMaxZoomLevel - cMinZoomLevel - end; + PrettifyAlpha2D(LandPixels, LAND_HEIGHT, LAND_WIDTH); end; - procedure DrawBorderFromImage(Surface: PSDL_Surface); var tmpsurf: PSDL_Surface; r, rr: TSDL_Rect; x, yd, yu: LongInt; + targetMask: Word; begin tmpsurf:= LoadDataImage(ptCurrTheme, 'Border', ifCritical or ifIgnoreCaps or ifTransparent); + + // if mask only, all land gets filled with landtex and therefore needs borders + if maskOnly then + targetMask:= lfLandMask + else + targetMask:= lfBasic; + for x:= 0 to LAND_WIDTH - 1 do begin yd:= LAND_HEIGHT - 1; repeat - while (yd > 0) and (Land[yd, x] = 0) do dec(yd); + while (yd > 0) and ((Land[yd, x] and targetMask) = 0) do dec(yd); if (yd < 0) then yd:= 0; - while (yd < LAND_HEIGHT) and (Land[yd, x] <> 0) do + while (yd < LAND_HEIGHT) and ((Land[yd, x] and targetMask) <> 0) do inc(yd); dec(yd); yu:= yd; - while (yu > 0 ) and (Land[yu, x] <> 0) do dec(yu); - while (yu < yd ) and (Land[yu, x] = 0) do inc(yu); + while (yu > 0 ) and ((Land[yu, x] and targetMask) <> 0) do dec(yu); + while (yu < yd ) and ((Land[yu, x] and targetMask) = 0) do inc(yu); if (yd < LAND_HEIGHT - 1) and ((yd - yu) >= 16) then begin @@ -120,16 +114,16 @@ // vertical s:= LAND_HEIGHT; - + for x:= 0 to LAND_WIDTH - 1 do for y:= 0 to LAND_HEIGHT - 1 do - if LandPixels[y, x] = 0 then + if Land[y, x] = 0 then if s < y then begin for i:= max(s, y - 8) to y - 1 do begin if ((x + i) and 16) = 0 then c:= c1 else c:= c2; - + if (cReducedQuality and rqBlurryLand) = 0 then LandPixels[i, x]:= c else @@ -144,26 +138,26 @@ if s + 8 > y then begin if ((x + y) and 16) = 0 then c:= c1 else c:= c2; - + if (cReducedQuality and rqBlurryLand) = 0 then LandPixels[y, x]:= c else LandPixels[y div 2, x div 2]:= c - end; + end; end; - + // horizontal s:= LAND_WIDTH; - + for y:= 0 to LAND_HEIGHT - 1 do for x:= 0 to LAND_WIDTH - 1 do - if LandPixels[y, x] = 0 then + if Land[y, x] = 0 then if s < x then begin for i:= max(s, x - 8) to x - 1 do begin if ((y + i) and 16) = 0 then c:= c1 else c:= c2; - + if (cReducedQuality and rqBlurryLand) = 0 then LandPixels[y, i]:= c else @@ -178,31 +172,34 @@ if s + 8 > x then begin if ((x + y) and 16) = 0 then c:= c1 else c:= c2; - + if (cReducedQuality and rqBlurryLand) = 0 then LandPixels[y, x]:= c else LandPixels[y div 2, x div 2]:= c - end; + end; end end; procedure ColorizeLand(Surface: PSDL_Surface); var tmpsurf: PSDL_Surface; r: TSDL_Rect; + y: LongInt; // stupid SDL 1.2 uses stupid SmallInt for y which limits us to 32767. But is even worse if LandTex is large, can overflow on 32767 map. begin tmpsurf:= LoadDataImage(ptCurrTheme, 'LandTex', ifCritical or ifIgnoreCaps); r.y:= 0; - while r.y < LAND_HEIGHT do - begin + y:= 0; + while y < LAND_HEIGHT do + begin r.x:= 0; while r.x < LAND_WIDTH do - begin + begin SDL_UpperBlit(tmpsurf, nil, Surface, @r); inc(r.x, tmpsurf^.w) + end; + inc(y, tmpsurf^.h); + r.y:= y end; - inc(r.y, tmpsurf^.h) - end; SDL_FreeSurface(tmpsurf); // freed in freeModule() below @@ -210,138 +207,6 @@ if (LandBackSurface <> nil) and GrayScale then Surface2GrayScale(LandBackSurface); end; -procedure SetPoints(var Template: TEdgeTemplate; var pa: TPixAr; fps: PPointArray); -var i: LongInt; -begin -with Template do - begin - pa.Count:= BasePointsCount; - for i:= 0 to pred(pa.Count) do - begin - pa.ar[i].x:= BasePoints^[i].x + LongInt(GetRandom(BasePoints^[i].w)); - if pa.ar[i].x <> NTPX then - pa.ar[i].x:= pa.ar[i].x + ((LAND_WIDTH - Template.TemplateWidth) div 2); - pa.ar[i].y:= BasePoints^[i].y + LongInt(GetRandom(BasePoints^[i].h)) + LAND_HEIGHT - LongInt(Template.TemplateHeight) - end; - - if canMirror then - if getrandom(2) = 0 then - begin - for i:= 0 to pred(BasePointsCount) do - if pa.ar[i].x <> NTPX then - pa.ar[i].x:= LAND_WIDTH - 1 - pa.ar[i].x; - for i:= 0 to pred(FillPointsCount) do - fps^[i].x:= LAND_WIDTH - 1 - fps^[i].x; - end; - -(* Experiment in making this option more useful - if ((not isNegative) and (cTemplateFilter = 4)) or - (canFlip and (getrandom(2) = 0)) then - begin - for i:= 0 to pred(BasePointsCount) do - begin - pa.ar[i].y:= LAND_HEIGHT - 1 - pa.ar[i].y + (LAND_HEIGHT - TemplateHeight) * 2; - if pa.ar[i].y > LAND_HEIGHT - 1 then - pa.ar[i].y:= LAND_HEIGHT - 1; - end; - for i:= 0 to pred(FillPointsCount) do - begin - FillPoints^[i].y:= LAND_HEIGHT - 1 - FillPoints^[i].y + (LAND_HEIGHT - TemplateHeight) * 2; - if FillPoints^[i].y > LAND_HEIGHT - 1 then - FillPoints^[i].y:= LAND_HEIGHT - 1; - end; - end; - end -*) -// template recycling. Pull these off the floor a bit - if (not isNegative) and (cTemplateFilter = 4) then - begin - for i:= 0 to pred(BasePointsCount) do - begin - dec(pa.ar[i].y, 100); - if pa.ar[i].y < 0 then - pa.ar[i].y:= 0; - end; - for i:= 0 to pred(FillPointsCount) do - begin - dec(fps^[i].y, 100); - if fps^[i].y < 0 then - fps^[i].y:= 0; - end; - end; - - if (canFlip and (getrandom(2) = 0)) then - begin - for i:= 0 to pred(BasePointsCount) do - pa.ar[i].y:= LAND_HEIGHT - 1 - pa.ar[i].y; - for i:= 0 to pred(FillPointsCount) do - fps^[i].y:= LAND_HEIGHT - 1 - fps^[i].y; - end; - end -end; - - -procedure GenBlank(var Template: TEdgeTemplate); -var pa: TPixAr; - i: Longword; - y, x: Longword; - fps: TPointArray; -begin - fps:=Template.FillPoints^; - ResizeLand(Template.TemplateWidth, Template.TemplateHeight); - for y:= 0 to LAND_HEIGHT - 1 do - for x:= 0 to LAND_WIDTH - 1 do - Land[y, x]:= lfBasic; - {$HINTS OFF} - SetPoints(Template, pa, @fps); - {$HINTS ON} - for i:= 1 to Template.BezierizeCount do - begin - BezierizeEdge(pa, _0_5); - RandomizePoints(pa); - RandomizePoints(pa) - end; - for i:= 1 to Template.RandPassesCount do - RandomizePoints(pa); - BezierizeEdge(pa, _0_1); - - - DrawEdge(pa, 0); - - with Template do - for i:= 0 to pred(FillPointsCount) do - with fps[i] do - FillLand(x, y); - - DrawEdge(pa, lfBasic); - - MaxHedgehogs:= Template.MaxHedgehogs; - hasGirders:= Template.hasGirders; - playHeight:= Template.TemplateHeight; - playWidth:= Template.TemplateWidth; - leftX:= ((LAND_WIDTH - playWidth) div 2); - rightX:= (playWidth + ((LAND_WIDTH - playWidth) div 2)) - 1; - topY:= LAND_HEIGHT - playHeight; - - // HACK: force to only cavern even if a cavern map is invertable if cTemplateFilter = 4 ? - if (cTemplateFilter = 4) - or (Template.canInvert and (getrandom(2) = 0)) - or (not Template.canInvert and Template.isNegative) then - begin - hasBorder:= true; - for y:= 0 to LAND_HEIGHT - 1 do - for x:= 0 to LAND_WIDTH - 1 do - if (y < topY) or (x < leftX) or (x > rightX) then - Land[y, x]:= 0 - else - begin - if Land[y, x] = 0 then - Land[y, x]:= lfBasic - else if Land[y, x] = lfBasic then - Land[y, x]:= 0; - end; - end; -end; procedure GenDrawnMap; begin @@ -372,7 +237,7 @@ dec(l, TemplateCounts[cTemplateFilter]); until l < 0; end else getRandom(1); - + case cTemplateFilter of 0: OutError('Ask unC0Rr about what you did wrong', true); 1: SelectTemplate:= SmallTemplates[getrandom(TemplateCounts[cTemplateFilter])]; @@ -384,7 +249,7 @@ 6: begin SelectTemplate:= min(LuaTemplateNumber,High(EdgeTemplates)); GetRandom(2) // burn 1 - end; + end end end; @@ -410,7 +275,7 @@ else LandPixels[y div 2, x div 2]:= p^[x] or AMask; - p:= @(p^[Surface^.pitch div 4]); + p:= PLongwordArray(@(p^[Surface^.pitch div 4])); end; if SDL_MustLock(Surface) then @@ -433,12 +298,12 @@ LandSurface2LandPixels(tmpsurf); SDL_FreeSurface(tmpsurf); - + if gameFlags and gfShoppaBorder <> 0 then DrawShoppaBorder; - + for x:= leftX+2 to rightX-2 do for y:= topY+2 to LAND_HEIGHT-3 do - if (Land[y, x] = 0) and + if (Land[y, x] = 0) and (((Land[y, x-1] = lfBasic) and ((Land[y+1,x] = lfBasic)) or (Land[y-1,x] = lfBasic)) or ((Land[y, x+1] = lfBasic) and ((Land[y-1,x] = lfBasic) or (Land[y+1,x] = lfBasic)))) then begin @@ -446,16 +311,16 @@ begin if (Land[y, x-1] = lfBasic) and (LandPixels[y, x-1] and AMask <> 0) then LandPixels[y, x]:= LandPixels[y, x-1] - + else if (Land[y, x+1] = lfBasic) and (LandPixels[y, x+1] and AMask <> 0) then LandPixels[y, x]:= LandPixels[y, x+1] - + else if (Land[y-1, x] = lfBasic) and (LandPixels[y-1, x] and AMask <> 0) then LandPixels[y, x]:= LandPixels[y-1, x] - + else if (Land[y+1, x] = lfBasic) and (LandPixels[y+1, x] and AMask <> 0) then LandPixels[y, x]:= LandPixels[y+1, x]; - + if (((LandPixels[y,x] and AMask) shr AShift) > 10) then LandPixels[y,x]:= (LandPixels[y,x] and (not AMask)) or (128 shl AShift) end; @@ -470,25 +335,25 @@ ((Land[y-1, x] = lfBasic) and (Land[y-1,x+1] = lfBasic) and (Land[y,x+2] = lfBasic)) or ((Land[y+1, x] = lfBasic) and (Land[y+1,x-1] = lfBasic) and (Land[y,x-2] = lfBasic)) or ((Land[y-1, x] = lfBasic) and (Land[y-1,x-1] = lfBasic) and (Land[y,x-2] = lfBasic))) then - + begin - + if (cReducedQuality and rqBlurryLand) = 0 then - + begin - + if (Land[y, x-1] = lfBasic) and (LandPixels[y,x-1] and AMask <> 0) then LandPixels[y, x]:= LandPixels[y, x-1] - + else if (Land[y, x+1] = lfBasic) and (LandPixels[y,x+1] and AMask <> 0) then LandPixels[y, x]:= LandPixels[y, x+1] - + else if (Land[y+1, x] = lfBasic) and (LandPixels[y+1,x] and AMask <> 0) then LandPixels[y, x]:= LandPixels[y+1, x] - + else if (Land[y-1, x] = lfBasic) and (LandPixels[y-1,x] and AMask <> 0) then LandPixels[y, x]:= LandPixels[y-1, x]; - + if (((LandPixels[y,x] and AMask) shr AShift) > 10) then LandPixels[y,x]:= (LandPixels[y,x] and (not AMask)) or (64 shl AShift) end; @@ -516,8 +381,16 @@ BlitImageAndGenerateCollisionInfo(leftX+150, LAND_HEIGHT - tmpsurf^.h, tmpsurf^.w, tmpsurf); SDL_FreeSurface(tmpsurf); -tmpsurf:= LoadDataImage(ptForts, ClansArray[1]^.Teams[0]^.FortName + 'R', ifAlpha or ifCritical or ifTransparent or ifIgnoreCaps); -BlitImageAndGenerateCollisionInfo(rightX - 150 - tmpsurf^.w, LAND_HEIGHT - tmpsurf^.h, tmpsurf^.w, tmpsurf); +// not critical because if no R we can fallback to mirrored L +tmpsurf:= LoadDataImage(ptForts, ClansArray[1]^.Teams[0]^.FortName + 'R', ifAlpha or ifTransparent or ifIgnoreCaps); +// fallback +if tmpsurf = nil then + begin + tmpsurf:= LoadDataImage(ptForts, ClansArray[1]^.Teams[0]^.FortName + 'L', ifAlpha or ifCritical or ifTransparent or ifIgnoreCaps); + BlitImageAndGenerateCollisionInfo(rightX - 150 - tmpsurf^.w, LAND_HEIGHT - tmpsurf^.h, tmpsurf^.w, tmpsurf, 0, true); + end +else + BlitImageAndGenerateCollisionInfo(rightX - 150 - tmpsurf^.w, LAND_HEIGHT - tmpsurf^.h, tmpsurf^.w, tmpsurf); SDL_FreeSurface(tmpsurf); end; @@ -585,7 +458,7 @@ begin for x:= 0 to Pred(tmpsurf^.w) do SetLand(Land[cpY + y, cpX + x], p^[x]); - p:= @(p^[tmpsurf^.pitch div 4]); + p:= PLongwordArray(@(p^[tmpsurf^.pitch div 4])); end; if SDL_MustLock(tmpsurf) then @@ -661,7 +534,6 @@ procedure GenMap; var x, y, w, c: Longword; map, mask: shortstring; - maskOnly: boolean; begin hasBorder:= false; maskOnly:= false; @@ -689,9 +561,10 @@ begin WriteLnToConsole('Generating land...'); case cMapGen of - 0: GenBlank(EdgeTemplates[SelectTemplate]); - 1: begin ResizeLand(4096,2048); GenMaze; end; - 2: GenDrawnMap; + mgRandom: GenTemplated(EdgeTemplates[SelectTemplate]); + mgMaze : begin ResizeLand(4096,2048); GenMaze; end; + mgPerlin: begin ResizeLand(4096,2048); GenPerlin; end; + mgDrawn : GenDrawnMap; else OutError('Unknown mapgen', true); end; @@ -721,10 +594,19 @@ if hasBorder then begin - for y:= 0 to LAND_HEIGHT - 1 do - for x:= 0 to LAND_WIDTH - 1 do - if (y < topY) or (x < leftX) or (x > rightX) then + if WorldEdge = weNone then + begin + for y:= 0 to LAND_HEIGHT - 1 do + for x:= 0 to LAND_WIDTH - 1 do + if (y < topY) or (x < leftX) or (x > rightX) then + Land[y, x]:= lfIndestructible; + end + else if topY > 0 then + begin + for y:= 0 to LongInt(topY) - 1 do + for x:= 0 to LAND_WIDTH - 1 do Land[y, x]:= lfIndestructible; + end; // experiment hardcoding cave // also try basing cave dimensions on map/template dimensions, if they exist for w:= 0 to 5 do // width of 3 allowed hogs to be knocked through with grenade @@ -775,7 +657,7 @@ if (GameFlags and gfForts = 0) and (maskOnly or (cPathz[ptMapCurrent] = '')) then AddObjects - + else AddProgress(); @@ -802,12 +684,17 @@ begin w:= LandPixels[y div 2,x div 2]; w:= ((w shr RShift and $FF) + (w shr BShift and $FF) + (w shr GShift and $FF)) div 3; - if w > 255 then - w:= 255; w:= (w and $FF shl RShift) or (w and $FF shl BShift) or (w and $FF shl GShift) or (LandPixels[y div 2,x div 2] and AMask); LandPixels[y,x]:= w or (LandPixels[y div 2, x div 2] and AMask) end end; + +PrettifyLandAlpha(); + +// adjust world edges for borderless maps +if (WorldEdge <> weNone) and (not hasBorder) then + InitWorldEdges(); + end; procedure GenPreview(out Preview: TPreview); @@ -815,9 +702,10 @@ begin WriteLnToConsole('Generating preview...'); case cMapGen of - 0: GenBlank(EdgeTemplates[SelectTemplate]); - 1: begin ResizeLand(4096,2048); GenMaze; end; - 2: GenDrawnMap; + mgRandom: GenTemplated(EdgeTemplates[SelectTemplate]); + mgMaze: begin ResizeLand(4096,2048); GenMaze; end; + mgPerlin: begin ResizeLand(4096,2048); GenPerlin; end; + mgDrawn: GenDrawnMap; else OutError('Unknown mapgen', true); end; @@ -831,7 +719,7 @@ rw:= rh*2; end; if rh < rw div 2 then rh:= rw * 2; - + ox:= (rw-LAND_WIDTH) div 2; oy:= rh-LAND_HEIGHT; @@ -847,7 +735,7 @@ cbit:= bit * 8; for yy:= y * lh to y * lh + 7 do for xx:= x * lw + cbit to x * lw + cbit + 7 do - if ((yy-oy) and LAND_HEIGHT_MASK = 0) and ((xx-ox) and LAND_WIDTH_MASK = 0) + if ((yy-oy) and LAND_HEIGHT_MASK = 0) and ((xx-ox) and LAND_WIDTH_MASK = 0) and (Land[yy-oy, xx-ox] <> 0) then inc(t); if t > 8 then @@ -857,6 +745,49 @@ end; +procedure GenPreviewAlpha(out Preview: TPreviewAlpha); +var rh, rw, ox, oy, x, y, xx, yy, t, lh, lw: LongInt; +begin + WriteLnToConsole('Generating preview...'); + case cMapGen of + mgRandom: GenTemplated(EdgeTemplates[SelectTemplate]); + mgMaze: begin ResizeLand(4096,2048); GenMaze; end; + mgPerlin: begin ResizeLand(4096,2048); GenPerlin; end; + mgDrawn: GenDrawnMap; + else + OutError('Unknown mapgen', true); + end; + + // strict scaling needed here since preview assumes a rectangle + rh:= max(LAND_HEIGHT, 2048); + rw:= max(LAND_WIDTH, 4096); + ox:= 0; + if rw < rh*2 then + begin + rw:= rh*2; + end; + if rh < rw div 2 then rh:= rw * 2; + + ox:= (rw-LAND_WIDTH) div 2; + oy:= rh-LAND_HEIGHT; + + lh:= rh div 128; + lw:= rw div 256; + for y:= 0 to 127 do + for x:= 0 to 255 do + begin + t:= 0; + + for yy:= y * lh - oy to y * lh + lh - 1 - oy do + for xx:= x * lw - ox to x * lw + lw - 1 - ox do + if (yy and LAND_HEIGHT_MASK = 0) and (xx and LAND_WIDTH_MASK = 0) + and (Land[yy, xx] <> 0) then + inc(t); + + Preview[y, x]:= t * 255 div (lh * lw); + end; +end; + procedure chLandCheck(var s: shortstring); begin AddFileLog('CheckLandDigest: ' + s + ' digest : ' + digest); @@ -874,6 +805,8 @@ adler:= Adler32Update(adler, @Land[i,0], LAND_WIDTH); s:= 'M' + IntToStr(adler) + cScriptName; + ScriptSetString('LandDigest', s); + chLandCheck(s); SendIPCRaw(@s[0], Length(s) + 1) end; @@ -885,6 +818,7 @@ LandBackSurface:= nil; digest:= ''; + maskOnly:= false; LAND_WIDTH:= 0; LAND_HEIGHT:= 0; (* diff -r 31570b766315 -r ed5a6478e710 hedgewars/uLandGenMaze.pas --- a/hedgewars/uLandGenMaze.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uLandGenMaze.pas Tue Nov 10 20:43:13 2015 +0100 @@ -8,7 +8,7 @@ implementation -uses uRandom, uLandOutline, uLandTemplates, uVariables, uFloat, uConsts; +uses uRandom, uLandOutline, uLandTemplates, uVariables, uFloat, uConsts, uLandGenTemplateBased, uUtils; type direction = record x, y: LongInt; end; const DIR_N: direction = (x: 0; y: -1); @@ -16,7 +16,6 @@ DIR_S: direction = (x: 0; y: 1); DIR_W: direction = (x: -1; y: 0); - operator = (const a, b: direction) c: Boolean; begin c := (a.x = b.x) and (a.y = b.y); @@ -27,28 +26,43 @@ large_cell_size = 256; braidness = 10; -var x, y: LongInt; - cellsize: LongInt; //selected by the user in the gui - seen_cells_x, seen_cells_y: LongInt; //number of cells that can be visited by the generator, that is every second cell in x and y direction. the cells between there are walls that will be removed when we move from one cell to another - num_edges_x, num_edges_y: LongInt; //number of resulting edges that need to be vertexificated - num_cells_x, num_cells_y: LongInt; //actual number of cells, depending on cell size - seen_list: array of array of LongInt; - xwalls: array of array of Boolean; - ywalls: array of array of Boolean; - x_edge_list: array of array of Boolean; - y_edge_list: array of array of Boolean; - maze: array of array of Boolean; - pa: TPixAr; - num_vertices: LongInt; - off_y: LongInt; - num_steps: LongInt; - current_step: LongInt; - step_done: array of Boolean; - done: Boolean; - last_cell: array of record x, y: LongInt; end; - came_from: array of array of record x, y: LongInt; end; +type + cell_t = record x,y : LongInt + end; + +var x, y : LongInt; + cellsize : LongInt; //selected by the user in the gui + seen_cells_x, seen_cells_y : LongInt; //number of cells that can be visited by the generator, that is every second cell in x and y direction. the cells between there are walls that will be removed when we move from one cell to another + num_edges_x, num_edges_y : LongInt; //number of resulting edges that need to be vertexificated + num_cells_x, num_cells_y : LongInt; //actual number of cells, depending on cell size + + + seen_list : array of array of LongInt; + xwalls : array of array of Boolean; + ywalls : array of array of Boolean; + x_edge_list : array of array of Boolean; + y_edge_list : array of array of Boolean; + maze : array of array of Boolean; + + pa : TPixAr; + num_vertices : LongInt; + off_y : LongInt; + num_steps : LongInt; + current_step : LongInt; + + step_done : array of Boolean; + + done : Boolean; + +{ last_cell : array 0..3 of record x, y :LongInt ; end; + came_from : array of array of record x, y: LongInt; end; + came_from_pos : array of LongInt; +} + last_cell : array of cell_t; + came_from : array of array of cell_t; came_from_pos: array of LongInt; - maze_inverted: Boolean; + + maze_inverted : Boolean; function when_seen(x: LongInt; y: LongInt): LongInt; begin @@ -104,11 +118,11 @@ begin //we have already seen the target cell, decide if we should remove the wall anyway //(or put a wall there if maze_inverted, but we are not doing that right now) - if not maze_inverted and (GetRandom(braidness) = 0) then + if (not maze_inverted) and (GetRandom(braidness) = 0) then //or just warn that inverted+braid+indestructible terrain != good idea begin case dir.x of - + -1: if x > 0 then ywalls[x-1, y] := false; @@ -178,46 +192,56 @@ last_cell[current_step].x := came_from[current_step, came_from_pos[current_step]].x; last_cell[current_step].y := came_from[current_step, came_from_pos[current_step]].y; came_from_pos[current_step] := came_from_pos[current_step] - 1; - + if came_from_pos[current_step] >= 0 then - see_cell - + see_cell() + else step_done[current_step] := true; end; end; procedure add_vertex(x, y: LongInt); -var tmp_x, tmp_y: LongInt; -begin -if x = NTPX then +var tmp_x, tmp_y, nx, ny: LongInt; begin - if pa.ar[num_vertices - 6].x = NTPX then + if x = NTPX then begin - num_vertices := num_vertices - 6; + if pa.ar[num_vertices - 6].x = NTPX then + begin + num_vertices := num_vertices - 6; + end + else + begin + pa.ar[num_vertices].x := NTPX; + pa.ar[num_vertices].y := 0; + end end else begin - pa.ar[num_vertices].x := NTPX; - pa.ar[num_vertices].y := 0; - end -end -else -begin - if maze_inverted or (x mod 2 = 0) then - tmp_x := cellsize - else - tmp_x := cellsize * 2 div 3; - - if maze_inverted or (y mod 2 = 0) then - tmp_y := cellsize - else - tmp_y := cellsize * 2 div 3; + if maze_inverted or (x mod 2 = 0) then + tmp_x := cellsize + else + tmp_x := cellsize * 2 div 3; + + if maze_inverted or (y mod 2 = 0) then + tmp_y := cellsize + else + tmp_y := cellsize * 2 div 3; - pa.ar[num_vertices].x := (x-1)*cellsize + tmp_x; - pa.ar[num_vertices].y := (y-1)*cellsize + tmp_y + off_y; -end; -num_vertices := num_vertices + 1; + nx:= (x-1)*cellsize + tmp_x; + ny:= (y-1)*cellsize + tmp_y + off_y; + + if num_vertices > 2 then + if ((pa.ar[num_vertices - 2].x = pa.ar[num_vertices - 1].x) and (pa.ar[num_vertices - 1].x = nx)) + or ((pa.ar[num_vertices - 2].y = pa.ar[num_vertices - 1].y) and (pa.ar[num_vertices - 1].y = ny)) + then + dec(num_vertices); + + pa.ar[num_vertices].x := nx; + pa.ar[num_vertices].y := ny; + end; + + num_vertices := num_vertices + 1; end; procedure add_edge(x, y: LongInt; dir: direction); @@ -251,78 +275,91 @@ else dir := DIR_N; -if (dir = DIR_N) and is_x_edge(x, y) then - begin - x_edge_list[x, y] := false; - add_vertex(x+1, y); - add_edge(x, y-1, DIR_N); - break; - end; + if (dir = DIR_N) and is_x_edge(x, y) then + begin + x_edge_list[x, y] := false; + add_vertex(x+1, y); + add_edge(x, y-1, DIR_N); + break; + end; -if (dir = DIR_E) and is_y_edge(x+1, y) then - begin - y_edge_list[x+1, y] := false; - add_vertex(x+2, y+1); - add_edge(x+1, y, DIR_E); - break; - end; + if (dir = DIR_E) and is_y_edge(x+1, y) then + begin + y_edge_list[x+1, y] := false; + add_vertex(x+2, y+1); + add_edge(x+1, y, DIR_E); + break; + end; -if (dir = DIR_S) and is_x_edge(x, y+1) then - begin - x_edge_list[x, y+1] := false; - add_vertex(x+1, y+2); - add_edge(x, y+1, DIR_S); - break; - end; + if (dir = DIR_S) and is_x_edge(x, y+1) then + begin + x_edge_list[x, y+1] := false; + add_vertex(x+1, y+2); + add_edge(x, y+1, DIR_S); + break; + end; -if (dir = DIR_W) and is_y_edge(x, y) then - begin - y_edge_list[x, y] := false; - add_vertex(x, y+1); - add_edge(x-1, y, DIR_W); - break; + if (dir = DIR_W) and is_y_edge(x, y) then + begin + y_edge_list[x, y] := false; + add_vertex(x, y+1); + add_edge(x-1, y, DIR_W); + break; + end; end; -end; end; procedure GenMaze; +var i: Longword; begin case cTemplateFilter of 0: begin - cellsize := small_cell_size; - maze_inverted := false; - end; + cellsize := small_cell_size; + maze_inverted := false; + minDistance:= max(cFeatureSize*8,32); + dabDiv:= 150; + end; 1: begin - cellsize := medium_cell_size; - maze_inverted := false; - end; + cellsize := medium_cell_size; + minDistance:= max(cFeatureSize*6,20); + maze_inverted := false; + dabDiv:= 100; + end; 2: begin - cellsize := large_cell_size; - maze_inverted := false; - end; + cellsize := large_cell_size; + minDistance:= max(cFeatureSize*5,12); + maze_inverted := false; + dabDiv:= 90; + end; 3: begin - cellsize := small_cell_size; - maze_inverted := true; - end; + cellsize := small_cell_size; + minDistance:= max(cFeatureSize*8,32); + maze_inverted := true; + dabDiv:= 130; + end; 4: begin - cellsize := medium_cell_size; - maze_inverted := true; - end; + cellsize := medium_cell_size; + minDistance:= max(cFeatureSize*6,20); + maze_inverted := true; + dabDiv:= 100; + end; 5: begin - cellsize := large_cell_size; - maze_inverted := true; + cellsize := large_cell_size; + minDistance:= max(cFeatureSize*5,12); + maze_inverted := true; + dabDiv:= 85; + end; end; -end; num_cells_x := LAND_WIDTH div cellsize; if not odd(num_cells_x) then num_cells_x := num_cells_x - 1; //needs to be odd - + num_cells_y := LAND_HEIGHT div cellsize; if not odd(num_cells_y) then num_cells_y := num_cells_y - 1; - + num_edges_x := num_cells_x - 1; num_edges_y := num_cells_y - 1; @@ -333,19 +370,23 @@ num_steps := 3 //TODO randomize, between 3 and 5? else num_steps := 1; - + SetLength(step_done, num_steps); SetLength(last_cell, num_steps); SetLength(came_from_pos, num_steps); SetLength(came_from, num_steps, num_cells_x*num_cells_y); + done := false; for current_step := 0 to num_steps - 1 do + begin step_done[current_step] := false; came_from_pos[current_step] := 0; - + end; + current_step := 0; + SetLength(seen_list, seen_cells_x, seen_cells_y); SetLength(xwalls, seen_cells_x, seen_cells_y - 1); SetLength(ywalls, seen_cells_x - 1, seen_cells_y); @@ -353,6 +394,7 @@ SetLength(y_edge_list, num_cells_x, num_edges_y); SetLength(maze, num_cells_x, num_cells_y); + num_vertices := 0; playHeight := num_cells_y * cellsize; @@ -402,14 +444,14 @@ begin done := true; for current_step := 0 to num_steps-1 do - begin + begin if not step_done[current_step] then - begin + begin see_cell; done := false; + end; end; end; -end; for x := 0 to seen_cells_x - 1 do for y := 0 to seen_cells_y - 1 do @@ -454,15 +496,34 @@ pa.count := num_vertices; -RandomizePoints(pa); -BezierizeEdge(pa, _0_25); -RandomizePoints(pa); -BezierizeEdge(pa, _0_25); +leftX:= 0; +rightX:= playWidth; +topY:= off_y; + +// fill point +pa.ar[pa.Count].x:= 1; +pa.ar[pa.Count].y:= 1 + off_y; + +{ +for i:= 0 to pa.Count - 1 do + begin + system.writeln(pa.ar[i].x, ', ', pa.ar[i].y); + end; +} + +// divide while it divides +repeat + i:= pa.Count; + DivideEdges(1, pa) +until i = pa.Count; + +// make it smooth +BezierizeEdge(pa, _0_2); DrawEdge(pa, 0); if maze_inverted then - FillLand(1, 1+off_y) + FillLand(1, 1 + off_y, 0, 0) else begin x := 0; @@ -470,7 +531,7 @@ x := x + 1; while Land[cellsize div 2 + cellsize + off_y, x] = 0 do x := x + 1; - FillLand(x+1, cellsize div 2 + cellsize + off_y); + FillLand(x+1, cellsize div 2 + cellsize + off_y, 0, 0); end; MaxHedgehogs:= 32; @@ -478,9 +539,7 @@ hasGirders:= false else hasGirders := true; -leftX:= 0; -rightX:= playWidth; -topY:= off_y; + hasBorder := false; end; diff -r 31570b766315 -r ed5a6478e710 hedgewars/uLandGenPerlin.pas --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hedgewars/uLandGenPerlin.pas Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,197 @@ +{$INCLUDE "options.inc"} + +unit uLandGenPerlin; +interface + +procedure GenPerlin; + +implementation +uses uVariables + , uConsts + , uRandom + , uLandOutline // FillLand + , uUtils + ; + +var p: array[0..511] of LongInt; + +const fadear: array[byte] of LongInt = +(0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 3, 3, 4, 6, 7, 9, 10, 12, +14, 17, 19, 22, 25, 29, 32, 36, 40, 45, 49, 54, 60, 65, 71, +77, 84, 91, 98, 105, 113, 121, 130, 139, 148, 158, 167, 178, +188, 199, 211, 222, 234, 247, 259, 273, 286, 300, 314, 329, 344, +359, 374, 390, 407, 424, 441, 458, 476, 494, 512, 531, 550, +570, 589, 609, 630, 651, 672, 693, 715, 737, 759, 782, 805, 828, +851, 875, 899, 923, 948, 973, 998, 1023, 1049, 1074, 1100, 1127, +1153, 1180, 1207, 1234, 1261, 1289, 1316, 1344, 1372, 1400, 1429, +1457, 1486, 1515, 1543, 1572, 1602, 1631, 1660, 1690, 1719, 1749, +1778, 1808, 1838, 1868, 1898, 1928, 1958, 1988, 2018, 2048, 2077, +2107, 2137, 2167, 2197, 2227, 2257, 2287, 2317, 2346, 2376, 2405, +2435, 2464, 2493, 2523, 2552, 2580, 2609, 2638, 2666, 2695, 2723, +2751, 2779, 2806, 2834, 2861, 2888, 2915, 2942, 2968, 2995, 3021, +3046, 3072, 3097, 3122, 3147, 3172, 3196, 3220, 3244, 3267, 3290, +3313, 3336, 3358, 3380, 3402, 3423, 3444, 3465, 3486, 3506, 3525, +3545, 3564, 3583, 3601, 3619, 3637, 3654, 3672, 3688, 3705, 3721, +3736, 3751, 3766, 3781, 3795, 3809, 3822, 3836, 3848, 3861, 3873, +3884, 3896, 3907, 3917, 3928, 3937, 3947, 3956, 3965, 3974, 3982, +3990, 3997, 4004, 4011, 4018, 4024, 4030, 4035, 4041, 4046, 4050, +4055, 4059, 4063, 4066, 4070, 4073, 4076, 4078, 4081, 4083, 4085, +4086, 4088, 4089, 4091, 4092, 4092, 4093, 4094, 4094, 4095, 4095, +4095, 4095, 4095, 4095, 4095); + +function fade(t: LongInt) : LongInt; inline; +var t0, t1: LongInt; +begin + t0:= fadear[t shr 8]; + + if t0 = fadear[255] then + t1:= t0 + else + t1:= fadear[t shr 8 + 1]; + + fade:= t0 + ((t and 255) * (t1 - t0) shr 8) +end; + + +function lerp(t, a, b: LongInt) : LongInt; inline; +begin + lerp:= a + ((Int64(b) - a) * t shr 12) +end; + + +function grad(hash, x, y: LongInt) : LongInt; inline; +var h, v, u: LongInt; +begin + h:= hash and 15; + if h < 8 then u:= x else u:= y; + if h < 4 then v:= y else + if (h = 12) or (h = 14) then v:= x else v:= 0; + + if (h and 1) <> 0 then u:= -u; + if (h and 2) <> 0 then v:= -v; + + grad:= u + v +end; + + +function inoise(x, y: LongInt) : LongInt; inline; +const N = $10000; +var xx, yy, u, v, A, AA, AB, B, BA, BB: LongInt; +begin + xx:= (x shr 16) and 255; + yy:= (y shr 16) and 255; + + x:= x and $FFFF; + y:= y and $FFFF; + + u:= fade(x); + v:= fade(y); + + A:= p[xx ] + yy; AA:= p[A]; AB:= p[A + 1]; + B:= p[xx + 1] + yy; BA:= p[B]; BB:= p[B + 1]; + + inoise:= + lerp(v, lerp(u, grad(p[AA ], x , y ), + grad(p[BA ], x-N , y )), + lerp(u, grad(p[AB ], x , y-N), + grad(p[BB ], x-N , y-N))); +end; + +procedure inoise_setup(); +var i, ii, t: Longword; +begin + for i:= 0 to 254 do + p[i]:= i + 1; + p[255]:= 0; + + for i:= 0 to 254 do + begin + ii:= GetRandom(256 - i) + i; + t:= p[i]; + p[i]:= p[ii]; + p[ii]:= t + end; + + for i:= 0 to 255 do + p[256 + i]:= p[i]; +end; + +const width = 4096; + height = 2048; + minY = 500; + + //bottomPlateHeight = 90; + //bottomPlateMargin = 1200; + margin = 200; + +procedure GenPerlin; +var y, x, di, dj, r, param1, param2, rCutoff, detail: LongInt; +var df: Int64; +begin + param1:= cTemplateFilter div 3; + param2:= cTemplateFilter mod 3; + rCutoff:= min(max((26-cFeatureSize)*4,15),85); + detail:= (26-cFeatureSize)*16000+50000; // feature size is a slider from 1-25 at present. flip it for perlin + + df:= detail * (6 - param2 * 2); + + inoise_setup(); + + for y:= minY to pred(height) do + begin + di:= df * y div height; + for x:= 0 to pred(width) do + begin + dj:= df * x div width; + + r:= ((abs(inoise(di, dj)) + y*4) mod 65536 - (height - y) * 8) div 256; + + //r:= (abs(inoise(di, dj))) shr 8 and $ff; + if (x < margin) or (x > width - margin) then r:= r - abs(x - width div 2) + width div 2 - margin; // fade on edges + + //r:= r - max(0, - abs(x - width div 2) + width * 2 div 100); // split vertically in the middle + //r:= r + (trunc(1000 - sqrt(sqr(x - (width div 2)) * 4 + sqr(y - height * 5 div 4) * 22))) div 600 * 20; // ellipse + //r:= r + 1 - ((abs(x - (width div 2)) + abs(y - height) * 2)) div 32; // manhattan length ellipse + + { + if (y > height - bottomPlateHeight) and (x > bottomPlateMargin) and (x + bottomPlateMargin < width) then + begin + dy:= (y - height + bottomPlateHeight); + r:= r + dy; + + if x < bottomPlateMargin + bottomPlateHeight then + r:= r + (x - bottomPlateMargin - bottomPlateHeight) + else + if x + bottomPlateMargin + bottomPlateHeight > width then + r:= r - (x - width + bottomPlateMargin + bottomPlateHeight); + end; + } + + if r < rCutoff then + Land[y, x]:= 0 + else if param1 = 0 then + Land[y, x]:= lfObjMask + else + Land[y, x]:= lfBasic + end; + end; + + if param1 = 0 then + begin + for x:= 0 to width do + if Land[height - 1, x] = lfObjMask then FillLand(x, height - 1, 0, lfBasic); + + // strip all lfObjMask pixels + for y:= minY to LAND_HEIGHT - 1 do + for x:= 0 to LAND_WIDTH - 1 do + if Land[y, x] = lfObjMask then + Land[y, x]:= 0; + end; + + leftX:= 0; + rightX:= 4095; + topY:= 0; + hasBorder:= false; +end; + +end. diff -r 31570b766315 -r ed5a6478e710 hedgewars/uLandGenTemplateBased.pas --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hedgewars/uLandGenTemplateBased.pas Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,398 @@ +unit uLandGenTemplateBased; +interface + +uses uLandTemplates, uLandOutline; + +procedure GenTemplated(var Template: TEdgeTemplate); +procedure DivideEdges(fillPointsCount: LongWord; var pa: TPixAr); + +var minDistance, dabDiv: LongInt; // different details size + +implementation +uses uVariables, uTypes, uConsts, uFloat, uLandUtils, uRandom, SDLh, math; + + +procedure SetPoints(var Template: TEdgeTemplate; var pa: TPixAr; fps: PPointArray); +var i: LongInt; +begin + with Template do + begin + pa.Count:= BasePointsCount; + for i:= 0 to pred(LongInt(pa.Count)) do + begin + pa.ar[i].x:= BasePoints^[i].x + LongInt(GetRandom(BasePoints^[i].w)); + if pa.ar[i].x <> NTPX then + pa.ar[i].x:= pa.ar[i].x + ((LAND_WIDTH - Template.TemplateWidth) div 2); + pa.ar[i].y:= BasePoints^[i].y + LongInt(GetRandom(BasePoints^[i].h)) + LAND_HEIGHT - LongInt(Template.TemplateHeight) + end; + + if canMirror then + if getrandom(2) = 0 then + begin + for i:= 0 to pred(BasePointsCount) do + if pa.ar[i].x <> NTPX then + pa.ar[i].x:= LAND_WIDTH - 1 - pa.ar[i].x; + for i:= 0 to pred(FillPointsCount) do + fps^[i].x:= LAND_WIDTH - 1 - fps^[i].x; + end; + +(* Experiment in making this option more useful + if ((not isNegative) and (cTemplateFilter = 4)) or + (canFlip and (getrandom(2) = 0)) then + begin + for i:= 0 to pred(BasePointsCount) do + begin + pa.ar[i].y:= LAND_HEIGHT - 1 - pa.ar[i].y + (LAND_HEIGHT - TemplateHeight) * 2; + if pa.ar[i].y > LAND_HEIGHT - 1 then + pa.ar[i].y:= LAND_HEIGHT - 1; + end; + for i:= 0 to pred(FillPointsCount) do + begin + FillPoints^[i].y:= LAND_HEIGHT - 1 - FillPoints^[i].y + (LAND_HEIGHT - TemplateHeight) * 2; + if FillPoints^[i].y > LAND_HEIGHT - 1 then + FillPoints^[i].y:= LAND_HEIGHT - 1; + end; + end; + end +*) +// template recycling. Pull these off the floor a bit + if (not isNegative) and (cTemplateFilter = 4) then + begin + for i:= 0 to pred(BasePointsCount) do + begin + dec(pa.ar[i].y, 100); + if pa.ar[i].y < 0 then + pa.ar[i].y:= 0; + end; + for i:= 0 to pred(FillPointsCount) do + begin + dec(fps^[i].y, 100); + if fps^[i].y < 0 then + fps^[i].y:= 0; + end; + end; + + if (canFlip and (getrandom(2) = 0)) then + begin + for i:= 0 to pred(BasePointsCount) do + pa.ar[i].y:= LAND_HEIGHT - 1 - pa.ar[i].y; + for i:= 0 to pred(FillPointsCount) do + fps^[i].y:= LAND_HEIGHT - 1 - fps^[i].y; + end; + end +end; + + +procedure Distort1(var Template: TEdgeTemplate; var pa: TPixAr); +var i: Longword; +begin + for i:= 1 to Template.BezierizeCount do + begin + BezierizeEdge(pa, _0_5); + RandomizePoints(pa); + RandomizePoints(pa) + end; + for i:= 1 to Template.RandPassesCount do + RandomizePoints(pa); + BezierizeEdge(pa, _0_1); +end; + +procedure FindPoint(si: LongInt; fillPointsCount: LongWord; var newPoint: TPoint; var pa: TPixAr); +const mapBorderMargin = 40; +var p1, p2, p4, fp, mp: TPoint; + i, t1, t2, iy, ix, aqpb: LongInt; + a, b, p, q: LongInt; + dab, d, distL, distR: LongInt; +begin + // [p1, p2] is the segment we're trying to divide + p1:= pa.ar[si]; + p2:= pa.ar[si + 1]; + + if p2.x = NTPX then + // it is segment from last to first point, so need to find first point + begin + i:= si - 2; + while (i >= 0) and (pa.ar[i].x <> NTPX) do + dec(i); + p2:= pa.ar[i + 1] + end; + + // perpendicular vector + a:= p2.y - p1.y; + b:= p1.x - p2.x; + dab:= DistanceI(a, b).Round; + + // its middle point + mp.x:= (p1.x + p2.x) div 2; + mp.y:= (p1.y + p2.y) div 2; + + // don't process too short segments or those which are too close to map borders + if (p1.x = NTPX) + or (dab < minDistance * 3) + or (mp.x < LongInt(leftX) + mapBorderMargin) + or (mp.x > LongInt(rightX) - mapBorderMargin) + or (mp.y < LongInt(topY) + mapBorderMargin) + or (mp.y > LongInt(LAND_HEIGHT) - mapBorderMargin) + then + begin + newPoint:= p1; + exit; + end; + + // find distances to map borders + if a <> 0 then + begin + // left border + iy:= (LongInt(leftX) + mapBorderMargin - mp.x) * b div a + mp.y; + d:= DistanceI(mp.x - leftX - mapBorderMargin, mp.y - iy).Round; + t1:= a * (mp.x - mapBorderMargin) + b * (mp.y - iy); + if t1 > 0 then distL:= d else distR:= d; + + // right border + iy:= (LongInt(rightX) - mapBorderMargin - mp.x) * b div a + mp.y; + d:= DistanceI(mp.x - rightX + mapBorderMargin, mp.y - iy).Round; + if t1 > 0 then distR:= d else distL:= d; + end else + begin + distL:= LAND_WIDTH + LAND_HEIGHT; + distR:= distL; + end; + + if b <> 0 then + begin + // top border + ix:= (LongInt(topY) + mapBorderMargin - mp.y) * a div b + mp.x; + d:= DistanceI(mp.y - topY - mapBorderMargin, mp.x - ix).Round; + t2:= b * (mp.y - mapBorderMargin) + a * (mp.x - ix); + if t2 > 0 then distL:= min(d, distL) else distR:= min(d, distR); + + // bottom border + ix:= (LAND_HEIGHT - mapBorderMargin - mp.y) * a div b + mp.x; + d:= DistanceI(mp.y - LAND_HEIGHT + mapBorderMargin, mp.x - ix).Round; + if t2 > 0 then distR:= min(d, distR) else distL:= min(d, distL); + end; + + // now go through all other segments + fp:= pa.ar[0]; + for i:= 0 to LongInt(pa.Count) - 2 do + if pa.ar[i].x = NTPX then + fp:= pa.ar[i + 1] + else if (i <> si) then + begin + p4:= pa.ar[i + 1]; + if p4.x = NTPX then + p4:= fp; + + // check if it intersects + t1:= (mp.x - pa.ar[i].x) * b - a * (mp.y - pa.ar[i].y); + t2:= (mp.x - p4.x) * b - a * (mp.y - p4.y); + + if (t1 > 0) <> (t2 > 0) then // yes it does, hard arith follows + begin + p:= p4.x - pa.ar[i].x; + q:= p4.y - pa.ar[i].y; + aqpb:= a * q - p * b; + + if (aqpb <> 0) then + begin + // (ix; iy) is intersection point + iy:= (((Int64(pa.ar[i].x) - mp.x) * b + Int64(mp.y) * a) * q - Int64(pa.ar[i].y) * p * b) div aqpb; + if abs(b) > abs(q) then + ix:= (iy - mp.y) * a div b + mp.x + else + ix:= (iy - pa.ar[i].y) * p div q + pa.ar[i].x; + + d:= DistanceI(mp.y - iy, mp.x - ix).Round; + t1:= b * (mp.y - iy) + a * (mp.x - ix); + if t1 > 0 then distL:= min(d, distL) else distR:= min(d, distR); + end; + end; + end; + + // go through all points, including fill points + for i:= 0 to Pred(LongInt(pa.Count + fillPointsCount)) do + // if this point isn't on current segment + if (si <> i) and (i <> si + 1) and (pa.ar[i].x <> NTPX) then + begin + // also check intersection with rays through pa.ar[i] if this point is good + t1:= (p1.x - pa.ar[i].x) * b - a * (p1.y - pa.ar[i].y); + t2:= (p2.x - pa.ar[i].x) * b - a * (p2.y - pa.ar[i].y); + if (t1 > 0) <> (t2 > 0) then + begin + // ray from p1 + p:= pa.ar[i].x - p1.x; + q:= pa.ar[i].y - p1.y; + aqpb:= a * q - p * b; + + if (aqpb <> 0) then + begin + // (ix; iy) is intersection point + iy:= (((Int64(p1.x) - mp.x) * b + Int64(mp.y) * a) * q - Int64(p1.y) * p * b) div aqpb; + if abs(b) > abs(q) then + ix:= (iy - mp.y) * a div b + mp.x + else + ix:= (iy - p1.y) * p div q + p1.x; + + d:= DistanceI(mp.y - iy, mp.x - ix).Round; + t1:= b * (mp.y - iy) + a * (mp.x - ix); + if t1 > 0 then distL:= min(d, distL) else distR:= min(d, distR); + end; + + // and ray from p2 + p:= pa.ar[i].x - p2.x; + q:= pa.ar[i].y - p2.y; + aqpb:= a * q - p * b; + + if (aqpb <> 0) then + begin + // (ix; iy) is intersection point + iy:= (((Int64(p2.x) - mp.x) * b + Int64(mp.y) * a) * q - Int64(p2.y) * p * b) div aqpb; + if abs(b) > abs(q) then + ix:= (iy - mp.y) * a div b + mp.x + else + ix:= (iy - p2.y) * p div q + p2.x; + + d:= DistanceI(mp.y - iy, mp.x - ix).Round; + t2:= b * (mp.y - iy) + a * (mp.x - ix); + if t2 > 0 then distL:= min(d, distL) else distR:= min(d, distR); + end; + end; + end; + + // don't move new point for more than length of initial segment + // adjust/parametrize for more flat surfaces (try values 3/4, 1/2 of dab, or even 1/4) + d:= dab * 100 div dabDiv; + //d:= dab * (1 + abs(cFeatureSize - 8)) div 6; + //d:= dab * (14 + cFeatureSize) div 20; + if distL > d then distL:= d; + if distR > d then distR:= d; + + if distR + distL < minDistance * 2 + 10 then + begin + // limits are too narrow, just divide + newPoint.x:= mp.x; + newPoint.y:= mp.y; + end + else + begin + // select distance within [-distL; distR] + d:= -distL + minDistance + LongInt(GetRandom(distR + distL - minDistance * 2)); + //d:= distR - minDistance; + //d:= - distL + minDistance; + + // calculate new point + newPoint.x:= mp.x + a * d div dab; + newPoint.y:= mp.y + b * d div dab; + end; +end; + +procedure DivideEdges(fillPointsCount: LongWord; var pa: TPixAr); +var i, t: LongInt; + newPoint: TPoint; +begin + newPoint.x:= 0; + newPoint.y:= 0; + i:= 0; + + while i < LongInt(pa.Count) - 1 do + begin + FindPoint(i, fillPointsCount, newPoint, pa); + + if (newPoint.x <> pa.ar[i].x) or (newPoint.y <> pa.ar[i].y) then + begin + // point found, free a slot for it in array, don't forget to move appended fill points + for t:= pa.Count + fillPointsCount downto i + 2 do + pa.ar[t]:= pa.ar[t - 1]; + inc(pa.Count); + pa.ar[i + 1]:= newPoint; + inc(i) + end; + inc(i) + end; +end; + +procedure Distort2(var Template: TEdgeTemplate; fps: PPointArray; var pa: TPixAr); +var i: Longword; +begin + // append fill points to ensure distortion won't move them to other side of segment + for i:= 0 to pred(Template.FillPointsCount) do + begin + pa.ar[pa.Count + i].x:= fps^[i].x; + pa.ar[pa.Count + i].y:= fps^[i].y; + end; + + // divide while it divides + repeat + i:= pa.Count; + DivideEdges(Template.FillPointsCount, pa) + until i = pa.Count; + +{$IFDEF IPHONEOS} + if GameType <> gmtLandPreview then +{$ENDIF} + // make it smooth + BezierizeEdge(pa, _0_2); +end; + + +procedure GenTemplated(var Template: TEdgeTemplate); +var pa: TPixAr; + i: Longword; + y, x: Longword; + fps: TPointArray; +begin + fps:=Template.FillPoints^; + ResizeLand(Template.TemplateWidth, Template.TemplateHeight); + for y:= 0 to LAND_HEIGHT - 1 do + for x:= 0 to LAND_WIDTH - 1 do + Land[y, x]:= lfBasic; + + minDistance:= sqr(cFeatureSize) div 8 + 10; + //dabDiv:= getRandom(41)+60; + //dabDiv:= getRandom(31)+70; + dabDiv:= getRandom(21)+100; + MaxHedgehogs:= Template.MaxHedgehogs; + hasGirders:= Template.hasGirders; + playHeight:= Template.TemplateHeight; + playWidth:= Template.TemplateWidth; + leftX:= (LAND_WIDTH - playWidth) div 2; + rightX:= Pred(leftX + playWidth); + topY:= LAND_HEIGHT - playHeight; + + {$HINTS OFF} + SetPoints(Template, pa, @fps); + {$HINTS ON} + + Distort2(Template, @fps, pa); + + DrawEdge(pa, 0); + + with Template do + for i:= 0 to pred(FillPointsCount) do + with fps[i] do + FillLand(x, y, 0, 0); + + DrawEdge(pa, lfBasic); + + // HACK: force to only cavern even if a cavern map is invertable if cTemplateFilter = 4 ? + if (cTemplateFilter = 4) + or (Template.canInvert and (getrandom(2) = 0)) + or (not Template.canInvert and Template.isNegative) then + begin + hasBorder:= true; + for y:= 0 to LAND_HEIGHT - 1 do + for x:= 0 to LAND_WIDTH - 1 do + if (y < topY) or (x < leftX) or (x > rightX) then + Land[y, x]:= 0 + else + begin + if Land[y, x] = 0 then + Land[y, x]:= lfBasic + else if Land[y, x] = lfBasic then + Land[y, x]:= 0; + end; + end; +end; + + +end. diff -r 31570b766315 -r ed5a6478e710 hedgewars/uLandGraphics.pas --- a/hedgewars/uLandGraphics.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uLandGraphics.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,14 +13,14 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} unit uLandGraphics; interface -uses uFloat, uConsts, uTypes; +uses uFloat, uConsts, uTypes, Math, uRenderUtils; type fillType = (nullPixel, backgroundPixel, ebcPixel, icePixel, setNotCurrentMask, changePixelSetNotCurrent, setCurrentHog, changePixelNotSetNotCurrent); @@ -39,19 +39,23 @@ function DrawExplosion(X, Y, Radius: LongInt): Longword; 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); -function FillRoundInLand(X, Y, Radius: LongInt; fill: fillType): LongWord; +function FillRoundInLand(X, Y, Radius: LongInt; Value: Longword): Longword; +function FillRoundInLandFT(X, Y, Radius: LongInt; fill: fillType): Longword; 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); +function DrawThickLine(X1, Y1, X2, Y2, radius: LongInt; color: Longword): Longword; procedure DumpLandToLog(x, y, r: LongInt); procedure DrawIceBreak(x, y, iceRadius, iceHeight: Longint); -function TryPlaceOnLand(cpX, cpY: LongInt; Obj: TSprite; Frame: LongInt; doPlace, indestructible: boolean): boolean; inline; -function TryPlaceOnLand(cpX, cpY: LongInt; Obj: TSprite; Frame: LongInt; doPlace, indestructible: boolean; LandFlags: Word): boolean; +function TryPlaceOnLandSimple(cpX, cpY: LongInt; Obj: TSprite; Frame: LongInt; doPlace, indestructible: boolean): boolean; inline; +function TryPlaceOnLand(cpX, cpY: LongInt; Obj: TSprite; Frame: LongInt; doPlace: boolean; LandFlags: Word): boolean; inline; +function ForcePlaceOnLand(cpX, cpY: LongInt; Obj: TSprite; Frame: LongInt; LandFlags: Word; Tint: LongWord; Behind, flipHoriz, flipVert: boolean): boolean; inline; +function TryPlaceOnLand(cpX, cpY: LongInt; Obj: TSprite; Frame: LongInt; doPlace, outOfMap, force, behind, flipHoriz, flipVert: boolean; LandFlags: Word; Tint: LongWord): boolean; +procedure EraseLand(cpX, cpY: LongInt; Obj: TSprite; Frame: LongInt; LandFlags: Word; eraseOnLFMatch, onlyEraseLF, flipHoriz, flipVert: boolean); +function GetPlaceCollisionTex(cpX, cpY: LongInt; Obj: TSprite; Frame: LongInt): PTexture; implementation -uses SDLh, uLandTexture, uVariables, uUtils, uDebug; +uses SDLh, uLandTexture, uTextures, uVariables, uUtils, uDebug, uScript; procedure calculatePixelsCoordinates(landX, landY: Longint; var pixelX, pixelY: Longint); inline; @@ -79,30 +83,31 @@ inc(drawPixelBG); end else if ((Land[landY, landX] and lfObject) <> 0) or (((LandPixels[pixelY, pixelX] and AMask) shr AShift) < 255) then - LandPixels[pixelY, pixelX]:= 0 + LandPixels[pixelY, pixelX]:= ExplosionBorderColorNoA end; end; procedure drawPixelEBC(landX, landY, pixelX, pixelY: Longint); inline; begin -if ((Land[landY, landX] and lfBasic) <> 0) or ((Land[landY, landX] and lfObject) <> 0) then +if (Land[landY, landX] and lfIndestructible = 0) and + (((Land[landY, landX] and lfBasic) <> 0) or ((Land[landY, landX] and lfObject) <> 0)) then begin LandPixels[pixelY, pixelX]:= ExplosionBorderColor; - Land[landY, landX]:= (Land[landY, landX] or lfDamaged) and not lfIce; + Land[landY, landX]:= (Land[landY, landX] or lfDamaged) and (not lfIce); LandDirty[landY div 32, landX div 32]:= 1; end; end; function isLandscapeEdge(weight:Longint):boolean; inline; begin -result := (weight < 8) and (weight >= 2); +isLandscapeEdge := (weight < 8) and (weight >= 2); end; function getPixelWeight(x, y:Longint): Longint; var - i, j:Longint; + i, j, r: Longint; begin -result := 0; +r := 0; for i := x - 1 to x + 1 do for j := y - 1 to y + 1 do begin @@ -110,13 +115,13 @@ (i > LAND_WIDTH - 1) or (j < 0) or (j > LAND_HEIGHT -1) then - begin - result := 9; - exit; - end; - if Land[j, i] and lfLandMask and not lfIce = 0 then - result := result + 1; + exit(9); + + if Land[j, i] and lfLandMask and (not lfIce) = 0 then + inc(r) end; + + getPixelWeight:= r end; @@ -144,11 +149,11 @@ end else begin - LandPixels[pixelY, pixelX]:= IceColor and not AMask or $E8 shl AShift; + LandPixels[pixelY, pixelX]:= IceColor and (not AMask) or $E8 shl AShift; LandPixels[pixelY, pixelX]:= addBgColor(LandPixels[pixelY, pixelX], icePixels^[iceSurface^.w * (pixelY mod iceSurface^.h) + (pixelX mod iceSurface^.w)]); // silly workaround to avoid having to make background erasure a tadb it smarter about sea ice if LandPixels[pixelY, pixelX] and AMask shr AShift = 255 then - LandPixels[pixelY, pixelX]:= LandPixels[pixelY, pixelX] and not AMask or 254 shl AShift; + LandPixels[pixelY, pixelX]:= LandPixels[pixelY, pixelX] and (not AMask) or 254 shl AShift; end; end; @@ -159,7 +164,7 @@ if isLandscapeEdge(getPixelWeight(landX, landY)) then begin if (LandPixels[pixelY, pixelX] and AMask < 255) and (LandPixels[pixelY, pixelX] and AMask > 0) then - LandPixels[pixelY, pixelX] := (IceEdgeColor and not AMask) or (LandPixels[pixelY, pixelX] and AMask) + LandPixels[pixelY, pixelX] := (IceEdgeColor and (not AMask)) or (LandPixels[pixelY, pixelX] and AMask) else if (LandPixels[pixelY, pixelX] and AMask < 255) or (Land[landY, landX] > 255) then LandPixels[pixelY, pixelX] := IceEdgeColor end @@ -167,91 +172,91 @@ begin fillPixelFromIceSprite(pixelX, pixelY); end; -if Land[landY, landX] > 255 then Land[landY, landX] := Land[landY, landX] or lfIce and not lfDamaged; +if Land[landY, landX] > 255 then Land[landY, landX] := Land[landY, landX] or lfIce and (not lfDamaged); end; -function FillLandCircleLine(y, fromPix, toPix: LongInt; fill : fillType): Longword; +function FillLandCircleLineFT(y, fromPix, toPix: LongInt; fill : fillType): Longword; var px, py, i: LongInt; begin //get rid of compiler warning px := 0; py := 0; - FillLandCircleLine := 0; + FillLandCircleLineFT := 0; case fill of backgroundPixel: - for i:= fromPix to toPix do - begin - calculatePixelsCoordinates(i, y, px, py); - inc(FillLandCircleLine, drawPixelBG(i, y, px, py)); - end; + for i:= fromPix to toPix do + begin + calculatePixelsCoordinates(i, y, px, py); + inc(FillLandCircleLineFT, drawPixelBG(i, y, px, py)); + end; ebcPixel: - for i:= fromPix to toPix do - begin - calculatePixelsCoordinates(i, y, px, py); - drawPixelEBC(i, y, px, py); - end; + for i:= fromPix to toPix do + begin + calculatePixelsCoordinates(i, y, px, py); + drawPixelEBC(i, y, px, py); + end; nullPixel: - for i:= fromPix to toPix do - begin - calculatePixelsCoordinates(i, y, px, py); - if ((Land[y, i] and lfIndestructible) = 0) and (not disableLandBack or (Land[y, i] > 255)) then - LandPixels[py, px]:= 0 - end; + for i:= fromPix to toPix do + begin + calculatePixelsCoordinates(i, y, px, py); + if ((Land[y, i] and lfIndestructible) = 0) and (not disableLandBack or (Land[y, i] > 255)) then + LandPixels[py, px]:= ExplosionBorderColorNoA; + end; icePixel: - for i:= fromPix to toPix do - begin - calculatePixelsCoordinates(i, y, px, py); - DrawPixelIce(i, y, px, py); - end; + for i:= fromPix to toPix do + begin + calculatePixelsCoordinates(i, y, px, py); + DrawPixelIce(i, y, px, py); + end; setNotCurrentMask: - for i:= fromPix to toPix do - begin - Land[y, i]:= Land[y, i] and lfNotCurrentMask; - end; + for i:= fromPix to toPix do + begin + Land[y, i]:= Land[y, i] and lfNotCurrentMask; + end; changePixelSetNotCurrent: - for i:= fromPix to toPix do - begin - if Land[y, i] and lfObjMask > 0 then - Land[y, i]:= (Land[y, i] and lfNotObjMask) or ((Land[y, i] and lfObjMask) - 1); - end; + for i:= fromPix to toPix do + begin + if Land[y, i] and lfObjMask > 0 then + Land[y, i]:= Land[y, i] - 1; + end; setCurrentHog: - for i:= fromPix to toPix do - begin - Land[y, i]:= Land[y, i] or lfCurrentHog - end; + for i:= fromPix to toPix do + begin + Land[y, i]:= Land[y, i] or lfCurrentHog + end; changePixelNotSetNotCurrent: - for i:= fromPix to toPix do - begin - if Land[y, i] and lfObjMask < lfObjMask then - Land[y, i]:= (Land[y, i] and lfNotObjMask) or ((Land[y, i] and lfObjMask) + 1) - end; + for i:= fromPix to toPix do + begin + if Land[y, i] and lfObjMask < lfObjMask then + Land[y, i]:= Land[y, i] + 1 + end; end; end; -function FillLandCircleSegment(x, y, dx, dy: LongInt; fill : fillType): Longword; inline; +function FillLandCircleSegmentFT(x, y, dx, dy: LongInt; fill : fillType): Longword; inline; begin - FillLandCircleSegment := 0; + FillLandCircleSegmentFT := 0; if ((y + dy) and LAND_HEIGHT_MASK) = 0 then - inc(FillLandCircleSegment, FillLandCircleLine(y + dy, Max(x - dx, 0), Min(x + dx, LAND_WIDTH - 1), fill)); + inc(FillLandCircleSegmentFT, FillLandCircleLineFT(y + dy, Max(x - dx, 0), Min(x + dx, LAND_WIDTH - 1), fill)); if ((y - dy) and LAND_HEIGHT_MASK) = 0 then - inc(FillLandCircleSegment, FillLandCircleLine(y - dy, Max(x - dx, 0), Min(x + dx, LAND_WIDTH - 1), fill)); + inc(FillLandCircleSegmentFT, FillLandCircleLineFT(y - dy, Max(x - dx, 0), Min(x + dx, LAND_WIDTH - 1), fill)); if ((y + dx) and LAND_HEIGHT_MASK) = 0 then - inc(FillLandCircleSegment, FillLandCircleLine(y + dx, Max(x - dy, 0), Min(x + dy, LAND_WIDTH - 1), fill)); + inc(FillLandCircleSegmentFT, FillLandCircleLineFT(y + dx, Max(x - dy, 0), Min(x + dy, LAND_WIDTH - 1), fill)); if ((y - dx) and LAND_HEIGHT_MASK) = 0 then - inc(FillLandCircleSegment, FillLandCircleLine(y - dx, Max(x - dy, 0), Min(x + dy, LAND_WIDTH - 1), fill)); + inc(FillLandCircleSegmentFT, FillLandCircleLineFT(y - dx, Max(x - dy, 0), Min(x + dy, LAND_WIDTH - 1), fill)); end; -function FillRoundInLand(X, Y, Radius: LongInt; fill: fillType): Longword; inline; +function FillRoundInLandFT(X, Y, Radius: LongInt; fill: fillType): Longword; inline; var dx, dy, d: LongInt; begin dx:= 0; dy:= Radius; d:= 3 - 2 * Radius; -FillRoundInLand := 0; +FillRoundInLandFT := 0; while (dx < dy) do begin - inc(FillRoundInLand, FillLandCircleSegment(x, y, dx, dy, fill)); + inc(FillRoundInLandFT, FillLandCircleSegmentFT(x, y, dx, dy, fill)); if (d < 0) then d:= d + 4 * dx + 6 else @@ -262,7 +267,7 @@ inc(dx) end; if (dx = dy) then - inc (FillRoundInLand, FillLandCircleSegment(x, y, dx, dy, fill)); + inc (FillRoundInLandFT, FillLandCircleSegmentFT(x, y, dx, dy, fill)); end; @@ -297,36 +302,51 @@ addBgColor := (nAlpha shl AShift) or (nRed shl RShift) or (nGreen shl GShift) or (nBlue shl BShift); end; -procedure FillCircleLines(x, y, dx, dy: LongInt; Value: Longword); +function FillCircleLines(x, y, dx, dy: LongInt; Value: Longword): Longword; var i: LongInt; 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] and lfIndestructible) = 0 then - Land[y + dy, i]:= Value; -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] and lfIndestructible) = 0 then - Land[y - dy, i]:= Value; -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] and lfIndestructible) = 0 then - Land[y + dx, i]:= Value; -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] and lfIndestructible) = 0 then - Land[y - dx, i]:= Value; + FillCircleLines:= 0; + + 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] and lfIndestructible) = 0 then + begin + if Land[y + dy, i] <> Value then inc(FillCircleLines); + Land[y + dy, i]:= Value; + end; + 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] and lfIndestructible) = 0 then + begin + if Land[y - dy, i] <> Value then inc(FillCircleLines); + Land[y - dy, i]:= Value; + end; + 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] and lfIndestructible) = 0 then + begin + if Land[y + dx, i] <> Value then inc(FillCircleLines); + Land[y + dx, i]:= Value; + end; + 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] and lfIndestructible) = 0 then + begin + if Land[y - dx, i] <> Value then inc(FillCircleLines); + Land[y - dx, i]:= Value; + end; end; -procedure FillRoundInLand(X, Y, Radius: LongInt; Value: Longword); +function FillRoundInLand(X, Y, Radius: LongInt; Value: Longword): Longword; var dx, dy, d: LongInt; begin +FillRoundInLand:= 0; dx:= 0; dy:= Radius; d:= 3 - 2 * Radius; while (dx < dy) do begin - FillCircleLines(x, y, dx, dy, Value); + inc(FillRoundInLand, FillCircleLines(x, y, dx, dy, Value)); if (d < 0) then d:= d + 4 * dx + 6 else @@ -337,41 +357,82 @@ inc(dx) end; if (dx = dy) then - FillCircleLines(x, y, dx, dy, Value); + inc(FillRoundInLand, FillCircleLines(x, y, dx, dy, Value)); end; procedure ChangeRoundInLand(X, Y, Radius: LongInt; doSet, isCurrent: boolean); begin if not doSet and isCurrent then - FillRoundInLand(X, Y, Radius, setNotCurrentMask) -else if not doSet and not IsCurrent then - FillRoundInLand(X, Y, Radius, changePixelSetNotCurrent) + FillRoundInLandFT(X, Y, Radius, setNotCurrentMask) +else if not doSet and (not IsCurrent) then + FillRoundInLandFT(X, Y, Radius, changePixelSetNotCurrent) else if doSet and IsCurrent then - FillRoundInLand(X, Y, Radius, setCurrentHog) -else if doSet and not IsCurrent then - FillRoundInLand(X, Y, Radius, changePixelNotSetNotCurrent); + FillRoundInLandFT(X, Y, Radius, setCurrentHog) +else if doSet and (not IsCurrent) then + FillRoundInLandFT(X, Y, Radius, changePixelNotSetNotCurrent); end; procedure DrawIceBreak(x, y, iceRadius, iceHeight: Longint); var - i, j: integer; + i, j, iceL, iceR, IceT, iceB: LongInt; landRect: TSDL_Rect; begin -for i := min(max(x - iceRadius, 0), LAND_WIDTH - 1) to min(max(x + iceRadius, 0), LAND_WIDTH - 1) do +// figure out bottom/left/right/top coords of ice to draw + +// determine absolute limits first +iceT:= 0; +iceB:= min(cWaterLine, LAND_HEIGHT - 1); + +iceL:= 0; +iceR:= LAND_WIDTH - 1; + +if WorldEdge <> weNone then + begin + iceL:= max(leftX, iceL); + iceR:= min(rightX, iceR); + end; + +// adjust based on location but without violating absolute limits +if y >= cWaterLine then begin - for j := min(max(y, 0), LAND_HEIGHT - 1) to min(max(y + iceHeight, 0), LAND_HEIGHT - 1) do + iceL:= max(x - iceRadius, iceL); + iceR:= min(x + iceRadius, iceR); + iceT:= max(cWaterLine - iceHeight, iceT); + end +else {if WorldEdge = weSea then} + begin + iceT:= max(y - iceRadius, iceT); + iceB:= min(y + iceRadius, iceB); + if x <= leftX then + iceR:= min(leftX + iceHeight, iceR) + else {if x >= rightX then} + iceL:= max(LongInt(rightX) - iceHeight, iceL); + end; + +// don't continue if all ice is outside land array +if (iceL > iceR) or (iceT > iceB) then + exit(); + +for i := iceL to iceR do + begin + for j := iceT to iceB do begin if Land[j, i] = 0 then begin Land[j, i] := lfIce; - fillPixelFromIceSprite(i, j); + if (cReducedQuality and rqBlurryLand) = 0 then + fillPixelFromIceSprite(i, j) + else + fillPixelFromIceSprite(i div 2, j div 2); end; end; end; -landRect.x := min(max(x - iceRadius, 0), LAND_WIDTH - 1); -landRect.y := min(max(y, 0), LAND_HEIGHT - 1); -landRect.w := min(2*iceRadius, LAND_WIDTH - landRect.x - 1); -landRect.h := min(iceHeight, LAND_HEIGHT - landRect.y - 1); + +landRect.x := iceL; +landRect.y := iceT; +landRect.w := iceR - IceL + 1; +landRect.h := iceB - iceT + 1; + UpdateLandTexture(landRect.x, landRect.w, landRect.y, landRect.h, true); end; @@ -379,11 +440,11 @@ var tx, ty, dx, dy: Longint; begin - DrawExplosion := FillRoundInLand(x, y, Radius, backgroundPixel); + DrawExplosion := FillRoundInLandFT(x, y, Radius, backgroundPixel); if Radius > 20 then - FillRoundInLand(x, y, Radius - 15, nullPixel); + FillRoundInLandFT(x, y, Radius - 15, nullPixel); FillRoundInLand(X, Y, Radius, 0); - FillRoundInLand(x, y, Radius + 4, ebcPixel); + FillRoundInLandFT(x, y, Radius + 4, ebcPixel); tx:= Max(X - Radius - 5, 0); dx:= Min(X + Radius + 5, LAND_WIDTH) - tx; ty:= Max(Y - Radius - 5, 0); @@ -412,7 +473,7 @@ if ((Land[ty, tx] and lfBasic) <> 0) and (((LandPixels[by,bx] and AMask) shr AShift) = 255) and (not disableLandBack) then LandPixels[by, bx]:= LandBackPixel(tx, ty) else if ((Land[ty, tx] and lfObject) <> 0) or (((LandPixels[by,bx] and AMask) shr AShift) < 255) then - LandPixels[by, bx]:= 0 + LandPixels[by, bx]:= LandPixels[by, bx] and (not AMASK) end end; inc(y, dY) @@ -432,7 +493,7 @@ else LandPixels[ty div 2, tx div 2]:= ExplosionBorderColor; - Land[ty, tx]:= (Land[ty, tx] or lfDamaged) and not lfIce; + Land[ty, tx]:= (Land[ty, tx] or lfDamaged) and (not lfIce); LandDirty[ty div 32, tx div 32]:= 1; end; inc(y, dY) @@ -457,7 +518,7 @@ if ((ty and LAND_HEIGHT_MASK) = 0) and ((tx and LAND_WIDTH_MASK) = 0) and (((Land[ty, tx] and lfBasic) <> 0) or ((Land[ty, tx] and lfObject) <> 0)) then begin - Land[ty, tx]:= (Land[ty, tx] or lfDamaged) and not lfIce; + Land[ty, tx]:= (Land[ty, tx] or lfDamaged) and (not lfIce); if despeckle then LandDirty[ty div 32, tx div 32]:= 1; if (cReducedQuality and rqBlurryLand) = 0 then @@ -468,15 +529,18 @@ end; end; +type TWrapNeeded = (wnNone, wnLeft, wnRight); // // - (dX, dY) - direction, vector of length = 0.5 // -procedure DrawTunnel(X, Y, dX, dY: hwFloat; ticks, HalfWidth: LongInt); +function DrawTunnel_real(X, Y, dX, dY: hwFloat; ticks, HalfWidth: LongInt): TWrapNeeded; var nx, ny, dX8, dY8: hwFloat; i, t, tx, ty, by, bx, stX, stY, ddy, ddx: Longint; despeckle : Boolean; begin // (-dY, dX) is (dX, dY) rotated by PI/2 +DrawTunnel_real:= wnNone; + stY:= hwRound(Y); stX:= hwRound(X); @@ -501,7 +565,7 @@ and ((tx and LAND_WIDTH_MASK) = 0) and (((Land[ty, tx] and lfBasic) <> 0) or ((Land[ty, tx] and lfObject) <> 0)) then begin - Land[ty, tx]:= Land[ty, tx] and not lfIce; + Land[ty, tx]:= Land[ty, tx] and (not lfIce); if despeckle then begin Land[ty, tx]:= Land[ty, tx] or lfDamaged; @@ -543,7 +607,7 @@ if ((Land[ty, tx] and lfBasic) <> 0) and (((LandPixels[by,bx] and AMask) shr AShift) = 255) and (not disableLandBack) then LandPixels[by, bx]:= LandBackPixel(tx, ty) else if ((Land[ty, tx] and lfObject) <> 0) or (((LandPixels[by,bx] and AMask) shr AShift) < 255) then - LandPixels[by, bx]:= 0; + LandPixels[by, bx]:= LandPixels[by, bx] and (not AMASK); Land[ty, tx]:= 0; end end; @@ -565,7 +629,7 @@ if ((ty and LAND_HEIGHT_MASK) = 0) and ((tx and LAND_WIDTH_MASK) = 0) and (((Land[ty, tx] and lfBasic) <> 0) or ((Land[ty, tx] and lfObject) <> 0)) then begin - Land[ty, tx]:= (Land[ty, tx] or lfDamaged) and not lfIce; + Land[ty, tx]:= (Land[ty, tx] or lfDamaged) and (not lfIce); if despeckle then LandDirty[ty div 32, tx div 32]:= 1; if (cReducedQuality and rqBlurryLand) = 0 then @@ -578,25 +642,272 @@ ny:= ny + dX; end; -tx:= Max(stX - HalfWidth * 2 - 4 - abs(hwRound(dX * ticks)), 0); +tx:= stX - HalfWidth * 2 - 4 - abs(hwRound(dX * ticks)); +ddx:= stX + HalfWidth * 2 + 4 + abs(hwRound(dX * ticks)); + +if WorldEdge = weWrap then + begin + if (tx < leftX) or (ddx < leftX) then + DrawTunnel_real:= wnLeft + else if (tx > rightX) or (ddx > rightX) then + DrawTunnel_real:= wnRight; + end; + +tx:= Max(tx, 0); ty:= Max(stY - HalfWidth * 2 - 4 - abs(hwRound(dY * ticks)), 0); -ddx:= Min(stX + HalfWidth * 2 + 4 + abs(hwRound(dX * ticks)), LAND_WIDTH) - tx; +ddx:= Min(ddx, LAND_WIDTH) - tx; ddy:= Min(stY + HalfWidth * 2 + 4 + abs(hwRound(dY * ticks)), LAND_HEIGHT) - ty; UpdateLandTexture(tx, ddx, ty, ddy, false) end; -function TryPlaceOnLand(cpX, cpY: LongInt; Obj: TSprite; Frame: LongInt; doPlace, indestructible: boolean): boolean; inline; +procedure DrawTunnel(X, Y, dX, dY: hwFloat; ticks, HalfWidth: LongInt); +var wn: TWrapNeeded; +begin +wn:= DrawTunnel_real(X, Y, dX, dY, ticks, HalfWidth); +if wn <> wnNone then + begin + if wn = wnLeft then + DrawTunnel_real(X + int2hwFloat(playWidth), Y, dX, dY, ticks, HalfWidth) + else + DrawTunnel_real(X - int2hwFloat(playWidth), Y, dX, dY, ticks, HalfWidth); + end; +end; + +function TryPlaceOnLandSimple(cpX, cpY: LongInt; Obj: TSprite; Frame: LongInt; doPlace, indestructible: boolean): boolean; inline; +var lf: Word; begin -TryPlaceOnLand:= TryPlaceOnLand(cpX, cpY, Obj, Frame, doPlace, indestructible, 0); +if indestructible then + lf:= lfIndestructible +else + lf:= 0; +TryPlaceOnLandSimple:= TryPlaceOnLand(cpX, cpY, Obj, Frame, doPlace, false, false, false, false, false, lf, $FFFFFFFF); +end; + +function TryPlaceOnLand(cpX, cpY: LongInt; Obj: TSprite; Frame: LongInt; doPlace: boolean; LandFlags: Word): boolean; inline; +begin +TryPlaceOnLand:= TryPlaceOnLand(cpX, cpY, Obj, Frame, doPlace, false, false, false, false, false, LandFlags, $FFFFFFFF); +end; + +function ForcePlaceOnLand(cpX, cpY: LongInt; Obj: TSprite; Frame: LongInt; LandFlags: Word; Tint: LongWord; Behind, flipHoriz, flipVert: boolean): boolean; inline; +begin + ForcePlaceOnLand:= TryPlaceOnLand(cpX, cpY, Obj, Frame, true, false, true, behind, flipHoriz, flipVert, LandFlags, Tint) end; -function TryPlaceOnLand(cpX, cpY: LongInt; Obj: TSprite; Frame: LongInt; doPlace, indestructible: boolean; LandFlags: Word): boolean; +function TryPlaceOnLand(cpX, cpY: LongInt; Obj: TSprite; Frame: LongInt; doPlace, outOfMap, force, behind, flipHoriz, flipVert: boolean; LandFlags: Word; Tint: LongWord): boolean; +var X, Y, bpp, h, w, row, col, gx, gy, numFramesFirstCol: LongInt; + p: PByteArray; + Image: PSDL_Surface; + pixel: LongWord; +begin +TryPlaceOnLand:= false; +numFramesFirstCol:= SpritesData[Obj].imageHeight div SpritesData[Obj].Height; + +if outOfMap then doPlace:= false; // just using for a check + +TryDo(SpritesData[Obj].Surface <> nil, 'Assert SpritesData[Obj].Surface failed', true); + +Image:= SpritesData[Obj].Surface; +w:= SpritesData[Obj].Width; +h:= SpritesData[Obj].Height; +if flipVert then flipSurface(Image, true); +if flipHoriz then flipSurface(Image, false); +row:= Frame mod numFramesFirstCol; +col:= Frame div numFramesFirstCol; + +if SDL_MustLock(Image) then + SDLTry(SDL_LockSurface(Image) >= 0, 'TryPlaceOnLand', true); + +bpp:= Image^.format^.BytesPerPixel; +TryDo(bpp = 4, 'It should be 32 bpp sprite', true); +// Check that sprite fits free space +p:= PByteArray(@(PByteArray(Image^.pixels)^[ Image^.pitch * row * h + col * w * 4 ])); +case bpp of + 4: for y:= 0 to Pred(h) do + begin + for x:= 0 to Pred(w) do + if ((PLongword(@(p^[x * 4]))^) and AMask) <> 0 then + if (outOfMap and + ((cpY + y) < LAND_HEIGHT) and ((cpY + y) >= 0) and + ((cpX + x) < LAND_WIDTH) and ((cpX + x) >= 0) and + ((not force) and (Land[cpY + y, cpX + x] <> 0))) or + + (not outOfMap and + (((cpY + y) <= Longint(topY)) or ((cpY + y) >= LAND_HEIGHT) or + ((cpX + x) <= Longint(leftX)) or ((cpX + x) >= Longint(rightX)) or + ((not force) and (Land[cpY + y, cpX + x] <> 0)))) then + begin + if SDL_MustLock(Image) then + SDL_UnlockSurface(Image); + exit + end; + p:= PByteArray(@(p^[Image^.pitch])) + end + end; + +TryPlaceOnLand:= true; +if not doPlace then + begin + if SDL_MustLock(Image) then + SDL_UnlockSurface(Image); + exit + end; + +// Checked, now place +p:= PByteArray(@(PByteArray(Image^.pixels)^[ Image^.pitch * row * h + col * w * 4 ])); +case bpp of + 4: for y:= 0 to Pred(h) do + begin + for x:= 0 to Pred(w) do + if ((PLongword(@(p^[x * 4]))^) and AMask) <> 0 then + begin + if (cReducedQuality and rqBlurryLand) = 0 then + begin + gX:= cpX + x; + gY:= cpY + y; + end + else + begin + gX:= (cpX + x) div 2; + gY:= (cpY + y) div 2; + end; + if not behind or (Land[cpY + y, cpX + x] and lfLandMask = 0) then + begin + if (LandFlags and lfBasic <> 0) or + (((LandPixels[gY, gX] and AMask) shr AShift = 255) and // This test assumes lfBasic and lfObject differ only graphically + (LandFlags or lfObject = 0)) then + Land[cpY + y, cpX + x]:= lfBasic or LandFlags + else Land[cpY + y, cpX + x]:= lfObject or LandFlags + end; + if not behind or (LandPixels[gY, gX] = 0) then + begin + if tint = $FFFFFFFF then + LandPixels[gY, gX]:= PLongword(@(p^[x * 4]))^ + else + begin + pixel:= PLongword(@(p^[x * 4]))^; + LandPixels[gY, gX]:= + ceil((pixel shr RShift and $FF) * ((tint shr 24) / 255)) shl RShift or + ceil((pixel shr GShift and $FF) * ((tint shr 16 and $ff) / 255)) shl GShift or + ceil((pixel shr BShift and $FF) * ((tint shr 8 and $ff) / 255)) shl BShift or + ceil((pixel shr AShift and $FF) * ((tint and $ff) / 255)) shl AShift; + end + end + end; + p:= PByteArray(@(p^[Image^.pitch])); + end; + end; +if SDL_MustLock(Image) then + SDL_UnlockSurface(Image); + +if flipVert then flipSurface(Image, true); +if flipHoriz then flipSurface(Image, false); + +x:= Max(cpX, leftX); +w:= Min(cpX + Image^.w, LAND_WIDTH) - x; +y:= Max(cpY, topY); +h:= Min(cpY + Image^.h, LAND_HEIGHT) - y; +UpdateLandTexture(x, w, y, h, true); + +ScriptCall('onSpritePlacement', ord(Obj), cpX + w div 2, cpY + h div 2); +if Obj = sprAmGirder then + ScriptCall('onGirderPlacement', frame, cpX + w div 2, cpY + h div 2) +else if Obj = sprAmRubber then + ScriptCall('onRubberPlacement', frame, cpX + w div 2, cpY + h div 2); + +end; + +procedure EraseLand(cpX, cpY: LongInt; Obj: TSprite; Frame: LongInt; LandFlags: Word; eraseOnLFMatch, onlyEraseLF, flipHoriz, flipVert: boolean); var X, Y, bpp, h, w, row, col, gx, gy, numFramesFirstCol: LongInt; p: PByteArray; Image: PSDL_Surface; begin -TryPlaceOnLand:= false; +numFramesFirstCol:= SpritesData[Obj].imageHeight div SpritesData[Obj].Height; + +TryDo(SpritesData[Obj].Surface <> nil, 'Assert SpritesData[Obj].Surface failed', true); + +Image:= SpritesData[Obj].Surface; +w:= SpritesData[Obj].Width; +h:= SpritesData[Obj].Height; +if flipVert then flipSurface(Image, true); +if flipHoriz then flipSurface(Image, false); +row:= Frame mod numFramesFirstCol; +col:= Frame div numFramesFirstCol; + +if SDL_MustLock(Image) then + SDLTry(SDL_LockSurface(Image) >= 0, 'EraseLand', true); + +bpp:= Image^.format^.BytesPerPixel; +TryDo(bpp = 4, 'It should be 32 bpp sprite', true); +// Check that sprite fits free space +p:= PByteArray(@(PByteArray(Image^.pixels)^[ Image^.pitch * row * h + col * w * 4 ])); +case bpp of + 4: for y:= 0 to Pred(h) do + begin + for x:= 0 to Pred(w) do + if ((PLongword(@(p^[x * 4]))^) and AMask) <> 0 then + if ((cpY + y) <= Longint(topY)) or ((cpY + y) >= LAND_HEIGHT) or + ((cpX + x) <= Longint(leftX)) or ((cpX + x) >= Longint(rightX)) then + begin + if SDL_MustLock(Image) then + SDL_UnlockSurface(Image); + exit + end; + p:= PByteArray(@(p^[Image^.pitch])) + end + end; + +// Checked, now place +p:= PByteArray(@(PByteArray(Image^.pixels)^[ Image^.pitch * row * h + col * w * 4 ])); +case bpp of + 4: for y:= 0 to Pred(h) do + begin + for x:= 0 to Pred(w) do + if ((PLongword(@(p^[x * 4]))^) and AMask) <> 0 then + begin + if (cReducedQuality and rqBlurryLand) = 0 then + begin + gX:= cpX + x; + gY:= cpY + y; + end + else + begin + gX:= (cpX + x) div 2; + gY:= (cpY + y) div 2; + end; + if (not eraseOnLFMatch or (Land[cpY + y, cpX + x] and LandFlags <> 0)) and + ((PLongword(@(p^[x * 4]))^) and AMask <> 0) then + begin + if not onlyEraseLF then + begin + LandPixels[gY, gX]:= 0; + Land[cpY + y, cpX + x]:= 0 + end + else Land[cpY + y, cpX + x]:= Land[cpY + y, cpX + x] and (not LandFlags) + end + end; + p:= PByteArray(@(p^[Image^.pitch])); + end; + end; +if SDL_MustLock(Image) then + SDL_UnlockSurface(Image); + +if flipVert then flipSurface(Image, true); +if flipHoriz then flipSurface(Image, false); + +x:= Max(cpX, leftX); +w:= Min(cpX + Image^.w, LAND_WIDTH) - x; +y:= Max(cpY, topY); +h:= Min(cpY + Image^.h, LAND_HEIGHT) - y; +UpdateLandTexture(x, w, y, h, true) +end; + +function GetPlaceCollisionTex(cpX, cpY: LongInt; Obj: TSprite; Frame: LongInt): PTexture; +var X, Y, bpp, h, w, row, col, numFramesFirstCol: LongInt; + p, pt: PLongWordArray; + Image, finalSurface: PSDL_Surface; +begin +GetPlaceCollisionTex:= nil; numFramesFirstCol:= SpritesData[Obj].imageHeight div SpritesData[Obj].Height; TryDo(SpritesData[Obj].Surface <> nil, 'Assert SpritesData[Obj].Surface failed', true); @@ -611,74 +922,48 @@ bpp:= Image^.format^.BytesPerPixel; TryDo(bpp = 4, 'It should be 32 bpp sprite', true); -// Check that sprite fits free space -p:= @(PByteArray(Image^.pixels)^[ Image^.pitch * row * h + col * w * 4 ]); -case bpp of - 4: for y:= 0 to Pred(h) do - begin - for x:= 0 to Pred(w) do - if (PLongword(@(p^[x * 4]))^) <> 0 then - if ((cpY + y) <= Longint(topY)) or ((cpY + y) >= LAND_HEIGHT) or - ((cpX + x) <= Longint(leftX)) or ((cpX + x) >= Longint(rightX)) or (Land[cpY + y, cpX + x] <> 0) then - begin - if SDL_MustLock(Image) then - SDL_UnlockSurface(Image); - exit; - end; - p:= @(p^[Image^.pitch]); - end; - end; + + + +finalSurface:= SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32, RMask, GMask, BMask, AMask); + +TryDo(finalSurface <> nil, 'GetPlaceCollisionTex: fail to create surface', true); + +if SDL_MustLock(finalSurface) then + SDLTry(SDL_LockSurface(finalSurface) >= 0, 'GetPlaceCollisionTex', true); -TryPlaceOnLand:= true; -if not doPlace then +p:= PLongWordArray(@(PLongWordArray(Image^.pixels)^[ (Image^.pitch div 4) * row * h + col * w ])); +pt:= PLongWordArray(finalSurface^.pixels); + +for y:= 0 to Pred(h) do begin - if SDL_MustLock(Image) then - SDL_UnlockSurface(Image); - exit + for x:= 0 to Pred(w) do + if ((p^[x] and AMask) <> 0) + and (((cpY + y) < Longint(topY)) or ((cpY + y) >= LAND_HEIGHT) or + ((cpX + x) < Longint(leftX)) or ((cpX + x) > Longint(rightX)) or (Land[cpY + y, cpX + x] <> 0)) then + pt^[x]:= cWhiteColor + else + (pt^[x]):= cWhiteColor and (not AMask); + p:= PLongWordArray(@(p^[Image^.pitch div 4])); + pt:= PLongWordArray(@(pt^[finalSurface^.pitch div 4])); end; -// Checked, now place -p:= @(PByteArray(Image^.pixels)^[ Image^.pitch * row * h + col * w * 4 ]); -case bpp of - 4: for y:= 0 to Pred(h) do - begin - for x:= 0 to Pred(w) do - if (PLongword(@(p^[x * 4]))^) <> 0 then - begin - if (cReducedQuality and rqBlurryLand) = 0 then - begin - gX:= cpX + x; - gY:= cpY + y; - end - else - begin - gX:= (cpX + x) div 2; - gY:= (cpY + y) div 2; - end; - if indestructible then - Land[cpY + y, cpX + x]:= lfIndestructible or LandFlags - else if (LandPixels[gY, gX] and AMask) shr AShift = 255 then // This test assumes lfBasic and lfObject differ only graphically - Land[cpY + y, cpX + x]:= lfBasic or LandFlags - else - Land[cpY + y, cpX + x]:= lfObject or LandFlags; - LandPixels[gY, gX]:= PLongword(@(p^[x * 4]))^ - end; - p:= @(p^[Image^.pitch]); - end; - end; if SDL_MustLock(Image) then SDL_UnlockSurface(Image); -x:= Max(cpX, leftX); -w:= Min(cpX + Image^.w, LAND_WIDTH) - x; -y:= Max(cpY, topY); -h:= Min(cpY + Image^.h, LAND_HEIGHT) - y; -UpdateLandTexture(x, w, y, h, true) +if SDL_MustLock(finalSurface) then + SDL_UnlockSurface(finalSurface); + +GetPlaceCollisionTex:= Surface2Tex(finalSurface, true); + +SDL_FreeSurface(finalSurface); end; + function Despeckle(X, Y: LongInt): boolean; var nx, ny, i, j, c, xx, yy: LongInt; pixelsweep: boolean; + begin Despeckle:= true; @@ -693,7 +978,7 @@ yy:= Y div 2; end; - pixelsweep:= (Land[Y, X] <= lfAllObjMask) and (LandPixels[yy, xx] <> 0); + pixelsweep:= (Land[Y, X] <= lfAllObjMask) and ((LandPixels[yy, xx] and AMASK) <> 0); if (((Land[Y, X] and lfDamaged) <> 0) and ((Land[Y, X] and lfIndestructible) = 0)) or pixelsweep then begin c:= 0; @@ -709,11 +994,14 @@ begin if ((cReducedQuality and rqBlurryLand) <> 0) then begin - nx:= nx div 2; - ny:= ny div 2 - end; - if LandPixels[ny, nx] <> 0 then - inc(c); + ny:= Y div 2 + i; + nx:= X div 2 + j; + if ((ny and (LAND_HEIGHT_MASK div 2)) = 0) and ((nx and (LAND_WIDTH_MASK div 2)) = 0) then + if (LandPixels[ny, nx] and AMASK) <> 0 then + inc(c); + end + else if (LandPixels[ny, nx] and AMASK) <> 0 then + inc(c); end else if Land[ny, nx] > 255 then inc(c); @@ -725,7 +1013,7 @@ if ((Land[Y, X] and lfBasic) <> 0) and (not disableLandBack) then LandPixels[yy, xx]:= LandBackPixel(X, Y) else - LandPixels[yy, xx]:= 0; + LandPixels[yy, xx]:= LandPixels[yy, xx] and (not AMASK); if not pixelsweep then begin @@ -737,7 +1025,68 @@ Despeckle:= false end; +// a bit of AA for explosions procedure Smooth(X, Y: LongInt); +var c, r, g, b, a, i: integer; + nx, ny: LongInt; + pixel: LongWord; +begin + +// only AA inwards +if (Land[Y, X] and lfDamaged) = 0 then + exit; + +// check location +if (Y <= LongInt(topY) + 1) or (Y >= LAND_HEIGHT-2) +or (X <= LongInt(leftX) + 1) or (X >= LongInt(rightX) - 1) then + exit; + +// counter for neighbor pixels that are not known to be undamaged +c:= 8; + +// accumalating rgba value of relevant pixels here +r:= 0; +g:= 0; +b:= 0; +a:= 0; + +// iterate over all neighbor pixels (also itself, will be skipped anyway) +for nx:= X-1 to X+1 do + for ny:= Y-1 to Y+1 do + // only consider undamaged neighbors (also leads to skipping itself) + if (Land[ny, nx] and lfDamaged) = 0 then + begin + pixel:= LandPixels[ny, nx]; + inc(r, (pixel and RMask) shr RShift); + inc(g, (pixel and GMask) shr GShift); + inc(b, (pixel and BMask) shr BShift); + inc(a, (pixel and AMask) shr AShift); + dec(c); + end; + +// nothing do to if all neighbors damaged +if c < 1 then + exit; + +// use explosion color for damaged pixels +for i:= 1 to c do + begin + inc(r, ExplosionBorderColorR); + inc(g, ExplosionBorderColorG); + inc(b, ExplosionBorderColorB); + inc(a, 255); + end; + +// set resulting color value based on average of all neighbors +r:= r div 8; +g:= g div 8; +b:= b div 8; +a:= a div 8; +LandPixels[y,x]:= (r shl RShift) or (g shl GShift) or (b shl BShift) or (a shl AShift); + +end; + +procedure Smooth_oldImpl(X, Y: LongInt); begin // a bit of AA for explosions if (Land[Y, X] = 0) and (Y > LongInt(topY) + 1) and @@ -756,12 +1105,14 @@ (((((LandPixels[y,x] and GMask shr GShift) div 2)+((ExplosionBorderColor and GMask) shr GShift) div 2) and $FF) shl GShift) or (((((LandPixels[y,x] and BMask shr BShift) div 2)+((ExplosionBorderColor and BMask) shr BShift) div 2) and $FF) shl BShift) or ($FF shl AShift) end; +{ if (Land[y, x-1] = lfObject) then Land[y,x]:= lfObject else if (Land[y, x+1] = lfObject) then Land[y,x]:= lfObject else Land[y,x]:= lfBasic; +} end else if ((((Land[y, x-1] and lfDamaged) <> 0) and ((Land[y+1,x-1] and lfDamaged) <> 0) and ((Land[y+2,x] and lfDamaged) <> 0)) or (((Land[y, x-1] and lfDamaged) <> 0) and ((Land[y-1,x-1] and lfDamaged) <> 0) and ((Land[y-2,x] and lfDamaged) <> 0)) @@ -782,6 +1133,7 @@ (((((LandPixels[y,x] and GMask shr GShift) * 3 div 4)+((ExplosionBorderColor and GMask) shr GShift) div 4) and $FF) shl GShift) or (((((LandPixels[y,x] and BMask shr BShift) * 3 div 4)+((ExplosionBorderColor and BMask) shr BShift) div 4) and $FF) shl BShift) or ($FF shl AShift) end; +{ if (Land[y, x-1] = lfObject) then Land[y, x]:= lfObject else if (Land[y, x+1] = lfObject) then @@ -791,9 +1143,10 @@ else if (Land[y-1, x] = lfObject) then Land[y, x]:= lfObject else Land[y,x]:= lfBasic +} end end -else if ((cReducedQuality and rqBlurryLand) = 0) and (LandPixels[Y, X] and AMask = 255) +else if ((cReducedQuality and rqBlurryLand) = 0) and ((LandPixels[Y, X] and AMask) = AMask) and (Land[Y, X] and (lfDamaged or lfBasic) = lfBasic) and (Y > LongInt(topY) + 1) and (Y < LAND_HEIGHT-2) and (X > LongInt(leftX) + 1) and (X < LongInt(rightX) - 1) then begin @@ -824,7 +1177,7 @@ function SweepDirty: boolean; var x, y, xx, yy, ty, tx: LongInt; - bRes, updateBlock, resweep, recheck: boolean; + bRes, resweep, recheck: boolean; begin bRes:= false; reCheck:= true; @@ -838,7 +1191,6 @@ begin if LandDirty[y, x] = 1 then begin - updateBlock:= false; resweep:= true; ty:= y * 32; tx:= x * 32; @@ -850,7 +1202,6 @@ if Despeckle(xx, yy) then begin bRes:= true; - updateBlock:= true; resweep:= true; if (yy = ty) and (y > 0) then begin @@ -874,14 +1225,24 @@ end end; end; - if updateBlock then - UpdateLandTexture(tx, 32, ty, 32, false); - LandDirty[y, x]:= 2; end; end; end; end; +// smooth explosion borders (except if land is blurry) +if (cReducedQuality and rqBlurryLand) = 0 then + for y:= 0 to LAND_HEIGHT div 32 - 1 do + for x:= 0 to LAND_WIDTH div 32 - 1 do + if LandDirty[y, x] <> 0 then + begin + ty:= y * 32; + tx:= x * 32; + for yy:= ty to ty + 31 do + for xx:= tx to tx + 31 do + Smooth(xx,yy) + end; + for y:= 0 to LAND_HEIGHT div 32 - 1 do for x:= 0 to LAND_WIDTH div 32 - 1 do if LandDirty[y, x] <> 0 then @@ -889,9 +1250,7 @@ LandDirty[y, x]:= 0; ty:= y * 32; tx:= x * 32; - for yy:= ty to ty + 31 do - for xx:= tx to tx + 31 do - Smooth(xx,yy) + UpdateLandTexture(tx, 32, ty, 32, false); end; SweepDirty:= bRes; @@ -977,19 +1336,29 @@ end end; -procedure DrawDots(x, y, xx, yy: Longint; Color: Longword); inline; +function DrawDots(x, y, xx, yy: Longint; Color: Longword): Longword; inline; begin - if (((x + xx) and LAND_WIDTH_MASK) = 0) and (((y + yy) and LAND_HEIGHT_MASK) = 0) then Land[y + yy, x + xx]:= Color; - if (((x + xx) and LAND_WIDTH_MASK) = 0) and (((y - yy) and LAND_HEIGHT_MASK) = 0) then Land[y - yy, x + xx]:= Color; - if (((x - xx) and LAND_WIDTH_MASK) = 0) and (((y + yy) and LAND_HEIGHT_MASK) = 0) then Land[y + yy, x - xx]:= Color; - if (((x - xx) and LAND_WIDTH_MASK) = 0) and (((y - yy) and LAND_HEIGHT_MASK) = 0) then Land[y - yy, x - xx]:= Color; - if (((x + yy) and LAND_WIDTH_MASK) = 0) and (((y + xx) and LAND_HEIGHT_MASK) = 0) then Land[y + xx, x + yy]:= Color; - if (((x + yy) and LAND_WIDTH_MASK) = 0) and (((y - xx) and LAND_HEIGHT_MASK) = 0) then Land[y - xx, x + yy]:= Color; - if (((x - yy) and LAND_WIDTH_MASK) = 0) and (((y + xx) and LAND_HEIGHT_MASK) = 0) then Land[y + xx, x - yy]:= Color; - if (((x - yy) and LAND_WIDTH_MASK) = 0) and (((y - xx) and LAND_HEIGHT_MASK) = 0) then Land[y - xx, x - yy]:= Color; + DrawDots:= 0; + + if (((x + xx) and LAND_WIDTH_MASK) = 0) and (((y + yy) and LAND_HEIGHT_MASK) = 0) and (Land[y + yy, x + xx] <> Color) then + begin inc(DrawDots); Land[y + yy, x + xx]:= Color; end; + if (((x + xx) and LAND_WIDTH_MASK) = 0) and (((y - yy) and LAND_HEIGHT_MASK) = 0) and (Land[y - yy, x + xx] <> Color) then + begin inc(DrawDots); Land[y - yy, x + xx]:= Color; end; + if (((x - xx) and LAND_WIDTH_MASK) = 0) and (((y + yy) and LAND_HEIGHT_MASK) = 0) and (Land[y + yy, x - xx] <> Color) then + begin inc(DrawDots); Land[y + yy, x - xx]:= Color; end; + if (((x - xx) and LAND_WIDTH_MASK) = 0) and (((y - yy) and LAND_HEIGHT_MASK) = 0) and (Land[y - yy, x - xx] <> Color) then + begin inc(DrawDots); Land[y - yy, x - xx]:= Color; end; + if (((x + yy) and LAND_WIDTH_MASK) = 0) and (((y + xx) and LAND_HEIGHT_MASK) = 0) and (Land[y + xx, x + yy] <> Color) then + begin inc(DrawDots); Land[y + xx, x + yy]:= Color; end; + if (((x + yy) and LAND_WIDTH_MASK) = 0) and (((y - xx) and LAND_HEIGHT_MASK) = 0) and (Land[y - xx, x + yy] <> Color) then + begin inc(DrawDots); Land[y - xx, x + yy]:= Color; end; + if (((x - yy) and LAND_WIDTH_MASK) = 0) and (((y + xx) and LAND_HEIGHT_MASK) = 0) and (Land[y + xx, x - yy] <> Color) then + begin inc(DrawDots); Land[y + xx, x - yy]:= Color; end; + if (((x - yy) and LAND_WIDTH_MASK) = 0) and (((y - xx) and LAND_HEIGHT_MASK) = 0) and (Land[y - xx, x - yy] <> Color) then + begin inc(DrawDots); Land[y - xx, x - yy]:= Color; end; end; -procedure DrawLines(X1, Y1, X2, Y2, XX, YY: LongInt; color: Longword); +function DrawLines(X1, Y1, X2, Y2, XX, YY: LongInt; color: Longword): Longword; var eX, eY, dX, dY: LongInt; i, sX, sY, x, y, d: LongInt; @@ -999,6 +1368,7 @@ eY:= 0; dX:= X2 - X1; dY:= Y2 - Y1; + DrawLines:= 0; if (dX > 0) then sX:= 1 @@ -1040,30 +1410,32 @@ begin dec(eX, d); inc(x, sX); - DrawDots(x, y, xx, yy, color) + inc(DrawLines, DrawDots(x, y, xx, yy, color)) end; if (eY > d) then begin dec(eY, d); inc(y, sY); f:= true; - DrawDots(x, y, xx, yy, color) + inc(DrawLines, DrawDots(x, y, xx, yy, color)) end; if not f then - DrawDots(x, y, xx, yy, color) + inc(DrawLines, DrawDots(x, y, xx, yy, color)) end end; -procedure DrawThickLine(X1, Y1, X2, Y2, radius: LongInt; color: Longword); +function DrawThickLine(X1, Y1, X2, Y2, radius: LongInt; color: Longword): Longword; var dx, dy, d: LongInt; begin + DrawThickLine:= 0; + dx:= 0; dy:= Radius; d:= 3 - 2 * Radius; while (dx < dy) do begin - DrawLines(x1, y1, x2, y2, dx, dy, color); + inc(DrawThickLine, DrawLines(x1, y1, x2, y2, dx, dy, color)); if (d < 0) then d:= d + 4 * dx + 6 else @@ -1074,7 +1446,7 @@ inc(dx) end; if (dx = dy) then - DrawLines(x1, y1, x2, y2, dx, dy, color); + inc(DrawThickLine, DrawLines(x1, y1, x2, y2, dx, dy, color)); end; diff -r 31570b766315 -r ed5a6478e710 hedgewars/uLandObjects.pas --- a/hedgewars/uLandObjects.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uLandObjects.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} @@ -26,7 +26,8 @@ procedure FreeLandObjects(); procedure LoadThemeConfig; procedure BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface); inline; -procedure BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface; LandFlags: Word); +procedure BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface; LandFlags: Word); inline; +procedure BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface; LandFlags: Word; Flip: boolean); procedure BlitImageUsingMask(cpX, cpY: Longword; Image, Mask: PSDL_Surface); procedure AddOnLandObjects(Surface: PSDL_Surface); procedure SetLand(var LandWord: Word; Pixel: LongWord); inline; @@ -92,12 +93,17 @@ procedure BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface); inline; begin - BlitImageAndGenerateCollisionInfo(cpX, cpY, Width, Image, 0); + BlitImageAndGenerateCollisionInfo(cpX, cpY, Width, Image, 0, false); end; - -procedure BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface; LandFlags: Word); + +procedure BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface; LandFlags: Word); inline; +begin + BlitImageAndGenerateCollisionInfo(cpX, cpY, Width, Image, LandFlags, false); +end; + +procedure BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface; LandFlags: Word; Flip: boolean); var p: PLongwordArray; - x, y: Longword; + px, x, y: Longword; bpp: LongInt; begin WriteToConsole('Generating collision info... '); @@ -115,22 +121,30 @@ for y:= 0 to Pred(Image^.h) do begin for x:= 0 to Pred(Width) do - if (p^[x] and AMask) <> 0 then + begin + // map image pixels per line backwards if in flip mode + if Flip then + px:= Pred(Image^.w) - x + else + px:= x; + + if (p^[px] and AMask) <> 0 then begin if (cReducedQuality and rqBlurryLand) = 0 then begin if (LandPixels[cpY + y, cpX + x] = 0) - or (((p^[x] and AMask) <> 0) and (((LandPixels[cpY + y, cpX + x] and AMask) shr AShift) < 255)) then - LandPixels[cpY + y, cpX + x]:= p^[x]; + or (((p^[px] and AMask) <> 0) and (((LandPixels[cpY + y, cpX + x] and AMask) shr AShift) < 255)) then + LandPixels[cpY + y, cpX + x]:= p^[px]; end else - if LandPixels[(cpY + y) div 2, (cpX + x) div 2] = 0 then - LandPixels[(cpY + y) div 2, (cpX + x) div 2]:= p^[x]; + if LandPixels[(cpY + y) div 2, (cpX + x) div 2] = 0 then + LandPixels[(cpY + y) div 2, (cpX + x) div 2]:= p^[px]; - if (Land[cpY + y, cpX + x] <= lfAllObjMask) and ((p^[x] and AMask) <> 0) then + if (Land[cpY + y, cpX + x] <= lfAllObjMask) and ((p^[px] and AMask) <> 0) then Land[cpY + y, cpX + x]:= lfObject or LandFlags end; - p:= @(p^[Image^.pitch shr 2]) + end; + p:= PLongwordArray(@(p^[Image^.pitch shr 2])) end; if SDL_MustLock(Image) then @@ -164,14 +178,14 @@ LandPixels[cpY + y, cpX + x]:= p^[x]; end else - if LandPixels[(cpY + y) div 2, (cpX + x) div 2] = 0 then + if LandPixels[(cpY + y) div 2, (cpX + x) div 2] = 0 then LandPixels[(cpY + y) div 2, (cpX + x) div 2]:= p^[x]; if (Land[cpY + y, cpX + x] <= lfAllObjMask) or (Land[cpY + y, cpX + x] and lfObject <> 0) then SetLand(Land[cpY + y, cpX + x], mp^[x]); end; - p:= @(p^[Image^.pitch shr 2]); - mp:= @(mp^[Mask^.pitch shr 2]) + p:= PLongwordArray(@(p^[Image^.pitch shr 2])); + mp:= PLongwordArray(@(mp^[Mask^.pitch shr 2])) end; if SDL_MustLock(Image) then @@ -219,50 +233,54 @@ end; -function CountNonZeroz(x, y: LongInt): Longword; +function CountNonZeroz(x, y, h: LongInt): Longword; var i: LongInt; lRes: Longword; begin lRes:= 0; - for i:= y to y + 15 do + for i:= y to Pred(y + h) do if Land[i, x] <> 0 then inc(lRes); CountNonZeroz:= lRes; end; -function AddGirder(gX: LongInt): boolean; -var tmpsurf: PSDL_Surface; - x1, x2, y, k, i: LongInt; +function AddGirder(gX: LongInt; var girSurf: PSDL_Surface): boolean; +var x1, x2, y, k, i, girderHeight: LongInt; rr: TSDL_Rect; bRes: boolean; begin +if girSurf = nil then + girSurf:= LoadDataImageAltPath(ptCurrTheme, ptGraphics, 'Girder', ifCritical or ifTransparent or ifIgnoreCaps); + +girderHeight:= girSurf^.h; + y:= topY+150; repeat inc(y, 24); x1:= gX; x2:= gX; - while (x1 > Longint(leftX)+150) and (CountNonZeroz(x1, y) = 0) do + while (x1 > Longint(leftX)+150) and (CountNonZeroz(x1, y, girderHeight) = 0) do dec(x1, 2); i:= x1 - 12; repeat - dec(x1, 2); - k:= CountNonZeroz(x1, y) - until (x1 < Longint(leftX)+150) or (k = 0) or (k = 16) or (x1 < i); + k:= CountNonZeroz(x1, y, girderHeight); + dec(x1, 2) + until (x1 < Longint(leftX) + 100) or (k = 0) or (k = girderHeight) or (x1 < i); inc(x1, 2); - if k = 16 then + if k = girderHeight then begin - while (x2 < (rightX-150)) and (CountNonZeroz(x2, y) = 0) do + while (x2 < (LongInt(rightX) - 100)) and (CountNonZeroz(x2, y, girderHeight) = 0) do inc(x2, 2); i:= x2 + 12; repeat inc(x2, 2); - k:= CountNonZeroz(x2, y) - until (x2 >= (rightX-150)) or (k = 0) or (k = 16) or (x2 > i) or (x2 - x1 >= 768); - - if (x2 < (rightX - 150)) and (k = 16) and (x2 - x1 > 250) and (x2 - x1 < 768) + k:= CountNonZeroz(x2, y, girderHeight) + until (x2 >= (LongInt(rightX)-150)) or (k = 0) or (k = girderHeight) or (x2 > i) or (x2 - x1 >= 900); + + if (x2 < (LongInt(rightX) - 100)) and (k = girderHeight) and (x2 - x1 > 200) and (x2 - x1 < 900) and (not CheckIntersect(x1 - 32, y - 64, x2 - x1 + 64, 144)) then break; end; @@ -272,18 +290,16 @@ if x1 > 0 then begin bRes:= true; - tmpsurf:= LoadDataImageAltPath(ptCurrTheme, ptGraphics, 'Girder', ifCritical or ifTransparent or ifIgnoreCaps); rr.x:= x1; while rr.x < x2 do begin - if cIce then - BlitImageAndGenerateCollisionInfo(rr.x, y, min(x2 - rr.x, tmpsurf^.w), tmpsurf, lfIce) + if cIce then + BlitImageAndGenerateCollisionInfo(rr.x, y, min(x2 - rr.x, girSurf^.w), girSurf, lfIce) else - BlitImageAndGenerateCollisionInfo(rr.x, y, min(x2 - rr.x, tmpsurf^.w), tmpsurf); - inc(rr.x, tmpsurf^.w); + BlitImageAndGenerateCollisionInfo(rr.x, y, min(x2 - rr.x, girSurf^.w), girSurf); + inc(rr.x, girSurf^.w); end; - SDL_FreeSurface(tmpsurf); AddRect(x1 - 8, y - 32, x2 - x1 + 16, 80); end @@ -372,8 +388,8 @@ ar[cnt].y:= y; if cnt >= MaxPointsIndex then // buffer is full, do not check the rest land begin - y:= $FF000000; - x:= $FF000000; + y:= LAND_HEIGHT; + x:= LAND_WIDTH; end else inc(cnt); end; @@ -455,9 +471,9 @@ procedure CheckRect(Width, Height, x, y, w, h: LongWord); begin - if (x + w > Width) then + if (x + w > Width) then OutError('Object''s rectangle exceeds image: x + w (' + inttostr(x) + ' + ' + inttostr(w) + ') > Width (' + inttostr(Width) + ')', true); - if (y + h > Height) then + if (y + h > Height) then OutError('Object''s rectangle exceeds image: y + h (' + inttostr(y) + ' + ' + inttostr(h) + ') > Height (' + inttostr(Height) + ')', true); end; @@ -473,7 +489,7 @@ // Set default water greyscale values if GrayScale then begin - for i:= 0 to 3 do + for i:= Low(SDWaterColorArray) to High(SDWaterColorArray) do begin t:= round(SDWaterColorArray[i].r * RGB_LUMINANCE_RED + SDWaterColorArray[i].g * RGB_LUMINANCE_GREEN + SDWaterColorArray[i].b * RGB_LUMINANCE_BLUE); if t > 255 then @@ -482,7 +498,7 @@ SDWaterColorArray[i].g:= t; SDWaterColorArray[i].b:= t end; - for i:= 0 to 1 do + for i:= Low(WaterColorArray) to High(WaterColorArray) do begin t:= round(WaterColorArray[i].r * RGB_LUMINANCE_RED + WaterColorArray[i].g * RGB_LUMINANCE_GREEN + WaterColorArray[i].b * RGB_LUMINANCE_BLUE); if t > 255 then @@ -555,11 +571,39 @@ c2.g:= t; c2.b:= t end; - ExplosionBorderColor:= (c2.r shl RShift) or (c2.g shl GShift) or (c2.b shl BShift) or AMask; + ExplosionBorderColorR:= c2.r; + ExplosionBorderColorG:= c2.g; + ExplosionBorderColorB:= c2.b; + ExplosionBorderColorNoA:= + (c2.r shl RShift) or (c2.g shl GShift) or (c2.b shl BShift); + ExplosionBorderColor:= ExplosionBorderColorNoA or AMask; end else if key = 'water-top' then begin i:= Pos(',', s); + WaterColorArray[1].r:= StrToInt(Trim(Copy(s, 1, Pred(i)))); + Delete(s, 1, i); + i:= Pos(',', s); + WaterColorArray[1].g:= StrToInt(Trim(Copy(s, 1, Pred(i)))); + Delete(s, 1, i); + WaterColorArray[1].b:= StrToInt(Trim(s)); + WaterColorArray[1].a := 255; + if GrayScale then + begin + t:= round(WaterColorArray[0].r * RGB_LUMINANCE_RED + WaterColorArray[0].g * RGB_LUMINANCE_GREEN + WaterColorArray[0].b * RGB_LUMINANCE_BLUE); + if t > 255 then + t:= 255; + WaterColorArray[1].r:= t; + WaterColorArray[1].g:= t; + WaterColorArray[1].b:= t + end; + WaterColorArray[3]:= WaterColorArray[1]; + WaterColorArray[5]:= WaterColorArray[1]; + WaterColorArray[7]:= WaterColorArray[1]; + end + else if key = 'water-bottom' then + begin + i:= Pos(',', s); WaterColorArray[0].r:= StrToInt(Trim(Copy(s, 1, Pred(i)))); Delete(s, 1, i); i:= Pos(',', s); @@ -569,35 +613,16 @@ WaterColorArray[0].a := 255; if GrayScale then begin - t:= round(WaterColorArray[0].r * RGB_LUMINANCE_RED + WaterColorArray[0].g * RGB_LUMINANCE_GREEN + WaterColorArray[0].b * RGB_LUMINANCE_BLUE); + t:= round(WaterColorArray[2].r * RGB_LUMINANCE_RED + WaterColorArray[2].g * RGB_LUMINANCE_GREEN + WaterColorArray[2].b * RGB_LUMINANCE_BLUE); if t > 255 then t:= 255; WaterColorArray[0].r:= t; WaterColorArray[0].g:= t; WaterColorArray[0].b:= t end; - WaterColorArray[1]:= WaterColorArray[0]; - end - else if key = 'water-bottom' then - begin - i:= Pos(',', s); - WaterColorArray[2].r:= StrToInt(Trim(Copy(s, 1, Pred(i)))); - Delete(s, 1, i); - i:= Pos(',', s); - WaterColorArray[2].g:= StrToInt(Trim(Copy(s, 1, Pred(i)))); - Delete(s, 1, i); - WaterColorArray[2].b:= StrToInt(Trim(s)); - WaterColorArray[2].a := 255; - if GrayScale then - begin - t:= round(WaterColorArray[2].r * RGB_LUMINANCE_RED + WaterColorArray[2].g * RGB_LUMINANCE_GREEN + WaterColorArray[2].b * RGB_LUMINANCE_BLUE); - if t > 255 then - t:= 255; - WaterColorArray[2].r:= t; - WaterColorArray[2].g:= t; - WaterColorArray[2].b:= t - end; - WaterColorArray[3]:= WaterColorArray[2]; + WaterColorArray[2]:= WaterColorArray[0]; + WaterColorArray[4]:= WaterColorArray[0]; + WaterColorArray[6]:= WaterColorArray[0]; end else if key = 'water-opacity' then begin @@ -605,7 +630,9 @@ SDWaterOpacity:= WaterOpacity end else if key = 'music' then - SetMusicName(Trim(s)) + MusicFN:= Trim(s) + else if key = 'sd-music' then + SDMusicFN:= Trim(s) else if key = 'clouds' then begin cCloudsNumber:= Word(StrToInt(Trim(s))) * cScreenSpace div 4096; @@ -713,6 +740,29 @@ else if key = 'sd-water-top' then begin i:= Pos(',', s); + SDWaterColorArray[1].r:= StrToInt(Trim(Copy(s, 1, Pred(i)))); + Delete(s, 1, i); + i:= Pos(',', s); + SDWaterColorArray[1].g:= StrToInt(Trim(Copy(s, 1, Pred(i)))); + Delete(s, 1, i); + SDWaterColorArray[1].b:= StrToInt(Trim(s)); + SDWaterColorArray[1].a := 255; + if GrayScale then + begin + t:= round(SDWaterColorArray[0].r * RGB_LUMINANCE_RED + SDWaterColorArray[0].g * RGB_LUMINANCE_GREEN + SDWaterColorArray[0].b * RGB_LUMINANCE_BLUE); + if t > 255 then + t:= 255; + SDWaterColorArray[1].r:= t; + SDWaterColorArray[1].g:= t; + SDWaterColorArray[1].b:= t + end; + SDWaterColorArray[3]:= SDWaterColorArray[1]; + SDWaterColorArray[5]:= SDWaterColorArray[1]; + SDWaterColorArray[7]:= SDWaterColorArray[1]; + end + else if key = 'sd-water-bottom' then + begin + i:= Pos(',', s); SDWaterColorArray[0].r:= StrToInt(Trim(Copy(s, 1, Pred(i)))); Delete(s, 1, i); i:= Pos(',', s); @@ -722,35 +772,16 @@ SDWaterColorArray[0].a := 255; if GrayScale then begin - t:= round(SDWaterColorArray[0].r * RGB_LUMINANCE_RED + SDWaterColorArray[0].g * RGB_LUMINANCE_GREEN + SDWaterColorArray[0].b * RGB_LUMINANCE_BLUE); + t:= round(SDWaterColorArray[2].r * RGB_LUMINANCE_RED + SDWaterColorArray[2].g * RGB_LUMINANCE_GREEN + SDWaterColorArray[2].b * RGB_LUMINANCE_BLUE); if t > 255 then t:= 255; SDWaterColorArray[0].r:= t; SDWaterColorArray[0].g:= t; SDWaterColorArray[0].b:= t end; - SDWaterColorArray[1]:= SDWaterColorArray[0]; - end - else if key = 'sd-water-bottom' then - begin - i:= Pos(',', s); - SDWaterColorArray[2].r:= StrToInt(Trim(Copy(s, 1, Pred(i)))); - Delete(s, 1, i); - i:= Pos(',', s); - SDWaterColorArray[2].g:= StrToInt(Trim(Copy(s, 1, Pred(i)))); - Delete(s, 1, i); - SDWaterColorArray[2].b:= StrToInt(Trim(s)); - SDWaterColorArray[2].a := 255; - if GrayScale then - begin - t:= round(SDWaterColorArray[2].r * RGB_LUMINANCE_RED + SDWaterColorArray[2].g * RGB_LUMINANCE_GREEN + SDWaterColorArray[2].b * RGB_LUMINANCE_BLUE); - if t > 255 then - t:= 255; - SDWaterColorArray[2].r:= t; - SDWaterColorArray[2].g:= t; - SDWaterColorArray[2].b:= t - end; - SDWaterColorArray[3]:= SDWaterColorArray[2]; + SDWaterColorArray[2]:= SDWaterColorArray[0]; + SDWaterColorArray[4]:= SDWaterColorArray[0]; + SDWaterColorArray[6]:= SDWaterColorArray[0]; end else if key = 'sd-water-opacity' then SDWaterOpacity:= StrToInt(Trim(s)) @@ -856,17 +887,25 @@ end; procedure AddObjects(); -var i, g: Longword; +var girSurf: PSDL_Surface; + i, g: Longword; begin InitRects; if hasGirders then begin g:= max(playWidth div 8, 256); i:= leftX + g; + girSurf:= nil; repeat - AddGirder(i); + AddGirder(i, girSurf); i:=i + g; until (i > rightX - g); + // free girder surface + if girSurf <> nil then + begin + SDL_FreeSurface(girSurf); + girSurf:= nil; + end; end; if (GameFlags and gfDisableLandObjects) = 0 then AddThemeObjects(ThemeObjects); diff -r 31570b766315 -r ed5a6478e710 hedgewars/uLandOutline.pas --- a/hedgewars/uLandOutline.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uLandOutline.pas Tue Nov 10 20:43:13 2015 +0100 @@ -9,8 +9,8 @@ ar: array[0..Pred(cMaxEdgePoints)] of TPoint; end; -procedure DrawEdge(var pa: TPixAr; Color: Longword); -procedure FillLand(x, y: LongInt); +procedure DrawEdge(var pa: TPixAr; value: Word); +procedure FillLand(x, y: LongInt; border, value: Word); procedure BezierizeEdge(var pa: TPixAr; Delta: hwFloat); procedure RandomizePoints(var pa: TPixAr); @@ -27,8 +27,6 @@ end end; -const - cMaxEdgePoints = 16384; procedure Push(_xl, _xr, _y, _dir: LongInt); begin @@ -58,7 +56,7 @@ end end; -procedure FillLand(x, y: LongInt); +procedure FillLand(x, y: LongInt; border, value: Word); var xl, xr, dir: LongInt; begin Stack.Count:= 0; @@ -70,18 +68,18 @@ while Stack.Count > 0 do begin Pop(xl, xr, y, dir); - while (xl > 0) and (Land[y, xl] <> 0) do + while (xl > 0) and (Land[y, xl] <> border) and (Land[y, xl] <> value) do dec(xl); - while (xr < LAND_WIDTH - 1) and (Land[y, xr] <> 0) do + while (xr < LAND_WIDTH - 1) and (Land[y, xr] <> border) and (Land[y, xr] <> value) do inc(xr); while (xl < xr) do begin - while (xl <= xr) and (Land[y, xl] = 0) do + while (xl <= xr) and ((Land[y, xl] = border) or (Land[y, xl] = value)) do inc(xl); x:= xl; - while (xl <= xr) and (Land[y, xl] <> 0) do + while (xl <= xr) and (Land[y, xl] <> border) and (Land[y, xl] <> value) do begin - Land[y, xl]:= 0; + Land[y, xl]:= value; inc(xl) end; if x < xl then @@ -93,17 +91,17 @@ end; end; -procedure DrawEdge(var pa: TPixAr; Color: Longword); +procedure DrawEdge(var pa: TPixAr; value: Word); var i: LongInt; begin i:= 0; with pa do while i < LongInt(Count) - 1 do - if (ar[i + 1].X = NTPX) then + if (ar[i + 1].X = NTPX) then inc(i, 2) - else + else begin - DrawLine(ar[i].x, ar[i].y, ar[i + 1].x, ar[i + 1].y, Color); + DrawLine(ar[i].x, ar[i].y, ar[i + 1].x, ar[i + 1].y, value); inc(i) end end; @@ -115,30 +113,27 @@ Vx:= int2hwFloat(p1.X - p3.X); Vy:= int2hwFloat(p1.Y - p3.Y); - d:= DistanceI(p2.X - p1.X, p2.Y - p1.Y); - d1:= DistanceI(p2.X - p3.X, p2.Y - p3.Y); d2:= Distance(Vx, Vy); - if d1 < d then - d:= d1; - if d2 < d then - d:= d2; - - d:= d * _1div3; - if d2.QWordValue = 0 then begin Vx:= _0; Vy:= _0 - end + end else begin - d2:= _1 / d2; + d:= DistanceI(p2.X - p1.X, p2.Y - p1.Y); + d1:= DistanceI(p2.X - p3.X, p2.Y - p3.Y); + + if d1 < d then + d:= d1; + if d2 < d then + d:= d2; + + d2:= d * _1div3 / d2; + Vx:= Vx * d2; - Vy:= Vy * d2; - - Vx:= Vx * d; - Vy:= Vy * d + Vy:= Vy * d2 end end; @@ -149,54 +144,57 @@ tsq, tcb, t, r1, r2, r3, cx1, cx2, cy1, cy2: hwFloat; X, Y: LongInt; begin -pi:= EndI; -i:= StartI; -ni:= Succ(StartI); -{$HINTS OFF} -Vector(opa.ar[pi], opa.ar[i], opa.ar[ni], NVx, NVy); -{$HINTS ON} -repeat - inc(pi); - if pi > EndI then - pi:= StartI; - inc(i); - if i > EndI then + if pa.Count < cMaxEdgePoints - 2 then + begin + pi:= EndI; i:= StartI; - inc(ni); - if ni > EndI then - ni:= StartI; - PVx:= NVx; - PVy:= NVy; - Vector(opa.ar[pi], opa.ar[i], opa.ar[ni], NVx, NVy); + ni:= Succ(StartI); + {$HINTS OFF} + Vector(opa.ar[pi], opa.ar[i], opa.ar[ni], NVx, NVy); + {$HINTS ON} + repeat + i:= ni; + inc(pi); + if pi > EndI then + pi:= StartI; + inc(ni); + if ni > EndI then + ni:= StartI; + PVx:= NVx; + PVy:= NVy; + Vector(opa.ar[pi], opa.ar[i], opa.ar[ni], NVx, NVy); + + x1:= opa.ar[pi].x; + y1:= opa.ar[pi].y; + x2:= opa.ar[i].x; + y2:= opa.ar[i].y; - x1:= opa.ar[pi].x; - y1:= opa.ar[pi].y; - x2:= opa.ar[i].x; - y2:= opa.ar[i].y; - cx1:= int2hwFloat(x1) - PVx; - cy1:= int2hwFloat(y1) - PVy; - cx2:= int2hwFloat(x2) + NVx; - cy2:= int2hwFloat(y2) + NVy; - t:= _0; - while t.Round = 0 do - begin - tsq:= t * t; - tcb:= tsq * t; - r1:= (_1 - t*3 + tsq*3 - tcb); - r2:= ( t*3 - tsq*6 + tcb*3); - r3:= ( tsq*3 - tcb*3); - X:= hwRound(r1 * x1 + r2 * cx1 + r3 * cx2 + tcb * x2); - Y:= hwRound(r1 * y1 + r2 * cy1 + r3 * cy2 + tcb * y2); - t:= t + Delta; - pa.ar[pa.Count].x:= X; - pa.ar[pa.Count].y:= Y; - inc(pa.Count); - TryDo(pa.Count <= cMaxEdgePoints, 'Edge points overflow', true) + cx1:= int2hwFloat(x1) - PVx; + cy1:= int2hwFloat(y1) - PVy; + cx2:= int2hwFloat(x2) + NVx; + cy2:= int2hwFloat(y2) + NVy; + t:= _0; + while (t.Round = 0) and (pa.Count < cMaxEdgePoints-2) do + begin + tsq:= t * t; + tcb:= tsq * t; + r1:= (_1 - t*3 + tsq*3 - tcb); + r2:= ( t*3 - tsq*6 + tcb*3); + r3:= ( tsq*3 - tcb*3); + X:= hwRound(r1 * x1 + r2 * cx1 + r3 * cx2 + tcb * x2); + Y:= hwRound(r1 * y1 + r2 * cy1 + r3 * cy2 + tcb * y2); + t:= t + Delta; + pa.ar[pa.Count].x:= X; + pa.ar[pa.Count].y:= Y; + inc(pa.Count); + //TryDo(pa.Count <= cMaxEdgePoints, 'Edge points overflow', true) + end; + until i = StartI; end; -until i = StartI; -pa.ar[pa.Count].x:= opa.ar[StartI].X; -pa.ar[pa.Count].y:= opa.ar[StartI].Y; -inc(pa.Count) + + pa.ar[pa.Count].x:= opa.ar[StartI].X; + pa.ar[pa.Count].y:= opa.ar[StartI].Y; + inc(pa.Count) end; procedure BezierizeEdge(var pa: TPixAr; Delta: hwFloat); @@ -207,7 +205,7 @@ pa.Count:= 0; i:= 0; StartLoop:= 0; -while i < LongInt(opa.Count) do +while (i < LongInt(opa.Count)) and (pa.Count < cMaxEdgePoints-1) do if (opa.ar[i + 1].X = NTPX) then begin AddLoopPoints(pa, opa, StartLoop, i, Delta); @@ -237,7 +235,7 @@ CheckIntersect:= false else if (c2 < 0) or (c2 > dm) then CheckIntersect:= false; - end + end else begin if (c1 > 0) or (c1 < dm) then @@ -255,7 +253,7 @@ var i: Longword; begin CheckSelfIntersect:= false; - if (ind <= 0) or (ind >= Pred(pa.Count)) then + if (ind <= 0) or (LongInt(ind) >= Pred(pa.Count)) then exit; CheckSelfIntersect:= true; diff -r 31570b766315 -r ed5a6478e710 hedgewars/uLandPainted.pas --- a/hedgewars/uLandPainted.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uLandPainted.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} @@ -27,12 +27,13 @@ procedure freeModule; implementation -uses uLandGraphics, uConsts, uVariables, uUtils, SDLh, uCommands, uDebug, uScript; +uses uLandGraphics, uConsts, uVariables, uUtils, SDLh, uCommands, uScript, uIO; type PointRec = packed record X, Y: SmallInt; flags: byte; end; + PPointRec = ^PointRec; type PPointEntry = ^PointEntry; @@ -45,7 +46,7 @@ procedure chDraw(var s: shortstring); var rec: PointRec; - prec: ^PointRec; + prec: PPointRec; pe: PPointEntry; i, l: byte; begin @@ -53,7 +54,7 @@ l:= length(s); while i < l do begin - prec:= @s[i]; + prec:= PPointRec(@s[i]); rec:= prec^; rec.X:= SDLNet_Read16(@rec.X); rec.Y:= SDLNet_Read16(@rec.Y); @@ -81,11 +82,13 @@ prevPoint: PointRec; radius: LongInt; color: Longword; + lineNumber, linePoints: Longword; begin // shutup compiler prevPoint.X:= 0; prevPoint.Y:= 0; radius:= 0; + linePoints:= 0; pe:= pointsListHead; while (pe <> nil) and (pe^.point.flags and $80 = 0) do @@ -94,23 +97,27 @@ pe:= pe^.next; end; + lineNumber:= 0; + while(pe <> nil) do begin if (pe^.point.flags and $80 <> 0) then begin + if (lineNumber > 0) and (linePoints = 0) and cAdvancedMapGenMode then + SendIPC('|' + inttostr(lineNumber - 1)); + + inc(lineNumber); + if (pe^.point.flags and $40 <> 0) then color:= 0 else color:= lfBasic; radius:= (pe^.point.flags and $3F) * 5 + 3; - AddFileLog('[DRAW] Move to: ('+inttostr(pe^.point.X)+','+inttostr(pe^.point.Y)+'), radius = '+inttostr(radius)); - FillRoundInLand(pe^.point.X, pe^.point.Y, radius, color) + linePoints:= FillRoundInLand(pe^.point.X, pe^.point.Y, radius, color); end else begin - AddFileLog('[DRAW] Line to: ('+inttostr(pe^.point.X)+','+inttostr(pe^.point.Y)+'), radius = '+inttostr(radius)); - DrawThickLine(prevPoint.X, prevPoint.Y, pe^.point.X, pe^.point.Y, radius, color); - FillRoundInLand(pe^.point.X, pe^.point.Y, radius, color) + inc(linePoints, DrawThickLine(prevPoint.X, prevPoint.Y, pe^.point.X, pe^.point.Y, radius, color)); end; prevPoint:= pe^.point; diff -r 31570b766315 -r ed5a6478e710 hedgewars/uLandTemplates.pas --- a/hedgewars/uLandTemplates.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uLandTemplates.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} @@ -65,7 +65,7 @@ ); Template0FPoints: array[0..0] of TPoint = ( - (X: 1023; Y: 0) + (x: 1023; y: 0) ); const Template1Points: array[0..15] of TSDL_Rect = @@ -89,7 +89,7 @@ ); Template1FPoints: array[0..0] of TPoint = ( - (X: 1023; Y: 0) + (x: 1023; y: 0) ); const Template2Points: array[0..21] of TSDL_Rect = @@ -119,7 +119,7 @@ ); Template2FPoints: array[0..0] of TPoint = ( - (X: 1023; Y: 0) + (x: 1023; y: 0) ); const Template3Points: array[0..16] of TSDL_Rect = @@ -144,7 +144,7 @@ ); Template3FPoints: array[0..0] of TPoint = ( - (X: 1023; Y: 0) + (x: 1023; y: 0) ); const Template4Points: array[0..22] of TSDL_Rect = @@ -164,7 +164,7 @@ (x: 550; y: 568; w: 134; h: 78), (x: 1102; y: 560; w: 132; h: 84), (x: 1102; y: 708; w: 230; h: 36), - (x: 1120; y: 808; w: 166; h: 96), + (x: 1120; y: 848; w: 166; h: 96), (x: NTPX; y: 0; w: 1; h: 1), (x: 2102; y: 834; w: 202; h: 42), (x: 1652; y: 788; w: 134; h: 98), @@ -175,7 +175,7 @@ ); Template4FPoints: array[0..0] of TPoint = ( - (X: 1023; Y: 0) + (x: 1023; y: 0) ); const Template5Points: array[0..15] of TSDL_Rect = @@ -199,7 +199,7 @@ ); Template5FPoints: array[0..0] of TPoint = ( - (X: 1023; Y: 0) + (x: 1023; y: 0) ); const Template6Points: array[0..13] of TSDL_Rect = @@ -221,7 +221,7 @@ ); Template6FPoints: array[0..0] of TPoint = ( - (X: 1023; Y: 0) + (x: 1023; y: 0) ); const Template7Points: array[0..5] of TSDL_Rect = @@ -235,7 +235,7 @@ ); Template7FPoints: array[0..0] of TPoint = ( - (X: 1023; Y: 0) + (x: 1023; y: 0) ); @@ -264,7 +264,7 @@ ); Template8FPoints: array[0..0] of TPoint = ( - (X: 1023; Y: 0) + (x: 1023; y: 0) ); const Template9Points: array[0..31] of TSDL_Rect = @@ -304,7 +304,7 @@ ); Template9FPoints: array[0..0] of TPoint = ( - (X: 1023; Y: 0) + (x: 1023; y: 0) ); const Template10Points: array[0..13] of TSDL_Rect = @@ -326,7 +326,7 @@ ); Template10FPoints: array[0..0] of TPoint = ( - (X: 1023; Y: 0) + (x: 1023; y: 0) ); const Template11Points: array[0..9] of TSDL_Rect = @@ -344,7 +344,7 @@ ); Template11FPoints: array[0..0] of TPoint = ( - (X: 1023; Y: 0) + (x: 1023; y: 0) ); const Template12Points: array[0..13] of TSDL_Rect = @@ -366,7 +366,7 @@ ); Template12FPoints: array[0..0] of TPoint = ( - (X: 1023; Y: 0) + (x: 1023; y: 0) ); const Template13Points: array[0..15] of TSDL_Rect = @@ -390,7 +390,7 @@ ); Template13FPoints: array[0..0] of TPoint = ( - (X: 1023; Y: 0) + (x: 1023; y: 0) ); const Template14Points: array[0..13] of TSDL_Rect = @@ -412,7 +412,7 @@ ); Template14FPoints: array[0..0] of TPoint = ( - (X: 1023; Y: 0) + (x: 1023; y: 0) ); const Template15Points: array[0..23] of TSDL_Rect = @@ -444,7 +444,7 @@ ); Template15FPoints: array[0..0] of TPoint = ( - (X: 1023; Y: 0) + (x: 1023; y: 0) ); const Template16Points: array[0..28] of TSDL_Rect = @@ -481,7 +481,7 @@ ); Template16FPoints: array[0..0] of TPoint = ( - (X: 1023; Y: 0) + (x: 1023; y: 0) ); const Template17Points: array[0..13] of TSDL_Rect = @@ -503,7 +503,7 @@ ); Template17FPoints: array[0..0] of TPoint = ( - (X: 1023; Y: 0) + (x: 1023; y: 0) ); //////////////////// MIXING AND MATCHING ORIGINAL ////////////////////////////////////// const Template18Points: array[0..32] of TSDL_Rect = @@ -544,7 +544,7 @@ ); Template18FPoints: array[0..0] of TPoint = ( - (X: 2047; Y: 0) + (x: 2047; y: 0) ); const Template19Points: array[0..44] of TSDL_Rect = @@ -597,7 +597,7 @@ ); Template19FPoints: array[0..0] of TPoint = ( - (X: 2047; Y: 0) + (x: 2047; y: 0) ); const Template20Points: array[0..45] of TSDL_Rect = @@ -651,7 +651,7 @@ ); Template20FPoints: array[0..0] of TPoint = ( - (X: 2047; Y: 0) + (x: 2047; y: 0) ); const Template21Points: array[0..30] of TSDL_Rect = @@ -690,7 +690,7 @@ ); Template21FPoints: array[0..0] of TPoint = ( - (X: 2047; Y: 0) + (x: 2047; y: 0) ); const Template22Points: array[0..38] of TSDL_Rect = @@ -737,7 +737,7 @@ ); Template22FPoints: array[0..0] of TPoint = ( - (X: 2047; Y: 0) + (x: 2047; y: 0) ); const Template23Points: array[0..29] of TSDL_Rect = @@ -775,7 +775,7 @@ ); Template23FPoints: array[0..0] of TPoint = ( - (X: 2047; Y: 0) + (x: 2047; y: 0) ); const Template24Points: array[0..23] of TSDL_Rect = @@ -807,7 +807,7 @@ ); Template24FPoints: array[0..0] of TPoint = ( - (X: 2047; Y: 0) + (x: 2047; y: 0) ); const Template25Points: array[0..19] of TSDL_Rect = @@ -835,7 +835,7 @@ ); Template25FPoints: array[0..0] of TPoint = ( - (X: 2047; Y: 0) + (x: 2047; y: 0) ); @@ -896,7 +896,7 @@ ); Template26FPoints: array[0..0] of TPoint = ( - (X: 2047; Y: 0) + (x: 2047; y: 0) ); const Template27Points: array[0..42] of TSDL_Rect = @@ -947,7 +947,7 @@ ); Template27FPoints: array[0..0] of TPoint = ( - (X: 2047; Y: 0) + (x: 2047; y: 0) ); const Template28Points: array[0..29] of TSDL_Rect = @@ -985,7 +985,7 @@ ); Template28FPoints: array[0..0] of TPoint = ( - (X: 2047; Y: 0) + (x: 2047; y: 0) ); const Template29Points: array[0..37] of TSDL_Rect = @@ -1031,7 +1031,7 @@ ); Template29FPoints: array[0..0] of TPoint = ( - (X: 2047; Y: 0) + (x: 2047; y: 0) ); const Template30Points: array[0..30] of TSDL_Rect = @@ -1070,7 +1070,7 @@ ); Template30FPoints: array[0..0] of TPoint = ( - (X: 2047; Y: 0) + (x: 2047; y: 0) ); const Template31Points: array[0..32] of TSDL_Rect = @@ -1111,7 +1111,7 @@ ); Template31FPoints: array[0..0] of TPoint = ( - (X: 2047; Y: 0) + (x: 2047; y: 0) ); const Template32Points: array[0..29] of TSDL_Rect = @@ -1149,7 +1149,7 @@ ); Template32FPoints: array[0..0] of TPoint = ( - (X: 2047; Y: 0) + (x: 2047; y: 0) ); const Template33Points: array[0..45] of TSDL_Rect = @@ -1203,7 +1203,7 @@ ); Template33FPoints: array[0..0] of TPoint = ( - (X: 2047; Y: 0) + (x: 2047; y: 0) ); const Template34Points: array[0..25] of TSDL_Rect = @@ -1237,7 +1237,7 @@ ); Template34FPoints: array[0..0] of TPoint = ( - (X: 2047; Y: 0) + (x: 2047; y: 0) ); const Template35Points: array[0..48] of TSDL_Rect = @@ -1294,7 +1294,7 @@ ); Template35FPoints: array[0..0] of TPoint = ( - (X: 2047; Y: 0) + (x: 2047; y: 0) ); ///////////////////////// CAVERNS /////////////////////////////////// @@ -1322,7 +1322,7 @@ ); Template36FPoints: array[0..0] of TPoint = ( - (X: 2047; Y: 0) + (x: 2047; y: 0) ); ////////////////////////////// ... Silly ... //////////////////////////////// /// Ok. Tiy does not care for these. Perhaps they could be saved. @@ -1332,63 +1332,64 @@ // maybe Tiy would be ok with this if it was smoother/more climable and a bit shorter? const Template37Points: array[0..27] of TSDL_Rect = ( - (x: 700; y: 2100; w: 20; h: 75), - (x: 800; y: 1200; w: 20; h: 75), - (x: 900; y: 400; w: 20; h: 50), - (x: 1100; y: 600; w: 20; h: 50), - (x: 1300; y: 900; w: 20; h: 50), - (x: 1000; y: 1000; w: 20; h: 50), - (x: 1700; y: 1850; w: 20; h: 75), - (x: 2048; y: 2100; w: 20; h: 75), - (x: NTPX; y: 0; w: 1; h: 1), - (x: 2048; y: 2100; w: 20; h: 50), - (x: 2400; y: 1850; w: 20; h: 50), - (x: 2600; y: 1000; w: 20; h: 75), - (x: 2800; y: 900; w: 20; h: 50), - (x: 3000; y: 600; w: 20; h: 50), - (x: 3200; y: 400; w: 20; h: 50), - (x: 3300; y: 1200; w: 20; h: 50), - (x: 3400; y: 2100; w: 20; h: 75), - (x: NTPX; y: 0; w: 1; h: 1), - (x: 1450; y: 700; w: 25; h: 25), - (x: 1850; y: 650; w: 25; h: 25), - (x: 2250; y: 800; w: 25; h: 25), - (x: 2500; y: 700; w: 25; h: 25), - (x: NTPX; y: 0; w: 1; h: 1), - (x: 1550; y: 1500; w: 25; h: 25), - (x: 1830; y: 1150; w: 25; h: 25), - (x: 2260; y: 1000; w: 25; h: 25), - (x: 2250; y: 1200; w: 25; h: 25), - (x: NTPX; y: 0; w: 1; h: 1) + (x: 700; y: 2100; w: 120; h: 175), + (x: 800; y: 1200; w: 120; h: 175), + (x: 900; y: 400; w: 120; h: 150), + (x: 1100; y: 600; w: 120; h: 150), + (x: 1300; y: 900; w: 120; h: 150), + (x: 1000; y: 1000; w: 120; h: 150), + (x: 1700; y: 1850; w: 120; h: 175), + (x: 2048; y: 2100; w: 120; h: 175), + (x: NTPX; y: 0; w: 1; h: 1), + (x: 2048; y: 2100; w: 120; h: 150), + (x: 2400; y: 1850; w: 120; h: 150), + (x: 2600; y: 1000; w: 120; h: 175), + (x: 2800; y: 900; w: 120; h: 150), + (x: 3000; y: 600; w: 120; h: 150), + (x: 3200; y: 400; w: 120; h: 150), + (x: 3300; y: 1200; w: 120; h: 150), + (x: 3400; y: 2100; w: 120; h: 175), + (x: NTPX; y: 0; w: 1; h: 1), + (x: 1450; y: 700; w: 125; h: 125), + (x: 1850; y: 500; w: 125; h: 125), + (x: 2250; y: 500; w: 125; h: 125), + (x: 2500; y: 700; w: 125; h: 125), + (x: NTPX; y: 0; w: 1; h: 1), + (x: 1550; y: 1500; w: 125; h: 125), + (x: 1830; y: 1150; w: 125; h: 125), + (x: 2260; y: 1000; w: 125; h: 125), + (x: 2250; y: 1400; w: 125; h: 125), + (x: NTPX; y: 0; w: 1; h: 1) ); Template37FPoints: array[0..0] of TPoint = ( - (X: 2047; Y: 0) + (x: 2047; y: 0) ); // attempt to make a series of moderate hills/valleys - was before I really figured out the whole probabilities thing +// fixed much much later by unC0Rr during tempaltes review for new generator const Template38Points: array[0..16] of TSDL_Rect = ( (x: 100; y: 2100; w: 1; h: 1), - (x: 100; y: 1600; w: 300; h: 500), - (x: 400; y: 600; w: 300; h: 1500), - (x: 700; y: 1600; w: 300; h: 600), - (x: 1000; y: 1800; w: 300; h: 300), - (x: 1300; y: 500; w: 300; h: 1600), - (x: 1600; y: 1700; w: 300; h: 400), - (x: 1600; y: 1600; w: 300; h: 500), - (x: 1600; y: 1400; w: 300; h: 700), - (x: 2200; y: 300; w: 300; h: 1800), - (x: 2500; y: 1500; w: 300; h: 600), - (x: 2800; y: 1900; w: 300; h: 200), - (x: 3100; y: 1600; w: 300; h: 500), - (x: 3400; y: 600; w: 300; h: 1500), - (x: 3700; y: 1800; w: 200; h: 300), + (x: 100; y: 1600; w: 250; h: 500), + (x: 400; y: 600; w: 250; h: 1500), + (x: 700; y: 1600; w: 250; h: 600), + (x: 1000; y: 1800; w: 250; h: 300), + (x: 1300; y: 500; w: 250; h: 1600), + (x: 1600; y: 1700; w: 150; h: 400), + (x: 1800; y: 1600; w: 150; h: 500), + (x: 2000; y: 1400; w: 150; h: 700), + (x: 2200; y: 300; w: 250; h: 1800), + (x: 2500; y: 1500; w: 250; h: 600), + (x: 2800; y: 1900; w: 250; h: 200), + (x: 3100; y: 1600; w: 250; h: 500), + (x: 3400; y: 600; w: 250; h: 1500), + (x: 3700; y: 1800; w: 150; h: 300), (x: 3700; y: 2100; w: 1; h: 1), (x: NTPX; y: 0; w: 1; h: 1) ); Template38FPoints: array[0..0] of TPoint = ( - (X: 2047; Y: 0) + (x: 2047; y: 0) ); // 8 tiny islands @@ -1437,7 +1438,7 @@ ); Template39FPoints: array[0..0] of TPoint = ( - (X: 512; Y: 0) + (x: 512; y: 0) ); const Template40Points: array[0..7] of TSDL_Rect = ( @@ -1452,10 +1453,10 @@ ); Template40FPoints: array[0..0] of TPoint = ( - (X: 512; Y: 0) + (x: 512; y: 0) ); // Many islands -const Template41Points: array[0..86] of TSDL_Rect = +const Template41Points: array[0..85] of TSDL_Rect = ( (x: 95; y: 500; w: 26; h: 26), (x: 100; y: 275; w: 50; h: 125), @@ -1472,31 +1473,31 @@ (x: 1350; y: 300; w: 50; h: 75), (x: 1400; y: 575; w: 50; h: 75), (x: NTPX; y: 0; w: 1; h: 1), - (x: 525; y:1050; w: 75; h: 75), + (x: 725; y:1050; w: 75; h: 75), (x: 700; y: 800; w: 125; h: 175), - (x: 950; y: 900; w: 125; h: 175), - (x: 1100; y:1100; w: 75; h: 75), + (x: 950; y: 800; w: 125; h: 175), + (x: 1000; y:1100; w: 75; h: 75), (x: NTPX; y: 0; w: 1; h: 1), (x: 175; y:1500; w: 26; h: 26), - (x: 210; y:1400; w: 30; h: 50), - (x: 240; y:1400; w: 30; h: 50), + (x: 180; y:1400; w: 30; h: 50), + (x: 250; y:1400; w: 30; h: 50), (x: 275; y:1510; w: 26; h: 26), (x: NTPX; y: 0; w: 1; h: 1), - (x: 450; y:1800; w: 125; h: 125), - (x: 600; y:1750; w: 125; h: 125), - (x: 750; y:1750; w: 125; h: 125), + (x: 500; y:1800; w: 125; h: 125), + (x: 600; y:1650; w: 125; h: 125), + (x: 750; y:1650; w: 125; h: 125), (x: 950; y:1850; w: 125; h: 125), (x: NTPX; y: 0; w: 1; h: 1), (x: 1075; y:1450; w: 26; h: 26), - (x: 1110; y:1300; w: 30; h: 50), - (x: 1140; y:1300; w: 30; h: 50), + (x: 1100; y:1300; w: 30; h: 50), + (x: 1150; y:1300; w: 30; h: 50), (x: 1175; y:1430; w: 26; h: 26), (x: NTPX; y: 0; w: 1; h: 1), (x: 1600; y:1250; w: 50; h: 125), - (x: 1700; y:1150; w: 50; h: 125), + (x: 1700; y: 950; w: 50; h: 125), (x: 1850; y: 500; w: 75; h: 125), (x: 1950; y: 550; w: 75; h: 175), - (x: 2250; y:1150; w: 50; h: 125), + (x: 2250; y: 950; w: 50; h: 125), (x: 2350; y:1250; w: 50; h: 125), (x: NTPX; y: 0; w: 1; h: 1), (x: 1750; y:2010; w: 26; h: 26), @@ -1510,27 +1511,27 @@ (x: 2700; y:1690; w: 26; h: 26), (x: NTPX; y: 0; w: 1; h: 1), (x: 2000; y: 125; w: 26; h: 26), - (x: 2050; y: 50; w: 50; h: 50), + (x: 2000; y: 50; w: 50; h: 50), (x: 2100; y: 50; w: 50; h: 50), (x: 2150; y: 150; w: 26; h: 26), (x: NTPX; y: 0; w: 1; h: 1), - (x: 2600; y: 250; w: 50; h: 125), - (x: 2750; y: 400; w: 75; h: 75), - (x: 2900; y: 525; w: 75; h: 75), - (x: 3150; y: 550; w: 75; h: 125), + (x: 2600; y: 350; w: 50; h: 125), + (x: 2750; y: 250; w: 75; h: 75), + (x: 3200; y: 525; w: 75; h: 75), + (x: 2750; y: 550; w: 75; h: 125), (x: NTPX; y: 0; w: 1; h: 1), (x: 2800; y:1150; w: 26; h: 26), - (x: 2840; y: 950; w: 50; h: 50), + (x: 2770; y: 950; w: 50; h: 50), (x: 2880; y: 950; w: 50; h: 50), (x: 2900; y:1150; w: 26; h: 26), (x: NTPX; y: 0; w: 1; h: 1), (x: 3075; y:1985; w: 26; h: 26), - (x: 3325; y:1700; w: 75; h: 125), + (x: 3255; y:1700; w: 75; h: 125), (x: 3475; y:1700; w: 75; h: 125), (x: 3625; y:1985; w: 26; h: 26), (x: NTPX; y: 0; w: 1; h: 1), (x: 3200; y:1450; w: 26; h: 26), - (x: 3240; y:1350; w: 50; h: 50), + (x: 3140; y:1350; w: 50; h: 50), (x: 3280; y:1350; w: 50; h: 50), (x: 3300; y:1450; w: 26; h: 26), (x: NTPX; y: 0; w: 1; h: 1), @@ -1540,14 +1541,13 @@ (x: 3900; y:1000; w: 50; h: 75), (x: NTPX; y: 0; w: 1; h: 1), (x: 3800; y: 200; w: 50; h: 75), - (x: 3875; y: 100; w: 75; h: 75), - (x: 3925; y: 50; w: 75; h: 50), - (x: 4050; y: 125; w: 50; h: 75), + (x: 3975; y: 50; w: 75; h: 50), + (x: 4010; y: 225; w: 50; h: 75), (x: NTPX; y: 0; w: 1; h: 1) - ); + ); Template41FPoints: array[0..0] of TPoint = ( - (X: 2047; Y: 0) + (x: 2047; y: 0) ); // 2 tiny islands const Template42Points: array[0..13] of TSDL_Rect = @@ -1569,10 +1569,10 @@ ); Template42FPoints: array[0..0] of TPoint = ( - (X: 512; Y: 0) + (x: 512; y: 0) ); // Many islands -const Template43Points: array[0..173] of TSDL_Rect = +const Template43Points: array[0..172] of TSDL_Rect = ( (x: 95; y: 500; w: 26; h: 26), (x: 100; y: 275; w: 50; h: 125), @@ -1589,31 +1589,31 @@ (x: 1350; y: 300; w: 50; h: 75), (x: 1400; y: 575; w: 50; h: 75), (x: NTPX; y: 0; w: 1; h: 1), - (x: 525; y:1050; w: 75; h: 75), + (x: 725; y:1050; w: 75; h: 75), (x: 700; y: 800; w: 125; h: 175), - (x: 950; y: 900; w: 125; h: 175), - (x: 1100; y:1100; w: 75; h: 75), + (x: 950; y: 800; w: 125; h: 175), + (x: 1000; y:1100; w: 75; h: 75), (x: NTPX; y: 0; w: 1; h: 1), (x: 175; y:1500; w: 26; h: 26), - (x: 210; y:1400; w: 30; h: 50), - (x: 240; y:1400; w: 30; h: 50), + (x: 180; y:1400; w: 30; h: 50), + (x: 250; y:1400; w: 30; h: 50), (x: 275; y:1510; w: 26; h: 26), (x: NTPX; y: 0; w: 1; h: 1), - (x: 450; y:1800; w: 125; h: 125), - (x: 600; y:1750; w: 125; h: 125), - (x: 750; y:1750; w: 125; h: 125), + (x: 500; y:1800; w: 125; h: 125), + (x: 600; y:1650; w: 125; h: 125), + (x: 750; y:1650; w: 125; h: 125), (x: 950; y:1850; w: 125; h: 125), (x: NTPX; y: 0; w: 1; h: 1), (x: 1075; y:1450; w: 26; h: 26), - (x: 1110; y:1300; w: 30; h: 50), - (x: 1140; y:1300; w: 30; h: 50), + (x: 1100; y:1300; w: 30; h: 50), + (x: 1150; y:1300; w: 30; h: 50), (x: 1175; y:1430; w: 26; h: 26), (x: NTPX; y: 0; w: 1; h: 1), (x: 1600; y:1250; w: 50; h: 125), - (x: 1700; y:1150; w: 50; h: 125), + (x: 1700; y: 950; w: 50; h: 125), (x: 1850; y: 500; w: 75; h: 125), (x: 1950; y: 550; w: 75; h: 175), - (x: 2250; y:1150; w: 50; h: 125), + (x: 2250; y: 950; w: 50; h: 125), (x: 2350; y:1250; w: 50; h: 125), (x: NTPX; y: 0; w: 1; h: 1), (x: 1750; y:2010; w: 26; h: 26), @@ -1627,27 +1627,27 @@ (x: 2700; y:1690; w: 26; h: 26), (x: NTPX; y: 0; w: 1; h: 1), (x: 2000; y: 125; w: 26; h: 26), - (x: 2050; y: 50; w: 50; h: 50), + (x: 2000; y: 50; w: 50; h: 50), (x: 2100; y: 50; w: 50; h: 50), (x: 2150; y: 150; w: 26; h: 26), (x: NTPX; y: 0; w: 1; h: 1), - (x: 2600; y: 250; w: 50; h: 125), - (x: 2750; y: 400; w: 75; h: 75), - (x: 2900; y: 525; w: 75; h: 75), - (x: 3150; y: 550; w: 75; h: 125), + (x: 2600; y: 350; w: 50; h: 125), + (x: 2750; y: 250; w: 75; h: 75), + (x: 3200; y: 525; w: 75; h: 75), + (x: 2750; y: 550; w: 75; h: 125), (x: NTPX; y: 0; w: 1; h: 1), (x: 2800; y:1150; w: 26; h: 26), - (x: 2840; y: 950; w: 50; h: 50), + (x: 2770; y: 950; w: 50; h: 50), (x: 2880; y: 950; w: 50; h: 50), (x: 2900; y:1150; w: 26; h: 26), (x: NTPX; y: 0; w: 1; h: 1), (x: 3075; y:1985; w: 26; h: 26), - (x: 3325; y:1700; w: 75; h: 125), + (x: 3255; y:1700; w: 75; h: 125), (x: 3475; y:1700; w: 75; h: 125), (x: 3625; y:1985; w: 26; h: 26), (x: NTPX; y: 0; w: 1; h: 1), (x: 3200; y:1450; w: 26; h: 26), - (x: 3240; y:1350; w: 50; h: 50), + (x: 3140; y:1350; w: 50; h: 50), (x: 3280; y:1350; w: 50; h: 50), (x: 3300; y:1450; w: 26; h: 26), (x: NTPX; y: 0; w: 1; h: 1), @@ -1657,9 +1657,8 @@ (x: 3900; y:1000; w: 50; h: 75), (x: NTPX; y: 0; w: 1; h: 1), (x: 3800; y: 200; w: 50; h: 75), - (x: 3875; y: 100; w: 75; h: 75), - (x: 3925; y: 50; w: 75; h: 50), - (x: 4050; y: 125; w: 50; h: 75), + (x: 3975; y: 50; w: 75; h: 50), + (x: 4010; y: 225; w: 50; h: 75), (x: NTPX; y: 0; w: 1; h: 1), (x: 95; y:2548; w: 26; h: 26), (x: 100; y:2323; w: 50; h: 125), @@ -1751,7 +1750,7 @@ ); Template43FPoints: array[0..0] of TPoint = ( - (X: 4095; Y: 0) + (x: 4095; y: 0) ); // 3 large caverns @@ -1775,12 +1774,12 @@ ); Template44FPoints: array[0..5] of TSDL_Rect = ( - (X: 1; Y: 90; w: 0; h: 0), - (X: 1; Y: 500; w: 0; h: 0), - (X:4095; Y: 500; w: 0; h: 0), - (X: 1; Y:1200; w: 0; h: 0), - (X:4095; Y:1200; w: 0; h: 0), - (X: 1; Y:2010; w: 0; h: 0) + (x: 1; y: 90; w: 0; h: 0), + (x: 1; y: 500; w: 0; h: 0), + (x:4095; y: 500; w: 0; h: 0), + (x: 1; y:1200; w: 0; h: 0), + (x:4095; y:1200; w: 0; h: 0), + (x: 1; y:2010; w: 0; h: 0) ); // large caverns with an island @@ -1801,17 +1800,47 @@ ); Template45FPoints: array[0..2] of TSDL_Rect = ( - (X: 1; Y: 1; w: 0; h: 0), - (X: 1; Y:2047; w: 0; h: 0), - (X:1005; Y: 805; w: 0; h: 0) + (x: 1; y: 1; w: 0; h: 0), + (x: 1; y:2047; w: 0; h: 0), + (x:1005; y: 805; w: 0; h: 0) ); -//////////////////////////////////////////////////////////////////////// -var EdgeTemplates: array[0..45] of TEdgeTemplate = + +const Template46Points: array[0..19] of TSDL_Rect = ( - (BasePoints: @Template0Points; + (x: 800; y: 1424; w: 1; h: 1), + (x: 800; y: 1224; w: 1; h: 1), + (x: 2200; y: 1224; w: 1; h: 1), + (x: 2200; y: 1424; w: 1; h: 1), + (x: NTPX; y: 0; w: 1; h: 1), + (x: 800; y: 1024; w: 1; h: 1), + (x: 800; y: 844; w: 1; h: 1), + (x: 2200; y: 844; w: 1; h: 1), + (x: 2200; y: 1024; w: 1; h: 1), + (x: NTPX; y: 0; w: 1; h: 1), + (x: 800; y: 664; w: 1; h: 1), + (x: 800; y: 484; w: 1; h: 1), + (x: 2200; y: 484; w: 1; h: 1), + (x: 2200; y: 664; w: 1; h: 1), + (x: NTPX; y: 0; w: 1; h: 1), + (x: 800; y: 304; w: 1; h: 1), + (x: 800; y: 104; w: 1; h: 1), + (x: 2200; y: 104; w: 1; h: 1), + (x: 2200; y: 304; w: 1; h: 1), + (x: NTPX; y: 0; w: 1; h: 1) + + ); + Template46FPoints: array[0..0] of TPoint = + ( + (x: 1023; y: 0) + ); + +//////////////////////////////////////////////////////////////////////// +var EdgeTemplates: array[0..46] of TEdgeTemplate = + ( + (BasePoints: PPointArray(@Template0Points); BasePointsCount: Succ(High(Template0Points)); - FillPoints: @Template0FPoints; + FillPoints: PPointArray(@Template0FPoints); FillPointsCount: Succ(High(Template0FPoints)); BezierizeCount: 3; RandPassesCount: 8; @@ -1820,9 +1849,9 @@ hasGirders: true; MaxHedgeHogs: 18; ), - (BasePoints: @Template1Points; + (BasePoints: PPointArray(@Template1Points); BasePointsCount: Succ(High(Template1Points)); - FillPoints: @Template1FPoints; + FillPoints: PPointArray(@Template1FPoints); FillPointsCount: Succ(High(Template1FPoints)); BezierizeCount: 3; RandPassesCount: 7; @@ -1831,9 +1860,9 @@ hasGirders: true; MaxHedgeHogs: 18; ), - (BasePoints: @Template2Points; + (BasePoints: PPointArray(@Template2Points); BasePointsCount: Succ(High(Template2Points)); - FillPoints: @Template2FPoints; + FillPoints: PPointArray(@Template2FPoints); FillPointsCount: Succ(High(Template2FPoints)); BezierizeCount: 2; RandPassesCount: 6; @@ -1842,9 +1871,9 @@ hasGirders: true; MaxHedgeHogs: 18; ), - (BasePoints: @Template3Points; + (BasePoints: PPointArray(@Template3Points); BasePointsCount: Succ(High(Template3Points)); - FillPoints: @Template3FPoints; + FillPoints: PPointArray(@Template3FPoints); FillPointsCount: Succ(High(Template3FPoints)); BezierizeCount: 3; RandPassesCount: 4; @@ -1853,9 +1882,9 @@ hasGirders: true; MaxHedgeHogs: 18; ), - (BasePoints: @Template4Points; + (BasePoints: PPointArray(@Template4Points); BasePointsCount: Succ(High(Template4Points)); - FillPoints: @Template4FPoints; + FillPoints: PPointArray(@Template4FPoints); FillPointsCount: Succ(High(Template4FPoints)); BezierizeCount: 3; RandPassesCount: 4; @@ -1864,9 +1893,9 @@ hasGirders: true; MaxHedgeHogs: 18; ), - (BasePoints: @Template5Points; + (BasePoints: PPointArray(@Template5Points); BasePointsCount: Succ(High(Template5Points)); - FillPoints: @Template5FPoints; + FillPoints: PPointArray(@Template5FPoints); FillPointsCount: Succ(High(Template5FPoints)); BezierizeCount: 2; RandPassesCount: 8; @@ -1875,9 +1904,9 @@ hasGirders: true; MaxHedgeHogs: 18; ), - (BasePoints: @Template6Points; + (BasePoints: PPointArray(@Template6Points); BasePointsCount: Succ(High(Template6Points)); - FillPoints: @Template6FPoints; + FillPoints: PPointArray(@Template6FPoints); FillPointsCount: Succ(High(Template6FPoints)); BezierizeCount: 2; RandPassesCount: 5; @@ -1886,9 +1915,9 @@ hasGirders: true; MaxHedgeHogs: 18; ), - (BasePoints: @Template7Points; + (BasePoints: PPointArray(@Template7Points); BasePointsCount: Succ(High(Template7Points)); - FillPoints: @Template7FPoints; + FillPoints: PPointArray(@Template7FPoints); FillPointsCount: Succ(High(Template7FPoints)); BezierizeCount: 4; RandPassesCount: 4; @@ -1897,9 +1926,9 @@ hasGirders: true; MaxHedgeHogs: 18; ), - (BasePoints: @Template8Points; + (BasePoints: PPointArray(@Template8Points); BasePointsCount: Succ(High(Template8Points)); - FillPoints: @Template8FPoints; + FillPoints: PPointArray(@Template8FPoints); FillPointsCount: Succ(High(Template8FPoints)); BezierizeCount: 2; RandPassesCount: 7; @@ -1908,9 +1937,9 @@ hasGirders: true; MaxHedgeHogs: 18; ), - (BasePoints: @Template9Points; + (BasePoints: PPointArray(@Template9Points); BasePointsCount: Succ(High(Template9Points)); - FillPoints: @Template9FPoints; + FillPoints: PPointArray(@Template9FPoints); FillPointsCount: Succ(High(Template9FPoints)); BezierizeCount: 1; RandPassesCount: 5; @@ -1919,9 +1948,9 @@ hasGirders: true; MaxHedgeHogs: 18; ), - (BasePoints: @Template10Points; + (BasePoints: PPointArray(@Template10Points); BasePointsCount: Succ(High(Template10Points)); - FillPoints: @Template10FPoints; + FillPoints: PPointArray(@Template10FPoints); FillPointsCount: Succ(High(Template10FPoints)); BezierizeCount: 2; RandPassesCount: 6; @@ -1930,9 +1959,9 @@ hasGirders: true; MaxHedgeHogs: 18; ), - (BasePoints: @Template11Points; + (BasePoints: PPointArray(@Template11Points); BasePointsCount: Succ(High(Template11Points)); - FillPoints: @Template11FPoints; + FillPoints: PPointArray(@Template11FPoints); FillPointsCount: Succ(High(Template11FPoints)); BezierizeCount: 1; RandPassesCount: 8; @@ -1941,9 +1970,9 @@ hasGirders: true; MaxHedgeHogs: 18; ), - (BasePoints: @Template12Points; + (BasePoints: PPointArray(@Template12Points); BasePointsCount: Succ(High(Template12Points)); - FillPoints: @Template12FPoints; + FillPoints: PPointArray(@Template12FPoints); FillPointsCount: Succ(High(Template12FPoints)); BezierizeCount: 3; RandPassesCount: 8; @@ -1952,9 +1981,9 @@ hasGirders: true; MaxHedgeHogs: 18; ), - (BasePoints: @Template13Points; + (BasePoints: PPointArray(@Template13Points); BasePointsCount: Succ(High(Template13Points)); - FillPoints: @Template13FPoints; + FillPoints: PPointArray(@Template13FPoints); FillPointsCount: Succ(High(Template13FPoints)); BezierizeCount: 3; RandPassesCount: 5; @@ -1963,9 +1992,9 @@ hasGirders: true; MaxHedgeHogs: 18; ), - (BasePoints: @Template14Points; + (BasePoints: PPointArray(@Template14Points); BasePointsCount: Succ(High(Template14Points)); - FillPoints: @Template14FPoints; + FillPoints: PPointArray(@Template14FPoints); FillPointsCount: Succ(High(Template14FPoints)); BezierizeCount: 3; RandPassesCount: 7; @@ -1974,9 +2003,9 @@ hasGirders: true; MaxHedgeHogs: 18; ), - (BasePoints: @Template15Points; + (BasePoints: PPointArray(@Template15Points); BasePointsCount: Succ(High(Template15Points)); - FillPoints: @Template15FPoints; + FillPoints: PPointArray(@Template15FPoints); FillPointsCount: Succ(High(Template15FPoints)); BezierizeCount: 2; RandPassesCount: 6; @@ -1985,9 +2014,9 @@ hasGirders: true; MaxHedgeHogs: 18; ), - (BasePoints: @Template16Points; + (BasePoints: PPointArray(@Template16Points); BasePointsCount: Succ(High(Template16Points)); - FillPoints: @Template16FPoints; + FillPoints: PPointArray(@Template16FPoints); FillPointsCount: Succ(High(Template16FPoints)); BezierizeCount: 2; RandPassesCount: 6; @@ -1996,9 +2025,9 @@ hasGirders: true; MaxHedgeHogs: 18; ), - (BasePoints: @Template17Points; + (BasePoints: PPointArray(@Template17Points); BasePointsCount: Succ(High(Template17Points)); - FillPoints: @Template17FPoints; + FillPoints: PPointArray(@Template17FPoints); FillPointsCount: Succ(High(Template17FPoints)); BezierizeCount: 3; RandPassesCount: 7; @@ -2007,9 +2036,9 @@ hasGirders: true; MaxHedgeHogs: 18; ), - (BasePoints: @Template18Points; + (BasePoints: PPointArray(@Template18Points); BasePointsCount: Succ(High(Template18Points)); - FillPoints: @Template18FPoints; + FillPoints: PPointArray(@Template18FPoints); FillPointsCount: Succ(High(Template18FPoints)); BezierizeCount: 3; RandPassesCount: 8; @@ -2018,9 +2047,9 @@ hasGirders: true; MaxHedgeHogs: 36; ), - (BasePoints: @Template19Points; + (BasePoints: PPointArray(@Template19Points); BasePointsCount: Succ(High(Template19Points)); - FillPoints: @Template19FPoints; + FillPoints: PPointArray(@Template19FPoints); FillPointsCount: Succ(High(Template19FPoints)); BezierizeCount: 3; RandPassesCount: 7; @@ -2029,9 +2058,9 @@ hasGirders: true; MaxHedgeHogs: 36; ), - (BasePoints: @Template20Points; + (BasePoints: PPointArray(@Template20Points); BasePointsCount: Succ(High(Template20Points)); - FillPoints: @Template20FPoints; + FillPoints: PPointArray(@Template20FPoints); FillPointsCount: Succ(High(Template20FPoints)); BezierizeCount: 2; RandPassesCount: 6; @@ -2040,9 +2069,9 @@ hasGirders: true; MaxHedgeHogs: 36; ), - (BasePoints: @Template21Points; + (BasePoints: PPointArray(@Template21Points); BasePointsCount: Succ(High(Template21Points)); - FillPoints: @Template21FPoints; + FillPoints: PPointArray(@Template21FPoints); FillPointsCount: Succ(High(Template21FPoints)); BezierizeCount: 3; RandPassesCount: 4; @@ -2051,9 +2080,9 @@ hasGirders: true; MaxHedgeHogs: 36; ), - (BasePoints: @Template22Points; + (BasePoints: PPointArray(@Template22Points); BasePointsCount: Succ(High(Template22Points)); - FillPoints: @Template22FPoints; + FillPoints: PPointArray(@Template22FPoints); FillPointsCount: Succ(High(Template22FPoints)); BezierizeCount: 3; RandPassesCount: 4; @@ -2062,9 +2091,9 @@ hasGirders: true; MaxHedgeHogs: 36; ), - (BasePoints: @Template23Points; + (BasePoints: PPointArray(@Template23Points); BasePointsCount: Succ(High(Template23Points)); - FillPoints: @Template23FPoints; + FillPoints: PPointArray(@Template23FPoints); FillPointsCount: Succ(High(Template23FPoints)); BezierizeCount: 2; RandPassesCount: 8; @@ -2073,9 +2102,9 @@ hasGirders: true; MaxHedgeHogs: 36; ), - (BasePoints: @Template24Points; + (BasePoints: PPointArray(@Template24Points); BasePointsCount: Succ(High(Template24Points)); - FillPoints: @Template24FPoints; + FillPoints: PPointArray(@Template24FPoints); FillPointsCount: Succ(High(Template24FPoints)); BezierizeCount: 2; RandPassesCount: 5; @@ -2084,9 +2113,9 @@ hasGirders: true; MaxHedgeHogs: 36; ), - (BasePoints: @Template25Points; + (BasePoints: PPointArray(@Template25Points); BasePointsCount: Succ(High(Template25Points)); - FillPoints: @Template25FPoints; + FillPoints: PPointArray(@Template25FPoints); FillPointsCount: Succ(High(Template25FPoints)); BezierizeCount: 4; RandPassesCount: 4; @@ -2095,9 +2124,9 @@ hasGirders: true; MaxHedgeHogs: 36; ), - (BasePoints: @Template26Points; + (BasePoints: PPointArray(@Template26Points); BasePointsCount: Succ(High(Template26Points)); - FillPoints: @Template26FPoints; + FillPoints: PPointArray(@Template26FPoints); FillPointsCount: Succ(High(Template26FPoints)); BezierizeCount: 2; RandPassesCount: 7; @@ -2106,9 +2135,9 @@ hasGirders: true; MaxHedgeHogs: 36; ), - (BasePoints: @Template27Points; + (BasePoints: PPointArray(@Template27Points); BasePointsCount: Succ(High(Template27Points)); - FillPoints: @Template27FPoints; + FillPoints: PPointArray(@Template27FPoints); FillPointsCount: Succ(High(Template27FPoints)); BezierizeCount: 1; RandPassesCount: 5; @@ -2117,9 +2146,9 @@ hasGirders: true; MaxHedgeHogs: 36; ), - (BasePoints: @Template28Points; + (BasePoints: PPointArray(@Template28Points); BasePointsCount: Succ(High(Template28Points)); - FillPoints: @Template28FPoints; + FillPoints: PPointArray(@Template28FPoints); FillPointsCount: Succ(High(Template28FPoints)); BezierizeCount: 2; RandPassesCount: 6; @@ -2128,9 +2157,9 @@ hasGirders: true; MaxHedgeHogs: 36; ), - (BasePoints: @Template29Points; + (BasePoints: PPointArray(@Template29Points); BasePointsCount: Succ(High(Template29Points)); - FillPoints: @Template29FPoints; + FillPoints: PPointArray(@Template29FPoints); FillPointsCount: Succ(High(Template29FPoints)); BezierizeCount: 1; RandPassesCount: 8; @@ -2139,9 +2168,9 @@ hasGirders: true; MaxHedgeHogs: 36; ), - (BasePoints: @Template30Points; + (BasePoints: PPointArray(@Template30Points); BasePointsCount: Succ(High(Template30Points)); - FillPoints: @Template30FPoints; + FillPoints: PPointArray(@Template30FPoints); FillPointsCount: Succ(High(Template30FPoints)); BezierizeCount: 3; RandPassesCount: 8; @@ -2150,9 +2179,9 @@ hasGirders: true; MaxHedgeHogs: 36; ), - (BasePoints: @Template31Points; + (BasePoints: PPointArray(@Template31Points); BasePointsCount: Succ(High(Template31Points)); - FillPoints: @Template31FPoints; + FillPoints: PPointArray(@Template31FPoints); FillPointsCount: Succ(High(Template31FPoints)); BezierizeCount: 3; RandPassesCount: 5; @@ -2161,9 +2190,9 @@ hasGirders: true; MaxHedgeHogs: 36; ), - (BasePoints: @Template32Points; + (BasePoints: PPointArray(@Template32Points); BasePointsCount: Succ(High(Template32Points)); - FillPoints: @Template32FPoints; + FillPoints: PPointArray(@Template32FPoints); FillPointsCount: Succ(High(Template32FPoints)); BezierizeCount: 3; RandPassesCount: 7; @@ -2172,9 +2201,9 @@ hasGirders: true; MaxHedgeHogs: 36; ), - (BasePoints: @Template33Points; + (BasePoints: PPointArray(@Template33Points); BasePointsCount: Succ(High(Template33Points)); - FillPoints: @Template33FPoints; + FillPoints: PPointArray(@Template33FPoints); FillPointsCount: Succ(High(Template33FPoints)); BezierizeCount: 2; RandPassesCount: 6; @@ -2183,9 +2212,9 @@ hasGirders: true; MaxHedgeHogs: 36; ), - (BasePoints: @Template34Points; + (BasePoints: PPointArray(@Template34Points); BasePointsCount: Succ(High(Template34Points)); - FillPoints: @Template34FPoints; + FillPoints: PPointArray(@Template34FPoints); FillPointsCount: Succ(High(Template34FPoints)); BezierizeCount: 2; RandPassesCount: 6; @@ -2194,9 +2223,9 @@ hasGirders: true; MaxHedgeHogs: 36; ), - (BasePoints: @Template35Points; + (BasePoints: PPointArray(@Template35Points); BasePointsCount: Succ(High(Template35Points)); - FillPoints: @Template35FPoints; + FillPoints: PPointArray(@Template35FPoints); FillPointsCount: Succ(High(Template35FPoints)); BezierizeCount: 3; RandPassesCount: 7; @@ -2205,9 +2234,9 @@ hasGirders: true; MaxHedgeHogs: 36; ), - (BasePoints: @Template36Points; + (BasePoints: PPointArray(@Template36Points); BasePointsCount: Succ(High(Template36Points)); - FillPoints: @Template36FPoints; + FillPoints: PPointArray(@Template36FPoints); FillPointsCount: Succ(High(Template36FPoints)); BezierizeCount: 4; RandPassesCount: 12; @@ -2216,9 +2245,9 @@ hasGirders: false; MaxHedgeHogs: 32; ), - (BasePoints: @Template37Points; + (BasePoints: PPointArray(@Template37Points); BasePointsCount: Succ(High(Template37Points)); - FillPoints: @Template37FPoints; + FillPoints: PPointArray(@Template37FPoints); FillPointsCount: Succ(High(Template37FPoints)); BezierizeCount: 3; RandPassesCount: 3; @@ -2227,9 +2256,9 @@ hasGirders: true; MaxHedgeHogs: 48; ), - (BasePoints: @Template38Points; + (BasePoints: PPointArray(@Template38Points); BasePointsCount: Succ(High(Template38Points)); - FillPoints: @Template38FPoints; + FillPoints: PPointArray(@Template38FPoints); FillPointsCount: Succ(High(Template38FPoints)); BezierizeCount: 4; RandPassesCount: 4; @@ -2238,9 +2267,9 @@ hasGirders: true; MaxHedgeHogs: 48; ), - (BasePoints: @Template39Points; + (BasePoints: PPointArray(@Template39Points); BasePointsCount: Succ(High(Template39Points)); - FillPoints: @Template39FPoints; + FillPoints: PPointArray(@Template39FPoints); FillPointsCount: Succ(High(Template39FPoints)); BezierizeCount: 3; RandPassesCount: 3; @@ -2249,9 +2278,9 @@ hasGirders: false; MaxHedgeHogs: 8; ), - (BasePoints: @Template40Points; + (BasePoints: PPointArray(@Template40Points); BasePointsCount: Succ(High(Template40Points)); - FillPoints: @Template40FPoints; + FillPoints: PPointArray(@Template40FPoints); FillPointsCount: Succ(High(Template40FPoints)); BezierizeCount: 3; RandPassesCount: 3; @@ -2260,9 +2289,9 @@ hasGirders: false; MaxHedgeHogs: 8; ), - (BasePoints: @Template41Points; + (BasePoints: PPointArray(@Template41Points); BasePointsCount: Succ(High(Template41Points)); - FillPoints: @Template41FPoints; + FillPoints: PPointArray(@Template41FPoints); FillPointsCount: Succ(High(Template41FPoints)); BezierizeCount: 2; RandPassesCount: 9; @@ -2271,9 +2300,9 @@ hasGirders: true; MaxHedgeHogs: 48; ), - (BasePoints: @Template42Points; + (BasePoints: PPointArray(@Template42Points); BasePointsCount: Succ(High(Template42Points)); - FillPoints: @Template42FPoints; + FillPoints: PPointArray(@Template42FPoints); FillPointsCount: Succ(High(Template42FPoints)); BezierizeCount: 3; RandPassesCount: 3; @@ -2282,9 +2311,9 @@ hasGirders: false; MaxHedgeHogs: 8; ), - (BasePoints: @Template43Points; + (BasePoints: PPointArray(@Template43Points); BasePointsCount: Succ(High(Template43Points)); - FillPoints: @Template43FPoints; + FillPoints: PPointArray(@Template43FPoints); FillPointsCount: Succ(High(Template43FPoints)); BezierizeCount: 2; RandPassesCount: 9; @@ -2293,9 +2322,9 @@ hasGirders: true; MaxHedgeHogs: 48; ), - (BasePoints: @Template44Points; + (BasePoints: PPointArray(@Template44Points); BasePointsCount: Succ(High(Template44Points)); - FillPoints: @Template44FPoints; + FillPoints: PPointArray(@Template44FPoints); FillPointsCount: Succ(High(Template44FPoints)); BezierizeCount: 5; RandPassesCount: 3; @@ -2304,9 +2333,9 @@ hasGirders: false; MaxHedgeHogs: 48; ), - (BasePoints: @Template45Points; + (BasePoints: PPointArray(@Template45Points); BasePointsCount: Succ(High(Template45Points)); - FillPoints: @Template45FPoints; + FillPoints: PPointArray(@Template45FPoints); FillPointsCount: Succ(High(Template45FPoints)); BezierizeCount: 5; RandPassesCount: 7; @@ -2314,11 +2343,22 @@ canMirror: false; canFlip: false; isNegative: true; canInvert: false; hasGirders: false; MaxHedgeHogs: 48; + ), + (BasePoints: PPointArray(@Template46Points); + BasePointsCount: Succ(High(Template46Points)); + FillPoints: PPointArray(@Template46FPoints); + FillPointsCount: Succ(High(Template46FPoints)); + BezierizeCount: 2; + RandPassesCount: 8; + TemplateHeight: 1424; TemplateWidth: 3072; + canMirror: true; canFlip: false; isNegative: false; canInvert: false; + hasGirders: true; + MaxHedgeHogs: 18; ) ); const SmallTemplates: array[0..2] of Longword = ( 39, 40, 42 ); -const MediumTemplates: array[0..17] of Longword = - ( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 ); +const MediumTemplates: array[0..18] of Longword = + ( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 46 ); const LargeTemplates: array[0..20] of Longword = ( 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, diff -r 31570b766315 -r ed5a6478e710 hedgewars/uLandTexture.pas --- a/hedgewars/uLandTexture.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uLandTexture.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} @@ -30,9 +30,11 @@ procedure SetLandTexture; implementation -uses uConsts, GLunit, uTypes, uVariables, uTextures, uDebug, uRender; +uses uConsts, GLunit, uTypes, uVariables, uTextures, uDebug, uRender, uUtils; const TEXSIZE = 128; + // in avoid tile borders stretch the blurry texture by 1 pixel more + BLURRYLANDOVERLAP: real = 1 / TEXSIZE / 2.0; // 1 pixel divided by texsize and blurry land scale factor type TLandRecord = record shouldUpdate, landAdded: boolean; @@ -65,6 +67,7 @@ procedure UpdateLandTexture(X, Width, Y, Height: LongInt; landAdded: boolean); var tx, ty: Longword; + tSize : LongInt; begin if cOnlyStats then exit; if (Width <= 0) or (Height <= 0) then @@ -74,23 +77,25 @@ TryDo((Y >= 0) and (Y < LAND_HEIGHT), 'UpdateLandTexture: wrong Y parameter', true); TryDo(Y + Height <= LAND_HEIGHT, 'UpdateLandTexture: wrong Height parameter', true); - if (cReducedQuality and rqBlurryLand) = 0 then - for ty:= Y div TEXSIZE to (Y + Height - 1) div TEXSIZE do - for tx:= X div TEXSIZE to (X + Width - 1) div TEXSIZE do + tSize:= TEXSIZE; + + // land textures have half the size/resolution in blurry mode + if (cReducedQuality and rqBlurryLand) <> 0 then + tSize:= tSize * 2; + + for ty:= Y div tSize to (Y + Height - 1) div tSize do + for tx:= X div tSize to (X + Width - 1) div tSize do + begin + if not LandTextures[tx, ty].shouldUpdate then begin LandTextures[tx, ty].shouldUpdate:= true; - LandTextures[tx, ty].landAdded:= landAdded - end - else - for ty:= (Y div TEXSIZE) div 2 to ((Y + Height - 1) div TEXSIZE) div 2 do - for tx:= (X div TEXSIZE) div 2 to ((X + Width - 1) div TEXSIZE) div 2 do - begin - LandTextures[tx, ty].shouldUpdate:= true; - LandTextures[tx, ty].landAdded:= landAdded - end + inc(dirtyLandTexCount); + end; + LandTextures[tx, ty].landAdded:= landAdded + end; end; -procedure RealLandTexUpdate; +procedure RealLandTexUpdate(x1, x2, y1, y2: LongInt); var x, y, ty, tx, lx, ly : LongWord; isEmpty: boolean; begin @@ -107,12 +112,13 @@ end else *) - for x:= 0 to LANDTEXARW -1 do - for y:= 0 to LANDTEXARH - 1 do + for x:= x1 to x2 do + for y:= y1 to y2 do with LandTextures[x, y] do if shouldUpdate then begin shouldUpdate:= false; + dec(dirtyLandTexCount); isEmpty:= not landAdded; landAdded:= false; ty:= 0; @@ -123,13 +129,13 @@ while isEmpty and (ty < TEXSIZE) do begin isEmpty:= LandPixels[ly + ty, lx] and AMask = 0; - if isEmpty then isEmpty:= LandPixels[ly + ty, lx + TEXSIZE-1] and AMask = 0; + if isEmpty then isEmpty:= LandPixels[ly + ty, Pred(lx + TEXSIZE)] and AMask = 0; inc(ty) end; while isEmpty and (tx < TEXSIZE-1) do begin isEmpty:= LandPixels[ly, lx + tx] and AMask = 0; - if isEmpty then isEmpty:= LandPixels[ly + TEXSIZE-1, lx + tx] and AMask = 0; + if isEmpty then isEmpty:= LandPixels[Pred(ly + TEXSIZE), lx + tx] and AMask = 0; inc(tx) end; // then search every other remaining. does this sort of stuff defeat compiler opts? @@ -163,27 +169,90 @@ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TEXSIZE, TEXSIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, Pixels(x,y)); end else if tex <> nil then - begin - FreeTexture(tex); - tex:= nil - end; + FreeAndNilTexture(tex); + + // nothing else to do + if dirtyLandTexCount < 1 then + exit; end end; procedure DrawLand(dX, dY: LongInt); -var x, y: LongInt; +var x, y, tX, ty, tSize, fx, lx, fy, ly: LongInt; + tScale: GLfloat; + overlap: boolean; begin -RealLandTexUpdate; +// init values based on quality settings +if (cReducedQuality and rqBlurryLand) <> 0 then + begin + tSize:= TEXSIZE * 2; + tScale:= 2.0; + overlap:= (cReducedQuality and rqClampLess) <> 0; + end +else + begin + tSize:= TEXSIZE; + tScale:= 1.0; + overlap:= false; + end; + +// figure out visible area +// first column +tx:= ViewLeftX - dx; +fx:= tx div tSize; +if tx < 0 then dec(fx); +fx:= max(0, fx); + +// last column +tx:= ViewRightX - dx; +lx:= tx div tSize; +if tx < 0 then dec(lx); +lx:= min(LANDTEXARW -1, lx); -for x:= 0 to LANDTEXARW -1 do - for y:= 0 to LANDTEXARH - 1 do +// all offscreen +if (fx > lx) then + exit; + +// first row +ty:= ViewTopY - dy; +fy:= ty div tSize; +if ty < 0 then dec(fy); +fy:= max(0, fy); + +// last row +ty:= ViewBottomY - dy; +ly:= ty div tSize; +if ty < 0 then dec(ly); +ly:= min(LANDTEXARH -1, ly); + +// all offscreen +if (fy > ly) then + exit; + +// update visible areas of landtex before drawing +if dirtyLandTexCount > 0 then + RealLandTexUpdate(fx, lx, fy, ly); + +tX:= dX + tsize * fx; + +// loop through columns +for x:= fx to lx do + begin + // loop through textures in this column + for y:= fy to ly do with LandTextures[x, y] do if tex <> nil then - if (cReducedQuality and rqBlurryLand) = 0 then - DrawTexture(dX + x * TEXSIZE, dY + y * TEXSIZE, tex) + begin + ty:= dY + y * tSize; + if overlap then + DrawTexture2(tX, ty, tex, tScale, BLURRYLANDOVERLAP) else - DrawTexture(dX + x * TEXSIZE * 2, dY + y * TEXSIZE * 2, tex, 2.0) + DrawTexture(tX, ty, tex, tScale); + end; + // increment tX + inc(tX, tSize); + end; end; procedure SetLandTexture; @@ -212,13 +281,7 @@ for x:= 0 to LANDTEXARW - 1 do for y:= 0 to LANDTEXARH - 1 do with LandTextures[x, y] do - begin - if tex <> nil then - begin - FreeTexture(tex); - tex:= nil - end - end; + FreeAndNilTexture(tex); end; procedure freeModule; diff -r 31570b766315 -r ed5a6478e710 hedgewars/uLandUtils.pas --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hedgewars/uLandUtils.pas Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,87 @@ +unit uLandUtils; +interface + +procedure ResizeLand(width, height: LongWord); +procedure InitWorldEdges(); + +implementation +uses uUtils, uConsts, uVariables, uTypes; + +procedure ResizeLand(width, height: LongWord); +var potW, potH: LongInt; +begin +potW:= toPowerOf2(width); +potH:= toPowerOf2(height); +if (potW <> LAND_WIDTH) or (potH <> LAND_HEIGHT) then + begin + LAND_WIDTH:= potW; + LAND_HEIGHT:= potH; + LAND_WIDTH_MASK:= not(LAND_WIDTH-1); + LAND_HEIGHT_MASK:= not(LAND_HEIGHT-1); + cWaterLine:= LAND_HEIGHT; + if (cReducedQuality and rqBlurryLand) = 0 then + SetLength(LandPixels, LAND_HEIGHT, LAND_WIDTH) + else + SetLength(LandPixels, LAND_HEIGHT div 2, LAND_WIDTH div 2); + + SetLength(Land, LAND_HEIGHT, LAND_WIDTH); + SetLength(LandDirty, (LAND_HEIGHT div 32), (LAND_WIDTH div 32)); + // 0.5 is already approaching on unplayable + if (width div 4096 >= 2) or (height div 2048 >= 2) then cMaxZoomLevel:= cMaxZoomLevel/2; + cMinMaxZoomLevelDelta:= cMaxZoomLevel - cMinZoomLevel + end; +end; + +procedure InitWorldEdges(); +var cy, cx, lx, ly: LongInt; + found: boolean; +begin +playHeight:= LAND_HEIGHT; +topY:= 0; + +lx:= LongInt(LAND_WIDTH) - 1; + +if WorldEdge = weNone then + begin + playWidth:= LAND_WIDTH; + leftX := 0; + rightX:= lx; + EXIT; + end; + +ly:= LongInt(LAND_HEIGHT) - 1; + +// find most left land pixels and set leftX accordingly +found:= false; +for cx:= 0 to lx do + begin + for cy:= ly downto 0 do + if Land[cy, cx] <> 0 then + begin + leftX:= max(0, cx - cWorldEdgeDist); + // break out of both loops + found:= true; + break; + end; + if found then break; + end; + +// find most right land pixels and set rightX accordingly +found:= false; +for cx:= lx downto 0 do + begin + for cy:= ly downto 0 do + if Land[cy, cx] <> 0 then + begin + rightX:= min(lx, cx + cWorldEdgeDist); + // break out of both loops + found:= true; + break; + end; + if found then break; + end; + +playWidth := rightX + 1 - leftX; +end; + +end. diff -r 31570b766315 -r ed5a6478e710 hedgewars/uLocale.pas --- a/hedgewars/uLocale.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uLocale.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} @@ -30,7 +30,7 @@ function GetEventString(e: TEventId): ansistring; {$IFDEF HWLIBRARY} -procedure LoadLocaleWrapper(str: pchar); cdecl; export; +procedure LoadLocaleWrapper(path: pchar; filename: pchar); cdecl; export; {$ENDIF} implementation @@ -40,7 +40,7 @@ trevt_n: array[TEventId] of integer; procedure LoadLocale(FileName: shortstring); -var s: ansistring = ''; +var s: ansistring; f: pfsFile; a, b, c: LongInt; first: array[TEventId] of boolean; @@ -52,6 +52,8 @@ f:= pfsOpenRead(FileName); TryDo(f <> nil, 'Cannot load locale "' + FileName + '"', false); +s:= ''; + if f <> nil then begin while not pfsEof(f) do @@ -62,11 +64,16 @@ if (s[1] < '0') or (s[1] > '9') then continue; TryDo(Length(s) > 6, 'Load locale: empty string', true); + {$IFNDEF PAS2C} val(s[1]+s[2], a, c); - TryDo(c = 0, 'Load locale: numbers should be two-digit: ' + s, true); + TryDo(c = 0, ansistring('Load locale: numbers should be two-digit: ') + s, true); + val(s[4]+s[5], b, c); + TryDo(c = 0, ansistring('Load locale: numbers should be two-digit: ') + s, true); + {$ELSE} + val(s[1]+s[2], a); + val(s[4]+s[5], b); + {$ENDIF} TryDo(s[3] = ':', 'Load locale: ":" expected', true); - val(s[4]+s[5], b, c); - TryDo(c = 0, 'Load locale: numbers should be two-digit' + s, true); TryDo(s[6] = '=', 'Load locale: "=" expected', true); Delete(s, 1, 6); case a of @@ -126,9 +133,19 @@ end; {$IFDEF HWLIBRARY} -procedure LoadLocaleWrapper(str: pchar); cdecl; export; +procedure LoadLocaleWrapper(path: pchar; filename: pchar); cdecl; export; begin - LoadLocale(Strpas(str)); + PathPrefix := Strpas(path); + + uUtils.initModule(false); + uVariables.initModule; + uPhysFSLayer.initModule; + + LoadLocale(Strpas(filename)); + + uPhysFSLayer.freeModule; + uVariables.freeModule; + uUtils.freeModule; end; {$ENDIF} diff -r 31570b766315 -r ed5a6478e710 hedgewars/uMatrix.pas --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hedgewars/uMatrix.pas Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,270 @@ +(* + * Hedgewars, a free turn based strategy game + * Copyright (c) 2004-2012 Andrey Korotaev + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + *) + +{$INCLUDE "options.inc"} + +unit uMatrix; + +interface + +uses uTypes {$IFNDEF PAS2C}, gl{$ENDIF}; + +const + MATRIX_MODELVIEW:Integer = 0; + MATRIX_PROJECTION:Integer = 1; + +procedure MatrixLoadIdentity(out Result: TMatrix4x4f); +procedure MatrixMultiply(out Result: TMatrix4x4f; const lhs, rhs: TMatrix4x4f); + +procedure hglMatrixMode(t: Integer); +procedure hglLoadIdentity(); +procedure hglPushMatrix(); +procedure hglPopMatrix(); +procedure hglMVP(var res : TMatrix4x4f); +procedure hglScalef(x: GLfloat; y: GLfloat; z: GLfloat); +procedure hglTranslatef(x: GLfloat; y: GLfloat; z: GLfloat); +procedure hglRotatef(a:GLfloat; x:GLfloat; y:GLfloat; z:GLfloat); +procedure initModule(); +procedure freeModule(); + +implementation + +uses uDebug; + +const + MATRIX_STACK_SIZE = 10; + +type + TMatrixStack = record + top:Integer; + stack: array[0..9] of TMatrix4x4f; + end; +var + MatrixStacks : array[0..1] of TMatrixStack; + CurMatrix: integer; + +procedure MatrixLoadIdentity(out Result: TMatrix4x4f); +begin + Result[0,0]:= 1.0; Result[1,0]:=0.0; Result[2,0]:=0.0; Result[3,0]:=0.0; + Result[0,1]:= 0.0; Result[1,1]:=1.0; Result[2,1]:=0.0; Result[3,1]:=0.0; + Result[0,2]:= 0.0; Result[1,2]:=0.0; Result[2,2]:=1.0; Result[3,2]:=0.0; + Result[0,3]:= 0.0; Result[1,3]:=0.0; Result[2,3]:=0.0; Result[3,3]:=1.0; +end; + +procedure hglMatrixMode(t: Integer); +begin + CurMatrix := t; +end; + +procedure hglLoadIdentity(); +begin + MatrixLoadIdentity(MatrixStacks[CurMatrix].stack[MatrixStacks[CurMatrix].top]); +end; + +procedure hglScalef(x: GLfloat; y: GLfloat; z: GLfloat); +var + m:TMatrix4x4f; + t:TMatrix4x4f; +begin + m[0,0]:=x;m[1,0]:=0;m[2,0]:=0;m[3,0]:=0; + m[0,1]:=0;m[1,1]:=y;m[2,1]:=0;m[3,1]:=0; + m[0,2]:=0;m[1,2]:=0;m[2,2]:=z;m[3,2]:=0; + m[0,3]:=0;m[1,3]:=0;m[2,3]:=0;m[3,3]:=1; + + MatrixMultiply(t, MatrixStacks[CurMatrix].stack[MatrixStacks[CurMatrix].top], m); + MatrixStacks[CurMatrix].stack[MatrixStacks[CurMatrix].top] := t; +end; + +procedure hglTranslatef(x: GLfloat; y: GLfloat; z: GLfloat); +var + m:TMatrix4x4f; + t:TMatrix4x4f; +begin + m[0,0]:=1;m[1,0]:=0;m[2,0]:=0;m[3,0]:=x; + m[0,1]:=0;m[1,1]:=1;m[2,1]:=0;m[3,1]:=y; + m[0,2]:=0;m[1,2]:=0;m[2,2]:=1;m[3,2]:=z; + m[0,3]:=0;m[1,3]:=0;m[2,3]:=0;m[3,3]:=1; + + MatrixMultiply(t, MatrixStacks[CurMatrix].stack[MatrixStacks[CurMatrix].top], m); + MatrixStacks[CurMatrix].stack[MatrixStacks[CurMatrix].top] := t; +end; + +procedure hglRotatef(a:GLfloat; x:GLfloat; y:GLfloat; z:GLfloat); +var + m:TMatrix4x4f; + t:TMatrix4x4f; + c:GLfloat; + s:GLfloat; + xn, yn, zn:GLfloat; + l:GLfloat; +begin + a:=a * 3.14159265368 / 180; + c:=cos(a); + s:=sin(a); + + l := 1.0 / sqrt(x * x + y * y + z * z); + xn := x * l; + yn := y * l; + zn := z * l; + + m[0,0]:=c + xn * xn * (1 - c); + m[1,0]:=xn * yn * (1 - c) - zn * s; + m[2,0]:=xn * zn * (1 - c) + yn * s; + m[3,0]:=0; + + + m[0,1]:=yn * xn * (1 - c) + zn * s; + m[1,1]:=c + yn * yn * (1 - c); + m[2,1]:=yn * zn * (1 - c) - xn * s; + m[3,1]:=0; + + m[0,2]:=zn * xn * (1 - c) - yn * s; + m[1,2]:=zn * yn * (1 - c) + xn * s; + m[2,2]:=c + zn * zn * (1 - c); + m[3,2]:=0; + + m[0,3]:=0;m[1,3]:=0;m[2,3]:=0;m[3,3]:=1; + + MatrixMultiply(t, MatrixStacks[CurMatrix].stack[MatrixStacks[CurMatrix].top], m); + MatrixStacks[CurMatrix].stack[MatrixStacks[CurMatrix].top] := t; +end; + +procedure hglMVP(var res: TMatrix4x4f); +begin + MatrixMultiply(res, + MatrixStacks[MATRIX_PROJECTION].stack[MatrixStacks[MATRIX_PROJECTION].top], + MatrixStacks[MATRIX_MODELVIEW].stack[MatrixStacks[MATRIX_MODELVIEW].top]); +end; + +procedure hglPushMatrix(); +var + t: Integer; +begin + t := MatrixStacks[CurMatrix].top; + MatrixStacks[CurMatrix].stack[t + 1] := MatrixStacks[CurMatrix].stack[t]; + inc(t); + MatrixStacks[CurMatrix].top := t; +end; + +procedure hglPopMatrix(); +var + t: Integer; +begin + t := MatrixStacks[CurMatrix].top; + dec(t); + MatrixStacks[CurMatrix].top := t; +end; + +procedure initModule(); +begin + MatrixStacks[MATRIX_MODELVIEW].top := 0; + MatrixStacks[MATRIX_Projection].top := 0; + MatrixLoadIdentity(MatrixStacks[MATRIX_MODELVIEW].stack[0]); + MatrixLoadIdentity(MatrixStacks[MATRIX_PROJECTION].stack[0]); +end; + +procedure freeModule(); +begin +end; + +procedure MatrixMultiply(out Result: TMatrix4x4f; const lhs, rhs: TMatrix4x4f); +var + test: TMatrix4x4f; + i, j: Integer; + error: boolean; +begin + Result[0,0]:=lhs[0,0]*rhs[0,0] + lhs[1,0]*rhs[0,1] + lhs[2,0]*rhs[0,2] + lhs[3,0]*rhs[0,3]; + Result[0,1]:=lhs[0,1]*rhs[0,0] + lhs[1,1]*rhs[0,1] + lhs[2,1]*rhs[0,2] + lhs[3,1]*rhs[0,3]; + Result[0,2]:=lhs[0,2]*rhs[0,0] + lhs[1,2]*rhs[0,1] + lhs[2,2]*rhs[0,2] + lhs[3,2]*rhs[0,3]; + Result[0,3]:=lhs[0,3]*rhs[0,0] + lhs[1,3]*rhs[0,1] + lhs[2,3]*rhs[0,2] + lhs[3,3]*rhs[0,3]; + + Result[1,0]:=lhs[0,0]*rhs[1,0] + lhs[1,0]*rhs[1,1] + lhs[2,0]*rhs[1,2] + lhs[3,0]*rhs[1,3]; + Result[1,1]:=lhs[0,1]*rhs[1,0] + lhs[1,1]*rhs[1,1] + lhs[2,1]*rhs[1,2] + lhs[3,1]*rhs[1,3]; + Result[1,2]:=lhs[0,2]*rhs[1,0] + lhs[1,2]*rhs[1,1] + lhs[2,2]*rhs[1,2] + lhs[3,2]*rhs[1,3]; + Result[1,3]:=lhs[0,3]*rhs[1,0] + lhs[1,3]*rhs[1,1] + lhs[2,3]*rhs[1,2] + lhs[3,3]*rhs[1,3]; + + Result[2,0]:=lhs[0,0]*rhs[2,0] + lhs[1,0]*rhs[2,1] + lhs[2,0]*rhs[2,2] + lhs[3,0]*rhs[2,3]; + Result[2,1]:=lhs[0,1]*rhs[2,0] + lhs[1,1]*rhs[2,1] + lhs[2,1]*rhs[2,2] + lhs[3,1]*rhs[2,3]; + Result[2,2]:=lhs[0,2]*rhs[2,0] + lhs[1,2]*rhs[2,1] + lhs[2,2]*rhs[2,2] + lhs[3,2]*rhs[2,3]; + Result[2,3]:=lhs[0,3]*rhs[2,0] + lhs[1,3]*rhs[2,1] + lhs[2,3]*rhs[2,2] + lhs[3,3]*rhs[2,3]; + + Result[3,0]:=lhs[0,0]*rhs[3,0] + lhs[1,0]*rhs[3,1] + lhs[2,0]*rhs[3,2] + lhs[3,0]*rhs[3,3]; + Result[3,1]:=lhs[0,1]*rhs[3,0] + lhs[1,1]*rhs[3,1] + lhs[2,1]*rhs[3,2] + lhs[3,1]*rhs[3,3]; + Result[3,2]:=lhs[0,2]*rhs[3,0] + lhs[1,2]*rhs[3,1] + lhs[2,2]*rhs[3,2] + lhs[3,2]*rhs[3,3]; + Result[3,3]:=lhs[0,3]*rhs[3,0] + lhs[1,3]*rhs[3,1] + lhs[2,3]*rhs[3,2] + lhs[3,3]*rhs[3,3]; + +{ + Result[0,0]:=lhs[0,0]*rhs[0,0] + lhs[1,0]*rhs[0,1] + lhs[2,0]*rhs[0,2] + lhs[3,0]*rhs[0,3]; + Result[0,1]:=lhs[0,0]*rhs[1,0] + lhs[1,0]*rhs[1,1] + lhs[2,0]*rhs[1,2] + lhs[3,0]*rhs[1,3]; + Result[0,2]:=lhs[0,0]*rhs[2,0] + lhs[1,0]*rhs[2,1] + lhs[2,0]*rhs[2,2] + lhs[3,0]*rhs[2,3]; + Result[0,3]:=lhs[0,0]*rhs[3,0] + lhs[1,0]*rhs[3,1] + lhs[2,0]*rhs[3,2] + lhs[3,0]*rhs[3,3]; + + Result[1,0]:=lhs[0,1]*rhs[0,0] + lhs[1,1]*rhs[0,1] + lhs[2,1]*rhs[0,2] + lhs[3,1]*rhs[0,3]; + Result[1,1]:=lhs[0,1]*rhs[1,0] + lhs[1,1]*rhs[1,1] + lhs[2,1]*rhs[1,2] + lhs[3,1]*rhs[1,3]; + Result[1,2]:=lhs[0,1]*rhs[2,0] + lhs[1,1]*rhs[2,1] + lhs[2,1]*rhs[2,2] + lhs[3,1]*rhs[2,3]; + Result[1,3]:=lhs[0,1]*rhs[3,0] + lhs[1,1]*rhs[3,1] + lhs[2,1]*rhs[3,2] + lhs[3,1]*rhs[3,3]; + + Result[2,0]:=lhs[0,2]*rhs[0,0] + lhs[1,2]*rhs[0,1] + lhs[2,2]*rhs[0,2] + lhs[3,2]*rhs[0,3]; + Result[2,1]:=lhs[0,2]*rhs[1,0] + lhs[1,2]*rhs[1,1] + lhs[2,2]*rhs[1,2] + lhs[3,2]*rhs[1,3]; + Result[2,2]:=lhs[0,2]*rhs[2,0] + lhs[1,2]*rhs[2,1] + lhs[2,2]*rhs[2,2] + lhs[3,2]*rhs[2,3]; + Result[2,3]:=lhs[0,2]*rhs[3,0] + lhs[1,2]*rhs[3,1] + lhs[2,2]*rhs[3,2] + lhs[3,2]*rhs[3,3]; + + Result[3,0]:=lhs[0,3]*rhs[0,0] + lhs[1,3]*rhs[0,1] + lhs[2,3]*rhs[0,2] + lhs[3,3]*rhs[0,3]; + Result[3,1]:=lhs[0,3]*rhs[1,0] + lhs[1,3]*rhs[1,1] + lhs[2,3]*rhs[1,2] + lhs[3,3]*rhs[1,3]; + Result[3,2]:=lhs[0,3]*rhs[2,0] + lhs[1,3]*rhs[2,1] + lhs[2,3]*rhs[2,2] + lhs[3,3]*rhs[2,3]; + Result[3,3]:=lhs[0,3]*rhs[3,0] + lhs[1,3]*rhs[3,1] + lhs[2,3]*rhs[3,2] + lhs[3,3]*rhs[3,3]; +} + + glPushMatrix; + glLoadMatrixf(@lhs[0, 0]); + glMultMatrixf(@rhs[0, 0]); + glGetFloatv(GL_MODELVIEW_MATRIX, @test[0, 0]); + glPopMatrix; + + error:=false; + for i:=0 to 3 do + for j:=0 to 3 do + if Abs(test[i, j] - Result[i, j]) > 0.000001 then + error:=true; + + {$IFNDEF PAS2C} + if error then + begin + writeln('shall:'); + for i:=0 to 3 do + begin + for j:=0 to 3 do + write(test[i, j]); + writeln; + end; + + writeln('is:'); + for i:=0 to 3 do + begin + for j:=0 to 3 do + write(Result[i, j]); + writeln; + end; + TryDo(false, 'error in matrix multiplication?!', true); + end; + {$ENDIF} + +end; + + +end. diff -r 31570b766315 -r ed5a6478e710 hedgewars/uMisc.pas --- a/hedgewars/uMisc.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uMisc.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} @@ -28,7 +28,7 @@ procedure movecursor(dx, dy: LongInt); function doSurfaceConversion(tmpsurf: PSDL_Surface): PSDL_Surface; -function MakeScreenshot(filename: shortstring; k: LongInt): boolean; +function MakeScreenshot(filename: shortstring; k: LongInt; dump: LongWord): boolean; function GetTeamStatString(p: PTeam): shortstring; function SDL_RectMake(x, y, width, height: LongInt): TSDL_Rect; inline; @@ -44,7 +44,7 @@ size: QWord; end; -var conversionFormat: PSDL_PixelFormat; +var conversionFormat : PSDL_PixelFormat; procedure movecursor(dx, dy: LongInt); var x, y: LongInt; @@ -63,7 +63,7 @@ var i: LongInt; png_ptr: ^png_struct; info_ptr: ^png_info; - f: file; + f: File; image: PScreenshot; begin image:= PScreenshot(screenshot); @@ -136,6 +136,7 @@ ); image: PScreenshot; size: QWord; + writeResult:LongInt; begin image:= PScreenshot(screenshot); @@ -163,8 +164,8 @@ Rewrite(f, 1); if IOResult = 0 then begin - BlockWrite(f, head, sizeof(head)); - BlockWrite(f, image^.buffer^, size); + BlockWrite(f, head, sizeof(head), writeResult); + BlockWrite(f, image^.buffer^, size, writeResult); Close(f); end else @@ -216,12 +217,13 @@ // captures and saves the screen. returns true on success. // saved image will be k times smaller than original (useful for saving thumbnails). -function MakeScreenshot(filename: shortstring; k: LongInt): Boolean; +function MakeScreenshot(filename: shortstring; k: LongInt; dump: LongWord): boolean; var p: Pointer; size: QWord; image: PScreenshot; format: GLenum; ext: string[4]; + x,y: LongWord; begin {$IFDEF PNG_SCREENSHOTS} format:= GL_RGBA; @@ -231,7 +233,9 @@ ext:= '.bmp'; {$ENDIF} -size:= toPowerOf2(cScreenWidth) * toPowerOf2(cScreenHeight) * 4; +if dump > 0 then + size:= LAND_WIDTH*LAND_HEIGHT*4 +else size:= toPowerOf2(cScreenWidth) * toPowerOf2(cScreenHeight) * 4; p:= GetMem(size); // will be freed in SaveScreenshot() // memory could not be allocated @@ -242,18 +246,56 @@ exit; end; +// read pixels from land array +if dump > 0 then + begin + for y:= 0 to LAND_HEIGHT-1 do + for x:= 0 to LAND_WIDTH-1 do + if dump = 2 then + PLongWordArray(p)^[y*LAND_WIDTH+x]:= LandPixels[LAND_HEIGHT-1-y, x] + else + begin + if Land[LAND_HEIGHT-1-y, x] and lfIndestructible = lfIndestructible then + PLongWordArray(p)^[y*LAND_WIDTH+x]:= (AMask or RMask) + else if Land[LAND_HEIGHT-1-y, x] and lfIce = lfIce then + PLongWordArray(p)^[y*LAND_WIDTH+x]:= (AMask or BMask) + else if Land[LAND_HEIGHT-1-y, x] and lfBouncy = lfBouncy then + PLongWordArray(p)^[y*LAND_WIDTH+x]:= (AMask or GMask) + else if Land[LAND_HEIGHT-1-y, x] and lfObject = lfObject then + PLongWordArray(p)^[y*LAND_WIDTH+x]:= $FFFFFFFF + else if Land[LAND_HEIGHT-1-y, x] and lfBasic = lfBasic then + PLongWordArray(p)^[y*LAND_WIDTH+x]:= AMask + else + PLongWordArray(p)^[y*LAND_WIDTH+x]:= 0 + end + end +else // read pixels from the front buffer -glReadPixels(0, 0, cScreenWidth, cScreenHeight, format, GL_UNSIGNED_BYTE, p); - + begin + glReadPixels(0, 0, cScreenWidth, cScreenHeight, format, GL_UNSIGNED_BYTE, p); {$IFDEF USE_VIDEO_RECORDING} -ReduceImage(p, cScreenWidth, cScreenHeight, k); + ReduceImage(p, cScreenWidth, cScreenHeight, k) {$ENDIF} + end; // allocate and fill structure that will be passed to new thread New(image); // will be disposed in SaveScreenshot() -image^.filename:= UserPathPrefix + filename + ext; -image^.width:= cScreenWidth div k; -image^.height:= cScreenHeight div k; +if dump = 2 then + image^.filename:= shortstring(UserPathPrefix) + filename + '_landpixels' + ext +else if dump = 1 then + image^.filename:= shortstring(UserPathPrefix) + filename + '_land' + ext +else image^.filename:= shortstring(UserPathPrefix) + filename + ext; + +if dump <> 0 then + begin + image^.width:= LAND_WIDTH; + image^.height:= LAND_HEIGHT + end +else + begin + image^.width:= cScreenWidth div k; + image^.height:= cScreenHeight div k + end; image^.size:= size; image^.buffer:= p; @@ -284,7 +326,7 @@ end; function GetTeamStatString(p: PTeam): shortstring; -var s: ansistring; +var s: shortstring; begin s:= p^.TeamName + ':' + IntToStr(p^.TeamHealth) + ':'; GetTeamStatString:= s; diff -r 31570b766315 -r ed5a6478e710 hedgewars/uPhysFSLayer.pas --- a/hedgewars/uPhysFSLayer.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uPhysFSLayer.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,3 +1,5 @@ +{$INCLUDE "options.inc"} + unit uPhysFSLayer; interface @@ -34,21 +36,27 @@ procedure hedgewarsMountPackage(filename: PChar); cdecl; external PhyslayerLibName; implementation -uses uUtils, uVariables, sysutils; +uses uConsts, uUtils, uVariables{$IFNDEF PAS2C}, sysutils{$ELSE}, physfs{$ENDIF}; -function PHYSFS_init(argv0: PChar) : LongInt; cdecl; external PhysfsLibName; -function PHYSFS_deinit() : LongInt; cdecl; external PhysfsLibName; -function PHYSFSRWOPS_openRead(fname: PChar): PSDL_RWops; cdecl ; external PhyslayerLibName; +function PHYSFSRWOPS_openRead(fname: PChar): PSDL_RWops; cdecl; external PhyslayerLibName; function PHYSFSRWOPS_openWrite(fname: PChar): PSDL_RWops; cdecl; external PhyslayerLibName; - -function PHYSFS_mount(newDir, mountPoint: PChar; appendToPath: LongBool) : LongInt; cdecl; external PhysfsLibName; +procedure hedgewarsMountPackages(); cdecl; external PhyslayerLibName; +{$IFNDEF PAS2C} +function PHYSFS_init(argv0: PChar): LongInt; cdecl; external PhysfsLibName; +function PHYSFS_deinit(): LongInt; cdecl; external PhysfsLibName; +function PHYSFS_mount(newDir, mountPoint: PChar; appendToPath: LongBool) : LongBool; cdecl; external PhysfsLibName; function PHYSFS_openRead(fname: PChar): PFSFile; cdecl; external PhysfsLibName; function PHYSFS_eof(f: PFSFile): LongBool; cdecl; external PhysfsLibName; function PHYSFS_readBytes(f: PFSFile; buffer: pointer; len: Int64): Int64; cdecl; external PhysfsLibName; function PHYSFS_close(f: PFSFile): LongBool; cdecl; external PhysfsLibName; function PHYSFS_exists(fname: PChar): LongBool; cdecl; external PhysfsLibName; - -procedure hedgewarsMountPackages(); cdecl; external PhyslayerLibName; +function PHYSFS_getLastError(): PChar; cdecl; external PhysfsLibName; +{$ELSE} +function PHYSFS_readBytes(f: PFSFile; buffer: pointer; len: Int64): Int64; +begin + PHYSFS_readBytes:= PHYSFS_read(f, buffer, 1, len); +end; +{$ENDIF} function rwopsOpenRead(fname: shortstring): PSDL_RWops; begin @@ -108,12 +116,12 @@ b[byte(b[0])]:= c; if b[0] = #255 then begin - s:= s + b; + s:= s + ansistring(b); b[0]:= #0 end end; - -s:= s + b + +s:= s + ansistring(b) end; function pfsBlockRead(f: PFSFile; buf: pointer; size: Int64): Int64; @@ -127,9 +135,25 @@ pfsBlockRead:= r end; +procedure pfsMount(path: ansistring; mountpoint: PChar); +begin + if PHYSFS_mount(PChar(path), mountpoint, false) then + AddFileLog('[PhysFS] mount ' + shortstring(path) + ' at ' + shortstring(mountpoint) + ' : ok') + else + AddFileLog('[PhysFS] mount ' + shortstring(path) + ' at ' + shortstring(mountpoint) + ' : FAILED ("' + shortstring(PHYSFS_getLastError()) + '")'); +end; + +procedure pfsMountAtRoot(path: ansistring); +begin + pfsMount(path, PChar(_S'/')); +end; + procedure initModule; var i: LongInt; cPhysfsId: shortstring; +{$IFNDEF MOBILE} + fp: PChar; +{$ENDIF} begin {$IFDEF HWLIBRARY} //TODO: http://icculus.org/pipermail/physfs/2011-August/001006.html @@ -141,16 +165,29 @@ i:= PHYSFS_init(Str2PChar(cPhysfsId)); AddFileLog('[PhysFS] init: ' + inttostr(i)); - i:= PHYSFS_mount(Str2PChar(PathPrefix), nil, false); - AddFileLog('[PhysFS] mount ' + PathPrefix + ': ' + inttostr(i)); - i:= PHYSFS_mount(Str2PChar(UserPathPrefix + '/Data'), nil, false); - AddFileLog('[PhysFS] mount ' + UserPathPrefix + '/Data: ' + inttostr(i)); +{$IFNDEF MOBILE} + // mount system fonts paths first + for i:= low(cFontsPaths) to high(cFontsPaths) do + begin + fp := cFontsPaths[i]; + if fp <> nil then + pfsMount(ansistring(fp), PChar('/Fonts')); + end; +{$ENDIF} + + pfsMountAtRoot(PathPrefix); + pfsMountAtRoot(UserPathPrefix + ansistring('/Data')); hedgewarsMountPackages; - i:= PHYSFS_mount(Str2PChar(UserPathPrefix), nil, false); // need access to teams and frontend configs (for bindings) - AddFileLog('[PhysFS] mount ' + UserPathPrefix + ': ' + inttostr(i)); + pfsMountAtRoot(UserPathPrefix); + + if cTestLua then + begin + pfsMountAtRoot(ansistring(ExtractFileDir(cScriptName))); + cScriptName := ExtractFileName(cScriptName); + end; end; procedure freeModule; diff -r 31570b766315 -r ed5a6478e710 hedgewars/uRandom.pas --- a/hedgewars/uRandom.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uRandom.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} @@ -31,8 +31,8 @@ uses uFloat; procedure SetRandomSeed(Seed: shortstring; dropAdditionalPart: boolean); // Sets the seed that should be used for generating pseudo-random values. -function GetRandomf: hwFloat; overload; // Returns a pseudo-random hwFloat. -function GetRandom(m: LongWord): LongWord; overload; inline; // Returns a positive pseudo-random integer smaller than m. +function GetRandomf: hwFloat; // Returns a pseudo-random hwFloat. +function GetRandom(m: LongWord): LongWord; inline; // Returns a positive pseudo-random integer smaller than m. procedure AddRandomness(r: LongWord); inline; function rndSign(num: hwFloat): hwFloat; // Returns num with a random chance of having a inverted sign. @@ -45,10 +45,11 @@ procedure AddRandomness(r: LongWord); inline; begin n:= (n + 1) and $3F; -cirbuf[n]:= cirbuf[n] xor r + cirbuf[n]:= cirbuf[n] xor r; end; function GetNext: Longword; inline; +var s : string; begin n:= (n + 1) and $3F; cirbuf[n]:= @@ -56,7 +57,8 @@ cirbuf[(n + 9) and $3F]) {n - 55 mod 64} and $7FFFFFFF; {mod 2^31} -GetNext:= cirbuf[n] + GetNext:= cirbuf[n]; + str(GetNext, s); end; procedure SetRandomSeed(Seed: shortstring; dropAdditionalPart: boolean); @@ -80,7 +82,7 @@ cirbuf[i]:= $A98765 + 68; // odd number for i:= 0 to 1023 do - GetNext + GetNext; end; function GetRandomf: hwFloat; diff -r 31570b766315 -r ed5a6478e710 hedgewars/uRender.pas --- a/hedgewars/uRender.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uRender.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,16 +13,20 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} +{$IF GLunit = GL}{$DEFINE GLunit:=GL,GLext}{$ENDIF} unit uRender; interface -uses SDLh, uTypes, GLunit, uConsts; +uses SDLh, uTypes, GLunit; + +procedure initModule; +procedure freeModule; procedure DrawSprite (Sprite: TSprite; X, Y, Frame: LongInt); procedure DrawSprite (Sprite: TSprite; X, Y, FrameX, FrameY: LongInt); @@ -33,6 +37,7 @@ procedure DrawTexture (X, Y: LongInt; Texture: PTexture); inline; procedure DrawTexture (X, Y: LongInt; Texture: PTexture; Scale: GLfloat); +procedure DrawTexture2 (X, Y: LongInt; Texture: PTexture; Scale, Overlap: GLfloat); procedure DrawTextureFromRect (X, Y: LongInt; r: PSDL_Rect; SourceTexture: PTexture); inline; procedure DrawTextureFromRect (X, Y, W, H: LongInt; r: PSDL_Rect; SourceTexture: PTexture); inline; procedure DrawTextureFromRectDir(X, Y, W, H: LongInt; r: PSDL_Rect; SourceTexture: PTexture; Dir: LongInt); @@ -43,21 +48,64 @@ procedure DrawCircle (X, Y, Radius, Width: LongInt); procedure DrawCircle (X, Y, Radius, Width: LongInt; r, g, b, a: Byte); +procedure DrawCircleFilled (X, Y, Radius: LongInt; r, g, b, a: Byte); procedure DrawLine (X0, Y0, X1, Y1, Width: Single; color: LongWord); inline; procedure DrawLine (X0, Y0, X1, Y1, Width: Single; r, g, b, a: Byte); -procedure DrawFillRect (r: TSDL_Rect); +procedure DrawLineOnScreen (X0, Y0, X1, Y1, Width: Single; r, g, b, a: Byte); +procedure DrawRect (rect: TSDL_Rect; r, g, b, a: Byte; Fill: boolean); procedure DrawHedgehog (X, Y: LongInt; Dir: LongInt; Pos, Step: LongWord; Angle: real); procedure DrawScreenWidget (widget: POnScreenWidget); +procedure DrawWater (Alpha: byte; OffsetY, OffsetX: LongInt); +procedure DrawWaves (Dir, dX, dY, oX: LongInt; tnt: Byte); +procedure RenderClear (); +{$IFDEF USE_S3D_RENDERING} +procedure RenderClear (mode: TRenderMode); +{$ENDIF} +procedure RenderSetClearColor (r, g, b, a: real); procedure Tint (r, g, b, a: Byte); inline; procedure Tint (c: Longword); inline; procedure untint(); inline; procedure setTintAdd (f: boolean); inline; +// call this to finish the rendering of current frame +procedure FinishRender(); + +function isAreaOffscreen(X, Y, Width, Height: LongInt): boolean; inline; + +// 0 => not offscreen, <0 => left/top of screen >0 => right/below of screen +function isDxAreaOffscreen(X, Width: LongInt): LongInt; inline; +function isDyAreaOffscreen(Y, Height: LongInt): LongInt; inline; + +procedure SetScale(f: GLfloat); +procedure UpdateViewLimits(); + +procedure RendererSetup(); +procedure RendererCleanup(); + +procedure ChangeDepth(rm: TRenderMode; d: GLfloat); +procedure ResetDepth(rm: TRenderMode); + +// TODO everything below this should not need a public interface + +procedure EnableTexture(enable:Boolean); + +procedure SetTexCoordPointer(p: Pointer;n: Integer); inline; +procedure SetVertexPointer(p: Pointer;n: Integer); inline; +procedure SetColorPointer(p: Pointer;n: Integer); inline; + +procedure UpdateModelviewProjection(); inline; + +procedure openglPushMatrix (); inline; +procedure openglPopMatrix (); inline; +procedure openglTranslatef (X, Y, Z: GLfloat); inline; + implementation -uses uVariables; +uses {$IFNDEF PAS2C} StrUtils, {$ENDIF}SysUtils, uVariables, uUtils, uConsts + {$IFDEF GL2}, uMatrix, uConsole{$ENDIF} + {$IF NOT DEFINED(SDL2) AND DEFINED(USE_VIDEO_RECORDING)}, glut {$ENDIF}; {$IFDEF USE_TOUCH_INTERFACE} const @@ -65,7 +113,778 @@ MOVE_ANIM_TIME = 500; {$ENDIF} -var LastTint: LongWord = 0; +{$IFDEF GL2} +var + shaderMain: GLuint; + shaderWater: GLuint; +{$ENDIF} + +var VertexBuffer : array [0 ..59] of TVertex2f; + TextureBuffer: array [0 .. 7] of TVertex2f; + LastTint: LongWord = 0; + LastColorPointer , LastTexCoordPointer , LastVertexPointer : Pointer; +{$IFDEF GL2} + LastColorPointerN, LastTexCoordPointerN, LastVertexPointerN: Integer; +{$ENDIF} + +{$IFDEF USE_S3D_RENDERING} + // texture/vertex buffers for left/right/default eye modes + texLRDtb, texLvb, texRvb: array [0..3] of TVertex2f; +{$ENDIF} + +procedure openglLoadIdentity (); forward; +procedure openglTranslProjMatrix(X, Y, Z: GLFloat); forward; +procedure openglScalef (ScaleX, ScaleY, ScaleZ: GLfloat); forward; +procedure openglRotatef (RotX, RotY, RotZ: GLfloat; dir: LongInt); forward; +procedure openglTint (r, g, b, a: Byte); forward; + +{$IFDEF USE_S3D_RENDERING OR USE_VIDEO_RECORDING} +procedure CreateFramebuffer(var frame, depth, tex: GLuint); forward; +procedure DeleteFramebuffer(var frame, depth, tex: GLuint); forward; +{$ENDIF} + +function isAreaOffscreen(X, Y, Width, Height: LongInt): boolean; inline; +begin + isAreaOffscreen:= (isDxAreaOffscreen(X, Width) <> 0) or (isDyAreaOffscreen(Y, Height) <> 0); +end; + +function isDxAreaOffscreen(X, Width: LongInt): LongInt; inline; +begin + if X > ViewRightX then exit(1); + if X + Width < ViewLeftX then exit(-1); + isDxAreaOffscreen:= 0; +end; + +function isDyAreaOffscreen(Y, Height: LongInt): LongInt; inline; +begin + if Y > ViewBottomY then exit(1); + if Y + Height < ViewTopY then exit(-1); + isDyAreaOffscreen:= 0; +end; + +procedure RenderClear(); +begin + glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); +end; + +{$IFDEF USE_S3D_RENDERING} +procedure RenderClear(mode: TRenderMode); +var frame: GLuint; +begin + if (cStereoMode = smHorizontal) or (cStereoMode = smVertical) then + begin + case mode of + rmLeftEye: frame:= frameL; + rmRightEye: frame:= frameR; + else + frame:= defaultFrame; + end; + + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, frame); + + RenderClear(); + end + else + begin + // draw left eye in red channel only + if mode = rmLeftEye then + begin + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + RenderClear(); + if cStereoMode = smGreenRed then + glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_TRUE) + else if cStereoMode = smBlueRed then + glColorMask(GL_FALSE, GL_FALSE, GL_TRUE, GL_TRUE) + else if cStereoMode = smCyanRed then + glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_TRUE) + else + glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_TRUE); + end + else + begin + // draw right eye in selected channel(s) only + if cStereoMode = smRedGreen then + glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_TRUE) + else if cStereoMode = smRedBlue then + glColorMask(GL_FALSE, GL_FALSE, GL_TRUE, GL_TRUE) + else if cStereoMode = smRedCyan then + glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_TRUE) + else + glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_TRUE); + end; + end; +end; +{$ENDIF} + +procedure RenderSetClearColor(r, g, b, a: real); +begin + glClearColor(r, g, b, a); +end; + +procedure FinishRender(); +begin + +{$IFDEF USE_S3D_RENDERING} +if (cStereoMode = smHorizontal) or (cStereoMode = smVertical) then + begin + RenderClear(rmDefault); + + SetScale(cDefaultZoomLevel); + + + // same for all + SetTexCoordPointer(@texLRDtb, Length(texLRDtb)); + + + // draw left frame + glBindTexture(GL_TEXTURE_2D, texl); + SetVertexPointer(@texLvb, Length(texLvb)); + //UpdateModelviewProjection; + glDrawArrays(GL_TRIANGLE_FAN, 0, Length(texLvb)); + + // draw right frame + glBindTexture(GL_TEXTURE_2D, texl); + SetVertexPointer(@texRvb, Length(texRvb)); + //UpdateModelviewProjection; + glDrawArrays(GL_TRIANGLE_FAN, 0, Length(texRvb)); + + SetScale(zoom); + end; +{$ENDIF} +end; + +{$IFDEF GL2} +function CompileShader(shaderFile: string; shaderType: GLenum): GLuint; +var + shader: GLuint; + f: Textfile; + source, line: AnsiString; + sourceA: Pchar; + lengthA: GLint; + compileResult: GLint; + logLength: GLint; + log: PChar; +begin + Assign(f, PathPrefix + cPathz[ptShaders] + '/' + shaderFile); + filemode:= 0; // readonly + Reset(f); + if IOResult <> 0 then + begin + AddFileLog('Unable to load ' + shaderFile); + halt(HaltStartupError); + end; + + source:=''; + while not eof(f) do + begin + ReadLn(f, line); + source:= source + line + #10; + end; + + Close(f); + + WriteLnToConsole('Compiling shader: ' + PathPrefix + cPathz[ptShaders] + '/' + shaderFile); + + sourceA:=PChar(source); + lengthA:=Length(source); + + shader:=glCreateShader(shaderType); + glShaderSource(shader, 1, @sourceA, @lengthA); + glCompileShader(shader); + glGetShaderiv(shader, GL_COMPILE_STATUS, @compileResult); + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, @logLength); + + if logLength > 1 then + begin + log := GetMem(logLength); + glGetShaderInfoLog(shader, logLength, nil, log); + WriteLnToConsole('========== Compiler log =========='); + WriteLnToConsole(shortstring(log)); + WriteLnToConsole('==================================='); + FreeMem(log, logLength); + end; + + if compileResult <> GL_TRUE then + begin + WriteLnToConsole('Shader compilation failed, halting'); + halt(HaltStartupError); + end; + + CompileShader:= shader; +end; + +function CompileProgram(shaderName: string): GLuint; +var + program_: GLuint; + vs, fs: GLuint; + linkResult: GLint; + logLength: GLint; + log: PChar; +begin + program_:= glCreateProgram(); + vs:= CompileShader(shaderName + '.vs', GL_VERTEX_SHADER); + fs:= CompileShader(shaderName + '.fs', GL_FRAGMENT_SHADER); + glAttachShader(program_, vs); + glAttachShader(program_, fs); + + glBindAttribLocation(program_, aVertex, PChar('vertex')); + glBindAttribLocation(program_, aTexCoord, PChar('texcoord')); + glBindAttribLocation(program_, aColor, PChar('color')); + + glLinkProgram(program_); + glDeleteShader(vs); + glDeleteShader(fs); + + glGetProgramiv(program_, GL_LINK_STATUS, @linkResult); + glGetProgramiv(program_, GL_INFO_LOG_LENGTH, @logLength); + + if logLength > 1 then + begin + log := GetMem(logLength); + glGetProgramInfoLog(program_, logLength, nil, log); + WriteLnToConsole('========== Compiler log =========='); + WriteLnToConsole(shortstring(log)); + WriteLnToConsole('==================================='); + FreeMem(log, logLength); + end; + + if linkResult <> GL_TRUE then + begin + WriteLnToConsole('Linking program failed, halting'); + halt(HaltStartupError); + end; + + CompileProgram:= program_; +end; +{$ENDIF} + +function glLoadExtension(extension : shortstring) : boolean; +var logmsg: shortstring; +begin + extension:= extension; // avoid hint + glLoadExtension:= false; + logmsg:= 'OpenGL - "' + extension + '" skipped'; + +{$IFNDEF IPHONEOS} +//TODO: pas2c does not handle +{$IFNDEF PAS2C} +// FreePascal doesnt come with OpenGL ES 1.1 Extension headers +{$IF GLunit <> gles11} + + glLoadExtension:= glext_LoadExtension(extension); + + if glLoadExtension then + logmsg:= 'OpenGL - "' + extension + '" loaded' + else + logmsg:= 'OpenGL - "' + extension + '" failed to load'; + +{$ENDIF} +{$ENDIF} +{$ENDIF} + AddFileLog(logmsg); +end; + +{$IFDEF USE_S3D_RENDERING OR USE_VIDEO_RECORDING} +procedure CreateFramebuffer(var frame, depth, tex: GLuint); +begin + glGenFramebuffersEXT(1, @frame); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, frame); + glGenRenderbuffersEXT(1, @depth); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depth); + glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, cScreenWidth, cScreenHeight); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depth); + glGenTextures(1, @tex); + glBindTexture(GL_TEXTURE_2D, tex); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, cScreenWidth, cScreenHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, nil); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, tex, 0); +end; + +procedure DeleteFramebuffer(var frame, depth, tex: GLuint); +begin + glDeleteTextures(1, @tex); + glDeleteRenderbuffersEXT(1, @depth); + glDeleteFramebuffersEXT(1, @frame); +end; +{$ENDIF} + +procedure RendererCleanup(); +begin +{$IFNDEF PAS2C} +{$IFDEF USE_VIDEO_RECORDING} + if defaultFrame <> 0 then + DeleteFramebuffer(defaultFrame, depthv, texv); +{$ENDIF} +{$IFDEF USE_S3D_RENDERING} + if (cStereoMode = smHorizontal) or (cStereoMode = smVertical) then + begin + DeleteFramebuffer(framel, depthl, texl); + DeleteFramebuffer(framer, depthr, texr); + end +{$ENDIF} +{$ENDIF} +end; + +procedure RendererSetup(); +var AuxBufNum: LongInt = 0; + tmpstr: ansistring; + tmpint: LongInt; + tmpn: LongInt; +begin + // suppress hint/warning + AuxBufNum:= AuxBufNum; + + // get the max (h and v) size for textures that the gpu can support + glGetIntegerv(GL_MAX_TEXTURE_SIZE, @MaxTextureSize); + if MaxTextureSize <= 0 then + begin + MaxTextureSize:= 1024; + AddFileLog('OpenGL Warning - driver didn''t provide any valid max texture size; assuming 1024'); + end + else if (MaxTextureSize < 1024) and (MaxTextureSize >= 512) then + begin + cReducedQuality := cReducedQuality or rqNoBackground; + AddFileLog('Texture size too small for backgrounds, disabling.'); + end; + // everyone loves debugging + // find out which gpu we are using (for extension compatibility maybe?) + AddFileLog('OpenGL-- Renderer: ' + shortstring(pchar(glGetString(GL_RENDERER)))); + AddFileLog(' |----- Vendor: ' + shortstring(pchar(glGetString(GL_VENDOR)))); + AddFileLog(' |----- Version: ' + shortstring(pchar(glGetString(GL_VERSION)))); + AddFileLog(' |----- Texture Size: ' + inttostr(MaxTextureSize)); +{$IFDEF USE_VIDEO_RECORDING} + glGetIntegerv(GL_AUX_BUFFERS, @AuxBufNum); + AddFileLog(' |----- Number of auxiliary buffers: ' + inttostr(AuxBufNum)); +{$ENDIF} +{$IFNDEF PAS2C} + AddFileLog(' \----- Extensions: '); + + // fetch extentions and store them in string + tmpstr := StrPas(PChar(glGetString(GL_EXTENSIONS))); + tmpn := WordCount(tmpstr, [' ']); + tmpint := 1; + + repeat + begin + // print up to 3 extentions per row + // ExtractWord will return empty string if index out of range + AddFileLog(TrimRight( + ExtractWord(tmpint, tmpstr, [' ']) + ' ' + + ExtractWord(tmpint+1, tmpstr, [' ']) + ' ' + + ExtractWord(tmpint+2, tmpstr, [' ']) + )); + tmpint := tmpint + 3; + end; + until (tmpint > tmpn); +{$ENDIF} + AddFileLog(''); + + defaultFrame:= 0; + +{$IFDEF USE_VIDEO_RECORDING} + if GameType = gmtRecord then + begin + if glLoadExtension('GL_EXT_framebuffer_object') then + begin + CreateFramebuffer(defaultFrame, depthv, texv); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, defaultFrame); + AddFileLog('Using framebuffer for video recording.'); + end + else if AuxBufNum > 0 then + begin + glDrawBuffer(GL_AUX0); + glReadBuffer(GL_AUX0); + AddFileLog('Using auxiliary buffer for video recording.'); + end + else + begin + glDrawBuffer(GL_BACK); + glReadBuffer(GL_BACK); + AddFileLog('Warning: off-screen rendering is not supported; using back buffer but it may not work.'); + end; + end; +{$ENDIF} + +{$IFDEF GL2} + +{$IFDEF PAS2C} + err := glewInit(); + if err <> GLEW_OK then + begin + WriteLnToConsole('Failed to initialize GLEW.'); + halt(HaltStartupError); + end; +{$ENDIF} + +{$IFNDEF PAS2C} + if not Load_GL_VERSION_2_0 then + halt; +{$ENDIF} + + shaderWater:= CompileProgram('water'); + glUseProgram(shaderWater); + glUniform1i(glGetUniformLocation(shaderWater, pchar('tex0')), 0); + uWaterMVPLocation:= glGetUniformLocation(shaderWater, pchar('mvp')); + + shaderMain:= CompileProgram('default'); + glUseProgram(shaderMain); + glUniform1i(glGetUniformLocation(shaderMain, pchar('tex0')), 0); + uMainMVPLocation:= glGetUniformLocation(shaderMain, pchar('mvp')); + uMainTintLocation:= glGetUniformLocation(shaderMain, pchar('tint')); + + uCurrentMVPLocation:= uMainMVPLocation; + + Tint(255, 255, 255, 255); + UpdateModelviewProjection; +{$ENDIF} + +{$IFDEF USE_S3D_RENDERING} + if (cStereoMode = smHorizontal) or (cStereoMode = smVertical) then + begin + // prepare left and right frame buffers and associated textures + if glLoadExtension('GL_EXT_framebuffer_object') then + begin + CreateFramebuffer(framel, depthl, texl); + CreateFramebuffer(framer, depthr, texr); + + + + + // reset + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, defaultFrame) + end + else + cStereoMode:= smNone; + end; + + // set up vertex/texture buffers for frame textures + texLRDtb[0].X:= 0.0; + texLRDtb[0].Y:= 0.0; + texLRDtb[1].X:= 1.0; + texLRDtb[1].Y:= 0.0; + texLRDtb[2].X:= 1.0; + texLRDtb[2].Y:= 1.0; + texLRDtb[3].X:= 0.0; + texLRDtb[3].Y:= 1.0; + + if cStereoMode = smHorizontal then + begin + texLvb[0].X:= cScreenWidth / -2; + texLvb[0].Y:= cScreenHeight; + texLvb[1].X:= 0; + texLvb[1].Y:= cScreenHeight; + texLvb[2].X:= 0; + texLvb[2].Y:= 0; + texLvb[3].X:= cScreenWidth / -2; + texLvb[3].Y:= 0; + + texRvb[0].X:= 0; + texRvb[0].Y:= cScreenHeight; + texRvb[1].X:= cScreenWidth / 2; + texRvb[1].Y:= cScreenHeight; + texRvb[2].X:= cScreenWidth / 2; + texRvb[2].Y:= 0; + texRvb[3].X:= 0; + texRvb[3].Y:= 0; + end + else + begin + texLvb[0].X:= cScreenWidth / -2; + texLvb[0].Y:= cScreenHeight / 2; + texLvb[1].X:= cScreenWidth / 2; + texLvb[1].Y:= cScreenHeight / 2; + texLvb[2].X:= cScreenWidth / 2; + texLvb[2].Y:= 0; + texLvb[3].X:= cScreenWidth / -2; + texLvb[3].Y:= 0; + + texRvb[0].X:= cScreenWidth / -2; + texRvb[0].Y:= cScreenHeight; + texRvb[1].X:= cScreenWidth / 2; + texRvb[1].Y:= cScreenHeight; + texRvb[2].X:= cScreenWidth / 2; + texRvb[2].Y:= cScreenHeight / 2; + texRvb[3].X:= cScreenWidth / -2; + texRvb[3].Y:= cScreenHeight / 2; + end; +{$ENDIF} + +// set view port to whole window +glViewport(0, 0, cScreenWidth, cScreenHeight); + +{$IFDEF GL2} + uMatrix.initModule; + hglMatrixMode(MATRIX_MODELVIEW); + // prepare default translation/scaling + hglLoadIdentity(); + hglScalef(2.0 / cScreenWidth, -2.0 / cScreenHeight, 1.0); + hglTranslatef(0, -cScreenHeight / 2, 0); + + EnableTexture(True); + + glEnableVertexAttribArray(aVertex); + glEnableVertexAttribArray(aTexCoord); + glGenBuffers(1, @vBuffer); + glGenBuffers(1, @tBuffer); + glGenBuffers(1, @cBuffer); +{$ELSE} + glMatrixMode(GL_MODELVIEW); + // prepare default translation/scaling + glLoadIdentity(); + glScalef(2.0 / cScreenWidth, -2.0 / cScreenHeight, 1.0); + glTranslatef(0, -cScreenHeight / 2, 0); + + // disable/lower perspective correction (will not need it anyway) + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); + // disable dithering + glDisable(GL_DITHER); + // enable common states by default as they save a lot + glEnable(GL_TEXTURE_2D); + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); +{$ENDIF} + + // enable alpha blending + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + // disable/lower perspective correction (will not need it anyway) +end; + +procedure openglLoadIdentity(); inline; +begin +{$IFDEF GL2} + hglLoadIdentity(); +{$ELSE} + glLoadIdentity(); +{$ENDIF} +end; + +procedure openglTranslProjMatrix(X, Y, Z: GLfloat); inline; +begin +{$IFDEF GL2} + hglMatrixMode(MATRIX_PROJECTION); + hglTranslatef(X, Y, Z); + hglMatrixMode(MATRIX_MODELVIEW); +{$ELSE} + glMatrixMode(GL_PROJECTION); + glTranslatef(X, Y, Z); + glMatrixMode(GL_MODELVIEW); +{$ENDIF} +end; + +procedure openglPushMatrix(); inline; +begin +{$IFDEF GL2} + hglPushMatrix(); +{$ELSE} + glPushMatrix(); +{$ENDIF} +end; + +procedure openglPopMatrix(); inline; +begin +{$IFDEF GL2} + hglPopMatrix(); +{$ELSE} + glPopMatrix(); +{$ENDIF} +end; + +procedure openglTranslatef(X, Y, Z: GLfloat); inline; +begin +{$IFDEF GL2} + hglTranslatef(X, Y, Z); +{$ELSE} + glTranslatef(X, Y, Z); +{$ENDIF} +end; + +procedure openglScalef(ScaleX, ScaleY, ScaleZ: GLfloat); inline; +begin +{$IFDEF GL2} + hglScalef(ScaleX, ScaleY, ScaleZ); +{$ELSE} + glScalef(ScaleX, ScaleY, ScaleZ); +{$ENDIF} +end; + +procedure openglRotatef(RotX, RotY, RotZ: GLfloat; dir: LongInt); inline; +{ workaround for pascal bug http://bugs.freepascal.org/view.php?id=27222 } +var tmpdir: LongInt; +begin +tmpdir:=dir; +{$IFDEF GL2} + hglRotatef(RotX, RotY, RotZ, tmpdir); +{$ELSE} + glRotatef(RotX, RotY, RotZ, tmpdir); +{$ENDIF} +end; + +procedure openglUseColorOnly(b :boolean); inline; +begin + if b then + begin + {$IFDEF GL2} + glDisableVertexAttribArray(aTexCoord); + glEnableVertexAttribArray(aColor); + {$ELSE} + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + {$ENDIF} + LastTexCoordPointer:= nil; + end + else + begin + {$IFDEF GL2} + glDisableVertexAttribArray(aColor); + glEnableVertexAttribArray(aTexCoord); + {$ELSE} + glDisableClientState(GL_COLOR_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + {$ENDIF} + LastColorPointer:= nil; + end; + EnableTexture(not b); +end; + +procedure UpdateModelviewProjection(); inline; +{$IFDEF GL2} +var + mvp: TMatrix4x4f; +{$ENDIF} +begin +{$IFDEF GL2} + //MatrixMultiply(mvp, mProjection, mModelview); +{$HINTS OFF} + hglMVP(mvp); +{$HINTS ON} + glUniformMatrix4fv(uCurrentMVPLocation, 1, GL_FALSE, @mvp[0, 0]); +{$ENDIF} +end; + +procedure SetTexCoordPointer(p: Pointer; n: Integer); inline; +begin +{$IFDEF GL2} + if (p = LastTexCoordPointer) and (n = LastTexCoordPointerN) then + exit; + glBindBuffer(GL_ARRAY_BUFFER, tBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * n * 2, p, GL_STATIC_DRAW); + glEnableVertexAttribArray(aTexCoord); + glVertexAttribPointer(aTexCoord, 2, GL_FLOAT, GL_FALSE, 0, pointer(0)); + LastTexCoordPointerN:= n; +{$ELSE} + if p = LastTexCoordPointer then + exit; + n:= n; + glTexCoordPointer(2, GL_FLOAT, 0, p); +{$ENDIF} + LastTexCoordPointer:= p; +end; + +procedure SetVertexPointer(p: Pointer; n: Integer); inline; +begin +{$IFDEF GL2} + if (p = LastVertexPointer) and (n = LastVertexPointerN) then + exit; + glBindBuffer(GL_ARRAY_BUFFER, vBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * n * 2, p, GL_STATIC_DRAW); + glEnableVertexAttribArray(aVertex); + glVertexAttribPointer(aVertex, 2, GL_FLOAT, GL_FALSE, 0, pointer(0)); + LastVertexPointerN:= n; +{$ELSE} + if p = LastVertexPointer then + exit; + n:= n; + glVertexPointer(2, GL_FLOAT, 0, p); +{$ENDIF} + LastVertexPointer:= p; +end; + +procedure SetColorPointer(p: Pointer; n: Integer); inline; +begin +{$IFDEF GL2} + if (p = LastColorPointer) and (n = LastColorPointerN) then + exit; + glBindBuffer(GL_ARRAY_BUFFER, cBuffer); + glBufferData(GL_ARRAY_BUFFER, n * 4, p, GL_STATIC_DRAW); + glEnableVertexAttribArray(aColor); + glVertexAttribPointer(aColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, pointer(0)); + LastColorPointerN:= n; +{$ELSE} + if p = LastColorPointer then + exit; + n:= n; + glColorPointer(4, GL_UNSIGNED_BYTE, 0, p); +{$ENDIF} + LastColorPointer:= p; +end; + +procedure EnableTexture(enable:Boolean); +begin + {$IFDEF GL2} + if enable then + glUniform1i(glGetUniformLocation(shaderMain, pchar('enableTexture')), 1) + else + glUniform1i(glGetUniformLocation(shaderMain, pchar('enableTexture')), 0); + {$ELSE} + if enable then + glEnable(GL_TEXTURE_2D) + else + glDisable(GL_TEXTURE_2D); + {$ENDIF} +end; + +procedure UpdateViewLimits(); +var tmp: LongInt; +begin + // cScaleFactor is 2.0 on "no zoom" + tmp:= round(0.5 + cScreenWidth / cScaleFactor); + ViewRightX := tmp; + ViewLeftX := -tmp; + tmp:= round(0.5 + cScreenHeight / cScaleFactor); + ViewBottomY:= tmp + cScreenHeight div 2; + ViewTopY := -tmp + cScreenHeight div 2; + + // visual debugging fun :D + if cViewLimitsDebug then + begin + // some margin on each side + tmp:= trunc(min(cScreenWidth, cScreenHeight) div 2 / cScaleFactor); + ViewLeftX := ViewLeftX + trunc(tmp); + ViewRightX := ViewRightX - trunc(tmp); + ViewBottomY:= ViewBottomY - trunc(tmp); + ViewTopY := ViewTopY + trunc(tmp); + end; + + ViewWidth := ViewRightX - ViewLeftX + 1; + ViewHeight:= ViewBottomY - ViewTopY + 1; +end; + +procedure SetScale(f: GLfloat); +begin + // leave immediately if scale factor did not change + if f = cScaleFactor then + exit; + + // for going back to default scaling just pop matrix + if f = cDefaultZoomLevel then + begin + openglPopMatrix; + end + else + begin + openglPushMatrix; // save default scaling in matrix + openglLoadIdentity(); + openglScalef(f / cScreenWidth, -f / cScreenHeight, 1.0); + openglTranslatef(0, -cScreenHeight div 2, 0); + end; + + cScaleFactor:= f; + updateViewLimits(); + + UpdateModelviewProjection; +end; procedure DrawSpriteFromRect(Sprite: TSprite; r: TSDL_Rect; X, Y, Height, Position: LongInt); inline; begin @@ -78,59 +897,57 @@ begin DrawTextureFromRectDir(X, Y, r^.w, r^.h, r, SourceTexture, 1) end; + procedure DrawTextureFromRect(X, Y, W, H: LongInt; r: PSDL_Rect; SourceTexture: PTexture); inline; begin DrawTextureFromRectDir(X, Y, W, H, r, SourceTexture, 1) end; procedure DrawTextureFromRectDir(X, Y, W, H: LongInt; r: PSDL_Rect; SourceTexture: PTexture; Dir: LongInt); -var rr: TSDL_Rect; - _l, _r, _t, _b: real; - VertexBuffer, TextureBuffer: array [0..3] of TVertex2f; +var _l, _r, _t, _b: real; + xw, yh: LongInt; begin if (SourceTexture^.h = 0) or (SourceTexture^.w = 0) then exit; -// do not draw anything outside the visible screen space (first check fixes some sprite drawing, e.g. hedgehogs) -if (abs(X) > W) and ((abs(X + W / 2) - W / 2) > cScreenWidth / cScaleFactor) then - exit; -if (abs(Y) > H) and ((abs(Y + H / 2 - (0.5 * cScreenHeight)) - H / 2) > cScreenHeight / cScaleFactor) then +{if isDxAreaOffscreen(X, W) <> 0 then exit; +if isDyAreaOffscreen(Y, H) <> 0 then + exit;} -rr.x:= X; -rr.y:= Y; -rr.w:= W; -rr.h:= H; +// do not draw anything outside the visible screen space (first check fixes some sprite drawing, e.g. hedgehogs) +if (abs(X) > W) and ((abs(X + W / 2) - W / 2) * 2 > ViewWidth) then + exit; +if (abs(Y) > H) and ((abs(Y + H / 2 - (0.5 * cScreenHeight)) - H / 2) * 2 > ViewHeight) then + exit; _l:= r^.x / SourceTexture^.w * SourceTexture^.rx; _r:= (r^.x + r^.w) / SourceTexture^.w * SourceTexture^.rx; + +// if direction is mirrored, switch left and right +if Dir < 0 then + begin + _t:= _l; + _l:= _r; + _r:= _t; + end; + _t:= r^.y / SourceTexture^.h * SourceTexture^.ry; _b:= (r^.y + r^.h) / SourceTexture^.h * SourceTexture^.ry; glBindTexture(GL_TEXTURE_2D, SourceTexture^.id); -if Dir < 0 then - begin - VertexBuffer[0].X:= X + rr.w/2; - VertexBuffer[0].Y:= Y; - VertexBuffer[1].X:= X - rr.w/2; - VertexBuffer[1].Y:= Y; - VertexBuffer[2].X:= X - rr.w/2; - VertexBuffer[2].Y:= rr.h + Y; - VertexBuffer[3].X:= X + rr.w/2; - VertexBuffer[3].Y:= rr.h + Y; - end -else - begin - VertexBuffer[0].X:= X; - VertexBuffer[0].Y:= Y; - VertexBuffer[1].X:= rr.w + X; - VertexBuffer[1].Y:= Y; - VertexBuffer[2].X:= rr.w + X; - VertexBuffer[2].Y:= rr.h + Y; - VertexBuffer[3].X:= X; - VertexBuffer[3].Y:= rr.h + Y; - end; +xw:= X + W; +yh:= Y + H; + +VertexBuffer[0].X:= X; +VertexBuffer[0].Y:= Y; +VertexBuffer[1].X:= xw; +VertexBuffer[1].Y:= Y; +VertexBuffer[2].X:= xw; +VertexBuffer[2].Y:= yh; +VertexBuffer[3].X:= X; +VertexBuffer[3].Y:= yh; TextureBuffer[0].X:= _l; TextureBuffer[0].Y:= _t; @@ -141,9 +958,9 @@ TextureBuffer[3].X:= _l; TextureBuffer[3].Y:= _b; -glVertexPointer(2, GL_FLOAT, 0, @VertexBuffer[0]); -glTexCoordPointer(2, GL_FLOAT, 0, @TextureBuffer[0]); -glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer)); +SetVertexPointer(@VertexBuffer[0], 4); +SetTexCoordPointer(@TextureBuffer[0], 4); +glDrawArrays(GL_TRIANGLE_FAN, 0, 4); end; procedure DrawTexture(X, Y: LongInt; Texture: PTexture); inline; @@ -154,17 +971,51 @@ procedure DrawTexture(X, Y: LongInt; Texture: PTexture; Scale: GLfloat); begin -glPushMatrix; -glTranslatef(X, Y, 0); -glScalef(Scale, Scale, 1); +openglPushMatrix; +openglTranslatef(X, Y, 0); + +if Scale <> 1.0 then + openglScalef(Scale, Scale, 1); glBindTexture(GL_TEXTURE_2D, Texture^.id); -glVertexPointer(2, GL_FLOAT, 0, @Texture^.vb); -glTexCoordPointer(2, GL_FLOAT, 0, @Texture^.tb); +SetVertexPointer(@Texture^.vb, Length(Texture^.vb)); +SetTexCoordPointer(@Texture^.tb, Length(Texture^.vb)); + +UpdateModelviewProjection; + glDrawArrays(GL_TRIANGLE_FAN, 0, Length(Texture^.vb)); +openglPopMatrix; -glPopMatrix +end; + +{ this contains tweaks in order to avoid land tile borders in blurry land mode } +procedure DrawTexture2(X, Y: LongInt; Texture: PTexture; Scale, Overlap: GLfloat); +var + TextureBuffer: array [0..3] of TVertex2f; +begin +openglPushMatrix; +openglTranslatef(X, Y, 0); +openglScalef(Scale, Scale, 1); + +glBindTexture(GL_TEXTURE_2D, Texture^.id); + +TextureBuffer[0].X:= Texture^.tb[0].X + Overlap; +TextureBuffer[0].Y:= Texture^.tb[0].Y + Overlap; +TextureBuffer[1].X:= Texture^.tb[1].X - Overlap; +TextureBuffer[1].Y:= Texture^.tb[1].Y + Overlap; +TextureBuffer[2].X:= Texture^.tb[2].X - Overlap; +TextureBuffer[2].Y:= Texture^.tb[2].Y - Overlap; +TextureBuffer[3].X:= Texture^.tb[3].X + Overlap; +TextureBuffer[3].Y:= Texture^.tb[3].Y - Overlap; + +SetVertexPointer(@Texture^.vb, 4); +SetTexCoordPointer(@TextureBuffer, 4); + +UpdateModelviewProjection; + +glDrawArrays(GL_TRIANGLE_FAN, 0, 4); +openglPopMatrix; end; procedure DrawTextureF(Texture: PTexture; Scale: GLfloat; X, Y, Frame, Dir, w, h: LongInt); @@ -174,31 +1025,69 @@ procedure DrawTextureRotatedF(Texture: PTexture; Scale, OffsetX, OffsetY: GLfloat; X, Y, Frame, Dir, w, h: LongInt; Angle: real); var ft, fb, fl, fr: GLfloat; - hw, nx, ny: LongInt; - VertexBuffer, TextureBuffer: array [0..3] of TVertex2f; + hw, hh, nx, ny: LongInt; begin +// visibility check only under trivial conditions +if (Scale <= 1) then + begin + if Angle <> 0 then + begin + if (OffsetX = 0) and (OffsetY = 0) then + begin + // sized doubled because the sprite might occupy up to 1.4 * of it's + // original size in each dimension, because it is rotated + if isDxAreaOffscreen(X - w, 2 * w) <> 0 then + exit; + if isDYAreaOffscreen(Y - h, 2 * h) <> 0 then + exit; + end; + end + else + begin + if isDxAreaOffscreen(X + dir * trunc(OffsetX) - w div 2, w) <> 0 then + exit; + if isDYAreaOffscreen(Y + trunc(OffsetY) - h div 2, h) <> 0 then + exit; + end; + end; + +{ // do not draw anything outside the visible screen space (first check fixes some sprite drawing, e.g. hedgehogs) -if (abs(X) > W) and ((abs(X + dir * OffsetX) - W / 2) * cScaleFactor > cScreenWidth) then +if (abs(X) > W) and ((abs(X + dir * OffsetX) - W / 2) * 2 > ViewWidth) then exit; -if (abs(Y) > H) and ((abs(Y + OffsetY - (0.5 * cScreenHeight)) - W / 2) * cScaleFactor > cScreenHeight) then +if (abs(Y) > H) and ((abs(Y + OffsetY - (cScreenHeight / 2)) - W / 2) * 2 > ViewHeight) then exit; +} -glPushMatrix; -glTranslatef(X, Y, 0); +openglPushMatrix; + +openglTranslatef(X, Y, 0); + if Dir = 0 then Dir:= 1; -glRotatef(Angle, 0, 0, Dir); +if Angle <> 0 then + openglRotatef(Angle, 0, 0, Dir); -glTranslatef(Dir*OffsetX, OffsetY, 0); -glScalef(Scale, Scale, 1); +if (OffsetX <> 0) or (OffsetY <> 0) then + openglTranslatef(Dir*OffsetX, OffsetY, 0); + +if Scale <> 1.0 then + openglScalef(Scale, Scale, 1); // Any reason for this call? And why only in t direction, not s? //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); -hw:= w div (2 div Dir); +if Dir > 0 then + hw:= w div 2 +else + hw:= -w div 2; -nx:= round(Texture^.w / w); // number of horizontal frames -ny:= round(Texture^.h / h); // number of vertical frames +hh:= h div 2; + +nx:= Texture^.w div w; // number of horizontal frames +if nx = 0 then nx:= 1; // one frame is minimum +ny:= Texture^.h div h; // number of vertical frames +if ny = 0 then ny:= 1; ft:= (Frame mod ny) * Texture^.ry / ny; fb:= ((Frame mod ny) + 1) * Texture^.ry / ny; @@ -208,13 +1097,13 @@ glBindTexture(GL_TEXTURE_2D, Texture^.id); VertexBuffer[0].X:= -hw; -VertexBuffer[0].Y:= w / -2; -VertexBuffer[1].X:= hw; -VertexBuffer[1].Y:= w / -2; -VertexBuffer[2].X:= hw; -VertexBuffer[2].Y:= w / 2; +VertexBuffer[0].Y:= -hh; +VertexBuffer[1].X:= hw; +VertexBuffer[1].Y:= -hh; +VertexBuffer[2].X:= hw; +VertexBuffer[2].Y:= hh; VertexBuffer[3].X:= -hw; -VertexBuffer[3].Y:= w / 2; +VertexBuffer[3].Y:= hh; TextureBuffer[0].X:= fl; TextureBuffer[0].Y:= ft; @@ -225,11 +1114,15 @@ TextureBuffer[3].X:= fl; TextureBuffer[3].Y:= fb; -glVertexPointer(2, GL_FLOAT, 0, @VertexBuffer[0]); -glTexCoordPointer(2, GL_FLOAT, 0, @TextureBuffer[0]); -glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer)); +SetVertexPointer(@VertexBuffer[0], 4); +SetTexCoordPointer(@TextureBuffer[0], 4); + +UpdateModelviewProjection; -glPopMatrix +glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + +openglPopMatrix; + end; procedure DrawSpriteRotated(Sprite: TSprite; X, Y, Dir: LongInt; Angle: real); @@ -242,41 +1135,66 @@ procedure DrawSpriteRotatedF(Sprite: TSprite; X, Y, Frame, Dir: LongInt; Angle: real); begin -glPushMatrix; -glTranslatef(X, Y, 0); +if Angle <> 0 then + begin + // sized doubled because the sprite might occupy up to 1.4 * of it's + // original size in each dimension, because it is rotated + if isDxAreaOffscreen(X - SpritesData[Sprite].Width, 2 * SpritesData[Sprite].Width) <> 0 then + exit; + if isDYAreaOffscreen(Y - SpritesData[Sprite].Height, 2 * SpritesData[Sprite].Height) <> 0 then + exit; + end +else + begin + if isDxAreaOffscreen(X - SpritesData[Sprite].Width div 2, SpritesData[Sprite].Width) <> 0 then + exit; + if isDYAreaOffscreen(Y - SpritesData[Sprite].Height div 2 , SpritesData[Sprite].Height) <> 0 then + exit; + end; + + +openglPushMatrix; +openglTranslatef(X, Y, 0); + +// mirror if Dir < 0 then - glRotatef(Angle, 0, 0, -1) -else - glRotatef(Angle, 0, 0, 1); -if Dir < 0 then - glScalef(-1.0, 1.0, 1.0); + openglScalef(-1.0, 1.0, 1.0); + +// apply angle after (conditional) mirroring +if Angle <> 0 then + openglRotatef(Angle, 0, 0, 1); DrawSprite(Sprite, -SpritesData[Sprite].Width div 2, -SpritesData[Sprite].Height div 2, Frame); -glPopMatrix +openglPopMatrix; + end; procedure DrawTextureRotated(Texture: PTexture; hw, hh, X, Y, Dir: LongInt; Angle: real); -var VertexBuffer: array [0..3] of TVertex2f; begin + +if isDxAreaOffscreen(X, 2 * hw) <> 0 then + exit; +if isDyAreaOffscreen(Y, 2 * hh) <> 0 then + exit; + // do not draw anything outside the visible screen space (first check fixes some sprite drawing, e.g. hedgehogs) -if (abs(X) > 2 * hw) and ((abs(X) - hw) > cScreenWidth / cScaleFactor) then +{if (abs(X) > 2 * hw) and ((abs(X) - hw) > cScreenWidth / cScaleFactor) then exit; if (abs(Y) > 2 * hh) and ((abs(Y - 0.5 * cScreenHeight) - hh) > cScreenHeight / cScaleFactor) then - exit; + exit;} -glPushMatrix; -glTranslatef(X, Y, 0); +openglPushMatrix; +openglTranslatef(X, Y, 0); if Dir < 0 then begin hw:= - hw; - glRotatef(Angle, 0, 0, -1); + openglRotatef(Angle, 0, 0, -1); end else - glRotatef(Angle, 0, 0, 1); - + openglRotatef(Angle, 0, 0, 1); glBindTexture(GL_TEXTURE_2D, Texture^.id); @@ -289,11 +1207,15 @@ VertexBuffer[3].X:= -hw; VertexBuffer[3].Y:= hh; -glVertexPointer(2, GL_FLOAT, 0, @VertexBuffer[0]); -glTexCoordPointer(2, GL_FLOAT, 0, @Texture^.tb); -glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer)); +SetVertexPointer(@VertexBuffer[0], 4); +SetTexCoordPointer(@Texture^.tb, 4); + +UpdateModelviewProjection; -glPopMatrix +glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + +openglPopMatrix; + end; procedure DrawSprite(Sprite: TSprite; X, Y, Frame: LongInt); @@ -335,7 +1257,7 @@ if (X + SpritesData[Sprite].Width > RightX) then r.w:= RightX - X + 1; -if (r.h < r.y) or (r.w < r.x) then +if (r.h < r.y) or (r.w < r.x) then exit; dec(r.h, r.y); @@ -346,12 +1268,20 @@ procedure DrawTextureCentered(X, Top: LongInt; Source: PTexture); var scale: GLfloat; + left : LongInt; begin + // scale down if larger than screen if (Source^.w + 20) > cScreenWidth then - scale:= cScreenWidth / (Source^.w + 20) + begin + scale:= cScreenWidth / (Source^.w + 20); + DrawTexture(X - round(Source^.w * scale) div 2, Top, Source, scale); + end else - scale:= 1.0; - DrawTexture(X - round(Source^.w * scale) div 2, Top, Source, scale) + begin + left:= X - Source^.w div 2; + if (not isAreaOffscreen(left, Top, Source^.w, Source^.h)) then + DrawTexture(left, Top, Source); + end; end; procedure DrawLine(X0, Y0, X1, Y1, Width: Single; color: LongWord); inline; @@ -360,13 +1290,23 @@ end; procedure DrawLine(X0, Y0, X1, Y1, Width: Single; r, g, b, a: Byte); -var VertexBuffer: array [0..1] of TVertex2f; begin - glDisable(GL_TEXTURE_2D); + openglPushMatrix(); + openglTranslatef(WorldDx, WorldDy, 0); + + UpdateModelviewProjection; + + DrawLineOnScreen(X0, Y0, X1, Y1, Width, r, g, b, a); + + openglPopMatrix(); +end; + +procedure DrawLineOnScreen(X0, Y0, X1, Y1, Width: Single; r, g, b, a: Byte); +begin glEnable(GL_LINE_SMOOTH); - glPushMatrix; - glTranslatef(WorldDx, WorldDy, 0); + EnableTexture(False); + glLineWidth(Width); Tint(r, g, b, a); @@ -375,72 +1315,106 @@ VertexBuffer[1].X:= X1; VertexBuffer[1].Y:= Y1; - glVertexPointer(2, GL_FLOAT, 0, @VertexBuffer[0]); - glDrawArrays(GL_LINES, 0, Length(VertexBuffer)); - untint; - - glPopMatrix; - - glEnable(GL_TEXTURE_2D); + SetVertexPointer(@VertexBuffer[0], 2); + glDrawArrays(GL_LINES, 0, 2); + untint(); + + EnableTexture(True); + glDisable(GL_LINE_SMOOTH); end; -procedure DrawFillRect(r: TSDL_Rect); -var VertexBuffer: array [0..3] of TVertex2f; +procedure DrawRect(rect: TSDL_Rect; r, g, b, a: Byte; Fill: boolean); begin // do not draw anything outside the visible screen space (first check fixes some sprite drawing, e.g. hedgehogs) -if (abs(r.x) > r.w) and ((abs(r.x + r.w / 2) - r.w / 2) * cScaleFactor > cScreenWidth) then +if (abs(rect.x) > rect.w) and ((abs(rect.x + rect.w / 2) - rect.w / 2) * 2 > ViewWidth) then exit; -if (abs(r.y) > r.h) and ((abs(r.y + r.h / 2 - (0.5 * cScreenHeight)) - r.h / 2) * cScaleFactor > cScreenHeight) then +if (abs(rect.y) > rect.h) and ((abs(rect.y + rect.h / 2 - (cScreenHeight / 2)) - rect.h / 2) * 2 > ViewHeight) then exit; -glDisable(GL_TEXTURE_2D); +EnableTexture(False); -Tint($00, $00, $00, $80); +Tint(r, g, b, a); -VertexBuffer[0].X:= r.x; -VertexBuffer[0].Y:= r.y; -VertexBuffer[1].X:= r.x + r.w; -VertexBuffer[1].Y:= r.y; -VertexBuffer[2].X:= r.x + r.w; -VertexBuffer[2].Y:= r.y + r.h; -VertexBuffer[3].X:= r.x; -VertexBuffer[3].Y:= r.y + r.h; +with rect do +begin + VertexBuffer[0].X:= x; + VertexBuffer[0].Y:= y; + VertexBuffer[1].X:= x + w; + VertexBuffer[1].Y:= y; + VertexBuffer[2].X:= x + w; + VertexBuffer[2].Y:= y + h; + VertexBuffer[3].X:= x; + VertexBuffer[3].Y:= y + h; +end; -glVertexPointer(2, GL_FLOAT, 0, @VertexBuffer[0]); -glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer)); +SetVertexPointer(@VertexBuffer[0], 4); +if Fill then + glDrawArrays(GL_TRIANGLE_FAN, 0, 4) +else + begin + glLineWidth(1); + glDrawArrays(GL_LINE_LOOP, 0, 4); + end; untint; -glEnable(GL_TEXTURE_2D) + +EnableTexture(True); + end; -procedure DrawCircle(X, Y, Radius, Width: LongInt; r, g, b, a: Byte); +procedure DrawCircle(X, Y, Radius, Width: LongInt; r, g, b, a: Byte); begin Tint(r, g, b, a); - DrawCircle(X, Y, Radius, Width); + DrawCircle(X, Y, Radius, Width); untint; end; -procedure DrawCircle(X, Y, Radius, Width: LongInt); +procedure DrawCircle(X, Y, Radius, Width: LongInt); var i: LongInt; - CircleVertex: array [0..59] of TVertex2f; begin + i:= Radius + Width; + if isDxAreaOffscreen(X - i, 2 * i) <> 0 then + exit; + if isDyAreaOffscreen(Y - i, 2 * i) <> 0 then + exit; + for i := 0 to 59 do begin - CircleVertex[i].X := X + Radius*cos(i*pi/30); - CircleVertex[i].Y := Y + Radius*sin(i*pi/30); + VertexBuffer[i].X := X + Radius*cos(i*pi/30); + VertexBuffer[i].Y := Y + Radius*sin(i*pi/30); end; - glDisable(GL_TEXTURE_2D); + + EnableTexture(False); glEnable(GL_LINE_SMOOTH); - glPushMatrix; + //openglPushMatrix; glLineWidth(Width); - glVertexPointer(2, GL_FLOAT, 0, @CircleVertex[0]); + SetVertexPointer(@VertexBuffer[0], 60); glDrawArrays(GL_LINE_LOOP, 0, 60); - glPopMatrix; - glEnable(GL_TEXTURE_2D); + //openglPopMatrix; + EnableTexture(True); glDisable(GL_LINE_SMOOTH); end; +procedure DrawCircleFilled(X, Y, Radius: LongInt; r, g, b, a: Byte); +var + i: LongInt; +begin + VertexBuffer[0].X := X; + VertexBuffer[0].Y := Y; + + for i := 1 to 19 do begin + VertexBuffer[i].X := X + Radius*cos(i*pi/9); + VertexBuffer[i].Y := Y + Radius*sin(i*pi/9); + end; + + EnableTexture(False); + Tint(r, g, b, a); + SetVertexPointer(@VertexBuffer[0], 20); + glDrawArrays(GL_TRIANGLE_FAN, 0, 20); + Untint(); + EnableTexture(True); +end; procedure DrawHedgehog(X, Y: LongInt; Dir: LongInt; Pos, Step: LongWord; Angle: real); const VertexBuffer: array [0..3] of TVertex2f = ( @@ -449,12 +1423,11 @@ (X: 16; Y: 16), (X: -16; Y: 16)); var l, r, t, b: real; - TextureBuffer: array [0..3] of TVertex2f; begin // do not draw anything outside the visible screen space (first check fixes some sprite drawing, e.g. hedgehogs) - if (abs(X) > 32) and ((abs(X) - 16) * cScaleFactor > cScreenWidth) then + if (abs(X) > 32) and ((abs(X) - 16) * 2 > ViewWidth) then exit; - if (abs(Y) > 32) and ((abs(Y - 0.5 * cScreenHeight) - 16) * cScaleFactor > cScreenHeight) then + if (abs(Y) > 32) and ((abs(Y - cScreenHeight / 2) - 16) * 2 > ViewHeight) then exit; t:= Pos * 32 / HHTexture^.h; @@ -471,10 +1444,9 @@ r:= (Step + 1) * 32 / HHTexture^.w end; - - glPushMatrix(); - glTranslatef(X, Y, 0); - glRotatef(Angle, 0, 0, 1); + openglPushMatrix(); + openglTranslatef(X, Y, 0); + openglRotatef(Angle, 0, 0, 1); glBindTexture(GL_TEXTURE_2D, HHTexture^.id); @@ -487,11 +1459,14 @@ TextureBuffer[3].X:= l; TextureBuffer[3].Y:= b; - glVertexPointer(2, GL_FLOAT, 0, @VertexBuffer[0]); - glTexCoordPointer(2, GL_FLOAT, 0, @TextureBuffer[0]); - glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer)); + SetVertexPointer(@VertexBuffer[0], 4); + SetTexCoordPointer(@TextureBuffer[0], 4); - glPopMatrix + UpdateModelviewProjection; + + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + openglPopMatrix; end; procedure DrawScreenWidget(widget: POnScreenWidget); @@ -505,9 +1480,9 @@ if RealTicks > (fadeAnimStart + FADE_ANIM_TIME) then fadeAnimStart:= 0 else - if show then + if show then alpha:= Byte(trunc((RealTicks - fadeAnimStart)/FADE_ANIM_TIME * $FF)) - else + else alpha:= Byte($FF - trunc((RealTicks - fadeAnimStart)/FADE_ANIM_TIME * $FF)); end; @@ -541,12 +1516,362 @@ {$ENDIF} end; +procedure BeginWater; +begin +{$IFDEF GL2} + glUseProgram(shaderWater); + uCurrentMVPLocation:=uWaterMVPLocation; + UpdateModelviewProjection; +{$ENDIF} + + openglUseColorOnly(true); +end; + +procedure EndWater; +begin +{$IFDEF GL2} + glUseProgram(shaderMain); + uCurrentMVPLocation:=uMainMVPLocation; + UpdateModelviewProjection; +{$ENDIF} + + openglUseColorOnly(false); +end; + +procedure PrepareVbForWater( + WithWalls: Boolean; + InTopY, OutTopY, InLeftX, OutLeftX, InRightX, OutRightX, BottomY: LongInt; + out first, count: LongInt); + +var firsti, afteri, lol: LongInt; +begin + + // We will draw both bottom water and the water walls with a single call, + // by rendering a GL_TRIANGLE_STRIP of eight points. + // + // GL_TRIANGLE_STRIP works like this: "always create triangle between + // newest point and the two points that were specified before it." + // + // To get the result we want we will order the points like this: + // ^ -Y + // | + // 0-------1 7-------6 <--------------------- OutTopY -| + // | /| | _/| | + // | / | | / | | + // | / | | _/ | | + // | / | | / | | + // | / _.3---------5{ | <--------------------- InTopY --| + // | / _/ `---.___ `--._ | | + // |/_/ `---.___\| | + // 2-------------------------4 <--------------------- BottomY -| + // | + // ^ ^ ^ ^ V +Y + // | | | | + // | | | | + // | | | | + // | | | | + // | | | | + // | | | | + // | | | | + // OutLeftX InLeftX InRightX OutRightX + // | | | | + // <----------------------------------------> + // -X +X + // + +firsti:= -1; +afteri:= 0; + +if InTopY < 0 then + InTopY:= 0; + +if not WithWalls then + begin + // if no walls are needed, then bottom water surface spans full length + InLeftX := OutLeftX; + InRightX:= OutRightX; + end +else + begin + + // animate water walls raise animation at start of game + if GameTicks < 2000 then + lol:= 2000 - GameTicks + else + lol:= 0; + + if InLeftX > ViewLeftX then + begin + VertexBuffer[0].X:= OutLeftX - lol; + VertexBuffer[0].Y:= OutTopY; + VertexBuffer[1].X:= InLeftX - lol; + VertexBuffer[1].Y:= OutTopY; + // shares vertices 2 and 3 with bottom water + firsti:= 0; + afteri:= 4; + end; + + if InRightX < ViewRightX then + begin + VertexBuffer[6].X:= OutRightX + lol; + VertexBuffer[6].Y:= OutTopY; + VertexBuffer[7].X:= InRightX + lol; + VertexBuffer[7].Y:= OutTopY; + // shares vertices 4 and 5 with bottom water + if firsti < 0 then + firsti:= 4; + afteri:= 8; + end; + end; + +if InTopY < ViewBottomY then + begin + // shares vertices 2-5 with water walls + + // starts at vertex 2 + if (firsti < 0) or (firsti > 2) then + firsti:= 2; + // ends at vertex 5 + if afteri < 6 then + afteri:= 6; + end; + +if firsti < 0 then + begin + // nothing to draw at all! + first:= -1; + count:= 0; + exit; + end; + +if firsti < 4 then + begin + VertexBuffer[2].X:= OutLeftX; + VertexBuffer[2].Y:= BottomY; + VertexBuffer[3].X:= InLeftX; + VertexBuffer[3].Y:= InTopY; + end; + +if afteri > 4 then + begin + VertexBuffer[4].X:= OutRightX; + VertexBuffer[4].Y:= BottomY; + VertexBuffer[5].X:= InRightX; + VertexBuffer[5].Y:= InTopY; + end; + +// first index to draw in vertex buffer +first:= firsti; +// number of points to draw +count:= afteri - firsti; + +end; + +procedure DrawWater(Alpha: byte; OffsetY, OffsetX: LongInt); +var first, count: LongInt; +begin + +if (WorldEdge <> weSea) then + PrepareVbForWater(false, + OffsetY + WorldDy + cWaterLine, 0, + 0, ViewLeftX, + 0, ViewRightX, + ViewBottomY, + first, count) +else + PrepareVbForWater(true, + OffsetY + WorldDy + cWaterLine, ViewTopY, + LongInt(LeftX) + WorldDx - OffsetX, ViewLeftX, + LongInt(RightX) + WorldDx + OffsetX, ViewRightX, + ViewBottomY, + first, count); + +// quit if there's nothing to draw (nothing in view) +if count < 1 then + exit; + +// drawing time + +UpdateModelviewProjection; + +BeginWater; + +if SuddenDeathDmg then + begin // only set alpha if it differs from what we want + if SDWaterColorArray[0].a <> Alpha then + begin + SDWaterColorArray[0].a := Alpha; + SDWaterColorArray[1].a := Alpha; + SDWaterColorArray[2].a := Alpha; + SDWaterColorArray[3].a := Alpha; + SDWaterColorArray[4].a := Alpha; + SDWaterColorArray[5].a := Alpha; + SDWaterColorArray[6].a := Alpha; + SDWaterColorArray[7].a := Alpha; + end; + SetColorPointer(@SDWaterColorArray[0], 8); + end +else + begin + if WaterColorArray[0].a <> Alpha then + begin + WaterColorArray[0].a := Alpha; + WaterColorArray[1].a := Alpha; + WaterColorArray[2].a := Alpha; + WaterColorArray[3].a := Alpha; + WaterColorArray[4].a := Alpha; + WaterColorArray[5].a := Alpha; + WaterColorArray[6].a := Alpha; + WaterColorArray[7].a := Alpha; + end; + SetColorPointer(@WaterColorArray[0], 8); + end; + +SetVertexPointer(@VertexBuffer[0], 8); + +glDrawArrays(GL_TRIANGLE_STRIP, first, count); + +EndWater; + +{$IFNDEF GL2} +// must not be Tint() as color array seems to stay active and color reset is required +glColor4ub($FF, $FF, $FF, $FF); +{$ENDIF} +end; + +procedure DrawWaves(Dir, dX, dY, oX: LongInt; tnt: Byte); +var first, count, topy, lx, rx, spriteHeight, spriteWidth: LongInt; + lw, nWaves, shift: GLfloat; + sprite: TSprite; +begin +// note: spriteHeight is the Height of the wave sprite while +// cWaveHeight describes how many pixels of it will be above waterline + +if SuddenDeathDmg then + sprite:= sprSDWater +else + sprite:= sprWater; + +spriteHeight:= SpritesData[sprite].Height; + +// shift parameters by wave height +// ( ox and dy are used to create different horizontal and vertical offsets +// between wave layers ) +dY:= -cWaveHeight + dy; +ox:= -cWaveHeight + ox; + +lx:= LongInt(LeftX) + WorldDx - ox; +rx:= LongInt(RightX) + WorldDx + ox; + +topy:= cWaterLine + WorldDy + dY; + + +if (WorldEdge <> weSea) then + PrepareVbForWater(false, + topy, 0, + 0, ViewLeftX, + 0, ViewRightX, + topy + spriteHeight, + first, count) +else + PrepareVbForWater(true, + topy, ViewTopY, + lx, lx - spriteHeight, + rx, rx + spriteHeight, + topy + spriteHeight, + first, count); + +// quit if there's nothing to draw (nothing in view) +if count < 1 then + exit; + +if SuddenDeathDmg then + Tint(LongInt(tnt) * SDWaterColorArray[1].r div 255 + 255 - tnt, + LongInt(tnt) * SDWaterColorArray[1].g div 255 + 255 - tnt, + LongInt(tnt) * SDWaterColorArray[1].b div 255 + 255 - tnt, + 255 + ) +else + Tint(LongInt(tnt) * WaterColorArray[1].r div 255 + 255 - tnt, + LongInt(tnt) * WaterColorArray[1].g div 255 + 255 - tnt, + LongInt(tnt) * WaterColorArray[1].b div 255 + 255 - tnt, + 255 + ); + +if WorldEdge = weSea then + begin + lw:= playWidth; + dX:= ox; + end +else + begin + lw:= ViewWidth; + dx:= dx - WorldDx; + end; + +spriteWidth:= SpritesData[sprite].Width; +nWaves:= lw / spriteWidth; + shift:= - nWaves / 2; + +TextureBuffer[3].X:= shift + ((LongInt(RealTicks shr 6) * Dir + dX) mod spriteWidth) / (spriteWidth - 1); +TextureBuffer[3].Y:= 0; +TextureBuffer[5].X:= TextureBuffer[3].X + nWaves; +TextureBuffer[5].Y:= 0; +TextureBuffer[4].X:= TextureBuffer[5].X; +TextureBuffer[4].Y:= SpritesData[sprite].Texture^.ry; +TextureBuffer[2].X:= TextureBuffer[3].X; +TextureBuffer[2].Y:= SpritesData[sprite].Texture^.ry; + +if (WorldEdge = weSea) then + begin + nWaves:= (topy - ViewTopY) / spriteWidth; + + // left side + TextureBuffer[1].X:= TextureBuffer[3].X - nWaves; + TextureBuffer[1].Y:= 0; + TextureBuffer[0].X:= TextureBuffer[1].X; + TextureBuffer[0].Y:= SpritesData[sprite].Texture^.ry; + + // right side + TextureBuffer[7].X:= TextureBuffer[5].X + nWaves; + TextureBuffer[7].Y:= 0; + TextureBuffer[6].X:= TextureBuffer[7].X; + TextureBuffer[6].Y:= SpritesData[sprite].Texture^.ry; + end; + +glBindTexture(GL_TEXTURE_2D, SpritesData[sprite].Texture^.id); + +SetVertexPointer(@VertexBuffer[0], 8); +SetTexCoordPointer(@TextureBuffer[0], 8); + +UpdateModelviewProjection; + +glDrawArrays(GL_TRIANGLE_STRIP, first, count); + +untint; + +end; + +procedure openglTint(r, g, b, a: Byte); inline; +{$IFDEF GL2} +const + scale:Real = 1.0/255.0; +{$ENDIF} +begin + {$IFDEF GL2} + glUniform4f(uMainTintLocation, r*scale, g*scale, b*scale, a*scale); + {$ELSE} + glColor4ub(r, g, b, a); + {$ENDIF} +end; + procedure Tint(r, g, b, a: Byte); inline; -var nc, tw: Longword; +var + nc, tw: Longword; begin nc:= (r shl 24) or (g shl 16) or (b shl 8) or a; - if nc = lastTint then + if nc = LastTint then exit; if GrayScale then @@ -559,19 +1884,21 @@ b:= tw end; - glColor4ub(r, g, b, a); - lastTint:= nc; + openglTint(r, g, b, a); + LastTint:= nc; end; procedure Tint(c: Longword); inline; begin - if c = lastTint then exit; + if c = LastTint then exit; Tint(((c shr 24) and $FF), ((c shr 16) and $FF), (c shr 8) and $FF, (c and $FF)) end; procedure untint(); inline; begin - Tint($FF, $FF, $FF, $FF) + if cWhiteColor = LastTint then exit; + openglTint($FF, $FF, $FF, $FF); + LastTint:= cWhiteColor; end; procedure setTintAdd(f: boolean); inline; @@ -582,4 +1909,63 @@ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); end; +procedure ChangeDepth(rm: TRenderMode; d: GLfloat); +var tmp: LongInt; +begin +{$IFNDEF USE_S3D_RENDERING} + rm:= rm; d:= d; tmp:= tmp; // avoid hint +{$ELSE} + d:= d / 5; + if rm = rmDefault then + exit + else if rm = rmLeftEye then + d:= -d; + cStereoDepth:= cStereoDepth + d; + openglTranslProjMatrix(d, 0, 0); + tmp:= round(d / cScaleFactor * cScreenWidth); + ViewLeftX := ViewLeftX - tmp; + ViewRightX:= ViewRightX - tmp; +{$ENDIF} +end; + +procedure ResetDepth(rm: TRenderMode); +var tmp: LongInt; +begin +{$IFNDEF USE_S3D_RENDERING} + rm:= rm; tmp:= tmp; // avoid hint +{$ELSE} + if rm = rmDefault then + exit; + openglTranslProjMatrix(-cStereoDepth, 0, 0); + tmp:= round(cStereoDepth / cScaleFactor * cScreenWidth); + ViewLeftX := ViewLeftX + tmp; + ViewRightX:= ViewRightX + tmp; + cStereoDepth:= 0; +{$ENDIF} +end; + + +procedure initModule; +begin + LastTint:= cWhiteColor + 1; + LastColorPointer := nil; + LastTexCoordPointer := nil; + LastVertexPointer := nil; +{$IFDEF GL2} + LastColorPointerN := 0; + LastTexCoordPointerN:= 0; + LastVertexPointerN := 0; +{$ENDIF} +end; + +procedure freeModule; +begin +{$IFDEF GL2} + glDeleteProgram(shaderMain); + glDeleteProgram(shaderWater); + glDeleteBuffers(1, @vBuffer); + glDeleteBuffers(1, @tBuffer); + glDeleteBuffers(1, @cBuffer); +{$ENDIF} +end; end. diff -r 31570b766315 -r ed5a6478e710 hedgewars/uRenderUtils.pas --- a/hedgewars/uRenderUtils.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uRenderUtils.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} @@ -68,7 +68,7 @@ r.y:= rect^.y + 2; r.w:= rect^.w - 2; r.h:= rect^.h - 4; - SDL_FillRect(Surface, @r, FillColor) + SDL_FillRect(Surface, @r, FillColor); end; (* function WriteInRoundRect(Surface: PSDL_Surface; X, Y: LongInt; Color: LongWord; Font: THWFont; s: ansistring): TSDL_Rect; @@ -77,13 +77,13 @@ end;*) function WriteInRoundRect(Surface: PSDL_Surface; X, Y: LongInt; Color: LongWord; Font: THWFont; s: ansistring; maxLength: LongWord): TSDL_Rect; -var w, h: LongInt; +var w, h: Longword; tmpsurf: PSDL_Surface; clr: TSDL_Color; finalRect, textRect: TSDL_Rect; begin - TTF_SizeUTF8(Fontz[Font].Handle, Str2PChar(s), @w, @h); - if (maxLength <> 0) and (w > maxLength) then w := maxLength; + TTF_SizeUTF8(Fontz[Font].Handle, PChar(s), @w, @h); + if (maxLength > 0) and (w > maxLength) then w := maxLength; finalRect.x:= X; finalRect.y:= Y; finalRect.w:= w + cFontBorder * 2 + 4; @@ -96,7 +96,7 @@ clr.r:= (Color shr 16) and $FF; clr.g:= (Color shr 8) and $FF; clr.b:= Color and $FF; - tmpsurf:= TTF_RenderUTF8_Blended(Fontz[Font].Handle, Str2PChar(s), clr); + tmpsurf:= TTF_RenderUTF8_Blended(Fontz[Font].Handle, PChar(s), clr); finalRect.x:= X + cFontBorder + 2; finalRect.y:= Y + cFontBorder; SDLTry(tmpsurf <> nil, 'TTF_RenderUTF8_Blended', true); @@ -115,6 +115,7 @@ pixels: PLongWordArray; begin TryDo(Surface^.format^.BytesPerPixel = 4, 'flipSurface failed, expecting 32 bit surface', true); + SDL_LockSurface(Surface); pixels:= Surface^.pixels; if Vertical then for y := 0 to (Surface^.h div 2) - 1 do @@ -136,6 +137,7 @@ pixels^[i]:= pixels^[j]; pixels^[j]:= tmpPixel; end; + SDL_UnlockSurface(Surface); end; procedure copyToXY(src, dest: PSDL_Surface; destX, destY: LongInt); inline; @@ -150,6 +152,10 @@ begin maxDest:= (dest^.pitch div 4) * dest^.h; maxSrc:= (src^.pitch div 4) * src^.h; + + SDL_LockSurface(src); + SDL_LockSurface(dest); + srcPixels:= src^.pixels; destPixels:= dest^.pixels; @@ -165,10 +171,13 @@ r0:= (r0 * (255 - LongInt(a1)) + r1 * LongInt(a1)) div 255; g0:= (g0 * (255 - LongInt(a1)) + g1 * LongInt(a1)) div 255; b0:= (b0 * (255 - LongInt(a1)) + b1 * LongInt(a1)) div 255; - a0:= (a0 * (255 - LongInt(a1)) + a1 * LongInt(a1)) div 255; + a0:= a0 + ((255 - LongInt(a0)) * a1 div 255); destPixels^[i]:= SDL_MapRGBA(dest^.format, r0, g0, b0, a0); end; end; + + SDL_UnlockSurface(src); + SDL_UnlockSurface(dest); end; procedure DrawSprite2Surf(sprite: TSprite; dest: PSDL_Surface; x,y: LongInt); inline; @@ -182,12 +191,12 @@ numFramesFirstCol:= SpritesData[sprite].imageHeight div SpritesData[sprite].Height; row:= Frame mod numFramesFirstCol; col:= Frame div numFramesFirstCol; - - copyToXYFromRect(SpritesData[sprite].Surface, dest, - col*SpritesData[sprite].Width, - row*SpritesData[sprite].Height, - SpritesData[sprite].Width, - spritesData[sprite].Height, + + copyToXYFromRect(SpritesData[sprite].Surface, dest, + col*SpritesData[sprite].Width, + row*SpritesData[sprite].Height, + SpritesData[sprite].Width, + spritesData[sprite].Height, x,y); end; @@ -199,13 +208,16 @@ begin //max:= (dest^.pitch div 4) * dest^.h; yMax:= dest^.pitch div 4; + + SDL_LockSurface(dest); + destPixels:= dest^.pixels; dx:= abs(x1-x0); dy:= abs(y1-y0); if x0 < x1 then sx:= 1 else sx:= -1; if y0 < y1 then sy:= 1 else sy:= -1; - err:= dx-dy; + err:= dx-dy; while(true) do begin @@ -225,7 +237,8 @@ err:= err + dx; y0:=y0+sy end; - end; + end; + SDL_UnlockSurface(dest); end; procedure copyRotatedSurface(src, dest: PSDL_Surface); // this is necessary since width/height are read only in SDL, apparently @@ -235,6 +248,9 @@ TryDo(src^.format^.BytesPerPixel = 4, 'rotateSurface failed, expecting 32 bit surface', true); TryDo(dest^.format^.BytesPerPixel = 4, 'rotateSurface failed, expecting 32 bit surface', true); + SDL_LockSurface(src); + SDL_LockSurface(dest); + srcPixels:= src^.pixels; destPixels:= dest^.pixels; @@ -246,6 +262,10 @@ destPixels^[j]:= srcPixels^[i]; inc(j) end; + + SDL_UnlockSurface(src); + SDL_UnlockSurface(dest); + end; function RenderStringTex(s: ansistring; Color: Longword; font: THWFont): PTexture; @@ -254,54 +274,116 @@ end; function RenderStringTexLim(s: ansistring; Color: Longword; font: THWFont; maxLength: LongWord): PTexture; -var w, h: LongInt; +var w, h: Longword; finalSurface: PSDL_Surface; begin - if length(s) = 0 then s:= _S' '; - font:= CheckCJKFont(s, font); - w:= 0; h:= 0; // avoid compiler hints - TTF_SizeUTF8(Fontz[font].Handle, Str2PChar(s), @w, @h); - if (maxLength <> 0) and (w > maxLength) then w := maxLength; - - finalSurface:= SDL_CreateRGBSurface(SDL_SWSURFACE, w + cFontBorder * 2 + 4, h + cFontBorder * 2, - 32, RMask, GMask, BMask, AMask); + if cOnlyStats then + begin + RenderStringTexLim:= nil; + end + else + begin + if length(s) = 0 then s:= _S' '; + font:= CheckCJKFont(s, font); + w:= 0; h:= 0; // avoid compiler hints + TTF_SizeUTF8(Fontz[font].Handle, PChar(s), @w, @h); + if (maxLength > 0) and (w > maxLength) then w := maxLength; - TryDo(finalSurface <> nil, 'RenderString: fail to create surface', true); + finalSurface:= SDL_CreateRGBSurface(SDL_SWSURFACE, w + cFontBorder * 2 + 4, h + cFontBorder * 2, + 32, RMask, GMask, BMask, AMask); - WriteInRoundRect(finalSurface, 0, 0, Color, font, s, maxLength); + TryDo(finalSurface <> nil, 'RenderString: fail to create surface', true); + + WriteInRoundRect(finalSurface, 0, 0, Color, font, s, maxLength); - TryDo(SDL_SetColorKey(finalSurface, SDL_SRCCOLORKEY, 0) = 0, errmsgTransparentSet, true); + TryDo(SDL_SetColorKey(finalSurface, SDL_SRCCOLORKEY, 0) = 0, errmsgTransparentSet, true); - RenderStringTexLim:= Surface2Tex(finalSurface, false); + RenderStringTexLim:= Surface2Tex(finalSurface, false); - SDL_FreeSurface(finalSurface); + SDL_FreeSurface(finalSurface); + end; end; +function GetNextSpeechLine(s: ansistring; ldelim: char; var startFrom: LongInt; out substr: ansistring): boolean; +var p, l, m, r: Integer; + newl, skip: boolean; + c : char; +begin + m:= Length(s); + + substr:= ''; + + SetLengthA(substr, m); + + // number of chars read + r:= 0; + + // number of chars to be written + l:= 0; + + newl:= true; + + for p:= max(1, startFrom) to m do + begin + + inc(r); + // read char from source string + c:= s[p]; + + // strip empty lines, spaces and newlines on beginnings of line + skip:= ((newl or (p = m)) and ((c = ' ') or (c = ldelim))); + + if (not skip) then + begin + newl:= (c = ldelim); + // stop if we went past the end of the line + if newl then + break; + + // copy current char to output substring + inc(l); + substr[l]:= c; + end; + + end; + + inc(startFrom, r); + + SetLengthA(substr, l); + + GetNextSpeechLine:= (l > 0); +end; function RenderSpeechBubbleTex(s: ansistring; SpeechType: Longword; font: THWFont): PTexture; -var textWidth, textHeight, x, y, w, h, i, j, pos, prevpos, line, numLines, edgeWidth, edgeHeight, cornerWidth, cornerHeight: LongInt; +var textWidth, textHeight, x, y, w, h, i, j, pos, line, numLines, edgeWidth, edgeHeight, cornerWidth, cornerHeight: LongInt; finalSurface, tmpsurf, rotatedEdge: PSDL_Surface; rect: TSDL_Rect; + {$IFNDEF PAS2C} chars: set of char = [#9,' ',';',':','?','!',',']; - substr: shortstring; + {$ENDIF} + substr: ansistring; edge, corner, tail: TSPrite; begin + if cOnlyStats then exit(nil); + case SpeechType of - 1: begin; - edge:= sprSpeechEdge; - corner:= sprSpeechCorner; - tail:= sprSpeechTail; - end; - 2: begin; - edge:= sprThoughtEdge; - corner:= sprThoughtCorner; - tail:= sprThoughtTail; - end; - 3: begin; - edge:= sprShoutEdge; - corner:= sprShoutCorner; - tail:= sprShoutTail; - end; + 1: begin + edge:= sprSpeechEdge; + corner:= sprSpeechCorner; + tail:= sprSpeechTail; + end; + 2: begin + edge:= sprThoughtEdge; + corner:= sprThoughtCorner; + tail:= sprThoughtTail; + end; + 3: begin + edge:= sprShoutEdge; + corner:= sprShoutCorner; + tail:= sprShoutTail; + end + else + exit(nil) end; edgeHeight:= SpritesData[edge].Height; edgeWidth:= SpritesData[edge].Width; @@ -318,7 +400,7 @@ s:= '...'; font:= CheckCJKFont(s, font); w:= 0; h:= 0; // avoid compiler hints - TTF_SizeUTF8(Fontz[font].Handle, Str2PChar(s), @w, @h); + TTF_SizeUTF8(Fontz[font].Handle, PChar(s), @w, @h); if w<8 then w:= 8; j:= 0; @@ -326,28 +408,28 @@ begin w:= 0; i:= round(Sqrt(length(s)) * 2); + {$IFNDEF PAS2C} s:= WrapText(s, #1, chars, i); - pos:= 1; prevpos:= 0; line:= 0; + {$ENDIF} + pos:= 1; line:= 0; // Find the longest line for the purposes of centring the text. Font dependant. - while pos <= length(s) do + while GetNextSpeechLine(s, #1, pos, substr) do begin - if (s[pos] = #1) or (pos = length(s)) then - begin - inc(numlines); - if s[pos] <> #1 then inc(pos); - while s[prevpos+1] = ' ' do inc(prevpos); - substr:= copy(s, prevpos+1, pos-prevpos-1); - i:= 0; j:= 0; - TTF_SizeUTF8(Fontz[font].Handle, Str2PChar(substr), @i, @j); - if i > w then - w:= i; - prevpos:= pos; - end; - inc(pos); + inc(numLines); + i:= 0; j:= 0; + TTF_SizeUTF8(Fontz[font].Handle, PChar(substr), @i, @j); + if i > w then + w:= i; end; end else numLines := 1; + if numLines < 1 then + begin + s:= '...'; + numLines:= 1; + end; + textWidth:=((w-(cornerWidth-edgeWidth)*2) div edgeWidth)*edgeWidth+edgeWidth; textHeight:=(((numlines * h + 2)-((cornerHeight-edgeWidth)*2)) div edgeWidth)*edgeWidth; @@ -433,36 +515,24 @@ j:= rect.h; SDL_FillRect(finalSurface, @rect, cWhiteColor); - pos:= 1; prevpos:= 0; line:= 0; - while pos <= length(s) do + pos:= 1; line:= 0; + while GetNextSpeechLine(s, #1, pos, substr) do begin - if (s[pos] = #1) or (pos = length(s)) then - begin - if s[pos] <> #1 then - inc(pos); - while s[prevpos+1] = ' 'do - inc(prevpos); - substr:= copy(s, prevpos+1, pos-prevpos-1); - if Length(substr) <> 0 then - begin - tmpsurf:= TTF_RenderUTF8_Blended(Fontz[Font].Handle, Str2PChar(substr), cNearBlackColorChannels); - rect.x:= edgeHeight + 1 + ((i - w) div 2); - // trying to more evenly position the text, vertically - rect.y:= edgeHeight + ((j-(numLines*h)) div 2) + line * h; - SDLTry(tmpsurf <> nil, 'TTF_RenderUTF8_Blended', true); - SDL_UpperBlit(tmpsurf, nil, finalSurface, @rect); - SDL_FreeSurface(tmpsurf); - inc(line); - prevpos:= pos; - end; - end; - inc(pos); + tmpsurf:= TTF_RenderUTF8_Blended(Fontz[Font].Handle, PChar(substr), cNearBlackColorChannels); + rect.x:= edgeHeight + 1 + ((i - w) div 2); + // trying to more evenly position the text, vertically + rect.y:= edgeHeight + ((j-(numLines*h)) div 2) + line * h; + SDLTry(tmpsurf <> nil, 'TTF_Init', true); + SDL_UpperBlit(tmpsurf, nil, finalSurface, @rect); + SDL_FreeSurface(tmpsurf); + inc(line); end; RenderSpeechBubbleTex:= Surface2Tex(finalSurface, true); SDL_FreeSurface(rotatedEdge); SDL_FreeSurface(finalSurface); + end; end. diff -r 31570b766315 -r ed5a6478e710 hedgewars/uScript.pas --- a/hedgewars/uScript.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uScript.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} @@ -35,9 +35,11 @@ procedure ScriptClearStack; procedure ScriptLoad(name : shortstring); +procedure ScriptOnPreviewInit; procedure ScriptOnGameInit; procedure ScriptOnScreenResize; procedure ScriptSetInteger(name : shortstring; value : LongInt); +procedure ScriptSetString(name : shortstring; value : shortstring); procedure ScriptCall(fname : shortstring); function ScriptCall(fname : shortstring; par1: LongInt) : LongInt; @@ -46,6 +48,7 @@ function ScriptCall(fname : shortstring; par1, par2, par3, par4 : LongInt) : LongInt; function ScriptExists(fname : shortstring) : boolean; +procedure LuaParseString(s: shortString); //function ParseCommandOverride(key, value : shortstring) : shortstring; This did not work out well @@ -85,7 +88,10 @@ uVisualGearsList, uGearsHandlersMess, uPhysFSLayer, - typinfo + SDLh +{$IFNDEF PAS2C} + , typinfo +{$ENDIF} ; var luaState : Plua_State; @@ -95,22 +101,241 @@ ScriptAmmoReinforcement : shortstring; ScriptLoaded : boolean; mapDims : boolean; + PointsBuffer: shortstring; + prevCursorPoint: TPoint; // why is tpoint still in sdlh... procedure ScriptPrepareAmmoStore; forward; procedure ScriptApplyAmmoStore; forward; procedure ScriptSetAmmo(ammo : TAmmoType; count, probability, delay, reinforcement: Byte); forward; procedure ScriptSetAmmoDelay(ammo : TAmmoType; delay: Byte); forward; +var LuaDebugInfo: lua_Debug; + +procedure SetGlobals; forward; +procedure LuaParseString(s: shortString); +begin + SetGlobals; + AddFileLog('[Lua] input string: ' + s); + AddChatString(#3 + '[Lua] > ' + s); + if luaL_dostring(luaState, Str2PChar(s)) <> 0 then + begin + AddFileLog('[Lua] input string parsing error!'); + AddChatString(#5 + '[Lua] Error while parsing!'); + end; +end; + +function LuaUpdateDebugInfo(): Boolean; +begin + FillChar(LuaDebugInfo, sizeof(LuaDebugInfo), 0); + + if lua_getstack(luaState, 1, @LuaDebugInfo) = 0 then + exit(false); // stack not deep enough + + // get source name and line count + lua_getinfo(luaState, PChar('Sl'), @LuaDebugInfo); + exit(true); +end; + procedure LuaError(s: shortstring); +var src: shortstring; +const + maxsrclen = 20; begin + if LuaUpdateDebugInfo() then + begin + src:= StrPas(LuaDebugInfo.source); + s:= 'LUA ERROR [ ... ' + + copy(src, Length(src) - maxsrclen, maxsrclen - 3) + ':' + + inttostr(LuaDebugInfo.currentLine) + ']: ' + s; + end + else + s:= 'LUA ERROR: ' + s; WriteLnToConsole(s); AddChatString(#5 + s); + if cTestLua then + halt(HaltTestLuaError); +end; + +procedure LuaCallError(error, call, paramsyntax: shortstring); +begin + LuaError(call + ': ' + error); + LuaError('-- SYNTAX: ' + call + ' ( ' + paramsyntax + ' )'); +end; + +procedure LuaParameterCountError(expected, call, paramsyntax: shortstring; wrongcount: LongInt); inline; +begin + // TODO: i18n? + LuaCallError('Wrong number of parameters! (is: ' + inttostr(wrongcount) + ', should be: '+ expected + ')', call, paramsyntax); +end; + +// compare with allowed count +function CheckLuaParamCount(L : Plua_State; count: LongInt; call, paramsyntax: shortstring): boolean; inline; +var c: LongInt; +begin + c:= lua_gettop(L); + if c <> count then + begin + LuaParameterCountError('exactly ' + inttostr(count), call, paramsyntax, c); + exit(false); + end; + + CheckLuaParamCount:= true; +end; + +// check if is either count1 or count2 +function CheckAndFetchParamCount(L : Plua_State; count1, count2: LongInt; call, paramsyntax: shortstring; out actual: LongInt): boolean; inline; +begin + actual:= lua_gettop(L); + if (actual <> count1) and (actual <> count2) then + begin + LuaParameterCountError('either ' + inttostr(count1) + ' or ' + inttostr(count2), call, paramsyntax, actual); + exit(false); + end; + + CheckAndFetchParamCount:= true; +end; + +// check if is in range of count1 and count2 +function CheckAndFetchParamCountRange(L : Plua_State; count1, count2: LongInt; call, paramsyntax: shortstring; out actual: LongInt): boolean; inline; +begin + actual:= lua_gettop(L); + if (actual < count1) or (actual > count2) then + begin + LuaParameterCountError('at least ' + inttostr(count1) + ', but at most ' + inttostr(count2), call, paramsyntax, actual); + exit(false); + end; + + CheckAndFetchParamCountRange:= true; +end; + +// check if is same or higher as minCount +function CheckAndFetchLuaParamMinCount(L : Plua_State; minCount: LongInt; call, paramsyntax: shortstring; out actual: LongInt): boolean; inline; +begin + actual:= lua_gettop(L); + if (actual < minCount) then + begin + LuaParameterCountError(inttostr(minCount) + ' or more', call, paramsyntax, actual); + exit(false); + end; + + CheckAndFetchLuaParamMinCount:= true; +end; + +function LuaToGearTypeOrd(L : Plua_State; i: LongInt; call, paramsyntax: shortstring): LongInt; inline; +begin + if lua_isnoneornil(L, i) then i:= -1 + else i:= lua_tointeger(L, i); + if (i < ord(Low(TGearType))) or (i > ord(High(TGearType))) then + begin + LuaCallError('Invalid gearType!', call, paramsyntax); + LuaToGearTypeOrd:= -1; + end + else + LuaToGearTypeOrd:= i; end; -procedure LuaParameterCountError(call, paramsyntax: shortstring; wrongcount: LongInt); +function LuaToVisualGearTypeOrd(L : Plua_State; i: LongInt; call, paramsyntax: shortstring): LongInt; inline; +begin + if lua_isnoneornil(L, i) then i:= -1 + else i:= lua_tointeger(L, i); + if (i < ord(Low(TVisualGearType))) or (i > ord(High(TVisualGearType))) then + begin + LuaCallError('Invalid visualGearType!', call, paramsyntax); + LuaToVisualGearTypeOrd:= -1; + end + else + LuaToVisualGearTypeOrd:= i; +end; + +function LuaToAmmoTypeOrd(L : Plua_State; i: LongInt; call, paramsyntax: shortstring): LongInt; inline; +begin + if lua_isnoneornil(L, i) then i:= -1 + else i:= lua_tointeger(L, i); + if (i < ord(Low(TAmmoType))) or (i > ord(High(TAmmoType))) then + begin + LuaCallError('Invalid ammoType!', call, paramsyntax); + LuaToAmmoTypeOrd:= -1; + end + else + LuaToAmmoTypeOrd:= i; +end; + +function LuaToStatInfoTypeOrd(L : Plua_State; i: LongInt; call, paramsyntax: shortstring): LongInt; inline; +begin + if lua_isnoneornil(L, i) then i:= -1 + else i:= lua_tointeger(L, i); + if (i < ord(Low(TStatInfoType))) or (i > ord(High(TStatInfoType))) then + begin + LuaCallError('Invalid statInfoType!', call, paramsyntax); + LuaToStatInfoTypeOrd:= -1; + end + else + LuaToStatInfoTypeOrd:= i; +end; + +function LuaToSoundOrd(L : Plua_State; i: LongInt; call, paramsyntax: shortstring): LongInt; inline; begin - // TODO: i18n? - LuaError('Lua: Wrong number of parameters (' + inttostr(wrongcount) + ') passed to ' + call + '! syntax: ' + call + ' ( ' + paramsyntax + ' )'); + if lua_isnoneornil(L, i) then i:= -1 + else i:= lua_tointeger(L, i); + if (i < ord(Low(TSound))) or (i > ord(High(TSound))) then + begin + LuaCallError('Invalid soundId!', call, paramsyntax); + LuaToSoundOrd:= -1; + end + else + LuaToSoundOrd:= i; +end; + +function LuaToHogEffectOrd(L : Plua_State; i: LongInt; call, paramsyntax: shortstring): LongInt; inline; +begin + if lua_isnoneornil(L, i) then i:= -1 + else i:= lua_tointeger(L, i); + if (i < ord(Low(THogEffect))) or (i > ord(High(THogEffect))) then + begin + LuaCallError('Invalid gear type!', call, paramsyntax); + LuaToHogEffectOrd:= -1; + end + else + LuaToHogEffectOrd:= i; +end; + +function LuaToCapGroupOrd(L : Plua_State; i: LongInt; call, paramsyntax: shortstring): LongInt; inline; +begin + if lua_isnoneornil(L, i) then i:= -1 + else i:= lua_tointeger(L, i); + if (i < ord(Low(TCapGroup))) or (i > ord(High(TCapGroup))) then + begin + LuaCallError('Invalid capgroup type!', call, paramsyntax); + LuaToCapGroupOrd:= -1; + end + else + LuaToCapGroupOrd:= i; +end; + +function LuaToSpriteOrd(L : Plua_State; i: LongInt; call, paramsyntax: shortstring): LongInt; inline; +begin + if lua_isnoneornil(L, i) then i:= -1 + else i:= lua_tointeger(L, i); + if (i < ord(Low(TSprite))) or (i > ord(High(TSprite))) then + begin + LuaCallError('Invalid sprite id!', call, paramsyntax); + LuaToSpriteOrd:= -1; + end + else + LuaToSpriteOrd:= i; +end; + +function LuaToMapGenOrd(L : Plua_State; i: LongInt; call, paramsyntax: shortstring): LongInt; inline; +begin + if lua_isnoneornil(L, i) then i:= -1 + else i:= lua_tointeger(L, i); + if (i < ord(Low(TMapGen))) or (i > ord(High(TMapGen))) then + begin + LuaCallError('Invalid mapgen id!', call, paramsyntax); + LuaToMapGenOrd:= -1; + end + else + LuaToMapGenOrd:= i; end; // wrapped calls // @@ -118,82 +343,65 @@ // functions called from Lua: // function(L : Plua_State) : LongInt; Cdecl; // where L contains the state, returns the number of return values on the stack -// call lua_gettop(L) to receive number of parameters passed +// call CheckLuaParamCount or CheckAndFetchParamCount +// to validate/get the number of passed arguments (see their call definitions) +// +// use as return value the number of variables pushed back to the lua script function lc_band(L: PLua_State): LongInt; Cdecl; begin - if lua_gettop(L) <> 2 then - begin - LuaParameterCountError('band', 'value1, value2', lua_gettop(L)); + if CheckLuaParamCount(L, 2, 'band', 'value1, value2') then + lua_pushinteger(L, lua_tointeger(L, 2) and lua_tointeger(L, 1)) + else lua_pushnil(L); - end - else - lua_pushinteger(L, lua_tointeger(L, 2) and lua_tointeger(L, 1)); lc_band := 1; end; function lc_bor(L: PLua_State): LongInt; Cdecl; begin - if lua_gettop(L) <> 2 then - begin - LuaParameterCountError('bor', 'value1, value2', lua_gettop(L)); + if CheckLuaParamCount(L, 2, 'bor', 'value1, value2') then + lua_pushinteger(L, lua_tointeger(L, 2) or lua_tointeger(L, 1)) + else lua_pushnil(L); - end - else - lua_pushinteger(L, lua_tointeger(L, 2) or lua_tointeger(L, 1)); lc_bor := 1; end; function lc_bnot(L: PLua_State): LongInt; Cdecl; begin - if lua_gettop(L) <> 1 then - begin - LuaParameterCountError('bnot', 'value', lua_gettop(L)); + if CheckLuaParamCount(L, 1, 'bnot', 'value') then + lua_pushinteger(L, (not lua_tointeger(L, 1))) + else lua_pushnil(L); - end - else - lua_pushinteger(L, not lua_tointeger(L, 1)); lc_bnot := 1; end; function lc_div(L: PLua_State): LongInt; Cdecl; begin - if lua_gettop(L) <> 2 then - begin - LuaParameterCountError('div', 'dividend, divisor', lua_gettop(L)); + if CheckLuaParamCount(L, 2, 'div', 'dividend, divisor') then + lua_pushinteger(L, lua_tointeger(L, 1) div lua_tointeger(L, 2)) + else lua_pushnil(L); - end - else - lua_pushinteger(L, lua_tointeger(L, 1) div lua_tointeger(L, 2)); lc_div := 1; end; function lc_getinputmask(L : Plua_State) : LongInt; Cdecl; begin - if lua_gettop(L) <> 0 then - LuaParameterCountError('GetInputMask', '', lua_gettop(L)) - else + if CheckLuaParamCount(L, 0, 'GetInputMask', '') then lua_pushinteger(L, InputMask); lc_getinputmask:= 1 end; function lc_setinputmask(L : Plua_State) : LongInt; Cdecl; begin - if lua_gettop(L) <> 1 then - LuaParameterCountError('SetInputMask', 'mask', lua_gettop(L)) - else + if CheckLuaParamCount(L, 1, 'SetInputMask', 'mask') then InputMask:= lua_tointeger(L, 1); lc_setinputmask:= 0 end; function lc_writelntoconsole(L : Plua_State) : LongInt; Cdecl; begin - if lua_gettop(L) = 1 then - begin + if CheckLuaParamCount(L, 1, 'WriteLnToConsole', 'string') then WriteLnToConsole('Lua: ' + lua_tostring(L ,1)); - end - else - LuaParameterCountError('WriteLnToConsole', 'string', lua_gettop(L)); lc_writelntoconsole:= 0; end; @@ -202,29 +410,124 @@ i,c: LongWord; s: shortstring; begin - if lua_gettop(L) = 1 then + if CheckLuaParamCount(L, 1, 'ParseCommand', 'string') then begin - t:= lua_tolstring(L,1,@c); + t:= lua_tolstring(L, 1, Psize_t(@c)); for i:= 1 to c do s[i]:= t[i-1]; s[0]:= char(c); ParseCommand(s, true, true); - end - else - LuaParameterCountError('ParseCommand', 'string', lua_gettop(L)); + end; lc_parsecommand:= 0; end; +// sets weapon to the desired ammo type +function lc_setweapon(L : Plua_State) : LongInt; Cdecl; +var at: LongInt; +const + call = 'SetWeapon'; + params = 'ammoType'; +begin + // no point to run this without any CurrentHedgehog + if (CurrentHedgehog <> nil) and (CheckLuaParamCount(L, 1, call, params)) then + begin + at:= LuaToAmmoTypeOrd(L, 1, call, params); + if at >= 0 then + ParseCommand('setweap ' + char(at), true, true); + end; + lc_setweapon:= 0; +end; + +// no parameter means reset to default (and 0 means unlimited) +function lc_setmaxbuilddistance(L : Plua_State) : LongInt; Cdecl; +var np: LongInt; +const + call = 'SetMaxBuildDistance'; + params = '[ distInPx ]'; +begin + if CheckAndFetchParamCountRange(L, 0, 1, call, params, np) then + begin + if np = 0 then + begin + // no args? reset + cBuildMaxDist:= cDefaultBuildMaxDist; + end + else + CBuildMaxDist:= lua_tointeger(L, 1); + end; + lc_setmaxbuilddistance:= 0; +end; + +// sets weapon to whatever weapons is next (wraps around, amSkip is skipped) +function lc_setnextweapon(L : Plua_State) : LongInt; Cdecl; +var at : LongInt; + nextAmmo : TAmmo; + s, a, cs, fa: LongInt; +const + call = 'SetNextWeapon'; + params = ''; +begin + if (CurrentHedgehog <> nil) and (CheckLuaParamCount(L, 0, call, params)) then + begin + at:= -1; + with CurrentHedgehog^ do + begin + cs:= 0; // current slot + fa:= 0; // first ammo item to check + + // if something is selected, find it's successor + if curAmmoType <> amNothing then + begin + // get current slot index + cs:= Ammoz[CurAmmoType].Slot; + // find current ammo index + while (fa < cMaxSlotAmmoIndex) + and (Ammo^[cs, fa].AmmoType <> CurAmmoType) do + inc(fa); + // increase once more because we won't successor + inc(fa); + end; + + // find first available ammo + // revisit current slot too (current item might not be first) + for s:= cs to cs + cMaxSlotIndex + 1 do + begin + for a:= fa to cMaxSlotAmmoIndex do + begin + // check if we went full circle + if (a = fa) and (s = cs + cMaxSlotIndex + 1) then + exit(0); + + // get ammo + nextAmmo:= Ammo^[s mod (cMaxSlotIndex + 1), a]; + // only switch to ammos the hog actually has + if (nextAmmo.AmmoType <> amNothing) + and (nextAmmo.AmmoType <> amSkip) and (nextAmmo.Count > 0) then + begin + at:= ord(nextAmmo.AmmoType); + break; + end; + end; + // stop slot loop if something was found + if at >= 0 then + break; + // check following slots starting with first item + fa:= 0; + end; + end; + + if at >= 0 then + ParseCommand('setweap ' + char(at), true, true); + end; + lc_setnextweapon:= 0; +end; + function lc_showmission(L : Plua_State) : LongInt; Cdecl; begin - if lua_gettop(L) = 5 then - begin - ShowMission(lua_tostring(L, 1), lua_tostring(L, 2), lua_tostring(L, 3), lua_tointeger(L, 4), lua_tointeger(L, 5)); - end - else - LuaParameterCountError('ShowMission', 'caption, subcaption, text, icon, time', lua_gettop(L)); + if CheckLuaParamCount(L, 5, 'ShowMission', 'caption, subcaption, text, icon, time') then + ShowMission(lua_tostringA(L, 1), lua_tostringA(L, 2), lua_tostringA(L, 3), lua_tointeger(L, 4), lua_tointeger(L, 5)); lc_showmission:= 0; end; @@ -236,181 +539,189 @@ end; function lc_enablegameflags(L : Plua_State) : LongInt; Cdecl; -var i : integer; +var i, n : integer; begin - for i:= 1 to lua_gettop(L) do - GameFlags := GameFlags or LongWord(lua_tointeger(L, i)); - ScriptSetInteger('GameFlags', GameFlags); + // can have 1 or more arguments + if CheckAndFetchLuaParamMinCount(L, 1, 'EnableGameFlags', 'gameFlag, ... ', n) then + begin + for i:= 1 to n do + GameFlags := GameFlags or LongWord(lua_tointeger(L, i)); + ScriptSetInteger('GameFlags', GameFlags); + end; lc_enablegameflags:= 0; end; function lc_disablegameflags(L : Plua_State) : LongInt; Cdecl; -var i : integer; +var i , n: integer; begin - for i:= 1 to lua_gettop(L) do - GameFlags := GameFlags and not(LongWord(lua_tointeger(L, i))); - ScriptSetInteger('GameFlags', GameFlags); + // can have 1 or more arguments + if CheckAndFetchLuaParamMinCount(L, 1, 'DisableGameFlags', 'gameFlag, ... ', n) then + begin + for i:= 1 to n do + GameFlags := GameFlags and (not LongWord(lua_tointeger(L, i))); + ScriptSetInteger('GameFlags', GameFlags); + end; lc_disablegameflags:= 0; end; function lc_cleargameflags(L : Plua_State) : LongInt; Cdecl; begin - // Silence hint - L:= L; - GameFlags:= 0; - ScriptSetInteger('GameFlags', GameFlags); + if CheckLuaParamCount(L, 0, 'ClearGameFlags', '') then + begin + GameFlags:= 0; + ScriptSetInteger('GameFlags', GameFlags); + end; lc_cleargameflags:= 0; end; +function lc_getgameflag(L : Plua_State) : LongInt; Cdecl; +begin + if CheckLuaParamCount(L, 1, 'GetGameFlag', 'gameflag') then + lua_pushboolean(L, (GameFlags and LongWord(lua_tointeger(L, 1)) <> 0)) + else + lua_pushnil(L); + lc_getgameflag:= 1; +end; + function lc_addcaption(L : Plua_State) : LongInt; Cdecl; +var cg: LongInt; +const + call = 'AddCaption'; + params = 'text [, color, captiongroup]'; begin - if lua_gettop(L) = 1 then - AddCaption(lua_tostring(L, 1), cWhiteColor, capgrpMessage) - else if lua_gettop(L) = 3 then + if CheckAndFetchParamCount(L, 1, 3, call, params, cg) then begin - AddCaption(lua_tostring(L, 1), lua_tointeger(L, 2) shr 8, TCapGroup(lua_tointeger(L, 3))); - end - else - LuaParameterCountError('AddCaption', 'text[, color, captiongroup]', lua_gettop(L)); + if cg = 1 then + AddCaption(lua_tostringA(L, 1), cWhiteColor, capgrpMessage) + else + begin + cg:= LuaToCapGroupOrd(L, 3, call, params); + if cg >= 0 then + AddCaption(lua_tostringA(L, 1), lua_tointeger(L, 2) shr 8, TCapGroup(cg)); + end + end; lc_addcaption:= 0; end; function lc_campaignlock(L : Plua_State) : LongInt; Cdecl; begin - if lua_gettop(L) = 1 then + if CheckLuaParamCount(L, 1, 'CampaignLock', 'TODO') then begin - // to be done - end - else - LuaParameterCountError('CampaignLock', 'TODO', lua_gettop(L)); + // TODO + end; lc_campaignlock:= 0; end; function lc_campaignunlock(L : Plua_State) : LongInt; Cdecl; begin - if lua_gettop(L) = 1 then + if CheckLuaParamCount(L, 1, 'CampaignUnlock', 'TODO') then begin - // to be done - end - else - LuaParameterCountError('CampaignUnlock', 'TODO', lua_gettop(L)); + // TODO + end; lc_campaignunlock:= 0; end; function lc_spawnfakehealthcrate(L: Plua_State) : LongInt; Cdecl; var gear: PGear; begin - if lua_gettop(L) <> 4 then - begin - LuaParameterCountError('SpawnFakeHealthCrate', 'x, y, explode, poison', lua_gettop(L)); - lua_pushnil(L); - end - else + if CheckLuaParamCount(L, 4,'SpawnFakeHealthCrate', 'x, y, explode, poison') then begin gear := SpawnFakeCrateAt(lua_tointeger(L, 1), lua_tointeger(L, 2), HealthCrate, lua_toboolean(L, 3), lua_toboolean(L, 4)); - lua_pushinteger(L, gear^.uid); - end; + if gear <> nil then + lua_pushinteger(L, gear^.uid) + else lua_pushnil(L) + end + else + lua_pushnil(L); lc_spawnfakehealthcrate := 1; end; function lc_spawnfakeammocrate(L: PLua_State): LongInt; Cdecl; var gear: PGear; begin - if lua_gettop(L) <> 4 then - begin - LuaParameterCountError('SpawnFakeAmmoCrate', 'x, y, explode, poison', lua_gettop(L)); - lua_pushnil(L); - end - else + if CheckLuaParamCount(L, 4,'SpawnFakeAmmoCrate', 'x, y, explode, poison') then begin gear := SpawnFakeCrateAt(lua_tointeger(L, 1), lua_tointeger(L, 2), AmmoCrate, lua_toboolean(L, 3), lua_toboolean(L, 4)); - lua_pushinteger(L, gear^.uid); - end; + if gear <> nil then + lua_pushinteger(L, gear^.uid) + else lua_pushnil(L) + end + else + lua_pushnil(L); lc_spawnfakeammocrate := 1; end; function lc_spawnfakeutilitycrate(L: PLua_State): LongInt; Cdecl; var gear: PGear; begin - if lua_gettop(L) <> 4 then - begin - LuaParameterCountError('SpawnFakeUtilityCrate', 'x, y, explode, poison', lua_gettop(L)); - lua_pushnil(L); - end - else + if CheckLuaParamCount(L, 4,'SpawnFakeUtilityCrate', 'x, y, explode, poison') then begin gear := SpawnFakeCrateAt(lua_tointeger(L, 1), lua_tointeger(L, 2), UtilityCrate, lua_toboolean(L, 3), lua_toboolean(L, 4)); - lua_pushinteger(L, gear^.uid); - end; + if gear <> nil then + lua_pushinteger(L, gear^.uid) + else lua_pushnil(L) + end + else + lua_pushnil(L); lc_spawnfakeutilitycrate := 1; end; function lc_spawnhealthcrate(L: Plua_State) : LongInt; Cdecl; var gear: PGear; -var health: LongInt; +var health, n: LongInt; begin - if (lua_gettop(L) < 2) or (lua_gettop(L) > 3) then + if CheckAndFetchParamCount(L, 2, 3, 'SpawnHealthCrate', 'x, y [, health]', n) then begin - LuaParameterCountError('SpawnHealthCrate', 'x, y[, health]', lua_gettop(L)); - lua_pushnil(L); - end - else - begin - if lua_gettop(L) = 3 then + if n = 3 then health:= lua_tointeger(L, 3) else health:= cHealthCaseAmount; gear := SpawnCustomCrateAt(lua_tointeger(L, 1), lua_tointeger(L, 2), HealthCrate, health, 0); if gear <> nil then - lua_pushinteger(L, gear^.uid) - else - lua_pushnil(L); - end; + lua_pushinteger(L, gear^.uid) + else lua_pushnil(L); + end + else + lua_pushnil(L); lc_spawnhealthcrate := 1; end; function lc_spawnammocrate(L: PLua_State): LongInt; Cdecl; var gear: PGear; + n : LongInt; begin - if (lua_gettop(L) <> 3) and (lua_gettop(L) <> 4) then + if CheckAndFetchParamCount(L, 3, 4, 'SpawnAmmoCrate', 'x, y, content [, amount]', n) then begin - LuaParameterCountError('SpawnAmmoCrate', 'x, y, content[, amount]', lua_gettop(L)); - lua_pushnil(L); - end - else - begin - if (lua_gettop(L) = 3) then + if n = 3 then gear := SpawnCustomCrateAt(lua_tointeger(L, 1), lua_tointeger(L, 2), AmmoCrate, lua_tointeger(L, 3), 0) else gear := SpawnCustomCrateAt(lua_tointeger(L, 1), lua_tointeger(L, 2), AmmoCrate, lua_tointeger(L, 3), lua_tointeger(L, 4)); if gear <> nil then - lua_pushinteger(L, gear^.uid) - else - lua_pushnil(L); - end; + lua_pushinteger(L, gear^.uid) + else lua_pushnil(L); + end + else + lua_pushnil(L); lc_spawnammocrate := 1; end; function lc_spawnutilitycrate(L: PLua_State): LongInt; Cdecl; var gear: PGear; + n : LongInt; begin - if (lua_gettop(L) <> 3) and (lua_gettop(L) <> 4) then + if CheckAndFetchParamCount(L, 3, 4, 'SpawnUtilityCrate', 'x, y, content [, amount]', n) then begin - LuaParameterCountError('SpawnUtilityCrate', 'x, y, content[, amount]', lua_gettop(L)); - lua_pushnil(L); - end - else - begin - if (lua_gettop(L) = 3) then + if n = 3 then gear := SpawnCustomCrateAt(lua_tointeger(L, 1), lua_tointeger(L, 2), UtilityCrate, lua_tointeger(L, 3), 0) else gear := SpawnCustomCrateAt(lua_tointeger(L, 1), lua_tointeger(L, 2), UtilityCrate, lua_tointeger(L, 3), lua_tointeger(L, 4)); if gear <> nil then - lua_pushinteger(L, gear^.uid) - else - lua_pushnil(L); - end; + lua_pushinteger(L, gear^.uid) + else lua_pushnil(L); + end + else + lua_pushnil(L); lc_spawnutilitycrate := 1; end; @@ -419,37 +730,39 @@ x, y, s, t: LongInt; dx, dy: hwFloat; gt: TGearType; +const + call = 'AddGear'; + params = 'x, y, gearType, state, dx, dy, timer'; begin - if lua_gettop(L) <> 7 then + if CheckLuaParamCount(L, 7, call, params) then begin - LuaParameterCountError('AddGear', 'x, y, gearType, state, dx, dy, timer', lua_gettop(L)); - lua_pushnil(L); // return value on stack (nil) + t:= LuaToGearTypeOrd(L, 3, call, params); + if t >= 0 then + begin + gt:= TGearType(t); + x:= lua_tointeger(L, 1); + y:= lua_tointeger(L, 2); + s:= lua_tointeger(L, 4); + dx:= int2hwFloat(lua_tointeger(L, 5)) / 1000000; + dy:= int2hwFloat(lua_tointeger(L, 6)) / 1000000; + t:= lua_tointeger(L, 7); + + gear:= AddGear(x, y, gt, s, dx, dy, t); + lastGearByUID:= gear; + lua_pushinteger(L, gear^.uid) + end + else + lua_pushnil(L); end else - begin - x:= lua_tointeger(L, 1); - y:= lua_tointeger(L, 2); - gt:= TGearType(lua_tointeger(L, 3)); - s:= lua_tointeger(L, 4); - dx:= int2hwFloat(lua_tointeger(L, 5)) / 1000000; - dy:= int2hwFloat(lua_tointeger(L, 6)) / 1000000; - t:= lua_tointeger(L, 7); - - gear:= AddGear(x, y, gt, s, dx, dy, t); - lastGearByUID:= gear; - lua_pushinteger(L, gear^.uid) - end; + lua_pushnil(L); lc_addgear:= 1; // 1 return value end; function lc_deletegear(L : Plua_State) : LongInt; Cdecl; var gear : PGear; begin - if lua_gettop(L) <> 1 then - begin - LuaParameterCountError('DeleteGear', 'gearUid', lua_gettop(L)); - end - else + if CheckLuaParamCount(L, 1, 'DeleteGear', 'gearUid') then begin gear:= GearByUID(lua_tointeger(L, 1)); if gear <> nil then @@ -460,61 +773,68 @@ function lc_addvisualgear(L : Plua_State) : LongInt; Cdecl; var vg : PVisualGear; - x, y, s: LongInt; + x, y, s, n, layer: LongInt; c: Boolean; vgt: TVisualGearType; + uid: Longword; +const + call = 'AddVisualGear'; + params = 'x, y, visualGearType, state, critical [, layer]'; begin - if lua_gettop(L) <> 5 then + uid:= 0; + if CheckAndFetchParamCount(L, 5, 6, call, params, n) then begin - LuaParameterCountError('AddVisualGear', 'x, y, visualGearType, state, critical', lua_gettop(L)); - lua_pushnil(L); // return value on stack (nil) + s:= LuaToVisualGearTypeOrd(L, 3, call, params); + if s >= 0 then + begin + vgt:= TVisualGearType(s); + x:= lua_tointeger(L, 1); + y:= lua_tointeger(L, 2); + s:= lua_tointeger(L, 4); + c:= lua_toboolean(L, 5); + + if n = 6 then + begin + layer:= lua_tointeger(L, 6); + vg:= AddVisualGear(x, y, vgt, s, c, layer); + end + else + vg:= AddVisualGear(x, y, vgt, s, c); + + if vg <> nil then + begin + lastVisualGearByUID:= vg; + uid:= vg^.uid; + lua_pushinteger(L, uid); + end; + end + else + lua_pushnil(L); end else - begin - x:= lua_tointeger(L, 1); - y:= lua_tointeger(L, 2); - vgt:= TVisualGearType(lua_tointeger(L, 3)); - s:= lua_tointeger(L, 4); - c:= lua_toboolean(L, 5); - - vg:= AddVisualGear(x, y, vgt, s, c); - if vg <> nil then - begin - lastVisualGearByUID:= vg; - lua_pushinteger(L, vg^.uid) - end - else - lua_pushinteger(L, 0) - end; + lua_pushnil(L); // return value on stack (nil) lc_addvisualgear:= 1; // 1 return value end; function lc_deletevisualgear(L : Plua_State) : LongInt; Cdecl; var vg : PVisualGear; begin - if lua_gettop(L) <> 1 then - begin - LuaParameterCountError('DeleteVisualGear', 'vgUid', lua_gettop(L)); - end - else + vg:= nil; + if CheckLuaParamCount(L, 1, 'DeleteVisualGear', 'vgUid') then begin vg:= VisualGearByUID(lua_tointeger(L, 1)); if vg <> nil then DeleteVisualGear(vg); end; - lc_deletevisualgear:= 0 + // allow caller to know whether there was something to delete + lua_pushboolean(L, vg <> nil); + lc_deletevisualgear:= 1 end; function lc_getvisualgearvalues(L : Plua_State) : LongInt; Cdecl; var vg: PVisualGear; begin - if lua_gettop(L) <> 1 then - begin - LuaParameterCountError('GetVisualGearValues', 'vgUid', lua_gettop(L)); - lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); - lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L) - end - else + if CheckLuaParamCount(L, 1, 'GetVisualGearValues', 'vgUid') then begin vg:= VisualGearByUID(lua_tointeger(L, 1)); if vg <> nil then @@ -533,119 +853,238 @@ else begin lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); - lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L) + lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); end + end + else + begin + lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); + lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); end; - lc_getvisualgearvalues:= 10; + lc_getvisualgearvalues:= 10 end; function lc_setvisualgearvalues(L : Plua_State) : LongInt; Cdecl; var vg : PVisualGear; begin - if lua_gettop(L) <> 11 then - begin - LuaParameterCountError('SetVisualGearValues', 'vgUid, X, Y, dX, dY, Angle, Frame, FrameTicks, State, Timer, Tint', lua_gettop(L)); - lua_pushnil(L); // return value on stack (nil) - end - else - begin +// Param count can be 1-11 at present +// if CheckLuaParamCount(L, 11, 'SetVisualGearValues', 'vgUid, X, Y, dX, dY, Angle, Frame, FrameTicks, State, Timer, Tint') then +// begin vg:= VisualGearByUID(lua_tointeger(L, 1)); if vg <> nil then begin - vg^.X:= lua_tointeger(L, 2); - vg^.Y:= lua_tointeger(L, 3); - vg^.dX:= lua_tonumber(L, 4); - vg^.dY:= lua_tonumber(L, 5); - vg^.Angle:= lua_tonumber(L, 6); - vg^.Frame:= lua_tointeger(L, 7); - if lua_tointeger(L, 8) <> 0 then - vg^.FrameTicks:= lua_tointeger(L, 8); // find a better way to do this. maybe need to break all these up. - vg^.State:= lua_tointeger(L, 9); - vg^.Timer:= lua_tointeger(L, 10); - vg^.Tint:= lua_tointeger(L, 11); + if not lua_isnoneornil(L, 2) then + vg^.X:= lua_tointeger(L, 2); + if not lua_isnoneornil(L, 3) then + vg^.Y:= lua_tointeger(L, 3); + if not lua_isnoneornil(L, 4) then + vg^.dX:= lua_tonumber(L, 4); + if not lua_isnoneornil(L, 5) then + vg^.dY:= lua_tonumber(L, 5); + if not lua_isnoneornil(L, 6) then + vg^.Angle:= lua_tonumber(L, 6); + if not lua_isnoneornil(L, 7) then + vg^.Frame:= lua_tointeger(L, 7); + if not lua_isnoneornil(L, 8) then + vg^.FrameTicks:= lua_tointeger(L, 8); + if not lua_isnoneornil(L, 9) then + vg^.State:= lua_tointeger(L, 9); + if not lua_isnoneornil(L, 10) then + vg^.Timer:= lua_tointeger(L, 10); + if not lua_isnoneornil(L, 11) then + vg^.Tint:= lua_tointeger(L, 11) + end; +// end +// else +// lua_pushnil(L); // return value on stack (nil) + lc_setvisualgearvalues:= 0 +end; + +// so. going to use this to get/set some of the more obscure gear values which weren't already exposed elsewhere +// can keep adding things in the future. isnoneornil makes it safe +function lc_getgearvalues(L : Plua_State) : LongInt; Cdecl; +var gear: PGear; +begin + if CheckLuaParamCount(L, 1, 'GetGearValues', 'gearUid') then + begin + gear:= GearByUID(lua_tointeger(L, 1)); + if gear <> nil then + begin + lua_pushinteger(L, gear^.Angle); + lua_pushinteger(L, gear^.Power); + lua_pushinteger(L, gear^.WDTimer); + lua_pushinteger(L, gear^.Radius); + lua_pushinteger(L, hwRound(gear^.Density * _10000)); + lua_pushinteger(L, gear^.Karma); + lua_pushnumber(L, gear^.DirAngle); + lua_pushinteger(L, gear^.AdvBounce); + lua_pushinteger(L, Integer(gear^.ImpactSound)); + lua_pushinteger(L, gear^.nImpactSounds); + lua_pushinteger(L, gear^.Tint); + lua_pushinteger(L, gear^.Damage) end + else + begin + lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); + lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); + lua_pushnil(L); lua_pushnil(L) + end + end + else + begin + lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); + lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); + lua_pushnil(L); lua_pushnil(L) end; - lc_setvisualgearvalues:= 0; + lc_getgearvalues:= 12 +end; + +function lc_setgearvalues(L : Plua_State) : LongInt; Cdecl; +var gear : PGear; +begin +// Currently allows 1-13 params +// if CheckLuaParamCount(L, 13, 'SetGearValues', 'gearUid, Angle, Power, WDTimer, Radius, Density, Karma, DirAngle, AdvBounce, ImpactSound, # ImpactSounds, Tint, Damage') then +// begin + gear:= GearByUID(lua_tointeger(L, 1)); + if gear <> nil then + begin + if not lua_isnoneornil(L, 2) then + gear^.Angle := lua_tointeger(L, 2); + if not lua_isnoneornil(L, 3) then + gear^.Power := lua_tointeger(L, 3); + if not lua_isnoneornil(L, 4) then + gear^.WDTimer := lua_tointeger(L, 4); + if not lua_isnoneornil(L, 5) then + gear^.Radius := lua_tointeger(L, 5); + if not lua_isnoneornil(L, 6) then + gear^.Density:= int2hwFloat(lua_tointeger(L, 6)) / 10000; + if not lua_isnoneornil(L, 7) then + gear^.Karma := lua_tointeger(L, 7); + if not lua_isnoneornil(L, 8) then + gear^.DirAngle:= lua_tonumber(L, 8); + if not lua_isnoneornil(L, 9) then + gear^.AdvBounce := lua_tointeger(L, 9); + if not lua_isnoneornil(L, 10) then + gear^.ImpactSound := TSound(lua_tointeger(L, 10)); + if not lua_isnoneornil(L, 11) then + gear^.nImpactSounds := lua_tointeger(L, 11); + if not lua_isnoneornil(L, 12) then + gear^.Tint := lua_tointeger(L, 12); + if not lua_isnoneornil(L, 13) then + gear^.Damage := lua_tointeger(L, 13); + end; +// end +// else +// lua_pushnil(L); // return value on stack (nil) + lc_setgearvalues:= 0 end; function lc_getfollowgear(L : Plua_State) : LongInt; Cdecl; begin - if lua_gettop(L) <> 0 then + if CheckLuaParamCount(L, 0, 'GetFollowGear', '') then begin - LuaParameterCountError('GetFollowGear', '', lua_gettop(L)); - lua_pushnil(L); // return value on stack (nil) - end - else if FollowGear = nil then lua_pushnil(L) else lua_pushinteger(L, FollowGear^.uid); + end + else + lua_pushnil(L); lc_getfollowgear:= 1; // 1 return value end; function lc_getgeartype(L : Plua_State) : LongInt; Cdecl; var gear : PGear; begin - if lua_gettop(L) <> 1 then - begin - LuaParameterCountError('GetGearType', 'gearUid', lua_gettop(L)); - lua_pushnil(L); // return value on stack (nil) - end - else + if CheckLuaParamCount(L, 1, 'GetGearType', 'gearUid') then begin gear:= GearByUID(lua_tointeger(L, 1)); if gear <> nil then lua_pushinteger(L, ord(gear^.Kind)) else lua_pushnil(L); - end; + end + else + lua_pushnil(L); // return value on stack (nil) lc_getgeartype:= 1 end; function lc_getgearmessage(L : Plua_State) : LongInt; Cdecl; var gear : PGear; begin - if lua_gettop(L) <> 1 then - begin - LuaParameterCountError('GetGearMessage', 'gearUid', lua_gettop(L)); - lua_pushnil(L); // return value on stack (nil) - end - else + if CheckLuaParamCount(L, 1, 'GetGearMessage', 'gearUid') then begin gear:= GearByUID(lua_tointeger(L, 1)); if gear <> nil then lua_pushinteger(L, gear^.message) else lua_pushnil(L); - end; + end + else + lua_pushnil(L); // return value on stack (nil) lc_getgearmessage:= 1 end; function lc_getgearelasticity(L : Plua_State) : LongInt; Cdecl; var gear : PGear; begin - if lua_gettop(L) <> 1 then - begin - LuaParameterCountError('GetGearElasticity', 'gearUid', lua_gettop(L)); - lua_pushnil(L); // return value on stack (nil) - end - else + if CheckLuaParamCount(L, 1, 'GetGearElasticity', 'gearUid') then begin gear:= GearByUID(lua_tointeger(L, 1)); if gear <> nil then lua_pushinteger(L, hwRound(gear^.elasticity * _10000)) else lua_pushnil(L); + end + else + lua_pushnil(L); // return value on stack (nil) + lc_getgearelasticity:= 1 +end; + +function lc_setgearelasticity(L : Plua_State) : LongInt; Cdecl; +var gear: PGear; +begin + if CheckLuaParamCount(L, 2, 'SetGearElasticity', 'gearUid, Elasticity') then + begin + gear:= GearByUID(lua_tointeger(L, 1)); + if gear <> nil then + gear^.Elasticity:= int2hwFloat(lua_tointeger(L, 2)) / 10000 end; - lc_getgearelasticity:= 1 + lc_setgearelasticity:= 0 +end; + +function lc_getgearfriction(L : Plua_State) : LongInt; Cdecl; +var gear : PGear; +begin + if CheckLuaParamCount(L, 1, 'GetGearFriction', 'gearUid') then + begin + gear:= GearByUID(lua_tointeger(L, 1)); + if gear <> nil then + lua_pushinteger(L, hwRound(gear^.friction * _10000)) + else + lua_pushnil(L); + end + else + lua_pushnil(L); // return value on stack (nil) + lc_getgearfriction:= 1 +end; + +function lc_setgearfriction(L : Plua_State) : LongInt; Cdecl; +var gear: PGear; +begin + if CheckLuaParamCount(L, 2, 'SetGearFriction', 'gearUid, Friction') then + begin + gear:= GearByUID(lua_tointeger(L, 1)); + if gear <> nil then + gear^.Friction:= int2hwFloat(lua_tointeger(L, 2)) / 10000 + end; + lc_setgearfriction:= 0 end; function lc_setgearmessage(L : Plua_State) : LongInt; Cdecl; var gear : PGear; begin - if lua_gettop(L) <> 2 then - LuaParameterCountError('SetGearMessage', 'gearUid, message', lua_gettop(L)) - else + if CheckLuaParamCount(L, 2, 'SetGearMessage', 'gearUid, message') then begin gear:= GearByUID(lua_tointeger(L, 1)); if gear <> nil then @@ -657,28 +1096,23 @@ function lc_getgearpos(L : Plua_State) : LongInt; Cdecl; var gear : PGear; begin - if lua_gettop(L) <> 1 then - begin - LuaParameterCountError('GetGearPos', 'gearUid', lua_gettop(L)); - lua_pushnil(L); // return value on stack (nil) - end - else + if CheckLuaParamCount(L, 1, 'GetGearPos', 'gearUid') then begin gear:= GearByUID(lua_tointeger(L, 1)); if gear <> nil then lua_pushinteger(L, gear^.Pos) else lua_pushnil(L); - end; + end + else + lua_pushnil(L); // return value on stack (nil) lc_getgearpos:= 1 end; function lc_setgearpos(L : Plua_State) : LongInt; Cdecl; var gear : PGear; begin - if lua_gettop(L) <> 2 then - LuaParameterCountError('SetGearPos', 'gearUid, value', lua_gettop(L)) - else + if CheckLuaParamCount(L, 2, 'SetGearPos', 'gearUid, value') then begin gear:= GearByUID(lua_tointeger(L, 1)); if gear <> nil then @@ -690,28 +1124,23 @@ function lc_getgearcollisionmask(L : Plua_State) : LongInt; Cdecl; var gear : PGear; begin - if lua_gettop(L) <> 1 then - begin - LuaParameterCountError('GetGearCollisionMask', 'gearUid', lua_gettop(L)); - lua_pushnil(L); // return value on stack (nil) - end - else + if CheckLuaParamCount(L, 1, 'GetGearCollisionMask', 'gearUid') then begin gear:= GearByUID(lua_tointeger(L, 1)); if gear <> nil then lua_pushinteger(L, gear^.CollisionMask) else lua_pushnil(L); - end; + end + else + lua_pushnil(L); // return value on stack (nil) lc_getgearcollisionmask:= 1 end; function lc_setgearcollisionmask(L : Plua_State) : LongInt; Cdecl; var gear : PGear; begin - if lua_gettop(L) <> 2 then - LuaParameterCountError('SetGearCollisionMask', 'gearUid, mask', lua_gettop(L)) - else + if CheckLuaParamCount(L, 2, 'SetGearCollisionMask', 'gearUid, mask') then begin gear:= GearByUID(lua_tointeger(L, 1)); if gear <> nil then @@ -723,9 +1152,7 @@ function lc_gethoglevel(L : Plua_State): LongInt; Cdecl; var gear : PGear; begin - if lua_gettop(L) <> 1 then - LuaParameterCountError('GetHogLevel', 'gearUid', lua_gettop(L)) - else + if CheckLuaParamCount(L, 1, 'GetHogLevel', 'gearUid') then begin gear := GearByUID(lua_tointeger(L, 1)); if (gear <> nil) and ((gear^.Kind = gtHedgehog) or (gear^.Kind = gtGrave)) and (gear^.Hedgehog <> nil) then @@ -739,9 +1166,7 @@ function lc_sethoglevel(L : Plua_State) : LongInt; Cdecl; var gear : PGear; begin - if lua_gettop(L) <> 2 then - LuaParameterCountError('SetHogLevel', 'gearUid, level', lua_gettop(L)) - else + if CheckLuaParamCount(L, 2, 'SetHogLevel', 'gearUid, level') then begin gear:= GearByUID(lua_tointeger(L, 1)); if (gear <> nil) and (gear^.Kind = gtHedgehog) and (gear^.Hedgehog <> nil) then @@ -753,12 +1178,7 @@ function lc_gethogclan(L : Plua_State) : LongInt; Cdecl; var gear : PGear; begin - if lua_gettop(L) <> 1 then - begin - LuaParameterCountError('GetHogClan', 'gearUid', lua_gettop(L)); - lua_pushnil(L); // return value on stack (nil) - end - else + if CheckLuaParamCount(L, 1, 'GetHogClan', 'gearUid') then begin gear:= GearByUID(lua_tointeger(L, 1)); if (gear <> nil) and ((gear^.Kind = gtHedgehog) or (gear^.Kind = gtGrave)) and (gear^.Hedgehog <> nil) then @@ -767,18 +1187,18 @@ end else lua_pushnil(L); - end; + end + else + lua_pushnil(L); // return value on stack (nil) lc_gethogclan:= 1 end; function lc_getclancolor(L : Plua_State) : LongInt; Cdecl; begin - if lua_gettop(L) <> 1 then - begin - LuaParameterCountError('GetClanColor', 'clan', lua_gettop(L)); + if CheckLuaParamCount(L, 1, 'GetClanColor', 'clan') then + lua_pushinteger(L, ClansArray[lua_tointeger(L, 1)]^.Color shl 8 or $FF) + else lua_pushnil(L); // return value on stack (nil) - end - else lua_pushinteger(L, ClansArray[lua_tointeger(L, 1)]^.Color shl 8 or $FF); lc_getclancolor:= 1 end; @@ -788,11 +1208,11 @@ hh : THedgehog; i, j : LongInt; begin - if lua_gettop(L) <> 2 then - LuaParameterCountError('SetClanColor', 'clan, color', lua_gettop(L)) - else + if CheckLuaParamCount(L, 2, 'SetClanColor', 'clan, color') then begin - clan := ClansArray[lua_tointeger(L, 1)]; + i:= lua_tointeger(L,1); + if i >= ClansCount then exit(0); + clan := ClansArray[i]; clan^.Color:= lua_tointeger(L, 2) shr 8; for i:= 0 to Pred(clan^.TeamsNumber) do @@ -803,75 +1223,111 @@ hh:= team^.Hedgehogs[j]; if (hh.Gear <> nil) or (hh.GearHidden <> nil) then begin - FreeTexture(hh.NameTagTex); - hh.NameTagTex:= RenderStringTex(hh.Name, clan^.Color, fnt16); + FreeAndNilTexture(hh.NameTagTex); + hh.NameTagTex:= RenderStringTex(ansistring(hh.Name), clan^.Color, fnt16); RenderHealth(hh); end; end; - FreeTexture(team^.NameTagTex); - team^.NameTagTex:= RenderStringTex(clan^.Teams[i]^.TeamName, clan^.Color, fnt16); + FreeAndNilTexture(team^.NameTagTex); + team^.NameTagTex:= RenderStringTex(ansistring(clan^.Teams[i]^.TeamName), clan^.Color, fnt16); end; + FreeAndNilTexture(clan^.HealthTex); clan^.HealthTex:= makeHealthBarTexture(cTeamHealthWidth + 5, clan^.Teams[0]^.NameTagTex^.h, clan^.Color); end; lc_setclancolor:= 0 end; +function lc_gethogvoicepack(L : Plua_State) : LongInt; Cdecl; +var gear : PGear; +begin + if CheckLuaParamCount(L, 1, 'GetHogVoicepack', 'gearUid') then + begin + gear:= GearByUID(lua_tointeger(L, 1)); + if (gear <> nil) and (gear^.Kind = gtHedgehog) and (gear^.Hedgehog <> nil) then + lua_pushstring(L, str2pchar(gear^.Hedgehog^.Team^.Voicepack^.name)) + else + lua_pushnil(L); + end + else + lua_pushnil(L); // return value on stack (nil) + lc_gethogvoicepack:= 1 +end; + +function lc_gethoggrave(L : Plua_State) : LongInt; Cdecl; +var gear : PGear; +begin + if CheckLuaParamCount(L, 1, 'GetHogGrave', 'gearUid') then + begin + gear:= GearByUID(lua_tointeger(L, 1)); + if (gear <> nil) and ((gear^.Kind = gtHedgehog) or (gear^.Kind = gtGrave)) and (gear^.Hedgehog <> nil) then + lua_pushstring(L, str2pchar(gear^.Hedgehog^.Team^.GraveName)) + else + lua_pushnil(L); + end + else + lua_pushnil(L); // return value on stack (nil) + lc_gethoggrave:= 1 +end; + +function lc_gethogflag(L : Plua_State) : LongInt; Cdecl; +var gear : PGear; +begin + if CheckLuaParamCount(L, 1, 'GetHogFlag', 'gearUid') then + begin + gear:= GearByUID(lua_tointeger(L, 1)); + if (gear <> nil) and (gear^.Kind = gtHedgehog) and (gear^.Hedgehog <> nil) then + lua_pushstring(L, str2pchar(gear^.Hedgehog^.Team^.Flag)) + else + lua_pushnil(L); + end + else + lua_pushnil(L); // return value on stack (nil) + lc_gethogflag:= 1 +end; + function lc_gethogteamname(L : Plua_State) : LongInt; Cdecl; var gear : PGear; begin - if lua_gettop(L) <> 1 then - begin - LuaParameterCountError('GetHogTeamName', 'gearUid', lua_gettop(L)); - lua_pushnil(L); // return value on stack (nil) - end - else + if CheckLuaParamCount(L, 1, 'GetHogTeamName', 'gearUid') then begin gear:= GearByUID(lua_tointeger(L, 1)); if (gear <> nil) and ((gear^.Kind = gtHedgehog) or (gear^.Kind = gtGrave)) and (gear^.Hedgehog <> nil) then - begin lua_pushstring(L, str2pchar(gear^.Hedgehog^.Team^.TeamName)) - end else lua_pushnil(L); - end; + end + else + lua_pushnil(L); // return value on stack (nil) lc_gethogteamname:= 1 end; function lc_sethogteamname(L : Plua_State) : LongInt; Cdecl; var gear : PGear; begin - if lua_gettop(L) <> 2 then - begin - LuaParameterCountError('SetHogTeamName', 'gearUid, name', lua_gettop(L)); - lua_pushnil(L); // return value on stack (nil) - end - else + if CheckLuaParamCount(L, 2, 'SetHogTeamName', 'gearUid, name') then begin gear := GearByUID(lua_tointeger(L, 1)); if (gear <> nil) and ((gear^.Kind = gtHedgehog) or (gear^.Kind = gtGrave)) and (gear^.Hedgehog <> nil) then begin gear^.Hedgehog^.Team^.TeamName := lua_tostring(L, 2); - FreeTexture(gear^.Hedgehog^.Team^.NameTagTex); - gear^.Hedgehog^.Team^.NameTagTex:= RenderStringTex(gear^.Hedgehog^.Team^.TeamName, gear^.Hedgehog^.Team^.Clan^.Color, fnt16); + FreeAndNilTexture(gear^.Hedgehog^.Team^.NameTagTex); + gear^.Hedgehog^.Team^.NameTagTex:= RenderStringTex(ansistring(gear^.Hedgehog^.Team^.TeamName), gear^.Hedgehog^.Team^.Clan^.Color, fnt16); end else lua_pushnil(L); - end; + end + else + lua_pushnil(L); // return value on stack (nil) lc_sethogteamname:= 1 end; function lc_gethogname(L : Plua_State) : LongInt; Cdecl; var gear : PGear; begin - if lua_gettop(L) <> 1 then - begin - LuaParameterCountError('GetHogName', 'gearUid', lua_gettop(L)); - lua_pushnil(L); // return value on stack (nil) - end - else + if CheckLuaParamCount(L, 1, 'GetHogName', 'gearUid') then begin gear:= GearByUID(lua_tointeger(L, 1)); if (gear <> nil) and ((gear^.Kind = gtHedgehog) or (gear^.Kind = gtGrave)) and (gear^.Hedgehog <> nil) then @@ -880,27 +1336,24 @@ end else lua_pushnil(L); - end; + end + else + lua_pushnil(L); // return value on stack (nil) lc_gethogname:= 1 end; function lc_sethogname(L : Plua_State) : LongInt; Cdecl; var gear : PGear; begin - if lua_gettop(L) <> 2 then - begin - LuaParameterCountError('SetHogName', 'gearUid, name', lua_gettop(L)); - lua_pushnil(L) - end - else + if CheckLuaParamCount(L, 2, 'SetHogName', 'gearUid, name') then begin gear:= GearByUID(lua_tointeger(L, 1)); if (gear <> nil) and (gear^.Kind = gtHedgehog) and (gear^.Hedgehog <> nil) then begin gear^.Hedgehog^.Name:= lua_tostring(L, 2); - FreeTexture(gear^.Hedgehog^.NameTagTex); - gear^.Hedgehog^.NameTagTex:= RenderStringTex(gear^.Hedgehog^.Name, gear^.Hedgehog^.Team^.Clan^.Color, fnt16) + FreeAndNilTexture(gear^.Hedgehog^.NameTagTex); + gear^.Hedgehog^.NameTagTex:= RenderStringTex(ansistring(gear^.Hedgehog^.Name), gear^.Hedgehog^.Team^.Clan^.Color, fnt16) end end; lc_sethogname:= 0; @@ -909,87 +1362,87 @@ function lc_gettimer(L : Plua_State) : LongInt; Cdecl; var gear : PGear; begin - if lua_gettop(L) <> 1 then - begin - LuaParameterCountError('GetTimer', 'gearUid', lua_gettop(L)); - lua_pushnil(L); // return value on stack (nil) - end - else + if CheckLuaParamCount(L, 1, 'GetTimer', 'gearUid') then begin gear:= GearByUID(lua_tointeger(L, 1)); if gear <> nil then lua_pushinteger(L, gear^.Timer) else lua_pushnil(L); - end; + end + else + lua_pushnil(L); // return value on stack (nil) lc_gettimer:= 1 end; +function lc_getflighttime(L : Plua_State) : LongInt; Cdecl; +var gear : PGear; +begin + if CheckLuaParamCount(L, 1, 'GetFlightTime', 'gearUid') then + begin + gear:= GearByUID(lua_tointeger(L, 1)); + if gear <> nil then + lua_pushinteger(L, gear^.FlightTime) + else + lua_pushnil(L); + end + else + lua_pushnil(L); // return value on stack (nil) + lc_getflighttime:= 1 +end; + function lc_gethealth(L : Plua_State) : LongInt; Cdecl; var gear : PGear; begin - if lua_gettop(L) <> 1 then - begin - LuaParameterCountError('GetHealth', 'gearUid', lua_gettop(L)); - lua_pushnil(L); // return value on stack (nil) - end - else + if CheckLuaParamCount(L, 1, 'GetHealth', 'gearUid') then begin gear:= GearByUID(lua_tointeger(L, 1)); if gear <> nil then lua_pushinteger(L, gear^.Health) else lua_pushnil(L); - end; + end + else + lua_pushnil(L); // return value on stack (nil) lc_gethealth:= 1 end; function lc_getx(L : Plua_State) : LongInt; Cdecl; var gear : PGear; begin - if lua_gettop(L) <> 1 then - begin - LuaParameterCountError('GetX', 'gearUid', lua_gettop(L)); - lua_pushnil(L); // return value on stack (nil) - end - else + if CheckLuaParamCount(L, 1, 'GetX', 'gearUid') then begin gear:= GearByUID(lua_tointeger(L, 1)); if gear <> nil then lua_pushinteger(L, hwRound(gear^.X)) else lua_pushnil(L); - end; + end + else + lua_pushnil(L); // return value on stack (nil) lc_getx:= 1 end; function lc_gety(L : Plua_State) : LongInt; Cdecl; var gear : PGear; begin - if lua_gettop(L) <> 1 then - begin - LuaParameterCountError('GetY', 'gearUid', lua_gettop(L)); - lua_pushnil(L); // return value on stack (nil) - end - else + if CheckLuaParamCount(L, 1, 'GetY', 'gearUid') then begin gear:= GearByUID(lua_tointeger(L, 1)); if gear <> nil then lua_pushinteger(L, hwRound(gear^.Y)) else lua_pushnil(L); - end; + end + else + lua_pushnil(L); // return value on stack (nil) lc_gety:= 1 end; function lc_copypv(L : Plua_State) : LongInt; Cdecl; var gears, geard : PGear; begin - if lua_gettop(L) <> 2 then - begin - LuaParameterCountError('CopyPV', 'fromGearUid, toGearUid', lua_gettop(L)); - end - else + if CheckLuaParamCount(L, 2, 'CopyPV', 'fromGearUid, toGearUid') then begin gears:= GearByUID(lua_tointeger(L, 1)); geard:= GearByUID(lua_tointeger(L, 2)); @@ -1001,15 +1454,13 @@ geard^.dY:= gears^.dY; end end; - lc_copypv:= 1 + lc_copypv:= 0 end; function lc_followgear(L : Plua_State) : LongInt; Cdecl; var gear : PGear; begin - if lua_gettop(L) <> 1 then - LuaParameterCountError('FollowGear', 'gearUid', lua_gettop(L)) - else + if CheckLuaParamCount(L, 1, 'FollowGear', 'gearUid') then begin gear:= GearByUID(lua_tointeger(L, 1)); if gear <> nil then FollowGear:= gear @@ -1021,42 +1472,47 @@ var gear : PGear; vgear : PVisualGear; s : LongWord; + n : LongInt; begin - if lua_gettop(L) = 4 then - s:= lua_tointeger(L, 4) - else - s:= 0; - - if (lua_gettop(L) = 4) or (lua_gettop(L) = 3) then + if CheckAndFetchParamCount(L, 3, 4, 'HogSay', 'gearUid, text, manner [, vgState]', n) then begin gear:= GearByUID(lua_tointeger(L, 1)); if gear <> nil then begin + // state defaults to 0 if state param is given + if n = 4 then + s:= lua_tointeger(L, 4) + else + s:= 0; vgear:= AddVisualGear(0, 0, vgtSpeechBubble, s, true); if vgear <> nil then begin vgear^.Text:= lua_tostring(L, 2); - vgear^.Hedgehog:= gear^.Hedgehog; + if Gear^.Kind = gtHedgehog then + begin + AddChatString(#9+'[' + gear^.Hedgehog^.Name + '] '+vgear^.text); + vgear^.Hedgehog:= gear^.Hedgehog + end + else vgear^.Frame:= gear^.uid; + vgear^.FrameTicks:= lua_tointeger(L, 3); if (vgear^.FrameTicks < 1) or (vgear^.FrameTicks > 3) then vgear^.FrameTicks:= 1; lua_pushinteger(L, vgear^.Uid); - AddChatString(#1+'[' + gear^.Hedgehog^.Name + '] '+vgear^.text) end end - else - lua_pushnil(L) + else + lua_pushnil(L) end - else LuaParameterCountError('HogSay', 'gearUid, text, manner[, vgState]', lua_gettop(L)); + else + lua_pushnil(L); lc_hogsay:= 1 end; function lc_switchhog(L : Plua_State) : LongInt; Cdecl; var gear, prevgear : PGear; begin - if lua_gettop(L) <> 1 then - LuaParameterCountError('SwitchHog', 'gearUid', lua_gettop(L)) - else + if CheckLuaParamCount(L, 1, 'SwitchHog', 'gearUid') then begin gear:= GearByUID(lua_tointeger(L, 1)); // should we allow this when there is no current hedgehog? might do some odd(er) things to turn sequence. @@ -1083,93 +1539,78 @@ lc_switchhog:= 0 end; -{function lc_addammo(L : Plua_State) : LongInt; Cdecl; -var gear : PGear; -begin - - if lua_gettop(L) = 3 then - begin - gear:= GearByUID(lua_tointeger(L, 1)); - if (gear <> nil) and (gear^.Hedgehog <> nil) then - AddAmmoAmount(gear^.Hedgehog^, TAmmoType(lua_tointeger(L, 2)), lua_tointeger(L,3) ); - end else - - if lua_gettop(L) = 2 then - begin - gear:= GearByUID(lua_tointeger(L, 1)); - if (gear <> nil) and (gear^.Hedgehog <> nil) then - AddAmmo(gear^.Hedgehog^, TAmmoType(lua_tointeger(L, 2))); - end else - begin - LuaParameterCountError('AddAmmo', 'TODO', lua_gettop(L)); - end; - - lc_addammo:= 0; - -end;} - function lc_addammo(L : Plua_State) : LongInt; Cdecl; var gear : PGear; + at, n: LongInt; +const + call = 'AddAmmo'; + params = 'gearUid, ammoType [, ammoCount]'; begin - if (lua_gettop(L) = 3) or (lua_gettop(L) = 2) then + if CheckAndFetchParamCount(L, 2, 3, call, params, n) then begin - gear:= GearByUID(lua_tointeger(L, 1)); - if (gear <> nil) and (gear^.Hedgehog <> nil) then - if lua_gettop(L) = 2 then - AddAmmo(gear^.Hedgehog^, TAmmoType(lua_tointeger(L, 2))) - else - SetAmmo(gear^.Hedgehog^, TAmmoType(lua_tointeger(L, 2)), lua_tointeger(L, 3)) - end - else LuaParameterCountError('AddAmmo', 'gearUid, ammoType[, ammoCount]', lua_gettop(L)); + at:= LuaToAmmoTypeOrd(L, 2, call, params); + if at >= 0 then + begin + gear:= GearByUID(lua_tointeger(L, 1)); + if (gear <> nil) and (gear^.Hedgehog <> nil) then + if n = 2 then + AddAmmo(gear^.Hedgehog^, TAmmoType(at)) + else + SetAmmo(gear^.Hedgehog^, TAmmoType(at), lua_tointeger(L, 3)) + end; + end; lc_addammo:= 0 end; function lc_getammocount(L : Plua_State) : LongInt; Cdecl; var gear : PGear; ammo : PAmmo; + at : LongInt; +const + call = 'GetAmmoCount'; + params = 'gearUid, ammoType'; begin - if (lua_gettop(L) = 2) then + if CheckLuaParamCount(L, 2, call, params) then begin gear:= GearByUID(lua_tointeger(L, 1)); if (gear <> nil) and (gear^.Hedgehog <> nil) then begin - ammo:= GetAmmoEntry(gear^.Hedgehog^, TAmmoType(lua_tointeger(L, 2))); - if ammo^.AmmoType = amNothing then - lua_pushinteger(L, 0) - else - lua_pushinteger(L, ammo^.Count) + at:= LuaToAmmoTypeOrd(L, 2, call, params); + if at >= 0 then + begin + ammo:= GetAmmoEntry(gear^.Hedgehog^, TAmmoType(at)); + if ammo^.AmmoType = amNothing then + lua_pushinteger(L, 0) + else + lua_pushinteger(L, ammo^.Count); + end; end - else lua_pushinteger(L, 0) + else lua_pushinteger(L, 0); end else - begin - LuaParameterCountError('GetAmmoCount', 'gearUid, ammoType', lua_gettop(L)); - lua_pushnil(L) - end; + lua_pushnil(L); lc_getammocount:= 1 end; function lc_sethealth(L : Plua_State) : LongInt; Cdecl; var gear : PGear; begin - if lua_gettop(L) <> 2 then - begin - LuaParameterCountError('SetHealth', 'gearUid, health', lua_gettop(L)); - end - else + if CheckLuaParamCount(L, 2, 'SetHealth', 'gearUid, health') then begin gear:= GearByUID(lua_tointeger(L, 1)); if gear <> nil then begin gear^.Health:= lua_tointeger(L, 2); - if (gear^.Kind = gtHedgehog) and (gear^.Hedgehog <> nil) then - begin - RenderHealth(gear^.Hedgehog^); - RecountTeamHealth(gear^.Hedgehog^.Team) - end; - - SetAllToActive; + if (gear^.Kind = gtHedgehog) and (gear^.Hedgehog <> nil) then + begin + RenderHealth(gear^.Hedgehog^); + RecountTeamHealth(gear^.Hedgehog^.Team) + end; + // Why did this do a "setalltoactive" ? + //SetAllToActive; + Gear^.Active:= true; + AllInactive:= false end end; lc_sethealth:= 0 @@ -1178,11 +1619,7 @@ function lc_settimer(L : Plua_State) : LongInt; Cdecl; var gear : PGear; begin - if lua_gettop(L) <> 2 then - begin - LuaParameterCountError('SetTimer', 'gearUid, timer', lua_gettop(L)); - end - else + if CheckLuaParamCount(L, 2, 'SetTimer', 'gearUid, timer') then begin gear:= GearByUID(lua_tointeger(L, 1)); if gear <> nil then gear^.Timer:= lua_tointeger(L, 2) @@ -1190,45 +1627,65 @@ lc_settimer:= 0 end; +function lc_setflighttime(L : Plua_State) : LongInt; Cdecl; +var gear : PGear; +begin + if CheckLuaParamCount(L, 2, 'SetFlightTime', 'gearUid, flighttime') then + begin + gear:= GearByUID(lua_tointeger(L, 1)); + if gear <> nil then gear^.FlightTime:= lua_tointeger(L, 2) + end; + lc_setflighttime:= 0 +end; + function lc_seteffect(L : Plua_State) : LongInt; Cdecl; var gear: PGear; + t : LongInt; +const + call = 'SetEffect'; + params = 'gearUid, effect, effectState'; begin - if lua_gettop(L) <> 3 then - LuaParameterCountError('SetEffect', 'gearUid, effect, enabled', lua_gettop(L)) - else begin - gear := GearByUID(lua_tointeger(L, 1)); - if (gear <> nil) and (gear^.Hedgehog <> nil) then - gear^.Hedgehog^.Effects[THogEffect(lua_tointeger(L, 2))]:= lua_tointeger(L, 3); - end; + if CheckLuaParamCount(L, 3, call, params) then + begin + t:= LuaToHogEffectOrd(L, 2, call, params); + if t >= 0 then + begin + gear := GearByUID(lua_tointeger(L, 1)); + if (gear <> nil) and (gear^.Hedgehog <> nil) then + gear^.Hedgehog^.Effects[THogEffect(t)]:= lua_tointeger(L, 3); + end; + end; lc_seteffect := 0; end; function lc_geteffect(L : Plua_State) : LongInt; Cdecl; var gear : PGear; + t : LongInt; +const + call = 'GetEffect'; + params = 'gearUid, effect'; begin - if lua_gettop(L) <> 2 then + if CheckLuaParamCount(L, 2, call, params) then begin - LuaParameterCountError('GetEffect', 'gearUid, effect', lua_gettop(L)); + t:= LuaToHogEffectOrd(L, 2, call, params); + if t >= 0 then + begin + gear:= GearByUID(lua_tointeger(L, 1)); + if (gear <> nil) and (gear^.Hedgehog <> nil) then + lua_pushinteger(L, gear^.Hedgehog^.Effects[THogEffect(t)]) + else + lua_pushinteger(L, 0) + end; end else - begin - gear:= GearByUID(lua_tointeger(L, 1)); - if (gear <> nil) and (gear^.Hedgehog <> nil) then - lua_pushinteger(L, gear^.Hedgehog^.Effects[THogEffect(lua_tointeger(L, 2))]) - else - lua_pushinteger(L, 0) - end; + lua_pushinteger(L, 0); lc_geteffect:= 1 end; function lc_setstate(L : Plua_State) : LongInt; Cdecl; var gear : PGear; begin - if lua_gettop(L) <> 2 then - begin - LuaParameterCountError('SetState', 'gearUid, state', lua_gettop(L)); - end - else + if CheckLuaParamCount(L, 2, 'SetState', 'gearUid, state') then begin gear:= GearByUID(lua_tointeger(L, 1)); if gear <> nil then @@ -1243,48 +1700,39 @@ function lc_getstate(L : Plua_State) : LongInt; Cdecl; var gear : PGear; begin - if lua_gettop(L) <> 1 then - begin - LuaParameterCountError('GetState', 'gearUid', lua_gettop(L)); - end - else + if CheckLuaParamCount(L, 1, 'GetState', 'gearUid') then begin gear:= GearByUID(lua_tointeger(L, 1)); if gear <> nil then lua_pushinteger(L, gear^.State) else lua_pushnil(L) - end; + end + else + lua_pushnil(L); // return value on stack (nil) lc_getstate:= 1 end; function lc_gettag(L : Plua_State) : LongInt; Cdecl; var gear : PGear; begin - if lua_gettop(L) <> 1 then - begin - LuaParameterCountError('GetTag', 'gearUid', lua_gettop(L)); - lua_pushnil(L); // return value on stack (nil) - end - else + if CheckLuaParamCount(L, 1, 'GetTag', 'gearUid') then begin gear:= GearByUID(lua_tointeger(L, 1)); if gear <> nil then lua_pushinteger(L, gear^.Tag) else lua_pushnil(L); - end; + end + else + lua_pushnil(L); // return value on stack (nil) lc_gettag:= 1 end; function lc_settag(L : Plua_State) : LongInt; Cdecl; var gear : PGear; begin - if lua_gettop(L) <> 2 then - begin - LuaParameterCountError('SetTag', 'gearUid, tag', lua_gettop(L)); - end - else + if CheckLuaParamCount(L, 2, 'SetTag', 'gearUid, tag') then begin gear:= GearByUID(lua_tointeger(L, 1)); if gear <> nil then @@ -1305,50 +1753,62 @@ function lc_sendstat(L : Plua_State) : LongInt; Cdecl; var statInfo : TStatInfoType; -var i : LongInt; -var color : shortstring; + i, n : LongInt; + color, tn: shortstring; + needsTn : boolean; +const + call = 'SendStat'; + params = 'statInfoType, color [, teamname]'; begin - statInfo := TStatInfoType(lua_tointeger(L, 1)); - if (lua_gettop(L) <> 2) and ((statInfo <> siPlayerKills) - and (statInfo <> siClanHealth)) then + if CheckAndFetchParamCount(L, 2, 3, call, params, n) then begin - LuaParameterCountError('SendStat', 'statInfoType, color', lua_gettop(L)); - end - else if (lua_gettop(L) <> 3) and ((statInfo = siPlayerKills) - or (statInfo = siClanHealth)) then - begin - LuaParameterCountError('SendStat', 'siClanHealth, color, teamname', lua_gettop(L)); - end - else - begin - if ((statInfo = siPlayerKills) or (statInfo = siClanHealth)) then + i:= LuaToStatInfoTypeOrd(L, 1, call, params); + if i >= 0 then begin - // 3: team name - for i:= 0 to Pred(TeamsCount) do + statInfo:= TStatInfoType(i); + needsTn:= ((statInfo = siPlayerKills) or (statInfo = siClanHealth)); + // check if param count is correct for the used statInfo + if (n = 3) <> needsTn then + begin + if n = 3 then + LuaCallError(EnumToStr(statInfo) + ' does not support the teamname parameter', call, params) + else + LuaCallError(EnumToStr(statInfo) + ' requires the teamname parameter', call, params); + end + else // count is correct! begin - with TeamsArray[i]^ do + if needsTn then begin - if TeamName = lua_tostring(L, 3) then + // 3: team name + for i:= 0 to Pred(TeamsCount) do + begin + color:= _S'0'; + tn:= lua_tostring(L, 3); + with TeamsArray[i]^ do begin - color := uUtils.IntToStr(Clan^.Color); - Break; + if TeamName = tn then + begin + color := uUtils.IntToStr(Clan^.Color); + Break; + end end + end; + if (statInfo = siPlayerKills) then + begin + SendStat(siPlayerKills, color + ' ' + + lua_tostring(L, 2) + ' ' + tn); + end + else if (statInfo = siClanHealth) then + begin + SendStat(siClanHealth, color + ' ' + + lua_tostring(L, 2)); + end end + else + begin + SendStat(statInfo,lua_tostring(L, 2)); + end; end; - if (statInfo = siPlayerKills) then - begin - SendStat(siPlayerKills, color + ' ' + - lua_tostring(L, 2) + ' ' + TeamsArray[i]^.TeamName); - end - else if (statInfo = siClanHealth) then - begin - SendStat(siClanHealth, color + ' ' + - lua_tostring(L, 2)); - end - end - else - begin - SendStat(statInfo,lua_tostring(L, 2)); end; end; lc_sendstat:= 0 @@ -1365,54 +1825,60 @@ var gear: PGear; fall: boolean; tryhard: boolean; - left, right: LongInt; + left, right, n: LongInt; begin - tryhard:= false; - if (lua_gettop(L) <> 4) and (lua_gettop(L) <> 5) then - LuaParameterCountError('FindPlace', 'gearUid, fall, left, right[, tryHarder]', lua_gettop(L)) - else + if CheckAndFetchParamCount(L, 4, 5, 'FindPlace', 'gearUid, fall, left, right [, tryHarder]', n) then begin gear:= GearByUID(lua_tointeger(L, 1)); fall:= lua_toboolean(L, 2); left:= lua_tointeger(L, 3); right:= lua_tointeger(L, 4); - if lua_gettop(L) = 5 then - tryhard:= lua_toboolean(L, 5); + if n = 5 then + tryhard:= lua_toboolean(L, 5) + else + tryhard:= false; if gear <> nil then FindPlace(gear, fall, left, right, tryhard); if gear <> nil then lua_pushinteger(L, gear^.uid) else lua_pushnil(L); - end; + end + else + lua_pushnil(L); // return value on stack (nil) lc_findplace:= 1 end; function lc_playsound(L : Plua_State) : LongInt; Cdecl; var gear: PGear; + n, s: LongInt; +const + call = 'PlaySound'; + params = 'soundId [, hhGearUid]'; begin - if lua_gettop(L) = 1 then - PlaySound(TSound(lua_tointeger(L, 1))) - else if lua_gettop(L) = 2 then + if CheckAndFetchParamCount(L, 1, 2, call, params, n) then begin - gear:= GearByUID(lua_tointeger(L, 2)); - if (gear <> nil) and (gear^.Kind = gtHedgehog) and (gear^.Hedgehog <> nil) then - AddVoice(TSound(lua_tointeger(L, 1)),gear^.Hedgehog^.Team^.Voicepack) - end - else LuaParameterCountError('PlaySound', 'soundId', lua_gettop(L)); + s:= LuaToSoundOrd(L, 1, call, params); + if s >= 0 then + begin + // no gear specified + if n = 1 then + PlaySound(TSound(s)) + else + begin + gear:= GearByUID(lua_tointeger(L, 2)); + if (gear <> nil) and (gear^.Kind = gtHedgehog) and (gear^.Hedgehog <> nil) then + AddVoice(TSound(s),gear^.Hedgehog^.Team^.Voicepack) + end; + end; + end; lc_playsound:= 0; end; function lc_addteam(L : Plua_State) : LongInt; Cdecl; var np: LongInt; begin - np:= lua_gettop(L); - if (np < 5) or (np > 6) then - begin - LuaParameterCountError('AddTeam', 'teamname, color, grave, fort, voicepack[, flag]', lua_gettop(L)); - //lua_pushnil(L) - end - else + if CheckAndFetchParamCount(L, 5, 6, 'AddTeam', 'teamname, color, grave, fort, voicepack [, flag]', np) then begin ParseCommand('addteam x ' + lua_tostring(L, 2) + ' ' + lua_tostring(L, 1), true, true); ParseCommand('grave ' + lua_tostring(L, 3), true, true); @@ -1423,35 +1889,73 @@ // fails on x64 //lua_pushinteger(L, LongInt(CurrentTeam)); end; + //else + //lua_pushnil(L) lc_addteam:= 0;//1; end; +function lc_dismissteam(L : Plua_State) : LongInt; Cdecl; +var HHGear: PGear; + i, h : LongInt; + hidden: boolean; +begin + if CheckLuaParamCount(L, 1, 'DismissTeam', 'teamname') then + begin + if TeamsCount > 0 then + for i:= 0 to Pred(TeamsCount) do + begin + // skip teams that don't have matching name + if TeamsArray[i]^.TeamName <> lua_tostring(L, 1) then + continue; + + // destroy all hogs of matching team, including the hidden ones + for h:= 0 to cMaxHHIndex do + begin + hidden:= (TeamsArray[i]^.Hedgehogs[h].GearHidden <> nil); + if hidden then + RestoreHog(@TeamsArray[i]^.Hedgehogs[h]); + // destroy hedgehog gear, if any + HHGear:= TeamsArray[i]^.Hedgehogs[h].Gear; + if HHGear <> nil then + begin + // smoke effect + if (not hidden) then + begin + AddVisualGear(hwRound(HHGear^.X), hwRound(HHGear^.Y), vgtSmokeWhite); + AddVisualGear(hwRound(HHGear^.X) - 16 + Random(32), hwRound(HHGear^.Y) - 16 + Random(32), vgtSmokeWhite); + AddVisualGear(hwRound(HHGear^.X) - 16 + Random(32), hwRound(HHGear^.Y) - 16 + Random(32), vgtSmokeWhite); + AddVisualGear(hwRound(HHGear^.X) - 16 + Random(32), hwRound(HHGear^.Y) - 16 + Random(32), vgtSmokeWhite); + AddVisualGear(hwRound(HHGear^.X) - 16 + Random(32), hwRound(HHGear^.Y) - 16 + Random(32), vgtSmokeWhite); + end; + HHGear^.Message:= HHGear^.Message or gmDestroy; + end; + end; + // can't dismiss more than one team + break; + end; + end; + lc_dismissteam:= 0; +end; + function lc_addhog(L : Plua_State) : LongInt; Cdecl; var temp: ShortString; begin - if lua_gettop(L) <> 4 then - begin - LuaParameterCountError('AddHog', 'hogname, botlevel, health, hat', lua_gettop(L)); - lua_pushnil(L) - end - else + if CheckLuaParamCount(L, 4, 'AddHog', 'hogname, botlevel, health, hat') then begin temp:= lua_tostring(L, 4); ParseCommand('addhh ' + lua_tostring(L, 2) + ' ' + lua_tostring(L, 3) + ' ' + lua_tostring(L, 1), true, true); ParseCommand('hat ' + temp, true, true); lua_pushinteger(L, CurrentHedgehog^.Gear^.uid); - end; + end + else + lua_pushnil(L); lc_addhog:= 1; end; function lc_hogturnleft(L : Plua_State) : LongInt; Cdecl; var gear: PGear; begin - if lua_gettop(L) <> 2 then - begin - LuaParameterCountError('HogTurnLeft', 'gearUid, boolean', lua_gettop(L)); - end - else + if CheckLuaParamCount(L, 2, 'HogTurnLeft', 'gearUid, boolean') then begin gear:= GearByUID(lua_tointeger(L, 1)); if gear <> nil then @@ -1463,13 +1967,7 @@ function lc_getgearposition(L : Plua_State) : LongInt; Cdecl; var gear: PGear; begin - if lua_gettop(L) <> 1 then - begin - LuaParameterCountError('GetGearPosition', 'gearUid', lua_gettop(L)); - lua_pushnil(L); - lua_pushnil(L) - end - else + if CheckLuaParamCount(L, 1, 'GetGearPosition', 'gearUid') then begin gear:= GearByUID(lua_tointeger(L, 1)); if gear <> nil then @@ -1482,6 +1980,11 @@ lua_pushnil(L); lua_pushnil(L) end; + end + else + begin + lua_pushnil(L); + lua_pushnil(L) end; lc_getgearposition:= 2; end; @@ -1491,9 +1994,7 @@ col: boolean; x, y: LongInt; begin - if lua_gettop(L) <> 3 then - LuaParameterCountError('SetGearPosition', 'gearUid, x, y', lua_gettop(L)) - else + if CheckLuaParamCount(L, 3, 'SetGearPosition', 'gearUid, x, y') then begin gear:= GearByUID(lua_tointeger(L, 1)); if gear <> nil then @@ -1516,13 +2017,7 @@ function lc_getgeartarget(L : Plua_State) : LongInt; Cdecl; var gear: PGear; begin - if lua_gettop(L) <> 1 then - begin - LuaParameterCountError('GetGearTarget', 'gearUid', lua_gettop(L)); - lua_pushnil(L); - lua_pushnil(L) - end - else + if CheckLuaParamCount(L, 1, 'GetGearTarget', 'gearUid') then begin gear:= GearByUID(lua_tointeger(L, 1)); if gear <> nil then @@ -1535,6 +2030,11 @@ lua_pushnil(L); lua_pushnil(L) end + end + else + begin + lua_pushnil(L); + lua_pushnil(L) end; lc_getgeartarget:= 2; end; @@ -1542,9 +2042,7 @@ function lc_setgeartarget(L : Plua_State) : LongInt; Cdecl; var gear: PGear; begin - if lua_gettop(L) <> 3 then - LuaParameterCountError('SetGearTarget', 'gearUid, x, y', lua_gettop(L)) - else + if CheckLuaParamCount(L, 3, 'SetGearTarget', 'gearUid, x, y') then begin gear:= GearByUID(lua_tointeger(L, 1)); if gear <> nil then @@ -1560,13 +2058,7 @@ var gear: PGear; var t: LongInt; begin - if lua_gettop(L) <> 1 then - begin - LuaParameterCountError('GetGearVelocity', 'gearUid', lua_gettop(L)); - lua_pushnil(L); - lua_pushnil(L) - end - else + if CheckLuaParamCount(L, 1, 'GetGearVelocity', 'gearUid') then begin gear:= GearByUID(lua_tointeger(L, 1)); if gear <> nil then @@ -1577,6 +2069,11 @@ lua_pushinteger(L, t); lua_pushinteger(L, hwRound(gear^.dY * 1000000)) end + end + else + begin + lua_pushnil(L); + lua_pushnil(L); end; lc_getgearvelocity:= 2; end; @@ -1584,9 +2081,7 @@ function lc_setgearvelocity(L : Plua_State) : LongInt; Cdecl; var gear: PGear; begin - if lua_gettop(L) <> 3 then - LuaParameterCountError('SetGearVelocity', 'gearUid, dx, dy', lua_gettop(L)) - else + if CheckLuaParamCount(L, 3, 'SetGearVelocity', 'gearUid, dx, dy') then begin gear:= GearByUID(lua_tointeger(L, 1)); if gear <> nil then @@ -1601,9 +2096,7 @@ function lc_setzoom(L : Plua_State) : LongInt; Cdecl; begin - if lua_gettop(L) <> 1 then - LuaParameterCountError('SetZoom', 'zoomLevel', lua_gettop(L)) - else + if CheckLuaParamCount(L, 1, 'SetZoom', 'zoomLevel') then begin ZoomValue:= lua_tonumber(L, 1); if ZoomValue < cMaxZoomLevel then @@ -1616,47 +2109,51 @@ function lc_getzoom(L : Plua_State) : LongInt; Cdecl; begin - if lua_gettop(L) <> 0 then - begin - LuaParameterCountError('GetZoom', '', lua_gettop(L)); - lua_pushnil(L) - end + if CheckLuaParamCount(L, 0, 'GetZoom', '') then + lua_pushnumber(L, ZoomValue) else - lua_pushnumber(L, ZoomValue); + lua_pushnil(L); lc_getzoom:= 1 end; function lc_setammo(L : Plua_State) : LongInt; Cdecl; -var np: LongInt; +var np, at: LongInt; +const + call = 'SetAmmo'; + params = 'ammoType, count, probability, delay [, numberInCrate]'; begin - np:= lua_gettop(L); - if (np < 4) or (np > 5) then - LuaParameterCountError('SetAmmo', 'ammoType, count, probability, delay[, numberInCrate]', lua_gettop(L)) - else if np = 4 then - ScriptSetAmmo(TAmmoType(lua_tointeger(L, 1)), lua_tointeger(L, 2), lua_tointeger(L, 3), lua_tointeger(L, 4), 1) - else - ScriptSetAmmo(TAmmoType(lua_tointeger(L, 1)), lua_tointeger(L, 2), lua_tointeger(L, 3), lua_tointeger(L, 4), lua_tointeger(L, 5)); + if CheckAndFetchParamCount(L, 4, 5, call, params, np) then + begin + at:= LuaToAmmoTypeOrd(L, 1, call, params); + if at >= 0 then + begin + if np = 4 then + ScriptSetAmmo(TAmmoType(at), lua_tointeger(L, 2), lua_tointeger(L, 3), lua_tointeger(L, 4), 1) + else + ScriptSetAmmo(TAmmoType(at), lua_tointeger(L, 2), lua_tointeger(L, 3), lua_tointeger(L, 4), lua_tointeger(L, 5)); + end; + end; lc_setammo:= 0 end; function lc_setammodelay(L : Plua_State) : LongInt; Cdecl; -var np: LongInt; +var at: LongInt; +const + call = 'SetAmmoDelay'; + params = 'ammoType, delay'; begin - np:= lua_gettop(L); - if (np <> 2) then - LuaParameterCountError('SetAmmoDelay', 'ammoType, delay', lua_gettop(L)) - else - ScriptSetAmmoDelay(TAmmoType(lua_tointeger(L, 1)), lua_tointeger(L, 2)); + if CheckLuaParamCount(L, 2, call, params) then + begin + at:= LuaToAmmoTypeOrd(L, 1, call, params); + if at >= 0 then + ScriptSetAmmoDelay(TAmmoType(at), lua_tointeger(L, 2)); + end; lc_setammodelay:= 0 end; function lc_setammostore(L : Plua_State) : LongInt; Cdecl; -var np: LongInt; begin - np:= lua_gettop(L); - if (np <> 4) then - LuaParameterCountError('SetAmmoStore', 'loadouts, probabilities, delays, reinforments', lua_gettop(L)) - else + if CheckLuaParamCount(L, 4, 'SetAmmoStore', 'loadouts, probabilities, delays, reinforments') then begin ScriptAmmoLoadout:= lua_tostring(L, 1); ScriptAmmoProbability:= lua_tostring(L, 2); @@ -1669,12 +2166,7 @@ function lc_getrandom(L : Plua_State) : LongInt; Cdecl; var m : LongInt; begin - if lua_gettop(L) <> 1 then - begin - LuaParameterCountError('GetRandom', 'number', lua_gettop(L)); - lua_pushnil(L); // return value on stack (nil) - end - else + if CheckLuaParamCount(L, 1, 'GetRandom', 'number') then begin m:= lua_tointeger(L, 1); if (m > 0) then @@ -1684,15 +2176,15 @@ LuaError('Lua: Tried to pass 0 to GetRandom!'); lua_pushnil(L); end - end; + end + else + lua_pushnil(L); // return value on stack (nil) lc_getrandom:= 1 end; function lc_setwind(L : Plua_State) : LongInt; Cdecl; begin - if lua_gettop(L) <> 1 then - LuaParameterCountError('SetWind', 'windSpeed', lua_gettop(L)) - else + if CheckLuaParamCount(L, 1, 'SetWind', 'windSpeed') then begin cWindSpeed:= int2hwfloat(lua_tointeger(L, 1)) / 100 * cMaxWindSpeed; cWindSpeedf:= SignAs(cWindSpeed,cWindSpeed).QWordValue / SignAs(_1,_1).QWordValue; @@ -1705,71 +2197,60 @@ function lc_getdatapath(L : Plua_State) : LongInt; Cdecl; begin - if lua_gettop(L) <> 0 then - begin - LuaParameterCountError('GetDataPath', '', lua_gettop(L)); + if CheckLuaParamCount(L, 0, 'GetDataPath', '') then + lua_pushstring(L, str2pchar(cPathz[ptData])) + else lua_pushnil(L); - end - else - lua_pushstring(L, str2pchar(cPathz[ptData])); lc_getdatapath:= 1 end; function lc_getuserdatapath(L : Plua_State) : LongInt; Cdecl; begin - if lua_gettop(L) <> 0 then - begin - LuaParameterCountError('GetUserDataPath', '', lua_gettop(L)); + if CheckLuaParamCount(L, 0, 'GetUserDataPath', '') then + lua_pushstring(L, str2pchar(cPathz[ptData])) + else lua_pushnil(L); - end - else - lua_pushstring(L, str2pchar(cPathz[ptData])); lc_getuserdatapath:= 1 end; function lc_maphasborder(L : Plua_State) : LongInt; Cdecl; begin - if lua_gettop(L) <> 0 then - begin - LuaParameterCountError('MapHasBorder', '', lua_gettop(L)); + if CheckLuaParamCount(L, 0, 'MapHasBorder', '') then + lua_pushboolean(L, hasBorder) + else lua_pushnil(L); - end - else - lua_pushboolean(L, hasBorder); lc_maphasborder:= 1 end; function lc_getgearradius(L : Plua_State) : LongInt; Cdecl; var gear : PGear; begin - if lua_gettop(L) <> 1 then - begin - LuaParameterCountError('GetGearRadius', 'gearUid', lua_gettop(L)); - lua_pushnil(L); // return value on stack (nil) - end - else + if CheckLuaParamCount(L, 1, 'GetGearRadius', 'gearUid') then begin gear:= GearByUID(lua_tointeger(L, 1)); if gear <> nil then lua_pushinteger(L, gear^.Radius) else lua_pushnil(L); - end; + end + else + lua_pushnil(L); // return value on stack (nil) lc_getgearradius:= 1 end; function lc_gethoghat(L : Plua_State): LongInt; Cdecl; var gear : PGear; begin - if lua_gettop(L) <> 1 then - LuaParameterCountError('GetHogHat', 'gearUid', lua_gettop(L)) - else begin + if CheckLuaParamCount(L, 1, 'GetHogHat', 'gearUid') then + begin gear := GearByUID(lua_tointeger(L, 1)); if (gear <> nil) and ((gear^.Kind = gtHedgehog) or (gear^.Kind = gtGrave)) and (gear^.Hedgehog <> nil) then lua_pushstring(L, str2pchar(gear^.Hedgehog^.Hat)) else lua_pushnil(L); - end; + end + else + lua_pushnil(L); lc_gethoghat := 1; end; @@ -1777,12 +2258,7 @@ var gear : PGear; hat: ShortString; begin - if lua_gettop(L) <> 2 then - begin - LuaParameterCountError('SetHogHat', 'gearUid, hat', lua_gettop(L)); - lua_pushnil(L) - end - else + if CheckLuaParamCount(L, 2, 'SetHogHat', 'gearUid, hat') then begin gear:= GearByUID(lua_tointeger(L, 1)); if (gear <> nil) and (gear^.Kind = gtHedgehog) and (gear^.Hedgehog <> nil) then @@ -1799,42 +2275,133 @@ lc_sethoghat:= 0; end; -function lc_placegirder(L : Plua_State) : LongInt; Cdecl; +function lc_placesprite(L : Plua_State) : LongInt; Cdecl; +var spr : TSprite; + lf : Word; + tint : LongWord; + i, n : LongInt; + placed, behind, flipHoriz, flipVert : boolean; +const + call = 'PlaceSprite'; + params = 'x, y, sprite, frameIdx, tint, behind, flipHoriz, flipVert, [, landFlag, ... ]'; begin - if lua_gettop(L) <> 3 then - LuaParameterCountError('PlaceGirder', 'x, y, state', lua_gettop(L)) - else - TryPlaceOnLand( + placed:= false; + if CheckAndFetchLuaParamMinCount(L, 4, call, params, n) then + begin + if not lua_isnoneornil(L, 5) then + tint := lua_tointeger(L, 5) + else tint := $FFFFFFFF; + if not lua_isnoneornil(L, 6) then + behind := lua_toboolean(L, 6) + else behind := false; + if not lua_isnoneornil(L, 7) then + flipHoriz := lua_toboolean(L, 7) + else flipHoriz := false; + if not lua_isnoneornil(L, 8) then + flipVert := lua_toboolean(L, 8) + else flipVert := false; + lf:= 0; + + // accept any amount of landflags, loop is never executed if n<9 + for i:= 9 to n do + lf:= lf or lua_tointeger(L, i); + + n:= LuaToSpriteOrd(L, 3, call, params); + if n >= 0 then + begin + spr:= TSprite(n); + if SpritesData[spr].Surface = nil then + LuaError(call + ': ' + EnumToStr(spr) + ' cannot be placed! (required information not loaded)' ) + else + placed:= ForcePlaceOnLand( + lua_tointeger(L, 1) - SpritesData[spr].Width div 2, + lua_tointeger(L, 2) - SpritesData[spr].Height div 2, + spr, lua_tointeger(L, 4), lf, tint, behind, flipHoriz, flipVert); + end; + end; + + lua_pushboolean(L, placed); + lc_placesprite:= 1 +end; + +function lc_erasesprite(L : Plua_State) : LongInt; Cdecl; +var spr : TSprite; + lf : Word; + i, n : LongInt; + eraseOnLFMatch, onlyEraseLF, flipHoriz, flipVert : boolean; +const + call = 'EraseSprite'; + params = 'x, y, sprite, frameIdx, eraseOnLFMatch, onlyEraseLF, flipHoriz, flipVert, [, landFlag, ... ]'; +begin + if CheckAndFetchLuaParamMinCount(L, 4, call, params, n) then + begin + if not lua_isnoneornil(L, 5) then + eraseOnLFMatch := lua_toboolean(L, 5) + else eraseOnLFMatch := false; + if not lua_isnoneornil(L, 6) then + onlyEraseLF := lua_toboolean(L, 6) + else onlyEraseLF := false; + if not lua_isnoneornil(L, 7) then + flipHoriz := lua_toboolean(L, 7) + else flipHoriz := false; + if not lua_isnoneornil(L, 8) then + flipVert := lua_toboolean(L, 8) + else flipVert := false; + lf:= 0; + + // accept any amount of landflags, loop is never executed if n<9 + for i:= 9 to n do + lf:= lf or lua_tointeger(L, i); + + n:= LuaToSpriteOrd(L, 3, call, params); + if n >= 0 then + begin + spr:= TSprite(n); + if SpritesData[spr].Surface = nil then + LuaError(call + ': ' + EnumToStr(spr) + ' cannot be placed! (required information not loaded)' ) + else + EraseLand( + lua_tointeger(L, 1) - SpritesData[spr].Width div 2, + lua_tointeger(L, 2) - SpritesData[spr].Height div 2, + spr, lua_tointeger(L, 4), lf, eraseOnLFMatch, onlyEraseLF, flipHoriz, flipVert); + end; + end; + lc_erasesprite:= 0 +end; + +function lc_placegirder(L : Plua_State) : LongInt; Cdecl; +var placed: boolean; +begin + placed:= false; + if CheckLuaParamCount(L, 3, 'PlaceGirder', 'x, y, frameIdx') then + placed:= TryPlaceOnLandSimple( lua_tointeger(L, 1) - SpritesData[sprAmGirder].Width div 2, lua_tointeger(L, 2) - SpritesData[sprAmGirder].Height div 2, sprAmGirder, lua_tointeger(L, 3), true, false); - lc_placegirder:= 0 + + lua_pushboolean(L, placed); + lc_placegirder:= 1 end; function lc_getcurammotype(L : Plua_State): LongInt; Cdecl; begin - if lua_gettop(L) <> 0 then - LuaParameterCountError('GetCurAmmoType', '', lua_gettop(L)) + if (CurrentHedgehog <> nil) and (CheckLuaParamCount(L, 0, 'GetCurAmmoType', '')) then + lua_pushinteger(L, ord(CurrentHedgehog^.CurAmmoType)) else - lua_pushinteger(L, ord(CurrentHedgehog^.CurAmmoType)); + lua_pushinteger(L, ord(amNothing)); lc_getcurammotype := 1; end; function lc_savecampaignvar(L : Plua_State): LongInt; Cdecl; begin - if lua_gettop(L) <> 2 then - LuaParameterCountError('SaveCampaignVar', 'varname, value', lua_gettop(L)) - else begin + if CheckLuaParamCount(L, 2, 'SaveCampaignVar', 'varname, value') then SendIPC('V!' + lua_tostring(L, 1) + ' ' + lua_tostring(L, 2) + #0); - end; lc_savecampaignvar := 0; end; function lc_getcampaignvar(L : Plua_State): LongInt; Cdecl; begin - if (lua_gettop(L) <> 1) then - LuaParameterCountError('GetCampaignVar', 'varname', lua_gettop(L)) - else + if CheckLuaParamCount(L, 1, 'GetCampaignVar', 'varname') then SendIPCAndWaitReply('V?' + lua_tostring(L, 1) + #0); lua_pushstring(L, str2pchar(CampaignVariable)); lc_getcampaignvar := 1; @@ -1843,9 +2410,7 @@ function lc_hidehog(L: Plua_State): LongInt; Cdecl; var gear: PGear; begin - if lua_gettop(L) <> 1 then - LuaParameterCountError('HideHog', 'gearUid', lua_gettop(L)) - else + if CheckLuaParamCount(L, 1, 'HideHog', 'gearUid') then begin gear:= GearByUID(lua_tointeger(L, 1)); HideHog(gear^.hedgehog) @@ -1857,9 +2422,7 @@ var i, h: LongInt; uid: LongWord; begin - if lua_gettop(L) <> 1 then - LuaParameterCountError('RestoreHog', 'gearUid', lua_gettop(L)) - else + if CheckLuaParamCount(L, 1, 'RestoreHog', 'gearUid') then begin uid:= LongWord(lua_tointeger(L, 1)); if TeamsCount > 0 then @@ -1878,14 +2441,9 @@ function lc_testrectforobstacle(L : Plua_State) : LongInt; Cdecl; var rtn: Boolean; begin - if lua_gettop(L) <> 5 then + if CheckLuaParamCount(L, 5, 'TestRectForObstacle', 'x1, y1, x2, y2, landOnly') then begin - LuaParameterCountError('TestRectForObstacle', 'x1, y1, x2, y2, landOnly', lua_gettop(L)); - lua_pushnil(L); // return value on stack (nil) - end - else - begin - rtn:= TestRectancleForObstacle( + rtn:= TestRectangleForObstacle( lua_tointeger(L, 1), lua_tointeger(L, 2), lua_tointeger(L, 3), @@ -1893,47 +2451,165 @@ lua_toboolean(L, 5) ); lua_pushboolean(L, rtn); - end; + end + else + lua_pushnil(L); // return value on stack (nil) lc_testrectforobstacle:= 1 end; -function lc_setaihintsongear(L : Plua_State) : LongInt; Cdecl; +function lc_getgravity(L : Plua_State) : LongInt; Cdecl; +begin + if CheckLuaParamCount(L, 0, 'GetGravity', '') then + lua_pushinteger(L, hwRound(SignAs(_0_5, cGravity) + (cGravity * 50 / cMaxWindSpeed))); + lc_getgravity:= 1 +end; + +function lc_setgravity(L : Plua_State) : LongInt; Cdecl; +begin + if CheckLuaParamCount(L, 1, 'SetGravity', 'percent') then + begin + cGravity:= _0_02 * lua_tointeger(L, 1) * cMaxWindSpeed; + cGravityf:= 0.00025 * lua_tointeger(L, 1) * 0.02 + end; + lc_setgravity:= 0 +end; + +function lc_setwaterline(L : Plua_State) : LongInt; Cdecl; +var iterator: PGear; +begin + if CheckLuaParamCount(L, 1, 'SetWaterLine', 'waterline') then + begin + cWaterLine:= lua_tointeger(L,1); + AllInactive:= false; + iterator:= GearsList; + while iterator <> nil do + begin + if not (iterator^.Kind in [gtPortal, gtAirAttack]) and (iterator^.Message and (gmAllStoppable or gmLJump or gmHJump) = 0) then + begin + iterator^.Active:= true; + if iterator^.dY.QWordValue = 0 then iterator^.dY.isNegative:= false; + iterator^.State:= iterator^.State or gstMoving; + DeleteCI(iterator) + end; + iterator:= iterator^.NextGear + end + end; + lc_setwaterline:= 0 +end; + +function lc_setgearaihints(L : Plua_State) : LongInt; Cdecl; var gear: PGear; begin - if lua_gettop(L) <> 2 then - LuaParameterCountError('SetAIHintOnGear', 'gearUid, aiHints', lua_gettop(L)) - else + if CheckLuaParamCount(L, 2, 'SetAIHintOnGear', 'gearUid, aiHints') then begin gear:= GearByUID(lua_tointeger(L, 1)); if gear <> nil then gear^.aihints:= lua_tointeger(L, 2); end; - lc_setaihintsongear:= 0 + lc_setgearaihints:= 0 end; function lc_hedgewarsscriptload(L : Plua_State) : LongInt; Cdecl; begin - if lua_gettop(L) <> 1 then - begin - LuaParameterCountError('HedgewarsScriptLoad', 'scriptPath', lua_gettop(L)); - lua_pushnil(L) - end + if CheckLuaParamCount(L, 1, 'HedgewarsScriptLoad', 'scriptPath') then + ScriptLoad(lua_tostring(L, 1)) else - ScriptLoad(lua_tostring(L, 1)); + lua_pushnil(L); lc_hedgewarsscriptload:= 0; end; function lc_declareachievement(L : Plua_State) : LongInt; Cdecl; begin - if lua_gettop(L) <> 4 then - LuaParameterCountError('DeclareAchievement', 'achievementId, teamname, location, value', lua_gettop(L)) - else + if CheckLuaParamCount(L, 4, 'DeclareAchievement', 'achievementId, teamname, location, value') then declareAchievement(lua_tostring(L, 1), lua_tostring(L, 2), lua_tostring(L, 3), lua_tointeger(L, 4)); lc_declareachievement:= 0 end; + + +procedure ScriptFlushPoints(); +begin + ParseCommand('draw ' + PointsBuffer, true, true); + PointsBuffer:= ''; +end; + + +function lc_addPoint(L : Plua_State) : LongInt; Cdecl; +var np, param: LongInt; +begin + if CheckAndFetchParamCountRange(L, 2, 4, 'AddPoint', 'x, y [, width [, erase] ]', np) then + begin + // x + param:= LongInt(lua_tointeger(L,1)); + PointsBuffer:= PointsBuffer + char((param shr 8) and $FF); + PointsBuffer:= PointsBuffer + char((param and $FF)); + // y + param:= LongInt(lua_tointeger(L,2)); + PointsBuffer:= PointsBuffer + char((param shr 8) and $FF); + PointsBuffer:= PointsBuffer + char((param and $FF)); + // width + if np > 2 then + begin + param:= lua_tointeger(L,3); + param:= (param or $80); + // erase + if (np > 3) and lua_toboolean(L, 4) then + param:= (param or $40); + PointsBuffer:= PointsBuffer + char(param); + end + // no width defined + else + PointsBuffer:= PointsBuffer + char(0); + + // flush before shortstring limit length is reached + if length(PointsBuffer) > 245 then + ScriptFlushPoints(); + end; + lc_addPoint:= 0 +end; + + +function lc_flushPoints(L : Plua_State) : LongInt; Cdecl; +begin + if CheckLuaParamCount(L, 0, 'FlushPoints', '') then + if length(PointsBuffer) > 0 then + ScriptFlushPoints(); + lc_flushPoints:= 0 +end; + +// stuff for lua tests +function lc_endluatest(L : Plua_State) : LongInt; Cdecl; +var rstring: shortstring; +const + call = 'EndLuaTest'; + params = 'TEST_SUCCESSFUL or TEST_FAILED'; +begin + if CheckLuaParamCount(L, 1, call, params) then + begin + + case lua_tointeger(L, 1) of + HaltTestSuccess : rstring:= 'Success'; + HaltTestLuaError: rstring:= 'FAILED'; + else + begin + LuaCallError('Parameter must be either ' + params, call, params); + exit(0); + end; + end; + + if cTestLua then + begin + WriteLnToConsole('Lua test finished, result: ' + rstring); + halt(lua_tointeger(L, 1)); + end + else LuaError('Not in lua test mode, engine will keep running. Reported test result: ' + rstring); + + end; + + lc_endluatest:= 0; +end; /////////////////// procedure ScriptPrintStack; @@ -1987,6 +2663,28 @@ lua_pop(luaState, 1); end; +procedure ScriptOnPreviewInit; +begin +// not required if there is no script to run +if not ScriptLoaded then + exit; + +ScriptSetString('Seed', cSeed); +ScriptSetInteger('TemplateFilter', cTemplateFilter); +ScriptSetInteger('TemplateNumber', LuaTemplateNumber); +ScriptSetInteger('MapGen', ord(cMapGen)); +ScriptSetInteger('MapFeatureSize', cFeatureSize); + +ScriptCall('onPreviewInit'); + +// pop game variables +ParseCommand('seed ' + ScriptGetString('Seed'), true, true); +cTemplateFilter := ScriptGetInteger('TemplateFilter'); +LuaTemplateNumber:= ScriptGetInteger('TemplateNumber'); +cMapGen := TMapGen(ScriptGetInteger('MapGen')); +cFeatureSize := ScriptGetInteger('MapFeatureSize'); +end; + procedure ScriptOnGameInit; var i, j, k: LongInt; begin @@ -1995,12 +2693,15 @@ exit; // push game variables so they may be modified by the script +ScriptSetInteger('CursorX', CursorPoint.X); +ScriptSetInteger('CursorY', CursorPoint.Y); ScriptSetInteger('BorderColor', ExplosionBorderColor); ScriptSetInteger('GameFlags', GameFlags); ScriptSetString('Seed', cSeed); ScriptSetInteger('TemplateFilter', cTemplateFilter); ScriptSetInteger('TemplateNumber', LuaTemplateNumber); -ScriptSetInteger('MapGen', cMapGen); +ScriptSetInteger('MapGen', ord(cMapGen)); +ScriptSetInteger('MapFeatureSize', cFeatureSize); ScriptSetInteger('ScreenHeight', cScreenHeight); ScriptSetInteger('ScreenWidth', cScreenWidth); ScriptSetInteger('TurnTime', cHedgehogTurnTime); @@ -2018,8 +2719,8 @@ ScriptSetInteger('SuddenDeathTurns', cSuddenDTurns); ScriptSetInteger('WaterRise', cWaterRise); ScriptSetInteger('HealthDecrease', cHealthDecrease); +ScriptSetInteger('GetAwayTime', cGetAwayTime); ScriptSetString('Map', cMapName); - ScriptSetString('Theme', ''); ScriptSetString('Goals', ''); @@ -2029,7 +2730,8 @@ ParseCommand('seed ' + ScriptGetString('Seed'), true, true); cTemplateFilter := ScriptGetInteger('TemplateFilter'); LuaTemplateNumber:= ScriptGetInteger('TemplateNumber'); -cMapGen := ScriptGetInteger('MapGen'); +cMapGen := TMapGen(ScriptGetInteger('MapGen')); +cFeatureSize := ScriptGetInteger('MapFeatureSize'); GameFlags := ScriptGetInteger('GameFlags'); cHedgehogTurnTime:= ScriptGetInteger('TurnTime'); cCaseFactor := ScriptGetInteger('CaseFreq'); @@ -2046,6 +2748,7 @@ cSuddenDTurns := ScriptGetInteger('SuddenDeathTurns'); cWaterRise := ScriptGetInteger('WaterRise'); cHealthDecrease := ScriptGetInteger('HealthDecrease'); +cGetAwayTime := ScriptGetInteger('GetAwayTime'); if cMapName <> ScriptGetString('Map') then ParseCommand('map ' + ScriptGetString('Map'), true, true); @@ -2133,8 +2836,8 @@ if ret <> 0 then begin - LuaError('Lua: Failed to load ' + name + '(error ' + IntToStr(ret) + ')'); - LuaError('Lua: ' + lua_tostring(luaState, -1)); + LuaError('Failed to load ' + name + '(error ' + IntToStr(ret) + ')'); + LuaError(lua_tostring(luaState, -1)); end else begin @@ -2143,7 +2846,7 @@ lua_pcall(luaState, 0, 0, 0); ScriptLoaded:= true end; - hedgewarsMountPackage(Str2PChar(copy(s, 1, length(s)-4)+'.hwp')); +hedgewarsMountPackage(Str2PChar(copy(s, 1, length(s)-4)+'.hwp')); end; procedure SetGlobals; @@ -2152,6 +2855,25 @@ ScriptSetInteger('GameTime', GameTicks); ScriptSetInteger('TotalRounds', TotalRounds); ScriptSetInteger('WaterLine', cWaterLine); +if isCursorVisible and (not bShowAmmoMenu) then + begin + if (prevCursorPoint.X <> CursorPoint.X) or + (prevCursorPoint.Y <> CursorPoint.Y) then + begin + ScriptSetInteger('CursorX', CursorPoint.X - WorldDx); + ScriptSetInteger('CursorY', cScreenHeight - CursorPoint.Y- WorldDy); + prevCursorPoint.X:= CursorPoint.X; + prevCursorPoint.Y:= CursorPoint.Y; + end + end +else + begin + ScriptSetInteger('CursorX', NoPointX); + ScriptSetInteger('CursorY', NoPointX); + prevCursorPoint.X:= NoPointX; + prevCursorPoint.Y:= NoPointX + end; + if not mapDims then begin mapDims:= true; @@ -2169,18 +2891,24 @@ procedure GetGlobals; begin +// TODO +// Use setters instead, because globals should be read-only! +// Otherwise globals might be changed by Lua, but then unexpectatly overwritten by engine when a ScriptCall is triggered by whatever Lua is doing! +// Sure, one could work around that in engine (e.g. by setting writable globals in SetGlobals only when their engine-side value has actually changed since SetGlobals was called the last time...), but things just get messier and messier then. +// It is inconsistent anyway to have some globals be read-only and others not with no indication whatsoever. +// -- sheepluva TurnTimeLeft:= ScriptGetInteger('TurnTimeLeft'); end; procedure ScriptCall(fname : shortstring); begin -if not ScriptLoaded or (not ScriptExists(fname)) then +if (not ScriptLoaded) or (not ScriptExists(fname)) then exit; SetGlobals; lua_getglobal(luaState, Str2PChar(fname)); if lua_pcall(luaState, 0, 0, 0) <> 0 then begin - LuaError('Lua: Error while calling ' + fname + ': ' + lua_tostring(luaState, -1)); + LuaError('Error while calling ' + fname + ': ' + lua_tostring(luaState, -1)); lua_pop(luaState, 1) end; GetGlobals; @@ -2225,8 +2953,8 @@ function ScriptCall(fname : shortstring; par1, par2, par3, par4 : LongInt) : LongInt; begin -if not ScriptLoaded or (not ScriptExists(fname)) then - exit; +if (not ScriptLoaded) or (not ScriptExists(fname)) then + exit(0); SetGlobals; lua_getglobal(luaState, Str2PChar(fname)); lua_pushinteger(luaState, par1); @@ -2236,7 +2964,7 @@ ScriptCall:= 0; if lua_pcall(luaState, 4, 1, 0) <> 0 then begin - LuaError('Lua: Error while calling ' + fname + ': ' + lua_tostring(luaState, -1)); + LuaError('Error while calling ' + fname + ': ' + lua_tostring(luaState, -1)); lua_pop(luaState, 1) end else @@ -2361,6 +3089,8 @@ st : TSound; he : THogEffect; cg : TCapGroup; + spr: TSprite; + mg : TMapGen; begin // initialize lua luaState:= lua_open; @@ -2385,6 +3115,7 @@ ScriptSetInteger('gfLowGravity', gfLowGravity); ScriptSetInteger('gfLaserSight', gfLaserSight); ScriptSetInteger('gfInvulnerable', gfInvulnerable); +ScriptSetInteger('gfResetHealth', gfResetHealth); ScriptSetInteger('gfVampiric', gfVampiric); ScriptSetInteger('gfKarma', gfKarma); ScriptSetInteger('gfArtillery', gfArtillery); @@ -2420,7 +3151,6 @@ ScriptSetInteger('gmPrecise', gmPrecise); ScriptSetInteger('gmAllStoppable', gmAllStoppable); - // speech bubbles ScriptSetInteger('SAY_SAY', 1); ScriptSetInteger('SAY_THINK', 2); @@ -2450,30 +3180,44 @@ for cg:= Low(TCapGroup) to High(TCapGroup) do ScriptSetInteger(EnumToStr(cg), ord(cg)); -ScriptSetInteger('gstDrowning' ,$00000001); -ScriptSetInteger('gstHHDriven' ,$00000002); -ScriptSetInteger('gstMoving' ,$00000004); -ScriptSetInteger('gstAttacked' ,$00000008); -ScriptSetInteger('gstAttacking' ,$00000010); -ScriptSetInteger('gstCollision' ,$00000020); -ScriptSetInteger('gstHHChooseTarget' ,$00000040); -ScriptSetInteger('gstHHJumping' ,$00000100); -ScriptSetInteger('gsttmpFlag' ,$00000200); -ScriptSetInteger('gstHHThinking' ,$00000800); -ScriptSetInteger('gstNoDamage' ,$00001000); -ScriptSetInteger('gstHHHJump' ,$00002000); -ScriptSetInteger('gstAnimation' ,$00004000); -ScriptSetInteger('gstHHDeath' ,$00008000); -ScriptSetInteger('gstWinner' ,$00010000); -ScriptSetInteger('gstWait' ,$00020000); -ScriptSetInteger('gstNotKickable' ,$00040000); -ScriptSetInteger('gstLoser' ,$00080000); -ScriptSetInteger('gstHHGone' ,$00100000); -ScriptSetInteger('gstInvisible' ,$00200000); +for spr:= Low(TSprite) to High(TSprite) do + ScriptSetInteger(EnumToStr(spr), ord(spr)); + +for mg:= Low(TMapGen) to High(TMapGen) do + ScriptSetInteger(EnumToStr(mg), ord(mg)); + +ScriptSetInteger('gstDrowning' , gstDrowning); +ScriptSetInteger('gstHHDriven' , gstHHDriven); +ScriptSetInteger('gstMoving' , gstMoving); +ScriptSetInteger('gstAttacked' , gstAttacked); +ScriptSetInteger('gstAttacking' , gstAttacking); +ScriptSetInteger('gstCollision' , gstCollision); +ScriptSetInteger('gstChooseTarget' , gstChooseTarget); +ScriptSetInteger('gstHHJumping' , gstHHJumping); +ScriptSetInteger('gsttmpFlag' , gsttmpFlag); +ScriptSetInteger('gstHHThinking' , gstHHThinking); +ScriptSetInteger('gstNoDamage' , gstNoDamage); +ScriptSetInteger('gstHHHJump' , gstHHHJump); +ScriptSetInteger('gstAnimation' , gstAnimation); +ScriptSetInteger('gstHHDeath' , gstHHDeath); +ScriptSetInteger('gstWinner' , gstWinner); +ScriptSetInteger('gstWait' , gstWait); +ScriptSetInteger('gstNotKickable' , gstNotKickable); +ScriptSetInteger('gstLoser' , gstLoser); +ScriptSetInteger('gstHHGone' , gstHHGone); +ScriptSetInteger('gstInvisible' , gstInvisible); +ScriptSetInteger('gstSubmersible' , gstSubmersible); +ScriptSetInteger('gstFrozen' , gstFrozen); +ScriptSetInteger('gstNoGravity' , gstNoGravity); // ai hints -ScriptSetInteger('aihUsualProcessing' ,$00000000); -ScriptSetInteger('aihDoesntMatter' ,$00000001); +ScriptSetInteger('aihUsualProcessing', aihUsualProcessing); +ScriptSetInteger('aihDoesntMatter' , aihDoesntMatter); + +// land flags +ScriptSetInteger('lfIndestructible', lfIndestructible); +ScriptSetInteger('lfIce' , lfIce); +ScriptSetInteger('lfBouncy' , lfBouncy); // register functions lua_register(luaState, _P'HideHog', @lc_hidehog); @@ -2487,14 +3231,18 @@ lua_register(luaState, _P'GetInputMask', @lc_getinputmask); lua_register(luaState, _P'SetInputMask', @lc_setinputmask); lua_register(luaState, _P'AddGear', @lc_addgear); +lua_register(luaState, _P'DismissTeam', @lc_dismissteam); lua_register(luaState, _P'EnableGameFlags', @lc_enablegameflags); lua_register(luaState, _P'DisableGameFlags', @lc_disablegameflags); lua_register(luaState, _P'ClearGameFlags', @lc_cleargameflags); +lua_register(luaState, _P'GetGameFlag', @lc_getgameflag); lua_register(luaState, _P'DeleteGear', @lc_deletegear); lua_register(luaState, _P'AddVisualGear', @lc_addvisualgear); lua_register(luaState, _P'DeleteVisualGear', @lc_deletevisualgear); lua_register(luaState, _P'GetVisualGearValues', @lc_getvisualgearvalues); lua_register(luaState, _P'SetVisualGearValues', @lc_setvisualgearvalues); +lua_register(luaState, _P'GetGearValues', @lc_getgearvalues); +lua_register(luaState, _P'SetGearValues', @lc_setgearvalues); lua_register(luaState, _P'SpawnHealthCrate', @lc_spawnhealthcrate); lua_register(luaState, _P'SpawnAmmoCrate', @lc_spawnammocrate); lua_register(luaState, _P'SpawnUtilityCrate', @lc_spawnutilitycrate); @@ -2532,6 +3280,9 @@ lua_register(luaState, _P'GetHogClan', @lc_gethogclan); lua_register(luaState, _P'GetClanColor', @lc_getclancolor); lua_register(luaState, _P'SetClanColor', @lc_setclancolor); +lua_register(luaState, _P'GetHogVoicepack', @lc_gethogvoicepack); +lua_register(luaState, _P'GetHogFlag', @lc_gethogflag); +lua_register(luaState, _P'GetHogGrave', @lc_gethoggrave); lua_register(luaState, _P'GetHogTeamName', @lc_gethogteamname); lua_register(luaState, _P'SetHogTeamName', @lc_sethogteamname); lua_register(luaState, _P'GetHogName', @lc_gethogname); @@ -2549,6 +3300,8 @@ lua_register(luaState, _P'SetTag', @lc_settag); lua_register(luaState, _P'SetTimer', @lc_settimer); lua_register(luaState, _P'GetTimer', @lc_gettimer); +lua_register(luaState, _P'SetFlightTime', @lc_setflighttime); +lua_register(luaState, _P'GetFlightTime', @lc_getflighttime); lua_register(luaState, _P'SetZoom', @lc_setzoom); lua_register(luaState, _P'GetZoom', @lc_getzoom); lua_register(luaState, _P'HogSay', @lc_hogsay); @@ -2557,6 +3310,9 @@ lua_register(luaState, _P'CampaignLock', @lc_campaignlock); lua_register(luaState, _P'CampaignUnlock', @lc_campaignunlock); lua_register(luaState, _P'GetGearElasticity', @lc_getgearelasticity); +lua_register(luaState, _P'SetGearElasticity', @lc_setgearelasticity); +lua_register(luaState, _P'GetGearFriction', @lc_getgearfriction); +lua_register(luaState, _P'SetGearFriction', @lc_setgearfriction); lua_register(luaState, _P'GetGearRadius', @lc_getgearradius); lua_register(luaState, _P'GetGearMessage', @lc_getgearmessage); lua_register(luaState, _P'SetGearMessage', @lc_setgearmessage); @@ -2571,14 +3327,28 @@ lua_register(luaState, _P'MapHasBorder', @lc_maphasborder); lua_register(luaState, _P'GetHogHat', @lc_gethoghat); lua_register(luaState, _P'SetHogHat', @lc_sethoghat); +lua_register(luaState, _P'EraseSprite', @lc_erasesprite); +lua_register(luaState, _P'PlaceSprite', @lc_placesprite); lua_register(luaState, _P'PlaceGirder', @lc_placegirder); lua_register(luaState, _P'GetCurAmmoType', @lc_getcurammotype); lua_register(luaState, _P'TestRectForObstacle', @lc_testrectforobstacle); +lua_register(luaState, _P'GetGravity', @lc_getgravity); +lua_register(luaState, _P'SetGravity', @lc_setgravity); +lua_register(luaState, _P'SetWaterLine', @lc_setwaterline); +lua_register(luaState, _P'SetNextWeapon', @lc_setnextweapon); +lua_register(luaState, _P'SetWeapon', @lc_setweapon); +lua_register(luaState, _P'SetMaxBuildDistance', @lc_setmaxbuilddistance); +// drawn map functions +lua_register(luaState, _P'AddPoint', @lc_addPoint); +lua_register(luaState, _P'FlushPoints', @lc_flushPoints); -lua_register(luaState, _P'SetGearAIHints', @lc_setaihintsongear); +lua_register(luaState, _P'SetGearAIHints', @lc_setgearaihints); lua_register(luaState, _P'HedgewarsScriptLoad', @lc_hedgewarsscriptload); lua_register(luaState, _P'DeclareAchievement', @lc_declareachievement); +ScriptSetInteger('TEST_SUCCESSFUL' , HaltTestSuccess); +ScriptSetInteger('TEST_FAILED' , HaltTestFailed); +lua_register(luaState, _P'EndLuaTest', @lc_endluatest); ScriptClearStack; // just to be sure stack is empty ScriptLoaded:= false; @@ -2672,6 +3442,9 @@ procedure initModule; begin mapDims:= false; +PointsBuffer:= ''; +prevCursorPoint.X:= NoPointX; +prevCursorPoint.Y:= 0; end; procedure freeModule; diff -r 31570b766315 -r ed5a6478e710 hedgewars/uSinTable.pas --- a/hedgewars/uSinTable.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uSinTable.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) unit uSinTable; diff -r 31570b766315 -r ed5a6478e710 hedgewars/uSound.pas --- a/hedgewars/uSound.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uSound.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} @@ -70,7 +70,7 @@ // Returns sound channel of the looped sound. function LoopSound(snd: TSound): LongInt; function LoopSound(snd: TSound; fadems: LongInt): LongInt; -function LoopSoundV(snd: TSound; voicepack: PVoicepack): LongInt; // WTF? +function LoopSoundV(snd: TSound; voicepack: PVoicepack): LongInt; function LoopSoundV(snd: TSound; voicepack: PVoicepack; fadems: LongInt): LongInt; // Stops the normal/looped sound of the given type/in the given channel @@ -104,6 +104,8 @@ // Returns a pointer to the voicepack with the given name. function AskForVoicepack(name: shortstring): Pointer; +var MusicFN: shortstring; // music file name + SDMusicFN: shortstring; // SD music file name var Volume: LongInt; SoundTimerTicks: Longword; @@ -117,7 +119,6 @@ voicepacks: array[0..cMaxTeams] of TVoicepack; defVoicepack: PVoicepack; Mus: PMixMusic; // music pointer - MusicFN: shortstring; // music file name isMusicEnabled: boolean; isSoundEnabled: boolean; isSEBackup: boolean; @@ -260,8 +261,9 @@ var i: Longword; locName, path: shortstring; begin -i:= 0; - // First, attempt to locate a localised version of the voice + i:= 0; + + // Adjust voicepack name if there's a localised version version of the voice if cLocale <> 'en' then begin locName:= name+'_'+cLocale; @@ -278,7 +280,16 @@ end end; - // If that fails, use the unmodified one + path:= cPathz[ptVoices] + '/' + name; + + // Fallback to Default if voicepack can't be found at all + if (name <> 'Default') and (not pfsExists(path)) then + begin + path:= cPathz[ptVoices] + '/Default'; + if pfsExists(path) then + exit(AskForVoicepack('Default')); + end; + while (voicepacks[i].name <> name) and (voicepacks[i].name <> '') do begin inc(i); @@ -290,7 +301,7 @@ end; procedure InitSound; -const channels: LongInt = {$IFDEF MOBILE}1{$ELSE}2{$ENDIF}; +const channels: LongInt = 2; var success: boolean; begin if not (isSoundEnabled or isMusicEnabled) then @@ -315,7 +326,7 @@ WriteLnToConsole(msgOK); Mix_AllocateChannels(Succ(chanTPU)); - ChangeVolume(cInitVolume); + ChangeVolume(cInitVolume); end; procedure ResetSound; @@ -434,14 +445,17 @@ end; i:= 0; - while (i<8) and (VoiceList[i].snd <> sndNone) do + while (i <= High(VoiceList)) and (VoiceList[i].snd <> sndNone) do inc(i); // skip playing same sound for same hog twice if (i>0) and (VoiceList[i-1].snd = snd) and (VoiceList[i-1].voicepack = voicepack) then exit; - VoiceList[i].snd:= snd; - VoiceList[i].voicepack:= voicepack; + if(i <= High(VoiceList)) then + begin + VoiceList[i].snd:= snd; + VoiceList[i].voicepack:= voicepack; + end end; procedure PlayNextVoice; @@ -452,7 +466,7 @@ i:= 0; while (i sndNone) then begin LastVoice.snd:= VoiceList[i].snd; @@ -554,8 +568,9 @@ begin if (MusicFN = '') or (not isMusicEnabled) then exit; - - s:= '/Music/' + MusicFN; + if SuddenDeath and (SDMusicFN <> '') then + s:= '/Music/' + SDMusicFN + else s:= '/Music/' + MusicFN; WriteToConsole(msgLoading + s + ' '); Mus:= Mix_LoadMUS_RW(rwopsOpenRead(s)); @@ -712,6 +727,7 @@ RegisterVariable('mute' , @chMute , true ); MusicFN:=''; + SDMusicFN:= 'sdmusic.ogg'; Mus:= nil; isAudioMuted:= false; isSEBackup:= isSoundEnabled; diff -r 31570b766315 -r ed5a6478e710 hedgewars/uStats.pas --- a/hedgewars/uStats.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uStats.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} @@ -25,7 +25,7 @@ var TotalRounds: LongInt; FinishedTurnsTotal: LongInt; SendHealthStatsOn : boolean = true; - + procedure initModule; procedure freeModule; @@ -97,12 +97,14 @@ procedure TurnReaction; var i, t: LongInt; + s: ansistring; begin TryDo(not bBetweenTurns, 'Engine bug: TurnReaction between turns', true); inc(FinishedTurnsTotal); if FinishedTurnsTotal <> 0 then begin + s:= ansistring(CurrentHedgehog^.Name); inc(CurrentHedgehog^.stats.FinishedTurns); if (CurrentHedgehog^.stats.DamageGiven = DamageTotal) and (DamageTotal > 0) then @@ -111,8 +113,8 @@ else if CurrentHedgehog^.stats.StepDamageRecv > 0 then begin AddVoice(sndStupid, PreviousTeam^.voicepack); - if CurrentHedgehog^.stats.DamageGiven = CurrentHedgehog^.stats.StepDamageRecv then - AddCaption(Format(GetEventString(eidHurtSelf), CurrentHedgehog^.Name), cWhiteColor, capgrpMessage); + if CurrentHedgehog^.stats.DamageGiven = CurrentHedgehog^.stats.StepDamageRecv then + AddCaption(FormatA(GetEventString(eidHurtSelf), s), cWhiteColor, capgrpMessage); end else if DamageClan <> 0 then @@ -140,7 +142,7 @@ else if isTurnSkipped then begin AddVoice(sndBoring, PreviousTeam^.voicepack); - AddCaption(Format(GetEventString(eidTurnSkipped), CurrentHedgehog^.Name), cWhiteColor, capgrpMessage); + AddCaption(FormatA(GetEventString(eidTurnSkipped), s), cWhiteColor, capgrpMessage); end else if not PlacingHogs then AddVoice(sndCoward, PreviousTeam^.voicepack); @@ -164,7 +166,7 @@ StepDamageRecv:= 0; StepDamageGiven:= 0 end; - + if SendHealthStatsOn then for t:= 0 to Pred(ClansCount) do with ClansArray[t]^ do @@ -298,7 +300,7 @@ SendStat(siKilledHHs, IntToStr(KilledHHs)); // now to console - if winnersClan <> nil then + if winnersClan <> nil then begin WriteLnToConsole('WINNERS'); WriteLnToConsole(inttostr(winnersClan^.TeamsNumber)); @@ -307,12 +309,12 @@ end else WriteLnToConsole('DRAW'); - + ScriptCall('onAchievementsDeclaration'); end; procedure declareAchievement(id, teamname, location: shortstring; value: LongInt); -begin +begin if (length(id) = 0) or (length(teamname) = 0) or (length(location) = 0) then exit; WriteLnToConsole('ACHIEVEMENT'); WriteLnToConsole(id); diff -r 31570b766315 -r ed5a6478e710 hedgewars/uStore.pas --- a/hedgewars/uStore.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uStore.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} @@ -21,7 +21,7 @@ unit uStore; interface -uses StrUtils, SysUtils, uConsts, SDLh, GLunit, uTypes, uLandTexture, uCaptions, uChat; +uses SysUtils, uConsts, SDLh, GLunit, uTypes, uLandTexture, uCaptions, uChat; procedure initModule; procedure freeModule; @@ -42,12 +42,14 @@ function LoadDataImageAltFile(const path: TPathType; const filename, altFile: shortstring; imageFlags: LongInt): PSDL_Surface; procedure LoadHedgehogHat(var HH: THedgehog; newHat: shortstring); +procedure LoadHedgehogHat2(var HH: THedgehog; newHat: shortstring; allowSurfReuse: boolean); + +procedure InitZoom(zoom: real); + procedure SetupOpenGL; -procedure SetScale(f: GLfloat); function RenderHelpWindow(caption, subcaption, description, extra: ansistring; extracolor: LongInt; iconsurf: PSDL_Surface; iconrect: PSDL_Rect): PTexture; procedure RenderWeaponTooltip(atype: TAmmoType); procedure ShowWeaponTooltip(x, y: LongInt); -procedure FreeWeaponTooltip; procedure MakeCrossHairs; {$IFDEF USE_VIDEO_RECORDING} procedure InitOffscreenOpenGL; @@ -58,32 +60,50 @@ procedure SetSkyColor(r, g, b: real); implementation -uses uMisc, uConsole, uVariables, uUtils, uTextures, uRender, uRenderUtils, uCommands - , uPhysFSLayer - , uDebug +uses uMisc, uConsole, uVariables, uUtils, uTextures, uRender, uRenderUtils, + uCommands, uPhysFSLayer, uDebug {$IFDEF USE_CONTEXT_RESTORE}, uWorld{$ENDIF}; //type TGPUVendor = (gvUnknown, gvNVIDIA, gvATI, gvIntel, gvApple); -var MaxTextureSize: LongInt; +var SDLwindow: PSDL_Window; SDLGLcontext: PSDL_GLContext; squaresize : LongInt; numsquares : LongInt; ProgrTex: PTexture; + prevHat: shortstring; + tmpHatSurf: PSDL_Surface; + const cHHFileName = 'Hedgehog'; cCHFileName = 'Crosshair'; -function WriteInRect(Surface: PSDL_Surface; X, Y: LongInt; Color: LongWord; Font: THWFont; s: ansistring): TSDL_Rect; +procedure freeTmpHatSurf(); +begin + if tmpHatSurf = nil then exit; + SDL_FreeSurface(tmpHatSurf); + tmpHatSurf:= nil; + prevHat:= 'NoHat'; +end; + +procedure InitZoom(zoom: real); +begin + SetScale(zoom); + // make sure view limits are updated + // because SetScale() doesn't do it, if zoom=cScaleFactor + updateViewLimits(); +end; + +function WriteInRect(Surface: PSDL_Surface; X, Y: LongInt; Color: LongWord; Font: THWFont; s: PChar): TSDL_Rect; var w, h: LongInt; tmpsurf: PSDL_Surface; clr: TSDL_Color; finalRect: TSDL_Rect; begin w:= 0; h:= 0; // avoid compiler hints -TTF_SizeUTF8(Fontz[Font].Handle, Str2PChar(s), @w, @h); +TTF_SizeUTF8(Fontz[Font].Handle, s, @w, @h); finalRect.x:= X + cFontBorder + 2; finalRect.y:= Y + cFontBorder; finalRect.w:= w + cFontBorder * 2 + 4; @@ -91,7 +111,8 @@ clr.r:= Color shr 16; clr.g:= (Color shr 8) and $FF; clr.b:= Color and $FF; -tmpsurf:= TTF_RenderUTF8_Blended(Fontz[Font].Handle, Str2PChar(s), clr); +tmpsurf:= TTF_RenderUTF8_Blended(Fontz[Font].Handle, s, clr); +SDLTry(tmpsurf <> nil, 'TTF_RenderUTF8_Blended', true); tmpsurf:= doSurfaceConversion(tmpsurf); SDLTry(tmpsurf <> nil, 'TTF_RenderUTF8_Blended, doSurfaceConversion', true); SDL_UpperBlit(tmpsurf, nil, Surface, @finalRect); @@ -148,17 +169,23 @@ foundBot: boolean; year, month, md : word; begin - if cOnlyStats then exit; +if cOnlyStats then exit; r.x:= 0; r.y:= 0; drY:= - 4; +{$IFNDEF PAS2C} DecodeDate(Date, year, month, md); +{$ELSE} +year:= 0; +month:= 0; +md:= 0; +{$ENDIF} for t:= 0 to Pred(TeamsCount) do with TeamsArray[t]^ do begin - NameTagTex:= RenderStringTexLim(TeamName, Clan^.Color, Font, cTeamHealthWidth); + NameTagTex:= RenderStringTexLim(ansistring(TeamName), Clan^.Color, Font, cTeamHealthWidth); if length(Owner) > 0 then - OwnerTex:= RenderStringTexLim(Owner, Clan^.Color, Font, cTeamHealthWidth); + OwnerTex:= RenderStringTexLim(ansistring(Owner), Clan^.Color, Font, cTeamHealthWidth); r.x:= 0; r.y:= 0; @@ -224,7 +251,7 @@ SDL_FreeSurface(texsurf); texsurf:= nil; - AIKillsTex := RenderStringTex(inttostr(stats.AIKills), Clan^.Color, fnt16); + AIKillsTex := RenderStringTex(ansistring(inttostr(stats.AIKills)), Clan^.Color, fnt16); dec(drY, r.h + 2); DrawHealthY:= drY; @@ -232,26 +259,34 @@ with Hedgehogs[i] do if Gear <> nil then begin - NameTagTex:= RenderStringTexLim(Name, Clan^.Color, fnt16, cTeamHealthWidth); + NameTagTex:= RenderStringTexLim(ansistring(Name), Clan^.Color, fnt16, cTeamHealthWidth); if Hat = 'NoHat' then begin - if ((month = 4) and (md = 20)) then - Hat := 'eastertop'; // Easter - if ((month = 12) and (md = 25)) then - Hat := 'Santa'; // Christmas - if ((month = 10) and (md = 31)) then + if (month = 4) and (md = 20) then + Hat := 'eastertop' // Easter + else if (month = 12) and ((md = 24) or (md = 25) or (md = 26)) then + Hat := 'Santa' // Christmas Eve/Christmas/Boxing Day + else if (month = 10) and (md = 31) then Hat := 'fr_pumpkin'; // Halloween/Hedgewars' birthday end; - + if (month = 4) and (md = 1) then + begin + AprilOne:= true; + Hat := 'fr_tomato'; // avoid promoting violence to hedgehogs. see http://hedgewars.org/node/5818 + end; + if Hat <> 'NoHat' then begin if (Length(Hat) > 39) and (Copy(Hat,1,8) = 'Reserved') and (Copy(Hat,9,32) = PlayerHash) then - LoadHedgehogHat(Hedgehogs[i], 'Reserved/' + Copy(Hat,9,Length(Hat)-8)) + LoadHedgehogHat2(Hedgehogs[i], 'Reserved/' + Copy(Hat,9,Length(Hat)-8), true) else - LoadHedgehogHat(Hedgehogs[i], Hat); + LoadHedgehogHat2(Hedgehogs[i], Hat, true); end end; end; + + freeTmpHatSurf(); + MissionIcons:= LoadDataImage(ptGraphics, 'missions', ifCritical); iconsurf:= SDL_CreateRGBSurface(SDL_SWSURFACE, 28, 28, 32, RMask, GMask, BMask, AMask); if iconsurf <> nil then @@ -314,7 +349,7 @@ begin AddFileLog('StoreLoad()'); -if not reload then +if (not reload) and (not cOnlyStats) then for fi:= Low(THWFont) to High(THWFont) do with Fontz[fi] do begin @@ -326,8 +361,19 @@ WriteLnToConsole(msgOK) end; -MakeCrossHairs; -LoadGraves; +if not cOnlyStats then + begin + MakeCrossHairs; + LoadGraves; +{$IFDEF IPHONEOS} + tmpHatSurf:= LoadDataImage(ptHats, 'chef', ifNone); +{$ELSE} + tmpHatSurf:= LoadDataImage(ptHats, 'Reserved/chef', ifNone); +{$ENDIF} + ChefHatTexture:= Surface2Tex(tmpHatSurf, true); + freeTmpHatSurf(); + end; + if not reload then AddProgress; @@ -335,11 +381,13 @@ with SpritesData[ii] do // FIXME - add a sprite attribute to match on rq flags? if (((cReducedQuality and (rqNoBackground or rqLowRes)) = 0) or // why rqLowRes? - (not (ii in [sprSky, sprSkyL, sprSkyR, sprHorizont, sprHorizontL, sprHorizontR]))) and - (((cReducedQuality and rqPlainSplash) = 0) or ((not (ii in [sprSplash, sprDroplet, sprSDSplash, sprSDDroplet])))) and - (((cReducedQuality and rqKillFlakes) = 0) or cSnow or ((not (ii in [sprFlake, sprSDFlake])))) and - ((cCloudsNumber > 0) or (ii <> sprCloud)) and - ((vobCount > 0) or (ii <> sprFlake)) then + (not (ii in [sprSky, sprSkyL, sprSkyR, sprHorizont, sprHorizontL, sprHorizontR]))) + and (((cReducedQuality and rqPlainSplash) = 0) or ((not (ii in [sprSplash, sprDroplet, sprSDSplash, sprSDDroplet])))) + and (((cReducedQuality and rqKillFlakes) = 0) or cSnow or ((not (ii in [sprFlake, sprSDFlake])))) + and ((cCloudsNumber > 0) or (ii <> sprCloud)) + and ((vobCount > 0) or (ii <> sprFlake)) + and (savesurf or (not cOnlyStats)) // in stats-only only load those which are needed later + then begin if reload then tmpsurf:= Surface @@ -397,79 +445,58 @@ Surface:= nil end; -WriteNames(fnt16); +if not cOnlyStats then + begin + WriteNames(fnt16); -if not reload then - AddProgress; + if not reload then + AddProgress; + + tmpsurf:= LoadDataImage(ptGraphics, cHHFileName, ifAlpha or ifCritical or ifTransparent); -tmpsurf:= LoadDataImage(ptGraphics, cHHFileName, ifAlpha or ifCritical or ifTransparent); + HHTexture:= Surface2Tex(tmpsurf, false); + SDL_FreeSurface(tmpsurf); + + InitHealth; -HHTexture:= Surface2Tex(tmpsurf, false); -SDL_FreeSurface(tmpsurf); - -InitHealth; + PauseTexture:= RenderStringTex(trmsg[sidPaused], cYellowColor, fntBig); + AFKTexture:= RenderStringTex(trmsg[sidAFK], cYellowColor, fntBig); + ConfirmTexture:= RenderStringTex(trmsg[sidConfirm], cYellowColor, fntBig); + SyncTexture:= RenderStringTex(trmsg[sidSync], cYellowColor, fntBig); -PauseTexture:= RenderStringTex(trmsg[sidPaused], cYellowColor, fntBig); -AFKTexture:= RenderStringTex(trmsg[sidAFK], cYellowColor, fntBig); -ConfirmTexture:= RenderStringTex(trmsg[sidConfirm], cYellowColor, fntBig); -SyncTexture:= RenderStringTex(trmsg[sidSync], cYellowColor, fntBig); - -if not reload then - AddProgress; + if not reload then + AddProgress; -// name of weapons in ammo menu -for ai:= Low(TAmmoType) to High(TAmmoType) do - with Ammoz[ai] do + // name of weapons in ammo menu + for ai:= Low(TAmmoType) to High(TAmmoType) do + with Ammoz[ai] do + begin + TryDo(length(trAmmo[NameId]) > 0,'No default text/translation found for ammo type #' + intToStr(ord(ai)) + '!',true); + tmpsurf:= TTF_RenderUTF8_Blended(Fontz[CheckCJKFont(trAmmo[NameId],fnt16)].Handle, PChar(trAmmo[NameId]), cWhiteColorChannels); + TryDo(tmpsurf <> nil,'Name-texture creation for ammo type #' + intToStr(ord(ai)) + ' failed!',true); + tmpsurf:= doSurfaceConversion(tmpsurf); + FreeAndNilTexture(NameTex); + NameTex:= Surface2Tex(tmpsurf, false); + SDL_FreeSurface(tmpsurf) + end; + + // number of weapons in ammo menu + for i:= Low(CountTexz) to High(CountTexz) do begin - TryDo(trAmmo[NameId] <> '','No default text/translation found for ammo type #' + intToStr(ord(ai)) + '!',true); - tmpsurf:= TTF_RenderUTF8_Blended(Fontz[CheckCJKFont(trAmmo[NameId],fnt16)].Handle, Str2PChar(trAmmo[NameId]), cWhiteColorChannels); - TryDo(tmpsurf <> nil,'Name-texture creation for ammo type #' + intToStr(ord(ai)) + ' failed!',true); + tmpsurf:= TTF_RenderUTF8_Blended(Fontz[fnt16].Handle, Str2PChar(IntToStr(i) + 'x'), cWhiteColorChannels); tmpsurf:= doSurfaceConversion(tmpsurf); - FreeTexture(NameTex); - NameTex:= Surface2Tex(tmpsurf, false); + FreeAndNilTexture(CountTexz[i]); + CountTexz[i]:= Surface2Tex(tmpsurf, false); SDL_FreeSurface(tmpsurf) end; -// number of weapons in ammo menu -for i:= Low(CountTexz) to High(CountTexz) do - begin - tmpsurf:= TTF_RenderUTF8_Blended(Fontz[fnt16].Handle, Str2PChar(IntToStr(i) + 'x'), cWhiteColorChannels); - tmpsurf:= doSurfaceConversion(tmpsurf); - FreeTexture(CountTexz[i]); - CountTexz[i]:= Surface2Tex(tmpsurf, false); - SDL_FreeSurface(tmpsurf) + if not reload then + AddProgress; end; -if not reload then - AddProgress; IMG_Quit(); end; -{$IF DEFINED(USE_S3D_RENDERING) OR DEFINED(USE_VIDEO_RECORDING)} -procedure CreateFramebuffer(var frame, depth, tex: GLuint); -begin - glGenFramebuffersEXT(1, @frame); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, frame); - glGenRenderbuffersEXT(1, @depth); - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depth); - glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, cScreenWidth, cScreenHeight); - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depth); - glGenTextures(1, @tex); - glBindTexture(GL_TEXTURE_2D, tex); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, cScreenWidth, cScreenHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nil); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, tex, 0); -end; - -procedure DeleteFramebuffer(var frame, depth, tex: GLuint); -begin - glDeleteTextures(1, @tex); - glDeleteRenderbuffersEXT(1, @depth); - glDeleteFramebuffersEXT(1, @frame); -end; -{$ENDIF} - procedure StoreRelease(reload: boolean); var ii: TSprite; ai: TAmmoType; @@ -488,6 +515,7 @@ SDL_FreeSurface(MissionIcons); // free the textures declared in uVariables +FreeAndNilTexture(ChefHatTexture); FreeAndNilTexture(CrosshairTexture); FreeAndNilTexture(WeaponTooltipTex); FreeAndNilTexture(PauseTexture); @@ -532,17 +560,8 @@ end; end; end; -{$IFDEF USE_VIDEO_RECORDING} - if defaultFrame <> 0 then - DeleteFramebuffer(defaultFrame, depthv, texv); -{$ENDIF} -{$IFDEF USE_S3D_RENDERING} - if (cStereoMode = smHorizontal) or (cStereoMode = smVertical) then - begin - DeleteFramebuffer(framel, depthl, texl); - DeleteFramebuffer(framer, depthr, texr); - end -{$ENDIF} + +RendererCleanup(); end; @@ -550,23 +569,47 @@ var s: shortstring; begin str(Hedgehog.Gear^.Health, s); -FreeTexture(Hedgehog.HealthTagTex); -Hedgehog.HealthTagTex:= RenderStringTex(s, Hedgehog.Team^.Clan^.Color, fnt16) +FreeAndNilTexture(Hedgehog.HealthTagTex); +Hedgehog.HealthTagTex:= RenderStringTex(ansistring(s), Hedgehog.Team^.Clan^.Color, fnt16) end; function LoadImage(const filename: shortstring; imageFlags: LongInt): PSDL_Surface; var tmpsurf: PSDL_Surface; s: shortstring; + rwops: PSDL_RWops; begin LoadImage:= nil; WriteToConsole(msgLoading + filename + '.png [flags: ' + inttostr(imageFlags) + '] '); s:= filename + '.png'; - tmpsurf:= IMG_Load_RW(rwopsOpenRead(s), true); + + rwops:= nil; + tmpsurf:= nil; + if pfsExists(s) then + begin + // get data source + rwops:= rwopsOpenRead(s); + + // load image with SDL (with freesrc param set to true) + if rwops <> nil then + tmpsurf:= IMG_Load_RW(rwops, true); + end; + + // loading failed if tmpsurf = nil then begin - OutError(msgFailed, (imageFlags and ifCritical) <> 0); + // output sdl error if loading failed when data source was available + if rwops <> nil then + begin + // anounce that loading failed + OutError(msgFailed, false); + + SDLTry(false, 'LoadImage', (imageFlags and ifCritical) <> 0); + // rwops was already freed by IMG_Load_RW + rwops:= nil; + end else + OutError(msgFailed, (imageFlags and ifCritical) <> 0); exit; end; @@ -635,43 +678,39 @@ end; procedure LoadHedgehogHat(var HH: THedgehog; newHat: shortstring); -var texsurf: PSDL_Surface; +begin + LoadHedgehogHat2(HH, newHat, false); +end; + +procedure LoadHedgehogHat2(var HH: THedgehog; newHat: shortstring; allowSurfReuse: boolean); begin // free the mem of any previously assigned texture. This was previously only if the new one could be loaded, but, NoHat is usually a better choice if HH.HatTex <> nil then + FreeAndNilTexture(HH.HatTex); + + // load new hat surface if this hat is different than the one already loaded + if newHat <> prevHat then begin - FreeTexture(HH.HatTex); - HH.HatTex:= nil + freeTmpHatSurf(); + tmpHatSurf:= LoadDataImage(ptHats, newHat, ifNone); end; - texsurf:= LoadDataImage(ptHats, newHat, ifNone); + AddFileLog('Hat => '+newHat); // only do something if the hat could be loaded - if texsurf <> nil then + if tmpHatSurf <> nil then begin AddFileLog('Got Hat'); // assign new hat to hedgehog - HH.HatTex:= Surface2Tex(texsurf, true); - - // cleanup: free temporary surface mem - SDL_FreeSurface(texsurf) - end; -end; + HH.HatTex:= Surface2Tex(tmpHatSurf, true); -function glLoadExtension(extension : shortstring) : boolean; -begin -{$IF GLunit = gles11} - // FreePascal doesnt come with OpenGL ES 1.1 Extension headers - extension:= extension; // avoid hint - glLoadExtension:= false; - AddFileLog('OpenGL - "' + extension + '" skipped') -{$ELSE} - glLoadExtension:= glext_LoadExtension(extension); - if glLoadExtension then - AddFileLog('OpenGL - "' + extension + '" loaded') - else - AddFileLog('OpenGL - "' + extension + '" failed to load'); -{$ENDIF} + // remember that this hat was used last + if allowSurfReuse then + prevHat:= newHat + // cleanup: free temporary surface mem + else + freeTmpHatSurf(); + end; end; procedure SetupOpenGLAttributes; @@ -679,6 +718,9 @@ {$IFDEF IPHONEOS} SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 0); SDL_GL_SetAttribute(SDL_GL_RETAINED_BACKING, 1); + + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); {$ELSE} SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); {$ENDIF} @@ -693,15 +735,9 @@ procedure SetupOpenGL; var buf: array[byte] of char; - AuxBufNum: LongInt = 0; - tmpstr: AnsiString; - tmpint: LongInt; - tmpn: LongInt; begin AddFileLog('Setting up OpenGL (using driver: ' + shortstring(SDL_GetCurrentVideoDriver()) + ')'); - AuxBufNum:= AuxBufNum; - // TODO: this function creates an opengles1.1 context // un-comment below and add proper logic to support opengles2.0 //SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); @@ -711,130 +747,9 @@ SDLTry(SDLGLcontext <> nil, 'SDLGLcontext', true); SDLTry(SDL_GL_SetSwapInterval(1) = 0, 'SDL_GL_SetSwapInterval', true); - // get the max (h and v) size for textures that the gpu can support - glGetIntegerv(GL_MAX_TEXTURE_SIZE, @MaxTextureSize); - if MaxTextureSize <= 0 then - begin - MaxTextureSize:= 1024; - AddFileLog('OpenGL Warning - driver didn''t provide any valid max texture size; assuming 1024'); - end - else if (MaxTextureSize < 1024) and (MaxTextureSize >= 512) then - begin - cReducedQuality := cReducedQuality or rqNoBackground; - AddFileLog('Texture size too small for backgrounds, disabling.'); - end; - - // everyone loves debugging - AddFileLog('OpenGL-- Renderer: ' + shortstring(pchar(glGetString(GL_RENDERER)))); - AddFileLog(' |----- Vendor: ' + shortstring(pchar(glGetString(GL_VENDOR)))); - AddFileLog(' |----- Version: ' + shortstring(pchar(glGetString(GL_VERSION)))); - AddFileLog(' |----- Texture Size: ' + inttostr(MaxTextureSize)); -{$IFDEF USE_VIDEO_RECORDING} - glGetIntegerv(GL_AUX_BUFFERS, @AuxBufNum); - AddFileLog(' |----- Number of auxiliary buffers: ' + inttostr(AuxBufNum)); -{$ENDIF} - AddFileLog(' \----- Extensions: '); - - // fetch extentions and store them in string - tmpstr := StrPas(PChar(glGetString(GL_EXTENSIONS))); - tmpn := WordCount(tmpstr, [' ']); - tmpint := 1; - - repeat - begin - // print up to 3 extentions per row - // ExtractWord will return empty string if index out of range - AddFileLog(TrimRight( - ExtractWord(tmpint, tmpstr, [' ']) + ' ' + - ExtractWord(tmpint+1, tmpstr, [' ']) + ' ' + - ExtractWord(tmpint+2, tmpstr, [' ']) - )); - tmpint := tmpint + 3; - end; - until (tmpint > tmpn); - AddFileLog(''); + RendererSetup(); - defaultFrame:= 0; -{$IFDEF USE_VIDEO_RECORDING} - if GameType = gmtRecord then - begin - if glLoadExtension('GL_EXT_framebuffer_object') then - begin - CreateFramebuffer(defaultFrame, depthv, texv); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, defaultFrame); - AddFileLog('Using framebuffer for video recording.'); - end - else if AuxBufNum > 0 then - begin - glDrawBuffer(GL_AUX0); - glReadBuffer(GL_AUX0); - AddFileLog('Using auxiliary buffer for video recording.'); - end - else - begin - glDrawBuffer(GL_BACK); - glReadBuffer(GL_BACK); - AddFileLog('Warning: off-screen rendering is not supported; using back buffer but it may not work.'); - end; - end; -{$ENDIF} - -{$IFDEF USE_S3D_RENDERING} - if (cStereoMode = smHorizontal) or (cStereoMode = smVertical) then - begin - // prepare left and right frame buffers and associated textures - if glLoadExtension('GL_EXT_framebuffer_object') then - begin - CreateFramebuffer(framel, depthl, texl); - CreateFramebuffer(framer, depthr, texr); - - // reset - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, defaultFrame) - end - else - cStereoMode:= smNone; - end; -{$ENDIF} - - // set view port to whole window - glViewport(0, 0, cScreenWidth, cScreenHeight); - - glMatrixMode(GL_MODELVIEW); - // prepare default translation/scaling - glLoadIdentity(); - glScalef(2.0 / cScreenWidth, -2.0 / cScreenHeight, 1.0); - glTranslatef(0, -cScreenHeight / 2, 0); - - // enable alpha blending - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - // disable/lower perspective correction (will not need it anyway) - glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); - // disable dithering - glDisable(GL_DITHER); - // enable common states by default as they save a lot - glEnable(GL_TEXTURE_2D); - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); -end; - -procedure SetScale(f: GLfloat); -begin -// leave immediately if scale factor did not change - if f = cScaleFactor then - exit; - - if f = cDefaultZoomLevel then - glPopMatrix // return to default scaling - else // other scaling - begin - glPushMatrix; // save default scaling - glLoadIdentity; - glScalef(f / cScreenWidth, -f / cScreenHeight, 1.0); - glTranslatef(0, -cScreenHeight / 2, 0); - end; - - cScaleFactor:= f; +// gl2 init/matrix code was here, but removed end; //////////////////////////////////////////////////////////////////////////////// @@ -853,15 +768,16 @@ squaresize:= texsurf^.w shr 1; numsquares:= texsurf^.h div squaresize; SDL_FreeSurface(texsurf); + {$IFNDEF PAS2C} with mobileRecord do if GameLoading <> nil then GameLoading(); - + {$ENDIF} end; TryDo(ProgrTex <> nil, 'Error - Progress Texure is nil!', true); - glClear(GL_COLOR_BUFFER_BIT); + RenderClear(); if Step < numsquares then r.x:= 0 else @@ -874,17 +790,19 @@ DrawTextureFromRect( -squaresize div 2, (cScreenHeight - squaresize) shr 1, @r, ProgrTex); SwapBuffers; + inc(Step); end; procedure FinishProgress; begin + {$IFNDEF PAS2C} with mobileRecord do if GameLoaded <> nil then GameLoaded(); + {$ENDIF} WriteLnToConsole('Freeing progress surface... '); - FreeTexture(ProgrTex); - ProgrTex:= nil; + FreeAndNilTexture(ProgrTex); Step:= 0 end; @@ -897,10 +815,10 @@ tmpline, tmpline2, tmpdesc: ansistring; begin // make sure there is a caption as well as a sub caption - description is optional -if caption = '' then - caption:= '???'; -if subcaption = '' then - subcaption:= _S' '; +if length(caption) = 0 then + caption:= ansistring('???'); +if length(subcaption) = 0 then + subcaption:= ansistring(_S' '); font:= CheckCJKFont(caption,fnt16); font:= CheckCJKFont(subcaption,font); @@ -917,13 +835,13 @@ // TODO: Recheck height/position calculation // get caption's dimensions -TTF_SizeUTF8(Fontz[font].Handle, Str2PChar(caption), @i, @j); +TTF_SizeUTF8(Fontz[font].Handle, PChar(caption), @i, @j); // width adds 36 px (image + space) w:= i + 36 + wa; h:= j + ha; // get sub caption's dimensions -TTF_SizeUTF8(Fontz[font].Handle, Str2PChar(subcaption), @i, @j); +TTF_SizeUTF8(Fontz[font].Handle, PChar(subcaption), @i, @j); // width adds 36 px (image + space) if w < (i + 36 + wa) then w:= i + 36 + wa; @@ -931,23 +849,23 @@ // get description's dimensions tmpdesc:= description; -while tmpdesc <> '' do +while length(tmpdesc) > 0 do begin tmpline:= tmpdesc; - SplitByChar(tmpline, tmpdesc, '|'); - if tmpline <> '' then + SplitByCharA(tmpline, tmpdesc, '|'); + if length(tmpline) > 0 then begin - TTF_SizeUTF8(Fontz[font].Handle, Str2PChar(tmpline), @i, @j); + TTF_SizeUTF8(Fontz[font].Handle, PChar(tmpline), @i, @j); if w < (i + wa) then w:= i + wa; inc(h, j + ha) end end; -if extra <> '' then +if length(extra) > 0 then begin // get extra label's dimensions - TTF_SizeUTF8(Fontz[font].Handle, Str2PChar(extra), @i, @j); + TTF_SizeUTF8(Fontz[font].Handle, PChar(extra), @i, @j); if w < (i + wa) then w:= i + wa; inc(h, j + ha); @@ -968,31 +886,34 @@ DrawRoundRect(@r, cWhiteColor, cNearBlackColor, tmpsurf, true); // render caption -r:= WriteInRect(tmpsurf, 36 + cFontBorder + 2, ha, $ffffffff, font, caption); +r:= WriteInRect(tmpsurf, 36 + cFontBorder + 2, ha, $ffffffff, font, PChar(caption)); // render sub caption -r:= WriteInRect(tmpsurf, 36 + cFontBorder + 2, r.y + r.h, $ffc7c7c7, font, subcaption); +r:= WriteInRect(tmpsurf, 36 + cFontBorder + 2, r.y + r.h, $ffc7c7c7, font, PChar(subcaption)); // render all description lines tmpdesc:= description; -while tmpdesc <> '' do +while length(tmpdesc) > 0 do begin tmpline:= tmpdesc; - SplitByChar(tmpline, tmpdesc, '|'); + SplitByCharA(tmpline, tmpdesc, '|'); r2:= r; - if tmpline <> '' then + if length(tmpline) > 0 then begin - r:= WriteInRect(tmpsurf, cFontBorder + 2, r.y + r.h, $ff707070, font, tmpline); + r:= WriteInRect(tmpsurf, cFontBorder + 2, r.y + r.h, $ff707070, font, PChar(tmpline)); // render highlighted caption (if there is a ':') tmpline2:= _S''; - SplitByChar(tmpline, tmpline2, ':'); - if tmpline2 <> _S'' then - WriteInRect(tmpsurf, cFontBorder + 2, r2.y + r2.h, $ffc7c7c7, font, tmpline + ':'); + SplitByCharA(tmpline, tmpline2, ':'); + if length(tmpline2) > 0 then + begin + tmpline:= tmpline + ':'; + WriteInRect(tmpsurf, cFontBorder + 2, r2.y + r2.h, $ffc7c7c7, font, PChar(tmpline)); + end; end end; -if extra <> '' then - r:= WriteInRect(tmpsurf, cFontBorder + 2, r.y + r.h, extracolor, font, extra); +if length(extra) > 0 then + r:= WriteInRect(tmpsurf, cFontBorder + 2, r.y + r.h, extracolor, font, PChar(extra)); r.x:= cFontBorder + 6; r.y:= cFontBorder + 4; @@ -1019,7 +940,7 @@ end; // free old texture -FreeWeaponTooltip; +FreeAndNilTexture(WeaponTooltipTex); // image region i:= LongInt(atype) - 1; @@ -1059,13 +980,6 @@ DrawTexture(x, y, WeaponTooltipTex) end; -procedure FreeWeaponTooltip; -begin -// free the existing texture (if there is any) -FreeTexture(WeaponTooltipTex); -WeaponTooltipTex:= nil -end; - {$IFDEF USE_VIDEO_RECORDING} procedure InitOffscreenOpenGL; begin @@ -1171,10 +1085,11 @@ SDLTry(SDLwindow <> nil, 'SDL_CreateWindow', true); SetupOpenGL(); + if reinit then begin // clean the window from any previous content - glClear(GL_COLOR_BUFFER_BIT); + RenderClear(); if SuddenDeathDmg then SetSkyColor(SDSkyColor.r * (SDTint/255) / 255, SDSkyColor.g * (SDTint/255) / 255, SDSkyColor.b * (SDTint/255) / 255) else if ((cReducedQuality and rqNoBackground) = 0) then @@ -1209,7 +1124,7 @@ procedure SetSkyColor(r, g, b: real); begin - glClearColor(r, g, b, 0.99) + RenderSetClearColor(r, g, b, 0.99) end; procedure initModule; @@ -1219,6 +1134,7 @@ RegisterVariable('fullscr', @chFullScr, true); cScaleFactor:= 2.0; + updateViewLimits(); Step:= 0; ProgrTex:= nil; SupportNPOTT:= false; @@ -1233,11 +1149,26 @@ CountTexz[i] := nil; SDLwindow:= nil; SDLGLcontext:= nil; + + prevHat:= 'NoHat'; + tmpHatSurf:= nil; end; procedure freeModule; +var fi: THWFont; begin StoreRelease(false); + // make sure fonts are cleaned up + for fi:= Low(THWFont) to High(THWFont) do + with Fontz[fi] do + begin + if Handle <> nil then + begin + TTF_CloseFont(Handle); + Handle:= nil; + end; + end; + TTF_Quit(); SDL_GL_DeleteContext(SDLGLcontext); SDL_DestroyWindow(SDLwindow); diff -r 31570b766315 -r ed5a6478e710 hedgewars/uTeams.pas --- a/hedgewars/uTeams.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uTeams.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,14 +13,14 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} unit uTeams; interface -uses uConsts, uInputHandler, uRandom, uFloat, uStats, +uses uConsts, uInputHandler, uRandom, uFloat, uStats, uCollisions, uSound, uStore, uTypes, uScript {$IFDEF USE_TOUCH_INTERFACE}, uWorld{$ENDIF}; @@ -34,6 +34,7 @@ procedure InitTeams; function TeamSize(p: PTeam): Longword; procedure RecountTeamHealth(team: PTeam); +procedure RecountAllTeamsHealth(); procedure RestoreHog(HH: PHedgehog); procedure RestoreTeamsFromSave; @@ -53,7 +54,7 @@ function CheckForWin: boolean; var AliveClan: PClan; - s: shortstring; + s, ts: ansistring; t, AliveCount, i, j: LongInt; begin CheckForWin:= false; @@ -81,16 +82,17 @@ if AliveCount = 0 then begin // draw AddCaption(trmsg[sidDraw], cWhiteColor, capgrpGameState); - SendStat(siGameResult, trmsg[sidDraw]); + SendStat(siGameResult, shortstring(trmsg[sidDraw])); AddGear(0, 0, gtATFinishGame, 0, _0, _0, 3000) end else // win with AliveClan^ do begin + ts:= ansistring(Teams[0]^.TeamName); if TeamsNumber = 1 then - s:= Format(shortstring(trmsg[sidWinner]), Teams[0]^.TeamName) // team wins + s:= FormatA(trmsg[sidWinner], ts) // team wins else - s:= Format(shortstring(trmsg[sidWinner]), Teams[0]^.TeamName); // clan wins + s:= FormatA(trmsg[sidWinner], ts); // clan wins for j:= 0 to Pred(TeamsNumber) do with Teams[j]^ do @@ -104,7 +106,7 @@ AddVoice(sndVictory, Teams[0]^.voicepack); AddCaption(s, cWhiteColor, capgrpGameState); - SendStat(siGameResult, s); + SendStat(siGameResult, shortstring(s)); AddGear(0, 0, gtATFinishGame, 0, _0, _0, 3000) end; SendStats; @@ -155,7 +157,7 @@ if c > cMaxHHIndex then c:= 0 end - until (c = CurrHedgehog) or (Hedgehogs[c].Gear <> nil); + until (c = CurrHedgehog) or (Hedgehogs[c].Gear <> nil) and (Hedgehogs[c].Effects[heFrozen] < 50255); LocalAmmo:= Hedgehogs[c].AmmoStore end; @@ -237,7 +239,7 @@ CurWeapon: PAmmo; w: real; vg: PVisualGear; - + s: ansistring; begin if PlacingHogs then begin @@ -334,7 +336,8 @@ end; if cHedgehogTurnTime < 1000000 then ReadyTimeLeft:= cReadyDelay; - AddCaption(Format(shortstring(trmsg[sidReady]), CurrentTeam^.TeamName), cWhiteColor, capgrpGameState) + s:= ansistring(CurrentTeam^.TeamName); + AddCaption(FormatA(trmsg[sidReady], s), cWhiteColor, capgrpGameState) end else begin @@ -514,20 +517,31 @@ procedure TeamGoneEffect(var Team: TTeam); var i: LongInt; begin -with Team do - for i:= 0 to cMaxHHIndex do - with Hedgehogs[i] do + with Team do + if skippedTurns < 3 then begin - if Hedgehogs[i].GearHidden <> nil then - RestoreHog(@Hedgehogs[i]); + inc(skippedTurns); + for i:= 0 to cMaxHHIndex do + with Hedgehogs[i] do + if Gear <> nil then + Gear^.State:= Gear^.State and (not gstHHDriven); - if Gear <> nil then - begin - Gear^.Hedgehog^.Effects[heInvulnerable]:= 0; - Gear^.Damage:= Gear^.Health; - Gear^.State:= (Gear^.State or gstHHGone) and (not gstHHDriven) - end + ParseCommand('/skip', true); end + else + for i:= 0 to cMaxHHIndex do + with Hedgehogs[i] do + begin + if Hedgehogs[i].GearHidden <> nil then + RestoreHog(@Hedgehogs[i]); + + if Gear <> nil then + begin + Gear^.Hedgehog^.Effects[heInvulnerable]:= 0; + Gear^.Damage:= Gear^.Health; + Gear^.State:= (Gear^.State or gstHHGone) and (not gstHHDriven) + end + end end; procedure chAddHH(var id: shortstring); @@ -535,10 +549,12 @@ Gear: PGear; begin s:= ''; -if (not isDeveloperMode) or (CurrentTeam = nil) then +if (not isDeveloperMode) then exit; +TryDo((CurrentTeam <> nil), 'Can''t add hedgehogs yet, add a team first!', true); with CurrentTeam^ do begin + TryDo(HedgehogsNumber<=cMaxHHIndex, 'Can''t add hedgehog to "' + TeamName + '"! (already ' + intToStr(HedgehogsNumber) + ' hogs)', true); SplitBySpace(id, s); SwitchCurrentHedgehog(@Hedgehogs[HedgehogsNumber]); CurrentHedgehog^.BotLevel:= StrToInt(id); @@ -567,7 +583,10 @@ var i: LongInt; begin for i:= 1 to length(s) do - if s[i] in ['\', '/', ':'] then s[i]:= '_'; + if ((s[i] = '\') or + (s[i] = '/') or + (s[i] = ':')) then + s[i]:= '_'; s:= cPathz[ptTeams] + '/' + s + '.hwt'; @@ -585,7 +604,6 @@ SplitBySpace(s, cs); SplitBySpace(cs, ts); Color:= StrToInt(cs); - TryDo(Color <> 0, 'Error: black team color', true); // color is always little endian so the mask must be constant also in big endian archs Color:= Color or $FF000000; @@ -593,7 +611,7 @@ CurrentTeam^.TeamName:= ts; CurrentTeam^.PlayerHash:= s; loadTeamBinds(ts); - + if GameType in [gmtDemo, gmtSave, gmtRecord] then CurrentTeam^.ExtDriven:= true; @@ -624,21 +642,85 @@ end; procedure chTeamGone(var s:shortstring); -var t: LongInt; +var t, i: LongInt; + isSynced: boolean; begin -t:= 0; -while (t < cMaxTeams) and (TeamsArray[t] <> nil) and (TeamsArray[t]^.TeamName <> s) do - inc(t); -if (t = cMaxTeams) or (TeamsArray[t] = nil) then - exit; + isSynced:= s[1] = 's'; + + Delete(s, 1, 1); + + t:= 0; + while (t < TeamsCount) and (TeamsArray[t]^.TeamName <> s) do + inc(t); + if t = TeamsCount then + exit; + + TeamsArray[t]^.isGoneFlagPendingToBeSet:= true; + + if isSynced then + begin + for i:= 0 to Pred(TeamsCount) do + with TeamsArray[i]^ do + begin + if (not hasGone) and isGoneFlagPendingToBeSet then + begin + AddChatString(#7 + '* '+ TeamName + ' is gone'); // TODO: localize + if not CurrentTeam^.ExtDriven then SendIPC(_S'f' + s); + hasGone:= true; + skippedTurns:= 0; + isGoneFlagPendingToBeSet:= false; + RecountTeamHealth(TeamsArray[i]) + end; + if hasGone and isGoneFlagPendingToBeUnset then + ParseCommand('/teamback s' + s, true) + end + end + else + begin + //TeamsArray[t]^.isGoneFlagPendingToBeSet:= true; -with TeamsArray[t]^ do - if not hasGone then + if (not CurrentTeam^.ExtDriven) or (CurrentTeam^.TeamName = s) or (CurrentTeam^.hasGone) then + ParseCommand('/teamgone s' + s, true) + end; +end; + +procedure chTeamBack(var s:shortstring); +var t: LongInt; + isSynced: boolean; +begin + isSynced:= s[1] = 's'; + + Delete(s, 1, 1); + + t:= 0; + while (t < TeamsCount) and (TeamsArray[t]^.TeamName <> s) do + inc(t); + if t = TeamsCount then + exit; + + if isSynced then begin - AddChatString('** '+ TeamName + ' is gone'); - hasGone:= true; + with TeamsArray[t]^ do + if hasGone then + begin + AddChatString(#8 + '* '+ TeamName + ' is back'); + if not CurrentTeam^.ExtDriven then SendIPC(_S'g' + s); + hasGone:= false; + + RecountTeamHealth(TeamsArray[t]); - RecountTeamHealth(TeamsArray[t]) + if isGoneFlagPendingToBeUnset and (Owner = UserNick) then + ExtDriven:= false; + + isGoneFlagPendingToBeUnset:= false; + end; + end + else + begin + TeamsArray[t]^.isGoneFlagPendingToBeUnset:= true; + + if not CurrentTeam^.ExtDriven then + ParseCommand('/teamback s' + s, true); end; end; @@ -649,14 +731,16 @@ // avoid compiler hint s:= s; +isPaused:= false; + t:= 0; -while (t < cMaxTeams) and (TeamsArray[t] <> nil) do +while t < TeamsCount do begin TeamsArray[t]^.hasGone:= true; - inc(t); + inc(t) end; -AddChatString('** Good-bye!'); +AddChatString(#7 + '* Good-bye!'); RecountAllTeamsHealth(); end; @@ -672,8 +756,6 @@ if newCI then DeleteCI(newHog^.Gear); oldHH:= CurrentHedgehog; CurrentHedgehog:= newHog; - if (CurrentHedgehog <> nil) and (CurrentHedgehog^.CurAmmoType = amKnife) then - LoadHedgehogHat(CurrentHedgehog^, 'Reserved/chef'); if oldCI then AddCI(oldHH^.Gear); if newCI then AddCI(newHog^.Gear) end; @@ -742,6 +824,7 @@ RegisterVariable('hhcoords', @chSetHHCoords, false); RegisterVariable('bind', @chBind, true ); RegisterVariable('teamgone', @chTeamGone, true ); +RegisterVariable('teamback', @chTeamBack, true ); RegisterVariable('finish', @chFinish, true ); // all teams gone RegisterVariable('fort' , @chFort , false); RegisterVariable('grave' , @chGrave , false); @@ -765,6 +848,7 @@ procedure freeModule; var i, h: LongWord; begin +CurrentHedgehog:= nil; if TeamsCount > 0 then begin for i:= 0 to Pred(TeamsCount) do @@ -772,28 +856,32 @@ for h:= 0 to cMaxHHIndex do with TeamsArray[i]^.Hedgehogs[h] do begin +// if Gear <> nil then +// DeleteGearStage(Gear, true); if GearHidden <> nil then Dispose(GearHidden); +// DeleteGearStage(GearHidden, true); - FreeTexture(NameTagTex); - FreeTexture(HealthTagTex); - FreeTexture(HatTex); + FreeAndNilTexture(NameTagTex); + FreeAndNilTexture(HealthTagTex); + FreeAndNilTexture(HatTex) end; with TeamsArray[i]^ do begin - FreeTexture(NameTagTex); - FreeTexture(GraveTex); - FreeTexture(AIKillsTex); - FreeTexture(FlagTex); + FreeAndNilTexture(NameTagTex); + FreeAndNilTexture(OwnerTex); + FreeAndNilTexture(GraveTex); + FreeAndNilTexture(AIKillsTex); + FreeAndNilTexture(FlagTex); end; - Dispose(TeamsArray[i]); - end; + Dispose(TeamsArray[i]) + end; for i:= 0 to Pred(ClansCount) do begin - FreeTexture(ClansArray[i]^.HealthTex); - Dispose(ClansArray[i]); + FreeAndNilTexture(ClansArray[i]^.HealthTex); + Dispose(ClansArray[i]) end end; TeamsCount:= 0; diff -r 31570b766315 -r ed5a6478e710 hedgewars/uTextures.pas --- a/hedgewars/uTextures.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uTextures.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} @@ -25,7 +25,8 @@ function NewTexture(width, height: Longword; buf: Pointer): PTexture; procedure Surface2GrayScale(surf: PSDL_Surface); function Surface2Tex(surf: PSDL_Surface; enableClamp: boolean): PTexture; -procedure FreeTexture(tex: PTexture); +procedure PrettifySurfaceAlpha(surf: PSDL_Surface; pixels: PLongwordArray); +procedure PrettifyAlpha2D(pixels: TLandArray; height, width: LongWord); procedure FreeAndNilTexture(var tex: PTexture); procedure initModule; @@ -107,20 +108,102 @@ fromP4:= Surf^.pixels; for y:= 0 to Pred(Surf^.h) do begin - for x:= 0 to Pred(Surf^.w) do + for x:= 0 to Pred(Surf^.w) do begin tw:= fromP4^[x]; - tw:= round((tw shr RShift and $FF) * RGB_LUMINANCE_RED + - (tw shr GShift and $FF) * RGB_LUMINANCE_GREEN + + tw:= round((tw shr RShift and $FF) * RGB_LUMINANCE_RED + + (tw shr GShift and $FF) * RGB_LUMINANCE_GREEN + (tw shr BShift and $FF) * RGB_LUMINANCE_BLUE); if tw > 255 then tw:= 255; tw:= (tw and $FF shl RShift) or (tw and $FF shl BShift) or (tw and $FF shl GShift) or (fromP4^[x] and AMask); fromP4^[x]:= tw; end; - fromP4:= @(fromP4^[Surf^.pitch div 4]) + fromP4:= PLongWordArray(@(fromP4^[Surf^.pitch div 4])) end; end; +{ this will make invisible pixels that have a visible neighbor have the + same color as their visible neighbor, so that bilinear filtering won't + display a "wrongly" colored border when zoomed in } +procedure PrettifyAlpha(row1, row2: PLongwordArray; firsti, lasti, ioffset: LongWord); +var + i: Longword; + lpi, cpi, bpi: boolean; // was last/current/bottom neighbor pixel invisible? +begin + // suppress incorrect warning + lpi:= true; + for i:=firsti to lasti do + begin + // use first pixel in row1 as starting point + if i = firsti then + cpi:= ((row1^[i] and AMask) = 0) + else + begin + cpi:= ((row1^[i] and AMask) = 0); + if cpi <> lpi then + begin + // invisible pixels get colors from visible neighbors + if cpi then + begin + row1^[i]:= row1^[i-1] and (not AMask); + // as this pixel is invisible and already colored correctly now, no point in further comparing it + lpi:= cpi; + continue; + end + else + row1^[i-1]:= row1^[i] and (not AMask); + end; + end; + lpi:= cpi; + // also check bottom neighbor + if row2 <> nil then + begin + bpi:= ((row2^[i+ioffset] and AMask) = 0); + if cpi <> bpi then + begin + if cpi then + row1^[i]:= row2^[i+ioffset] and (not AMask) + else + row2^[i+ioffset]:= row1^[i] and (not AMask); + end; + end; + end; +end; + +procedure PrettifySurfaceAlpha(surf: PSDL_Surface; pixels: PLongwordArray); +var + // current row index, second last row index of array, width and first/last i of row + r, slr, w, si, li: LongWord; +begin + w:= surf^.w; + slr:= surf^.h - 2; + si:= 0; + li:= w - 1; + for r:= 0 to slr do + begin + PrettifyAlpha(pixels, pixels, si, li, w); + // move indices to next row + si:= si + w; + li:= li + w; + end; + // don't forget last row + PrettifyAlpha(pixels, nil, si, li, w); +end; + +procedure PrettifyAlpha2D(pixels: TLandArray; height, width: LongWord); +var + // current y; last x, second last y of array; + y, lx, sly: LongWord; +begin + sly:= height - 2; + lx:= width - 1; + for y:= 0 to sly do + begin + PrettifyAlpha(PLongWordArray(pixels[y]), PLongWordArray(pixels[y+1]), 0, lx, 0); + end; + // don't forget last row + PrettifyAlpha(PLongWordArray(pixels[sly+1]), nil, 0, lx, 0); +end; function Surface2Tex(surf: PSDL_Surface; enableClamp: boolean): PTexture; var tw, th, x, y: Longword; @@ -148,7 +231,6 @@ exit end; - glGenTextures(1, @Surface2Tex^.id); glBindTexture(GL_TEXTURE_2D, Surface2Tex^.id); @@ -161,6 +243,8 @@ if GrayScale then Surface2GrayScale(Surf); +PrettifySurfaceAlpha(surf, fromP4); + if (not SupportNPOTT) and (not (isPowerOf2(Surf^.w) and isPowerOf2(Surf^.h))) then begin tw:= toPowerOf2(Surf^.w); @@ -179,16 +263,16 @@ for x:= 0 to Pred(Surf^.w) do toP4^[x]:= fromP4^[x]; for x:= Surf^.w to Pred(tw) do - toP4^[x]:= 0; - toP4:= @(toP4^[tw]); - fromP4:= @(fromP4^[Surf^.pitch div 4]) + toP4^[x]:= fromP4^[0]; + toP4:= PLongWordArray(@(toP4^[tw])); + fromP4:= PLongWordArray(@(fromP4^[Surf^.pitch div 4])) end; for y:= Surf^.h to Pred(th) do begin for x:= 0 to Pred(tw) do toP4^[x]:= 0; - toP4:= @(toP4^[tw]) + toP4:= PLongWordArray(@(toP4^[tw])) end; glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tw, th, 0, GL_RGBA, GL_UNSIGNED_BYTE, tmpp); @@ -212,25 +296,20 @@ // deletes texture and frees the memory allocated for it. // if nil is passed nothing is done -procedure FreeTexture(tex: PTexture); -begin -if tex <> nil then - begin - if tex^.NextTexture <> nil then - tex^.NextTexture^.PrevTexture:= tex^.PrevTexture; - if tex^.PrevTexture <> nil then - tex^.PrevTexture^.NextTexture:= tex^.NextTexture - else - TextureList:= tex^.NextTexture; - glDeleteTextures(1, @tex^.id); - Dispose(tex); - end -end; - procedure FreeAndNilTexture(var tex: PTexture); begin - FreeTexture(tex); - tex:= nil + if tex <> nil then + begin + if tex^.NextTexture <> nil then + tex^.NextTexture^.PrevTexture:= tex^.PrevTexture; + if tex^.PrevTexture <> nil then + tex^.PrevTexture^.NextTexture:= tex^.NextTexture + else + TextureList:= tex^.NextTexture; + glDeleteTextures(1, @tex^.id); + Dispose(tex); + tex:= nil; + end; end; procedure initModule; @@ -239,13 +318,15 @@ end; procedure freeModule; +var tex: PTexture; begin if TextureList <> nil then WriteToConsole('FIXME FIXME FIXME. App shutdown without full cleanup of texture list; read game0.log and please report this problem'); - while TextureList <> nil do + while TextureList <> nil do begin - AddFileLog('Texture not freed: width='+inttostr(LongInt(TextureList^.w))+' height='+inttostr(LongInt(TextureList^.h))+' priority='+inttostr(round(TextureList^.priority*1000))); - FreeTexture(TextureList); + tex:= TextureList; + AddFileLog('Texture not freed: width='+inttostr(LongInt(tex^.w))+' height='+inttostr(LongInt(tex^.h))+' priority='+inttostr(round(tex^.priority*1000))); + FreeAndNilTexture(tex); end end; diff -r 31570b766315 -r ed5a6478e710 hedgewars/uTouch.pas --- a/hedgewars/uTouch.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uTouch.pas Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} @@ -63,6 +63,7 @@ const clickTime = 200; + nilFingerId = High(TSDL_FingerId); baseRectSize = 96; var @@ -295,7 +296,7 @@ end; if targetting then - AddCaption('Press the target button to mark the target', cWhiteColor, capgrpAmmoInfo); + AddCaption(trmsg[sidPressTarget], cWhiteColor, capgrpAmmoInfo); deleteFinger(pointerId); end; @@ -360,8 +361,9 @@ //Check array sizes if length(fingers) < pointerCount then begin - setLength(fingers, pointerCount * 2); - WriteLnToConsole('allocated ' + inttostr(length(fingers)) + ' finger elements'); + setLength(fingers, length(fingers)*2); + for index := length(fingers) div 2 to length(fingers) do + fingers[index].id := nilFingerId; end; xCursor := convertToCursorX(x); diff -r 31570b766315 -r ed5a6478e710 hedgewars/uTypes.pas --- a/hedgewars/uTypes.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uTypes.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} @@ -43,8 +43,9 @@ // Different files are stored in different folders, this enumeration is used to tell which folder to use TPathType = (ptNone, ptData, ptGraphics, ptThemes, ptCurrTheme, ptTeams, ptMaps, - ptMapCurrent, ptDemos, ptSounds, ptGraves, ptFonts, ptForts, - ptLocale, ptAmmoMenu, ptHedgehog, ptVoices, ptHats, ptFlags, ptMissionMaps, ptSuddenDeath, ptButtons); + ptMapCurrent, ptDemos, ptSounds, ptGraves, ptFonts, ptForts, ptLocale, + ptAmmoMenu, ptHedgehog, ptVoices, ptHats, ptFlags, ptMissionMaps, + ptSuddenDeath, ptButtons, ptShaders); // Available sprites for displaying stuff TSprite = (sprWater, sprCloud, sprBomb, sprBigDigit, sprFrame, @@ -60,6 +61,7 @@ {$IFDEF USE_TOUCH_INTERFACE} sprFireButton, sprArrowUp, sprArrowDown, sprArrowLeft, sprArrowRight, sprJumpWidget, sprAMWidget, sprPauseButton, sprTimerButton, sprTargetButton, + sprSwitchButton, {$ENDIF} sprFlake, sprHandRope, sprHandBazooka, sprHandShotgun, sprHandDEagle, sprHandAirAttack, sprHandBaseball, sprPHammer, @@ -86,22 +88,24 @@ sprHandResurrector, sprCross, sprAirDrill, sprNapalmBomb, sprBulletHit, sprSnowball, sprHandSnowball, sprSnow, sprSDFlake, sprSDWater, sprSDCloud, sprSDSplash, sprSDDroplet, sprTardis, - sprSlider, sprBotlevels, sprHandKnife, sprKnife, sprStar, sprIceTexture, sprIceGun, sprFrozenHog, sprAmRubber, sprBoing + sprSlider, sprBotlevels, sprHandKnife, sprKnife, sprStar, sprIceTexture, sprIceGun, + sprFrozenHog, sprAmRubber, sprBoing, sprCustom1, sprCustom2, sprAirMine, sprHandAirMine ); // Gears that interact with other Gears and/or Land - TGearType = ({-->}gtFlame, gtHedgehog, gtMine, gtCase, gtExplosives, // <-- these are gears which should be avoided when searching a spawn place - gtGrenade, gtShell, gtGrave, gtBee, // 8 - gtShotgunShot, gtPickHammer, gtRope, // 11 - gtDEagleShot, gtDynamite, gtClusterBomb, gtCluster, gtShover, // 16 - gtFirePunch, gtATStartGame, // 18 - gtATFinishGame, gtParachute, gtAirAttack, gtAirBomb, gtBlowTorch, // 23 - gtGirder, gtTeleport, gtSwitcher, gtTarget, gtMortar, // 28 - gtWhip, gtKamikaze, gtCake, gtSeduction, gtWatermelon, gtMelonPiece, // 34 - gtHellishBomb, gtWaterUp, gtDrill, gtBallGun, gtBall, gtRCPlane, // 40 - gtSniperRifleShot, gtJetpack, gtMolotov, gtBirdy, // 44 - gtEgg, gtPortal, gtPiano, gtGasBomb, gtSineGunShot, gtFlamethrower, // 50 - gtSMine, gtPoisonCloud, gtHammer, gtHammerHit, gtResurrector, // 55 + // first row of gears ( + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} @@ -25,7 +25,7 @@ procedure SplitBySpace(var a, b: shortstring); procedure SplitByChar(var a, b: shortstring; c: char); -procedure SplitByChar(var a, b: ansistring; c: char); +procedure SplitByCharA(var a, b: ansistring; c: char); function EnumToStr(const en : TGearType) : shortstring; overload; function EnumToStr(const en : TVisualGearType) : shortstring; overload; @@ -34,8 +34,11 @@ function EnumToStr(const en : TStatInfoType) : shortstring; overload; function EnumToStr(const en : THogEffect) : shortstring; overload; function EnumToStr(const en : TCapGroup) : shortstring; overload; +function EnumToStr(const en : TSprite) : shortstring; overload; +function EnumToStr(const en : TMapGen) : shortstring; overload; function Min(a, b: LongInt): LongInt; inline; +function MinD(a, b: double) : double; inline; function Max(a, b: LongInt): LongInt; inline; function IntToStr(n: LongInt): shortstring; @@ -67,8 +70,12 @@ function GetLaunchX(at: TAmmoType; dir: LongInt; angle: LongInt): LongInt; function GetLaunchY(at: TAmmoType; angle: LongInt): LongInt; +{$IFNDEF PAS2C} procedure Write(var f: textfile; s: shortstring); procedure WriteLn(var f: textfile; s: shortstring); +function StrLength(s: PChar): Longword; +procedure SetLengthA(var s: ansistring; len: Longword); +{$ENDIF} function isPhone: Boolean; inline; @@ -88,15 +95,15 @@ implementation -uses typinfo, Math, uConsts, uVariables, SysUtils; +uses {$IFNDEF PAS2C}typinfo, {$ENDIF}Math, uConsts, uVariables, SysUtils; {$IFDEF DEBUGFILE} -var f: textfile; +var logFile: textfile; {$IFDEF USE_VIDEO_RECORDING} logMutex: TRTLCriticalSection; // mutex for debug file {$ENDIF} {$ENDIF} -var CharArray: array[byte] of Char; +var CharArray: array[0..255] of Char; procedure SplitBySpace(var a,b: shortstring); begin @@ -115,21 +122,31 @@ Inc(a[t], 32); b:= copy(a, i + 1, Length(a) - i); a[0]:= char(Pred(i)) + {$IFDEF PAS2C} + a[i] := 0; + {$ENDIF} end else b:= ''; end; -procedure SplitByChar(var a, b: ansistring; c: char); +{$IFNDEF PAS2C} +procedure SetLengthA(var s: ansistring; len: Longword); +begin + SetLength(s, len) +end; +{$ENDIF} + +procedure SplitByCharA(var a, b: ansistring; c: char); var i: LongInt; begin i:= Pos(c, a); if i > 0 then begin b:= copy(a, i + 1, Length(a) - i); - setlength(a, Pred(i)); + SetLengthA(a, Pred(i)); end else b:= ''; -end; +end; { SplitByCharA } function EnumToStr(const en : TGearType) : shortstring; overload; begin @@ -166,6 +183,16 @@ EnumToStr := GetEnumName(TypeInfo(TCapGroup), ord(en)) end; +function EnumToStr(const en: TSprite) : shortstring; overload; +begin +EnumToStr := GetEnumName(TypeInfo(TSprite), ord(en)) +end; + +function EnumToStr(const en: TMapGen) : shortstring; overload; +begin +EnumToStr := GetEnumName(TypeInfo(TMapGen), ord(en)) +end; + function Min(a, b: LongInt): LongInt; begin @@ -175,6 +202,14 @@ Min:= b end; +function MinD(a, b: double): double; +begin +if a < b then + MinD:= a +else + MinD:= b +end; + function Max(a, b: LongInt): LongInt; begin if a > b then @@ -189,13 +224,17 @@ str(n, IntToStr) end; -function StrToInt(s: shortstring): LongInt; +function StrToInt(s: shortstring): LongInt; var c: LongInt; begin +{$IFDEF PAS2C} +val(s, StrToInt); +{$ELSE} val(s, StrToInt, c); {$IFDEF DEBUGFILE} if c <> 0 then - writeln(f, 'Error at position ' + IntToStr(c) + ' : ' + s[c]) + writeln(logFile, 'Error at position ' + IntToStr(c) + ' : ' + s[c]) +{$ENDIF} {$ENDIF} end; @@ -257,7 +296,7 @@ function DecodeBase64(s: shortstring): shortstring; const table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; -var i, t, c: Longword; +var i, t, c: LongInt; begin c:= 0; for i:= 1 to Length(s) do @@ -290,10 +329,14 @@ function Str2PChar(const s: shortstring): PChar; +var i :Integer ; begin -CharArray:= s; -CharArray[Length(s)]:= #0; -Str2PChar:= @CharArray + for i:= 1 to Length(s) do + begin + CharArray[i - 1] := s[i]; + end; + CharArray[Length(s)]:= #0; + Str2PChar:= @(CharArray[0]); end; @@ -312,32 +355,37 @@ procedure AddFileLog(s: shortstring); begin -s:= s; +// s:= s; {$IFDEF DEBUGFILE} + {$IFDEF USE_VIDEO_RECORDING} EnterCriticalSection(logMutex); {$ENDIF} -writeln(f, inttostr(GameTicks) + ': ' + s); -flush(f); +writeln(logFile, inttostr(GameTicks) + ': ' + s); +flush(logFile); + {$IFDEF USE_VIDEO_RECORDING} LeaveCriticalSection(logMutex); {$ENDIF} + {$ENDIF} end; procedure AddFileLogRaw(s: pchar); cdecl; begin s:= s; +{$IFNDEF PAS2C} {$IFDEF DEBUGFILE} {$IFDEF USE_VIDEO_RECORDING} EnterCriticalSection(logMutex); {$ENDIF} -write(f, s); -flush(f); +write(logFile, s); +flush(logFile); {$IFDEF USE_VIDEO_RECORDING} LeaveCriticalSection(logMutex); {$ENDIF} {$ENDIF} +{$ENDIF} end; function CheckCJKFont(s: ansistring; font: THWFont): THWFont; @@ -353,7 +401,7 @@ {$ENDIF} exit; -l:= Utf8ToUnicode(@tmpstr, Str2PChar(s), length(s))-1; +l:= Utf8ToUnicode(PWideChar(@tmpstr), PChar(s), min(length(tmpstr), length(s)))-1; i:= 0; while i < l do @@ -370,7 +418,7 @@ ((#$F900 <= u) and (u <= #$FAFF)) or // CJK Compatibility Ideographs ((#$FE30 <= u) and (u <= #$FE4F)) or // CJK Compatibility Forms ((#$FF66 <= u) and (u <= #$FF9D))) // halfwidth katakana - then + then begin CheckCJKFont:= THWFont( ord(font) + ((ord(High(THWFont))+1) div 2) ); exit; @@ -408,6 +456,7 @@ CheckNoTeamOrHH:= (CurrentTeam = nil) or (CurrentHedgehog^.Gear = nil); end; +{$IFNDEF PAS2C} procedure Write(var f: textfile; s: shortstring); begin system.write(f, s) @@ -418,6 +467,11 @@ system.writeln(f, s) end; +function StrLength(s: PChar): Longword; +begin + StrLength:= length(s) +end; +{$ENDIF} // this function is just to determine whether we are running on a limited screen device function isPhone: Boolean; inline; @@ -444,7 +498,7 @@ r[i]:= '?' else r[i]:= s[i]; - + sanitizeForLog:= r end; @@ -454,8 +508,12 @@ if (c < #32) or (c > #127) then r:= '#' + inttostr(byte(c)) else - r:= c; - + begin + // some magic for pas2c + r[0]:= #1; + r[1]:= c; + end; + sanitizeCharForLog:= r end; @@ -463,6 +521,7 @@ {$IFDEF DEBUGFILE} var logfileBase: shortstring; i: LongInt; + rwfailed: boolean; {$ENDIF} begin {$IFDEF DEBUGFILE} @@ -471,32 +530,49 @@ if GameType = gmtRecord then logfileBase:= 'rec' else - logfileBase:= 'game'; + {$IFDEF PAS2C} + logfileBase:= 'game_pas2c'; + {$ELSE} + logfileBase:= 'game'; + {$ENDIF} end else + {$IFDEF PAS2C} + logfileBase:= 'preview_pas2c'; + {$ELSE} logfileBase:= 'preview'; + {$ENDIF} {$IFDEF USE_VIDEO_RECORDING} InitCriticalSection(logMutex); {$ENDIF} {$I-} - f:= stderr; // if everything fails, write to stderr - if (UserPathPrefix <> '') then + rwfailed:= false; + if (length(UserPathPrefix) > 0) then begin + {$IFNDEF PAS2C} // create directory if it doesn't exist if not FileExists(UserPathPrefix + '/Logs/') then CreateDir(UserPathPrefix + '/Logs/'); - + {$ENDIF} // if log is locked, write to the next one i:= 0; while(i < 7) do begin - assign(f, UserPathPrefix + '/Logs/' + logfileBase + inttostr(i) + '.log'); - if IOResult = 0 then + assign(logFile, shortstring(UserPathPrefix) + '/Logs/' + logfileBase + inttostr(i) + '.log'); + Rewrite(logFile); + // note: IOResult is a function in pascal and a variable in pas2c + rwfailed:= (IOResult <> 0); + if (not rwfailed) then break; inc(i) end; end; - Rewrite(f); + +{$IFNDEF PAS2C} + // if everything fails, write to stderr + if (length(UserPathPrefix) = 0) or (rwfailed) then + logFile:= stderr; +{$ENDIF} {$I+} {$ENDIF} @@ -518,9 +594,9 @@ procedure freeModule; begin {$IFDEF DEBUGFILE} - writeln(f, 'halt at ' + inttostr(GameTicks) + ' ticks. TurnTimeLeft = ' + inttostr(TurnTimeLeft)); - flush(f); - close(f); + writeln(logFile, 'halt at ' + inttostr(GameTicks) + ' ticks. TurnTimeLeft = ' + inttostr(TurnTimeLeft)); + flush(logFile); + close(logFile); {$IFDEF USE_VIDEO_RECORDING} DoneCriticalSection(logMutex); {$ENDIF} diff -r 31570b766315 -r ed5a6478e710 hedgewars/uVariables.pas --- a/hedgewars/uVariables.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uVariables.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} @@ -21,7 +21,7 @@ unit uVariables; interface -uses SDLh, uTypes, uFloat, GLunit, uConsts, Math; +uses SDLh, uTypes, uFloat, GLunit, uConsts, Math, uUtils{$IFDEF GL2}, uMatrix{$ENDIF}; var /////// init flags /////// @@ -37,12 +37,13 @@ cNewScreenHeight : LongInt; cScreenResizeDelay : LongWord; ipcPort : Word; + AprilOne : boolean; cFullScreen : boolean; cLocaleFName : shortstring; cLocale : shortstring; cTimerInterval : LongInt; - PathPrefix : shortstring; - UserPathPrefix : shortstring; + PathPrefix : ansistring; + UserPathPrefix : ansistring; cShowFPS : boolean; cFlattenFlakes : boolean; cFlattenClouds : boolean; @@ -97,10 +98,13 @@ cDamagePercent : LongInt; cMineDudPercent : LongWord; cTemplateFilter : LongInt; - cMapGen : LongInt; + cFeatureSize : LongInt; + cMapGen : TMapGen; cRopePercent : LongWord; cGetAwayTime : LongWord; + cAdvancedMapGenMode: boolean; + cHedgehogTurnTime: Longword; cMinesTime : LongInt; cMaxAIThinkTime : Longword; @@ -122,7 +126,11 @@ isAudioMuted : boolean; // originally typed consts - ExplosionBorderColor: LongWord; + ExplosionBorderColorR, + ExplosionBorderColorG, + ExplosionBorderColorB, + ExplosionBorderColorNoA, + ExplosionBorderColor: LongWord; IceColor : LongWord; IceEdgeColor : LongWord; WaterOpacity: byte; @@ -135,6 +143,7 @@ LAND_WIDTH_MASK : LongWord; LAND_HEIGHT_MASK : LongWord; + ChefHatTexture : PTexture; CrosshairTexture : PTexture; GenericHealthTexture : PTexture; @@ -144,9 +153,11 @@ cCaseFactor : Longword; cLandMines : Longword; + cAirMines : Longword; cExplosives : Longword; cScriptName : shortstring; + cScriptParam : shortstring; cSeed : shortstring; cVolumeDelta : LongInt; cHasFocus : boolean; @@ -159,6 +170,7 @@ CrosshairY : LongInt; CursorMovementX : LongInt; CursorMovementY : LongInt; + cWaveHeight : LongInt; cDrownSpeed : hwFloat; cDrownSpeedf : real; cMaxWindSpeed : hwFloat; @@ -167,13 +179,14 @@ cElastic : hwFloat; cGravity : hwFloat; cGravityf : real; + cBuildMaxDist : LongInt; cDamageModifier : hwFloat; cLaserSighting : boolean; cVampiric : boolean; cArtillery : boolean; WeaponTooltipTex: PTexture; AmmoMenuInvalidated: boolean; - AmmoRect : TSDL_Rect; + AmmoRect : TSDL_Rect; HHTexture : PTexture; cMaxZoomLevel : real; cMinZoomLevel : real; @@ -182,13 +195,14 @@ flagMakeCapture : boolean; + flagDumpLand : boolean; InitStepsFlags : Longword; RealTicks : Longword; AttackBar : LongInt; - WaterColorArray : array[0..3] of HwColor4f; - SDWaterColorArray : array[0..3] of HwColor4f; + WaterColorArray : array[0..7] of HwColor4f; + SDWaterColorArray : array[0..7] of HwColor4f; SDTint : LongInt; TargetCursorPoint : TPoint; @@ -208,16 +222,30 @@ WorldDx: LongInt; WorldDy: LongInt; + SpeechHogNumber: LongInt; + + // for tracking the limits of the visible grid based on cScaleFactor + ViewLeftX, ViewRightX, ViewBottomY, ViewTopY, ViewWidth, ViewHeight: LongInt; + + // for debugging the view limits visually + cViewLimitsDebug: boolean; + + dirtyLandTexCount: LongInt; + hiTicks: Word; LuaGoals : shortstring; LuaTemplateNumber : LongWord; - LastVoice : TVoice = ( snd: sndNone; voicepack: nil ); + LastVoice : TVoice; mobileRecord: TMobileRecord; + MaxTextureSize: LongInt; + + ChatPasteBuffer: shortstring; + ///////////////////////////////////// //Buttons {$IFDEF USE_TOUCH_INTERFACE} @@ -231,9 +259,12 @@ var // these consts are here because they would cause circular dependencies in uConsts/uTypes - cPathz: array[TPathType] of shortstring = ( + cPathz: array[TPathType] of shortstring; + +const + cPathzInit: array[TPathType] of shortstring = ( '', // ptNone - '/', // ptData + '//', // ptData '/Graphics', // ptGraphics '/Themes', // ptThemes '/Themes/Bamboo', // ptCurrTheme @@ -253,10 +284,15 @@ '/Graphics/Flags', // ptFlags '/Missions/Maps', // ptMissionMaps '/Graphics/SuddenDeath', // ptSuddenDeath - '/Graphics/Buttons' // ptButton + '/Graphics/Buttons', // ptButton + '/Shaders' // ptShaders ); - Fontz: array[THWFont] of THHFont = ( +var + Fontz: array[THWFont] of THHFont; + +const + FontzInit: array[THWFont] of THHFont = ( (Handle: nil; Height: 12; style: TTF_STYLE_NORMAL; @@ -286,16 +322,10 @@ ); var - SpritesData: array[TSprite] of record - FileName: string[15]; - Path, AltPath: TPathType; - Texture: PTexture; - Surface: PSDL_Surface; - Width, Height, imageWidth, imageHeight: LongInt; - saveSurf: boolean; - priority: GLfloat; - getDimensions, getImageDimensions: boolean; - end = ( + SpritesData: array[TSprite] of TSpriteData; + +const + SpritesDataInit: array[TSprite] of TSpriteData = ( (FileName: 'BlueWater'; Path: ptCurrTheme;AltPath: ptGraphics; Texture: nil; Surface: nil; Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: true; getImageDimensions: true),// sprWater (FileName: 'Clouds'; Path: ptCurrTheme;AltPath: ptGraphics; Texture: nil; Surface: nil; @@ -345,15 +375,15 @@ (FileName: 'horizont'; Path: ptCurrTheme;AltPath: ptNone; Texture: nil; Surface: nil; Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: true; getImageDimensions: true),// sprHorizont (FileName: 'horizontL'; Path: ptCurrTheme;AltPath: ptNone; Texture: nil; Surface: nil; - Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: true; getImageDimensions: true),// sprHorizont + Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: true; getImageDimensions: true),// sprHorizontL (FileName: 'horizontR'; Path: ptCurrTheme;AltPath: ptNone; Texture: nil; Surface: nil; - Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: true; getImageDimensions: true),// sprHorizont + Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: true; getImageDimensions: true),// sprHorizontR (FileName: 'Sky'; Path: ptCurrTheme;AltPath: ptNone; Texture: nil; Surface: nil; Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: true; getImageDimensions: true),// sprSky (FileName: 'SkyL'; Path: ptCurrTheme;AltPath: ptNone; Texture: nil; Surface: nil; - Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: true; getImageDimensions: true),// sprSky + Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: true; getImageDimensions: true),// sprSkyL (FileName: 'SkyR'; Path: ptCurrTheme;AltPath: ptNone; Texture: nil; Surface: nil; - Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: true; getImageDimensions: true),// sprSky + Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: true; getImageDimensions: true),// sprSkyR (FileName: 'Slot'; Path: ptAmmoMenu; AltPath: ptNone; Texture: nil; Surface: nil; Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprAMSlot (FileName: 'Ammos'; Path: ptAmmoMenu; AltPath: ptNone; Texture: nil; Surface: nil; @@ -397,13 +427,13 @@ {$IFDEF USE_TOUCH_INTERFACE} (FileName: 'firebutton'; Path: ptButtons; AltPath: ptNone; Texture: nil; Surface: nil; Width: 128; Height: 128; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprFireButton - (FileName: 'arrowUp'; Path: ptButtons; AltPath: ptNone; Texture: nil; Surface: nil; + (FileName: 'arrowup'; Path: ptButtons; AltPath: ptNone; Texture: nil; Surface: nil; Width: 100; Height: 100; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprArrowUp - (FileName: 'arrowDown'; Path: ptButtons; AltPath: ptNone; Texture: nil; Surface: nil; + (FileName: 'arrowdown'; Path: ptButtons; AltPath: ptNone; Texture: nil; Surface: nil; Width: 100; Height: 100; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprArrowDown - (FileName: 'arrowLeft'; Path: ptButtons; AltPath: ptNone; Texture: nil; Surface: nil; + (FileName: 'arrowleft'; Path: ptButtons; AltPath: ptNone; Texture: nil; Surface: nil; Width: 100; Height: 100; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprArrowLeft - (FileName: 'arrowRight'; Path: ptButtons; AltPath: ptNone; Texture: nil; Surface: nil; + (FileName: 'arrowright'; Path: ptButtons; AltPath: ptNone; Texture: nil; Surface: nil; Width: 100; Height: 100; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprArrowRight (FileName: 'forwardjump'; Path: ptButtons; AltPath: ptNone; Texture: nil; Surface: nil; Width: 128; Height: 128; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprAMWidget @@ -411,10 +441,12 @@ Width: 128; Height: 128; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprJumpWidget (FileName: 'pause'; Path: ptButtons; AltPath: ptNone; Texture: nil; Surface: nil; Width: 120; Height: 100; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprPauseButton - (FileName: 'pause'; Path: ptButtons; AltPath: ptNone; Texture: nil; Surface: nil;//TODO correct image - Width: 120; Height: 128; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprTimerButton - (FileName: 'forwardjump'; Path: ptButtons; AltPath: ptNone; Texture: nil; Surface: nil;//TODO correct image - Width: 120; Height: 128; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprTargetButton + (FileName: 'timerbutton'; Path: ptButtons; AltPath: ptNone; Texture: nil; Surface: nil; + Width: 128; Height: 128; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprTimerButton + (FileName: 'targetbutton'; Path: ptButtons; AltPath: ptNone; Texture: nil; Surface: nil; + Width: 128; Height: 128; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprTargetButton + (FileName: 'switchbutton'; Path: ptButtons; AltPath: ptNone; Texture: nil; Surface: nil; + Width: 128; Height: 128; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprSwitchButton {$ENDIF} (FileName: 'Flake'; Path:ptCurrTheme; AltPath: ptNone; Texture: nil; Surface: nil; Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprFlake @@ -665,8 +697,8 @@ Width: 80; Height: 50; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprSDSplash (FileName: 'SDDroplet'; Path: ptCurrTheme; AltPath: ptSuddenDeath; Texture: nil; Surface: nil; Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprSDDroplet - (FileName: 'TARDIS'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil; - Width: 48; Height: 79; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprTardis + (FileName: 'Timebox'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil; + Width: 50; Height: 81; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprTardis (FileName: 'slider'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil; Width: 3; Height: 17; imageWidth: 3; imageHeight: 17; saveSurf: false; priority: tpLow; getDimensions: false; getImageDimensions: false), // sprSlider (FileName: 'botlevels'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil; @@ -686,7 +718,15 @@ (FileName: 'amRubber'; Path: ptCurrTheme; AltPath: ptGraphics; Texture: nil; Surface: nil; Width: 160; Height:160; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpMedium; getDimensions: false; getImageDimensions: true), // sprAmRubber (FileName: 'boing'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil; - Width: 101; Height: 97; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpLow; getDimensions: false; getImageDimensions: false) // sprBoing + Width: 101; Height: 97; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpLow; getDimensions: false; getImageDimensions: false), // sprBoing + (FileName: 'custom1'; Path: ptCurrTheme;AltPath: ptGraphics; Texture: nil; Surface: nil; + Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpLow; getDimensions: true; getImageDimensions: true), // sprCustom1 + (FileName: 'custom2'; Path: ptCurrTheme;AltPath: ptGraphics; Texture: nil; Surface: nil; + Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpLow; getDimensions: true; getImageDimensions: true), // sprCustom2 + (FileName: 'AirMine'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil; + Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true), // sprAirMine + (FileName: 'amAirMine'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil; + Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true) // sprHandAirMine ); const @@ -707,8 +747,8 @@ (Sprite: sprJuggle; FramesCount: 49; Interval: 38; cmd: '/juggle'; Voice: sndNone; VoiceDelay: 0) ); -var - Ammoz: array [TAmmoType] of record +type + TAmmozRec = record NameId: TAmmoStrId; NameTex: PTexture; Probability, NumberInCase: Longword; @@ -717,11 +757,17 @@ TimeAfterTurn: Longword; minAngle, maxAngle: Longword; isDamaging: boolean; - SkipTurns: Longword; + SkipTurns: LongWord; PosCount: Longword; PosSprite: TSprite; ejectX, ejectY: Longint; - end = ( + end; + +var + Ammoz: array [TAmmoType] of TAmmozRec; + +const + AmmozInit: array [TAmmoType] of TAmmozRec = ( (NameId: sidNothing; NameTex: nil; Probability: 0; @@ -750,9 +796,9 @@ NameTex: nil; Probability: 0; NumberInCase: 1; - Ammo: (Propz: ammoprop_Timerable or - ammoprop_Power or - ammoprop_AltUse or + Ammo: (Propz: ammoprop_Timerable or + ammoprop_Power or + ammoprop_AltUse or ammoprop_SetBounce or ammoprop_NeedUpDown; Count: AMMO_INFINITE; @@ -778,9 +824,9 @@ NameTex: nil; Probability: 100; NumberInCase: 3; - Ammo: (Propz: ammoprop_Timerable or - ammoprop_Power or - ammoprop_AltUse or + Ammo: (Propz: ammoprop_Timerable or + ammoprop_Power or + ammoprop_AltUse or ammoprop_SetBounce or ammoprop_NeedUpDown; Count: 5; @@ -806,7 +852,7 @@ NameTex: nil; Probability: 0; NumberInCase: 1; - Ammo: (Propz: ammoprop_Power or + Ammo: (Propz: ammoprop_Power or ammoprop_AltUse or ammoprop_NeedUpDown; Count: AMMO_INFINITE; @@ -832,8 +878,8 @@ NameTex: nil; Probability: 100; NumberInCase: 1; - Ammo: (Propz: ammoprop_Power or - ammoprop_NeedTarget or + Ammo: (Propz: ammoprop_Power or + ammoprop_NeedTarget or ammoprop_DontHold or ammoprop_NeedUpDown; Count: 2; @@ -885,9 +931,9 @@ NameTex: nil; Probability: 0; NumberInCase: 1; - Ammo: (Propz: ammoprop_ForwMsgs or - ammoprop_AttackInMove or - ammoprop_NoCrosshair or + Ammo: (Propz: ammoprop_ForwMsgs or + ammoprop_AttackInMove or + ammoprop_NoCrosshair or ammoprop_DontHold; Count: 2; NumPerTurn: 0; @@ -912,7 +958,8 @@ NameTex: nil; Probability: 0; NumberInCase: 1; - Ammo: (Propz: ammoprop_NoCrosshair or + Ammo: (Propz: ammoprop_NoCrosshair or + ammoprop_AttackInMove or ammoprop_DontHold; Count: AMMO_INFINITE; NumPerTurn: 0; @@ -967,10 +1014,10 @@ NameTex: nil; Probability: 100; NumberInCase: 1; - Ammo: (Propz: ammoprop_NoCrosshair or - ammoprop_AttackInMove or - ammoprop_DontHold or - ammoprop_AltUse or + Ammo: (Propz: ammoprop_NoCrosshair or + ammoprop_AttackInMove or + ammoprop_DontHold or + ammoprop_AltUse or ammoprop_SetBounce; Count: 2; NumPerTurn: 0; @@ -1019,9 +1066,9 @@ NameTex: nil; Probability: 100; NumberInCase: 1; - Ammo: (Propz: ammoprop_NoCrosshair or - ammoprop_AttackInMove or - ammoprop_DontHold or + Ammo: (Propz: ammoprop_NoCrosshair or + ammoprop_AttackInMove or + ammoprop_DontHold or ammoprop_AltUse; Count: 1; NumPerTurn: 0; @@ -1046,8 +1093,8 @@ NameTex: nil; Probability: 0; NumberInCase: 1; - Ammo: (Propz: ammoprop_NoCrosshair or - ammoprop_ForwMsgs or + Ammo: (Propz: ammoprop_NoCrosshair or + ammoprop_ForwMsgs or ammoprop_AttackInMove; Count: AMMO_INFINITE; NumPerTurn: 0; @@ -1318,7 +1365,7 @@ NameTex: nil; Probability: 100; NumberInCase: 4; - Ammo: (Propz: 0; + Ammo: (Propz: ammoprop_NeedUpDown; Count: 4; NumPerTurn: 0; Timer: 0; @@ -1342,8 +1389,8 @@ NameTex: nil; Probability: 100; NumberInCase: 1; - Ammo: (Propz: ammoprop_ForwMsgs or - ammoprop_DontHold or + Ammo: (Propz: ammoprop_ForwMsgs or + ammoprop_DontHold or ammoprop_NeedUpDown or ammoprop_AttackInMove; Count: 1; @@ -1369,8 +1416,8 @@ NameTex: nil; Probability: 100; NumberInCase: 1; - Ammo: (Propz: ammoprop_ForwMsgs or - ammoprop_NoCrosshair or + Ammo: (Propz: ammoprop_ForwMsgs or + ammoprop_NoCrosshair or ammoprop_DontHold or ammoprop_Track; Count: 1; @@ -1396,7 +1443,7 @@ NameTex: nil; Probability: 100; NumberInCase: 1; - Ammo: (Propz: ammoprop_ForwMsgs or + Ammo: (Propz: ammoprop_ForwMsgs or ammoprop_DontHold or ammoprop_NoCrosshair; Count: 1; @@ -1422,8 +1469,8 @@ NameTex: nil; Probability: 400; NumberInCase: 1; - Ammo: (Propz: ammoprop_Timerable or - ammoprop_Power or + Ammo: (Propz: ammoprop_Timerable or + ammoprop_Power or ammoprop_NeedUpDown or ammoprop_AltUse; Count: 0; @@ -1449,7 +1496,7 @@ NameTex: nil; Probability: 400; NumberInCase: 1; - Ammo: (Propz: ammoprop_Power or + Ammo: (Propz: ammoprop_Power or ammoprop_NeedUpDown or ammoprop_AltUse; Count: 0; @@ -1503,7 +1550,7 @@ NameTex: nil; Probability: 300; NumberInCase: 1; - Ammo: (Propz: ammoprop_Power or + Ammo: (Propz: ammoprop_Power or ammoprop_NeedUpDown or ammoprop_AltUse; Count: AMMO_INFINITE; @@ -1529,7 +1576,7 @@ NameTex: nil; Probability: 400; NumberInCase: 1; - Ammo: (Propz: ammoprop_ForwMsgs or + Ammo: (Propz: ammoprop_ForwMsgs or ammoprop_NeedUpDown or ammoprop_DontHold; Count: AMMO_INFINITE; @@ -1814,7 +1861,7 @@ NameTex: nil; Probability: 0; NumberInCase: 1; - Ammo: (Propz: ammoprop_Power or + Ammo: (Propz: ammoprop_Power or ammoprop_NeedUpDown or ammoprop_AltUse; Count: AMMO_INFINITE; @@ -1923,9 +1970,9 @@ NameTex: nil; Probability: 0; NumberInCase: 1; - Ammo: (Propz: ammoprop_Timerable or - ammoprop_Power or - ammoprop_AltUse or + Ammo: (Propz: ammoprop_Timerable or + ammoprop_Power or + ammoprop_AltUse or ammoprop_NeedUpDown or ammoprop_SetBounce; Count: AMMO_INFINITE; @@ -1976,7 +2023,7 @@ NameTex: nil; Probability: 20; NumberInCase: 1; - Ammo: (Propz: ammoprop_ForwMsgs or + Ammo: (Propz: ammoprop_ForwMsgs or ammoprop_NeedUpDown or ammoprop_DontHold; Count: 1; @@ -2107,8 +2154,9 @@ NameTex: nil; Probability: 0; NumberInCase: 1; - Ammo: (Propz: ammoprop_Power or + Ammo: (Propz: ammoprop_Power or ammoprop_AltUse or + ammoprop_NeedUpDown or ammoprop_NoRoundEnd; Count: 2; NumPerTurn: 0; @@ -2125,7 +2173,7 @@ SkipTurns: 0; PosCount: 1; PosSprite: sprWater; - ejectX: 0; + ejectX: 0; ejectY: 0), // Tardis @@ -2155,7 +2203,7 @@ ejectX: 0; ejectY: 0), -// Structure +// Structure { (NameId: sidStructure; NameTex: nil; @@ -2183,13 +2231,14 @@ ejectX: 0; ejectY: 0), } - + // Land Gun (NameId: sidLandGun; NameTex: nil; Probability: 20; NumberInCase: 1; Ammo: (Propz: ammoprop_NoRoundEnd or + ammoprop_NeedUpDown or ammoprop_Utility; Count: 1; NumPerTurn: 0; @@ -2213,7 +2262,7 @@ NameTex: nil; Probability: 20; NumberInCase: 1; - Ammo: (Propz: ammoprop_ForwMsgs or + Ammo: (Propz: ammoprop_ForwMsgs or ammoprop_NeedUpDown or ammoprop_DontHold; Count: 1; @@ -2284,6 +2333,31 @@ PosCount: 4; PosSprite: sprAmRubber; ejectX: 0; + ejectY: 0), +// Air Mine + (NameId: sidAirMine; + NameTex: nil; + Probability: 100; + NumberInCase: 1; + Ammo: (Propz: ammoprop_Power or + ammoprop_AltUse or + ammoprop_NeedUpDown; + Count: 2; + NumPerTurn: 0; + Timer: 0; + Pos: 0; + AmmoType: amAirMine; + AttackVoice: sndLaugh; + Bounciness: 1000); + Slot: 5; + TimeAfterTurn: 5000; + minAngle: 0; + maxAngle: 0; + isDamaging: true; + SkipTurns: 0; + PosCount: 1; + PosSprite: sprWater; + ejectX: 0; ejectY: 0) ); @@ -2340,6 +2414,7 @@ SyncTexture, ConfirmTexture: PTexture; cScaleFactor: GLfloat; + cStereoDepth: GLfloat; SupportNPOTT: Boolean; Step: LongInt; MissionIcons: PSDL_Surface; @@ -2363,18 +2438,35 @@ lastTurnChecksum : Longword; + mModelview: TMatrix4x4f; + mProjection: TMatrix4x4f; + vBuffer: GLuint; // vertex buffer + tBuffer: GLuint; // texture coords buffer + cBuffer: GLuint; // color buffer + + uCurrentMVPLocation: GLint; + + uMainMVPLocation: GLint; + uMainTintLocation: GLint; + + uWaterMVPLocation: GLint; + + aVertex: GLint; + aTexCoord: GLint; + aColor: GLint; + var trammo: array[TAmmoStrId] of ansistring; // name of the weapon trammoc: array[TAmmoStrId] of ansistring; // caption of the weapon trammod: array[TAmmoStrId] of ansistring; // description of the weapon trmsg: array[TMsgStrId] of ansistring; // message of the event trgoal: array[TGoalStrId] of ansistring; // message of the goal + cTestLua : Boolean; procedure preInitModule; procedure initModule; procedure freeModule; implementation -uses strutils; procedure preInitModule; begin @@ -2403,6 +2495,9 @@ PathPrefix := './'; GameType := gmtLocal; cOnlyStats := False; + cScriptName := ''; + cScriptParam := ''; + cTestLua := False; {$IFDEF USE_VIDEO_RECORDING} RecPrefix := ''; @@ -2413,12 +2508,27 @@ cVideoQuality := 0; cAudioCodec := ''; {$ENDIF} + + cTagsMask:= htTeamName or htName or htHealth; end; procedure initModule; +var s: shortstring; + i: integer; begin - // TODO: we could just have one cLocale variables and drop strutils - cLocale:= ExtractDelimited(1, cLocaleFName, StdWordDelims); + // init LastVoice + LastVoice.snd:= sndNone; + LastVoice.voicepack:= nil; + + // init arrays + Move(cPathzInit, cPathz, sizeof(cPathz)); + Move(FontzInit, Fontz, sizeof(Fontz)); + Move(SpritesDataInit, SpritesData, sizeof(SpritesData)); + Move(AmmozInit, Ammoz, sizeof(Ammoz)); + + + cLocale:= cLocaleFName; + SplitByChar(cLocale, s, '.'); cFlattenFlakes := false; cFlattenClouds := false; @@ -2448,24 +2558,39 @@ LAND_HEIGHT_MASK:= $FFFFF800 end; - SDWaterColorArray[0].r := 182; - SDWaterColorArray[0].g := 144; - SDWaterColorArray[0].b := 201; + // default sudden death water + + // deep water + SDWaterColorArray[0].r := 150; + SDWaterColorArray[0].g := 112; + SDWaterColorArray[0].b := 169; SDWaterColorArray[0].a := 255; - SDWaterColorArray[2].r := 150; - SDWaterColorArray[2].g := 112; - SDWaterColorArray[2].b := 169; - SDWaterColorArray[2].a := 255; - SDWaterColorArray[1]:= SDWaterColorArray[0]; - SDWaterColorArray[3]:= SDWaterColorArray[2]; + SDWaterColorArray[2]:= SDWaterColorArray[0]; + SDWaterColorArray[4]:= SDWaterColorArray[0]; + SDWaterColorArray[6]:= SDWaterColorArray[0]; + // water surface + SDWaterColorArray[1].r := 182; + SDWaterColorArray[1].g := 144; + SDWaterColorArray[1].b := 201; + SDWaterColorArray[1].a := 255; + SDWaterColorArray[3]:= SDWaterColorArray[1]; + SDWaterColorArray[5]:= SDWaterColorArray[1]; + SDWaterColorArray[7]:= SDWaterColorArray[1]; + SDWaterOpacity:= $80; + SDTint:= $80; + ExplosionBorderColorR:= 80; + ExplosionBorderColorG:= 80; + ExplosionBorderColorB:= 80; ExplosionBorderColor:= $FF808080; + ExplosionBorderColorNoA:= ExplosionBorderColor and (not AMask); IceColor:= ($44 shl RShift) or ($97 shl GShift) or ($A9 shl BShift) or ($A0 shl AShift); IceEdgeColor:= ($8A shl RShift) or ($AF shl GShift) or ($B2 shl BShift) or ($FF shl AShift); WaterOpacity:= $80; + cWaveHeight := 32; cDrownSpeed.QWordValue := 257698038; // 0.06 cDrownSpeedf := 0.06; cMaxWindSpeed.QWordValue:= 1073742; // 0.00025 @@ -2474,6 +2599,7 @@ cElastic := _0_9; cGravity := cMaxWindSpeed * 2; cGravityf := 0.00025 * 2; + cBuildMaxDist := cDefaultBuildMaxDist; cDamageModifier := _1; TargetPoint := cTargetPointRef; @@ -2511,7 +2637,8 @@ cGetAwayTime := 100; cMineDudPercent := 0; cTemplateFilter := 0; - cMapGen := 0; // MAPGEN_REGULAR + cFeatureSize := 50; + cMapGen := mgRandom; cHedgehogTurnTime := 45000; cMinesTime := 3000; cMaxAIThinkTime := 9000; @@ -2521,12 +2648,14 @@ cHealthCaseAmount := 25; cWaterRise := 47; cHealthDecrease := 5; + cAdvancedMapGenMode := false; InitStepsFlags := 0; RealTicks := 0; AttackBar := 0; // 0 - none, 1 - just bar at the right-down corner, 2 - from weapon cCaseFactor := 5; {0..9} cLandMines := 4; + cAirMines := 0; cExplosives := 2; GameState := Low(TGameState); @@ -2537,6 +2666,7 @@ cVampiric := false; cArtillery := false; flagMakeCapture := false; + flagDumpLand := false; bBetweenTurns := false; bWaterRising := false; isCursorVisible := false; @@ -2549,13 +2679,12 @@ fastUntilLag := false; fastScrolling := false; autoCameraOn := true; - cScriptName := ''; cSeed := ''; cVolumeDelta := 0; cHasFocus := true; cInactDelay := 100; ReadyTimeLeft := 0; - + disableLandBack := false; ScreenFade := sfNone; @@ -2564,20 +2693,27 @@ cRightScreenBorder:= round(cMinZoomLevel * cScreenWidth + LAND_WIDTH); cScreenSpace:= cRightScreenBorder - cLeftScreenBorder; - vobFrameTicks:= 99999; + dirtyLandTexCount:= 0; + + vobFrameTicks:= 0; vobFramesCount:= 4; vobCount:= 0; vobVelocity:= 10; vobFallSpeed:= 100; - vobSDFrameTicks:= 99999; + vobSDFrameTicks:= 0; vobSDFramesCount:= 4; vobSDCount:= 30 * cScreenSpace div LAND_WIDTH; vobSDVelocity:= 15; vobSDFallSpeed:= 250; +{$IFDEF MOBILE} + cMinScreenWidth := min(cScreenWidth, 480); + cMinScreenHeight := min(cScreenHeight, 320); +{$ELSE} cMinScreenWidth := min(cScreenWidth, 640); cMinScreenHeight := min(cScreenHeight, 480); +{$ENDIF} cNewScreenWidth := cScreenWidth; cNewScreenHeight := cScreenHeight; @@ -2589,6 +2725,7 @@ if cFullscreenHeight = 0 then cFullscreenHeight:= min(cWindowedHeight, 480); + SpeechHogNumber:= -1; LuaGoals:= ''; cMapName:= ''; @@ -2597,6 +2734,49 @@ UIDisplay:= uiAll; LocalMessage:= 0; + + cStereoDepth:= 0; + cViewLimitsDebug:= false; + AprilOne := false; + + ChatPasteBuffer:= ''; + + // initialize pointers to nil + // (don't rely on implicit init of fpc, because that one only happens ONCE when used as lib) + CurAmmoGear:= nil; + lastGearByUID:= nil; + GearsList:= nil; + CurrentTeam:= nil; + PreviousTeam:= nil; + CurrentHedgehog:= nil; + FollowGear:= nil; + lastVisualGearByUID:= nil; + + ChefHatTexture:= nil; + CrosshairTexture:= nil; + GenericHealthTexture:= nil; + WeaponTooltipTex:= nil; + HHTexture:= nil; + LandBackSurface:= nil; + ConfirmTexture:= nil; + MissionIcons:= nil; + ropeIconTex:= nil; + + for i:= Low(ClansArray) to High(ClansArray) do + begin + ClansArray[i]:= nil; + end; + + for i:= Low(TeamsArray) to High(TeamsArray) do + begin + TeamsArray[i]:= nil; + end; + + for i:= Low(CountTexz) to High(CountTexz) do + begin + CountTexz[i]:= nil; + end; + end; procedure freeModule; diff -r 31570b766315 -r ed5a6478e710 hedgewars/uVideoRec.pas --- a/hedgewars/uVideoRec.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uVideoRec.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) @@ -48,17 +48,17 @@ procedure freeModule; implementation -uses uVariables, uUtils, GLunit, SDLh, SysUtils, uIO, uMisc, uTypes; +uses uVariables, uUtils, GLunit, SDLh, SysUtils, uIO, uMisc, uTypes, uDebug; type TAddFileLogRaw = procedure (s: pchar); cdecl; const AvwrapperLibName = 'libavwrapper'; -procedure AVWrapper_Init( +function AVWrapper_Init( AddLog: TAddFileLogRaw; filename, desc, soundFile, format, vcodec, acodec: PChar; - width, height, framerateNum, framerateDen, vquality: LongInt); cdecl; external AvwrapperLibName; -procedure AVWrapper_Close; cdecl; external AvwrapperLibName; -procedure AVWrapper_WriteFrame( pY, pCb, pCr: PByte ); cdecl; external AvwrapperLibName; + width, height, framerateNum, framerateDen, vquality: LongInt): LongInt; cdecl; external AvwrapperLibName; +function AVWrapper_Close: LongInt; cdecl; external AvwrapperLibName; +function AVWrapper_WriteFrame( pY, pCb, pCr: PByte ): LongInt; cdecl; external AvwrapperLibName; type TFrame = record realTicks: LongWord; @@ -109,14 +109,16 @@ filename:= UserPathPrefix + '/VideoTemp/' + RecPrefix; soundFilePath:= UserPathPrefix + '/VideoTemp/' + RecPrefix + '.sw'; - AVWrapper_Init(@AddFileLogRaw + TryDo(AVWrapper_Init(@AddFileLogRaw , PChar(ansistring(filename)) , PChar(ansistring(desc)) , PChar(ansistring(soundFilePath)) , PChar(ansistring(cAVFormat)) , PChar(ansistring(cVideoCodec)) , PChar(ansistring(cAudioCodec)) - , cScreenWidth, cScreenHeight, cVideoFramerateNum, cVideoFramerateDen, cVideoQuality); + , cScreenWidth, cScreenHeight, cVideoFramerateNum, cVideoFramerateDen, cVideoQuality) >= 0, + 'AVWrapper_Init failed', + true); numPixels:= cScreenWidth*cScreenHeight; YCbCr_Planes[0]:= GetMem(numPixels); @@ -150,7 +152,8 @@ FreeMem(YCbCr_Planes[2], numPixels div 4); FreeMem(RGB_Buffer, 4*numPixels); Close(cameraFile); - AVWrapper_Close(); + if AVWrapper_Close() < 0 then + halt(-1); Erase(cameraFile); DeleteFile(soundFilePath); SendIPC(_S'v'); // inform frontend that we finished @@ -185,7 +188,8 @@ YCbCr_Planes[2][y*(cScreenWidth div 2) + x]:= Byte(128 + (( 7196*r - 6026*g - 1170*b) shr 16)); end; - AVWrapper_WriteFrame(YCbCr_Planes[0], YCbCr_Planes[1], YCbCr_Planes[2]); + if AVWrapper_WriteFrame(YCbCr_Planes[0], YCbCr_Planes[1], YCbCr_Planes[2]) < 0 then + halt(-1); // inform frontend that we have encoded new frame s[0]:= #3; @@ -235,7 +239,7 @@ thumbpath:= '/VideoTemp/' + RecPrefix; AddFileLog('Saving thumbnail ' + thumbpath); k:= max(max(cScreenWidth, cScreenHeight) div 400, 1); // here 400 is minimum size of thumbnail - MakeScreenshot(thumbpath, k); + MakeScreenshot(thumbpath, k, 0); thumbnailSaved:= true; end; diff -r 31570b766315 -r ed5a6478e710 hedgewars/uVisualGears.pas --- a/hedgewars/uVisualGears.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uVisualGears.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} @@ -47,22 +47,18 @@ procedure KickFlakes(Radius, X, Y: LongInt); implementation -uses uVariables, uRender, Math, uRenderUtils, uStore, uUtils +uses uVariables, uRender, Math, uRenderUtils, uUtils , uVisualGearsList; procedure AddDamageTag(X, Y, Damage, Color: LongWord); -var s: shortstring; - Gear: PVisualGear; +var Gear: PVisualGear; begin if cAltDamage then begin Gear:= AddVisualGear(X, Y, vgtSmallDamageTag); if Gear <> nil then with Gear^ do - begin - str(Damage, s); - Tex:= RenderStringTex(s, Color, fntSmall); - end + Tex:= RenderStringTex(ansistring(inttostr(Damage)), Color, fntSmall); end end; @@ -121,12 +117,32 @@ end end; +function GetSprite(sprite, SDsprite: TSprite): TSprite; inline; +begin + if SuddenDeathDmg then + exit(SDsprite) + else + exit(sprite); +end; + +function GetSpriteData(sprite, SDsprite: TSprite): PSpriteData; inline; +begin + exit(@SpritesData[GetSprite(sprite, SDsprite)]); +end; + procedure DrawVisualGears(Layer: LongWord); var Gear: PVisualGear; - tinted: boolean; + tinted, speedlessFlakes: boolean; tmp: real; i: LongInt; + sprite: TSprite; + spriteData: PSpriteData; begin +if SuddenDeathDmg then + speedlessFlakes:= (vobSDVelocity = 0) +else + speedlessFlakes:= (vobVelocity = 0); + case Layer of // this layer is very distant in the background when stereo 0: begin @@ -135,36 +151,27 @@ begin if Gear^.Tint <> $FFFFFFFF then Tint(Gear^.Tint); case Gear^.Kind of - vgtCloud: if SuddenDeathDmg then - DrawTextureF(SpritesData[sprSDCloud].Texture, Gear^.Scale, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 2, SpritesData[sprCloud].Width, SpritesData[sprCloud].Height) - else - DrawTextureF(SpritesData[sprCloud].Texture, Gear^.Scale, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 2, SpritesData[sprCloud].Width, SpritesData[sprCloud].Height); - vgtFlake: if cFlattenFlakes then + vgtCloud: begin + spriteData:= GetSpriteData(sprCloud, sprSDCloud); + DrawTextureF(spriteData^.Texture, Gear^.Scale, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, spriteData^.Width, spriteData^.Height) + end; + vgtFlake: begin + sprite:= GetSprite(sprFlake, sprSDFlake); + if cFlattenFlakes then begin - if SuddenDeathDmg then - if vobSDVelocity = 0 then - DrawSprite(sprSDFlake, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame) - else - DrawSpriteRotatedF(sprSDFlake, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, Gear^.Angle) + if speedlessFlakes then + DrawSprite(sprite, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame) else - if vobVelocity = 0 then - DrawSprite(sprFlake, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame) - else - DrawSpriteRotatedF(sprFlake, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, Gear^.Angle) + DrawSpriteRotatedF(sprite, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, Gear^.Angle); end else begin - if SuddenDeathDmg then - if vobSDVelocity = 0 then - DrawTextureF(SpritesData[sprSDFlake].Texture, Gear^.Scale, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, SpritesData[sprFlake].Width, SpritesData[sprFlake].Height) - else - DrawTextureRotatedF(SpritesData[sprSDFlake].Texture, Gear^.Scale, 0, 0, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, SpritesData[sprFlake].Width, SpritesData[sprFlake].Height, Gear^.Angle) + if speedlessFlakes then + DrawTextureF(SpritesData[sprite].Texture, Gear^.Scale, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, SpritesData[sprFlake].Width, SpritesData[sprFlake].Height) else - if vobVelocity = 0 then - DrawTextureF(SpritesData[sprFlake].Texture, Gear^.Scale, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, SpritesData[sprFlake].Width, SpritesData[sprFlake].Height) - else - DrawTextureRotatedF(SpritesData[sprFlake].Texture, Gear^.Scale, 0, 0, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, SpritesData[sprFlake].Width, SpritesData[sprFlake].Height, Gear^.Angle) + DrawTextureRotatedF(SpritesData[sprite].Texture, Gear^.Scale, 0, 0, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, SpritesData[sprFlake].Width, SpritesData[sprFlake].Height, Gear^.Angle); end; + end; end; if Gear^.Tint <> $FFFFFFFF then untint; @@ -180,16 +187,13 @@ if Gear^.Tint <> $FFFFFFFF then Tint(Gear^.Tint); case Gear^.Kind of - vgtFlake: if SuddenDeathDmg then - if vobSDVelocity = 0 then - DrawSprite(sprSDFlake, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame) - else - DrawSpriteRotatedF(sprSDFlake, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, Gear^.Angle) + vgtFlake: begin + sprite:= GetSprite(sprFlake, sprSDFlake); + if speedlessFlakes then + DrawSprite(sprite, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame) else - if vobVelocity = 0 then - DrawSprite(sprFlake, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame) - else - DrawSpriteRotatedF(sprFlake, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, Gear^.Angle); + DrawSpriteRotatedF(sprite, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, Gear^.Angle); + end; vgtSmokeTrace: if Gear^.State < 8 then DrawSprite(sprSmokeTrace, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.State); vgtEvilTrace: if Gear^.State < 8 then @@ -201,25 +205,27 @@ 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 - DrawSpriteRotatedF(sprSnowDust, round(Gear^.X) + WorldDx - 11, round(Gear^.Y) + WorldDy - 11, 7 - Gear^.Frame, Gear^.Tag, Gear^.Angle) + DrawSpriteRotatedF(sprSnowDust, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, 7 - Gear^.Frame, Gear^.Tag, Gear^.Angle) else - DrawSpriteRotatedF(sprDust, round(Gear^.X) + WorldDx - 11, round(Gear^.Y) + WorldDy - 11, 7 - Gear^.Frame, Gear^.Tag, Gear^.Angle); + DrawSpriteRotatedF(sprDust, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, 7 - Gear^.Frame, Gear^.Tag, Gear^.Angle); vgtFire: if (Gear^.State and gstTmpFlag) = 0 then DrawSprite(sprFlame, round(Gear^.X) + WorldDx - 8, round(Gear^.Y) + WorldDy, (RealTicks shr 6 + Gear^.Frame) mod 8) else DrawTextureF(SpritesData[sprFlame].Texture, Gear^.FrameTicks / 900, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, (RealTicks shr 7 + Gear^.Frame) mod 8, 1, 16, 16); - vgtSplash: if SuddenDeathDmg then - //DrawSprite(sprSDSplash, round(Gear^.X) + WorldDx - 40, round(Gear^.Y) + WorldDy - 58, 19 - (Gear^.FrameTicks div 37)) - DrawTextureF(SpritesData[sprSDSplash].Texture, Gear^.scale, round(Gear^.X + WorldDx), round(Gear^.Y + WorldDy - ((SpritesData[sprSDSplash].Height+8)*Gear^.Scale)/2), 19 - (Gear^.FrameTicks div Gear^.Timer div 37), 1, SpritesData[sprSDSplash].Width, SpritesData[sprSDSplash].Height) + vgtSplash: begin + spriteData:= GetSpriteData(sprSplash, sprSDSplash); + if Gear^.Angle <> 0 then + DrawTextureRotatedF(spriteData^.Texture, Gear^.scale, 0, 0, round(Gear^.X + WorldDx + (((spriteData^.Height+8)*Gear^.Scale)/2) * (Gear^.Angle / abs(Gear^.Angle))), round(Gear^.Y + WorldDy), 19 - (Gear^.FrameTicks div Gear^.Timer div 37), 1, spriteData^.Width, spriteData^.Height, Gear^.Angle) else - //DrawSprite(sprSplash, round(Gear^.X) + WorldDx - 40, round(Gear^.Y) + WorldDy - 58, 19 - (Gear^.FrameTicks div 37)); - DrawTextureF(SpritesData[sprSplash].Texture, Gear^.scale, round(Gear^.X + WorldDx), round(Gear^.Y + WorldDy - ((SpritesData[sprSplash].Height+8)*Gear^.Scale)/2), 19 - (Gear^.FrameTicks div Gear^.Timer div 37), 1, SpritesData[sprSplash].Width, SpritesData[sprSplash].Height); - vgtDroplet: if SuddenDeathDmg then - DrawSprite(sprSDDroplet, round(Gear^.X) + WorldDx - 8, round(Gear^.Y) + WorldDy - 8, Gear^.Frame) - else - DrawSprite(sprDroplet, round(Gear^.X) + WorldDx - 8, round(Gear^.Y) + WorldDy - 8, Gear^.Frame); + //DrawSprite(sprite, round(Gear^.X) + WorldDx - 40, round(Gear^.Y) + WorldDy - 58, 19 - (Gear^.FrameTicks div 37)) + DrawTextureF(spriteData^.Texture, Gear^.scale, round(Gear^.X + WorldDx), round(Gear^.Y + WorldDy - ((spriteData^.Height+8)*Gear^.Scale)/2), 19 - (Gear^.FrameTicks div Gear^.Timer div 37), 1, spriteData^.Width, spriteData^.Height); + end; + vgtDroplet: begin + sprite:= GetSprite(sprDroplet, sprSDDroplet); + DrawSprite(sprite, round(Gear^.X) + WorldDx - 8, round(Gear^.Y) + WorldDy - 8, Gear^.Frame); + end; vgtBubble: DrawSprite(sprBubbles, round(Gear^.X) + WorldDx - 8, round(Gear^.Y) + WorldDy - 8, Gear^.Frame);//(RealTicks div 64 + Gear^.Frame) mod 8); - vgtStraightShot: begin + vgtStraightShot: begin if Gear^.dX < 0 then i:= -1 else @@ -243,30 +249,27 @@ Tint(Gear^.Tint); case Gear^.Kind of (* - vgtFlake: if SuddenDeathDmg then - if vobSDVelocity = 0 then - DrawSprite(sprSDFlake, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame) - else - DrawSpriteRotatedF(sprSDFlake, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, Gear^.Angle) - else - if vobVelocity = 0 then - DrawSprite(sprFlake, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame) - else - DrawSpriteRotatedF(sprFlake, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, Gear^.Angle);*) + vgtFlake: begin + sprite:= GetSprite(sprFlake, sprSDFlake); + if speedlessFlakes then + DrawSprite(sprite, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame) + else + DrawSpriteRotatedF(sprite, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, Gear^.Angle) + end;*) vgtSpeechBubble: begin - if (Gear^.Tex <> nil) and (((Gear^.State = 0) and (Gear^.Hedgehog^.Team <> CurrentTeam)) or (Gear^.State = 1)) then + if (Gear^.Tex <> nil) and (((Gear^.State = 0) and (Gear^.Hedgehog <> nil) and (Gear^.Hedgehog^.Team <> CurrentTeam)) or (Gear^.State = 1)) then begin tinted:= true; Tint($FF, $FF, $FF, $66); DrawTextureCentered(round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Tex) end - else if (Gear^.Tex <> nil) and (((Gear^.State = 0) and (Gear^.Hedgehog^.Team = CurrentTeam)) or (Gear^.State = 2)) then + else if (Gear^.Tex <> nil) and (((Gear^.State = 0) and ((Gear^.Hedgehog = nil) or (Gear^.Hedgehog^.Team = CurrentTeam))) or (Gear^.State = 2)) then DrawTextureCentered(round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Tex); end; vgtSmallDamageTag: DrawTextureCentered(round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Tex); - vgtHealthTag: if Gear^.Tex <> nil then + vgtHealthTag: if Gear^.Tex <> nil then begin - if Gear^.Frame = 0 then + if Gear^.Frame = 0 then DrawTextureCentered(round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Tex) else begin @@ -274,17 +277,25 @@ if Gear^.Angle = 0 then DrawTexture(round(Gear^.X), round(Gear^.Y), Gear^.Tex) else - DrawTexture(round(Gear^.X), round(Gear^.Y), Gear^.Tex, Gear^.Angle); + DrawTexture(round(Gear^.X), round(Gear^.Y), Gear^.Tex, Gear^.Angle); SetScale(zoom) end end; - vgtStraightShot: begin + vgtStraightShot: begin if Gear^.dX < 0 then i:= -1 else i:= 1; DrawTextureRotatedF(SpritesData[TSprite(Gear^.State)].Texture, Gear^.Scale, 0, 0, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Frame, i, SpritesData[TSprite(Gear^.State)].Width, SpritesData[TSprite(Gear^.State)].Height, Gear^.Angle); end; + vgtFeather: begin + if Gear^.FrameTicks < 255 then + begin + Tint($FF, $FF, $FF, Gear^.FrameTicks); + tinted:= true + end; + DrawSpriteRotatedF(sprFeather, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Frame, 1, Gear^.Angle); + end; end; if (cReducedQuality and rqAntiBoom) = 0 then case Gear^.Kind of @@ -330,14 +341,6 @@ end; DrawSpriteRotatedF(sprShell, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Frame, 1, Gear^.Angle); end; - vgtFeather: begin - if Gear^.FrameTicks < 255 then - begin - Tint($FF, $FF, $FF, Gear^.FrameTicks); - tinted:= true - end; - DrawSpriteRotatedF(sprFeather, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Frame, 1, Gear^.Angle); - end; vgtEgg: DrawSpriteRotatedF(sprEgg, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Frame, 1, Gear^.Angle); vgtBeeTrace: begin if Gear^.FrameTicks < $FF then @@ -356,16 +359,13 @@ vgtBulletHit: DrawSpriteRotatedF(sprBulletHit, round(Gear^.X) + WorldDx - 0, round(Gear^.Y) + WorldDy - 0, 7 - (Gear^.FrameTicks div 50), 1, Gear^.Angle); end; case Gear^.Kind of - vgtFlake: if SuddenDeathDmg then - if vobSDVelocity = 0 then - DrawTextureF(SpritesData[sprSDFlake].Texture, Gear^.Scale, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, SpritesData[sprFlake].Width, SpritesData[sprFlake].Height) - else - DrawTextureRotatedF(SpritesData[sprSDFlake].Texture, Gear^.Scale, 0, 0, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, SpritesData[sprFlake].Width, SpritesData[sprFlake].Height, Gear^.Angle) + vgtFlake: begin + spriteData:= GetSpriteData(sprFlake, sprSDFlake); + if speedlessFlakes then + DrawTextureF(spriteData^.Texture, Gear^.Scale, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, spriteData^.Width, spriteData^.Height) else - if vobVelocity = 0 then - DrawTextureF(SpritesData[sprFlake].Texture, Gear^.Scale, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, SpritesData[sprFlake].Width, SpritesData[sprFlake].Height) - else - DrawTextureRotatedF(SpritesData[sprFlake].Texture, Gear^.Scale, 0, 0, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, SpritesData[sprFlake].Width, SpritesData[sprFlake].Height, Gear^.Angle); + DrawTextureRotatedF(spriteData^.Texture, Gear^.Scale, 0, 0, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, spriteData^.Width, spriteData^.Height, Gear^.Angle); + end; vgtCircle: if gear^.Angle = 1 then begin tmp:= Gear^.State / 100; @@ -387,20 +387,17 @@ if Gear^.Tint <> $FFFFFFFF then Tint(Gear^.Tint); case Gear^.Kind of - vgtCloud: if SuddenDeathDmg then - DrawTextureF(SpritesData[sprSDCloud].Texture, Gear^.Scale, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 2, SpritesData[sprCloud].Width, SpritesData[sprCloud].Height) + vgtCloud: begin + spriteData:= GetSpriteData(sprCloud, sprSDCloud); + DrawTextureF(spriteData^.Texture, Gear^.Scale, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, spriteData^.Width, spriteData^.Height); + end; + vgtFlake: begin + spriteData:= GetSpriteData(sprFlake, sprSDFlake); + if speedlessFlakes then + DrawTextureF(spriteData^.Texture, Gear^.Scale, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, spriteData^.Width, spriteData^.Height) else - DrawTextureF(SpritesData[sprCloud].Texture, Gear^.Scale, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 2, SpritesData[sprCloud].Width, SpritesData[sprCloud].Height); - vgtFlake: if SuddenDeathDmg then - if vobSDVelocity = 0 then - DrawTextureF(SpritesData[sprSDFlake].Texture, Gear^.Scale, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, SpritesData[sprFlake].Width, SpritesData[sprFlake].Height) - else - DrawTextureRotatedF(SpritesData[sprSDFlake].Texture, Gear^.Scale, 0, 0, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, SpritesData[sprFlake].Width, SpritesData[sprFlake].Height, Gear^.Angle) - else - if vobVelocity = 0 then - DrawTextureF(SpritesData[sprFlake].Texture, Gear^.Scale, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, SpritesData[sprFlake].Width, SpritesData[sprFlake].Height) - else - DrawTextureRotatedF(SpritesData[sprFlake].Texture, Gear^.Scale, 0, 0, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, SpritesData[sprFlake].Width, SpritesData[sprFlake].Height, Gear^.Angle); + DrawTextureRotatedF(spriteData^.Texture, Gear^.Scale, 0, 0, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, spriteData^.Width, spriteData^.Height, Gear^.Angle); + end; end; if (Gear^.Tint <> $FFFFFFFF) then untint; @@ -415,20 +412,17 @@ if Gear^.Tint <> $FFFFFFFF then Tint(Gear^.Tint); case Gear^.Kind of - vgtCloud: if SuddenDeathDmg then - DrawSprite(sprSDCloud, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame) - else - DrawSprite(sprCloud, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame); - vgtFlake: if SuddenDeathDmg then - if vobSDVelocity = 0 then - DrawSprite(sprSDFlake, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame) - else - DrawSpriteRotatedF(sprSDFlake, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, Gear^.Angle) - else - if vobVelocity = 0 then - DrawSprite(sprFlake, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame) - else - DrawSpriteRotatedF(sprFlake, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, Gear^.Angle); + vgtCloud: begin + sprite:= GetSprite(sprCloud, sprSDCloud); + DrawSprite(sprite, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame); + end; + vgtFlake: begin + sprite:= GetSprite(sprFlake, sprSDFlake); + if speedlessFlakes then + DrawSprite(sprite, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame) + else + DrawSpriteRotatedF(sprite, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, Gear^.Angle); + end; end; if (Gear^.Tint <> $FFFFFFFF) then untint; @@ -443,16 +437,15 @@ if Gear^.Tint <> $FFFFFFFF then Tint(Gear^.Tint); case Gear^.Kind of - vgtFlake: if SuddenDeathDmg then - if vobSDVelocity = 0 then - DrawSprite(sprSDFlake, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame) - else - DrawSpriteRotatedF(sprSDFlake, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, Gear^.Angle) + vgtFlake: begin + sprite:= GetSprite(sprFlake, sprSDFlake); + if speedlessFlakes then + DrawSprite(sprite, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame) else - if vobVelocity = 0 then - DrawSprite(sprFlake, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame) - else - DrawSpriteRotatedF(sprFlake, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, Gear^.Angle); + DrawSpriteRotatedF(sprite, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy + SkyOffset, Gear^.Frame, 1, Gear^.Angle) + end; + vgtNoPlaceWarn: + DrawTexture(round(Gear^.X) + WorldDx - round(Gear^.Tex^.w * Gear^.Scale) div 2, round(Gear^.Y) + WorldDy - round(Gear^.Tex^.h * Gear^.Scale) div 2, Gear^.Tex, Gear^.Scale); end; if (Gear^.Tint <> $FFFFFFFF) then untint; @@ -515,11 +508,11 @@ vg:= VisualGearLayers[i]; while vg <> nil do if vg^.Kind = vgtFlake then - begin - tmp:= vg^.NextGear; - DeleteVisualGear(vg); - vg:= tmp - end + begin + tmp:= vg^.NextGear; + DeleteVisualGear(vg); + vg:= tmp + end else vg:= vg^.NextGear; end; if hasBorder or (not cSnow) then diff -r 31570b766315 -r ed5a6478e710 hedgewars/uVisualGearsHandlers.pas --- a/hedgewars/uVisualGearsHandlers.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uVisualGearsHandlers.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) (* @@ -24,15 +24,15 @@ * => The usage of safe functions or data types (e.g. GetRandom() or hwFloat) * is usually not necessary and therefore undesirable. *) - -{$INCLUDE "options.inc"} - + +{$INCLUDE "options.inc"} + unit uVisualGearsHandlers; interface -uses uTypes; +uses uTypes, uGears; -var doStepHandlers: array[TVisualGearType] of TVGearStepProcedure; +var doStepVGHandlers: array[TVisualGearType] of TVGearStepProcedure; procedure doStepFlake(Gear: PVisualGear; Steps: Longword); procedure doStepBeeTrace(Gear: PVisualGear; Steps: Longword); @@ -75,48 +75,57 @@ procedure initModule; implementation -uses uVariables, Math, uConsts, uVisualGearsList, uFloat, uSound, uRenderUtils, uWorld; +uses uCollisions, uVariables, Math, uConsts, uVisualGearsList, uFloat, uSound, uRenderUtils, uWorld; procedure doStepFlake(Gear: PVisualGear; Steps: Longword); var sign: real; moved: boolean; + vfc, vft: LongWord; begin if vobCount = 0 then exit; sign:= 1; with Gear^ do begin - inc(FrameTicks, Steps); - if not SuddenDeathDmg and (FrameTicks > vobFrameTicks) then + + X:= X + (cWindSpeedf * 400 + dX + tdX) * Steps * Gear^.Scale; + + if SuddenDeathDmg then begin - dec(FrameTicks, vobFrameTicks); - inc(Frame); - if Frame = vobFramesCount then - Frame:= 0 + Y:= Y + (dY + tdY + cGravityf * vobSDFallSpeed) * Steps * Gear^.Scale; + vfc:= vobSDFramesCount; + vft:= vobSDFrameTicks; end - else if SuddenDeathDmg and (FrameTicks > vobSDFrameTicks) then + else begin - dec(FrameTicks, vobSDFrameTicks); - inc(Frame); - if Frame = vobSDFramesCount then - Frame:= 0 + Y:= Y + (dY + tdY + cGravityf * vobFallSpeed) * Steps * Gear^.Scale; + vfc:= vobFramesCount; + vft:= vobFrameTicks; end; - X:= X + (cWindSpeedf * 400 + dX + tdX) * Steps * Gear^.Scale; - if SuddenDeathDmg then - Y:= Y + (dY + tdY + cGravityf * vobSDFallSpeed) * Steps * Gear^.Scale - else - Y:= Y + (dY + tdY + cGravityf * vobFallSpeed) * Steps * Gear^.Scale; + + if vft > 0 then + begin + inc(FrameTicks, Steps); + if FrameTicks > vft then + begin + dec(FrameTicks, vft); + inc(Frame); + if Frame = vfc then + Frame:= 0 + end; + end; + Angle:= Angle + dAngle * Steps; if Angle > 360 then Angle:= Angle - 360 else if Angle < - 360 then Angle:= Angle + 360; - - + + if (round(X) >= cLeftScreenBorder) and (round(X) <= cRightScreenBorder) - and (round(Y) - 75 <= LAND_HEIGHT) + and (round(Y) - 250 <= LAND_HEIGHT) and (Timer > 0) and (Timer-Steps > 0) then begin if tdX > 0 then @@ -143,23 +152,31 @@ X:= X + cScreenSpace; moved:= true end - else - if round(X) > cRightScreenBorder then - begin - X:= X - cScreenSpace; - moved:= true - end; + else if round(X) > cRightScreenBorder then + begin + X:= X - cScreenSpace; + moved:= true + end; // 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 + if (Gear^.Layer = 2) and (round(Y) - 400 > LAND_HEIGHT) and (cGravityf >= 0) then begin X:= cLeftScreenBorder + random(cScreenSpace); - Y:= Y - (1024 + 250 + random(50)); // TODO - configure in theme (jellies for example could use limited range) + Y:= Y-(1024 + 400 + random(50)); // TODO - configure in theme (jellies for example could use limited range) moved:= true end - else if (Gear^.Layer <> 2) and (round(Y) + 50 > LAND_HEIGHT) then + else if (Gear^.Layer <> 2) and (round(Y) - 150 > LAND_HEIGHT) and (cGravityf >= 0) then begin X:= cLeftScreenBorder + random(cScreenSpace); - Y:= Y - (1024 + random(25)); + Y:= Y-(1024 + 200 + random(50)); + moved:= true + end + else if (round(Y) < LAND_HEIGHT-1200) and (cGravityf < 0) then // gravity can make flakes move upwards + begin + X:= cLeftScreenBorder + random(cScreenSpace); + if Gear^.Layer = 2 then + Y:= Y+(1024 + 150 + random(100)) + else + Y:= Y+(1024 + random(50)); moved:= true end; if moved then @@ -249,7 +266,9 @@ //////////////////////////////////////////////////////////////////////////////// procedure doStepLineTrail(Gear: PVisualGear; Steps: Longword); begin +{$IFNDEF PAS2C} Steps := Steps; +{$ENDIF} if Gear^.Timer <= Steps then DeleteVisualGear(Gear) else @@ -343,7 +362,7 @@ Gear^.dX := Gear^.dX / (1.001 * Steps); Gear^.dY := Gear^.dY / (1.001 * Steps); -if (Gear^.FrameTicks <= Steps) or (round(Gear^.Y) < cWaterLine) then +if (Gear^.FrameTicks <= Steps) or (not CheckCoordInWater(round(Gear^.X), round(Gear^.Y))) then DeleteVisualGear(Gear) else dec(Gear^.FrameTicks, Steps) @@ -352,7 +371,9 @@ //////////////////////////////////////////////////////////////////////////////// procedure doStepSteam(Gear: PVisualGear; Steps: Longword); begin -Gear^.X:= Gear^.X + (cWindSpeedf * 100 + Gear^.dX) * Steps; +if ((cWindSpeedf > 0) and ( leftX > Gear^.X)) +or ((cWindSpeedf < 0) and (rightX < Gear^.X)) then + Gear^.X:= Gear^.X + (cWindSpeedf * 100 + Gear^.dX) * Steps; Gear^.Y:= Gear^.Y - cDrownSpeedf * Steps; if Gear^.FrameTicks <= Steps then @@ -494,7 +515,8 @@ procedure doStepTeamHealthSorterWork(Gear: PVisualGear; Steps: Longword); var i, t, h: LongInt; begin -for t:= 1 to min(Steps, Gear^.Timer) do +if currsorter = Gear then + for t:= 1 to min(Steps, Gear^.Timer) do begin dec(Gear^.Timer); if (Gear^.Timer and 15) = 0 then @@ -528,7 +550,9 @@ b: boolean; t, h: LongInt; begin +{$IFNDEF PAS2C} Steps:= Steps; // avoid compiler hint +{$ENDIF} for t:= 0 to Pred(TeamsCount) do with thexchar[t] do @@ -583,43 +607,60 @@ //////////////////////////////////////////////////////////////////////////////// procedure doStepSpeechBubbleWork(Gear: PVisualGear; Steps: Longword); +var realgear: PGear; begin if Gear^.Timer > Steps then dec(Gear^.Timer, Steps) else Gear^.Timer:= 0; - -if (Gear^.Hedgehog^.Gear <> nil) then +realgear:= nil; +if Gear^.Frame <> 0 then // use a non-hedgehog gear - a lua trick that hopefully won't be overused + begin + realgear:= GearByUID(Gear^.Frame); + if realgear <> nil then + begin + Gear^.X:= hwFloat2Float(realgear^.X) + (Gear^.Tex^.w div 2 - Gear^.Tag); + Gear^.Y:= hwFloat2Float(realgear^.Y) - (realgear^.Radius + Gear^.Tex^.h); + end + end +else if Gear^.Hedgehog^.Gear <> nil then begin Gear^.X:= hwFloat2Float(Gear^.Hedgehog^.Gear^.X) + (Gear^.Tex^.w div 2 - Gear^.Tag); - Gear^.Y:= hwFloat2Float(Gear^.Hedgehog^.Gear^.Y) - (16 + Gear^.Tex^.h); + Gear^.Y:= hwFloat2Float(Gear^.Hedgehog^.Gear^.Y) - (cHHRadius + Gear^.Tex^.h); end; -if Gear^.Timer = 0 then +if (Gear^.Timer = 0) or ((realgear = nil) and (Gear^.Frame <> 0)) then begin - if Gear^.Hedgehog^.SpeechGear = Gear then + if (Gear^.Hedgehog <> nil) and (Gear^.Hedgehog^.SpeechGear = Gear) then Gear^.Hedgehog^.SpeechGear:= nil; DeleteVisualGear(Gear) end; end; procedure doStepSpeechBubble(Gear: PVisualGear; Steps: Longword); +var realgear: PGear; begin -Steps:= Steps; // avoid compiler hint -with Gear^.Hedgehog^ do - if SpeechGear <> nil then - SpeechGear^.Timer:= 0; +{$IFNDEF PAS2C} +Steps:= Steps; // avoid compiler hint +{$ENDIF} +if Gear^.Frame <> 0 then + realgear:= GearByUID(Gear^.FrameTicks) +else + begin + with Gear^.Hedgehog^ do + if SpeechGear <> nil then + SpeechGear^.Timer:= 0; + realgear:= Gear^.Hedgehog^.Gear; + Gear^.Hedgehog^.SpeechGear:= Gear; + end; -Gear^.Hedgehog^.SpeechGear:= Gear; +if realgear <> nil then + case Gear^.FrameTicks of + 1: Gear^.Tag:= SpritesData[sprSpeechTail].Width-37+realgear^.Radius; + 2: Gear^.Tag:= SpritesData[sprThoughtTail].Width-29+realgear^.Radius; + 3: Gear^.Tag:= SpritesData[sprShoutTail].Width-19+realgear^.Radius; + end; Gear^.Timer:= max(LongInt(Length(Gear^.Text)) * 150, 3000); - -Gear^.Tex:= RenderSpeechBubbleTex(Gear^.Text, Gear^.FrameTicks, fnt16); - -// FrameTicks cannot hold negative values -case Gear^.FrameTicks of - 1: Gear^.Tag:= SpritesData[sprSpeechTail].Width-28; - 2: Gear^.Tag:= SpritesData[sprThoughtTail].Width-20; - 3: Gear^.Tag:= SpritesData[sprShoutTail].Width-10; - end; +Gear^.Tex:= RenderSpeechBubbleTex(ansistring(Gear^.Text), Gear^.FrameTicks, fnt16); Gear^.doStep:= @doStepSpeechBubbleWork; @@ -655,9 +696,9 @@ str(Gear^.State, s); if Gear^.Hedgehog <> nil then - Gear^.Tex:= RenderStringTex(s, Gear^.Hedgehog^.Team^.Clan^.Color, fnt16) + Gear^.Tex:= RenderStringTex(ansistring(s), Gear^.Hedgehog^.Team^.Clan^.Color, fnt16) else - Gear^.Tex:= RenderStringTex(s, cWhiteColor, fnt16); + Gear^.Tex:= RenderStringTex(ansistring(s), cWhiteColor, fnt16); Gear^.doStep:= @doStepHealthTagWork; @@ -708,10 +749,10 @@ begin gX:= round(Gear^.X); gY:= round(Gear^.Y); -for i:= 0 to 31 do +for i:= 0 to 31 do begin vg:= AddVisualGear(gX, gY, vgtFire); - if vg <> nil then + if vg <> nil then begin vg^.State:= gstTmpFlag; inc(vg^.FrameTicks, vg^.FrameTicks) @@ -752,10 +793,10 @@ gX:= round(Gear^.X); gY:= round(Gear^.Y); AddVisualGear(gX, gY, vgtSmokeRing); -for i:= 0 to 46 do +for i:= 0 to 46 do begin vg:= AddVisualGear(gX, gY, vgtFire); - if vg <> nil then + if vg <> nil then begin vg^.State:= gstTmpFlag; inc(vg^.FrameTicks, vg^.FrameTicks) @@ -768,9 +809,12 @@ Gear^.doStep:= @doStepBigExplosionWork; if Steps > 1 then Gear^.doStep(Gear, Steps-1); + +{$IFNDEF PAS2C} with mobileRecord do if (performRumble <> nil) and (not fastUntilLag) then performRumble(kSystemSoundID_Vibrate); +{$ENDIF} end; procedure doStepChunk(Gear: PVisualGear; Steps: Longword); @@ -829,31 +873,47 @@ end; //////////////////////////////////////////////////////////////////////////////// +var + currwindbar: PVisualGear = nil; + +procedure doStepSmoothWindBarWork(Gear: PVisualGear; Steps: Longword); +begin + if currwindbar = Gear then + begin + inc(Gear^.Timer, Steps); + + while Gear^.Timer >= 10 do + begin + dec(Gear^.Timer, 10); + if WindBarWidth < Gear^.Tag then + inc(WindBarWidth) + else if WindBarWidth > Gear^.Tag then + dec(WindBarWidth); + end; + if cWindspeedf > Gear^.dAngle then + begin + cWindspeedf := cWindspeedf - Gear^.Angle*Steps; + if cWindspeedf < Gear^.dAngle then cWindspeedf:= Gear^.dAngle; + end + else if cWindspeedf < Gear^.dAngle then + begin + cWindspeedf := cWindspeedf + Gear^.Angle*Steps; + if cWindspeedf > Gear^.dAngle then cWindspeedf:= Gear^.dAngle; + end; + end; + + if ((WindBarWidth = Gear^.Tag) and (cWindspeedf = Gear^.dAngle)) or (currwindbar <> Gear) then + begin + if currwindbar = Gear then currwindbar:= nil; + DeleteVisualGear(Gear) + end +end; + procedure doStepSmoothWindBar(Gear: PVisualGear; Steps: Longword); begin -inc(Gear^.Timer, Steps); - -while Gear^.Timer >= 10 do - begin - dec(Gear^.Timer, 10); - if WindBarWidth < Gear^.Tag then - inc(WindBarWidth) - else if WindBarWidth > Gear^.Tag then - dec(WindBarWidth); - end; -if cWindspeedf > Gear^.dAngle then - begin - cWindspeedf := cWindspeedf - Gear^.Angle*Steps; - if cWindspeedf < Gear^.dAngle then cWindspeedf:= Gear^.dAngle; - end -else if cWindspeedf < Gear^.dAngle then - begin - cWindspeedf := cWindspeedf + Gear^.Angle*Steps; - if cWindspeedf > Gear^.dAngle then cWindspeedf:= Gear^.dAngle; - end; - -if (WindBarWidth = Gear^.Tag) and (cWindspeedf = Gear^.dAngle) then - DeleteVisualGear(Gear) + currwindbar:= Gear; + Gear^.doStep:= @doStepSmoothWindBarWork; + doStepSmoothWindBarWork(Gear, Steps) end; //////////////////////////////////////////////////////////////////////////////// procedure doStepStraightShot(Gear: PVisualGear; Steps: Longword); @@ -861,16 +921,38 @@ Gear^.X:= Gear^.X + Gear^.dX * Steps; Gear^.Y:= Gear^.Y - Gear^.dY * Steps; +Gear^.dY:= Gear^.dY + Gear^.tdY * Steps; +Gear^.dX:= Gear^.dX + Gear^.tdX * Steps; + if Gear^.FrameTicks <= Steps then DeleteVisualGear(Gear) else begin dec(Gear^.FrameTicks, Steps); - if (Gear^.FrameTicks < 501) and (Gear^.FrameTicks mod 5 = 0) then + if (Gear^.FrameTicks < 501) and (Gear^.FrameTicks mod 5 = 0) then Gear^.Tint:= (Gear^.Tint and $FFFFFF00) or (((Gear^.Tint and $000000FF) * Gear^.FrameTicks) div 500) end end; +//////////////////////////////////////////////////////////////////////////////// +procedure doStepNoPlaceWarn(Gear: PVisualGear; Steps: Longword); +begin + +if Gear^.FrameTicks <= Steps then + DeleteVisualGear(Gear) +else + begin + // age + dec(Gear^.FrameTicks, Steps); + // toggle between orange and red every few ticks + if (Gear^.FrameTicks div 256) mod 2 = 0 then + Gear^.Tint:= $FF400000 + else + Gear^.Tint:= $FF000000; + // fade out alpha + Gear^.Tint:= (Gear^.Tint and (not $FF)) or (255 * Gear^.FrameTicks div 3000); + end +end; const handlers: array[TVisualGearType] of TVGearStepProcedure = ( @@ -906,12 +988,13 @@ @doStepBulletHit, @doStepCircle, @doStepSmoothWindBar, - @doStepStraightShot + @doStepStraightShot, + @doStepNoPlaceWarn ); procedure initModule; begin - doStepHandlers:= handlers + doStepVGHandlers:= handlers end; end. diff -r 31570b766315 -r ed5a6478e710 hedgewars/uVisualGearsList.pas --- a/hedgewars/uVisualGearsList.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uVisualGearsList.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} @@ -29,17 +29,21 @@ procedure DeleteVisualGear(Gear: PVisualGear); function VisualGearByUID(uid : Longword) : PVisualGear; -const +const cExplFrameTicks = 110; var VGCounter: LongWord; VisualGearLayers: array[0..6] of PVisualGear; implementation -uses uFloat, uVariables, uConsts, uTextures, uVisualGearsHandlers; +uses uCollisions, uFloat, uVariables, uConsts, uTextures, uVisualGearsHandlers; function AddVisualGear(X, Y: LongInt; Kind: TVisualGearType): PVisualGear; inline; begin + // adjust some visual gear types if underwater + if CheckCoordInWater(X, Y) and ((Kind = vgtBeeTrace) or (Kind = vgtSmokeTrace) or (Kind = vgtEvilTrace)) then + Kind:= vgtBubble; + AddVisualGear:= AddVisualGear(X, Y, Kind, 0, false, -1); end; @@ -74,8 +78,9 @@ vgtSmokeTrace, vgtEvilTrace, vgtNote, + vgtFeather, vgtSmoothWindBar])) then - + exit; inc(VGCounter); @@ -84,11 +89,9 @@ gear^.X:= real(X); gear^.Y:= real(Y); gear^.Kind := Kind; -gear^.doStep:= doStepHandlers[Kind]; -gear^.State:= 0; +gear^.doStep:= doStepVGHandlers[Kind]; gear^.Tint:= $FFFFFFFF; gear^.uid:= VGCounter; -gear^.Layer:= 0; with gear^ do case Kind of @@ -100,12 +103,14 @@ Scale:= 1.0; if SuddenDeathDmg then begin - FrameTicks:= random(vobSDFrameTicks); + if vobSDFrameTicks > 0 then + FrameTicks:= random(vobSDFrameTicks); Frame:= random(vobSDFramesCount); end else begin - FrameTicks:= random(vobFrameTicks); + if vobFrameTicks > 0 then + FrameTicks:= random(vobFrameTicks); Frame:= random(vobFramesCount); end; Angle:= random(360); @@ -289,7 +294,7 @@ if random(2) = 0 then dx := -dx; end; - vgtNote: + vgtNote: begin dx:= 0.005 * (random(15) + 10); dy:= -0.001 * (random(40) + 20); @@ -306,7 +311,7 @@ Frame:= 7; Angle:= 0; end; -vgtSmoothWindBar: +vgtSmoothWindBar: begin Angle:= hwFloat2Float(cMaxWindSpeed)*2 / 1440; // seems rate below is supposed to change wind bar at 1px per 10ms. Max time, 1440ms. This tries to match the rate of change Tag:= hwRound(cWindSpeed * 72 / cMaxWindSpeed); @@ -324,6 +329,12 @@ FrameTicks:= random(750) + 1250; State:= ord(sprSnowDust); end; + vgtNoPlaceWarn: + begin + FrameTicks:= 2000; + Tint:= $FF0000FF; + Scale:= 1.0; + end; end; if State <> 0 then @@ -332,7 +343,7 @@ case Gear^.Kind of vgtFlake: if cFlattenFlakes then gear^.Layer:= 0 - else if random(3) = 0 then + else if random(3) = 0 then begin gear^.Scale:= 0.5; gear^.Layer:= 0 // 33% - far back @@ -365,6 +376,7 @@ gear^.Scale:= 0.4; gear^.Layer:= 4 end; + vgtNoPlaceWarn: gear^.Layer:= 6; // 0: this layer is very distant in the background when in stereo vgtTeamHealthSorter, @@ -388,6 +400,7 @@ vgtSmallDamageTag, vgtHealthTag, vgtStraightShot, + vgtFeather, vgtChunk: gear^.Layer:= 3; // 2: this layer is outside the screen when stereo @@ -398,7 +411,6 @@ vgtSteam, vgtAmmo, vgtShell, - vgtFeather, vgtEgg, vgtBeeTrace, vgtSmokeRing, @@ -421,8 +433,7 @@ procedure DeleteVisualGear(Gear: PVisualGear); begin - FreeTexture(Gear^.Tex); - Gear^.Tex:= nil; + FreeAndNilTexture(Gear^.Tex); if Gear^.NextGear <> nil then Gear^.NextGear^.PrevGear:= Gear^.PrevGear; diff -r 31570b766315 -r ed5a6478e710 hedgewars/uWorld.pas --- a/hedgewars/uWorld.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uWorld.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,11 +13,10 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} -{$IF GLunit = GL}{$DEFINE GLunit:=GL,GLext}{$ENDIF} unit uWorld; interface @@ -40,6 +39,7 @@ procedure animateWidget(widget: POnScreenWidget; fade, showWidget: boolean); procedure MoveCamera; procedure onFocusStateChanged; +procedure updateCursorVisibility; implementation uses @@ -52,7 +52,6 @@ , uVisualGears , uChat , uLandTexture - , GLunit , uVariables , uUtils , uTextures @@ -66,8 +65,7 @@ {$ENDIF} ; -var cWaveWidth, cWaveHeight: LongInt; - AMShiftTargetX, AMShiftTargetY, AMShiftX, AMShiftY, SlotsNum: LongInt; +var AMShiftTargetX, AMShiftTargetY, AMShiftX, AMShiftY, SlotsNum: LongInt; AMAnimStartTime, AMState : LongInt; AMAnimState: Single; tmpSurface: PSDL_Surface; @@ -79,7 +77,6 @@ amSel: TAmmoType = amNothing; missionTex: PTexture; missionTimer: LongInt; - stereoDepth: GLfloat; isFirstFrame: boolean; AMAnimType: LongInt; recTexture: PTexture; @@ -121,18 +118,22 @@ function AddGoal(s: ansistring; gf: longword; si: TGoalStrId; i: LongInt): ansistring; var t: ansistring; begin +{$IFNDEF PAS2C} if (GameFlags and gf) <> 0 then begin t:= inttostr(i); s:= s + FormatA(trgoal[si], t) + '|' end; +{$ENDIF} AddGoal:= s; end; function AddGoal(s: ansistring; gf: longword; si: TGoalStrId): ansistring; begin +{$IFNDEF PAS2C} if (GameFlags and gf) <> 0 then s:= s + trgoal[si] + '|'; +{$ENDIF} AddGoal:= s; end; @@ -212,10 +213,10 @@ end; // if the string has been set, show it for (default timeframe) seconds -if g <> '' then +if length(g) > 0 then ShowMission(trgoal[gidCaption], trgoal[gidSubCaption], g, 1, 0); -cWaveWidth:= SpritesData[sprWater].Width; +//cWaveWidth:= SpritesData[sprWater].Width; //cWaveHeight:= SpritesData[sprWater].Height; cWaveHeight:= 32; @@ -225,7 +226,7 @@ prevPoint.Y:= cScreenHeight div 2; //prevTargetPoint.X:= 0; //prevTargetPoint.Y:= 0; -WorldDx:= -(LAND_WIDTH div 2) + cScreenWidth div 2; +WorldDx:= -(LongInt(leftX + (playWidth div 2))); // -(LAND_WIDTH div 2);// + cScreenWidth div 2; WorldDy:= -(LAND_HEIGHT - (playHeight div 2)) + (cScreenHeight div 2); //aligns it to the bottom of the screen, minus the border @@ -401,14 +402,12 @@ // for uStore texture resetting procedure ResetWorldTex; begin - FreeTexture(fpsTexture); - fpsTexture:= nil; - FreeTexture(timeTexture); - timeTexture:= nil; - FreeTexture(missionTex); - missionTex:= nil; - FreeTexture(recTexture); - recTexture:= nil; + FreeAndNilTexture(fpsTexture); + FreeAndNilTexture(timeTexture); + FreeAndNilTexture(missionTex); + FreeAndNilTexture(recTexture); + FreeAndNilTexture(AmmoMenuTex); + AmmoMenuInvalidated:= true; end; function GetAmmoMenuTexture(Ammo: PHHAmmo): PTexture; @@ -419,6 +418,8 @@ AMRect: TSDL_Rect; {$IFDEF USE_AM_NUMCOLUMN}tmpsurf: PSDL_Surface;{$ENDIF} begin + if cOnlyStats then exit(nil); + SlotsNum:= 0; for i:= 0 to cMaxSlotIndex do if((i = 0) and (Ammo^[i,1].Count > 0)) or ((i <> 0) and (Ammo^[i,0].Count > 0)) then @@ -441,14 +442,14 @@ AmmoRect.w:= (BORDERSIZE*2) + (SlotsNumX * AMSlotSize) + (SlotsNumX-1); AmmoRect.h:= (BORDERSIZE*2) + (SlotsNumY * AMSlotSize) + (SlotsNumY-1); amSurface := SDL_CreateRGBSurface(SDL_SWSURFACE, AmmoRect.w, AmmoRect.h, 32, RMask, GMask, BMask, AMask); - + AMRect.x:= BORDERSIZE; AMRect.y:= BORDERSIZE; AMRect.w:= AmmoRect.w - (BORDERSIZE*2); AMRect.h:= AmmoRect.h - (BORDERSIZE*2); SDL_FillRect(amSurface, @AMRect, SDL_MapRGB(amSurface^.format, 0,0,0)); - + x:= AMRect.x; y:= AMRect.y; for i:= 0 to cMaxSlotIndex do @@ -482,25 +483,25 @@ AMFrame:= LongInt(Ammo^[i,t].AmmoType) - 1; if STurns >= 0 then //weapon not usable yet, draw grayed out with turns remaining begin - DrawSpriteFrame2Surf(sprAMAmmosBW, amSurface, x + AMSlotPadding, + DrawSpriteFrame2Surf(sprAMAmmosBW, amSurface, x + AMSlotPadding, y + AMSlotPadding, AMFrame); if STurns < 100 then - DrawSpriteFrame2Surf(sprTurnsLeft, amSurface, - x + AMSlotSize-16, + DrawSpriteFrame2Surf(sprTurnsLeft, amSurface, + x + AMSlotSize-16, y + AMSlotSize + 1 - 16, STurns); end else //draw colored version begin - DrawSpriteFrame2Surf(sprAMAmmos, amSurface, x + AMSlotPadding, + DrawSpriteFrame2Surf(sprAMAmmos, amSurface, x + AMSlotPadding, y + AMSlotPadding, AMFrame); end; {$IFDEF USE_LANDSCAPE_AMMOMENU} - inc(y, AMSlotSize + 1); //the plus one is for the border + inc(y, AMSlotSize + 1); //the plus one is for the border {$ELSE} - inc(x, AMSlotSize + 1); + inc(x, AMSlotSize + 1); {$ENDIF} - end; - end; + end; + end; {$IFDEF USE_LANDSCAPE_AMMOMENU} inc(x, AMSlotSize + 1); {$ELSE} @@ -509,7 +510,7 @@ end; for i:= 1 to SlotsNumX -1 do -DrawLine2Surf(amSurface, i * (AMSlotSize+1)+1, BORDERSIZE, i * (AMSlotSize+1)+1, AMRect.h + BORDERSIZE - AMSlotSize - 2,160,160,160); +DrawLine2Surf(amSurface, i * (AMSlotSize+1)+1, BORDERSIZE, i * (AMSlotSize+1)+1, AMRect.h + BORDERSIZE - AMSlotSize - 2,160,160,160); for i:= 1 to SlotsNumY -1 do DrawLine2Surf(amSurface, BORDERSIZE, i * (AMSlotSize+1)+1, AMRect.w + BORDERSIZE, i * (AMSlotSize+1)+1,160,160,160); @@ -554,11 +555,11 @@ exit end; -//Init the menu -if(AmmoMenuInvalidated) then +//Init the menu +if(AmmoMenuInvalidated) then begin AmmoMenuInvalidated:= false; - FreeTexture(AmmoMenuTex); + FreeAndNilTexture(AmmoMenuTex); AmmoMenuTex:= GetAmmoMenuTexture(Ammo); {$IFDEF USE_LANDSCAPE_AMMOMENU} @@ -611,7 +612,7 @@ begin AMShiftX:= Round(AMShiftTargetX * (1 - AMAnimState)); AMShiftY:= Round(AMShiftTargetY * (1 - AMAnimState)); - if (AMAnimType and AMTypeMaskAlpha) <> 0 then + if (AMAnimType and AMTypeMaskAlpha) <> 0 then Tint($FF, $ff, $ff, Round($ff * AMAnimState)); end else @@ -636,10 +637,10 @@ begin AMShiftX:= Round(AMShiftTargetX * AMAnimState); AMShiftY:= Round(AMShiftTargetY * AMAnimState); - if (AMAnimType and AMTypeMaskAlpha) <> 0 then + if (AMAnimType and AMTypeMaskAlpha) <> 0 then Tint($FF, $ff, $ff, Round($ff * (1-AMAnimState))); end - else + else begin AMShiftX:= AMShiftTargetX; AMShiftY:= AMShiftTargetY; @@ -648,11 +649,11 @@ AMState:= AMHidden; end; end; - + DrawTexture(AmmoRect.x + AMShiftX, AmmoRect.y + AMShiftY, AmmoMenuTex); -if ((AMState = AMHiding) or (AMState = AMShowingUp)) and ((AMAnimType and AMTypeMaskAlpha) <> 0 )then - Tint($FF, $ff, $ff, $ff); +if ((AMState = AMHiding) or (AMState = AMShowingUp)) and ((AMAnimType and AMTypeMaskAlpha) <> 0 )then + untint; Pos:= -1; Slot:= -1; @@ -672,15 +673,15 @@ begin if (CursorPoint.Y <= (cScreenHeight - AmmoRect.y) - ( g * (AMSlotSize+1))) and (CursorPoint.Y > (cScreenHeight - AmmoRect.y) - ((g+1) * (AMSlotSize+1))) and - (CursorPoint.X > AmmoRect.x + ( c * (AMSlotSize+1))) and + (CursorPoint.X > AmmoRect.x + ( c * (AMSlotSize+1))) and (CursorPoint.X <= AmmoRect.x + ((c+1) * (AMSlotSize+1))) then begin Slot:= i; Pos:= t; STurns:= Ammoz[Ammo^[i, t].AmmoType].SkipTurns - CurrentTeam^.Clan^.TurnNumber; if (STurns < 0) and (AMShiftX = 0) and (AMShiftY = 0) then - DrawSprite(sprAMSlot, - AmmoRect.x + BORDERSIZE + (c * (AMSlotSize+1)) + AMSlotPadding, + DrawSprite(sprAMSlot, + AmmoRect.x + BORDERSIZE + (c * (AMSlotSize+1)) + AMSlotPadding, AmmoRect.y + BORDERSIZE + (g * (AMSlotSize+1)) + AMSlotPadding -1, 0); end; inc(g); @@ -702,15 +703,15 @@ begin if (CursorPoint.Y <= (cScreenHeight - AmmoRect.y) - ( c * (AMSlotSize+1))) and (CursorPoint.Y > (cScreenHeight - AmmoRect.y) - ((c+1) * (AMSlotSize+1))) and - (CursorPoint.X > AmmoRect.x + ( g * (AMSlotSize+1))) and + (CursorPoint.X > AmmoRect.x + ( g * (AMSlotSize+1))) and (CursorPoint.X <= AmmoRect.x + ((g+1) * (AMSlotSize+1))) then begin Slot:= i; Pos:= t; STurns:= Ammoz[Ammo^[i, t].AmmoType].SkipTurns - CurrentTeam^.Clan^.TurnNumber; if (STurns < 0) and (AMShiftX = 0) and (AMShiftY = 0) then - DrawSprite(sprAMSlot, - AmmoRect.x + BORDERSIZE + (g * (AMSlotSize+1)) + AMSlotPadding, + DrawSprite(sprAMSlot, + AmmoRect.x + BORDERSIZE + (g * (AMSlotSize+1)) + AMSlotPadding, AmmoRect.y + BORDERSIZE + (c * (AMSlotSize+1)) + AMSlotPadding -1, 0); end; inc(g); @@ -741,11 +742,11 @@ bShowAmmoMenu:= false; SetWeapon(Ammo^[Slot, Pos].AmmoType); bSelected:= false; - FreeWeaponTooltip; + FreeAndNilTexture(WeaponTooltipTex); {$IFDEF USE_TOUCH_INTERFACE}//show the aiming buttons + animation if (Ammo^[Slot, Pos].Propz and ammoprop_NeedUpDown) <> 0 then begin - if not(arrowUp.show) then + if (not arrowUp.show) then begin animateWidget(@arrowUp, true, true); animateWidget(@arrowDown, true, true); @@ -764,11 +765,11 @@ end end else - FreeWeaponTooltip; + FreeAndNilTexture(WeaponTooltipTex); if (WeaponTooltipTex <> nil) and (AMShiftX = 0) and (AMShiftY = 0) then {$IFDEF USE_LANDSCAPE_AMMOMENU} - if not isPhone() then + if (not isPhone()) then ShowWeaponTooltip(-WeaponTooltipTex^.w div 2, AmmoRect.y - WeaponTooltipTex^.h - AMSlotSize); {$ELSE} ShowWeaponTooltip(AmmoRect.x - WeaponTooltipTex^.w - 3, Min(AmmoRect.y + 1, cScreenHeight - WeaponTooltipTex^.h - 40)); @@ -781,127 +782,6 @@ {$ENDIF} end; -procedure DrawWater(Alpha: byte; OffsetY: LongInt); -var VertexBuffer: array [0..3] of TVertex2f; - r: TSDL_Rect; - lw, lh: GLfloat; -begin -if SuddenDeathDmg then - begin - SDWaterColorArray[0].a := Alpha; - SDWaterColorArray[1].a := Alpha; - SDWaterColorArray[2].a := Alpha; - SDWaterColorArray[3].a := Alpha - end -else - begin - WaterColorArray[0].a := Alpha; - WaterColorArray[1].a := Alpha; - WaterColorArray[2].a := Alpha; - WaterColorArray[3].a := Alpha - end; - -lw:= cScreenWidth / cScaleFactor; -lh:= trunc(cScreenHeight / cScaleFactor) + cScreenHeight div 2 + 16; - - // Water -r.y:= OffsetY + WorldDy + cWaterLine; -if WorldDy < trunc(cScreenHeight / cScaleFactor) + cScreenHeight div 2 - cWaterLine then - begin - if r.y < 0 then - r.y:= 0; - - glDisable(GL_TEXTURE_2D); - VertexBuffer[0].X:= -lw; - VertexBuffer[0].Y:= r.y; - VertexBuffer[1].X:= lw; - VertexBuffer[1].Y:= r.y; - VertexBuffer[2].X:= lw; - VertexBuffer[2].Y:= lh; - VertexBuffer[3].X:= -lw; - VertexBuffer[3].Y:= lh; - - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glEnableClientState(GL_COLOR_ARRAY); - if SuddenDeathDmg then - glColorPointer(4, GL_UNSIGNED_BYTE, 0, @SDWaterColorArray[0]) - else - glColorPointer(4, GL_UNSIGNED_BYTE, 0, @WaterColorArray[0]); - - glVertexPointer(2, GL_FLOAT, 0, @VertexBuffer[0]); - - glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer)); - - glDisableClientState(GL_COLOR_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glColor4ub($FF, $FF, $FF, $FF); // must not be Tint() as color array seems to stay active and color reset is required - glEnable(GL_TEXTURE_2D); - end; -end; - -procedure DrawWaves(Dir, dX, dY: LongInt; tnt: Byte); -var VertexBuffer, TextureBuffer: array [0..3] of TVertex2f; - lw, waves, shift: GLfloat; - sprite: TSprite; -begin -if SuddenDeathDmg then - sprite:= sprSDWater -else - sprite:= sprWater; - -cWaveWidth:= SpritesData[sprite].Width; - -lw:= cScreenWidth / cScaleFactor; -waves:= lw * 2 / cWaveWidth; - -if SuddenDeathDmg then - Tint(LongInt(tnt) * SDWaterColorArray[2].r div 255 + 255 - tnt, - LongInt(tnt) * SDWaterColorArray[2].g div 255 + 255 - tnt, - LongInt(tnt) * SDWaterColorArray[2].b div 255 + 255 - tnt, - 255 - ) -else - Tint(LongInt(tnt) * WaterColorArray[2].r div 255 + 255 - tnt, - LongInt(tnt) * WaterColorArray[2].g div 255 + 255 - tnt, - LongInt(tnt) * WaterColorArray[2].b div 255 + 255 - tnt, - 255 - ); - -glBindTexture(GL_TEXTURE_2D, SpritesData[sprite].Texture^.id); - -VertexBuffer[0].X:= -lw; -VertexBuffer[0].Y:= cWaterLine + WorldDy + dY; -VertexBuffer[1].X:= lw; -VertexBuffer[1].Y:= VertexBuffer[0].Y; -VertexBuffer[2].X:= lw; -VertexBuffer[2].Y:= VertexBuffer[0].Y + SpritesData[sprite].Height; -VertexBuffer[3].X:= -lw; -VertexBuffer[3].Y:= VertexBuffer[2].Y; - -shift:= - lw / cWaveWidth; -TextureBuffer[0].X:= shift + (( - WorldDx + LongInt(RealTicks shr 6) * Dir + dX) mod cWaveWidth) / (cWaveWidth - 1); -TextureBuffer[0].Y:= 0; -TextureBuffer[1].X:= TextureBuffer[0].X + waves; -TextureBuffer[1].Y:= TextureBuffer[0].Y; -TextureBuffer[2].X:= TextureBuffer[1].X; -TextureBuffer[2].Y:= SpritesData[sprite].Texture^.ry; -TextureBuffer[3].X:= TextureBuffer[0].X; -TextureBuffer[3].Y:= TextureBuffer[2].Y; - - -glVertexPointer(2, GL_FLOAT, 0, @VertexBuffer[0]); -glTexCoordPointer(2, GL_FLOAT, 0, @TextureBuffer[0]); -glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer)); - -untint; - -{for i:= -1 to cWaterSprCount do - DrawSprite(sprWater, - i * cWaveWidth + ((WorldDx + (RealTicks shr 6) * Dir + dX) mod cWaveWidth) - (cScreenWidth div 2), - cWaterLine + WorldDy + dY, - 0)} -end; - procedure DrawRepeated(spr, sprL, sprR: TSprite; Shift, OffsetY: LongInt); var i, w, h, lw, lh, rw, rh, sw: LongInt; begin @@ -975,180 +855,92 @@ else ZoomValue:= zoom; - // Sky - glClear(GL_COLOR_BUFFER_BIT); - //glPushMatrix; - //glScalef(1.0, 1.0, 1.0); - if (not isPaused) and (not isAFK) and (GameType <> gmtRecord) then MoveCamera; if cStereoMode = smNone then begin - glClear(GL_COLOR_BUFFER_BIT); + RenderClear(); DrawWorldStereo(Lag, rmDefault) - end {$IFDEF USE_S3D_RENDERING} - else if (cStereoMode = smHorizontal) or (cStereoMode = smVertical) then - begin - // create left fb - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framel); - glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); - DrawWorldStereo(Lag, rmLeftEye); - - // create right fb - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framer); - glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); - DrawWorldStereo(0, rmRightEye); - - // detatch drawing from fbs - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, defaultFrame); - glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); - SetScale(cDefaultZoomLevel); - - // draw left frame - glBindTexture(GL_TEXTURE_2D, texl); - glBegin(GL_QUADS); - if cStereoMode = smHorizontal then - begin - glTexCoord2f(0.0, 0.0); - glVertex2d(cScreenWidth / -2, cScreenHeight); - glTexCoord2f(1.0, 0.0); - glVertex2d(0, cScreenHeight); - glTexCoord2f(1.0, 1.0); - glVertex2d(0, 0); - glTexCoord2f(0.0, 1.0); - glVertex2d(cScreenWidth / -2, 0); - end - else - begin - glTexCoord2f(0.0, 0.0); - glVertex2d(cScreenWidth / -2, cScreenHeight / 2); - glTexCoord2f(1.0, 0.0); - glVertex2d(cScreenWidth / 2, cScreenHeight / 2); - glTexCoord2f(1.0, 1.0); - glVertex2d(cScreenWidth / 2, 0); - glTexCoord2f(0.0, 1.0); - glVertex2d(cScreenWidth / -2, 0); - end; - glEnd(); - - // draw right frame - glBindTexture(GL_TEXTURE_2D, texr); - glBegin(GL_QUADS); - if cStereoMode = smHorizontal then - begin - glTexCoord2f(0.0, 0.0); - glVertex2d(0, cScreenHeight); - glTexCoord2f(1.0, 0.0); - glVertex2d(cScreenWidth / 2, cScreenHeight); - glTexCoord2f(1.0, 1.0); - glVertex2d(cScreenWidth / 2, 0); - glTexCoord2f(0.0, 1.0); - glVertex2d(0, 0); - end - else - begin - glTexCoord2f(0.0, 0.0); - glVertex2d(cScreenWidth / -2, cScreenHeight); - glTexCoord2f(1.0, 0.0); - glVertex2d(cScreenWidth / 2, cScreenHeight); - glTexCoord2f(1.0, 1.0); - glVertex2d(cScreenWidth / 2, cScreenHeight / 2); - glTexCoord2f(0.0, 1.0); - glVertex2d(cScreenWidth / -2, cScreenHeight / 2); - end; - glEnd(); - SetScale(zoom); end else begin - // clear scene - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); - // draw left eye in red channel only - if cStereoMode = smGreenRed then - glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_TRUE) - else if cStereoMode = smBlueRed then - glColorMask(GL_FALSE, GL_FALSE, GL_TRUE, GL_TRUE) - else if cStereoMode = smCyanRed then - glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_TRUE) - else - glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_TRUE); + // draw frame for left eye + RenderClear(rmLeftEye); DrawWorldStereo(Lag, rmLeftEye); - // draw right eye in selected channel(s) only - if cStereoMode = smRedGreen then - glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_TRUE) - else if cStereoMode = smRedBlue then - glColorMask(GL_FALSE, GL_FALSE, GL_TRUE, GL_TRUE) - else if cStereoMode = smRedCyan then - glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_TRUE) - else - glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_TRUE); - DrawWorldStereo(Lag, rmRightEye); - end + + // draw frame for right eye + RenderClear(rmRightEye); + DrawWorldStereo(0, rmRightEye); {$ENDIF} + end; + +FinishRender(); end; -procedure ChangeDepth(rm: TRenderMode; d: GLfloat); -begin -{$IFNDEF USE_S3D_RENDERING} - rm:= rm; d:= d; // avoid hint - exit; -{$ELSE} - d:= d / 5; - if rm = rmDefault then - exit - else if rm = rmLeftEye then - d:= -d; - stereoDepth:= stereoDepth + d; - glMatrixMode(GL_PROJECTION); - glTranslatef(d, 0, 0); - glMatrixMode(GL_MODELVIEW); -{$ENDIF} -end; - -procedure ResetDepth(rm: TRenderMode); +procedure RenderWorldEdge; +var + //VertexBuffer: array [0..3] of TVertex2f; + tmp, w: LongInt; + rect: TSDL_Rect; + //c1, c2: LongWord; // couple of colours for edges begin -{$IFNDEF USE_S3D_RENDERING} - rm:= rm; // avoid hint - exit; -{$ELSE} - if rm = rmDefault then - exit; - glMatrixMode(GL_PROJECTION); - glTranslatef(-stereoDepth, 0, 0); - glMatrixMode(GL_MODELVIEW); - stereoDepth:= 0; -{$ENDIF} -end; - - -procedure RenderWorldEdge(Lag: Longword); -var - VertexBuffer: array [0..3] of TVertex2f; - c1, c2: LongWord; // couple of colours for edges -begin -if WorldEdge <> weNone then +if (WorldEdge <> weNone) and (WorldEdge <> weSea) then begin (* I think for a bounded world, will fill the left and right areas with black or something. Also will probably want various border effects/animations based on border type. Prob also, say, trigger a border animation timer on an impact. *) + rect.y:= ViewTopY; + rect.h:= ViewHeight; + tmp:= LongInt(leftX) + WorldDx; + w:= tmp - ViewLeftX; + + if w > 0 then + begin + rect.w:= w; + rect.x:= ViewLeftX; + DrawRect(rect, $10, $10, $10, $80, true); + if WorldEdge = weBounce then + DrawLineOnScreen(tmp - 1, ViewTopY, tmp - 1, ViewBottomY, 2, $54, $54, $FF, $FF); + end; + + tmp:= LongInt(rightX) + WorldDx; + w:= ViewRightX - tmp; + + if w > 0 then + begin + rect.w:= w; + rect.x:= tmp; + DrawRect(rect, $10, $10, $10, $80, true); + if WorldEdge = weBounce then + DrawLineOnScreen(tmp - 1, ViewTopY, tmp - 1, ViewBottomY, 2, $54, $54, $FF, $FF); + end; + + (* + WARNING: the following render code is outdated and does not work with + current Render.pas ! - don't just uncomment without fixing it first + glDisable(GL_TEXTURE_2D); glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glEnableClientState(GL_COLOR_ARRAY); + if (WorldEdge = weWrap) or (worldEdge = weBounce) then + glColor4ub($00, $00, $00, $40) + else + begin + glEnableClientState(GL_COLOR_ARRAY); + glColorPointer(4, GL_UNSIGNED_BYTE, 0, @WorldFade[0]); + end; glPushMatrix; glTranslatef(WorldDx, WorldDy, 0); - glColorPointer(4, GL_UNSIGNED_BYTE, 0, @WorldFade[0]); VertexBuffer[0].X:= leftX-20; - VertexBuffer[0].Y:= -3000; + VertexBuffer[0].Y:= -3500; VertexBuffer[1].X:= leftX-20; VertexBuffer[1].Y:= cWaterLine+cVisibleWater; VertexBuffer[2].X:= leftX+30; VertexBuffer[2].Y:= cWaterLine+cVisibleWater; VertexBuffer[3].X:= leftX+30; - VertexBuffer[3].Y:= -3000; + VertexBuffer[3].Y:= -3500; glVertexPointer(2, GL_FLOAT, 0, @VertexBuffer[0]); glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer)); @@ -1186,7 +978,7 @@ glColor4ub($FF, $FF, $FF, $FF); // must not be Tint() as color array seems to stay active and color reset is required glEnable(GL_TEXTURE_2D); - // I'd still like to have things happen to the border when a wrap or bounce just occurred, based on a timer + // I'd still like to have things happen to the border when a wrap or bounce just occurred, based on a timer if WorldEdge = weBounce then begin // could maybe alternate order of these on a bounce, or maybe drop the outer ones. @@ -1227,6 +1019,7 @@ end; if LeftImpactTimer > Lag then dec(LeftImpactTimer,Lag) else LeftImpactTimer:= 0; if RightImpactTimer > Lag then dec(RightImpactTimer,Lag) else RightImpactTimer:= 0 + *) end; end; @@ -1288,7 +1081,7 @@ for i:= 0 to cMaxHHIndex do begin inc(h, Hedgehogs[i].HealthBarHealth); - if (h < TeamHealthBarHealth) and (Hedgehogs[i].HealthBarHealth > 0) then + if (h < TeamHealthBarHealth) and (Hedgehogs[i].HealthBarHealth > 0) then DrawTexture(15 + h * TeamHealthBarWidth div TeamHealthBarHealth, cScreenHeight + DrawHealthY + smallScreenOffset + 1, SpritesData[sprSlider].Texture); end; @@ -1312,34 +1105,86 @@ r.w:= NameTagTex^.w - 4; r.h:= NameTagTex^.h - 4; DrawTextureFromRect(-NameTagTex^.w - 14, cScreenHeight + DrawHealthY + smallScreenOffset + 2, @r, NameTagTex); + + if OwnerTex <> nil then + begin + r.w:= OwnerTex^.w - 4; + r.h:= OwnerTex^.h - 4; + DrawTextureFromRect(-OwnerTex^.w - NameTagTex^.w - 16, cScreenHeight + DrawHealthY + smallScreenOffset + 2, @r, OwnerTex) + end; + + if (GameFlags and gfAISurvival) <> 0 then + begin + r.w:= AIKillsTex^.w - 4; + r.h:= AIKillsTex^.h - 4; + DrawTextureFromRect(TeamHealthBarWidth + 24, cScreenHeight + DrawHealthY + smallScreenOffset + 2, @r, AIKillsTex); + end; + // draw flag r.w:= 22; r.h:= 15; DrawTextureFromRect(-12, cScreenHeight + DrawHealthY + smallScreenOffset + 2, @r, FlagTex); + end + // draw an arrow next to active team + else if (CurrentTeam = TeamsArray[t]) and (TurnTimeLeft > 0) then + begin + h:= -NameTagTex^.w - 24; + if OwnerTex <> nil then + h:= h - OwnerTex^.w - 4; + DrawSpriteRotatedF(sprFinger, h, cScreenHeight + DrawHealthY + smallScreenOffset + 2 + SpritesData[sprFinger].Width div 4, 0, 1, -90); end; end; if smallScreenOffset <> 0 then begin SetScale(cDefaultZoomLevel); if TeamsCount * 20 > Longword(cScreenHeight) div 5 then - Tint($FF,$FF,$FF,$FF); + untint; end; end; +var preShiftWorldDx: LongInt; + +procedure ShiftWorld(Dir: LongInt); inline; +begin + preShiftWorldDx:= WorldDx; + WorldDx:= WorldDx + LongInt(Dir * LongInt(playWidth)); + +end; + +procedure UnshiftWorld(); inline; +begin + WorldDx:= preShiftWorldDx; +end; + procedure DrawWorldStereo(Lag: LongInt; RM: TRenderMode); var i, t: LongInt; r: TSDL_Rect; tdx, tdy: Double; s: shortstring; offsetX, offsetY, screenBottom: LongInt; - VertexBuffer: array [0..3] of TVertex2f; + replicateToLeft, replicateToRight, tmp: boolean; + a: Byte; begin +if WorldEdge <> weWrap then + begin + replicateToLeft := false; + replicateToRight:= false; + end +else + begin + replicateToLeft := (LongInt(leftX) + WorldDx > ViewLeftX); + replicateToRight:= (LongInt(rightX) + WorldDx < ViewRightX); + end; + +ScreenBottom:= (WorldDy - trunc(cScreenHeight/cScaleFactor) - (cScreenHeight div 2) + cWaterLine); + +// note: offsetY is negative! +offsetY:= 10 * Min(0, -145 - ScreenBottom); // TODO limit this in the other direction too + if (cReducedQuality and rqNoBackground) = 0 then begin // Offsets relative to camera - spare them to wimpier cpus, no bg or flakes for them anyway - ScreenBottom:= (WorldDy - trunc(cScreenHeight/cScaleFactor) - (cScreenHeight div 2) + cWaterLine); - offsetY:= 10 * Min(0, -145 - ScreenBottom); SkyOffset:= offsetY div 35 + cWaveHeight; HorizontOffset:= SkyOffset; if ScreenBottom > SkyOffset then @@ -1363,67 +1208,159 @@ if (cReducedQuality and rq2DWater) = 0 then begin // Waves - DrawWater(255, SkyOffset); + DrawWater(255, SkyOffset, 0); ChangeDepth(RM, -cStereo_Water_distant); - DrawWaves( 1, 0 - WorldDx div 32, - cWaveHeight + offsetY div 35, 64); + DrawWaves( 1, 0 - WorldDx div 32, offsetY div 35, -49, 64); ChangeDepth(RM, -cStereo_Water_distant); - DrawWaves( -1, 25 + WorldDx div 25, - cWaveHeight + offsetY div 38, 48); + DrawWaves( -1, 25 + WorldDx div 25, offsetY div 38, -37, 48); ChangeDepth(RM, -cStereo_Water_distant); - DrawWaves( 1, 75 - WorldDx div 19, - cWaveHeight + offsetY div 45, 32); + DrawWaves( 1, 75 - WorldDx div 19, offsetY div 45, -23, 32); ChangeDepth(RM, -cStereo_Water_distant); - DrawWaves(-1, 100 + WorldDx div 14, - cWaveHeight + offsetY div 70, 24); + DrawWaves(-1, 100 + WorldDx div 14, offsetY div 70, -7, 24); end else - DrawWaves(-1, 100, - (cWaveHeight + (cWaveHeight shr 1)), 0); + DrawWaves(-1, 100, - cWaveHeight div 2, - cWaveHeight div 2, 0); + +ChangeDepth(RM, cStereo_Land); +DrawVisualGears(5); +DrawLand(WorldDx, WorldDy); + +if replicateToLeft then + begin + ShiftWorld(-1); + DrawLand(WorldDx, WorldDy); + UnshiftWorld(); + end; + +if replicateToRight then + begin + ShiftWorld(1); + DrawLand(WorldDx, WorldDy); + UnshiftWorld(); + end; + +DrawWater(255, 0, 0); - changeDepth(RM, cStereo_Land); - DrawVisualGears(5); - DrawLand(WorldDx, WorldDy); +(* +// Attack bar + if CurrentTeam <> nil then + case AttackBar of + //1: begin + //r:= StuffPoz[sPowerBar]; + //{$WARNINGS OFF} + //r.w:= (CurrentHedgehog^.Gear^.Power * 256) div cPowerDivisor; + //{$WARNINGS ON} + //DrawSpriteFromRect(r, cScreenWidth - 272, cScreenHeight - 48, 16, 0, Surface); + //end; + 2: with CurrentHedgehog^ do + begin + tdx:= hwSign(Gear^.dX) * Sin(Gear^.Angle * Pi / cMaxAngle); + tdy:= - Cos(Gear^.Angle * Pi / cMaxAngle); + for i:= (Gear^.Power * 24) div cPowerDivisor downto 0 do + DrawSprite(sprPower, + hwRound(Gear^.X) + GetLaunchX(CurAmmoType, hwSign(Gear^.dX), Gear^.Angle) + LongInt(round(WorldDx + tdx * (24 + i * 2))) - 16, + hwRound(Gear^.Y) + GetLaunchY(CurAmmoType, Gear^.Angle) + LongInt(round(WorldDy + tdy * (24 + i * 2))) - 16, + i) + end + end; +*) - DrawWater(255, 0); +tmp:= bShowFinger; +bShowFinger:= false; + +if replicateToLeft then + begin + ShiftWorld(-1); + DrawVisualGears(1); + DrawGears(); + DrawVisualGears(6); + UnshiftWorld(); + end; + +if replicateToRight then + begin + ShiftWorld(1); + DrawVisualGears(1); + DrawGears(); + DrawVisualGears(6); + UnshiftWorld(); + end; + +bShowFinger:= tmp; DrawVisualGears(1); DrawGears; DrawVisualGears(6); + if SuddenDeathDmg then - DrawWater(SDWaterOpacity, 0) + DrawWater(SDWaterOpacity, 0, 0) else - DrawWater(WaterOpacity, 0); + DrawWater(WaterOpacity, 0, 0); // Waves ChangeDepth(RM, cStereo_Water_near); -DrawWaves( 1, 25 - WorldDx div 9, - cWaveHeight, 12); +DrawWaves( 1, 25 - WorldDx div 9, 0, 0, 12); if (cReducedQuality and rq2DWater) = 0 then begin //DrawWater(WaterOpacity, - offsetY div 40); ChangeDepth(RM, cStereo_Water_near); - DrawWaves(-1, 50 + WorldDx div 6, - cWaveHeight - offsetY div 40, 8); + DrawWaves(-1, 50 + WorldDx div 6, - offsetY div 40, 23, 8); if SuddenDeathDmg then - DrawWater(SDWaterOpacity, - offsetY div 20) + DrawWater(SDWaterOpacity, - offsetY div 20, 23) else - DrawWater(WaterOpacity, - offsetY div 20); + DrawWater(WaterOpacity, - offsetY div 20, 23); ChangeDepth(RM, cStereo_Water_near); - DrawWaves( 1, 75 - WorldDx div 4, - cWaveHeight - offsetY div 20, 2); + DrawWaves( 1, 75 - WorldDx div 4, - offsetY div 20, 37, 2); if SuddenDeathDmg then - DrawWater(SDWaterOpacity, - offsetY div 10) + DrawWater(SDWaterOpacity, - offsetY div 10, 47) else - DrawWater(WaterOpacity, - offsetY div 10); + DrawWater(WaterOpacity, - offsetY div 10, 47); ChangeDepth(RM, cStereo_Water_near); - DrawWaves( -1, 25 + WorldDx div 3, - cWaveHeight - offsetY div 10, 0); + DrawWaves( -1, 25 + WorldDx div 3, - offsetY div 10, 59, 0); end else - DrawWaves(-1, 50, - (cWaveHeight shr 1), 0); + DrawWaves(-1, 50, cWaveHeight div 2, cWaveHeight div 2, 0); // everything after this ChangeDepth will be drawn outside the screen // note: negative parallax gears should last very little for a smooth stereo effect ChangeDepth(RM, cStereo_Outside); + + if replicateToLeft then + begin + ShiftWorld(-1); + DrawVisualGears(2); + UnshiftWorld(); + end; + + if replicateToRight then + begin + ShiftWorld(1); + DrawVisualGears(2); + UnshiftWorld(); + end; + DrawVisualGears(2); // everything after this ResetDepth will be drawn at screen level (depth = 0) // note: everything that needs to be readable should be on this level ResetDepth(RM); + + if replicateToLeft then + begin + ShiftWorld(-1); + DrawVisualGears(3); + UnshiftWorld(); + end; + + if replicateToRight then + begin + ShiftWorld(1); + DrawVisualGears(3); + UnshiftWorld(); + end; + DrawVisualGears(3); {$WARNINGS OFF} @@ -1440,7 +1377,7 @@ end; {$WARNINGS ON} -RenderWorldEdge(Lag); +RenderWorldEdge(); // this scale is used to keep the various widgets at the same dimension at all zoom levels SetScale(cDefaultZoomLevel); @@ -1460,7 +1397,7 @@ i:= Succ(Pred(ReadyTimeLeft) div 1000) else i:= Succ(Pred(TurnTimeLeft) div 1000); - + if i>99 then t:= 112 else if i>9 then @@ -1545,14 +1482,14 @@ AMAnimStartTime:= RealTicks - (AMAnimDuration - (RealTicks - AMAnimStartTime)); AMState:= AMShowingUp; end; -if not(bShowAmmoMenu) and ((AMstate = AMShowing) or (AMState = AMShowingUp)) then +if (not bShowAmmoMenu) and ((AMstate = AMShowing) or (AMState = AMShowingUp)) then begin if (AMState = AMShowing) then AMAnimStartTime:= RealTicks else AMAnimStartTime:= RealTicks - (AMAnimDuration - (RealTicks - AMAnimStartTime)); AMState:= AMHiding; - end; + end; if bShowAmmoMenu or (AMState = AMHiding) then ShowAmmoMenu; @@ -1564,6 +1501,7 @@ // Chat DrawChat; + // various captions if fastUntilLag then DrawTextureCentered(0, (cScreenHeight shr 1), SyncTexture); @@ -1607,11 +1545,11 @@ if t < 10 then s:= '0' + s; s:= inttostr(i div 60) + ':' + s; - - + + tmpSurface:= TTF_RenderUTF8_Blended(Fontz[fnt16].Handle, Str2PChar(s), cWhiteColorChannels); tmpSurface:= doSurfaceConversion(tmpSurface); - FreeTexture(timeTexture); + FreeAndNilTexture(timeTexture); timeTexture:= Surface2Tex(tmpSurface, false); SDL_FreeSurface(tmpSurface) end; @@ -1629,7 +1567,7 @@ s:= inttostr(FPS) + ' fps'; tmpSurface:= TTF_RenderUTF8_Blended(Fontz[fnt16].Handle, Str2PChar(s), cWhiteColorChannels); tmpSurface:= doSurfaceConversion(tmpSurface); - FreeTexture(fpsTexture); + FreeAndNilTexture(fpsTexture); fpsTexture:= Surface2Tex(tmpSurface, false); SDL_FreeSurface(tmpSurface) end; @@ -1644,7 +1582,7 @@ if ScreenFade <> sfNone then begin - if not isFirstFrame then + if (not isFirstFrame) then case ScreenFade of sfToBlack, sfToWhite: if ScreenFadeValue + Lag * ScreenFadeSpeed < sfMax then inc(ScreenFadeValue, Lag * ScreenFadeSpeed) @@ -1657,27 +1595,16 @@ end; if ScreenFade <> sfNone then begin + r.x:= ViewLeftX; + r.y:= ViewTopY; + r.w:= ViewWidth; + r.h:= ViewHeight; + case ScreenFade of - sfToBlack, sfFromBlack: Tint(0, 0, 0, ScreenFadeValue * 255 div 1000); - sfToWhite, sfFromWhite: Tint($FF, $FF, $FF, ScreenFadeValue * 255 div 1000); + sfToBlack, sfFromBlack: DrawRect(r, 0, 0, 0, ScreenFadeValue * 255 div 1000, true); + sfToWhite, sfFromWhite: DrawRect(r, $FF, $FF, $FF, ScreenFadeValue * 255 div 1000, true); end; - VertexBuffer[0].X:= -cScreenWidth; - VertexBuffer[0].Y:= cScreenHeight; - VertexBuffer[1].X:= -cScreenWidth; - VertexBuffer[1].Y:= 0; - VertexBuffer[2].X:= cScreenWidth; - VertexBuffer[2].Y:= 0; - VertexBuffer[3].X:= cScreenWidth; - VertexBuffer[3].Y:= cScreenHeight; - - glDisable(GL_TEXTURE_2D); - - glVertexPointer(2, GL_FLOAT, 0, @VertexBuffer[0]); - glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer)); - - glEnable(GL_TEXTURE_2D); - untint; if not isFirstFrame and ((ScreenFadeValue = 0) or (ScreenFadeValue = sfMax)) then ScreenFade:= sfNone end @@ -1692,21 +1619,17 @@ s:= 'rec'; tmpSurface:= TTF_RenderUTF8_Blended(Fontz[fntBig].Handle, Str2PChar(s), cWhiteColorChannels); tmpSurface:= doSurfaceConversion(tmpSurface); - FreeTexture(recTexture); + FreeAndNilTexture(recTexture); recTexture:= Surface2Tex(tmpSurface, false); SDL_FreeSurface(tmpSurface) end; DrawTexture( -(cScreenWidth shr 1) + 50, 20, recTexture); + //a:= Byte(Round(127*(1 + sin(RealTicks*0.007)))); + a:= Byte(min(255, abs(-255 + ((RealTicks div 2) and 511)))); + // draw red circle - glDisable(GL_TEXTURE_2D); - Tint($FF, $00, $00, Byte(Round(127*(1 + sin(SDL_GetTicks()*0.007))))); - glBegin(GL_POLYGON); - for i:= 0 to 20 do - glVertex2f(-(cScreenWidth shr 1) + 30 + sin(i*2*Pi/20)*10, 35 + cos(i*2*Pi/20)*10); - glEnd(); - untint; - glEnable(GL_TEXTURE_2D); + DrawCircleFilled(-(cScreenWidth shr 1) + 30, 35, 10, $FF, $00, $00, a); end; {$ENDIF} @@ -1736,31 +1659,51 @@ // Cursor -if isCursorVisible then +if isCursorVisible and (not bShowAmmoMenu) then begin - if not bShowAmmoMenu then - begin - if not CurrentTeam^.ExtDriven then TargetCursorPoint:= CursorPoint; - with CurrentHedgehog^ do - if (Gear <> nil) and ((Gear^.State and gstHHChooseTarget) <> 0) then + if not CurrentTeam^.ExtDriven then TargetCursorPoint:= CursorPoint; + with CurrentHedgehog^ do + if (Gear <> nil) and ((Gear^.State and gstChooseTarget) <> 0) then + begin + if (CurAmmoType = amNapalm) or (CurAmmoType = amMineStrike) or (((GameFlags and gfMoreWind) <> 0) and ((CurAmmoType = amDrillStrike) or (CurAmmoType = amAirAttack))) then + DrawLine(-3000, topY-300, 7000, topY-300, 3.0, (Team^.Clan^.Color shr 16), (Team^.Clan^.Color shr 8) and $FF, Team^.Clan^.Color and $FF, $FF); + i:= GetCurAmmoEntry(CurrentHedgehog^)^.Pos; + with Ammoz[CurAmmoType] do + if PosCount > 1 then begin - if (CurAmmoType = amNapalm) or (CurAmmoType = amMineStrike) then - DrawLine(-3000, topY-300, 7000, topY-300, 3.0, (Team^.Clan^.Color shr 16), (Team^.Clan^.Color shr 8) and $FF, Team^.Clan^.Color and $FF, $FF); - i:= GetCurAmmoEntry(CurrentHedgehog^)^.Pos; - with Ammoz[CurAmmoType] do - if PosCount > 1 then - DrawSprite(PosSprite, TargetCursorPoint.X - (SpritesData[PosSprite].Width shr 1), cScreenHeight - TargetCursorPoint.Y - (SpritesData[PosSprite].Height shr 1),i); + if (CurAmmoType = amGirder) or (CurAmmoType = amTeleport) then + begin + // pulsating transparency + if ((GameTicks div 16) mod $80) >= $40 then + Tint($FF, $FF, $FF, $C0 - (GameTicks div 16) mod $40) + else + Tint($FF, $FF, $FF, $80 + (GameTicks div 16) mod $40); + end; + DrawSprite(PosSprite, TargetCursorPoint.X - (SpritesData[PosSprite].Width shr 1), cScreenHeight - TargetCursorPoint.Y - (SpritesData[PosSprite].Height shr 1),i); + Untint(); end; - DrawSprite(sprArrow, TargetCursorPoint.X, cScreenHeight - TargetCursorPoint.Y, (RealTicks shr 6) mod 8) - end + end; + //DrawSprite(sprArrow, TargetCursorPoint.X, cScreenHeight - TargetCursorPoint.Y, (RealTicks shr 6) mod 8) + DrawTextureF(SpritesData[sprArrow].Texture, cDefaultZoomLevel / cScaleFactor, TargetCursorPoint.X + round(SpritesData[sprArrow].Width / cScaleFactor), cScreenHeight + round(SpritesData[sprArrow].Height / cScaleFactor) - TargetCursorPoint.Y, (RealTicks shr 6) mod 8, 1, SpritesData[sprArrow].Width, SpritesData[sprArrow].Height); end; -isFirstFrame:= false; + +// debug stuff +if cViewLimitsDebug then + begin + r.x:= ViewLeftX; + r.y:= ViewTopY; + r.w:= ViewWidth; + r.h:= ViewHeight; + DrawRect(r, 255, 0, 0, 128, false); + end; + +isFirstFrame:= false end; var PrevSentPointTime: LongWord = 0; procedure MoveCamera; -var EdgesDist, wdy, shs,z, amNumOffsetX, amNumOffsetY: LongInt; +var EdgesDist, wdy, shs,z, amNumOffsetX, amNumOffsetY, dstX: LongInt; inbtwnTrgtAttks: Boolean; begin {$IFNDEF MOBILE} @@ -1768,8 +1711,8 @@ uCursor.updatePosition(); {$ENDIF} z:= round(200/zoom); -inbtwnTrgtAttks := (CurrentHedgehog <> nil) and ((Ammoz[CurrentHedgehog^.CurAmmoType].Ammo.Propz and ammoprop_NeedTarget) <> 0) and ((GameFlags and gfInfAttack) <> 0); -if autoCameraOn and not PlacingHogs and (FollowGear <> nil) and (not isCursorVisible) and (not bShowAmmoMenu) and (not fastUntilLag) and not inbtwnTrgtAttks then +inbtwnTrgtAttks := ((GameFlags and gfInfAttack) <> 0) and (CurrentHedgehog <> nil) and ((CurrentHedgehog^.Gear = nil) or (CurrentHedgehog^.Gear <> FollowGear)) and ((Ammoz[CurrentHedgehog^.CurAmmoType].Ammo.Propz and ammoprop_NeedTarget) <> 0); +if autoCameraOn and (not PlacingHogs) and (FollowGear <> nil) and (not isCursorVisible) and (not bShowAmmoMenu) and (not fastUntilLag) and (not inbtwnTrgtAttks) then if ((abs(CursorPoint.X - prevPoint.X) + abs(CursorPoint.Y - prevpoint.Y)) > 4) then begin FollowGear:= nil; @@ -1778,13 +1721,36 @@ end else begin - CursorPoint.X:= (prevPoint.X * 7 + hwRound(FollowGear^.X) + hwSign(FollowGear^.dX) * z + WorldDx) div 8; - if isPhone() or (cScreenHeight < 600) or ((hwSign(FollowGear^.dY) * z) < 10) then + dstX:= hwRound(FollowGear^.X) + hwSign(FollowGear^.dX) * z + WorldDx; + + if (WorldEdge = weWrap) then + begin + if dstX - prevPoint.X < (LongInt(leftX) - rightX) div 2 then + CursorPoint.X:= (prevPoint.X * 7 + dstX - (leftX - rightX)) div 8 + else if dstX - prevPoint.X > (LongInt(rightX) - leftX) div 2 then + CursorPoint.X:= (prevPoint.X * 7 + dstX - (rightX - leftX)) div 8 + else + CursorPoint.X:= (prevPoint.X * 7 + dstX) div 8; + end + else // usual camera movement routine + begin + CursorPoint.X:= (prevPoint.X * 7 + dstX) div 8; + end; + + if isPhone() or (cScreenHeight < 600) or (hwFloat(FollowGear^.dY * z).Round < 10) then CursorPoint.Y:= (prevPoint.Y * 7 + cScreenHeight - (hwRound(FollowGear^.Y) + WorldDy)) div 8 else CursorPoint.Y:= (prevPoint.Y * 7 + cScreenHeight - (hwRound(FollowGear^.Y) + hwSign(FollowGear^.dY) * z + WorldDy)) div 8; end; +if (WorldEdge = weWrap) then + begin + if -WorldDx < leftX then + WorldDx:= WorldDx - LongInt(rightX) + leftX + else if -WorldDx > rightX then + WorldDx:= WorldDx + LongInt(rightX) - leftX; + end; + wdy:= trunc(cScreenHeight / cScaleFactor) + cScreenHeight div 2 - cWaterLine - cVisibleWater; if WorldDy < wdy then WorldDy:= wdy; @@ -1810,7 +1776,7 @@ {$ENDIF} {$ENDIF} - if CursorPoint.X < AmmoRect.x + amNumOffsetX + 3 then//check left + if CursorPoint.X < AmmoRect.x + amNumOffsetX + 3 then//check left CursorPoint.X:= AmmoRect.x + amNumOffsetX + 3; if CursorPoint.X > AmmoRect.x + AmmoRect.w - 3 then//check right CursorPoint.X:= AmmoRect.x + AmmoRect.w - 3; @@ -1889,25 +1855,27 @@ procedure ShowMission(caption, subcaption, text: ansistring; icon, time : LongInt); var r: TSDL_Rect; begin +if cOnlyStats then exit; + r.w:= 32; r.h:= 32; if time = 0 then time:= 5000; missionTimer:= time; -FreeTexture(missionTex); +FreeAndNilTexture(missionTex); if icon > -1 then begin r.x:= 0; r.y:= icon * 32; - missionTex:= RenderHelpWindow(caption, subcaption, text, '', 0, MissionIcons, @r) + missionTex:= RenderHelpWindow(caption, subcaption, text, ansistring(''), 0, MissionIcons, @r) end else begin r.x:= ((-icon - 1) shr 4) * 32; r.y:= ((-icon - 1) mod 16) * 32; - missionTex:= RenderHelpWindow(caption, subcaption, text, '', 0, SpritesData[sprAMAmmos].Surface, @r) + missionTex:= RenderHelpWindow(caption, subcaption, text, ansistring(''), 0, SpritesData[sprAMAmmos].Surface, @r) end; end; @@ -1939,14 +1907,22 @@ {$IFDEF USE_VIDEO_RECORDING} // do not change volume during prerecording as it will affect sound in video file -if not flagPrerecording then +if (not flagPrerecording) then {$ENDIF} begin - if not cHasFocus then DampenAudio() + if (not cHasFocus) then DampenAudio() else UndampenAudio(); end; end; +procedure updateCursorVisibility; +begin + if isPaused or isAFK then + SDL_ShowCursor(1) + else + SDL_ShowCursor(ord(GameState = gsConfirm)) +end; + procedure SetUtilityWidgetState(ammoType: TAmmoType); begin {$IFDEF USE_TOUCH_INTERFACE} @@ -1954,11 +1930,11 @@ ammoType:= CurrentHedgehog^.CurAmmoType; if(CurrentHedgehog <> nil)then - if (Ammoz[ammoType].Ammo.Propz and ammoprop_Timerable) <> 0 then + if ((Ammoz[ammoType].Ammo.Propz and ammoprop_Timerable) <> 0) and (ammoType <> amDrillStrike) then begin utilityWidget.sprite:= sprTimerButton; animateWidget(@utilityWidget, true, true); - end + end else if (Ammoz[ammoType].Ammo.Propz and ammoprop_NeedTarget) <> 0 then begin utilityWidget.sprite:= sprTargetButton; @@ -1966,7 +1942,7 @@ end else if ammoType = amSwitch then begin - utilityWidget.sprite:= sprTargetButton; + utilityWidget.sprite:= sprSwitchButton; animateWidget(@utilityWidget, true, true); end else if utilityWidget.show then @@ -1982,7 +1958,7 @@ begin show:= showWidget; if fade then fadeAnimStart:= RealTicks; - + with moveAnim do begin animate:= true; @@ -2020,10 +1996,8 @@ missionTimer:= 0; missionTex:= nil; cOffsetY:= 0; - stereoDepth:= 0; AMState:= AMHidden; isFirstFrame:= true; - stereoDepth:= stereoDepth; // avoid hint FillChar(WorldFade, sizeof(WorldFade), 0); WorldFade[0].a:= 255; @@ -2034,6 +2008,8 @@ WorldEnd[2].a:= 255; WorldEnd[3].a:= 255; + AmmoMenuTex:= nil; + AmmoMenuInvalidated:= true end; procedure freeModule; diff -r 31570b766315 -r ed5a6478e710 man/hedgewars.6 --- a/man/hedgewars.6 Tue Nov 10 18:16:35 2015 +0100 +++ b/man/hedgewars.6 Tue Nov 10 20:43:13 2015 +0100 @@ -20,19 +20,29 @@ .SH "SYNOPSIS" . .B hedgewars -[\fIOPTIONS\fR] +[\fIOPTION\fR...] +[\fICONNECTSTRING\fR] . .SH "DESCRIPTION" Each player controls a team of several hedgehogs. During the course of the game, players take turns with one of their hedgehogs. They then use whatever tools and weapons are available to attack and kill the opponents' hedgehogs, thereby winning the game. Hedgehogs may move around the terrain in a variety of ways, normally by walking and jumping but also by using particular tools such as the "Rope" or "Parachute", to move to otherwise inaccessible areas. Each turn is time\-limited to ensure that players do not hold up the game with excessive thinking or moving. .SH "OPTIONS" . .TP -.BI \-style \ name -sets Qt GUI Style (qtconfig names). Example: \-style Oxygen +\fB\-\-help\fR +Displays help and exits +.TP +\fB\-\-config-dir=PATH\fR +Custom path for configuration data and user data +.TP +\fB\-\-data-dir=PATH\fR +Custom path to the game data folder +.SH "CONNECTSTRING" +. +If a CONNECTSTRING (e.g. "hwplay://netserver.hedgewars.org") is supplied, then hedgewars will try to connect to the specified destination on start. . .SH "COPYRIGHT" . -Copyright \(co 2004\-2008 Andrey Korotaev, Igor Ulyanov +Copyright \(co 2004\-2015 Andrey Korotaev, Igor Ulyanov .br This is Free Software; this software is licensed under the GPL version 2, as published by the Free Software Foundation. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. diff -r 31570b766315 -r ed5a6478e710 misc/OfficialChallenges/racer_#1.hwmap --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/misc/OfficialChallenges/racer_#1.hwmap Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,1 @@ +AAAAw3icJc6xDcIwEAXQz+niWBhkiggxAS0djZs0kYVASFmBBWiYw0xAQ5sOV7SZgBpKRvAC+Ezz9PWlfzrd8BHmyzvwiTvoFe7QTf0AAoaIUO9hrwUMpQN56iN5tcT8U6C+dKADuzi7scsHeJuEnCaXJOSkXklAtWaXBBjDbRJKF/7dgtsgyPYcBNm+gwBtaTNqqzyqJ3fj1Oeff4W8JYk= \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 misc/OfficialChallenges/racer_#10.hwmap --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/misc/OfficialChallenges/racer_#10.hwmap Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,1 @@ +AAABSnicJc7ZDoQwDEPRQJcwC/DDU6kf3oix45cDUuWr+LBhPnzY8TOCP48npoeFGdnA3AKfXexhRZSwKmpYEy2si04QeDCbxq1xtonCVFKZShpTSWcqwSEuEPDF0xaiFznBPBcevgLlj0D5LVB+CZQP0QkCN2bz4vbi7BSFqaQylTSmks5UwqsEAn+uK4bq \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 misc/OfficialChallenges/racer_#11.hwmap --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/misc/OfficialChallenges/racer_#11.hwmap Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,1 @@ +AAACCHicLY8LDsMgDEMpAbKtn114lTg40eYHkyrrtUltx+7tTvkudzo+ovMjqvGNXiNF0hO9QAZZbJEy8pX0BKUwXi16hnLkSGWJpm2J/m18c5ydPVtSMJiivKoV5U4/Z88ZNIJEG7SxnLWstEkNcqwq/Zxco3OFGuQ4F5ydLkaXCjXIaVX+ac+hfs+hey9Jf0E7tA/dcSBvSb+gaxiv8jugY+jA1xJNH0v074NvjrOzty8pGEyp5GZypx+XSzRoBIlO6GT50LLSJjXIsar0c3KNzhVq0Lyo4Ox0MbpUqEFcznSm/QB50Oil \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 misc/OfficialChallenges/racer_#12.hwmap --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/misc/OfficialChallenges/racer_#12.hwmap Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,1 @@ +AAAB1nicJY5HjsUwDEPpnjq5sAP44BIy5NfmgWoUxztelLe8wNuliG1i4pp14plJioAnX5lAdjhKgGULsNED1TECw/H55+shaFBlUGXQVfbo0YWDJtXUK4Gq2+IryTQ5n9ZA0R50kfTtB5ZDgTpXqLJ+8LZEoOarK0tSlqS9KlWl/qzZughc1g1ngOUeKIYtkA0j8BkeG7Y+ggZZBlkGUIno0YWDXWpX7wxk3RZbt0xvq4YjULTXddH07QeWQ4E2rlBV/eDtGYGSrU1ZbmW5tXdIHVL/NLTKIw== \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 misc/OfficialChallenges/racer_#13.hwmap --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/misc/OfficialChallenges/racer_#13.hwmap Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,1 @@ +AAAEC3icHZJ9aJZVGIevc859znme930etsRKEyllVlJr2AInGDXBBSWVfdHXlFFiq5CWH39U7gNCHVE6WrnSRIq0j01nW7KxaZEtwvFMSzYCl9MWKKnEYrI5puvZ+9/hwH39rt+5T1TjHybMcJjsjXoHJpKr+Dn2KG7KtOCV2oqZrdqZGmGiLX8uE+lJj7XlXdJjTF2S9C5PJgA32ZafcZP4s25d4rvdGXy5X4A77+/AbXHDuFVuA67GGdxp24lfadvx7XZ0eqIiN0Zwzr6WBL/Zvwi+cI8TPOcO4MfdFXy9vw0/wxfidvvZuCJ3AXvK7cJud0uwa+2v2FV2JXajnMZ+I29gr8pNuHLTjzthWvFl5lt8l+khWGCuEbwjjxF0yfcEg/bOXC7hqLyehP/IMGFinyXcY38hLHd3EUbuXYKDro+gzIf4fr8Iv9o/hLuQPp2r8iXYKT8T25iWtsVuJzLkSpFddghZa9cjyy3IYqlHlsoNyFNmN1Jj7ka6dQ821JXYl/Ut2ONqELdEHcQdUI34Bep9/GfqU4J81UmwWV1MTfU9hCW6jrBWnyXsMOnyhkw34X9yb64C8WG9OYm/1qPEdWYN8TLTS3RZbiXaJquJbpatZPfKR2QXyjYyHVJB5gmZT3jN9BEeMZWEjXqccMt0xoc6Q9ipmgjHVTGZFfxJ5hC7yc5jA9km1hDlUUVUx06i8wwQ368WElerD4j3q+vTLhtzQsR7dHES1+uviFeYPKJ/zfNE1aaWyJm3U5R5lGypniQb6QYyU3oO2blqP9kKtZzsMaWIFvM3UQsjxLPU7cSVqpr4Y3UpR0YWyWAi8+2TmDH7E+aQK8A846rQF90+9Cb3A+q660K95z5BFbgX4YQLoMF+DutsEbwiHVAry6DdDKAwb6EqzH2ok8ajy9Lfro8YwRSaIswOsx5zxiTITClBiqQlZ4DJV8cSPaZL0N/pJvQjuh/Vr4dRL+kfUaF+Ewa0g1Nqe5qh5qGepg/Vw5fopTSj9zGMHlEPTqPacjxMKFcSPWJfRTfb3tQlFVcn3SxUuR1DKdsMvbYUfpbjcFleQD0ggmpJe+gC8we6QUL0uXTTxsvvOR6+0Jcl0SZfhjpKaxLOoJX/Ac8c7Ww= \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 misc/OfficialChallenges/racer_#14.hwmap --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/misc/OfficialChallenges/racer_#14.hwmap Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,1 @@ +AAAFlnicHZR3bNdlEMY/771371FLixoxKEKEQAgGwzA1SMJ0D6ZARY1SLTEgKEVGGOKIDGUjEJkBIYKADFFQ2RISLFVcjQXRGnBQLEJECUgUv/398+RyefO+994ztEgLsUt+FdI35JH/itxPwa+2g7yquIUGo9M89Lj0hTKWbKPMW9Ngdw5YkushN0rJNrnRxlJ4XQ6kJNcjdoy1ywtaxFr8F5Uq/1lb4if0PvxHHYYf1Vn4N7oZP6xf4fv1PL7DrsPXWxG+3Abgs20MPtkW4sNtGz7IsnN321m8XcrHb0itcEk9SDXpcdKRNIb0QZpFWpzWkCalT0hPpCOkbukk6eZ0gYQ7Vu2NsD3eClvmRdh4744N9J5YBy/GCv1J9LQ/gx70EegqL0Mn+Ri02Mei7X0cWj+r4m8+mvipjyQu9+HE8T6EOMCfILb3AcQCfwA57V2RQ94BecdbIK95Q6TUFbkr/Ym0SNVISocJNWk7oSKtJGxJ0wmL0kjCpFRMKE2dCQ+l5oTbUyI0sxpCgVXAP/Ye1NgcOGrPQ7n1ht3WFrZaIazVWlih5bBI18FcnQoztBSmaXeYok0ziJdhaqyC1+N2mBnfhPmxDBbHXrAqtoENMR+2Sw18Kp/Bl5JdVS3T4ZwMJYg8SGgotxJay9WELuE8YUCoIowIuwlTw2rCyvAGYWcYRfguPEb4K9yDXBvaI+1CE6RPyEdGcgmZRw2yjWNIJZ8jF9lHbMyHxK5sJD7NauI0lhE3soj4FfOJF5iDNmYW2q0OhjAbfYNMp5tZgH6baVIvshK7iXVYN7ZipezCpnEIe5dK7DAnsVrOkwpCJN0aGpIeCq1Jw0Jn0rTQj7QmDCXtDS+TjobFpPPhfTw/VODNwym8oyjeU5rhJdIFf0Eex1+TifgCWYq/LTvxzXIc3yn/4gdjU/yL2A2vjE/h38cp+E9xLX4ylmfWiGdy/shm0cIfUn3tQKqnA0lBx2MXdVk2qe7BftBqrEL/wz62Jtga64TNzExio+w5rNimYJ1sKdbYNqGXbQ96zD5HP7IqdKGdQEfZKbRX9m29xc6gyX4nnrDfiHvtJ+Iy+444IdtMHGS7iJ1sQ8aCvYVcsVeRkzYMKbe+GVGZOWWFNUJmaEbeBD2KDNePkBJdhDyio5F+2gfppW2QnloP6R1/Rh6O+5FH44rMAXEiUhYHIS/Fjhn78QZkjVxGPpEfka/lAFIr64kubxJbymTiXfIssVQeI06RnsS10oNYLncQ/5Db0GukHVokbdFB0h59UW5HV0pn9IDci/4i/bEkT2MtZTR2ZyZgGywrsImyHVsgR7D18ju2N+ZhX8csFE7E+7BzcSh2Oc4gxbiJlJfpLtWPf+c4yl7LiKqDuqp/uRbVram5Sjl7Mxp9uHQvz1uVKTGvii2VeVU+mAbjcsCWXI+rOqTqygbXB8ul7dm6tD2bf0SWVhTMtS5cOVWPff8D7Vs1fw== \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 misc/OfficialChallenges/racer_#15.hwmap --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/misc/OfficialChallenges/racer_#15.hwmap Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,1 @@ +AAACYnicFc9NSJRRFAbgc3/PfP8lqGGLIlpIJVktlHAgXaSRLTLMQIQGwwhJF8UIUs7umHExvCn5CcWgiSFo0SBGUrjJjSAIFZWgQdmiggqjdd9sHs7qfc/rZ2UWwnasg6hS1IMzy7ZBn9BbAEfwEXAu6kBl2FNgGTZbcMpFZSEo5+0F+VLfKMiIbczrMbk2H7RpM8+kXs3zEdlR5BLoa6w77/TqK3nvuuzPh1/lmbxXxarzsCCHYr6i0zEe1Cux14k1RY4nHyRX0CLvx3Jc/IxTa6wpxlL+KQ4n4FsctfLGmLWIVstfiArL38GCVS3wzKppPmJTOXXYukdVifWW9CHr1fAd6+dg0uIyzFj+CmOry3DUph7iPevuxT7r7sc+iPZp3zKr7hjxRlUniE4jf8sfJnVA3zb4Tx4z6peIDS6xdeNe5OkiteB8hxnjZOSkcR/rdJFa8HNi0/hZ1WXCniQvNKLC+DmcMmIR75Ju1OeJN6sBYnk5TJAVVQQd0E+8DK4S32LTxFf5ZRLPYZzkEAyR/CAYiY8yR3BBPSD2Gp8UmQKOqEmcTVDncIpwFy4TliY7cRNHCf+oDCGpbUoNq8/kDKguwlviLekGUUp6B3LknCyyzrrJbU96vXqeJl+J0+ROiD5yG+Qe8rS6Sd4X1UthMy5SsJGkBF1ijsLdRQa5obCH/aXgPSsh/xTLUNCWjInmRCdFpJooWtZjFE7oQfoP92i1IA== \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 misc/OfficialChallenges/racer_#16.hwmap --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/misc/OfficialChallenges/racer_#16.hwmap Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,1 @@ +AAAAaXicY3RgdGBgWcB2gIGDAcjiTgCy+A6AxVhlgFwgwcHA9ISBgYGRYb8AkLAXYGBmsGeAEKwgLphgB3GBBCPQvD8g82pA5tWAzKsBmVcDAB2iEO4= \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 misc/OfficialChallenges/racer_#2.hwmap --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/misc/OfficialChallenges/racer_#2.hwmap Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,1 @@ +AAABkHicFdCxK8RhGAfw7/u87/v8zns/9y63Wij+A5SE8YYbXErCplgMRBxXBgveS91goOQGN1jdImVw0xlOucGVQcpgk9hQ/J7l07fn21NPj9vGtIoW+Ej5Ne5WVtsVpcfsgPITKCo/qmrK5+hemV7eqgtwbd6rC6AWl0/iVS7D9PPOmwD3yHuvAqjElXZ3D1eQrFWCIO1xEKR1gTbxCSG47ySZyK4GE+kmhBA/S0rTlMwewAWaCVzQF0itJ7NUMUmuRPPBlfQ54mvbaMbX0SnUix1/oFZ0Bc7bnaqA1KLZqApwLTt0JsAvoavul7SG/9JPZf8V/SLj6K7jR+gOmVlV6/hBVUNmGcWOH0MR6Qjv++no71ZuqX0IcsHFhwDOqb7AOSrBHSTJHdIl6EYVGnRjf2DyqtkweT2X/E8NN1ybHmGYJoNhu4k4S9ldAf9Gt2jZ \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 misc/OfficialChallenges/racer_#3.hwmap --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/misc/OfficialChallenges/racer_#3.hwmap Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,1 @@ +AAAQaHicbddtbKRVFQfw/31/3rZGCiliozRaxWFJkWpoNE2saJGaWFeLFDbFMGADKWpNatxBHWObsRIbrS6NWMgiDpqKJaSs9EPBVDqgs7vUsCLD2FktSKM2OsGUxUZHWf9Hv/rll9uZZ+5z77nnnOepa9qrYWfMpfAPuBvgl8xHib4c4bC9Fgc+774CnIeL4X5oDx0PD9kbjsez9sbj8ZftrxDf5N6L+ApXRvSK14ge8Nchutrfh/CCryNMBsC3woXwM+FN8Fl4Pdzd/izcpf4p2Kr/Guykfw/s29yLME1XhHnKnQ/zsP0hzLJ9N8zPzFMwL5gbYC/Qr8Ie1t+DfVhfA/c6HeDuUL+B+6tagb9ZfR++oe5HOKSOI2yoOqKDOkM0pz+KaFv/APFb9GuIP2FuQXzEPIP4a/Z9kH3A5NTCGZMLt0Df4186kx30L8FshO+cMX8K98CGcB/s24Ubw48ZJqEsVIU94s4TrhAOC18KD8HdKzwu/JH4JKzCXyoMh8fgp4S7wpPwj4YT8L8VXgubCAeFQ+F5hC8K9wiPCQ0SQbhYeJ9wk/BV4f7QQPSE8AcSp8Kl4deIPyzczknjOd4jLoefI3o5HDoTvYwS4nn13Bnyd470RcIHhFuEbwqPCC8wTMYJOWFImBLuEn4q/A5x0WrhIOKCvUH4urAiNOSLc7zOXcz53EcQL7jPIF50R7kgd1x4VngF8TF/Pkf+XYiX/QjiRz1vtObvktGjiFf8c8KriKv+94hf8k8jMf4nSF7vZ5G82Q8jucT3ILnMe8KUIo8L9wpfED7GS9w7hJi/sDv8rV1DEtlvIz5nbxbeg/jv9g3E/E04hfiv5gfCEWFIPusm+l+I/6mfFx4R7uRv9W3Ch7gq/Va55ADi6xliHFHPwWY4e4bxOQt7SPic8G38BXZVaAjnCFdHrhFuE47yOgaJPIt/g0H6N/yFwvuFcfwD3PxZMAzkGeFVEi4SPiTcKnxHeER4nkSOM0fdwgeFTwkl4UG8jKjOSWMvXC5cLxSEeWIGzfAZe7sZhr3DjNcFREdNT11AdLe7sy7AfNZdWbefc1dyl3bvlPms3WO5mKkNAbYlo9b/Gf1ZRk33xg0B9s8yIog63eENgQt3120IMjosI37WYT6+IfA6M7oh8FsztiHIzEfkHkdgvmWv+oVP7FWMqb36RQHhAXvtjoCwam/9ZXIJG0/aqRqzpMWR7kTapfuRdusxoYg0p48h7dHrSHv1NtJ+A6SDpgvpqOF1k7x5OmsmkZbNNNKKmUe6YxaQObOIrFtGg2YOWd4UkBUZv2yB4czKjF+2YtqQrekmsoreRFbVy/InL17WE7xEDyFb1Dlk07oL2bzurGXHuDR+MYZsiUsjZbm4InCWZZlvwfTxF2YE2bjcbUjum5MVtBnuo2mWkNZkkRVZ8yrXki5yLem0aUea13tIR/Rp2XQZaRvXkuzrSSS7elhgvTV1G5KWaiJ1qoZ0SlWPC5xZVRsCsoKaOCFwBWr/hMBlqL4TAteiOk8IyGIZEaQt1XZCQFpUQ1sCMmB/S0C6jeUtAemmjDZlVMbqloB0AWtbAtKCjAgjpGpbAiOktrcEfqsGt9K84laHFbc6AG61H6eFFaR9mJfPZnl4qrKV7vMXXFoLWZduR9bLnWdDepDHKLGfZkh4CkU5NwZ2Ry/ggNOLONDNVDnQzz8ZkpUnkzxPRh21V39draqlqqqpJah9oruEYXUMuigsCw1iYqFPmFBzMAvCmpqGaagCrFN52JwahR1Ug7Djqh92ljuyS6qbzyhG0ja5N9emYrheYVA56EE1XtXjahx6gociNPScGoNeUSPQNQZbtzif6VQDMP2c1OSFaZ6WKatemIqwq3KwsZBTXbBDqgN2gvewcwqwy2jBbvK0bIu4nDAsTAll4bSwT3ynMCLMCktCTdhHE6FbGBQK/CzIb0OVRJIMUTfvFo0KBWFZqHEZ0T6JO4R+Li3OMxrxNFcaS3DiqrDLWCVt3FuSU8znQYYzyTOwyTTjnJQZ9mSdLxhJQ20ihdpF2qEhtc8UHdS9SMdYBmlRmsIxqY81aQoNaQotVg+rbETqrSjFzrKfMsyhKctEn7ajyObsPIvTVoVdfuYcv3XdLBIGKht1TKkBx0u6HdOxxWilNccVrDq2pTkvxelzTFHfx1XJ06/B52Wy7rnwY76MpOCrSEb9LpK+4JDEgTvfDb2I1xnL+FgYRTwZJhAPBz5m28Msor0wj6gSlhCV+a4SFRjkqF9eKzrCDsJ22GOLFBYCD2BKGBQc8ZvCvDAWmvDdYZdHG7bhapzArYYa3JwwKvQJHcRuCyvCtDDKdxWbCxVmdliHqYUVmCUeuJnm0kw+MO/7wyQTkwvXzZCHrgSm7QI3o6fCMPRIYO72hgHoOHRA1bh9tehXoab8ItSoL0DlmGiqzQ8Ae3xdwCbDiQVXAcbdHJB3eaDgBoE51wmUHYB1Hg+aTGbVxtcFlbOs2mE7BTVmOdW47YKaME2oSVOFKrCfqqKZhZrn6asy35vUKt+gVJUdXTWYJWqXLUPtsY2oPbUnnBZWoDaFRdXgBOw0alxzC4N6gLfU40CLvQQ19mJU2NtRNh3APHs7CmaCC2cLx5BZA3rMPtBl+W2n5bcdzDW026LACdq4D7JHXDs/c72AY42SPZzb9SMVtPkxoJdvFxhlSmHaTwNLntNXGUTssjxVLDHNeUZjyLOlTXhuYd5z4WsS8W3f5AGweLWknp4MbXJGHdCrTEK9G3Lsa8xEvnazoQwxHc0ED8/M8Rj/C5cxNKMejFhyLozM6PXAtkRmzHejg2yHYX0m2mGCxGMBM6ERTSMeDW4mPc27xXl+loH/emSzbnMmfiI6+r9RNitNelaPcyTNnMygyBHZmVEzmguf080ZzBoGZ87szwj/G6lP2zrP1/IXc5IqZEa9098K1eMnZnCvfw3Jac6SfYOP1GzH9NYFFrZeqpNZFjtPMCvyLLNJeXbn2UayYbWDrEceSm3y5GxKk9lUFaRLio+xOcWGMqEW+fxVfBTlVLEusMmEsbrAx3FYrAu8JCzUBb6SyKiPo6wnDNSzdoaT0ZhAshZ268kiKzQpsHEmoxHfgfuiDiQdERvjfsT2sBP1IO4OrbqA6HSEUwKiRRktyqgoIwIzwJEAMx5apwSo9lA+JbDUwsopNcVKVvMsbLXEpqAqvDnyfvMUhv0y0C8plZMM6/BMUbAkz+17pkVvqJSiFf6W1ErxJ8MlctLdpXSUjwKSK2XfdGf5KmTKpWzR7Uh/rpaye82dSKpqvYQJtc6XE46yNVZFtm7mS9k6G2hWdbVSOs72IJTiPo7ioTBaYtfbk9bXLDG5mpKYzRKTtSAZWyhhjyPMho4StmU05TZL6jzPopu0rqSuYm5gSDVK6ia+LaFl8nWBlWLm6wL7i5msCywcN1UXmDkyIsCK668LwI5fOSmwLfnKSUG61OpJAWj48klBMrb75LmaZr8ftiPfEFjOIa6orhCzH/j9ChZZiJBqZNXu4lzLrVaw7ThLp2lWVDv7FXbtfkWdtjyUZT9bUdN8+Kpu01nRsWHr29e7FXYpVsWIaauoKelhC5qHPCWMCP0ky7ti5UA7/3tP7tbjTwtI6vpHTws4cIEZefrABf4y/Afo8PkY \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 misc/OfficialChallenges/racer_#4.hwmap --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/misc/OfficialChallenges/racer_#4.hwmap Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,1 @@ +AAAA63icDcgvSwRRFIbxc+89Z86ZXdkRFgwmg0VQMAmWZWCLW1cW/0QRLLIMWARB3muwiPgJRJtgMQh+ANFglzFomaLVZNiy3vKD5+ksUEOtMtslGmdPlK35K/KFI8o2pkTS49PIE56Al7kCVzyL8BMOEJ79OcK7+4r26q9jfu8fYv7NqzHv8mF6Moo2lmm0Wy2jbckf9EUH0DcF9CQhNzqHsJctwh1JADW8A7fNPUiflqClc9B9GkIvCbAhPaJ9F4rY/vUXoNzkrPgwIbdpUocqIf2ErhjV1lhet45Tzqyn7Mwnis/0/gGJl0BN \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 misc/OfficialChallenges/racer_#5.hwmap --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/misc/OfficialChallenges/racer_#5.hwmap Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,1 @@ +AAAAtHicFc6xDsFQHIXxc3tv+48oHUw2kRKv4Am8hYjFC4hGYjuLwWRi6+QVDDazxGbpYpHYPEL1LL9845cVVsD9/BrdjR/Cju4Cv6oHSM8Ndk32sDL0gYVVzN5WQahyZJXlRNlUdIq/FLBb/KJAp44fFAjTcKBAMvFbCrR2fkmBdBbmFAgWjSngnm5EgfY96lE0f/hQ4A+Rki/Q \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 misc/OfficialChallenges/racer_#6.hwmap --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/misc/OfficialChallenges/racer_#6.hwmap Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,1 @@ +AAAAaXicAWkAlv8ITgKBAAmqA0YACZMErAAISQV1AAbfBXoABZEEsAAFVQM9AAbWAoYAB5cAqpkHlwc7AAMmA/WZDB4D9QADtAEBmQtiBvIAA7kHCZkLawD8AA2jAaaFDboGDYUBhQYthQGPAlSFB6AEC/E0HxtP \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 misc/OfficialChallenges/racer_#7.hwmap --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/misc/OfficialChallenges/racer_#7.hwmap Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,1 @@ +AAAC83icFdJraE5xHAfw7/9+zvOc55y5vnB5oVy2NXmSS0viIZdJ2NiKeEMrhQiRJP2I8U8uHcWL1d6g1Yp41nLfC9FCG4Z2DOtxF4XRRto45//i0+/Ft379v/3Qjpfwe8xcMGW2QwkzC/HrzxcNRT+Cz/xXHqP5L/zrlV/zwWf5FUG37sljgu6JY6b3WNEE0wu0ozMKKthNJET+E1OChCi9nt9DQsRSPIeEeDJVybaqSD4SdZAvxMnIm6RnICGSg2Yy+EKWC81odIaZ/WxlGFToXaF/Tg6G6YnqSGj2mlmhmSqvh/KjHBGys6otFN/ZQOge4utCLyuXhmwtllmxE7ut8thW6zK8t6nZrMN689hPG5zjTdZv4VOsv0U9tP4Q/ddmitX1hBZklsoV1pvEX9nUgMhaM1cMt6qND7OO4uMs17zLyju8w/KxrGBxkW+yqFdejO627L4Zb8UKddmK1XKRdQvqh/XKdItNaeNadUo3WOeonmNlltWTiNgCyEHsIHkczVB92E16FDrh1LICOSXsENxS9pNcy0Kky3lA6X2sC6kHbAylVsWde9VsCXnleAO/OM5lPvHl8P+yE+R34y6CdrGNghqxDf5GcZr8N9JHpkULimlLfvmWMn3yLdJ7xG1KX4vbSs/mlyj1gZfC/S00uSfEfDjnRZac1fwddANfRbqRFaCe82ZSt0QRxCP+h8Q03gRWKk4SuyC6wHKyjthV+Roo6EpCra4EP61nEP+i14A/VR7xw/IZ5Ah5kOQiZaBHymrS5TKCbhR1pB7HZ+GckWVk+uUGuEvkZnIbVRFcpuKJqR9xB/oKpafrb8nRjCLvgGqNc7qV3Fx8wM55U0POTN0HfUO3Ucxi6IypItVsmvAfnbXVgw== \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 misc/OfficialChallenges/racer_#8.hwmap --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/misc/OfficialChallenges/racer_#8.hwmap Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,1 @@ +AAACF3icHdA9aBRRFIbh795z/2Z2h7sgAbs0EpsEjKI2goUgCBaujRG0ECVYpAgEbERiWJ2BK4wgqL0Yf0Bc0BBYA9FIcMGQiQQrrSSBLGsRcGGRWKxz0jy8nOaDg6vmNqLrtAuS4gn0gshR3dDrkIv6EJJpnAa9UY3MDpkV2GGzkrk/ZbkB9d8z+7W7X/GyNmm8POghXsV6mrzUB8CkNQiC74la6nvuG/x3M5eaD2YOUaJ+N6LEXEFl3kw2KvPUQbyGX414bfAYfkYcL/wM5ZDOHsmlw0fIw2jlZgEtlHwpi+6AyelZWTRM7cJOUBtmjxYLs4czsAJpUe6nEEtoFmLJHQS9VmmQ4yoFTYqdFwxoSuxsM1AnZHWbgT4nus8Z6LOiu8VA/RB/txjQhPiXMdCzopsxiCLqZwzsT3W37XJ1AbapRtvulRpF9Sad3Cg5Bj8iL973I+YB/D3zaJOB79tOXmnaDuSYvZXLMfe0fJwdCgxETX8OTHlTrcAAA/oaGOCUfBgYiLfifGCAa/poYBBPox4YJLPiRmAgL9t6UJdsHX7cvFtlUEuc+sTgP8+NlIU= \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 misc/OfficialChallenges/racer_#9.hwmap --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/misc/OfficialChallenges/racer_#9.hwmap Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,1 @@ +AAAB1nicLY9bjsMgDEUNNjhp2syGg8TCQR0f6M+R7ftIqE2apGZNrHkTb6XJ+cTtfuJ2PXE7nrjZ/M5uU6ZUpsrkgV6YytTf6rOwLlRulUQiEWnbyFQ5lhA0IEJWqVISOXw9M6UNB2FJmL/EZMcy5oUlGIIhKH1KTIkVbgsVn/OnUfoa8ZjXiO8eTAeTB/rJdA79rT4K6wLPAsdIJIyWhUyVYwnhCshN9qLqIvEOX38zfTYchOWD+Y/YvWMZ88ISDMEQlD4lpsQKt4WKj2dR+g9qCctS \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 misc/coverity_model.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/misc/coverity_model.c Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,7 @@ +void fpcrtl_halt(int num) { + __coverity_panic__(); +} + +int fpcrtl_abs(int num) { + return num >= 0 ? num : -num; +} diff -r 31570b766315 -r ed5a6478e710 misc/liblua/CMakeLists.txt diff -r 31570b766315 -r ed5a6478e710 misc/liblua/Xcode/Lua.xcodeproj/project.pbxproj --- a/misc/liblua/Xcode/Lua.xcodeproj/project.pbxproj Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/liblua/Xcode/Lua.xcodeproj/project.pbxproj Tue Nov 10 20:43:13 2015 +0100 @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 45; + objectVersion = 46; objects = { /* Begin PBXBuildFile section */ @@ -289,8 +289,11 @@ /* Begin PBXProject section */ 0867D690FE84028FC02AAC07 /* Project object */ = { isa = PBXProject; + attributes = { + LastUpgradeCheck = 0710; + }; buildConfigurationList = 1DEB922208733DC00010E9CD /* Build configuration list for PBXProject "Lua" */; - compatibilityVersion = "Xcode 3.1"; + compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 1; knownRegions = ( @@ -354,7 +357,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; COPY_PHASE_STRIP = NO; DSTROOT = /tmp/Lua.dst; GCC_DYNAMIC_NO_PIC = NO; @@ -365,6 +367,8 @@ GCC_PREFIX_HEADER = Lua_Prefix.pch; INSTALL_PATH = /usr/local/lib; PRODUCT_NAME = Lua; + SKIP_INSTALL = YES; + VALID_ARCHS = "armv7 x86_64 arm64"; }; name = Debug; }; @@ -372,49 +376,78 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; DSTROOT = /tmp/Lua.dst; GCC_MODEL_TUNING = G5; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = Lua_Prefix.pch; INSTALL_PATH = /usr/local/lib; PRODUCT_NAME = Lua; + SKIP_INSTALL = YES; + VALID_ARCHS = "armv7 x86_64 arm64"; }; name = Release; }; 1DEB922308733DC00010E9CD /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = c99; + GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_THUMB_SUPPORT = NO; GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 3.0; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; + ONLY_ACTIVE_ARCH = YES; OTHER_LDFLAGS = "-ObjC"; PREBINDING = NO; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; + VALID_ARCHS = "armv7 armv7s arm64"; }; name = Debug; }; 1DEB922408733DC00010E9CD /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = c99; GCC_FAST_MATH = YES; + GCC_NO_COMMON_BLOCKS = YES; GCC_THUMB_SUPPORT = NO; GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 3.0; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; OTHER_LDFLAGS = "-ObjC"; PREBINDING = NO; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; + VALID_ARCHS = "armv7 armv7s arm64"; }; name = Release; }; diff -r 31570b766315 -r ed5a6478e710 misc/liblua/lapi.c --- a/misc/liblua/lapi.c Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/liblua/lapi.c Tue Nov 10 20:43:13 2015 +0100 @@ -38,9 +38,9 @@ -#define api_checknelems(L, n) api_check(L, (n) <= (L->top - L->base)) +#define api_checknelems(L, n) api_check(L, (n) <= (L->top - L->base)) -#define api_checkvalidindex(L, i) api_check(L, (i) != luaO_nilobject) +#define api_checkvalidindex(L, i) api_check(L, (i) != luaO_nilobject) #define api_incr_top(L) {api_check(L, L->top < L->ci->top); L->top++;} diff -r 31570b766315 -r ed5a6478e710 misc/liblua/lauxlib.c --- a/misc/liblua/lauxlib.c Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/liblua/lauxlib.c Tue Nov 10 20:43:13 2015 +0100 @@ -25,12 +25,12 @@ #include "lauxlib.h" -#define FREELIST_REF 0 /* free list of references */ +#define FREELIST_REF 0 /* free list of references */ /* convert a stack index to positive */ -#define abs_index(L, i) ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \ - lua_gettop(L) + (i) + 1) +#define abs_index(L, i) ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \ + lua_gettop(L) + (i) + 1) /* @@ -389,10 +389,10 @@ */ -#define bufflen(B) ((B)->p - (B)->buffer) -#define bufffree(B) ((size_t)(LUAL_BUFFERSIZE - bufflen(B))) +#define bufflen(B) ((B)->p - (B)->buffer) +#define bufffree(B) ((size_t)(LUAL_BUFFERSIZE - bufflen(B))) -#define LIMIT (LUA_MINSTACK/2) +#define LIMIT (LUA_MINSTACK/2) static int emptybuffer (luaL_Buffer *B) { @@ -574,7 +574,8 @@ lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */ if (lf.f == NULL) return errfile(L, "reopen", fnameindex); /* skip eventual `#!...' */ - while ((c = getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) ; + while ((c = getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) + /* do nothing */ ; lf.extraline = 0; } ungetc(c, lf.f); diff -r 31570b766315 -r ed5a6478e710 misc/liblua/lauxlib.h --- a/misc/liblua/lauxlib.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/liblua/lauxlib.h Tue Nov 10 20:43:13 2015 +0100 @@ -24,7 +24,7 @@ #endif #if defined(LUA_COMPAT_OPENLIB) -#define luaI_openlib luaL_openlib +#define luaI_openlib luaL_openlib #endif @@ -97,26 +97,26 @@ ** =============================================================== */ -#define luaL_argcheck(L, cond,numarg,extramsg) \ - ((void)((cond) || luaL_argerror(L, (numarg), (extramsg)))) -#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) -#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL)) -#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n))) -#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d))) -#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n))) -#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d))) +#define luaL_argcheck(L, cond,numarg,extramsg) \ + ((void)((cond) || luaL_argerror(L, (numarg), (extramsg)))) +#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) +#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL)) +#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n))) +#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d))) +#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n))) +#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d))) -#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i))) +#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i))) #define luaL_dofile(L, fn) \ - (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0)) + (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0)) #define luaL_dostring(L, s) \ - (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0)) + (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0)) -#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n))) +#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n))) -#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n))) +#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n))) /* ** {====================================================== @@ -127,7 +127,7 @@ typedef struct luaL_Buffer { - char *p; /* current position in buffer */ + char *p; /* current position in buffer */ int lvl; /* number of strings in the stack (level) */ lua_State *L; char buffer[LUAL_BUFFERSIZE]; @@ -138,9 +138,9 @@ (*(B)->p++ = (char)(c))) /* compatibility only */ -#define luaL_putchar(B,c) luaL_addchar(B,c) +#define luaL_putchar(B,c) luaL_addchar(B,c) -#define luaL_addsize(B,n) ((B)->p += (n)) +#define luaL_addsize(B,n) ((B)->p += (n)) LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B); LUALIB_API char *(luaL_prepbuffer) (luaL_Buffer *B); @@ -167,7 +167,7 @@ #define lua_getref(L,ref) lua_rawgeti(L, LUA_REGISTRYINDEX, (ref)) -#define luaL_reg luaL_Reg +#define luaL_reg luaL_Reg #endif diff -r 31570b766315 -r ed5a6478e710 misc/liblua/lbaselib.c --- a/misc/liblua/lbaselib.c Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/liblua/lbaselib.c Tue Nov 10 20:43:13 2015 +0100 @@ -479,10 +479,10 @@ ** ======================================================= */ -#define CO_RUN 0 /* running */ -#define CO_SUS 1 /* suspended */ -#define CO_NOR 2 /* 'normal' (it resumed another coroutine) */ -#define CO_DEAD 3 +#define CO_RUN 0 /* running */ +#define CO_SUS 1 /* suspended */ +#define CO_NOR 2 /* 'normal' (it resumed another coroutine) */ +#define CO_DEAD 3 static const char *const statnames[] = {"running", "suspended", "normal", "dead"}; diff -r 31570b766315 -r ed5a6478e710 misc/liblua/lcode.c --- a/misc/liblua/lcode.c Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/liblua/lcode.c Tue Nov 10 20:43:13 2015 +0100 @@ -24,7 +24,7 @@ #include "ltable.h" -#define hasjumps(e) ((e)->t != (e)->f) +#define hasjumps(e) ((e)->t != (e)->f) static int isnumeral(expdesc *e) { diff -r 31570b766315 -r ed5a6478e710 misc/liblua/lcode.h --- a/misc/liblua/lcode.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/liblua/lcode.h Tue Nov 10 20:43:13 2015 +0100 @@ -36,11 +36,11 @@ typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr; -#define getcode(fs,e) ((fs)->f->code[(e)->u.s.info]) +#define getcode(fs,e) ((fs)->f->code[(e)->u.s.info]) -#define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx) +#define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx) -#define luaK_setmultret(fs,e) luaK_setreturns(fs, e, LUA_MULTRET) +#define luaK_setmultret(fs,e) luaK_setreturns(fs, e, LUA_MULTRET) LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx); LUAI_FUNC int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C); diff -r 31570b766315 -r ed5a6478e710 misc/liblua/ldblib.c --- a/misc/liblua/ldblib.c Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/liblua/ldblib.c Tue Nov 10 20:43:13 2015 +0100 @@ -315,8 +315,8 @@ } -#define LEVELS1 12 /* size of the first part of the stack */ -#define LEVELS2 10 /* size of the second part of the stack */ +#define LEVELS1 12 /* size of the first part of the stack */ +#define LEVELS2 10 /* size of the second part of the stack */ static int db_errorfb (lua_State *L) { int level; diff -r 31570b766315 -r ed5a6478e710 misc/liblua/ldebug.c --- a/misc/liblua/ldebug.c Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/liblua/ldebug.c Tue Nov 10 20:43:13 2015 +0100 @@ -265,11 +265,11 @@ ** ======================================================= */ -#define check(x) if (!(x)) return 0; +#define check(x) if (!(x)) return 0; -#define checkjump(pt,pc) check(0 <= pc && pc < pt->sizecode) +#define checkjump(pt,pc) check(0 <= pc && pc < pt->sizecode) -#define checkreg(pt,reg) check((reg) < (pt)->maxstacksize) +#define checkreg(pt,reg) check((reg) < (pt)->maxstacksize) @@ -285,7 +285,7 @@ } -#define checkopenop(pt,pc) luaG_checkopenop((pt)->code[(pc)+1]) +#define checkopenop(pt,pc) luaG_checkopenop((pt)->code[(pc)+1]) int luaG_checkopenop (Instruction i) { switch (GET_OPCODE(i)) { diff -r 31570b766315 -r ed5a6478e710 misc/liblua/ldebug.h --- a/misc/liblua/ldebug.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/liblua/ldebug.h Tue Nov 10 20:43:13 2015 +0100 @@ -11,11 +11,11 @@ #include "lstate.h" -#define pcRel(pc, p) (cast(int, (pc) - (p)->code) - 1) +#define pcRel(pc, p) (cast(int, (pc) - (p)->code) - 1) -#define getline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : 0) +#define getline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : 0) -#define resethookcount(L) (L->hookcount = L->basehookcount) +#define resethookcount(L) (L->hookcount = L->basehookcount) LUAI_FUNC void luaG_typeerror (lua_State *L, const TValue *o, diff -r 31570b766315 -r ed5a6478e710 misc/liblua/ldo.h --- a/misc/liblua/ldo.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/liblua/ldo.h Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ #include "lzio.h" -#define luaD_checkstack(L,n) \ +#define luaD_checkstack(L,n) \ if ((char *)L->stack_last - (char *)L->top <= (n)*(int)sizeof(TValue)) \ luaD_growstack(L, n); \ else condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); @@ -21,17 +21,17 @@ #define incr_top(L) {luaD_checkstack(L,1); L->top++;} -#define savestack(L,p) ((char *)(p) - (char *)L->stack) -#define restorestack(L,n) ((TValue *)((char *)L->stack + (n))) +#define savestack(L,p) ((char *)(p) - (char *)L->stack) +#define restorestack(L,n) ((TValue *)((char *)L->stack + (n))) -#define saveci(L,p) ((char *)(p) - (char *)L->base_ci) -#define restoreci(L,n) ((CallInfo *)((char *)L->base_ci + (n))) +#define saveci(L,p) ((char *)(p) - (char *)L->base_ci) +#define restoreci(L,n) ((CallInfo *)((char *)L->base_ci + (n))) /* results from luaD_precall */ -#define PCRLUA 0 /* initiated a call to a Lua function */ -#define PCRC 1 /* did a call to a C function */ -#define PCRYIELD 2 /* C funtion yielded */ +#define PCRLUA 0 /* initiated a call to a Lua function */ +#define PCRC 1 /* did a call to a C function */ +#define PCRYIELD 2 /* C funtion yielded */ /* type of protected functions, to be ran by `runprotected' */ diff -r 31570b766315 -r ed5a6478e710 misc/liblua/ldump.c --- a/misc/liblua/ldump.c Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/liblua/ldump.c Tue Nov 10 20:43:13 2015 +0100 @@ -23,8 +23,8 @@ int status; } DumpState; -#define DumpMem(b,n,size,D) DumpBlock(b,(n)*(size),D) -#define DumpVar(x,D) DumpMem(&x,1,sizeof(x),D) +#define DumpMem(b,n,size,D) DumpBlock(b,(n)*(size),D) +#define DumpVar(x,D) DumpMem(&x,1,sizeof(x),D) static void DumpBlock(const void* b, size_t size, DumpState* D) { @@ -67,13 +67,13 @@ } else { - size_t size=s->tsv.len+1; /* include trailing '\0' */ + size_t size=s->tsv.len+1; /* include trailing '\0' */ DumpVar(size,D); DumpBlock(getstr(s),size,D); } } -#define DumpCode(f,D) DumpVector(f->code,f->sizecode,sizeof(Instruction),D) +#define DumpCode(f,D) DumpVector(f->code,f->sizecode,sizeof(Instruction),D) static void DumpFunction(const Proto* f, const TString* p, DumpState* D); @@ -88,19 +88,19 @@ switch (ttype(o)) { case LUA_TNIL: - break; + break; case LUA_TBOOLEAN: - DumpChar(bvalue(o),D); - break; + DumpChar(bvalue(o),D); + break; case LUA_TNUMBER: - DumpNumber(nvalue(o),D); - break; + DumpNumber(nvalue(o),D); + break; case LUA_TSTRING: - DumpString(rawtsvalue(o),D); - break; + DumpString(rawtsvalue(o),D); + break; default: - lua_assert(0); /* cannot happen */ - break; + lua_assert(0); /* cannot happen */ + break; } } n=f->sizep; diff -r 31570b766315 -r ed5a6478e710 misc/liblua/lfunc.h --- a/misc/liblua/lfunc.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/liblua/lfunc.h Tue Nov 10 20:43:13 2015 +0100 @@ -11,10 +11,10 @@ #include "lobject.h" -#define sizeCclosure(n) (cast(int, sizeof(CClosure)) + \ +#define sizeCclosure(n) (cast(int, sizeof(CClosure)) + \ cast(int, sizeof(TValue)*((n)-1))) -#define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \ +#define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \ cast(int, sizeof(TValue *)*((n)-1))) diff -r 31570b766315 -r ed5a6478e710 misc/liblua/lgc.c --- a/misc/liblua/lgc.c Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/liblua/lgc.c Tue Nov 10 20:43:13 2015 +0100 @@ -23,25 +23,25 @@ #include "ltm.h" -#define GCSTEPSIZE 1024u -#define GCSWEEPMAX 40 -#define GCSWEEPCOST 10 -#define GCFINALIZECOST 100 +#define GCSTEPSIZE 1024u +#define GCSWEEPMAX 40 +#define GCSWEEPCOST 10 +#define GCFINALIZECOST 100 -#define maskmarks cast_byte(~(bitmask(BLACKBIT)|WHITEBITS)) +#define maskmarks cast_byte(~(bitmask(BLACKBIT)|WHITEBITS)) -#define makewhite(g,x) \ +#define makewhite(g,x) \ ((x)->gch.marked = cast_byte(((x)->gch.marked & maskmarks) | luaC_white(g))) -#define white2gray(x) reset2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) -#define black2gray(x) resetbit((x)->gch.marked, BLACKBIT) +#define white2gray(x) reset2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) +#define black2gray(x) resetbit((x)->gch.marked, BLACKBIT) -#define stringmark(s) reset2bits((s)->tsv.marked, WHITE0BIT, WHITE1BIT) +#define stringmark(s) reset2bits((s)->tsv.marked, WHITE0BIT, WHITE1BIT) -#define isfinalized(u) testbit((u)->marked, FINALIZEDBIT) -#define markfinalized(u) l_setbit((u)->marked, FINALIZEDBIT) +#define isfinalized(u) testbit((u)->marked, FINALIZEDBIT) +#define markfinalized(u) l_setbit((u)->marked, FINALIZEDBIT) #define KEYWEAK bitmask(KEYWEAKBIT) @@ -53,7 +53,7 @@ if (iscollectable(o) && iswhite(gcvalue(o))) reallymarkobject(g,gcvalue(o)); } #define markobject(g,t) { if (iswhite(obj2gco(t))) \ - reallymarkobject(g, obj2gco(t)); } + reallymarkobject(g, obj2gco(t)); } #define setthreshold(g) (g->GCthreshold = (g->estimate/100) * g->gcpause) @@ -401,7 +401,7 @@ -#define sweepwholelist(L,p) sweeplist(L,p,MAX_LUMEM) +#define sweepwholelist(L,p) sweeplist(L,p,MAX_LUMEM) static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { diff -r 31570b766315 -r ed5a6478e710 misc/liblua/lgc.h --- a/misc/liblua/lgc.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/liblua/lgc.h Tue Nov 10 20:43:13 2015 +0100 @@ -14,27 +14,27 @@ /* ** Possible states of the Garbage Collector */ -#define GCSpause 0 -#define GCSpropagate 1 -#define GCSsweepstring 2 -#define GCSsweep 3 -#define GCSfinalize 4 +#define GCSpause 0 +#define GCSpropagate 1 +#define GCSsweepstring 2 +#define GCSsweep 3 +#define GCSfinalize 4 /* ** some userful bit tricks */ -#define resetbits(x,m) ((x) &= cast(lu_byte, ~(m))) -#define setbits(x,m) ((x) |= (m)) -#define testbits(x,m) ((x) & (m)) -#define bitmask(b) (1<<(b)) -#define bit2mask(b1,b2) (bitmask(b1) | bitmask(b2)) -#define l_setbit(x,b) setbits(x, bitmask(b)) -#define resetbit(x,b) resetbits(x, bitmask(b)) -#define testbit(x,b) testbits(x, bitmask(b)) -#define set2bits(x,b1,b2) setbits(x, (bit2mask(b1, b2))) -#define reset2bits(x,b1,b2) resetbits(x, (bit2mask(b1, b2))) -#define test2bits(x,b1,b2) testbits(x, (bit2mask(b1, b2))) +#define resetbits(x,m) ((x) &= cast(lu_byte, ~(m))) +#define setbits(x,m) ((x) |= (m)) +#define testbits(x,m) ((x) & (m)) +#define bitmask(b) (1<<(b)) +#define bit2mask(b1,b2) (bitmask(b1) | bitmask(b2)) +#define l_setbit(x,b) setbits(x, bitmask(b)) +#define resetbit(x,b) resetbits(x, bitmask(b)) +#define testbit(x,b) testbits(x, bitmask(b)) +#define set2bits(x,b1,b2) setbits(x, (bit2mask(b1, b2))) +#define reset2bits(x,b1,b2) resetbits(x, (bit2mask(b1, b2))) +#define test2bits(x,b1,b2) testbits(x, (bit2mask(b1, b2))) @@ -51,47 +51,47 @@ */ -#define WHITE0BIT 0 -#define WHITE1BIT 1 -#define BLACKBIT 2 -#define FINALIZEDBIT 3 -#define KEYWEAKBIT 3 -#define VALUEWEAKBIT 4 -#define FIXEDBIT 5 -#define SFIXEDBIT 6 -#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) +#define WHITE0BIT 0 +#define WHITE1BIT 1 +#define BLACKBIT 2 +#define FINALIZEDBIT 3 +#define KEYWEAKBIT 3 +#define VALUEWEAKBIT 4 +#define FIXEDBIT 5 +#define SFIXEDBIT 6 +#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) #define iswhite(x) test2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) #define isblack(x) testbit((x)->gch.marked, BLACKBIT) -#define isgray(x) (!isblack(x) && !iswhite(x)) +#define isgray(x) (!isblack(x) && !iswhite(x)) -#define otherwhite(g) (g->currentwhite ^ WHITEBITS) -#define isdead(g,v) ((v)->gch.marked & otherwhite(g) & WHITEBITS) +#define otherwhite(g) (g->currentwhite ^ WHITEBITS) +#define isdead(g,v) ((v)->gch.marked & otherwhite(g) & WHITEBITS) -#define changewhite(x) ((x)->gch.marked ^= WHITEBITS) -#define gray2black(x) l_setbit((x)->gch.marked, BLACKBIT) +#define changewhite(x) ((x)->gch.marked ^= WHITEBITS) +#define gray2black(x) l_setbit((x)->gch.marked, BLACKBIT) -#define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x))) +#define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x))) -#define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS) +#define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS) #define luaC_checkGC(L) { \ condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); \ if (G(L)->totalbytes >= G(L)->GCthreshold) \ - luaC_step(L); } + luaC_step(L); } #define luaC_barrier(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \ - luaC_barrierf(L,obj2gco(p),gcvalue(v)); } + luaC_barrierf(L,obj2gco(p),gcvalue(v)); } #define luaC_barriert(L,t,v) { if (valiswhite(v) && isblack(obj2gco(t))) \ - luaC_barrierback(L,t); } + luaC_barrierback(L,t); } #define luaC_objbarrier(L,p,o) \ - { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \ - luaC_barrierf(L,obj2gco(p),obj2gco(o)); } + { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \ + luaC_barrierf(L,obj2gco(p),obj2gco(o)); } #define luaC_objbarriert(L,t,o) \ { if (iswhite(obj2gco(o)) && isblack(obj2gco(t))) luaC_barrierback(L,t); } diff -r 31570b766315 -r ed5a6478e710 misc/liblua/liolib.c --- a/misc/liblua/liolib.c Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/liblua/liolib.c Tue Nov 10 20:43:13 2015 +0100 @@ -20,8 +20,8 @@ -#define IO_INPUT 1 -#define IO_OUTPUT 2 +#define IO_INPUT 1 +#define IO_OUTPUT 2 static const char *const fnames[] = {"input", "output"}; @@ -51,7 +51,7 @@ } -#define tofilep(L) ((FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE)) +#define tofilep(L) ((FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE)) static int io_type (lua_State *L) { diff -r 31570b766315 -r ed5a6478e710 misc/liblua/llex.c --- a/misc/liblua/llex.c Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/liblua/llex.c Tue Nov 10 20:43:13 2015 +0100 @@ -30,7 +30,7 @@ -#define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r') +#define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r') /* ORDER RESERVED */ diff -r 31570b766315 -r ed5a6478e710 misc/liblua/llex.h --- a/misc/liblua/llex.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/liblua/llex.h Tue Nov 10 20:43:13 2015 +0100 @@ -11,10 +11,10 @@ #include "lzio.h" -#define FIRST_RESERVED 257 +#define FIRST_RESERVED 257 /* maximum length of a reserved word */ -#define TOKEN_LEN (sizeof("function")/sizeof(char)) +#define TOKEN_LEN (sizeof("function")/sizeof(char)) /* @@ -33,7 +33,7 @@ }; /* number of reserved words */ -#define NUM_RESERVED (cast(int, TK_WHILE-FIRST_RESERVED+1)) +#define NUM_RESERVED (cast(int, TK_WHILE-FIRST_RESERVED+1)) /* array with token `names' */ diff -r 31570b766315 -r ed5a6478e710 misc/liblua/llimits.h --- a/misc/liblua/llimits.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/liblua/llimits.h Tue Nov 10 20:43:13 2015 +0100 @@ -27,9 +27,9 @@ typedef unsigned char lu_byte; -#define MAX_SIZET ((size_t)(~(size_t)0)-2) +#define MAX_SIZET ((size_t)(~(size_t)0)-2) -#define MAX_LUMEM ((lu_mem)(~(lu_mem)0)-2) +#define MAX_LUMEM ((lu_mem)(~(lu_mem)0)-2) #define MAX_INT (INT_MAX-2) /* maximum value of an int (-2 for safety) */ @@ -54,30 +54,30 @@ /* internal assertions for in-house debugging */ #ifdef lua_assert -#define check_exp(c,e) (lua_assert(c), (e)) -#define api_check(l,e) lua_assert(e) +#define check_exp(c,e) (lua_assert(c), (e)) +#define api_check(l,e) lua_assert(e) #else -#define lua_assert(c) ((void)0) -#define check_exp(c,e) (e) -#define api_check luai_apicheck +#define lua_assert(c) ((void)0) +#define check_exp(c,e) (e) +#define api_check luai_apicheck #endif #ifndef UNUSED -#define UNUSED(x) ((void)(x)) /* to avoid warnings */ +#define UNUSED(x) ((void)(x)) /* to avoid warnings */ #endif #ifndef cast -#define cast(t, exp) ((t)(exp)) +#define cast(t, exp) ((t)(exp)) #endif -#define cast_byte(i) cast(lu_byte, (i)) -#define cast_num(i) cast(lua_Number, (i)) -#define cast_int(i) cast(int, (i)) +#define cast_byte(i) cast(lu_byte, (i)) +#define cast_num(i) cast(lua_Number, (i)) +#define cast_int(i) cast(int, (i)) @@ -90,19 +90,19 @@ /* maximum stack for a Lua function */ -#define MAXSTACK 250 +#define MAXSTACK 250 /* minimum size for the string table (must be power of 2) */ #ifndef MINSTRTABSIZE -#define MINSTRTABSIZE 32 +#define MINSTRTABSIZE 32 #endif /* minimum size for string buffer */ #ifndef LUA_MINBUFFER -#define LUA_MINBUFFER 32 +#define LUA_MINBUFFER 32 #endif @@ -120,9 +120,9 @@ ** macro to control inclusion of some hard tests on stack reallocation */ #ifndef HARDSTACKTESTS -#define condhardstacktests(x) ((void)0) +#define condhardstacktests(x) ((void)0) #else -#define condhardstacktests(x) x +#define condhardstacktests(x) x #endif #endif diff -r 31570b766315 -r ed5a6478e710 misc/liblua/lmem.c --- a/misc/liblua/lmem.c Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/liblua/lmem.c Tue Nov 10 20:43:13 2015 +0100 @@ -40,7 +40,7 @@ -#define MINSIZEARRAY 4 +#define MINSIZEARRAY 4 void *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems, diff -r 31570b766315 -r ed5a6478e710 misc/liblua/lmem.h --- a/misc/liblua/lmem.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/liblua/lmem.h Tue Nov 10 20:43:13 2015 +0100 @@ -13,22 +13,22 @@ #include "llimits.h" #include "lua.h" -#define MEMERRMSG "not enough memory" +#define MEMERRMSG "not enough memory" #define luaM_reallocv(L,b,on,n,e) \ - ((cast(size_t, (n)+1) <= MAX_SIZET/(e)) ? /* +1 to avoid warnings */ \ - luaM_realloc_(L, (b), (on)*(e), (n)*(e)) : \ - luaM_toobig(L)) + ((cast(size_t, (n)+1) <= MAX_SIZET/(e)) ? /* +1 to avoid warnings */ \ + luaM_realloc_(L, (b), (on)*(e), (n)*(e)) : \ + luaM_toobig(L)) -#define luaM_freemem(L, b, s) luaM_realloc_(L, (b), (s), 0) -#define luaM_free(L, b) luaM_realloc_(L, (b), sizeof(*(b)), 0) +#define luaM_freemem(L, b, s) luaM_realloc_(L, (b), (s), 0) +#define luaM_free(L, b) luaM_realloc_(L, (b), sizeof(*(b)), 0) #define luaM_freearray(L, b, n, t) luaM_reallocv(L, (b), n, 0, sizeof(t)) -#define luaM_malloc(L,t) luaM_realloc_(L, NULL, 0, (t)) -#define luaM_new(L,t) cast(t *, luaM_malloc(L, sizeof(t))) +#define luaM_malloc(L,t) luaM_realloc_(L, NULL, 0, (t)) +#define luaM_new(L,t) cast(t *, luaM_malloc(L, sizeof(t))) #define luaM_newvector(L,n,t) \ - cast(t *, luaM_reallocv(L, NULL, 0, n, sizeof(t))) + cast(t *, luaM_reallocv(L, NULL, 0, n, sizeof(t))) #define luaM_growvector(L,v,nelems,size,t,limit,e) \ if ((nelems)+1 > (size)) \ diff -r 31570b766315 -r ed5a6478e710 misc/liblua/loadlib.c --- a/misc/liblua/loadlib.c Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/liblua/loadlib.c Tue Nov 10 20:43:13 2015 +0100 @@ -23,23 +23,23 @@ /* prefix for open functions in C libraries */ -#define LUA_POF "luaopen_" +#define LUA_POF "luaopen_" /* separator for open functions in C libraries */ -#define LUA_OFSEP "_" +#define LUA_OFSEP "_" -#define LIBPREFIX "LOADLIB: " +#define LIBPREFIX "LOADLIB: " -#define POF LUA_POF -#define LIB_FAIL "open" +#define POF LUA_POF +#define LIB_FAIL "open" /* error codes for ll_loadfunc */ -#define ERRLIB 1 -#define ERRFUNC 2 +#define ERRLIB 1 +#define ERRFUNC 2 -#define setprogdir(L) ((void)0) +#define setprogdir(L) ((void)0) static void ll_unloadlib (void *lib); @@ -153,7 +153,7 @@ /* Mac appends a `_' before C function names */ #undef POF -#define POF "_" LUA_POF +#define POF "_" LUA_POF static void pusherror (lua_State *L) { @@ -230,10 +230,10 @@ */ #undef LIB_FAIL -#define LIB_FAIL "absent" +#define LIB_FAIL "absent" -#define DLMSG "dynamic libraries not enabled; check your Lua installation" +#define DLMSG "dynamic libraries not enabled; check your Lua installation" static void ll_unloadlib (void *lib) { @@ -445,7 +445,7 @@ static const int sentinel_ = 0; -#define sentinel ((void *)&sentinel_) +#define sentinel ((void *)&sentinel_) static int ll_require (lua_State *L) { @@ -587,7 +587,7 @@ /* auxiliary mark (for internal use) */ -#define AUXMARK "\1" +#define AUXMARK "\1" static void setpath (lua_State *L, const char *fieldname, const char *envname, const char *def) { diff -r 31570b766315 -r ed5a6478e710 misc/liblua/lobject.h --- a/misc/liblua/lobject.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/liblua/lobject.h Tue Nov 10 20:43:13 2015 +0100 @@ -17,17 +17,17 @@ /* tags for values visible from Lua */ -#define LAST_TAG LUA_TTHREAD +#define LAST_TAG LUA_TTHREAD -#define NUM_TAGS (LAST_TAG+1) +#define NUM_TAGS (LAST_TAG+1) /* ** Extra tags for non-values */ -#define LUA_TPROTO (LAST_TAG+1) -#define LUA_TUPVAL (LAST_TAG+2) -#define LUA_TDEADKEY (LAST_TAG+3) +#define LUA_TPROTO (LAST_TAG+1) +#define LUA_TUPVAL (LAST_TAG+2) +#define LUA_TDEADKEY (LAST_TAG+3) /* @@ -40,7 +40,7 @@ ** Common Header for all collectable objects (in macro form, to be ** included in other objects) */ -#define CommonHeader GCObject *next; lu_byte tt; lu_byte marked +#define CommonHeader GCObject *next; lu_byte tt; lu_byte marked /* @@ -68,7 +68,7 @@ ** Tagged Values */ -#define TValuefields Value value; int tt +#define TValuefields Value value; int tt typedef struct lua_TValue { TValuefields; @@ -76,31 +76,31 @@ /* Macros to test type */ -#define ttisnil(o) (ttype(o) == LUA_TNIL) -#define ttisnumber(o) (ttype(o) == LUA_TNUMBER) -#define ttisstring(o) (ttype(o) == LUA_TSTRING) -#define ttistable(o) (ttype(o) == LUA_TTABLE) -#define ttisfunction(o) (ttype(o) == LUA_TFUNCTION) -#define ttisboolean(o) (ttype(o) == LUA_TBOOLEAN) -#define ttisuserdata(o) (ttype(o) == LUA_TUSERDATA) -#define ttisthread(o) (ttype(o) == LUA_TTHREAD) -#define ttislightuserdata(o) (ttype(o) == LUA_TLIGHTUSERDATA) +#define ttisnil(o) (ttype(o) == LUA_TNIL) +#define ttisnumber(o) (ttype(o) == LUA_TNUMBER) +#define ttisstring(o) (ttype(o) == LUA_TSTRING) +#define ttistable(o) (ttype(o) == LUA_TTABLE) +#define ttisfunction(o) (ttype(o) == LUA_TFUNCTION) +#define ttisboolean(o) (ttype(o) == LUA_TBOOLEAN) +#define ttisuserdata(o) (ttype(o) == LUA_TUSERDATA) +#define ttisthread(o) (ttype(o) == LUA_TTHREAD) +#define ttislightuserdata(o) (ttype(o) == LUA_TLIGHTUSERDATA) /* Macros to access values */ -#define ttype(o) ((o)->tt) -#define gcvalue(o) check_exp(iscollectable(o), (o)->value.gc) -#define pvalue(o) check_exp(ttislightuserdata(o), (o)->value.p) -#define nvalue(o) check_exp(ttisnumber(o), (o)->value.n) -#define rawtsvalue(o) check_exp(ttisstring(o), &(o)->value.gc->ts) -#define tsvalue(o) (&rawtsvalue(o)->tsv) -#define rawuvalue(o) check_exp(ttisuserdata(o), &(o)->value.gc->u) -#define uvalue(o) (&rawuvalue(o)->uv) -#define clvalue(o) check_exp(ttisfunction(o), &(o)->value.gc->cl) -#define hvalue(o) check_exp(ttistable(o), &(o)->value.gc->h) -#define bvalue(o) check_exp(ttisboolean(o), (o)->value.b) -#define thvalue(o) check_exp(ttisthread(o), &(o)->value.gc->th) +#define ttype(o) ((o)->tt) +#define gcvalue(o) check_exp(iscollectable(o), (o)->value.gc) +#define pvalue(o) check_exp(ttislightuserdata(o), (o)->value.p) +#define nvalue(o) check_exp(ttisnumber(o), (o)->value.n) +#define rawtsvalue(o) check_exp(ttisstring(o), &(o)->value.gc->ts) +#define tsvalue(o) (&rawtsvalue(o)->tsv) +#define rawuvalue(o) check_exp(ttisuserdata(o), &(o)->value.gc->u) +#define uvalue(o) (&rawuvalue(o)->uv) +#define clvalue(o) check_exp(ttisfunction(o), &(o)->value.gc->cl) +#define hvalue(o) check_exp(ttistable(o), &(o)->value.gc->h) +#define bvalue(o) check_exp(ttisboolean(o), (o)->value.b) +#define thvalue(o) check_exp(ttisthread(o), &(o)->value.gc->th) -#define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0)) +#define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0)) /* ** for internal debug only @@ -169,24 +169,24 @@ */ /* from stack to (same) stack */ -#define setobjs2s setobj +#define setobjs2s setobj /* to stack (not from same stack) */ -#define setobj2s setobj -#define setsvalue2s setsvalue -#define sethvalue2s sethvalue -#define setptvalue2s setptvalue +#define setobj2s setobj +#define setsvalue2s setsvalue +#define sethvalue2s sethvalue +#define setptvalue2s setptvalue /* from table to same table */ -#define setobjt2t setobj +#define setobjt2t setobj /* to table */ -#define setobj2t setobj +#define setobj2t setobj /* to new object */ -#define setobj2n setobj -#define setsvalue2n setsvalue +#define setobj2n setobj +#define setsvalue2n setsvalue #define setttype(obj, tt) (ttype(obj) = (tt)) -#define iscollectable(o) (ttype(o) >= LUA_TSTRING) +#define iscollectable(o) (ttype(o) >= LUA_TSTRING) @@ -207,7 +207,7 @@ } TString; -#define getstr(ts) cast(const char *, (ts) + 1) +#define getstr(ts) cast(const char *, (ts) + 1) #define svalue(o) getstr(rawtsvalue(o)) @@ -254,9 +254,9 @@ /* masks for new-style vararg */ -#define VARARG_HASARG 1 -#define VARARG_ISVARARG 2 -#define VARARG_NEEDSARG 4 +#define VARARG_HASARG 1 +#define VARARG_ISVARARG 2 +#define VARARG_NEEDSARG 4 typedef struct LocVar { @@ -289,8 +289,8 @@ */ #define ClosureHeader \ - CommonHeader; lu_byte isC; lu_byte nupvalues; GCObject *gclist; \ - struct Table *env + CommonHeader; lu_byte isC; lu_byte nupvalues; GCObject *gclist; \ + struct Table *env typedef struct CClosure { ClosureHeader; @@ -312,8 +312,8 @@ } Closure; -#define iscfunction(o) (ttype(o) == LUA_TFUNCTION && clvalue(o)->c.isC) -#define isLfunction(o) (ttype(o) == LUA_TFUNCTION && !clvalue(o)->c.isC) +#define iscfunction(o) (ttype(o) == LUA_TFUNCTION && clvalue(o)->c.isC) +#define isLfunction(o) (ttype(o) == LUA_TFUNCTION && !clvalue(o)->c.isC) /* @@ -353,18 +353,18 @@ ** `module' operation for hashing (size is always a power of 2) */ #define lmod(s,size) \ - (check_exp((size&(size-1))==0, (cast(int, (s) & ((size)-1))))) + (check_exp((size&(size-1))==0, (cast(int, (s) & ((size)-1))))) -#define twoto(x) (1<<(x)) -#define sizenode(t) (twoto((t)->lsizenode)) +#define twoto(x) (1<<(x)) +#define sizenode(t) (twoto((t)->lsizenode)) -#define luaO_nilobject (&luaO_nilobject_) +#define luaO_nilobject (&luaO_nilobject_) LUAI_DATA const TValue luaO_nilobject_; -#define ceillog2(x) (luaO_log2((x)-1) + 1) +#define ceillog2(x) (luaO_log2((x)-1) + 1) LUAI_FUNC int luaO_log2 (unsigned int x); LUAI_FUNC int luaO_int2fb (unsigned int x); diff -r 31570b766315 -r ed5a6478e710 misc/liblua/lopcodes.c --- a/misc/liblua/lopcodes.c Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/liblua/lopcodes.c Tue Nov 10 20:43:13 2015 +0100 @@ -59,44 +59,44 @@ #define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m)) const lu_byte luaP_opmodes[NUM_OPCODES] = { -/* T A B C mode opcode */ - opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_MOVE */ - ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_LOADK */ - ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_LOADBOOL */ - ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LOADNIL */ - ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */ - ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_GETGLOBAL */ - ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_GETTABLE */ - ,opmode(0, 0, OpArgK, OpArgN, iABx) /* OP_SETGLOBAL */ - ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_SETUPVAL */ - ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABLE */ - ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_NEWTABLE */ - ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_SELF */ - ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_ADD */ - ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SUB */ - ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MUL */ - ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_DIV */ - ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MOD */ - ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_POW */ - ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_UNM */ - ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_NOT */ - ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LEN */ - ,opmode(0, 1, OpArgR, OpArgR, iABC) /* OP_CONCAT */ - ,opmode(0, 0, OpArgR, OpArgN, iAsBx) /* OP_JMP */ - ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_EQ */ - ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LT */ - ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LE */ - ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TEST */ - ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TESTSET */ - ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_CALL */ - ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_TAILCALL */ - ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_RETURN */ - ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORLOOP */ - ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORPREP */ - ,opmode(1, 0, OpArgN, OpArgU, iABC) /* OP_TFORLOOP */ - ,opmode(0, 0, OpArgU, OpArgU, iABC) /* OP_SETLIST */ - ,opmode(0, 0, OpArgN, OpArgN, iABC) /* OP_CLOSE */ - ,opmode(0, 1, OpArgU, OpArgN, iABx) /* OP_CLOSURE */ - ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_VARARG */ +/* T A B C mode opcode */ + opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_MOVE */ + ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_LOADK */ + ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_LOADBOOL */ + ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LOADNIL */ + ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */ + ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_GETGLOBAL */ + ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_GETTABLE */ + ,opmode(0, 0, OpArgK, OpArgN, iABx) /* OP_SETGLOBAL */ + ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_SETUPVAL */ + ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABLE */ + ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_NEWTABLE */ + ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_SELF */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_ADD */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SUB */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MUL */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_DIV */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MOD */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_POW */ + ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_UNM */ + ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_NOT */ + ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LEN */ + ,opmode(0, 1, OpArgR, OpArgR, iABC) /* OP_CONCAT */ + ,opmode(0, 0, OpArgR, OpArgN, iAsBx) /* OP_JMP */ + ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_EQ */ + ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LT */ + ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LE */ + ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TEST */ + ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TESTSET */ + ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_CALL */ + ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_TAILCALL */ + ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_RETURN */ + ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORLOOP */ + ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORPREP */ + ,opmode(1, 0, OpArgN, OpArgU, iABC) /* OP_TFORLOOP */ + ,opmode(0, 0, OpArgU, OpArgU, iABC) /* OP_SETLIST */ + ,opmode(0, 0, OpArgN, OpArgN, iABC) /* OP_CLOSE */ + ,opmode(0, 1, OpArgU, OpArgN, iABx) /* OP_CLOSURE */ + ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_VARARG */ }; diff -r 31570b766315 -r ed5a6478e710 misc/liblua/lopcodes.h --- a/misc/liblua/lopcodes.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/liblua/lopcodes.h Tue Nov 10 20:43:13 2015 +0100 @@ -14,11 +14,11 @@ We assume that instructions are unsigned numbers. All instructions have an opcode in the first 6 bits. Instructions can have the following fields: - `A' : 8 bits - `B' : 9 bits - `C' : 9 bits - `Bx' : 18 bits (`B' and `C' together) - `sBx' : signed Bx + `A' : 8 bits + `B' : 9 bits + `C' : 9 bits + `Bx' : 18 bits (`B' and `C' together) + `sBx' : signed Bx A signed argument is represented in excess K; that is, the number value is the unsigned value minus K. K is exactly the maximum value @@ -34,18 +34,18 @@ /* ** size and position of opcode arguments. */ -#define SIZE_C 9 -#define SIZE_B 9 -#define SIZE_Bx (SIZE_C + SIZE_B) -#define SIZE_A 8 +#define SIZE_C 9 +#define SIZE_B 9 +#define SIZE_Bx (SIZE_C + SIZE_B) +#define SIZE_A 8 -#define SIZE_OP 6 +#define SIZE_OP 6 -#define POS_OP 0 -#define POS_A (POS_OP + SIZE_OP) -#define POS_C (POS_A + SIZE_A) -#define POS_B (POS_C + SIZE_C) -#define POS_Bx POS_C +#define POS_OP 0 +#define POS_A (POS_OP + SIZE_OP) +#define POS_C (POS_A + SIZE_A) +#define POS_B (POS_C + SIZE_C) +#define POS_Bx POS_C /* @@ -68,47 +68,47 @@ /* creates a mask with `n' 1 bits at position `p' */ -#define MASK1(n,p) ((~((~(Instruction)0)<>POS_OP) & MASK1(SIZE_OP,0))) -#define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \ - ((cast(Instruction, o)<>POS_OP) & MASK1(SIZE_OP,0))) +#define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \ + ((cast(Instruction, o)<>POS_A) & MASK1(SIZE_A,0))) -#define SETARG_A(i,u) ((i) = (((i)&MASK0(SIZE_A,POS_A)) | \ - ((cast(Instruction, u)<>POS_A) & MASK1(SIZE_A,0))) +#define SETARG_A(i,u) ((i) = (((i)&MASK0(SIZE_A,POS_A)) | \ + ((cast(Instruction, u)<>POS_B) & MASK1(SIZE_B,0))) -#define SETARG_B(i,b) ((i) = (((i)&MASK0(SIZE_B,POS_B)) | \ - ((cast(Instruction, b)<>POS_B) & MASK1(SIZE_B,0))) +#define SETARG_B(i,b) ((i) = (((i)&MASK0(SIZE_B,POS_B)) | \ + ((cast(Instruction, b)<>POS_C) & MASK1(SIZE_C,0))) -#define SETARG_C(i,b) ((i) = (((i)&MASK0(SIZE_C,POS_C)) | \ - ((cast(Instruction, b)<>POS_C) & MASK1(SIZE_C,0))) +#define SETARG_C(i,b) ((i) = (((i)&MASK0(SIZE_C,POS_C)) | \ + ((cast(Instruction, b)<>POS_Bx) & MASK1(SIZE_Bx,0))) -#define SETARG_Bx(i,b) ((i) = (((i)&MASK0(SIZE_Bx,POS_Bx)) | \ - ((cast(Instruction, b)<>POS_Bx) & MASK1(SIZE_Bx,0))) +#define SETARG_Bx(i,b) ((i) = (((i)&MASK0(SIZE_Bx,POS_Bx)) | \ + ((cast(Instruction, b)< C) then pc++ */ -OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ +OP_TEST,/* A C if not (R(A) <=> C) then pc++ */ +OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ -OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ -OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ -OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */ +OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ +OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ +OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */ -OP_FORLOOP,/* A sBx R(A)+=R(A+2); - if R(A) =) R(A)*/ -OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */ +OP_CLOSE,/* A close all variables in the stack up to (>=) R(A)*/ +OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */ -OP_VARARG/* A B R(A), R(A+1), ..., R(A+B-1) = vararg */ +OP_VARARG/* A B R(A), R(A+1), ..., R(A+B-1) = vararg */ } OpCode; -#define NUM_OPCODES (cast(int, OP_VARARG) + 1) +#define NUM_OPCODES (cast(int, OP_VARARG) + 1) @@ -251,18 +251,18 @@ LUAI_DATA const lu_byte luaP_opmodes[NUM_OPCODES]; -#define getOpMode(m) (cast(enum OpMode, luaP_opmodes[m] & 3)) -#define getBMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 4) & 3)) -#define getCMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 2) & 3)) -#define testAMode(m) (luaP_opmodes[m] & (1 << 6)) -#define testTMode(m) (luaP_opmodes[m] & (1 << 7)) +#define getOpMode(m) (cast(enum OpMode, luaP_opmodes[m] & 3)) +#define getBMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 4) & 3)) +#define getCMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 2) & 3)) +#define testAMode(m) (luaP_opmodes[m] & (1 << 6)) +#define testTMode(m) (luaP_opmodes[m] & (1 << 7)) LUAI_DATA const char *const luaP_opnames[NUM_OPCODES+1]; /* opcode names */ /* number of list items to accumulate before a SETLIST instruction */ -#define LFIELDS_PER_FLUSH 50 +#define LFIELDS_PER_FLUSH 50 #endif diff -r 31570b766315 -r ed5a6478e710 misc/liblua/lparser.c --- a/misc/liblua/lparser.c Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/liblua/lparser.c Tue Nov 10 20:43:13 2015 +0100 @@ -27,11 +27,11 @@ -#define hasmultret(k) ((k) == VCALL || (k) == VVARARG) +#define hasmultret(k) ((k) == VCALL || (k) == VVARARG) -#define getlocvar(fs, i) ((fs)->f->locvars[(fs)->actvar[i]]) +#define getlocvar(fs, i) ((fs)->f->locvars[(fs)->actvar[i]]) -#define luaY_checklimit(fs,v,l,m) if ((v)>(l)) errorlimit(fs,l,m) +#define luaY_checklimit(fs,v,l,m) if ((v)>(l)) errorlimit(fs,l,m) /* @@ -97,7 +97,7 @@ } -#define check_condition(ls,c,msg) { if (!(c)) luaX_syntaxerror(ls, msg); } +#define check_condition(ls,c,msg) { if (!(c)) luaX_syntaxerror(ls, msg); } @@ -275,11 +275,11 @@ static void enterlevel (LexState *ls) { if (++ls->L->nCcalls > LUAI_MAXCCALLS) - luaX_lexerror(ls, "chunk has too many syntax levels", 0); + luaX_lexerror(ls, "chunk has too many syntax levels", 0); } -#define leavelevel(ls) ((ls)->L->nCcalls--) +#define leavelevel(ls) ((ls)->L->nCcalls--) static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isbreakable) { @@ -818,7 +818,7 @@ {2, 2}, {1, 1} /* logical (and/or) */ }; -#define UNARY_PRIORITY 8 /* priority for unary operators */ +#define UNARY_PRIORITY 8 /* priority for unary operators */ /* diff -r 31570b766315 -r ed5a6478e710 misc/liblua/lparser.h --- a/misc/liblua/lparser.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/liblua/lparser.h Tue Nov 10 20:43:13 2015 +0100 @@ -17,21 +17,21 @@ */ typedef enum { - VVOID, /* no value */ + VVOID, /* no value */ VNIL, VTRUE, VFALSE, - VK, /* info = index of constant in `k' */ - VKNUM, /* nval = numerical value */ - VLOCAL, /* info = local register */ + VK, /* info = index of constant in `k' */ + VKNUM, /* nval = numerical value */ + VLOCAL, /* info = local register */ VUPVAL, /* info = index of upvalue in `upvalues' */ - VGLOBAL, /* info = index of table; aux = index of global name in `k' */ - VINDEXED, /* info = table register; aux = index register (or `k') */ - VJMP, /* info = instruction pc */ - VRELOCABLE, /* info = instruction pc */ - VNONRELOC, /* info = result register */ - VCALL, /* info = instruction pc */ - VVARARG /* info = instruction pc */ + VGLOBAL, /* info = index of table; aux = index of global name in `k' */ + VINDEXED, /* info = table register; aux = index register (or `k') */ + VJMP, /* info = instruction pc */ + VRELOCABLE, /* info = instruction pc */ + VNONRELOC, /* info = result register */ + VCALL, /* info = instruction pc */ + VVARARG /* info = instruction pc */ } expkind; typedef struct expdesc { diff -r 31570b766315 -r ed5a6478e710 misc/liblua/lstate.c --- a/misc/liblua/lstate.c Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/liblua/lstate.c Tue Nov 10 20:43:13 2015 +0100 @@ -24,8 +24,8 @@ #include "ltm.h" -#define state_size(x) (sizeof(x) + LUAI_EXTRASPACE) -#define fromstate(l) (cast(lu_byte *, (l)) - LUAI_EXTRASPACE) +#define state_size(x) (sizeof(x) + LUAI_EXTRASPACE) +#define fromstate(l) (cast(lu_byte *, (l)) - LUAI_EXTRASPACE) #define tostate(l) (cast(lua_State *, cast(lu_byte *, l) + LUAI_EXTRASPACE)) diff -r 31570b766315 -r ed5a6478e710 misc/liblua/lstate.h --- a/misc/liblua/lstate.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/liblua/lstate.h Tue Nov 10 20:43:13 2015 +0100 @@ -19,10 +19,10 @@ /* table of globals */ -#define gt(L) (&L->l_gt) +#define gt(L) (&L->l_gt) /* registry */ -#define registry(L) (&G(L)->l_registry) +#define registry(L) (&G(L)->l_registry) /* extra stack space to handle TM calls and some other extras */ @@ -48,7 +48,7 @@ typedef struct CallInfo { StkId base; /* base for this function */ StkId func; /* function index in the stack */ - StkId top; /* top for this function */ + StkId top; /* top for this function */ const Instruction *savedpc; int nresults; /* expected number of results from this function */ int tailcalls; /* number of tail calls lost under this entry */ @@ -56,10 +56,10 @@ -#define curr_func(L) (clvalue(L->ci->func)) -#define ci_func(ci) (clvalue((ci)->func)) -#define f_isLua(ci) (!ci_func(ci)->c.isC) -#define isLua(ci) (ttisfunction((ci)->func) && f_isLua(ci)) +#define curr_func(L) (clvalue(L->ci->func)) +#define ci_func(ci) (clvalue((ci)->func)) +#define f_isLua(ci) (!ci_func(ci)->c.isC) +#define isLua(ci) (ttisfunction((ci)->func) && f_isLua(ci)) /* @@ -127,7 +127,7 @@ }; -#define G(L) (L->l_G) +#define G(L) (L->l_G) /* @@ -146,20 +146,20 @@ /* macros to convert a GCObject into a specific value */ -#define rawgco2ts(o) check_exp((o)->gch.tt == LUA_TSTRING, &((o)->ts)) -#define gco2ts(o) (&rawgco2ts(o)->tsv) -#define rawgco2u(o) check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u)) -#define gco2u(o) (&rawgco2u(o)->uv) -#define gco2cl(o) check_exp((o)->gch.tt == LUA_TFUNCTION, &((o)->cl)) -#define gco2h(o) check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h)) -#define gco2p(o) check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p)) -#define gco2uv(o) check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv)) +#define rawgco2ts(o) check_exp((o)->gch.tt == LUA_TSTRING, &((o)->ts)) +#define gco2ts(o) (&rawgco2ts(o)->tsv) +#define rawgco2u(o) check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u)) +#define gco2u(o) (&rawgco2u(o)->uv) +#define gco2cl(o) check_exp((o)->gch.tt == LUA_TFUNCTION, &((o)->cl)) +#define gco2h(o) check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h)) +#define gco2p(o) check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p)) +#define gco2uv(o) check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv)) #define ngcotouv(o) \ - check_exp((o) == NULL || (o)->gch.tt == LUA_TUPVAL, &((o)->uv)) -#define gco2th(o) check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th)) + check_exp((o) == NULL || (o)->gch.tt == LUA_TUPVAL, &((o)->uv)) +#define gco2th(o) check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th)) /* macro to convert any Lua object into a GCObject */ -#define obj2gco(v) (cast(GCObject *, (v))) +#define obj2gco(v) (cast(GCObject *, (v))) LUAI_FUNC lua_State *luaE_newthread (lua_State *L); diff -r 31570b766315 -r ed5a6478e710 misc/liblua/lstring.h --- a/misc/liblua/lstring.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/liblua/lstring.h Tue Nov 10 20:43:13 2015 +0100 @@ -13,15 +13,15 @@ #include "lstate.h" -#define sizestring(s) (sizeof(union TString)+((s)->len+1)*sizeof(char)) +#define sizestring(s) (sizeof(union TString)+((s)->len+1)*sizeof(char)) -#define sizeudata(u) (sizeof(union Udata)+(u)->len) +#define sizeudata(u) (sizeof(union Udata)+(u)->len) -#define luaS_new(L, s) (luaS_newlstr(L, s, strlen(s))) -#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ +#define luaS_new(L, s) (luaS_newlstr(L, s, strlen(s))) +#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ (sizeof(s)/sizeof(char))-1)) -#define luaS_fix(s) l_setbit((s)->tsv.marked, FIXEDBIT) +#define luaS_fix(s) l_setbit((s)->tsv.marked, FIXEDBIT) LUAI_FUNC void luaS_resize (lua_State *L, int newsize); LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e); diff -r 31570b766315 -r ed5a6478e710 misc/liblua/lstrlib.c --- a/misc/liblua/lstrlib.c Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/liblua/lstrlib.c Tue Nov 10 20:43:13 2015 +0100 @@ -164,8 +164,8 @@ */ -#define CAP_UNFINISHED (-1) -#define CAP_POSITION (-2) +#define CAP_UNFINISHED (-1) +#define CAP_POSITION (-2) typedef struct MatchState { const char *src_init; /* init of source string */ @@ -179,8 +179,8 @@ } MatchState; -#define L_ESC '%' -#define SPECIALS "^$*+?.([%-" +#define L_ESC '%' +#define SPECIALS "^$*+?.([%-" static int check_capture (MatchState *ms, int l) { @@ -683,14 +683,14 @@ /* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */ -#define MAX_ITEM 512 +#define MAX_ITEM 512 /* valid flags in a format specification */ -#define FLAGS "-+ #0" +#define FLAGS "-+ #0" /* ** maximum size of each format specification (such as '%-099.99d') ** (+10 accounts for %99.99x plus margin of error) */ -#define MAX_FORMAT (sizeof(FLAGS) + sizeof(LUA_INTFRMLEN) + 10) +#define MAX_FORMAT (sizeof(FLAGS) + sizeof(LUA_INTFRMLEN) + 10) static void addquoted (lua_State *L, luaL_Buffer *b, int arg) { diff -r 31570b766315 -r ed5a6478e710 misc/liblua/ltable.c --- a/misc/liblua/ltable.c Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/liblua/ltable.c Tue Nov 10 20:43:13 2015 +0100 @@ -39,12 +39,12 @@ ** max size of array part is 2^MAXBITS */ #if LUAI_BITSINT > 26 -#define MAXBITS 26 +#define MAXBITS 26 #else -#define MAXBITS (LUAI_BITSINT-2) +#define MAXBITS (LUAI_BITSINT-2) #endif -#define MAXASIZE (1 << MAXBITS) +#define MAXASIZE (1 << MAXBITS) #define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t)))) @@ -57,20 +57,20 @@ ** for some types, it is better to avoid modulus by power of 2, as ** they tend to have many 2 factors. */ -#define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1)))) +#define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1)))) -#define hashpointer(t,p) hashmod(t, IntPoint(p)) +#define hashpointer(t,p) hashmod(t, IntPoint(p)) /* ** number of ints inside a lua_Number */ -#define numints cast_int(sizeof(lua_Number)/sizeof(int)) +#define numints cast_int(sizeof(lua_Number)/sizeof(int)) -#define dummynode (&dummynode_) +#define dummynode (&dummynode_) static const Node dummynode_ = { {{NULL}, LUA_TNIL}, /* value */ diff -r 31570b766315 -r ed5a6478e710 misc/liblua/ltable.h --- a/misc/liblua/ltable.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/liblua/ltable.h Tue Nov 10 20:43:13 2015 +0100 @@ -10,12 +10,12 @@ #include "lobject.h" -#define gnode(t,i) (&(t)->node[i]) -#define gkey(n) (&(n)->i_key.nk) -#define gval(n) (&(n)->i_val) -#define gnext(n) ((n)->i_key.nk.next) +#define gnode(t,i) (&(t)->node[i]) +#define gkey(n) (&(n)->i_key.nk) +#define gval(n) (&(n)->i_val) +#define gnext(n) ((n)->i_key.nk.next) -#define key2tval(n) (&(n)->i_key.tvk) +#define key2tval(n) (&(n)->i_key.tvk) LUAI_FUNC const TValue *luaH_getnum (Table *t, int key); diff -r 31570b766315 -r ed5a6478e710 misc/liblua/ltablib.c --- a/misc/liblua/ltablib.c Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/liblua/ltablib.c Tue Nov 10 20:43:13 2015 +0100 @@ -16,7 +16,7 @@ #include "lualib.h" -#define aux_getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_getn(L, n)) +#define aux_getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_getn(L, n)) static int foreachi (lua_State *L) { diff -r 31570b766315 -r ed5a6478e710 misc/liblua/ltm.h --- a/misc/liblua/ltm.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/liblua/ltm.h Tue Nov 10 20:43:13 2015 +0100 @@ -33,7 +33,7 @@ TM_LE, TM_CONCAT, TM_CALL, - TM_N /* number of elements in the enum */ + TM_N /* number of elements in the enum */ } TMS; @@ -41,7 +41,7 @@ #define gfasttm(g,et,e) ((et) == NULL ? NULL : \ ((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e])) -#define fasttm(l,et,e) gfasttm(G(l), et, e) +#define fasttm(l,et,e) gfasttm(G(l), et, e) LUAI_DATA const char *const luaT_typenames[]; diff -r 31570b766315 -r ed5a6478e710 misc/liblua/lua.h --- a/misc/liblua/lua.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/liblua/lua.h Tue Nov 10 20:43:13 2015 +0100 @@ -16,35 +16,35 @@ #include "luaconf.h" -#define LUA_VERSION "Lua 5.1" -#define LUA_RELEASE "Lua 5.1.4" -#define LUA_VERSION_NUM 501 -#define LUA_COPYRIGHT "Copyright (C) 1994-2008 Lua.org, PUC-Rio" -#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes" +#define LUA_VERSION "Lua 5.1" +#define LUA_RELEASE "Lua 5.1.4" +#define LUA_VERSION_NUM 501 +#define LUA_COPYRIGHT "Copyright (C) 1994-2008 Lua.org, PUC-Rio" +#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes" /* mark for precompiled code (`Lua') */ -#define LUA_SIGNATURE "\033Lua" +#define LUA_SIGNATURE "\033Lua" /* option for multiple returns in `lua_pcall' and `lua_call' */ -#define LUA_MULTRET (-1) +#define LUA_MULTRET (-1) /* ** pseudo-indices */ -#define LUA_REGISTRYINDEX (-10000) -#define LUA_ENVIRONINDEX (-10001) -#define LUA_GLOBALSINDEX (-10002) -#define lua_upvalueindex(i) (LUA_GLOBALSINDEX-(i)) +#define LUA_REGISTRYINDEX (-10000) +#define LUA_ENVIRONINDEX (-10001) +#define LUA_GLOBALSINDEX (-10002) +#define lua_upvalueindex(i) (LUA_GLOBALSINDEX-(i)) /* thread status; 0 is OK */ -#define LUA_YIELD 1 -#define LUA_ERRRUN 2 -#define LUA_ERRSYNTAX 3 -#define LUA_ERRMEM 4 -#define LUA_ERRERR 5 +#define LUA_YIELD 1 +#define LUA_ERRRUN 2 +#define LUA_ERRSYNTAX 3 +#define LUA_ERRMEM 4 +#define LUA_ERRERR 5 typedef struct lua_State lua_State; @@ -69,22 +69,22 @@ /* ** basic types */ -#define LUA_TNONE (-1) +#define LUA_TNONE (-1) -#define LUA_TNIL 0 -#define LUA_TBOOLEAN 1 -#define LUA_TLIGHTUSERDATA 2 -#define LUA_TNUMBER 3 -#define LUA_TSTRING 4 -#define LUA_TTABLE 5 -#define LUA_TFUNCTION 6 -#define LUA_TUSERDATA 7 -#define LUA_TTHREAD 8 +#define LUA_TNIL 0 +#define LUA_TBOOLEAN 1 +#define LUA_TLIGHTUSERDATA 2 +#define LUA_TNUMBER 3 +#define LUA_TSTRING 4 +#define LUA_TTABLE 5 +#define LUA_TFUNCTION 6 +#define LUA_TUSERDATA 7 +#define LUA_TTHREAD 8 /* minimum Lua stack available to a C function */ -#define LUA_MINSTACK 20 +#define LUA_MINSTACK 20 /* @@ -149,7 +149,7 @@ LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len); LUA_API size_t (lua_objlen) (lua_State *L, int idx); LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx); -LUA_API void *(lua_touserdata) (lua_State *L, int idx); +LUA_API void *(lua_touserdata) (lua_State *L, int idx); LUA_API lua_State *(lua_tothread) (lua_State *L, int idx); LUA_API const void *(lua_topointer) (lua_State *L, int idx); @@ -218,14 +218,14 @@ ** garbage-collection function and options */ -#define LUA_GCSTOP 0 -#define LUA_GCRESTART 1 -#define LUA_GCCOLLECT 2 -#define LUA_GCCOUNT 3 -#define LUA_GCCOUNTB 4 -#define LUA_GCSTEP 5 -#define LUA_GCSETPAUSE 6 -#define LUA_GCSETSTEPMUL 7 +#define LUA_GCSTOP 0 +#define LUA_GCRESTART 1 +#define LUA_GCCOLLECT 2 +#define LUA_GCCOUNT 3 +#define LUA_GCCOUNTB 4 +#define LUA_GCSTEP 5 +#define LUA_GCSETPAUSE 6 +#define LUA_GCSETSTEPMUL 7 LUA_API int (lua_gc) (lua_State *L, int what, int data); @@ -251,32 +251,32 @@ ** =============================================================== */ -#define lua_pop(L,n) lua_settop(L, -(n)-1) +#define lua_pop(L,n) lua_settop(L, -(n)-1) -#define lua_newtable(L) lua_createtable(L, 0, 0) +#define lua_newtable(L) lua_createtable(L, 0, 0) #define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n))) -#define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0) +#define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0) -#define lua_strlen(L,i) lua_objlen(L, (i)) +#define lua_strlen(L,i) lua_objlen(L, (i)) -#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION) -#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE) -#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA) -#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL) -#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN) -#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD) -#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE) -#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0) +#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION) +#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE) +#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA) +#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL) +#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN) +#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD) +#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE) +#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0) -#define lua_pushliteral(L, s) \ - lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1) +#define lua_pushliteral(L, s) \ + lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1) -#define lua_setglobal(L,s) lua_setfield(L, LUA_GLOBALSINDEX, (s)) -#define lua_getglobal(L,s) lua_getfield(L, LUA_GLOBALSINDEX, (s)) +#define lua_setglobal(L,s) lua_setfield(L, LUA_GLOBALSINDEX, (s)) +#define lua_getglobal(L,s) lua_getfield(L, LUA_GLOBALSINDEX, (s)) -#define lua_tostring(L,i) lua_tolstring(L, (i), NULL) +#define lua_tostring(L,i) lua_tolstring(L, (i), NULL) @@ -284,18 +284,18 @@ ** compatibility macros and functions */ -#define lua_open() luaL_newstate() +#define lua_open() luaL_newstate() -#define lua_getregistry(L) lua_pushvalue(L, LUA_REGISTRYINDEX) +#define lua_getregistry(L) lua_pushvalue(L, LUA_REGISTRYINDEX) -#define lua_getgccount(L) lua_gc(L, LUA_GCCOUNT, 0) +#define lua_getgccount(L) lua_gc(L, LUA_GCCOUNT, 0) -#define lua_Chunkreader lua_Reader -#define lua_Chunkwriter lua_Writer +#define lua_Chunkreader lua_Reader +#define lua_Chunkwriter lua_Writer /* hack */ -LUA_API void lua_setlevel (lua_State *from, lua_State *to); +LUA_API void lua_setlevel (lua_State *from, lua_State *to); /* @@ -308,20 +308,20 @@ /* ** Event codes */ -#define LUA_HOOKCALL 0 -#define LUA_HOOKRET 1 -#define LUA_HOOKLINE 2 -#define LUA_HOOKCOUNT 3 +#define LUA_HOOKCALL 0 +#define LUA_HOOKRET 1 +#define LUA_HOOKLINE 2 +#define LUA_HOOKCOUNT 3 #define LUA_HOOKTAILRET 4 /* ** Event masks */ -#define LUA_MASKCALL (1 << LUA_HOOKCALL) -#define LUA_MASKRET (1 << LUA_HOOKRET) -#define LUA_MASKLINE (1 << LUA_HOOKLINE) -#define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT) +#define LUA_MASKCALL (1 << LUA_HOOKCALL) +#define LUA_MASKRET (1 << LUA_HOOKRET) +#define LUA_MASKLINE (1 << LUA_HOOKLINE) +#define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT) typedef struct lua_Debug lua_Debug; /* activation record */ @@ -345,14 +345,14 @@ struct lua_Debug { int event; - const char *name; /* (n) */ - const char *namewhat; /* (n) `global', `local', `field', `method' */ - const char *what; /* (S) `Lua', `C', `main', `tail' */ - const char *source; /* (S) */ - int currentline; /* (l) */ - int nups; /* (u) number of upvalues */ - int linedefined; /* (S) */ - int lastlinedefined; /* (S) */ + const char *name; /* (n) */ + const char *namewhat; /* (n) `global', `local', `field', `method' */ + const char *what; /* (S) `Lua', `C', `main', `tail' */ + const char *source; /* (S) */ + int currentline; /* (l) */ + int nups; /* (u) number of upvalues */ + int linedefined; /* (S) */ + int lastlinedefined; /* (S) */ char short_src[LUA_IDSIZE]; /* (S) */ /* private part */ int i_ci; /* active function */ diff -r 31570b766315 -r ed5a6478e710 misc/liblua/luaconf.h --- a/misc/liblua/luaconf.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/liblua/luaconf.h Tue Nov 10 20:43:13 2015 +0100 @@ -35,13 +35,13 @@ #if defined(LUA_USE_LINUX) #define LUA_USE_POSIX -#define LUA_USE_DLOPEN /* needs an extra library: -ldl */ -#define LUA_USE_READLINE /* needs some extra libraries */ +#define LUA_USE_DLOPEN /* needs an extra library: -ldl */ +#define LUA_USE_READLINE /* needs some extra libraries */ #endif #if defined(LUA_USE_MACOSX) #define LUA_USE_POSIX -#define LUA_DL_DYLD /* does not need extra library */ +#define LUA_DL_DYLD /* does not need extra library */ #endif @@ -68,7 +68,7 @@ */ #define LUA_PATH "LUA_PATH" #define LUA_CPATH "LUA_CPATH" -#define LUA_INIT "LUA_INIT" +#define LUA_INIT "LUA_INIT" /* @@ -85,23 +85,23 @@ ** In Windows, any exclamation mark ('!') in the path is replaced by the ** path of the directory of the executable file of the current process. */ -#define LUA_LDIR "!\\lua\\" -#define LUA_CDIR "!\\" +#define LUA_LDIR "!\\lua\\" +#define LUA_CDIR "!\\" #define LUA_PATH_DEFAULT \ - ".\\?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \ - LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua" + ".\\?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \ + LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua" #define LUA_CPATH_DEFAULT \ - ".\\?.dll;" LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll" + ".\\?.dll;" LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll" #else -#define LUA_ROOT "/usr/local/" -#define LUA_LDIR LUA_ROOT "share/lua/5.1/" -#define LUA_CDIR LUA_ROOT "lib/lua/5.1/" +#define LUA_ROOT "/usr/local/" +#define LUA_LDIR LUA_ROOT "share/lua/5.1/" +#define LUA_CDIR LUA_ROOT "lib/lua/5.1/" #define LUA_PATH_DEFAULT \ - "./?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \ - LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua" + "./?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \ + LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua" #define LUA_CPATH_DEFAULT \ - "./?.so;" LUA_CDIR"?.so;" LUA_CDIR"loadall.so" + "./?.so;" LUA_CDIR"?.so;" LUA_CDIR"loadall.so" #endif @@ -111,9 +111,9 @@ ** and is not Windows. (On Windows Lua automatically uses "\".) */ #if defined(_WIN32) -#define LUA_DIRSEP "\\" +#define LUA_DIRSEP "\\" #else -#define LUA_DIRSEP "/" +#define LUA_DIRSEP "/" #endif @@ -129,10 +129,10 @@ ** characters. (E.g., if one of those characters is a common character ** in file/directory names.) Probably you do not need to change them. */ -#define LUA_PATHSEP ";" -#define LUA_PATH_MARK "?" -#define LUA_EXECDIR "!" -#define LUA_IGMARK "-" +#define LUA_PATHSEP ";" +#define LUA_PATH_MARK "?" +#define LUA_EXECDIR "!" +#define LUA_IGMARK "-" /* @@ -140,7 +140,7 @@ ** CHANGE that if ptrdiff_t is not adequate on your machine. (On most ** machines, ptrdiff_t gives a good choice between int or long.) */ -#define LUA_INTEGER ptrdiff_t +#define LUA_INTEGER ptrdiff_t /* @@ -161,12 +161,12 @@ #else -#define LUA_API extern +#define LUA_API extern #endif /* more often than not the libs go together with the core */ -#define LUALIB_API LUA_API +#define LUALIB_API LUA_API /* @@ -179,17 +179,17 @@ ** when Lua is compiled as a shared library. */ #if defined(luaall_c) -#define LUAI_FUNC static -#define LUAI_DATA /* empty */ +#define LUAI_FUNC static +#define LUAI_DATA /* empty */ #elif defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \ defined(__ELF__) -#define LUAI_FUNC __attribute__((visibility("hidden"))) extern -#define LUAI_DATA LUAI_FUNC +#define LUAI_FUNC __attribute__((visibility("hidden"))) extern +#define LUAI_DATA LUAI_FUNC #else -#define LUAI_FUNC extern -#define LUAI_DATA extern +#define LUAI_FUNC extern +#define LUAI_DATA extern #endif @@ -198,8 +198,8 @@ @@ LUA_QL describes how error messages quote program elements. ** CHANGE it if you want a different appearance. */ -#define LUA_QL(x) "'" x "'" -#define LUA_QS LUA_QL("%s") +#define LUA_QL(x) "'" x "'" +#define LUA_QS LUA_QL("%s") /* @@ -207,7 +207,7 @@ @* of a function in debug information. ** CHANGE it if you want a different size. */ -#define LUA_IDSIZE 60 +#define LUA_IDSIZE 60 /* @@ -226,13 +226,13 @@ */ #if defined(LUA_USE_ISATTY) #include -#define lua_stdin_is_tty() isatty(0) +#define lua_stdin_is_tty() isatty(0) #elif defined(LUA_WIN) #include #include -#define lua_stdin_is_tty() _isatty(_fileno(stdin)) +#define lua_stdin_is_tty() _isatty(_fileno(stdin)) #else -#define lua_stdin_is_tty() 1 /* assume stdin is a tty */ +#define lua_stdin_is_tty() 1 /* assume stdin is a tty */ #endif @@ -242,8 +242,8 @@ ** CHANGE them if you want different prompts. (You can also change the ** prompts dynamically, assigning to globals _PROMPT/_PROMPT2.) */ -#define LUA_PROMPT "> " -#define LUA_PROMPT2 ">> " +#define LUA_PROMPT "> " +#define LUA_PROMPT2 ">> " /* @@ -251,7 +251,7 @@ ** CHANGE it if your stand-alone interpreter has a different name and ** your system is not able to detect that name automatically. */ -#define LUA_PROGNAME "lua" +#define LUA_PROGNAME "lua" /* @@ -259,7 +259,7 @@ @* stand-alone interpreter. ** CHANGE it if you need longer lines. */ -#define LUA_MAXINPUT 512 +#define LUA_MAXINPUT 512 /* @@ -274,17 +274,17 @@ #include #include #include -#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL) +#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL) #define lua_saveline(L,idx) \ - if (lua_strlen(L,idx) > 0) /* non-empty line? */ \ - add_history(lua_tostring(L, idx)); /* add it to history */ -#define lua_freeline(L,b) ((void)L, free(b)) + if (lua_strlen(L,idx) > 0) /* non-empty line? */ \ + add_history(lua_tostring(L, idx)); /* add it to history */ +#define lua_freeline(L,b) ((void)L, free(b)) #else -#define lua_readline(L,b,p) \ - ((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \ - fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */ -#define lua_saveline(L,idx) { (void)L; (void)idx; } -#define lua_freeline(L,b) { (void)L; (void)b; } +#define lua_readline(L,b,p) \ + ((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \ + fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */ +#define lua_saveline(L,idx) { (void)L; (void)idx; } +#define lua_freeline(L,b) { (void)L; (void)b; } #endif #endif @@ -299,7 +299,7 @@ ** mean larger pauses which mean slower collection.) You can also change ** this value dynamically. */ -#define LUAI_GCPAUSE 200 /* 200% (wait memory to double before next GC) */ +#define LUAI_GCPAUSE 200 /* 200% (wait memory to double before next GC) */ /* @@ -310,7 +310,7 @@ ** infinity, where each step performs a full collection.) You can also ** change this value dynamically. */ -#define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */ +#define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */ @@ -348,7 +348,7 @@ ** CHANGE it to 2 if you want the old behaviour, or undefine it to turn ** off the advisory error when nesting [[...]]. */ -#define LUA_COMPAT_LSTR 1 +#define LUA_COMPAT_LSTR 1 /* @@ LUA_COMPAT_GFIND controls compatibility with old 'string.gfind' name. @@ -376,9 +376,9 @@ */ #if defined(LUA_USE_APICHECK) #include -#define luai_apicheck(L,o) { (void)L; assert(o); } +#define luai_apicheck(L,o) { (void)L; assert(o); } #else -#define luai_apicheck(L,o) { (void)L; } +#define luai_apicheck(L,o) { (void)L; } #endif @@ -389,10 +389,10 @@ */ /* avoid overflows in comparison */ #if INT_MAX-20 < 32760 -#define LUAI_BITSINT 16 +#define LUAI_BITSINT 16 #elif INT_MAX > 2147483640L /* int has at least 32 bits */ -#define LUAI_BITSINT 32 +#define LUAI_BITSINT 32 #else #error "you must define LUA_BITSINT with number of bits in an integer" #endif @@ -411,18 +411,18 @@ ** longs.) Probably you do not need to change this. */ #if LUAI_BITSINT >= 32 -#define LUAI_UINT32 unsigned int -#define LUAI_INT32 int -#define LUAI_MAXINT32 INT_MAX -#define LUAI_UMEM size_t -#define LUAI_MEM ptrdiff_t +#define LUAI_UINT32 unsigned int +#define LUAI_INT32 int +#define LUAI_MAXINT32 INT_MAX +#define LUAI_UMEM size_t +#define LUAI_MEM ptrdiff_t #else /* 16-bit ints */ -#define LUAI_UINT32 unsigned long -#define LUAI_INT32 long -#define LUAI_MAXINT32 LONG_MAX -#define LUAI_UMEM unsigned long -#define LUAI_MEM long +#define LUAI_UINT32 unsigned long +#define LUAI_INT32 long +#define LUAI_MAXINT32 LONG_MAX +#define LUAI_UMEM unsigned long +#define LUAI_MEM long #endif @@ -432,7 +432,7 @@ ** arbitrary; its only purpose is to stop infinite recursion before ** exhausting memory. */ -#define LUAI_MAXCALLS 20000 +#define LUAI_MAXCALLS 20000 /* @@ -443,7 +443,7 @@ ** functions to consume unlimited stack space. (must be smaller than ** -LUA_REGISTRYINDEX) */ -#define LUAI_MAXCSTACK 8000 +#define LUAI_MAXCSTACK 8000 @@ -465,27 +465,27 @@ @@ LUAI_MAXCCALLS is the maximum depth for nested C calls (short) and @* syntactical nested non-terminals in a program. */ -#define LUAI_MAXCCALLS 200 +#define LUAI_MAXCCALLS 200 /* @@ LUAI_MAXVARS is the maximum number of local variables per function @* (must be smaller than 250). */ -#define LUAI_MAXVARS 200 +#define LUAI_MAXVARS 200 /* @@ LUAI_MAXUPVALUES is the maximum number of upvalues per function @* (must be smaller than 250). */ -#define LUAI_MAXUPVALUES 60 +#define LUAI_MAXUPVALUES 60 /* @@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system. */ -#define LUAL_BUFFERSIZE BUFSIZ +#define LUAL_BUFFERSIZE BUFSIZ /* }================================================================== */ @@ -502,13 +502,13 @@ */ #define LUA_NUMBER_DOUBLE -#define LUA_NUMBER double +#define LUA_NUMBER double /* @@ LUAI_UACNUMBER is the result of an 'usual argument conversion' @* over a number. */ -#define LUAI_UACNUMBER double +#define LUAI_UACNUMBER double /* @@ -518,11 +518,11 @@ @@ LUAI_MAXNUMBER2STR is maximum size of previous conversion. @@ lua_str2number converts a string to a number. */ -#define LUA_NUMBER_SCAN "%lf" -#define LUA_NUMBER_FMT "%.14g" -#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n)) -#define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */ -#define lua_str2number(s,p) strtod((s), (p)) +#define LUA_NUMBER_SCAN "%lf" +#define LUA_NUMBER_FMT "%.14g" +#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n)) +#define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */ +#define lua_str2number(s,p) strtod((s), (p)) /* @@ -530,17 +530,17 @@ */ #if defined(LUA_CORE) #include -#define luai_numadd(a,b) ((a)+(b)) -#define luai_numsub(a,b) ((a)-(b)) -#define luai_nummul(a,b) ((a)*(b)) -#define luai_numdiv(a,b) ((a)/(b)) -#define luai_nummod(a,b) ((a) - floor((a)/(b))*(b)) -#define luai_numpow(a,b) (pow(a,b)) -#define luai_numunm(a) (-(a)) -#define luai_numeq(a,b) ((a)==(b)) -#define luai_numlt(a,b) ((a)<(b)) -#define luai_numle(a,b) ((a)<=(b)) -#define luai_numisnan(a) (!luai_numeq((a), (a))) +#define luai_numadd(a,b) ((a)+(b)) +#define luai_numsub(a,b) ((a)-(b)) +#define luai_nummul(a,b) ((a)*(b)) +#define luai_numdiv(a,b) ((a)/(b)) +#define luai_nummod(a,b) ((a) - floor((a)/(b))*(b)) +#define luai_numpow(a,b) (pow(a,b)) +#define luai_numunm(a) (-(a)) +#define luai_numeq(a,b) ((a)==(b)) +#define luai_numlt(a,b) ((a)<(b)) +#define luai_numle(a,b) ((a)<=(b)) +#define luai_numisnan(a) (!luai_numeq((a), (a))) #endif @@ -561,7 +561,7 @@ #if defined(_MSC_VER) #define lua_number2int(i,d) __asm fld d __asm fistp i -#define lua_number2integer(i,n) lua_number2int(i, n) +#define lua_number2integer(i,n) lua_number2int(i, n) /* the next trick should work on any Pentium, but sometimes clashes with a DirectX idiosyncrasy */ @@ -570,15 +570,15 @@ union luai_Cast { double l_d; long l_l; }; #define lua_number2int(i,d) \ { volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; } -#define lua_number2integer(i,n) lua_number2int(i, n) +#define lua_number2integer(i,n) lua_number2int(i, n) #endif /* this option always works, but may be slow */ #else -#define lua_number2int(i,d) ((i)=(int)(d)) -#define lua_number2integer(i,d) ((i)=(lua_Integer)(d)) +#define lua_number2int(i,d) ((i)=(int)(d)) +#define lua_number2integer(i,d) ((i)=(lua_Integer)(d)) #endif @@ -592,7 +592,7 @@ ** aligned in 16-byte boundaries, then you should add long double in the ** union.) Probably you do not need to change this. */ -#define LUAI_USER_ALIGNMENT_T union { double u; void *s; long l; } +#define LUAI_USER_ALIGNMENT_T union { double u; void *s; long l; } /* @@ -605,22 +605,22 @@ */ #if defined(__cplusplus) /* C++ exceptions */ -#define LUAI_THROW(L,c) throw(c) -#define LUAI_TRY(L,c,a) try { a } catch(...) \ - { if ((c)->status == 0) (c)->status = -1; } -#define luai_jmpbuf int /* dummy variable */ +#define LUAI_THROW(L,c) throw(c) +#define LUAI_TRY(L,c,a) try { a } catch(...) \ + { if ((c)->status == 0) (c)->status = -1; } +#define luai_jmpbuf int /* dummy variable */ #elif defined(LUA_USE_ULONGJMP) /* in Unix, try _longjmp/_setjmp (more efficient) */ -#define LUAI_THROW(L,c) _longjmp((c)->b, 1) -#define LUAI_TRY(L,c,a) if (_setjmp((c)->b) == 0) { a } -#define luai_jmpbuf jmp_buf +#define LUAI_THROW(L,c) _longjmp((c)->b, 1) +#define LUAI_TRY(L,c,a) if (_setjmp((c)->b) == 0) { a } +#define luai_jmpbuf jmp_buf #else /* default handling with long jumps */ -#define LUAI_THROW(L,c) longjmp((c)->b, 1) -#define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a } -#define luai_jmpbuf jmp_buf +#define LUAI_THROW(L,c) longjmp((c)->b, 1) +#define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a } +#define luai_jmpbuf jmp_buf #endif @@ -630,7 +630,7 @@ @* can do during pattern-matching. ** CHANGE it if you need more captures. This limit is arbitrary. */ -#define LUA_MAXCAPTURES 32 +#define LUA_MAXCAPTURES 32 /* @@ -645,16 +645,16 @@ #if defined(LUA_USE_MKSTEMP) #include -#define LUA_TMPNAMBUFSIZE 32 -#define lua_tmpnam(b,e) { \ - strcpy(b, "/tmp/lua_XXXXXX"); \ - e = mkstemp(b); \ - if (e != -1) close(e); \ - e = (e == -1); } +#define LUA_TMPNAMBUFSIZE 32 +#define lua_tmpnam(b,e) { \ + strcpy(b, "/tmp/lua_XXXXXX"); \ + e = mkstemp(b); \ + if (e != -1) close(e); \ + e = (e == -1); } #else -#define LUA_TMPNAMBUFSIZE L_tmpnam -#define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); } +#define LUA_TMPNAMBUFSIZE L_tmpnam +#define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); } #endif #endif @@ -667,19 +667,19 @@ */ #if defined(LUA_USE_POPEN) -#define lua_popen(L,c,m) ((void)L, fflush(NULL), popen(c,m)) -#define lua_pclose(L,file) ((void)L, (pclose(file) != -1)) +#define lua_popen(L,c,m) ((void)L, fflush(NULL), popen(c,m)) +#define lua_pclose(L,file) ((void)L, (pclose(file) != -1)) #elif defined(LUA_WIN) -#define lua_popen(L,c,m) ((void)L, _popen(c,m)) -#define lua_pclose(L,file) ((void)L, (_pclose(file) != -1)) +#define lua_popen(L,c,m) ((void)L, _popen(c,m)) +#define lua_pclose(L,file) ((void)L, (_pclose(file) != -1)) #else -#define lua_popen(L,c,m) ((void)((void)c, m), \ - luaL_error(L, LUA_QL("popen") " not supported"), (FILE*)0) -#define lua_pclose(L,file) ((void)((void)L, file), 0) +#define lua_popen(L,c,m) ((void)((void)c, m), \ + luaL_error(L, LUA_QL("popen") " not supported"), (FILE*)0) +#define lua_pclose(L,file) ((void)((void)L, file), 0) #endif @@ -712,7 +712,7 @@ ** CHANGE (define) this if you really need that. This value must be ** a multiple of the maximum alignment required for your machine. */ -#define LUAI_EXTRASPACE 0 +#define LUAI_EXTRASPACE 0 /* @@ -720,12 +720,12 @@ ** CHANGE them if you defined LUAI_EXTRASPACE and need to do something ** extra when a thread is created/deleted/resumed/yielded. */ -#define luai_userstateopen(L) ((void)L) -#define luai_userstateclose(L) ((void)L) -#define luai_userstatethread(L,L1) ((void)L) -#define luai_userstatefree(L) ((void)L) -#define luai_userstateresume(L,n) ((void)L) -#define luai_userstateyield(L,n) ((void)L) +#define luai_userstateopen(L) ((void)L) +#define luai_userstateclose(L) ((void)L) +#define luai_userstatethread(L,L1) ((void)L) +#define luai_userstatefree(L) ((void)L) +#define luai_userstateresume(L,n) ((void)L) +#define luai_userstateyield(L,n) ((void)L) /* @@ -738,13 +738,13 @@ #if defined(LUA_USELONGLONG) -#define LUA_INTFRMLEN "ll" -#define LUA_INTFRM_T long long +#define LUA_INTFRMLEN "ll" +#define LUA_INTFRM_T long long #else -#define LUA_INTFRMLEN "l" -#define LUA_INTFRM_T long +#define LUA_INTFRMLEN "l" +#define LUA_INTFRM_T long #endif diff -r 31570b766315 -r ed5a6478e710 misc/liblua/lualib.h --- a/misc/liblua/lualib.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/liblua/lualib.h Tue Nov 10 20:43:13 2015 +0100 @@ -12,31 +12,31 @@ /* Key to file-handle type */ -#define LUA_FILEHANDLE "FILE*" +#define LUA_FILEHANDLE "FILE*" -#define LUA_COLIBNAME "coroutine" +#define LUA_COLIBNAME "coroutine" LUALIB_API int (luaopen_base) (lua_State *L); -#define LUA_TABLIBNAME "table" +#define LUA_TABLIBNAME "table" LUALIB_API int (luaopen_table) (lua_State *L); -#define LUA_IOLIBNAME "io" +#define LUA_IOLIBNAME "io" LUALIB_API int (luaopen_io) (lua_State *L); -#define LUA_OSLIBNAME "os" +#define LUA_OSLIBNAME "os" LUALIB_API int (luaopen_os) (lua_State *L); -#define LUA_STRLIBNAME "string" +#define LUA_STRLIBNAME "string" LUALIB_API int (luaopen_string) (lua_State *L); -#define LUA_MATHLIBNAME "math" +#define LUA_MATHLIBNAME "math" LUALIB_API int (luaopen_math) (lua_State *L); -#define LUA_DBLIBNAME "debug" +#define LUA_DBLIBNAME "debug" LUALIB_API int (luaopen_debug) (lua_State *L); -#define LUA_LOADLIBNAME "package" +#define LUA_LOADLIBNAME "package" LUALIB_API int (luaopen_package) (lua_State *L); @@ -46,7 +46,7 @@ #ifndef lua_assert -#define lua_assert(x) ((void)0) +#define lua_assert(x) ((void)0) #endif diff -r 31570b766315 -r ed5a6478e710 misc/liblua/lundump.c --- a/misc/liblua/lundump.c Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/liblua/lundump.c Tue Nov 10 20:43:13 2015 +0100 @@ -31,7 +31,7 @@ #define IF(c,s) #define error(S,s) #else -#define IF(c,s) if (c) error(S,s) +#define IF(c,s) if (c) error(S,s) static void error(LoadState* S, const char* why) { @@ -40,10 +40,10 @@ } #endif -#define LoadMem(S,b,n,size) LoadBlock(S,b,(n)*(size)) -#define LoadByte(S) (lu_byte)LoadChar(S) -#define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x)) -#define LoadVector(S,b,n,size) LoadMem(S,b,n,size) +#define LoadMem(S,b,n,size) LoadBlock(S,b,(n)*(size)) +#define LoadByte(S) (lu_byte)LoadChar(S) +#define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x)) +#define LoadVector(S,b,n,size) LoadMem(S,b,n,size) static void LoadBlock(LoadState* S, void* b, size_t size) { @@ -83,7 +83,7 @@ { char* s=luaZ_openspace(S->L,S->b,size); LoadBlock(S,s,size); - return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */ + return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */ } } @@ -111,20 +111,20 @@ switch (t) { case LUA_TNIL: - setnilvalue(o); - break; + setnilvalue(o); + break; case LUA_TBOOLEAN: - setbvalue(o,LoadChar(S)!=0); - break; + setbvalue(o,LoadChar(S)!=0); + break; case LUA_TNUMBER: - setnvalue(o,LoadNumber(S)); - break; + setnvalue(o,LoadNumber(S)); + break; case LUA_TSTRING: - setsvalue2n(S->L,o,LoadString(S)); - break; + setsvalue2n(S->L,o,LoadString(S)); + break; default: - error(S,"bad constant"); - break; + error(S,"bad constant"); + break; } } n=LoadInt(S); @@ -218,10 +218,10 @@ h+=sizeof(LUA_SIGNATURE)-1; *h++=(char)LUAC_VERSION; *h++=(char)LUAC_FORMAT; - *h++=(char)*(char*)&x; /* endianness */ + *h++=(char)*(char*)&x; /* endianness */ *h++=(char)sizeof(int); *h++=(char)sizeof(size_t); *h++=(char)sizeof(Instruction); *h++=(char)sizeof(lua_Number); - *h++=(char)(((lua_Number)0.5)==0); /* is lua_Number integral? */ + *h++=(char)(((lua_Number)0.5)==0); /* is lua_Number integral? */ } diff -r 31570b766315 -r ed5a6478e710 misc/liblua/lundump.h --- a/misc/liblua/lundump.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/liblua/lundump.h Tue Nov 10 20:43:13 2015 +0100 @@ -25,12 +25,12 @@ #endif /* for header of binary files -- this is Lua 5.1 */ -#define LUAC_VERSION 0x51 +#define LUAC_VERSION 0x51 /* for header of binary files -- this is the official format */ -#define LUAC_FORMAT 0 +#define LUAC_FORMAT 0 /* size of header of binary files */ -#define LUAC_HEADERSIZE 12 +#define LUAC_HEADERSIZE 12 #endif diff -r 31570b766315 -r ed5a6478e710 misc/liblua/lvm.c --- a/misc/liblua/lvm.c Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/liblua/lvm.c Tue Nov 10 20:43:13 2015 +0100 @@ -29,7 +29,7 @@ /* limit for table tag-method chains (to avoid loops) */ -#define MAXTAGLOOP 100 +#define MAXTAGLOOP 100 const TValue *luaV_tonumber (const TValue *obj, TValue *n) { @@ -338,23 +338,23 @@ ** some macros for common tasks in `luaV_execute' */ -#define runtime_check(L, c) { if (!(c)) break; } +#define runtime_check(L, c) { if (!(c)) break; } -#define RA(i) (base+GETARG_A(i)) +#define RA(i) (base+GETARG_A(i)) /* to be used after possible stack reallocation */ -#define RB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_B(i)) -#define RC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i)) -#define RKB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, \ - ISK(GETARG_B(i)) ? k+INDEXK(GETARG_B(i)) : base+GETARG_B(i)) -#define RKC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \ - ISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i)) -#define KBx(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, k+GETARG_Bx(i)) +#define RB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_B(i)) +#define RC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i)) +#define RKB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, \ + ISK(GETARG_B(i)) ? k+INDEXK(GETARG_B(i)) : base+GETARG_B(i)) +#define RKC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \ + ISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i)) +#define KBx(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, k+GETARG_Bx(i)) -#define dojump(L,pc,i) {(pc) += (i); luai_threadyield(L);} +#define dojump(L,pc,i) {(pc) += (i); luai_threadyield(L);} -#define Protect(x) { L->savedpc = pc; {x;}; base = L->base; } +#define Protect(x) { L->savedpc = pc; {x;}; base = L->base; } #define arith_op(op,tm) { \ diff -r 31570b766315 -r ed5a6478e710 misc/liblua/lvm.h --- a/misc/liblua/lvm.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/liblua/lvm.h Tue Nov 10 20:43:13 2015 +0100 @@ -15,11 +15,11 @@ #define tostring(L,o) ((ttype(o) == LUA_TSTRING) || (luaV_tostring(L, o))) -#define tonumber(o,n) (ttype(o) == LUA_TNUMBER || \ +#define tonumber(o,n) (ttype(o) == LUA_TNUMBER || \ (((o) = luaV_tonumber(o,n)) != NULL)) #define equalobj(L,o1,o2) \ - (ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2)) + (ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2)) LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r); diff -r 31570b766315 -r ed5a6478e710 misc/liblua/lzio.h --- a/misc/liblua/lzio.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/liblua/lzio.h Tue Nov 10 20:43:13 2015 +0100 @@ -13,11 +13,11 @@ #include "lmem.h" -#define EOZ (-1) /* end of stream */ +#define EOZ (-1) /* end of stream */ typedef struct Zio ZIO; -#define char2int(c) cast(int, cast(unsigned char, (c))) +#define char2int(c) cast(int, cast(unsigned char, (c))) #define zgetc(z) (((z)->n--)>0 ? char2int(*(z)->p++) : luaZ_fill(z)) @@ -29,24 +29,24 @@ #define luaZ_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->buffsize = 0) -#define luaZ_buffer(buff) ((buff)->buffer) -#define luaZ_sizebuffer(buff) ((buff)->buffsize) -#define luaZ_bufflen(buff) ((buff)->n) +#define luaZ_buffer(buff) ((buff)->buffer) +#define luaZ_sizebuffer(buff) ((buff)->buffsize) +#define luaZ_bufflen(buff) ((buff)->n) #define luaZ_resetbuffer(buff) ((buff)->n = 0) #define luaZ_resizebuffer(L, buff, size) \ - (luaM_reallocvector(L, (buff)->buffer, (buff)->buffsize, size, char), \ - (buff)->buffsize = size) + (luaM_reallocvector(L, (buff)->buffer, (buff)->buffsize, size, char), \ + (buff)->buffsize = size) -#define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0) +#define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0) LUAI_FUNC char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n); LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data); -LUAI_FUNC size_t luaZ_read (ZIO* z, void* b, size_t n); /* read next n bytes */ +LUAI_FUNC size_t luaZ_read (ZIO* z, void* b, size_t n); /* read next n bytes */ LUAI_FUNC int luaZ_lookahead (ZIO *z); @@ -54,11 +54,11 @@ /* --------- Private Part ------------------ */ struct Zio { - size_t n; /* bytes still unread */ - const char *p; /* current position in buffer */ + size_t n; /* bytes still unread */ + const char *p; /* current position in buffer */ lua_Reader reader; - void* data; /* additional data */ - lua_State *L; /* Lua state (for reader) */ + void* data; /* additional data */ + lua_State *L; /* Lua state (for reader) */ }; diff -r 31570b766315 -r ed5a6478e710 misc/liblua/print.c --- a/misc/liblua/print.c Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/liblua/print.c Tue Nov 10 20:43:13 2015 +0100 @@ -15,10 +15,10 @@ #include "lopcodes.h" #include "lundump.h" -#define PrintFunction luaU_print +#define PrintFunction luaU_print -#define Sizeof(x) ((int)sizeof(x)) -#define VOID(p) ((const void*)(p)) +#define Sizeof(x) ((int)sizeof(x)) +#define VOID(p) ((const void*)(p)) static void PrintString(const TString* ts) { @@ -39,10 +39,10 @@ case '\r': printf("\\r"); break; case '\t': printf("\\t"); break; case '\v': printf("\\v"); break; - default: if (isprint((unsigned char)c)) - putchar(c); - else - printf("\\%03u",(unsigned char)c); + default: if (isprint((unsigned char)c)) + putchar(c); + else + printf("\\%03u",(unsigned char)c); } } putchar('"'); @@ -54,20 +54,20 @@ switch (ttype(o)) { case LUA_TNIL: - printf("nil"); - break; + printf("nil"); + break; case LUA_TBOOLEAN: - printf(bvalue(o) ? "true" : "false"); - break; + printf(bvalue(o) ? "true" : "false"); + break; case LUA_TNUMBER: - printf(LUA_NUMBER_FMT,nvalue(o)); - break; + printf(LUA_NUMBER_FMT,nvalue(o)); + break; case LUA_TSTRING: - PrintString(rawtsvalue(o)); - break; - default: /* cannot happen */ - printf("? type=%d",ttype(o)); - break; + PrintString(rawtsvalue(o)); + break; + default: /* cannot happen */ + printf("? type=%d",ttype(o)); + break; } } @@ -155,8 +155,8 @@ } } -#define SS(x) (x==1)?"":"s" -#define S(x) x,SS(x) +#define SS(x) (x==1)?"":"s" +#define S(x) x,SS(x) static void PrintHeader(const Proto* f) { @@ -168,14 +168,14 @@ else s="(string)"; printf("\n%s <%s:%d,%d> (%d instruction%s, %d bytes at %p)\n", - (f->linedefined==0)?"main":"function",s, - f->linedefined,f->lastlinedefined, - S(f->sizecode),f->sizecode*Sizeof(Instruction),VOID(f)); + (f->linedefined==0)?"main":"function",s, + f->linedefined,f->lastlinedefined, + S(f->sizecode),f->sizecode*Sizeof(Instruction),VOID(f)); printf("%d%s param%s, %d slot%s, %d upvalue%s, ", - f->numparams,f->is_vararg?"+":"",SS(f->numparams), - S(f->maxstacksize),S(f->nups)); + f->numparams,f->is_vararg?"+":"",SS(f->numparams), + S(f->maxstacksize),S(f->nups)); printf("%d local%s, %d constant%s, %d function%s\n", - S(f->sizelocvars),S(f->sizek),S(f->sizep)); + S(f->sizelocvars),S(f->sizek),S(f->sizep)); } static void PrintConstants(const Proto* f) diff -r 31570b766315 -r ed5a6478e710 misc/libphysfs/CMakeLists.txt diff -r 31570b766315 -r ed5a6478e710 misc/libphysfs/Xcode/Physfs.xcodeproj/project.pbxproj --- a/misc/libphysfs/Xcode/Physfs.xcodeproj/project.pbxproj Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/libphysfs/Xcode/Physfs.xcodeproj/project.pbxproj Tue Nov 10 20:43:13 2015 +0100 @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 45; + objectVersion = 46; objects = { /* Begin PBXBuildFile section */ @@ -178,8 +178,11 @@ /* Begin PBXProject section */ 0867D690FE84028FC02AAC07 /* Project object */ = { isa = PBXProject; + attributes = { + LastUpgradeCheck = 0710; + }; buildConfigurationList = 1DEB922208733DC00010E9CD /* Build configuration list for PBXProject "Physfs" */; - compatibilityVersion = "Xcode 3.1"; + compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 1; knownRegions = ( @@ -230,7 +233,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; COPY_PHASE_STRIP = NO; DSTROOT = /tmp/Physfs.dst; GCC_DYNAMIC_NO_PIC = NO; @@ -241,6 +243,7 @@ GCC_PREFIX_HEADER = Physfs_Prefix.pch; INSTALL_PATH = /usr/local/lib; PRODUCT_NAME = Physfs; + SKIP_INSTALL = YES; }; name = Debug; }; @@ -248,13 +251,13 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; DSTROOT = /tmp/Physfs.dst; GCC_MODEL_TUNING = G5; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = Physfs_Prefix.pch; INSTALL_PATH = /usr/local/lib; PRODUCT_NAME = Physfs; + SKIP_INSTALL = YES; }; name = Release; }; @@ -262,20 +265,36 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = c99; + GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ""; GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = ( "\"$(SRCROOT)/../../liblua\"", "\"$(SRCROOT)/../../../../Library/SDL/include\"", ); + IPHONEOS_DEPLOYMENT_TARGET = 7.0; + ONLY_ACTIVE_ARCH = YES; OTHER_LDFLAGS = "-ObjC"; PREBINDING = NO; SDKROOT = iphoneos; + VALID_ARCHS = "armv7 x86_64 arm64"; }; name = Debug; }; @@ -283,19 +302,33 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = c99; + GCC_NO_COMMON_BLOCKS = YES; GCC_PREPROCESSOR_DEFINITIONS = ""; GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = ( "\"$(SRCROOT)/../../liblua\"", "\"$(SRCROOT)/../../../../Library/SDL/include\"", ); + IPHONEOS_DEPLOYMENT_TARGET = 7.0; OTHER_LDFLAGS = "-ObjC"; PREBINDING = NO; SDKROOT = iphoneos; + VALID_ARCHS = "armv7 x86_64 arm64"; }; name = Release; }; diff -r 31570b766315 -r ed5a6478e710 misc/libphysfs/archiver_unpacked.c --- a/misc/libphysfs/archiver_unpacked.c Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/libphysfs/archiver_unpacked.c Tue Nov 10 20:43:13 2015 +0100 @@ -200,7 +200,7 @@ rc = -1; else if (ch > '/') rc = 1; - else + else { if (stop_on_first_find) /* Just checking dir's existance? */ return middle; @@ -293,7 +293,7 @@ /* * This will find the UNPKentry associated with a path in platform-independent - * notation. Directories don't have UNPKentries associated with them, but + * notation. Directories don't have UNPKentries associated with them, but * (*isDir) will be set to non-zero if a dir was hit. */ static UNPKentry *findEntry(const UNPKinfo *info, const char *path, int *isDir) diff -r 31570b766315 -r ed5a6478e710 misc/libphysfs/archiver_wad.c --- a/misc/libphysfs/archiver_wad.c Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/libphysfs/archiver_wad.c Tue Nov 10 20:43:13 2015 +0100 @@ -1,7 +1,7 @@ /* * WAD support routines for PhysicsFS. * - * This driver handles DOOM engine archives ("wads"). + * This driver handles DOOM engine archives ("wads"). * This format (but not this driver) was designed by id Software for use * with the DOOM engine. * The specs of the format are from the unofficial doom specs v1.666 @@ -28,7 +28,7 @@ * (c) an 8-byte ASCII string, the name of the lump, padded with zeros. * For example, the "DEMO1" entry in hexadecimal would be * (44 45 4D 4F 31 00 00 00) - * + * * Note that there is no way to tell if an opened WAD archive is a * IWAD or PWAD with this archiver. * I couldn't think of a way to provide that information, without being too diff -r 31570b766315 -r ed5a6478e710 misc/libphysfs/archiver_zip.c --- a/misc/libphysfs/archiver_zip.c Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/libphysfs/archiver_zip.c Tue Nov 10 20:43:13 2015 +0100 @@ -488,7 +488,7 @@ (buf[i + 3] == 0x06) ) { found = 1; /* that's the signature! */ - break; + break; } /* if */ } /* for */ @@ -552,7 +552,7 @@ /* * This will find the ZIPentry associated with a path in platform-independent - * notation. Directories don't have ZIPentries associated with them, but + * notation. Directories don't have ZIPentries associated with them, but * (*isDir) will be set to non-zero if a dir was hit. */ static ZIPentry *zip_find_entry(const ZIPinfo *info, const char *path, @@ -724,7 +724,7 @@ path = (char *) __PHYSFS_smallAlloc(size + 1); BAIL_IF_MACRO(!path, PHYSFS_ERR_OUT_OF_MEMORY, 0); - + if (entry->compression_method == COMPMETH_NONE) rc = __PHYSFS_readAll(io, path, size); @@ -1445,7 +1445,7 @@ rc = -1; else if ('/' > ch) rc = 1; - else + else { if (stop_on_first_find) /* Just checking dir's existance? */ return middle; diff -r 31570b766315 -r ed5a6478e710 misc/libphysfs/physfs.c --- a/misc/libphysfs/physfs.c Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/libphysfs/physfs.c Tue Nov 10 20:43:13 2015 +0100 @@ -486,7 +486,7 @@ memcpy(retval, io, sizeof (PHYSFS_Io)); retval->opaque = newfh; return retval; - + handleIo_dupe_failed: if (newfh) { diff -r 31570b766315 -r ed5a6478e710 misc/libphysfs/physfs.h --- a/misc/libphysfs/physfs.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/libphysfs/physfs.h Tue Nov 10 20:43:13 2015 +0100 @@ -128,9 +128,9 @@ * * PhysicsFS is mostly thread safe. The error messages returned by * PHYSFS_getLastError() are unique by thread, and library-state-setting - * functions are mutex'd. For efficiency, individual file accesses are - * not locked, so you can not safely read/write/seek/close/etc the same - * file from two threads at the same time. Other race conditions are bugs + * functions are mutex'd. For efficiency, individual file accesses are + * not locked, so you can not safely read/write/seek/close/etc the same + * file from two threads at the same time. Other race conditions are bugs * that should be reported/patched. * * While you CAN use stdio/syscall file access in a program that has PHYSFS_* @@ -2604,10 +2604,10 @@ */ typedef enum PHYSFS_FileType { - PHYSFS_FILETYPE_REGULAR, /**< a normal file */ - PHYSFS_FILETYPE_DIRECTORY, /**< a directory */ - PHYSFS_FILETYPE_SYMLINK, /**< a symlink */ - PHYSFS_FILETYPE_OTHER /**< something completely different like a device */ + PHYSFS_FILETYPE_REGULAR, /**< a normal file */ + PHYSFS_FILETYPE_DIRECTORY, /**< a directory */ + PHYSFS_FILETYPE_SYMLINK, /**< a symlink */ + PHYSFS_FILETYPE_OTHER /**< something completely different like a device */ } PHYSFS_FileType; /** @@ -2628,12 +2628,12 @@ */ typedef struct PHYSFS_Stat { - PHYSFS_sint64 filesize; /**< size in bytes, -1 for non-files and unknown */ - PHYSFS_sint64 modtime; /**< last modification time */ - PHYSFS_sint64 createtime; /**< like modtime, but for file creation time */ - PHYSFS_sint64 accesstime; /**< like modtime, but for file access time */ - PHYSFS_FileType filetype; /**< File? Directory? Symlink? */ - int readonly; /**< non-zero if read only, zero if writable. */ + PHYSFS_sint64 filesize; /**< size in bytes, -1 for non-files and unknown */ + PHYSFS_sint64 modtime; /**< last modification time */ + PHYSFS_sint64 createtime; /**< like modtime, but for file creation time */ + PHYSFS_sint64 accesstime; /**< like modtime, but for file access time */ + PHYSFS_FileType filetype; /**< File? Directory? Symlink? */ + int readonly; /**< non-zero if read only, zero if writable. */ } PHYSFS_Stat; /** diff -r 31570b766315 -r ed5a6478e710 misc/libphysfs/physfs_internal.h --- a/misc/libphysfs/physfs_internal.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/libphysfs/physfs_internal.h Tue Nov 10 20:43:13 2015 +0100 @@ -726,12 +726,12 @@ /* * Grab possession of a platform-specific mutex. Mutexes should be recursive; * that is, the same thread should be able to call this function multiple - * times in a row without causing a deadlock. This function should block + * times in a row without causing a deadlock. This function should block * until a thread can gain possession of the mutex. * - * Return non-zero if the mutex was grabbed, zero if there was an - * unrecoverable problem grabbing it (this should not be a matter of - * timing out! We're talking major system errors; block until the mutex + * Return non-zero if the mutex was grabbed, zero if there was an + * unrecoverable problem grabbing it (this should not be a matter of + * timing out! We're talking major system errors; block until the mutex * is available otherwise.) * * _DO NOT_ call __PHYSFS_setError() in here! Since setError calls this @@ -741,7 +741,7 @@ int __PHYSFS_platformGrabMutex(void *mutex); /* - * Relinquish possession of the mutex when this method has been called + * Relinquish possession of the mutex when this method has been called * once for each time that platformGrabMutex was called. Once possession has * been released, the next thread in line to grab the mutex (if any) may * proceed. diff -r 31570b766315 -r ed5a6478e710 misc/libphysfs/physfs_miniz.h --- a/misc/libphysfs/physfs_miniz.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/libphysfs/physfs_miniz.h Tue Nov 10 20:43:13 2015 +0100 @@ -12,7 +12,7 @@ typedef PHYSFS_sint16 mz_int16; typedef PHYSFS_uint16 mz_uint16; typedef PHYSFS_uint32 mz_uint32; -typedef unsigned int mz_uint; +typedef unsigned int mz_uint; typedef PHYSFS_uint64 mz_uint64; /* For more compatibility with zlib, miniz.c uses unsigned long for some parameters/struct members. */ @@ -670,7 +670,7 @@ #endif /* #ifndef TINFL_HEADER_FILE_ONLY */ -/* +/* This is free and unencumbered software released into the public domain. Anyone is free to copy, modify, publish, use, compile, sell, or diff -r 31570b766315 -r ed5a6478e710 misc/libphysfs/platform_macosx.c --- a/misc/libphysfs/platform_macosx.c Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/libphysfs/platform_macosx.c Tue Nov 10 20:43:13 2015 +0100 @@ -38,7 +38,7 @@ doesn't work; once a symbol is marked as hidden, it stays that way. */ void __eprintf (const char *string, const char *expression, - unsigned int line, const char *filename) + unsigned int line, const char *filename) { fprintf(stderr, string, expression, line, filename); fflush(stderr); @@ -144,7 +144,7 @@ if (!IOObjectConformsTo(service, kIOMediaClass)) return 0; - + wholeMedia = IORegistryEntryCreateCFProperty(service, CFSTR(kIOMediaWholeKey), cfallocator, 0); @@ -180,7 +180,7 @@ rc = IORegistryEntryCreateIterator(service, kIOServicePlane, kIORegistryIterateRecursively | kIORegistryIterateParents, &iter); - + if (!iter) return 0; @@ -204,7 +204,7 @@ } /* if */ IOObjectRelease(service); } while ((service = IOIteratorNext(iter)) && (!retval)); - + IOObjectRelease(iter); IOObjectRelease(service); diff -r 31570b766315 -r ed5a6478e710 misc/libphysfs/platform_posix.c --- a/misc/libphysfs/platform_posix.c Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/libphysfs/platform_posix.c Tue Nov 10 20:43:13 2015 +0100 @@ -83,7 +83,7 @@ } /* if */ } /* if */ } /* if */ - + return retval; } /* getUserDirByUID */ diff -r 31570b766315 -r ed5a6478e710 misc/libphysfs/platform_unix.c --- a/misc/libphysfs/platform_unix.c Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/libphysfs/platform_unix.c Tue Nov 10 20:43:13 2015 +0100 @@ -193,7 +193,7 @@ if (access(exe, X_OK) == 0) /* Exists as executable? We're done. */ { - exe[size - binlen] = '\0'; /* chop off filename, leave '/' */ + exe[size - binlen - 1] = '\0'; /* chop off filename, leave '/' */ return exe; } /* if */ diff -r 31570b766315 -r ed5a6478e710 misc/libphysfs/platform_windows.c --- a/misc/libphysfs/platform_windows.c Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/libphysfs/platform_windows.c Tue Nov 10 20:43:13 2015 +0100 @@ -171,7 +171,7 @@ stem(SEM_FAILCRITICALERRORS, &oldErrorMode); else oldErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS); - + /* Do detection. This may block if a disc is spinning up. */ for (i = 'A'; i <= 'Z'; i++) { @@ -443,7 +443,7 @@ * psize. Also note that the second parameter can't be * NULL or the function fails. */ - rc = pGetDir(accessToken, &dummy, &psize); + rc = pGetDir(accessToken, &dummy, &psize); assert(!rc); /* !!! FIXME: handle this gracefully. */ (void) rc; @@ -481,7 +481,7 @@ static int isSymlinkAttrs(const DWORD attr, const DWORD tag) { - return ( (attr & FILE_ATTRIBUTE_REPARSE_POINT) && + return ( (attr & FILE_ATTRIBUTE_REPARSE_POINT) && (tag == PHYSFS_IO_REPARSE_TAG_SYMLINK) ); } /* isSymlinkAttrs */ @@ -720,7 +720,7 @@ { BAIL_MACRO(errcodeFromWinApi(), 0); } /* if */ - + return 1; /* No error occured */ } /* __PHYSFS_platformSeek */ diff -r 31570b766315 -r ed5a6478e710 misc/libphyslayer/CMakeLists.txt --- a/misc/libphyslayer/CMakeLists.txt Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/libphyslayer/CMakeLists.txt Tue Nov 10 20:43:13 2015 +0100 @@ -11,9 +11,9 @@ include_directories(${PHYSFS_INCLUDE_DIR}) include_directories(${LUA_INCLUDE_DIR}) -## extra functions needed by Hedgewars -## TODO: maybe it's better to have them in a separate library? + set(PHYSLAYER_SRCS + physfscompat.c physfsrwops.c physfslualoader.c hwpacksmounter.c diff -r 31570b766315 -r ed5a6478e710 misc/libphyslayer/Xcode/Physlayer.xcodeproj/project.pbxproj --- a/misc/libphyslayer/Xcode/Physlayer.xcodeproj/project.pbxproj Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/libphyslayer/Xcode/Physlayer.xcodeproj/project.pbxproj Tue Nov 10 20:43:13 2015 +0100 @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 45; + objectVersion = 46; objects = { /* Begin PBXBuildFile section */ @@ -124,8 +124,11 @@ /* Begin PBXProject section */ 0867D690FE84028FC02AAC07 /* Project object */ = { isa = PBXProject; + attributes = { + LastUpgradeCheck = 0710; + }; buildConfigurationList = 1DEB922208733DC00010E9CD /* Build configuration list for PBXProject "Physlayer" */; - compatibilityVersion = "Xcode 3.1"; + compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 1; knownRegions = ( @@ -162,7 +165,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; COPY_PHASE_STRIP = NO; DSTROOT = /tmp/Physlayer.dst; GCC_DYNAMIC_NO_PIC = NO; @@ -173,6 +175,7 @@ GCC_PREFIX_HEADER = Physlayer_Prefix.pch; INSTALL_PATH = /usr/local/lib; PRODUCT_NAME = Physlayer; + SKIP_INSTALL = YES; }; name = Debug; }; @@ -180,24 +183,70 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; DSTROOT = /tmp/Physlayer.dst; GCC_MODEL_TUNING = G5; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = Physlayer_Prefix.pch; INSTALL_PATH = /usr/local/lib; PRODUCT_NAME = Physlayer; + SKIP_INSTALL = YES; }; name = Release; }; 1DEB922308733DC00010E9CD /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = c99; + GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "\"$(SRCROOT)/../../libphysfs\"", + "\"$(SRCROOT)/../../liblua\"", + "\"$(SRCROOT)/../../../../Library/SDL/include\"", + ); + ONLY_ACTIVE_ARCH = YES; + OTHER_LDFLAGS = "-ObjC"; + PREBINDING = NO; + SDKROOT = iphoneos; + VALID_ARCHS = "armv7 x86_64 arm64"; + }; + name = Debug; + }; + 1DEB922408733DC00010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = ( "\"$(SRCROOT)/../../libphysfs\"", @@ -207,25 +256,7 @@ OTHER_LDFLAGS = "-ObjC"; PREBINDING = NO; SDKROOT = iphoneos; - }; - name = Debug; - }; - 1DEB922408733DC00010E9CD /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; - GCC_C_LANGUAGE_STANDARD = c99; - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - HEADER_SEARCH_PATHS = ( - "\"$(SRCROOT)/../../libphysfs\"", - "\"$(SRCROOT)/../../liblua\"", - "\"$(SRCROOT)/../../../../Library/SDL/include\"", - ); - OTHER_LDFLAGS = "-ObjC"; - PREBINDING = NO; - SDKROOT = iphoneos; + VALID_ARCHS = "armv7 x86_64 arm64"; }; name = Release; }; diff -r 31570b766315 -r ed5a6478e710 misc/libphyslayer/hwpacksmounter.h --- a/misc/libphyslayer/hwpacksmounter.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/libphyslayer/hwpacksmounter.h Tue Nov 10 20:43:13 2015 +0100 @@ -2,6 +2,13 @@ #define HEDGEWARS_PACKAGES_MOUNTER_H #include "physfs.h" +#include "physfscompat.h" + +#ifndef PAS2C +#ifndef QT_VERSION +#include "lua.h" +#endif +#endif #ifdef __cplusplus extern "C" { @@ -10,6 +17,11 @@ PHYSFS_DECL void hedgewarsMountPackages(); PHYSFS_DECL void hedgewarsMountPackage(char * fileName); +#ifndef QT_VERSION +PHYSFS_DECL const char * physfsReader(lua_State *L, PHYSFS_File *f, size_t *size); +#endif +PHYSFS_DECL void physfsReaderSetBuffer(void *buffer); + #ifdef __cplusplus } #endif diff -r 31570b766315 -r ed5a6478e710 misc/libphyslayer/physfscompat.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/misc/libphyslayer/physfscompat.c Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,73 @@ +/* + * Hedgewars, a free turn based strategy game + * Copyright (c) 2004-2015 Andrey Korotaev + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "physfscompat.h" + +#ifdef HW_PHYSFS_COMPAT + +PHYSFS_DECL int PHYSFS_stat(const char *fname, PHYSFS_Stat *stat) +{ + PHYSFS_File * handle; + + if (PHYSFS_exists(fname)) + { + handle = PHYSFS_openRead(fname); + if (handle) + { + stat->filesize = PHYSFS_fileLength(handle); + PHYSFS_close(handle); + handle = 0; + } + else + stat->filesize = -1; + + stat->modtime = PHYSFS_getLastModTime(fname); + stat->createtime = -1; + stat->accesstime = -1; + + if (PHYSFS_isSymbolicLink(fname)) + stat->filetype = PHYSFS_FILETYPE_SYMLINK; + else if (PHYSFS_isDirectory(fname)) + stat->filetype = PHYSFS_FILETYPE_DIRECTORY; + else stat->filetype = PHYSFS_FILETYPE_REGULAR; + + stat->readonly = 0; /* not supported */ + + /* success */ + return 1; + } + + /* does not exist, can't stat */ + return 0; +} + +PHYSFS_DECL PHYSFS_sint64 PHYSFS_readBytes(PHYSFS_File *handle, void *buffer, + PHYSFS_uint64 len) +{ + return PHYSFS_read(handle, buffer, 1, len); +} + + +PHYSFS_DECL PHYSFS_sint64 PHYSFS_writeBytes(PHYSFS_File *handle, + const void *buffer, + PHYSFS_uint64 len) +{ + return PHYSFS_write(handle, buffer, 1, len); +} + +#endif /* HW_PHYSFS_COMPAT */ diff -r 31570b766315 -r ed5a6478e710 misc/libphyslayer/physfscompat.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/misc/libphyslayer/physfscompat.h Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,71 @@ +/* + * Hedgewars, a free turn based strategy game + * Copyright (c) 2004-2015 Andrey Korotaev + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _HEDGEWARS_PHYSFSCOMPAT_C_ +#define _HEDGEWARS_PHYSFSCOMPAT_C_ + +#include "physfs.h" + +#if PHYSFS_VER_MAJOR == 2 +#if PHYSFS_VER_MINOR == 0 + +#define HW_PHYSFS_COMPAT + +#ifdef __cplusplus +extern "C" { +#endif + +#define PHYSFS_DECL __EXPORT__ + +typedef enum PHYSFS_FileType +{ + PHYSFS_FILETYPE_REGULAR, + PHYSFS_FILETYPE_DIRECTORY, + PHYSFS_FILETYPE_SYMLINK, + PHYSFS_FILETYPE_OTHER +} PHYSFS_FileType; + +typedef struct PHYSFS_Stat +{ + PHYSFS_sint64 filesize; + PHYSFS_sint64 modtime; + PHYSFS_sint64 createtime; + PHYSFS_sint64 accesstime; + PHYSFS_FileType filetype; + int readonly; +} PHYSFS_Stat; + +PHYSFS_DECL int PHYSFS_stat(const char *fname, PHYSFS_Stat *stat); + +PHYSFS_DECL PHYSFS_sint64 PHYSFS_readBytes(PHYSFS_File *handle, void *buffer, + PHYSFS_uint64 len); + + +PHYSFS_DECL PHYSFS_sint64 PHYSFS_writeBytes(PHYSFS_File *handle, + const void *buffer, + PHYSFS_uint64 len); + + +#ifdef __cplusplus +} +#endif + +#endif /* PHYSFS_VER_MAJOR == 2 */ +#endif /* PHYSFS_VER_MINOR == 0 */ + +#endif /* _HEDGEWARS_PHYSFSCOMPAT_C_ */ diff -r 31570b766315 -r ed5a6478e710 misc/libphyslayer/physfslualoader.c --- a/misc/libphyslayer/physfslualoader.c Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/libphyslayer/physfslualoader.c Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,8 @@ #include "lua.h" #include "physfs.h" +#include "physfscompat.h" + #define BUFSIZE 1024 void *physfsReaderBuffer; diff -r 31570b766315 -r ed5a6478e710 misc/libphyslayer/physfsrwops.c --- a/misc/libphyslayer/physfsrwops.c Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/libphyslayer/physfsrwops.c Tue Nov 10 20:43:13 2015 +0100 @@ -95,7 +95,7 @@ SDL_SetError("Attempt to seek past start of file."); return -1; } /* if */ - + if (!PHYSFS_seek(handle, (PHYSFS_uint64) pos)) { SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError()); diff -r 31570b766315 -r ed5a6478e710 misc/libphyslayer/physfsrwops.h --- a/misc/libphyslayer/physfsrwops.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/libphyslayer/physfsrwops.h Tue Nov 10 20:43:13 2015 +0100 @@ -24,8 +24,11 @@ #define _INCLUDE_PHYSFSRWOPS_H_ #include "physfs.h" + #include "SDL.h" +#include "physfscompat.h" + #ifdef __cplusplus extern "C" { #endif diff -r 31570b766315 -r ed5a6478e710 misc/theme_editor.html --- a/misc/theme_editor.html Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/theme_editor.html Tue Nov 10 20:43:13 2015 +0100 @@ -7,113 +7,113 @@ var skyColor, waterTopColor, waterBottomColor; var elements = 7; var landArray; - + function landFunction(x){ return 384 - 192 * Math.sin(x * Math.PI/512); } - + function tryToDraw(){ if (--elements <= 0) { draw(); } } - + function load(){ var canvas = document.getElementById('preview'); if (canvas.getContext){ var ctx = canvas.getContext('2d'); - + ctx.fillStyle = '#0b294b'; ctx.fillRect(0, 0, 512, 384); - + ctx.font = "40pt Arial"; ctx.fillStyle = '#2b7bd5'; ctx.fillText('Loading Images...', 32, 212); } - + sky = new Image(); sky.onload = tryToDraw; sky.src = 'http://hedgewars.googlecode.com/hg/share/hedgewars/Data/Themes/Nature/Sky.png'; - + clouds = new Image(); clouds.onload = tryToDraw; clouds.src = 'http://hedgewars.googlecode.com/hg/share/hedgewars/Data/Graphics/Clouds.png'; - + horizont = new Image(); horizont.onload = tryToDraw; horizont.src = 'http://hedgewars.googlecode.com/hg/share/hedgewars/Data/Themes/Nature/horizont.png'; - + land = new Image(); land.onload = tryToDraw; land.src = 'http://hedgewars.googlecode.com/hg/share/hedgewars/Data/Themes/Nature/LandTex.png'; - + border = new Image(); border.onload = tryToDraw; border.src = 'http://hedgewars.googlecode.com/hg/share/hedgewars/Data/Themes/Nature/Border.png'; - + water = new Image(); water.onload = tryToDraw; water.src = 'http://hedgewars.googlecode.com/hg/share/hedgewars/Data/Graphics/BlueWater.png'; - + landArray = new Array(512); for (var x = 0; x < landArray.length; x++) landArray[x] = landFunction(x); - + skyColor = '#131252'; document.getElementById('skyColor').value = skyColor; - + waterTopColor = '#555C9D'; document.getElementById('waterTopColor').value = waterTopColor; - + waterBottomColor = '#343C7D'; document.getElementById('waterBottomColor').value = waterBottomColor; - + tryToDraw(); } - + function draw(){ var canvas = document.getElementById('preview'); if (canvas.getContext){ var ctx = canvas.getContext('2d'); - + ctx.fillStyle = skyColor; ctx.fillRect(0, 0, 512, 384); - + ctx.drawImage(sky, 0, 64, 512, 256); - + for (var i = 0; i < 4; i++) ctx.drawImage(clouds, 0, i * 128, 256, 128, i * 128, 64, 128, 64); - + ctx.drawImage(horizont, 0, 192, 512, 128); - + ctx.save(); - + ctx.beginPath(); ctx.moveTo(0, 384); for (var x = 0; x < landArray.length; x++) ctx.lineTo(x, landArray[x]); ctx.clip(); - + for (var i = 0; i < 2; i++) - for (var k = 0; k < 2; k++) - ctx.drawImage(land, i * 320, k * 240, 320, 240); - + for (var k = 0; k < 2; k++) + ctx.drawImage(land, i * 320, k * 240, 320, 240); + ctx.restore(); - + var k = 0; for (var x = 0; x < landArray.length; x++) { if (++k == 64) k = 0; ctx.drawImage(border, k, 0, 2, 16, x, landArray[x] - 4, 1, 8); } - - + + var gradient = ctx.createLinearGradient(0, 320, 0, 384); gradient.addColorStop(0, waterTopColor); gradient.addColorStop(1, waterBottomColor); ctx.fillStyle = gradient; ctx.fillRect(0, 320, 512, 384); - + for (var i = 0; i < 8; i++) ctx.drawImage(water, i * 64, 308, 64, 24); } diff -r 31570b766315 -r ed5a6478e710 misc/winutils/include/GL/glut.h --- a/misc/winutils/include/GL/glut.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/winutils/include/GL/glut.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,716 +1,716 @@ -#ifndef __glut_h__ -#define __glut_h__ - -/* Copyright (c) Mark J. Kilgard, 1994, 1995, 1996, 1998. */ - -/* This program is freely distributable without licensing fees and is - provided without guarantee or warrantee expressed or implied. This - program is -not- in the public domain. */ - -#if defined(_WIN32) - -/* GLUT 3.7 now tries to avoid including - to avoid name space pollution, but Win32's - needs APIENTRY and WINGDIAPI defined properly. */ -# if 0 - /* This would put tons of macros and crap in our clean name space. */ -# define WIN32_LEAN_AND_MEAN -# include -# else - /* XXX This is from Win32's */ -# ifndef APIENTRY -# define GLUT_APIENTRY_DEFINED -# if (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED) || defined(__BORLANDC__) || defined(__LCC__) -# define APIENTRY __stdcall -# else -# define APIENTRY -# endif -# endif - /* XXX This is from Win32's */ -# ifndef CALLBACK -# if (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS) || defined(__LCC__) -# define CALLBACK __stdcall -# else -# define CALLBACK -# endif -# endif - /* XXX Hack for lcc compiler. It doesn't support __declspec(dllimport), just __stdcall. */ -# if defined( __LCC__ ) -# undef WINGDIAPI -# define WINGDIAPI __stdcall -# else - /* XXX This is from Win32's and */ -# ifndef WINGDIAPI -# define GLUT_WINGDIAPI_DEFINED -# define WINGDIAPI __declspec(dllimport) -# endif -# endif - /* XXX This is from Win32's */ -# ifndef _WCHAR_T_DEFINED -typedef unsigned short wchar_t; -# define _WCHAR_T_DEFINED -# endif -# endif - -/* To disable automatic library usage for GLUT, define GLUT_NO_LIB_PRAGMA - in your compile preprocessor options. */ -# if !defined(GLUT_BUILDING_LIB) && !defined(GLUT_NO_LIB_PRAGMA) -# pragma comment (lib, "winmm.lib") /* link with Windows MultiMedia lib */ -/* To enable automatic SGI OpenGL for Windows library usage for GLUT, - define GLUT_USE_SGI_OPENGL in your compile preprocessor options. */ -# ifdef GLUT_USE_SGI_OPENGL -# pragma comment (lib, "opengl.lib") /* link with SGI OpenGL for Windows lib */ -# pragma comment (lib, "glu.lib") /* link with SGI OpenGL Utility lib */ -# pragma comment (lib, "glut.lib") /* link with Win32 GLUT for SGI OpenGL lib */ -# else -# pragma comment (lib, "opengl32.lib") /* link with Microsoft OpenGL lib */ -# pragma comment (lib, "glu32.lib") /* link with Microsoft OpenGL Utility lib */ -# pragma comment (lib, "glut32.lib") /* link with Win32 GLUT lib */ -# endif -# endif - -/* To disable supression of annoying warnings about floats being promoted - to doubles, define GLUT_NO_WARNING_DISABLE in your compile preprocessor - options. */ -# ifndef GLUT_NO_WARNING_DISABLE -# pragma warning (disable:4244) /* Disable bogus VC++ 4.2 conversion warnings. */ -# pragma warning (disable:4305) /* VC++ 5.0 version of above warning. */ -# endif - -/* Win32 has an annoying issue where there are multiple C run-time - libraries (CRTs). If the executable is linked with a different CRT - from the GLUT DLL, the GLUT DLL will not share the same CRT static - data seen by the executable. In particular, atexit callbacks registered - in the executable will not be called if GLUT calls its (different) - exit routine). GLUT is typically built with the - "/MD" option (the CRT with multithreading DLL support), but the Visual - C++ linker default is "/ML" (the single threaded CRT). - - One workaround to this issue is requiring users to always link with - the same CRT as GLUT is compiled with. That requires users supply a - non-standard option. GLUT 3.7 has its own built-in workaround where - the executable's "exit" function pointer is covertly passed to GLUT. - GLUT then calls the executable's exit function pointer to ensure that - any "atexit" calls registered by the application are called if GLUT - needs to exit. - - Note that the __glut*WithExit routines should NEVER be called directly. - To avoid the atexit workaround, #define GLUT_DISABLE_ATEXIT_HACK. */ - -/* XXX This is from Win32's */ -# if !defined(_MSC_VER) && !defined(__cdecl) - /* Define __cdecl for non-Microsoft compilers. */ -# define __cdecl -# define GLUT_DEFINED___CDECL -# endif -# ifndef _CRTIMP -# ifdef _NTSDK - /* Definition compatible with NT SDK */ -# define _CRTIMP -# else - /* Current definition */ -# ifdef _DLL -# define _CRTIMP __declspec(dllimport) -# else -# define _CRTIMP -# endif -# endif -# define GLUT_DEFINED__CRTIMP -# endif - -/* GLUT API entry point declarations for Win32. */ -# ifdef GLUT_BUILDING_LIB -# define GLUTAPI __declspec(dllexport) -# else -# ifdef _DLL -# define GLUTAPI __declspec(dllimport) -# else -# define GLUTAPI extern -# endif -# endif - -/* GLUT callback calling convention for Win32. */ -# define GLUTCALLBACK __cdecl - -#endif /* _WIN32 */ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#if defined(_WIN32) -# ifndef GLUT_BUILDING_LIB -extern _CRTIMP void __cdecl exit(int); -# endif -#else -/* non-Win32 case. */ -/* Define APIENTRY and CALLBACK to nothing if we aren't on Win32. */ -# define APIENTRY -# define GLUT_APIENTRY_DEFINED -# define CALLBACK -/* Define GLUTAPI and GLUTCALLBACK as below if we aren't on Win32. */ -# define GLUTAPI extern -# define GLUTCALLBACK -/* Prototype exit for the non-Win32 case (see above). */ -extern void exit(int); -#endif - -/** - GLUT API revision history: - - GLUT_API_VERSION is updated to reflect incompatible GLUT - API changes (interface changes, semantic changes, deletions, - or additions). - - GLUT_API_VERSION=1 First public release of GLUT. 11/29/94 - - GLUT_API_VERSION=2 Added support for OpenGL/GLX multisampling, - extension. Supports new input devices like tablet, dial and button - box, and Spaceball. Easy to query OpenGL extensions. - - GLUT_API_VERSION=3 glutMenuStatus added. - - GLUT_API_VERSION=4 glutInitDisplayString, glutWarpPointer, - glutBitmapLength, glutStrokeLength, glutWindowStatusFunc, dynamic - video resize subAPI, glutPostWindowRedisplay, glutKeyboardUpFunc, - glutSpecialUpFunc, glutIgnoreKeyRepeat, glutSetKeyRepeat, - glutJoystickFunc, glutForceJoystickFunc (NOT FINALIZED!). -**/ -#ifndef GLUT_API_VERSION /* allow this to be overriden */ -#define GLUT_API_VERSION 3 -#endif - -/** - GLUT implementation revision history: - - GLUT_XLIB_IMPLEMENTATION is updated to reflect both GLUT - API revisions and implementation revisions (ie, bug fixes). - - GLUT_XLIB_IMPLEMENTATION=1 mjk's first public release of - GLUT Xlib-based implementation. 11/29/94 - - GLUT_XLIB_IMPLEMENTATION=2 mjk's second public release of - GLUT Xlib-based implementation providing GLUT version 2 - interfaces. - - GLUT_XLIB_IMPLEMENTATION=3 mjk's GLUT 2.2 images. 4/17/95 - - GLUT_XLIB_IMPLEMENTATION=4 mjk's GLUT 2.3 images. 6/?/95 - - GLUT_XLIB_IMPLEMENTATION=5 mjk's GLUT 3.0 images. 10/?/95 - - GLUT_XLIB_IMPLEMENTATION=7 mjk's GLUT 3.1+ with glutWarpPoitner. 7/24/96 - - GLUT_XLIB_IMPLEMENTATION=8 mjk's GLUT 3.1+ with glutWarpPoitner - and video resize. 1/3/97 - - GLUT_XLIB_IMPLEMENTATION=9 mjk's GLUT 3.4 release with early GLUT 4 routines. - - GLUT_XLIB_IMPLEMENTATION=11 Mesa 2.5's GLUT 3.6 release. - - GLUT_XLIB_IMPLEMENTATION=12 mjk's GLUT 3.6 release with early GLUT 4 routines + signal handling. - - GLUT_XLIB_IMPLEMENTATION=13 mjk's GLUT 3.7 beta with GameGLUT support. - - GLUT_XLIB_IMPLEMENTATION=14 mjk's GLUT 3.7 beta with f90gl friend interface. - - GLUT_XLIB_IMPLEMENTATION=15 mjk's GLUT 3.7 beta sync'ed with Mesa -**/ -#ifndef GLUT_XLIB_IMPLEMENTATION /* Allow this to be overriden. */ -#define GLUT_XLIB_IMPLEMENTATION 15 -#endif - -/* Display mode bit masks. */ -#define GLUT_RGB 0 -#define GLUT_RGBA GLUT_RGB -#define GLUT_INDEX 1 -#define GLUT_SINGLE 0 -#define GLUT_DOUBLE 2 -#define GLUT_ACCUM 4 -#define GLUT_ALPHA 8 -#define GLUT_DEPTH 16 -#define GLUT_STENCIL 32 -#if (GLUT_API_VERSION >= 2) -#define GLUT_MULTISAMPLE 128 -#define GLUT_STEREO 256 -#endif -#if (GLUT_API_VERSION >= 3) -#define GLUT_LUMINANCE 512 -#endif - -/* Mouse buttons. */ -#define GLUT_LEFT_BUTTON 0 -#define GLUT_MIDDLE_BUTTON 1 -#define GLUT_RIGHT_BUTTON 2 - -/* Mouse button state. */ -#define GLUT_DOWN 0 -#define GLUT_UP 1 - -#if (GLUT_API_VERSION >= 2) -/* function keys */ -#define GLUT_KEY_F1 1 -#define GLUT_KEY_F2 2 -#define GLUT_KEY_F3 3 -#define GLUT_KEY_F4 4 -#define GLUT_KEY_F5 5 -#define GLUT_KEY_F6 6 -#define GLUT_KEY_F7 7 -#define GLUT_KEY_F8 8 -#define GLUT_KEY_F9 9 -#define GLUT_KEY_F10 10 -#define GLUT_KEY_F11 11 -#define GLUT_KEY_F12 12 -/* directional keys */ -#define GLUT_KEY_LEFT 100 -#define GLUT_KEY_UP 101 -#define GLUT_KEY_RIGHT 102 -#define GLUT_KEY_DOWN 103 -#define GLUT_KEY_PAGE_UP 104 -#define GLUT_KEY_PAGE_DOWN 105 -#define GLUT_KEY_HOME 106 -#define GLUT_KEY_END 107 -#define GLUT_KEY_INSERT 108 -#endif - -/* Entry/exit state. */ -#define GLUT_LEFT 0 -#define GLUT_ENTERED 1 - -/* Menu usage state. */ -#define GLUT_MENU_NOT_IN_USE 0 -#define GLUT_MENU_IN_USE 1 - -/* Visibility state. */ -#define GLUT_NOT_VISIBLE 0 -#define GLUT_VISIBLE 1 - -/* Window status state. */ -#define GLUT_HIDDEN 0 -#define GLUT_FULLY_RETAINED 1 -#define GLUT_PARTIALLY_RETAINED 2 -#define GLUT_FULLY_COVERED 3 - -/* Color index component selection values. */ -#define GLUT_RED 0 -#define GLUT_GREEN 1 -#define GLUT_BLUE 2 - -#if defined(_WIN32) -/* Stroke font constants (use these in GLUT program). */ -#define GLUT_STROKE_ROMAN ((void*)0) -#define GLUT_STROKE_MONO_ROMAN ((void*)1) - -/* Bitmap font constants (use these in GLUT program). */ -#define GLUT_BITMAP_9_BY_15 ((void*)2) -#define GLUT_BITMAP_8_BY_13 ((void*)3) -#define GLUT_BITMAP_TIMES_ROMAN_10 ((void*)4) -#define GLUT_BITMAP_TIMES_ROMAN_24 ((void*)5) -#if (GLUT_API_VERSION >= 3) -#define GLUT_BITMAP_HELVETICA_10 ((void*)6) -#define GLUT_BITMAP_HELVETICA_12 ((void*)7) -#define GLUT_BITMAP_HELVETICA_18 ((void*)8) -#endif -#else -/* Stroke font opaque addresses (use constants instead in source code). */ -GLUTAPI void *glutStrokeRoman; -GLUTAPI void *glutStrokeMonoRoman; - -/* Stroke font constants (use these in GLUT program). */ -#define GLUT_STROKE_ROMAN (&glutStrokeRoman) -#define GLUT_STROKE_MONO_ROMAN (&glutStrokeMonoRoman) - -/* Bitmap font opaque addresses (use constants instead in source code). */ -GLUTAPI void *glutBitmap9By15; -GLUTAPI void *glutBitmap8By13; -GLUTAPI void *glutBitmapTimesRoman10; -GLUTAPI void *glutBitmapTimesRoman24; -GLUTAPI void *glutBitmapHelvetica10; -GLUTAPI void *glutBitmapHelvetica12; -GLUTAPI void *glutBitmapHelvetica18; - -/* Bitmap font constants (use these in GLUT program). */ -#define GLUT_BITMAP_9_BY_15 (&glutBitmap9By15) -#define GLUT_BITMAP_8_BY_13 (&glutBitmap8By13) -#define GLUT_BITMAP_TIMES_ROMAN_10 (&glutBitmapTimesRoman10) -#define GLUT_BITMAP_TIMES_ROMAN_24 (&glutBitmapTimesRoman24) -#if (GLUT_API_VERSION >= 3) -#define GLUT_BITMAP_HELVETICA_10 (&glutBitmapHelvetica10) -#define GLUT_BITMAP_HELVETICA_12 (&glutBitmapHelvetica12) -#define GLUT_BITMAP_HELVETICA_18 (&glutBitmapHelvetica18) -#endif -#endif - -/* glutGet parameters. */ -#define GLUT_WINDOW_X ((GLenum) 100) -#define GLUT_WINDOW_Y ((GLenum) 101) -#define GLUT_WINDOW_WIDTH ((GLenum) 102) -#define GLUT_WINDOW_HEIGHT ((GLenum) 103) -#define GLUT_WINDOW_BUFFER_SIZE ((GLenum) 104) -#define GLUT_WINDOW_STENCIL_SIZE ((GLenum) 105) -#define GLUT_WINDOW_DEPTH_SIZE ((GLenum) 106) -#define GLUT_WINDOW_RED_SIZE ((GLenum) 107) -#define GLUT_WINDOW_GREEN_SIZE ((GLenum) 108) -#define GLUT_WINDOW_BLUE_SIZE ((GLenum) 109) -#define GLUT_WINDOW_ALPHA_SIZE ((GLenum) 110) -#define GLUT_WINDOW_ACCUM_RED_SIZE ((GLenum) 111) -#define GLUT_WINDOW_ACCUM_GREEN_SIZE ((GLenum) 112) -#define GLUT_WINDOW_ACCUM_BLUE_SIZE ((GLenum) 113) -#define GLUT_WINDOW_ACCUM_ALPHA_SIZE ((GLenum) 114) -#define GLUT_WINDOW_DOUBLEBUFFER ((GLenum) 115) -#define GLUT_WINDOW_RGBA ((GLenum) 116) -#define GLUT_WINDOW_PARENT ((GLenum) 117) -#define GLUT_WINDOW_NUM_CHILDREN ((GLenum) 118) -#define GLUT_WINDOW_COLORMAP_SIZE ((GLenum) 119) -#if (GLUT_API_VERSION >= 2) -#define GLUT_WINDOW_NUM_SAMPLES ((GLenum) 120) -#define GLUT_WINDOW_STEREO ((GLenum) 121) -#endif -#if (GLUT_API_VERSION >= 3) -#define GLUT_WINDOW_CURSOR ((GLenum) 122) -#endif -#define GLUT_SCREEN_WIDTH ((GLenum) 200) -#define GLUT_SCREEN_HEIGHT ((GLenum) 201) -#define GLUT_SCREEN_WIDTH_MM ((GLenum) 202) -#define GLUT_SCREEN_HEIGHT_MM ((GLenum) 203) -#define GLUT_MENU_NUM_ITEMS ((GLenum) 300) -#define GLUT_DISPLAY_MODE_POSSIBLE ((GLenum) 400) -#define GLUT_INIT_WINDOW_X ((GLenum) 500) -#define GLUT_INIT_WINDOW_Y ((GLenum) 501) -#define GLUT_INIT_WINDOW_WIDTH ((GLenum) 502) -#define GLUT_INIT_WINDOW_HEIGHT ((GLenum) 503) -#define GLUT_INIT_DISPLAY_MODE ((GLenum) 504) -#if (GLUT_API_VERSION >= 2) -#define GLUT_ELAPSED_TIME ((GLenum) 700) -#endif -#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13) -#define GLUT_WINDOW_FORMAT_ID ((GLenum) 123) -#endif - -#if (GLUT_API_VERSION >= 2) -/* glutDeviceGet parameters. */ -#define GLUT_HAS_KEYBOARD ((GLenum) 600) -#define GLUT_HAS_MOUSE ((GLenum) 601) -#define GLUT_HAS_SPACEBALL ((GLenum) 602) -#define GLUT_HAS_DIAL_AND_BUTTON_BOX ((GLenum) 603) -#define GLUT_HAS_TABLET ((GLenum) 604) -#define GLUT_NUM_MOUSE_BUTTONS ((GLenum) 605) -#define GLUT_NUM_SPACEBALL_BUTTONS ((GLenum) 606) -#define GLUT_NUM_BUTTON_BOX_BUTTONS ((GLenum) 607) -#define GLUT_NUM_DIALS ((GLenum) 608) -#define GLUT_NUM_TABLET_BUTTONS ((GLenum) 609) -#endif -#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13) -#define GLUT_DEVICE_IGNORE_KEY_REPEAT ((GLenum) 610) -#define GLUT_DEVICE_KEY_REPEAT ((GLenum) 611) -#define GLUT_HAS_JOYSTICK ((GLenum) 612) -#define GLUT_OWNS_JOYSTICK ((GLenum) 613) -#define GLUT_JOYSTICK_BUTTONS ((GLenum) 614) -#define GLUT_JOYSTICK_AXES ((GLenum) 615) -#define GLUT_JOYSTICK_POLL_RATE ((GLenum) 616) -#endif - -#if (GLUT_API_VERSION >= 3) -/* glutLayerGet parameters. */ -#define GLUT_OVERLAY_POSSIBLE ((GLenum) 800) -#define GLUT_LAYER_IN_USE ((GLenum) 801) -#define GLUT_HAS_OVERLAY ((GLenum) 802) -#define GLUT_TRANSPARENT_INDEX ((GLenum) 803) -#define GLUT_NORMAL_DAMAGED ((GLenum) 804) -#define GLUT_OVERLAY_DAMAGED ((GLenum) 805) - -#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) -/* glutVideoResizeGet parameters. */ -#define GLUT_VIDEO_RESIZE_POSSIBLE ((GLenum) 900) -#define GLUT_VIDEO_RESIZE_IN_USE ((GLenum) 901) -#define GLUT_VIDEO_RESIZE_X_DELTA ((GLenum) 902) -#define GLUT_VIDEO_RESIZE_Y_DELTA ((GLenum) 903) -#define GLUT_VIDEO_RESIZE_WIDTH_DELTA ((GLenum) 904) -#define GLUT_VIDEO_RESIZE_HEIGHT_DELTA ((GLenum) 905) -#define GLUT_VIDEO_RESIZE_X ((GLenum) 906) -#define GLUT_VIDEO_RESIZE_Y ((GLenum) 907) -#define GLUT_VIDEO_RESIZE_WIDTH ((GLenum) 908) -#define GLUT_VIDEO_RESIZE_HEIGHT ((GLenum) 909) -#endif - -/* glutUseLayer parameters. */ -#define GLUT_NORMAL ((GLenum) 0) -#define GLUT_OVERLAY ((GLenum) 1) - -/* glutGetModifiers return mask. */ -#define GLUT_ACTIVE_SHIFT 1 -#define GLUT_ACTIVE_CTRL 2 -#define GLUT_ACTIVE_ALT 4 - -/* glutSetCursor parameters. */ -/* Basic arrows. */ -#define GLUT_CURSOR_RIGHT_ARROW 0 -#define GLUT_CURSOR_LEFT_ARROW 1 -/* Symbolic cursor shapes. */ -#define GLUT_CURSOR_INFO 2 -#define GLUT_CURSOR_DESTROY 3 -#define GLUT_CURSOR_HELP 4 -#define GLUT_CURSOR_CYCLE 5 -#define GLUT_CURSOR_SPRAY 6 -#define GLUT_CURSOR_WAIT 7 -#define GLUT_CURSOR_TEXT 8 -#define GLUT_CURSOR_CROSSHAIR 9 -/* Directional cursors. */ -#define GLUT_CURSOR_UP_DOWN 10 -#define GLUT_CURSOR_LEFT_RIGHT 11 -/* Sizing cursors. */ -#define GLUT_CURSOR_TOP_SIDE 12 -#define GLUT_CURSOR_BOTTOM_SIDE 13 -#define GLUT_CURSOR_LEFT_SIDE 14 -#define GLUT_CURSOR_RIGHT_SIDE 15 -#define GLUT_CURSOR_TOP_LEFT_CORNER 16 -#define GLUT_CURSOR_TOP_RIGHT_CORNER 17 -#define GLUT_CURSOR_BOTTOM_RIGHT_CORNER 18 -#define GLUT_CURSOR_BOTTOM_LEFT_CORNER 19 -/* Inherit from parent window. */ -#define GLUT_CURSOR_INHERIT 100 -/* Blank cursor. */ -#define GLUT_CURSOR_NONE 101 -/* Fullscreen crosshair (if available). */ -#define GLUT_CURSOR_FULL_CROSSHAIR 102 -#endif - -/* GLUT initialization sub-API. */ -GLUTAPI void APIENTRY glutInit(int *argcp, char **argv); -#if defined(_WIN32) && !defined(GLUT_DISABLE_ATEXIT_HACK) -GLUTAPI void APIENTRY __glutInitWithExit(int *argcp, char **argv, void (__cdecl *exitfunc)(int)); -#ifndef GLUT_BUILDING_LIB -static void APIENTRY glutInit_ATEXIT_HACK(int *argcp, char **argv) { __glutInitWithExit(argcp, argv, exit); } -#define glutInit glutInit_ATEXIT_HACK -#endif -#endif -GLUTAPI void APIENTRY glutInitDisplayMode(unsigned int mode); -#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) -GLUTAPI void APIENTRY glutInitDisplayString(const char *string); -#endif -GLUTAPI void APIENTRY glutInitWindowPosition(int x, int y); -GLUTAPI void APIENTRY glutInitWindowSize(int width, int height); -GLUTAPI void APIENTRY glutMainLoop(void); - -/* GLUT window sub-API. */ -GLUTAPI int APIENTRY glutCreateWindow(const char *title); -#if defined(_WIN32) && !defined(GLUT_DISABLE_ATEXIT_HACK) -GLUTAPI int APIENTRY __glutCreateWindowWithExit(const char *title, void (__cdecl *exitfunc)(int)); -#ifndef GLUT_BUILDING_LIB -static int APIENTRY glutCreateWindow_ATEXIT_HACK(const char *title) { return __glutCreateWindowWithExit(title, exit); } -#define glutCreateWindow glutCreateWindow_ATEXIT_HACK -#endif -#endif -GLUTAPI int APIENTRY glutCreateSubWindow(int win, int x, int y, int width, int height); -GLUTAPI void APIENTRY glutDestroyWindow(int win); -GLUTAPI void APIENTRY glutPostRedisplay(void); -#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 11) -GLUTAPI void APIENTRY glutPostWindowRedisplay(int win); -#endif -GLUTAPI void APIENTRY glutSwapBuffers(void); -GLUTAPI int APIENTRY glutGetWindow(void); -GLUTAPI void APIENTRY glutSetWindow(int win); -GLUTAPI void APIENTRY glutSetWindowTitle(const char *title); -GLUTAPI void APIENTRY glutSetIconTitle(const char *title); -GLUTAPI void APIENTRY glutPositionWindow(int x, int y); -GLUTAPI void APIENTRY glutReshapeWindow(int width, int height); -GLUTAPI void APIENTRY glutPopWindow(void); -GLUTAPI void APIENTRY glutPushWindow(void); -GLUTAPI void APIENTRY glutIconifyWindow(void); -GLUTAPI void APIENTRY glutShowWindow(void); -GLUTAPI void APIENTRY glutHideWindow(void); -#if (GLUT_API_VERSION >= 3) -GLUTAPI void APIENTRY glutFullScreen(void); -GLUTAPI void APIENTRY glutSetCursor(int cursor); -#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) -GLUTAPI void APIENTRY glutWarpPointer(int x, int y); -#endif - -/* GLUT overlay sub-API. */ -GLUTAPI void APIENTRY glutEstablishOverlay(void); -GLUTAPI void APIENTRY glutRemoveOverlay(void); -GLUTAPI void APIENTRY glutUseLayer(GLenum layer); -GLUTAPI void APIENTRY glutPostOverlayRedisplay(void); -#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 11) -GLUTAPI void APIENTRY glutPostWindowOverlayRedisplay(int win); -#endif -GLUTAPI void APIENTRY glutShowOverlay(void); -GLUTAPI void APIENTRY glutHideOverlay(void); -#endif - -/* GLUT menu sub-API. */ -GLUTAPI int APIENTRY glutCreateMenu(void (GLUTCALLBACK *func)(int)); -#if defined(_WIN32) && !defined(GLUT_DISABLE_ATEXIT_HACK) -GLUTAPI int APIENTRY __glutCreateMenuWithExit(void (GLUTCALLBACK *func)(int), void (__cdecl *exitfunc)(int)); -#ifndef GLUT_BUILDING_LIB -static int APIENTRY glutCreateMenu_ATEXIT_HACK(void (GLUTCALLBACK *func)(int)) { return __glutCreateMenuWithExit(func, exit); } -#define glutCreateMenu glutCreateMenu_ATEXIT_HACK -#endif -#endif -GLUTAPI void APIENTRY glutDestroyMenu(int menu); -GLUTAPI int APIENTRY glutGetMenu(void); -GLUTAPI void APIENTRY glutSetMenu(int menu); -GLUTAPI void APIENTRY glutAddMenuEntry(const char *label, int value); -GLUTAPI void APIENTRY glutAddSubMenu(const char *label, int submenu); -GLUTAPI void APIENTRY glutChangeToMenuEntry(int item, const char *label, int value); -GLUTAPI void APIENTRY glutChangeToSubMenu(int item, const char *label, int submenu); -GLUTAPI void APIENTRY glutRemoveMenuItem(int item); -GLUTAPI void APIENTRY glutAttachMenu(int button); -GLUTAPI void APIENTRY glutDetachMenu(int button); - -/* GLUT window callback sub-API. */ -GLUTAPI void APIENTRY glutDisplayFunc(void (GLUTCALLBACK *func)(void)); -GLUTAPI void APIENTRY glutReshapeFunc(void (GLUTCALLBACK *func)(int width, int height)); -GLUTAPI void APIENTRY glutKeyboardFunc(void (GLUTCALLBACK *func)(unsigned char key, int x, int y)); -GLUTAPI void APIENTRY glutMouseFunc(void (GLUTCALLBACK *func)(int button, int state, int x, int y)); -GLUTAPI void APIENTRY glutMotionFunc(void (GLUTCALLBACK *func)(int x, int y)); -GLUTAPI void APIENTRY glutPassiveMotionFunc(void (GLUTCALLBACK *func)(int x, int y)); -GLUTAPI void APIENTRY glutEntryFunc(void (GLUTCALLBACK *func)(int state)); -GLUTAPI void APIENTRY glutVisibilityFunc(void (GLUTCALLBACK *func)(int state)); -GLUTAPI void APIENTRY glutIdleFunc(void (GLUTCALLBACK *func)(void)); -GLUTAPI void APIENTRY glutTimerFunc(unsigned int millis, void (GLUTCALLBACK *func)(int value), int value); -GLUTAPI void APIENTRY glutMenuStateFunc(void (GLUTCALLBACK *func)(int state)); -#if (GLUT_API_VERSION >= 2) -GLUTAPI void APIENTRY glutSpecialFunc(void (GLUTCALLBACK *func)(int key, int x, int y)); -GLUTAPI void APIENTRY glutSpaceballMotionFunc(void (GLUTCALLBACK *func)(int x, int y, int z)); -GLUTAPI void APIENTRY glutSpaceballRotateFunc(void (GLUTCALLBACK *func)(int x, int y, int z)); -GLUTAPI void APIENTRY glutSpaceballButtonFunc(void (GLUTCALLBACK *func)(int button, int state)); -GLUTAPI void APIENTRY glutButtonBoxFunc(void (GLUTCALLBACK *func)(int button, int state)); -GLUTAPI void APIENTRY glutDialsFunc(void (GLUTCALLBACK *func)(int dial, int value)); -GLUTAPI void APIENTRY glutTabletMotionFunc(void (GLUTCALLBACK *func)(int x, int y)); -GLUTAPI void APIENTRY glutTabletButtonFunc(void (GLUTCALLBACK *func)(int button, int state, int x, int y)); -#if (GLUT_API_VERSION >= 3) -GLUTAPI void APIENTRY glutMenuStatusFunc(void (GLUTCALLBACK *func)(int status, int x, int y)); -GLUTAPI void APIENTRY glutOverlayDisplayFunc(void (GLUTCALLBACK *func)(void)); -#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) -GLUTAPI void APIENTRY glutWindowStatusFunc(void (GLUTCALLBACK *func)(int state)); -#endif -#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13) -GLUTAPI void APIENTRY glutKeyboardUpFunc(void (GLUTCALLBACK *func)(unsigned char key, int x, int y)); -GLUTAPI void APIENTRY glutSpecialUpFunc(void (GLUTCALLBACK *func)(int key, int x, int y)); -GLUTAPI void APIENTRY glutJoystickFunc(void (GLUTCALLBACK *func)(unsigned int buttonMask, int x, int y, int z), int pollInterval); -#endif -#endif -#endif - -/* GLUT color index sub-API. */ -GLUTAPI void APIENTRY glutSetColor(int, GLfloat red, GLfloat green, GLfloat blue); -GLUTAPI GLfloat APIENTRY glutGetColor(int ndx, int component); -GLUTAPI void APIENTRY glutCopyColormap(int win); - -/* GLUT state retrieval sub-API. */ -GLUTAPI int APIENTRY glutGet(GLenum type); -GLUTAPI int APIENTRY glutDeviceGet(GLenum type); -#if (GLUT_API_VERSION >= 2) -/* GLUT extension support sub-API */ -GLUTAPI int APIENTRY glutExtensionSupported(const char *name); -#endif -#if (GLUT_API_VERSION >= 3) -GLUTAPI int APIENTRY glutGetModifiers(void); -GLUTAPI int APIENTRY glutLayerGet(GLenum type); -#endif - -/* GLUT font sub-API */ -GLUTAPI void APIENTRY glutBitmapCharacter(void *font, int character); -GLUTAPI int APIENTRY glutBitmapWidth(void *font, int character); -GLUTAPI void APIENTRY glutStrokeCharacter(void *font, int character); -GLUTAPI int APIENTRY glutStrokeWidth(void *font, int character); -#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) -GLUTAPI int APIENTRY glutBitmapLength(void *font, const unsigned char *string); -GLUTAPI int APIENTRY glutStrokeLength(void *font, const unsigned char *string); -#endif - -/* GLUT pre-built models sub-API */ -GLUTAPI void APIENTRY glutWireSphere(GLdouble radius, GLint slices, GLint stacks); -GLUTAPI void APIENTRY glutSolidSphere(GLdouble radius, GLint slices, GLint stacks); -GLUTAPI void APIENTRY glutWireCone(GLdouble base, GLdouble height, GLint slices, GLint stacks); -GLUTAPI void APIENTRY glutSolidCone(GLdouble base, GLdouble height, GLint slices, GLint stacks); -GLUTAPI void APIENTRY glutWireCube(GLdouble size); -GLUTAPI void APIENTRY glutSolidCube(GLdouble size); -GLUTAPI void APIENTRY glutWireTorus(GLdouble innerRadius, GLdouble outerRadius, GLint sides, GLint rings); -GLUTAPI void APIENTRY glutSolidTorus(GLdouble innerRadius, GLdouble outerRadius, GLint sides, GLint rings); -GLUTAPI void APIENTRY glutWireDodecahedron(void); -GLUTAPI void APIENTRY glutSolidDodecahedron(void); -GLUTAPI void APIENTRY glutWireTeapot(GLdouble size); -GLUTAPI void APIENTRY glutSolidTeapot(GLdouble size); -GLUTAPI void APIENTRY glutWireOctahedron(void); -GLUTAPI void APIENTRY glutSolidOctahedron(void); -GLUTAPI void APIENTRY glutWireTetrahedron(void); -GLUTAPI void APIENTRY glutSolidTetrahedron(void); -GLUTAPI void APIENTRY glutWireIcosahedron(void); -GLUTAPI void APIENTRY glutSolidIcosahedron(void); - -#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) -/* GLUT video resize sub-API. */ -GLUTAPI int APIENTRY glutVideoResizeGet(GLenum param); -GLUTAPI void APIENTRY glutSetupVideoResizing(void); -GLUTAPI void APIENTRY glutStopVideoResizing(void); -GLUTAPI void APIENTRY glutVideoResize(int x, int y, int width, int height); -GLUTAPI void APIENTRY glutVideoPan(int x, int y, int width, int height); - -/* GLUT debugging sub-API. */ -GLUTAPI void APIENTRY glutReportErrors(void); -#endif - -#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13) -/* GLUT device control sub-API. */ -/* glutSetKeyRepeat modes. */ -#define GLUT_KEY_REPEAT_OFF 0 -#define GLUT_KEY_REPEAT_ON 1 -#define GLUT_KEY_REPEAT_DEFAULT 2 - -/* Joystick button masks. */ -#define GLUT_JOYSTICK_BUTTON_A 1 -#define GLUT_JOYSTICK_BUTTON_B 2 -#define GLUT_JOYSTICK_BUTTON_C 4 -#define GLUT_JOYSTICK_BUTTON_D 8 - -GLUTAPI void APIENTRY glutIgnoreKeyRepeat(int ignore); -GLUTAPI void APIENTRY glutSetKeyRepeat(int repeatMode); -GLUTAPI void APIENTRY glutForceJoystickFunc(void); - -/* GLUT game mode sub-API. */ -/* glutGameModeGet. */ -#define GLUT_GAME_MODE_ACTIVE ((GLenum) 0) -#define GLUT_GAME_MODE_POSSIBLE ((GLenum) 1) -#define GLUT_GAME_MODE_WIDTH ((GLenum) 2) -#define GLUT_GAME_MODE_HEIGHT ((GLenum) 3) -#define GLUT_GAME_MODE_PIXEL_DEPTH ((GLenum) 4) -#define GLUT_GAME_MODE_REFRESH_RATE ((GLenum) 5) -#define GLUT_GAME_MODE_DISPLAY_CHANGED ((GLenum) 6) - -GLUTAPI void APIENTRY glutGameModeString(const char *string); -GLUTAPI int APIENTRY glutEnterGameMode(void); -GLUTAPI void APIENTRY glutLeaveGameMode(void); -GLUTAPI int APIENTRY glutGameModeGet(GLenum mode); -#endif - -#ifdef __cplusplus -} - -#endif - -#ifdef GLUT_APIENTRY_DEFINED -# undef GLUT_APIENTRY_DEFINED -# undef APIENTRY -#endif - -#ifdef GLUT_WINGDIAPI_DEFINED -# undef GLUT_WINGDIAPI_DEFINED -# undef WINGDIAPI -#endif - -#ifdef GLUT_DEFINED___CDECL -# undef GLUT_DEFINED___CDECL -# undef __cdecl -#endif - -#ifdef GLUT_DEFINED__CRTIMP -# undef GLUT_DEFINED__CRTIMP -# undef _CRTIMP -#endif - -#endif /* __glut_h__ */ +#ifndef __glut_h__ +#define __glut_h__ + +/* Copyright (c) Mark J. Kilgard, 1994, 1995, 1996, 1998. */ + +/* This program is freely distributable without licensing fees and is + provided without guarantee or warrantee expressed or implied. This + program is -not- in the public domain. */ + +#if defined(_WIN32) + +/* GLUT 3.7 now tries to avoid including + to avoid name space pollution, but Win32's + needs APIENTRY and WINGDIAPI defined properly. */ +# if 0 + /* This would put tons of macros and crap in our clean name space. */ +# define WIN32_LEAN_AND_MEAN +# include +# else + /* XXX This is from Win32's */ +# ifndef APIENTRY +# define GLUT_APIENTRY_DEFINED +# if (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED) || defined(__BORLANDC__) || defined(__LCC__) +# define APIENTRY __stdcall +# else +# define APIENTRY +# endif +# endif + /* XXX This is from Win32's */ +# ifndef CALLBACK +# if (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS) || defined(__LCC__) +# define CALLBACK __stdcall +# else +# define CALLBACK +# endif +# endif + /* XXX Hack for lcc compiler. It doesn't support __declspec(dllimport), just __stdcall. */ +# if defined( __LCC__ ) +# undef WINGDIAPI +# define WINGDIAPI __stdcall +# else + /* XXX This is from Win32's and */ +# ifndef WINGDIAPI +# define GLUT_WINGDIAPI_DEFINED +# define WINGDIAPI __declspec(dllimport) +# endif +# endif + /* XXX This is from Win32's */ +# ifndef _WCHAR_T_DEFINED +typedef unsigned short wchar_t; +# define _WCHAR_T_DEFINED +# endif +# endif + +/* To disable automatic library usage for GLUT, define GLUT_NO_LIB_PRAGMA + in your compile preprocessor options. */ +# if !defined(GLUT_BUILDING_LIB) && !defined(GLUT_NO_LIB_PRAGMA) +# pragma comment (lib, "winmm.lib") /* link with Windows MultiMedia lib */ +/* To enable automatic SGI OpenGL for Windows library usage for GLUT, + define GLUT_USE_SGI_OPENGL in your compile preprocessor options. */ +# ifdef GLUT_USE_SGI_OPENGL +# pragma comment (lib, "opengl.lib") /* link with SGI OpenGL for Windows lib */ +# pragma comment (lib, "glu.lib") /* link with SGI OpenGL Utility lib */ +# pragma comment (lib, "glut.lib") /* link with Win32 GLUT for SGI OpenGL lib */ +# else +# pragma comment (lib, "opengl32.lib") /* link with Microsoft OpenGL lib */ +# pragma comment (lib, "glu32.lib") /* link with Microsoft OpenGL Utility lib */ +# pragma comment (lib, "glut32.lib") /* link with Win32 GLUT lib */ +# endif +# endif + +/* To disable supression of annoying warnings about floats being promoted + to doubles, define GLUT_NO_WARNING_DISABLE in your compile preprocessor + options. */ +# ifndef GLUT_NO_WARNING_DISABLE +# pragma warning (disable:4244) /* Disable bogus VC++ 4.2 conversion warnings. */ +# pragma warning (disable:4305) /* VC++ 5.0 version of above warning. */ +# endif + +/* Win32 has an annoying issue where there are multiple C run-time + libraries (CRTs). If the executable is linked with a different CRT + from the GLUT DLL, the GLUT DLL will not share the same CRT static + data seen by the executable. In particular, atexit callbacks registered + in the executable will not be called if GLUT calls its (different) + exit routine). GLUT is typically built with the + "/MD" option (the CRT with multithreading DLL support), but the Visual + C++ linker default is "/ML" (the single threaded CRT). + + One workaround to this issue is requiring users to always link with + the same CRT as GLUT is compiled with. That requires users supply a + non-standard option. GLUT 3.7 has its own built-in workaround where + the executable's "exit" function pointer is covertly passed to GLUT. + GLUT then calls the executable's exit function pointer to ensure that + any "atexit" calls registered by the application are called if GLUT + needs to exit. + + Note that the __glut*WithExit routines should NEVER be called directly. + To avoid the atexit workaround, #define GLUT_DISABLE_ATEXIT_HACK. */ + +/* XXX This is from Win32's */ +# if !defined(_MSC_VER) && !defined(__cdecl) + /* Define __cdecl for non-Microsoft compilers. */ +# define __cdecl +# define GLUT_DEFINED___CDECL +# endif +# ifndef _CRTIMP +# ifdef _NTSDK + /* Definition compatible with NT SDK */ +# define _CRTIMP +# else + /* Current definition */ +# ifdef _DLL +# define _CRTIMP __declspec(dllimport) +# else +# define _CRTIMP +# endif +# endif +# define GLUT_DEFINED__CRTIMP +# endif + +/* GLUT API entry point declarations for Win32. */ +# ifdef GLUT_BUILDING_LIB +# define GLUTAPI __declspec(dllexport) +# else +# ifdef _DLL +# define GLUTAPI __declspec(dllimport) +# else +# define GLUTAPI extern +# endif +# endif + +/* GLUT callback calling convention for Win32. */ +# define GLUTCALLBACK __cdecl + +#endif /* _WIN32 */ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(_WIN32) +# ifndef GLUT_BUILDING_LIB +extern _CRTIMP void __cdecl exit(int); +# endif +#else +/* non-Win32 case. */ +/* Define APIENTRY and CALLBACK to nothing if we aren't on Win32. */ +# define APIENTRY +# define GLUT_APIENTRY_DEFINED +# define CALLBACK +/* Define GLUTAPI and GLUTCALLBACK as below if we aren't on Win32. */ +# define GLUTAPI extern +# define GLUTCALLBACK +/* Prototype exit for the non-Win32 case (see above). */ +extern void exit(int); +#endif + +/** + GLUT API revision history: + + GLUT_API_VERSION is updated to reflect incompatible GLUT + API changes (interface changes, semantic changes, deletions, + or additions). + + GLUT_API_VERSION=1 First public release of GLUT. 11/29/94 + + GLUT_API_VERSION=2 Added support for OpenGL/GLX multisampling, + extension. Supports new input devices like tablet, dial and button + box, and Spaceball. Easy to query OpenGL extensions. + + GLUT_API_VERSION=3 glutMenuStatus added. + + GLUT_API_VERSION=4 glutInitDisplayString, glutWarpPointer, + glutBitmapLength, glutStrokeLength, glutWindowStatusFunc, dynamic + video resize subAPI, glutPostWindowRedisplay, glutKeyboardUpFunc, + glutSpecialUpFunc, glutIgnoreKeyRepeat, glutSetKeyRepeat, + glutJoystickFunc, glutForceJoystickFunc (NOT FINALIZED!). +**/ +#ifndef GLUT_API_VERSION /* allow this to be overriden */ +#define GLUT_API_VERSION 3 +#endif + +/** + GLUT implementation revision history: + + GLUT_XLIB_IMPLEMENTATION is updated to reflect both GLUT + API revisions and implementation revisions (ie, bug fixes). + + GLUT_XLIB_IMPLEMENTATION=1 mjk's first public release of + GLUT Xlib-based implementation. 11/29/94 + + GLUT_XLIB_IMPLEMENTATION=2 mjk's second public release of + GLUT Xlib-based implementation providing GLUT version 2 + interfaces. + + GLUT_XLIB_IMPLEMENTATION=3 mjk's GLUT 2.2 images. 4/17/95 + + GLUT_XLIB_IMPLEMENTATION=4 mjk's GLUT 2.3 images. 6/?/95 + + GLUT_XLIB_IMPLEMENTATION=5 mjk's GLUT 3.0 images. 10/?/95 + + GLUT_XLIB_IMPLEMENTATION=7 mjk's GLUT 3.1+ with glutWarpPoitner. 7/24/96 + + GLUT_XLIB_IMPLEMENTATION=8 mjk's GLUT 3.1+ with glutWarpPoitner + and video resize. 1/3/97 + + GLUT_XLIB_IMPLEMENTATION=9 mjk's GLUT 3.4 release with early GLUT 4 routines. + + GLUT_XLIB_IMPLEMENTATION=11 Mesa 2.5's GLUT 3.6 release. + + GLUT_XLIB_IMPLEMENTATION=12 mjk's GLUT 3.6 release with early GLUT 4 routines + signal handling. + + GLUT_XLIB_IMPLEMENTATION=13 mjk's GLUT 3.7 beta with GameGLUT support. + + GLUT_XLIB_IMPLEMENTATION=14 mjk's GLUT 3.7 beta with f90gl friend interface. + + GLUT_XLIB_IMPLEMENTATION=15 mjk's GLUT 3.7 beta sync'ed with Mesa +**/ +#ifndef GLUT_XLIB_IMPLEMENTATION /* Allow this to be overriden. */ +#define GLUT_XLIB_IMPLEMENTATION 15 +#endif + +/* Display mode bit masks. */ +#define GLUT_RGB 0 +#define GLUT_RGBA GLUT_RGB +#define GLUT_INDEX 1 +#define GLUT_SINGLE 0 +#define GLUT_DOUBLE 2 +#define GLUT_ACCUM 4 +#define GLUT_ALPHA 8 +#define GLUT_DEPTH 16 +#define GLUT_STENCIL 32 +#if (GLUT_API_VERSION >= 2) +#define GLUT_MULTISAMPLE 128 +#define GLUT_STEREO 256 +#endif +#if (GLUT_API_VERSION >= 3) +#define GLUT_LUMINANCE 512 +#endif + +/* Mouse buttons. */ +#define GLUT_LEFT_BUTTON 0 +#define GLUT_MIDDLE_BUTTON 1 +#define GLUT_RIGHT_BUTTON 2 + +/* Mouse button state. */ +#define GLUT_DOWN 0 +#define GLUT_UP 1 + +#if (GLUT_API_VERSION >= 2) +/* function keys */ +#define GLUT_KEY_F1 1 +#define GLUT_KEY_F2 2 +#define GLUT_KEY_F3 3 +#define GLUT_KEY_F4 4 +#define GLUT_KEY_F5 5 +#define GLUT_KEY_F6 6 +#define GLUT_KEY_F7 7 +#define GLUT_KEY_F8 8 +#define GLUT_KEY_F9 9 +#define GLUT_KEY_F10 10 +#define GLUT_KEY_F11 11 +#define GLUT_KEY_F12 12 +/* directional keys */ +#define GLUT_KEY_LEFT 100 +#define GLUT_KEY_UP 101 +#define GLUT_KEY_RIGHT 102 +#define GLUT_KEY_DOWN 103 +#define GLUT_KEY_PAGE_UP 104 +#define GLUT_KEY_PAGE_DOWN 105 +#define GLUT_KEY_HOME 106 +#define GLUT_KEY_END 107 +#define GLUT_KEY_INSERT 108 +#endif + +/* Entry/exit state. */ +#define GLUT_LEFT 0 +#define GLUT_ENTERED 1 + +/* Menu usage state. */ +#define GLUT_MENU_NOT_IN_USE 0 +#define GLUT_MENU_IN_USE 1 + +/* Visibility state. */ +#define GLUT_NOT_VISIBLE 0 +#define GLUT_VISIBLE 1 + +/* Window status state. */ +#define GLUT_HIDDEN 0 +#define GLUT_FULLY_RETAINED 1 +#define GLUT_PARTIALLY_RETAINED 2 +#define GLUT_FULLY_COVERED 3 + +/* Color index component selection values. */ +#define GLUT_RED 0 +#define GLUT_GREEN 1 +#define GLUT_BLUE 2 + +#if defined(_WIN32) +/* Stroke font constants (use these in GLUT program). */ +#define GLUT_STROKE_ROMAN ((void*)0) +#define GLUT_STROKE_MONO_ROMAN ((void*)1) + +/* Bitmap font constants (use these in GLUT program). */ +#define GLUT_BITMAP_9_BY_15 ((void*)2) +#define GLUT_BITMAP_8_BY_13 ((void*)3) +#define GLUT_BITMAP_TIMES_ROMAN_10 ((void*)4) +#define GLUT_BITMAP_TIMES_ROMAN_24 ((void*)5) +#if (GLUT_API_VERSION >= 3) +#define GLUT_BITMAP_HELVETICA_10 ((void*)6) +#define GLUT_BITMAP_HELVETICA_12 ((void*)7) +#define GLUT_BITMAP_HELVETICA_18 ((void*)8) +#endif +#else +/* Stroke font opaque addresses (use constants instead in source code). */ +GLUTAPI void *glutStrokeRoman; +GLUTAPI void *glutStrokeMonoRoman; + +/* Stroke font constants (use these in GLUT program). */ +#define GLUT_STROKE_ROMAN (&glutStrokeRoman) +#define GLUT_STROKE_MONO_ROMAN (&glutStrokeMonoRoman) + +/* Bitmap font opaque addresses (use constants instead in source code). */ +GLUTAPI void *glutBitmap9By15; +GLUTAPI void *glutBitmap8By13; +GLUTAPI void *glutBitmapTimesRoman10; +GLUTAPI void *glutBitmapTimesRoman24; +GLUTAPI void *glutBitmapHelvetica10; +GLUTAPI void *glutBitmapHelvetica12; +GLUTAPI void *glutBitmapHelvetica18; + +/* Bitmap font constants (use these in GLUT program). */ +#define GLUT_BITMAP_9_BY_15 (&glutBitmap9By15) +#define GLUT_BITMAP_8_BY_13 (&glutBitmap8By13) +#define GLUT_BITMAP_TIMES_ROMAN_10 (&glutBitmapTimesRoman10) +#define GLUT_BITMAP_TIMES_ROMAN_24 (&glutBitmapTimesRoman24) +#if (GLUT_API_VERSION >= 3) +#define GLUT_BITMAP_HELVETICA_10 (&glutBitmapHelvetica10) +#define GLUT_BITMAP_HELVETICA_12 (&glutBitmapHelvetica12) +#define GLUT_BITMAP_HELVETICA_18 (&glutBitmapHelvetica18) +#endif +#endif + +/* glutGet parameters. */ +#define GLUT_WINDOW_X ((GLenum) 100) +#define GLUT_WINDOW_Y ((GLenum) 101) +#define GLUT_WINDOW_WIDTH ((GLenum) 102) +#define GLUT_WINDOW_HEIGHT ((GLenum) 103) +#define GLUT_WINDOW_BUFFER_SIZE ((GLenum) 104) +#define GLUT_WINDOW_STENCIL_SIZE ((GLenum) 105) +#define GLUT_WINDOW_DEPTH_SIZE ((GLenum) 106) +#define GLUT_WINDOW_RED_SIZE ((GLenum) 107) +#define GLUT_WINDOW_GREEN_SIZE ((GLenum) 108) +#define GLUT_WINDOW_BLUE_SIZE ((GLenum) 109) +#define GLUT_WINDOW_ALPHA_SIZE ((GLenum) 110) +#define GLUT_WINDOW_ACCUM_RED_SIZE ((GLenum) 111) +#define GLUT_WINDOW_ACCUM_GREEN_SIZE ((GLenum) 112) +#define GLUT_WINDOW_ACCUM_BLUE_SIZE ((GLenum) 113) +#define GLUT_WINDOW_ACCUM_ALPHA_SIZE ((GLenum) 114) +#define GLUT_WINDOW_DOUBLEBUFFER ((GLenum) 115) +#define GLUT_WINDOW_RGBA ((GLenum) 116) +#define GLUT_WINDOW_PARENT ((GLenum) 117) +#define GLUT_WINDOW_NUM_CHILDREN ((GLenum) 118) +#define GLUT_WINDOW_COLORMAP_SIZE ((GLenum) 119) +#if (GLUT_API_VERSION >= 2) +#define GLUT_WINDOW_NUM_SAMPLES ((GLenum) 120) +#define GLUT_WINDOW_STEREO ((GLenum) 121) +#endif +#if (GLUT_API_VERSION >= 3) +#define GLUT_WINDOW_CURSOR ((GLenum) 122) +#endif +#define GLUT_SCREEN_WIDTH ((GLenum) 200) +#define GLUT_SCREEN_HEIGHT ((GLenum) 201) +#define GLUT_SCREEN_WIDTH_MM ((GLenum) 202) +#define GLUT_SCREEN_HEIGHT_MM ((GLenum) 203) +#define GLUT_MENU_NUM_ITEMS ((GLenum) 300) +#define GLUT_DISPLAY_MODE_POSSIBLE ((GLenum) 400) +#define GLUT_INIT_WINDOW_X ((GLenum) 500) +#define GLUT_INIT_WINDOW_Y ((GLenum) 501) +#define GLUT_INIT_WINDOW_WIDTH ((GLenum) 502) +#define GLUT_INIT_WINDOW_HEIGHT ((GLenum) 503) +#define GLUT_INIT_DISPLAY_MODE ((GLenum) 504) +#if (GLUT_API_VERSION >= 2) +#define GLUT_ELAPSED_TIME ((GLenum) 700) +#endif +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13) +#define GLUT_WINDOW_FORMAT_ID ((GLenum) 123) +#endif + +#if (GLUT_API_VERSION >= 2) +/* glutDeviceGet parameters. */ +#define GLUT_HAS_KEYBOARD ((GLenum) 600) +#define GLUT_HAS_MOUSE ((GLenum) 601) +#define GLUT_HAS_SPACEBALL ((GLenum) 602) +#define GLUT_HAS_DIAL_AND_BUTTON_BOX ((GLenum) 603) +#define GLUT_HAS_TABLET ((GLenum) 604) +#define GLUT_NUM_MOUSE_BUTTONS ((GLenum) 605) +#define GLUT_NUM_SPACEBALL_BUTTONS ((GLenum) 606) +#define GLUT_NUM_BUTTON_BOX_BUTTONS ((GLenum) 607) +#define GLUT_NUM_DIALS ((GLenum) 608) +#define GLUT_NUM_TABLET_BUTTONS ((GLenum) 609) +#endif +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13) +#define GLUT_DEVICE_IGNORE_KEY_REPEAT ((GLenum) 610) +#define GLUT_DEVICE_KEY_REPEAT ((GLenum) 611) +#define GLUT_HAS_JOYSTICK ((GLenum) 612) +#define GLUT_OWNS_JOYSTICK ((GLenum) 613) +#define GLUT_JOYSTICK_BUTTONS ((GLenum) 614) +#define GLUT_JOYSTICK_AXES ((GLenum) 615) +#define GLUT_JOYSTICK_POLL_RATE ((GLenum) 616) +#endif + +#if (GLUT_API_VERSION >= 3) +/* glutLayerGet parameters. */ +#define GLUT_OVERLAY_POSSIBLE ((GLenum) 800) +#define GLUT_LAYER_IN_USE ((GLenum) 801) +#define GLUT_HAS_OVERLAY ((GLenum) 802) +#define GLUT_TRANSPARENT_INDEX ((GLenum) 803) +#define GLUT_NORMAL_DAMAGED ((GLenum) 804) +#define GLUT_OVERLAY_DAMAGED ((GLenum) 805) + +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) +/* glutVideoResizeGet parameters. */ +#define GLUT_VIDEO_RESIZE_POSSIBLE ((GLenum) 900) +#define GLUT_VIDEO_RESIZE_IN_USE ((GLenum) 901) +#define GLUT_VIDEO_RESIZE_X_DELTA ((GLenum) 902) +#define GLUT_VIDEO_RESIZE_Y_DELTA ((GLenum) 903) +#define GLUT_VIDEO_RESIZE_WIDTH_DELTA ((GLenum) 904) +#define GLUT_VIDEO_RESIZE_HEIGHT_DELTA ((GLenum) 905) +#define GLUT_VIDEO_RESIZE_X ((GLenum) 906) +#define GLUT_VIDEO_RESIZE_Y ((GLenum) 907) +#define GLUT_VIDEO_RESIZE_WIDTH ((GLenum) 908) +#define GLUT_VIDEO_RESIZE_HEIGHT ((GLenum) 909) +#endif + +/* glutUseLayer parameters. */ +#define GLUT_NORMAL ((GLenum) 0) +#define GLUT_OVERLAY ((GLenum) 1) + +/* glutGetModifiers return mask. */ +#define GLUT_ACTIVE_SHIFT 1 +#define GLUT_ACTIVE_CTRL 2 +#define GLUT_ACTIVE_ALT 4 + +/* glutSetCursor parameters. */ +/* Basic arrows. */ +#define GLUT_CURSOR_RIGHT_ARROW 0 +#define GLUT_CURSOR_LEFT_ARROW 1 +/* Symbolic cursor shapes. */ +#define GLUT_CURSOR_INFO 2 +#define GLUT_CURSOR_DESTROY 3 +#define GLUT_CURSOR_HELP 4 +#define GLUT_CURSOR_CYCLE 5 +#define GLUT_CURSOR_SPRAY 6 +#define GLUT_CURSOR_WAIT 7 +#define GLUT_CURSOR_TEXT 8 +#define GLUT_CURSOR_CROSSHAIR 9 +/* Directional cursors. */ +#define GLUT_CURSOR_UP_DOWN 10 +#define GLUT_CURSOR_LEFT_RIGHT 11 +/* Sizing cursors. */ +#define GLUT_CURSOR_TOP_SIDE 12 +#define GLUT_CURSOR_BOTTOM_SIDE 13 +#define GLUT_CURSOR_LEFT_SIDE 14 +#define GLUT_CURSOR_RIGHT_SIDE 15 +#define GLUT_CURSOR_TOP_LEFT_CORNER 16 +#define GLUT_CURSOR_TOP_RIGHT_CORNER 17 +#define GLUT_CURSOR_BOTTOM_RIGHT_CORNER 18 +#define GLUT_CURSOR_BOTTOM_LEFT_CORNER 19 +/* Inherit from parent window. */ +#define GLUT_CURSOR_INHERIT 100 +/* Blank cursor. */ +#define GLUT_CURSOR_NONE 101 +/* Fullscreen crosshair (if available). */ +#define GLUT_CURSOR_FULL_CROSSHAIR 102 +#endif + +/* GLUT initialization sub-API. */ +GLUTAPI void APIENTRY glutInit(int *argcp, char **argv); +#if defined(_WIN32) && !defined(GLUT_DISABLE_ATEXIT_HACK) +GLUTAPI void APIENTRY __glutInitWithExit(int *argcp, char **argv, void (__cdecl *exitfunc)(int)); +#ifndef GLUT_BUILDING_LIB +static void APIENTRY glutInit_ATEXIT_HACK(int *argcp, char **argv) { __glutInitWithExit(argcp, argv, exit); } +#define glutInit glutInit_ATEXIT_HACK +#endif +#endif +GLUTAPI void APIENTRY glutInitDisplayMode(unsigned int mode); +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) +GLUTAPI void APIENTRY glutInitDisplayString(const char *string); +#endif +GLUTAPI void APIENTRY glutInitWindowPosition(int x, int y); +GLUTAPI void APIENTRY glutInitWindowSize(int width, int height); +GLUTAPI void APIENTRY glutMainLoop(void); + +/* GLUT window sub-API. */ +GLUTAPI int APIENTRY glutCreateWindow(const char *title); +#if defined(_WIN32) && !defined(GLUT_DISABLE_ATEXIT_HACK) +GLUTAPI int APIENTRY __glutCreateWindowWithExit(const char *title, void (__cdecl *exitfunc)(int)); +#ifndef GLUT_BUILDING_LIB +static int APIENTRY glutCreateWindow_ATEXIT_HACK(const char *title) { return __glutCreateWindowWithExit(title, exit); } +#define glutCreateWindow glutCreateWindow_ATEXIT_HACK +#endif +#endif +GLUTAPI int APIENTRY glutCreateSubWindow(int win, int x, int y, int width, int height); +GLUTAPI void APIENTRY glutDestroyWindow(int win); +GLUTAPI void APIENTRY glutPostRedisplay(void); +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 11) +GLUTAPI void APIENTRY glutPostWindowRedisplay(int win); +#endif +GLUTAPI void APIENTRY glutSwapBuffers(void); +GLUTAPI int APIENTRY glutGetWindow(void); +GLUTAPI void APIENTRY glutSetWindow(int win); +GLUTAPI void APIENTRY glutSetWindowTitle(const char *title); +GLUTAPI void APIENTRY glutSetIconTitle(const char *title); +GLUTAPI void APIENTRY glutPositionWindow(int x, int y); +GLUTAPI void APIENTRY glutReshapeWindow(int width, int height); +GLUTAPI void APIENTRY glutPopWindow(void); +GLUTAPI void APIENTRY glutPushWindow(void); +GLUTAPI void APIENTRY glutIconifyWindow(void); +GLUTAPI void APIENTRY glutShowWindow(void); +GLUTAPI void APIENTRY glutHideWindow(void); +#if (GLUT_API_VERSION >= 3) +GLUTAPI void APIENTRY glutFullScreen(void); +GLUTAPI void APIENTRY glutSetCursor(int cursor); +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) +GLUTAPI void APIENTRY glutWarpPointer(int x, int y); +#endif + +/* GLUT overlay sub-API. */ +GLUTAPI void APIENTRY glutEstablishOverlay(void); +GLUTAPI void APIENTRY glutRemoveOverlay(void); +GLUTAPI void APIENTRY glutUseLayer(GLenum layer); +GLUTAPI void APIENTRY glutPostOverlayRedisplay(void); +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 11) +GLUTAPI void APIENTRY glutPostWindowOverlayRedisplay(int win); +#endif +GLUTAPI void APIENTRY glutShowOverlay(void); +GLUTAPI void APIENTRY glutHideOverlay(void); +#endif + +/* GLUT menu sub-API. */ +GLUTAPI int APIENTRY glutCreateMenu(void (GLUTCALLBACK *func)(int)); +#if defined(_WIN32) && !defined(GLUT_DISABLE_ATEXIT_HACK) +GLUTAPI int APIENTRY __glutCreateMenuWithExit(void (GLUTCALLBACK *func)(int), void (__cdecl *exitfunc)(int)); +#ifndef GLUT_BUILDING_LIB +static int APIENTRY glutCreateMenu_ATEXIT_HACK(void (GLUTCALLBACK *func)(int)) { return __glutCreateMenuWithExit(func, exit); } +#define glutCreateMenu glutCreateMenu_ATEXIT_HACK +#endif +#endif +GLUTAPI void APIENTRY glutDestroyMenu(int menu); +GLUTAPI int APIENTRY glutGetMenu(void); +GLUTAPI void APIENTRY glutSetMenu(int menu); +GLUTAPI void APIENTRY glutAddMenuEntry(const char *label, int value); +GLUTAPI void APIENTRY glutAddSubMenu(const char *label, int submenu); +GLUTAPI void APIENTRY glutChangeToMenuEntry(int item, const char *label, int value); +GLUTAPI void APIENTRY glutChangeToSubMenu(int item, const char *label, int submenu); +GLUTAPI void APIENTRY glutRemoveMenuItem(int item); +GLUTAPI void APIENTRY glutAttachMenu(int button); +GLUTAPI void APIENTRY glutDetachMenu(int button); + +/* GLUT window callback sub-API. */ +GLUTAPI void APIENTRY glutDisplayFunc(void (GLUTCALLBACK *func)(void)); +GLUTAPI void APIENTRY glutReshapeFunc(void (GLUTCALLBACK *func)(int width, int height)); +GLUTAPI void APIENTRY glutKeyboardFunc(void (GLUTCALLBACK *func)(unsigned char key, int x, int y)); +GLUTAPI void APIENTRY glutMouseFunc(void (GLUTCALLBACK *func)(int button, int state, int x, int y)); +GLUTAPI void APIENTRY glutMotionFunc(void (GLUTCALLBACK *func)(int x, int y)); +GLUTAPI void APIENTRY glutPassiveMotionFunc(void (GLUTCALLBACK *func)(int x, int y)); +GLUTAPI void APIENTRY glutEntryFunc(void (GLUTCALLBACK *func)(int state)); +GLUTAPI void APIENTRY glutVisibilityFunc(void (GLUTCALLBACK *func)(int state)); +GLUTAPI void APIENTRY glutIdleFunc(void (GLUTCALLBACK *func)(void)); +GLUTAPI void APIENTRY glutTimerFunc(unsigned int millis, void (GLUTCALLBACK *func)(int value), int value); +GLUTAPI void APIENTRY glutMenuStateFunc(void (GLUTCALLBACK *func)(int state)); +#if (GLUT_API_VERSION >= 2) +GLUTAPI void APIENTRY glutSpecialFunc(void (GLUTCALLBACK *func)(int key, int x, int y)); +GLUTAPI void APIENTRY glutSpaceballMotionFunc(void (GLUTCALLBACK *func)(int x, int y, int z)); +GLUTAPI void APIENTRY glutSpaceballRotateFunc(void (GLUTCALLBACK *func)(int x, int y, int z)); +GLUTAPI void APIENTRY glutSpaceballButtonFunc(void (GLUTCALLBACK *func)(int button, int state)); +GLUTAPI void APIENTRY glutButtonBoxFunc(void (GLUTCALLBACK *func)(int button, int state)); +GLUTAPI void APIENTRY glutDialsFunc(void (GLUTCALLBACK *func)(int dial, int value)); +GLUTAPI void APIENTRY glutTabletMotionFunc(void (GLUTCALLBACK *func)(int x, int y)); +GLUTAPI void APIENTRY glutTabletButtonFunc(void (GLUTCALLBACK *func)(int button, int state, int x, int y)); +#if (GLUT_API_VERSION >= 3) +GLUTAPI void APIENTRY glutMenuStatusFunc(void (GLUTCALLBACK *func)(int status, int x, int y)); +GLUTAPI void APIENTRY glutOverlayDisplayFunc(void (GLUTCALLBACK *func)(void)); +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) +GLUTAPI void APIENTRY glutWindowStatusFunc(void (GLUTCALLBACK *func)(int state)); +#endif +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13) +GLUTAPI void APIENTRY glutKeyboardUpFunc(void (GLUTCALLBACK *func)(unsigned char key, int x, int y)); +GLUTAPI void APIENTRY glutSpecialUpFunc(void (GLUTCALLBACK *func)(int key, int x, int y)); +GLUTAPI void APIENTRY glutJoystickFunc(void (GLUTCALLBACK *func)(unsigned int buttonMask, int x, int y, int z), int pollInterval); +#endif +#endif +#endif + +/* GLUT color index sub-API. */ +GLUTAPI void APIENTRY glutSetColor(int, GLfloat red, GLfloat green, GLfloat blue); +GLUTAPI GLfloat APIENTRY glutGetColor(int ndx, int component); +GLUTAPI void APIENTRY glutCopyColormap(int win); + +/* GLUT state retrieval sub-API. */ +GLUTAPI int APIENTRY glutGet(GLenum type); +GLUTAPI int APIENTRY glutDeviceGet(GLenum type); +#if (GLUT_API_VERSION >= 2) +/* GLUT extension support sub-API */ +GLUTAPI int APIENTRY glutExtensionSupported(const char *name); +#endif +#if (GLUT_API_VERSION >= 3) +GLUTAPI int APIENTRY glutGetModifiers(void); +GLUTAPI int APIENTRY glutLayerGet(GLenum type); +#endif + +/* GLUT font sub-API */ +GLUTAPI void APIENTRY glutBitmapCharacter(void *font, int character); +GLUTAPI int APIENTRY glutBitmapWidth(void *font, int character); +GLUTAPI void APIENTRY glutStrokeCharacter(void *font, int character); +GLUTAPI int APIENTRY glutStrokeWidth(void *font, int character); +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) +GLUTAPI int APIENTRY glutBitmapLength(void *font, const unsigned char *string); +GLUTAPI int APIENTRY glutStrokeLength(void *font, const unsigned char *string); +#endif + +/* GLUT pre-built models sub-API */ +GLUTAPI void APIENTRY glutWireSphere(GLdouble radius, GLint slices, GLint stacks); +GLUTAPI void APIENTRY glutSolidSphere(GLdouble radius, GLint slices, GLint stacks); +GLUTAPI void APIENTRY glutWireCone(GLdouble base, GLdouble height, GLint slices, GLint stacks); +GLUTAPI void APIENTRY glutSolidCone(GLdouble base, GLdouble height, GLint slices, GLint stacks); +GLUTAPI void APIENTRY glutWireCube(GLdouble size); +GLUTAPI void APIENTRY glutSolidCube(GLdouble size); +GLUTAPI void APIENTRY glutWireTorus(GLdouble innerRadius, GLdouble outerRadius, GLint sides, GLint rings); +GLUTAPI void APIENTRY glutSolidTorus(GLdouble innerRadius, GLdouble outerRadius, GLint sides, GLint rings); +GLUTAPI void APIENTRY glutWireDodecahedron(void); +GLUTAPI void APIENTRY glutSolidDodecahedron(void); +GLUTAPI void APIENTRY glutWireTeapot(GLdouble size); +GLUTAPI void APIENTRY glutSolidTeapot(GLdouble size); +GLUTAPI void APIENTRY glutWireOctahedron(void); +GLUTAPI void APIENTRY glutSolidOctahedron(void); +GLUTAPI void APIENTRY glutWireTetrahedron(void); +GLUTAPI void APIENTRY glutSolidTetrahedron(void); +GLUTAPI void APIENTRY glutWireIcosahedron(void); +GLUTAPI void APIENTRY glutSolidIcosahedron(void); + +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) +/* GLUT video resize sub-API. */ +GLUTAPI int APIENTRY glutVideoResizeGet(GLenum param); +GLUTAPI void APIENTRY glutSetupVideoResizing(void); +GLUTAPI void APIENTRY glutStopVideoResizing(void); +GLUTAPI void APIENTRY glutVideoResize(int x, int y, int width, int height); +GLUTAPI void APIENTRY glutVideoPan(int x, int y, int width, int height); + +/* GLUT debugging sub-API. */ +GLUTAPI void APIENTRY glutReportErrors(void); +#endif + +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13) +/* GLUT device control sub-API. */ +/* glutSetKeyRepeat modes. */ +#define GLUT_KEY_REPEAT_OFF 0 +#define GLUT_KEY_REPEAT_ON 1 +#define GLUT_KEY_REPEAT_DEFAULT 2 + +/* Joystick button masks. */ +#define GLUT_JOYSTICK_BUTTON_A 1 +#define GLUT_JOYSTICK_BUTTON_B 2 +#define GLUT_JOYSTICK_BUTTON_C 4 +#define GLUT_JOYSTICK_BUTTON_D 8 + +GLUTAPI void APIENTRY glutIgnoreKeyRepeat(int ignore); +GLUTAPI void APIENTRY glutSetKeyRepeat(int repeatMode); +GLUTAPI void APIENTRY glutForceJoystickFunc(void); + +/* GLUT game mode sub-API. */ +/* glutGameModeGet. */ +#define GLUT_GAME_MODE_ACTIVE ((GLenum) 0) +#define GLUT_GAME_MODE_POSSIBLE ((GLenum) 1) +#define GLUT_GAME_MODE_WIDTH ((GLenum) 2) +#define GLUT_GAME_MODE_HEIGHT ((GLenum) 3) +#define GLUT_GAME_MODE_PIXEL_DEPTH ((GLenum) 4) +#define GLUT_GAME_MODE_REFRESH_RATE ((GLenum) 5) +#define GLUT_GAME_MODE_DISPLAY_CHANGED ((GLenum) 6) + +GLUTAPI void APIENTRY glutGameModeString(const char *string); +GLUTAPI int APIENTRY glutEnterGameMode(void); +GLUTAPI void APIENTRY glutLeaveGameMode(void); +GLUTAPI int APIENTRY glutGameModeGet(GLenum mode); +#endif + +#ifdef __cplusplus +} + +#endif + +#ifdef GLUT_APIENTRY_DEFINED +# undef GLUT_APIENTRY_DEFINED +# undef APIENTRY +#endif + +#ifdef GLUT_WINGDIAPI_DEFINED +# undef GLUT_WINGDIAPI_DEFINED +# undef WINGDIAPI +#endif + +#ifdef GLUT_DEFINED___CDECL +# undef GLUT_DEFINED___CDECL +# undef __cdecl +#endif + +#ifdef GLUT_DEFINED__CRTIMP +# undef GLUT_DEFINED__CRTIMP +# undef _CRTIMP +#endif + +#endif /* __glut_h__ */ diff -r 31570b766315 -r ed5a6478e710 misc/winutils/include/SDL.h --- a/misc/winutils/include/SDL.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/winutils/include/SDL.h Tue Nov 10 20:43:13 2015 +0100 @@ -58,17 +58,17 @@ * specify the subsystems which you will be using in your application. */ /*@{*/ -#define SDL_INIT_TIMER 0x00000001 -#define SDL_INIT_AUDIO 0x00000010 -#define SDL_INIT_VIDEO 0x00000020 -#define SDL_INIT_CDROM 0x00000100 -#define SDL_INIT_JOYSTICK 0x00000200 -#define SDL_INIT_NOPARACHUTE 0x00100000 /**< Don't catch fatal signals */ -#define SDL_INIT_EVENTTHREAD 0x01000000 /**< Not supported on all OS's */ -#define SDL_INIT_EVERYTHING 0x0000FFFF +#define SDL_INIT_TIMER 0x00000001 +#define SDL_INIT_AUDIO 0x00000010 +#define SDL_INIT_VIDEO 0x00000020 +#define SDL_INIT_CDROM 0x00000100 +#define SDL_INIT_JOYSTICK 0x00000200 +#define SDL_INIT_NOPARACHUTE 0x00100000 /**< Don't catch fatal signals */ +#define SDL_INIT_EVENTTHREAD 0x01000000 /**< Not supported on all OS's */ +#define SDL_INIT_EVERYTHING 0x0000FFFF /*@}*/ -/** This function loads the SDL dynamically linked library and initializes +/** This function loads the SDL dynamically linked library and initializes * the subsystems specified by 'flags' (and those satisfying dependencies) * Unless the SDL_INIT_NOPARACHUTE flag is set, it will install cleanup * signal handlers for some commonly ignored fatal signals (like SIGSEGV) diff -r 31570b766315 -r ed5a6478e710 misc/winutils/include/SDL_active.h --- a/misc/winutils/include/SDL_active.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/winutils/include/SDL_active.h Tue Nov 10 20:43:13 2015 +0100 @@ -22,7 +22,7 @@ /** * @file SDL_active.h - * Include file for SDL application focus event handling + * Include file for SDL application focus event handling */ #ifndef _SDL_active_h @@ -39,13 +39,13 @@ /** @name The available application states */ /*@{*/ -#define SDL_APPMOUSEFOCUS 0x01 /**< The app has mouse coverage */ -#define SDL_APPINPUTFOCUS 0x02 /**< The app has input focus */ -#define SDL_APPACTIVE 0x04 /**< The application is active */ +#define SDL_APPMOUSEFOCUS 0x01 /**< The app has mouse coverage */ +#define SDL_APPINPUTFOCUS 0x02 /**< The app has input focus */ +#define SDL_APPACTIVE 0x04 /**< The application is active */ /*@}*/ /* Function prototypes */ -/** +/** * This function returns the current state of the application, which is a * bitwise combination of SDL_APPMOUSEFOCUS, SDL_APPINPUTFOCUS, and * SDL_APPACTIVE. If SDL_APPACTIVE is set, then the user is able to diff -r 31570b766315 -r ed5a6478e710 misc/winutils/include/SDL_audio.h --- a/misc/winutils/include/SDL_audio.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/winutils/include/SDL_audio.h Tue Nov 10 20:43:13 2015 +0100 @@ -72,24 +72,24 @@ * */ typedef struct SDL_AudioSpec { - int freq; /**< DSP frequency -- samples per second */ - Uint16 format; /**< Audio data format */ - Uint8 channels; /**< Number of channels: 1 mono, 2 stereo */ - Uint8 silence; /**< Audio buffer silence value (calculated) */ - Uint16 samples; /**< Audio buffer size in samples (power of 2) */ - Uint16 padding; /**< Necessary for some compile environments */ - Uint32 size; /**< Audio buffer size in bytes (calculated) */ - /** - * This function is called when the audio device needs more data. - * - * @param[out] stream A pointer to the audio data buffer - * @param[in] len The length of the audio buffer in bytes. - * - * Once the callback returns, the buffer will no longer be valid. - * Stereo samples are stored in a LRLRLR ordering. - */ - void (SDLCALL *callback)(void *userdata, Uint8 *stream, int len); - void *userdata; + int freq; /**< DSP frequency -- samples per second */ + Uint16 format; /**< Audio data format */ + Uint8 channels; /**< Number of channels: 1 mono, 2 stereo */ + Uint8 silence; /**< Audio buffer silence value (calculated) */ + Uint16 samples; /**< Audio buffer size in samples (power of 2) */ + Uint16 padding; /**< Necessary for some compile environments */ + Uint32 size; /**< Audio buffer size in bytes (calculated) */ + /** + * This function is called when the audio device needs more data. + * + * @param[out] stream A pointer to the audio data buffer + * @param[in] len The length of the audio buffer in bytes. + * + * Once the callback returns, the buffer will no longer be valid. + * Stereo samples are stored in a LRLRLR ordering. + */ + void (SDLCALL *callback)(void *userdata, Uint8 *stream, int len); + void *userdata; } SDL_AudioSpec; /** @@ -97,25 +97,25 @@ * defaults to LSB byte order */ /*@{*/ -#define AUDIO_U8 0x0008 /**< Unsigned 8-bit samples */ -#define AUDIO_S8 0x8008 /**< Signed 8-bit samples */ -#define AUDIO_U16LSB 0x0010 /**< Unsigned 16-bit samples */ -#define AUDIO_S16LSB 0x8010 /**< Signed 16-bit samples */ -#define AUDIO_U16MSB 0x1010 /**< As above, but big-endian byte order */ -#define AUDIO_S16MSB 0x9010 /**< As above, but big-endian byte order */ -#define AUDIO_U16 AUDIO_U16LSB -#define AUDIO_S16 AUDIO_S16LSB +#define AUDIO_U8 0x0008 /**< Unsigned 8-bit samples */ +#define AUDIO_S8 0x8008 /**< Signed 8-bit samples */ +#define AUDIO_U16LSB 0x0010 /**< Unsigned 16-bit samples */ +#define AUDIO_S16LSB 0x8010 /**< Signed 16-bit samples */ +#define AUDIO_U16MSB 0x1010 /**< As above, but big-endian byte order */ +#define AUDIO_S16MSB 0x9010 /**< As above, but big-endian byte order */ +#define AUDIO_U16 AUDIO_U16LSB +#define AUDIO_S16 AUDIO_S16LSB /** * @name Native audio byte ordering */ /*@{*/ #if SDL_BYTEORDER == SDL_LIL_ENDIAN -#define AUDIO_U16SYS AUDIO_U16LSB -#define AUDIO_S16SYS AUDIO_S16LSB +#define AUDIO_U16SYS AUDIO_U16LSB +#define AUDIO_S16SYS AUDIO_S16LSB #else -#define AUDIO_U16SYS AUDIO_U16MSB -#define AUDIO_S16SYS AUDIO_S16MSB +#define AUDIO_U16SYS AUDIO_U16MSB +#define AUDIO_S16SYS AUDIO_S16MSB #endif /*@}*/ @@ -124,17 +124,17 @@ /** A structure to hold a set of audio conversion filters and buffers */ typedef struct SDL_AudioCVT { - int needed; /**< Set to 1 if conversion possible */ - Uint16 src_format; /**< Source audio format */ - Uint16 dst_format; /**< Target audio format */ - double rate_incr; /**< Rate conversion increment */ - Uint8 *buf; /**< Buffer to hold entire audio data */ - int len; /**< Length of original audio buffer */ - int len_cvt; /**< Length of converted audio buffer */ - int len_mult; /**< buffer must be len*len_mult big */ - double len_ratio; /**< Given len, final size is len*len_ratio */ - void (SDLCALL *filters[10])(struct SDL_AudioCVT *cvt, Uint16 format); - int filter_index; /**< Current audio conversion function */ + int needed; /**< Set to 1 if conversion possible */ + Uint16 src_format; /**< Source audio format */ + Uint16 dst_format; /**< Target audio format */ + double rate_incr; /**< Rate conversion increment */ + Uint8 *buf; /**< Buffer to hold entire audio data */ + int len; /**< Length of original audio buffer */ + int len_cvt; /**< Length of converted audio buffer */ + int len_mult; /**< buffer must be len*len_mult big */ + double len_ratio; /**< Given len, final size is len*len_ratio */ + void (SDLCALL *filters[10])(struct SDL_AudioCVT *cvt, Uint16 format); + int filter_index; /**< Current audio conversion function */ } SDL_AudioCVT; @@ -164,7 +164,7 @@ * structure pointed to by 'obtained'. If 'obtained' is NULL, the audio * data passed to the callback function will be guaranteed to be in the * requested format, and will be automatically converted to the hardware - * audio format if necessary. This function returns -1 if it failed + * audio format if necessary. This function returns -1 if it failed * to open the audio device, or couldn't set up the audio thread. * * The audio device starts out playing silence when it's opened, and should @@ -178,9 +178,9 @@ extern DECLSPEC int SDLCALL SDL_OpenAudio(SDL_AudioSpec *desired, SDL_AudioSpec *obtained); typedef enum { - SDL_AUDIO_STOPPED = 0, - SDL_AUDIO_PLAYING, - SDL_AUDIO_PAUSED + SDL_AUDIO_STOPPED = 0, + SDL_AUDIO_PLAYING, + SDL_AUDIO_PAUSED } SDL_audiostatus; /** Get the current audio state */ @@ -199,24 +199,24 @@ * This function loads a WAVE from the data source, automatically freeing * that source if 'freesrc' is non-zero. For example, to load a WAVE file, * you could do: - * @code SDL_LoadWAV_RW(SDL_RWFromFile("sample.wav", "rb"), 1, ...); @endcode + * @code SDL_LoadWAV_RW(SDL_RWFromFile("sample.wav", "rb"), 1, ...); @endcode * * If this function succeeds, it returns the given SDL_AudioSpec, * filled with the audio data format of the wave data, and sets * 'audio_buf' to a malloc()'d buffer containing the audio data, * and sets 'audio_len' to the length of that audio buffer, in bytes. - * You need to free the audio buffer with SDL_FreeWAV() when you are + * You need to free the audio buffer with SDL_FreeWAV() when you are * done with it. * - * This function returns NULL and sets the SDL error message if the - * wave file cannot be opened, uses an unknown data format, or is + * This function returns NULL and sets the SDL error message if the + * wave file cannot be opened, uses an unknown data format, or is * corrupt. Currently raw and MS-ADPCM WAVE files are supported. */ extern DECLSPEC SDL_AudioSpec * SDLCALL SDL_LoadWAV_RW(SDL_RWops *src, int freesrc, SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len); /** Compatibility convenience function -- loads a WAV from a file */ #define SDL_LoadWAV(file, spec, audio_buf, audio_len) \ - SDL_LoadWAV_RW(SDL_RWFromFile(file, "rb"),1, spec,audio_buf,audio_len) + SDL_LoadWAV_RW(SDL_RWFromFile(file, "rb"),1, spec,audio_buf,audio_len) /** * This function frees data previously allocated with SDL_LoadWAV_RW() @@ -232,8 +232,8 @@ * @return This function returns 0, or -1 if there was an error. */ extern DECLSPEC int SDLCALL SDL_BuildAudioCVT(SDL_AudioCVT *cvt, - Uint16 src_format, Uint8 src_channels, int src_rate, - Uint16 dst_format, Uint8 dst_channels, int dst_rate); + Uint16 src_format, Uint8 src_channels, int src_rate, + Uint16 dst_format, Uint8 dst_channels, int dst_rate); /** * Once you have initialized the 'cvt' structure using SDL_BuildAudioCVT(), diff -r 31570b766315 -r ed5a6478e710 misc/winutils/include/SDL_cdrom.h --- a/misc/winutils/include/SDL_cdrom.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/winutils/include/SDL_cdrom.h Tue Nov 10 20:43:13 2015 +0100 @@ -45,47 +45,47 @@ */ /** The maximum number of CD-ROM tracks on a disk */ -#define SDL_MAX_TRACKS 99 +#define SDL_MAX_TRACKS 99 /** @name Track Types * The types of CD-ROM track possible */ /*@{*/ -#define SDL_AUDIO_TRACK 0x00 -#define SDL_DATA_TRACK 0x04 +#define SDL_AUDIO_TRACK 0x00 +#define SDL_DATA_TRACK 0x04 /*@}*/ /** The possible states which a CD-ROM drive can be in. */ typedef enum { - CD_TRAYEMPTY, - CD_STOPPED, - CD_PLAYING, - CD_PAUSED, - CD_ERROR = -1 + CD_TRAYEMPTY, + CD_STOPPED, + CD_PLAYING, + CD_PAUSED, + CD_ERROR = -1 } CDstatus; /** Given a status, returns true if there's a disk in the drive */ -#define CD_INDRIVE(status) ((int)(status) > 0) +#define CD_INDRIVE(status) ((int)(status) > 0) typedef struct SDL_CDtrack { - Uint8 id; /**< Track number */ - Uint8 type; /**< Data or audio track */ - Uint16 unused; - Uint32 length; /**< Length, in frames, of this track */ - Uint32 offset; /**< Offset, in frames, from start of disk */ + Uint8 id; /**< Track number */ + Uint8 type; /**< Data or audio track */ + Uint16 unused; + Uint32 length; /**< Length, in frames, of this track */ + Uint32 offset; /**< Offset, in frames, from start of disk */ } SDL_CDtrack; /** This structure is only current as of the last call to SDL_CDStatus() */ typedef struct SDL_CD { - int id; /**< Private drive identifier */ - CDstatus status; /**< Current drive status */ + int id; /**< Private drive identifier */ + CDstatus status; /**< Current drive status */ - /** The rest of this structure is only valid if there's a CD in drive */ + /** The rest of this structure is only valid if there's a CD in drive */ /*@{*/ - int numtracks; /**< Number of tracks on disk */ - int cur_track; /**< Current track position */ - int cur_frame; /**< Current frame offset within current track */ - SDL_CDtrack track[SDL_MAX_TRACKS+1]; + int numtracks; /**< Number of tracks on disk */ + int cur_track; /**< Current track position */ + int cur_frame; /**< Current frame offset within current track */ + SDL_CDtrack track[SDL_MAX_TRACKS+1]; /*@}*/ } SDL_CD; @@ -93,16 +93,16 @@ * Conversion functions from frames to Minute/Second/Frames and vice versa */ /*@{*/ -#define CD_FPS 75 -#define FRAMES_TO_MSF(f, M,S,F) { \ - int value = f; \ - *(F) = value%CD_FPS; \ - value /= CD_FPS; \ - *(S) = value%60; \ - value /= 60; \ - *(M) = value; \ +#define CD_FPS 75 +#define FRAMES_TO_MSF(f, M,S,F) { \ + int value = f; \ + *(F) = value%CD_FPS; \ + value /= CD_FPS; \ + *(S) = value%60; \ + value /= 60; \ + *(M) = value; \ } -#define MSF_TO_FRAMES(M, S, F) ((M)*60*CD_FPS+(S)*CD_FPS+(F)) +#define MSF_TO_FRAMES(M, S, F) ((M)*60*CD_FPS+(S)*CD_FPS+(F)) /*@}*/ /* CD-audio API functions: */ @@ -140,28 +140,28 @@ /** * Play the given CD starting at 'start_track' and 'start_frame' for 'ntracks' - * tracks and 'nframes' frames. If both 'ntrack' and 'nframe' are 0, play + * tracks and 'nframes' frames. If both 'ntrack' and 'nframe' are 0, play * until the end of the CD. This function will skip data tracks. - * This function should only be called after calling SDL_CDStatus() to + * This function should only be called after calling SDL_CDStatus() to * get track information about the CD. * For example: * @code - * // Play entire CD: - * if ( CD_INDRIVE(SDL_CDStatus(cdrom)) ) - * SDL_CDPlayTracks(cdrom, 0, 0, 0, 0); - * // Play last track: - * if ( CD_INDRIVE(SDL_CDStatus(cdrom)) ) { - * SDL_CDPlayTracks(cdrom, cdrom->numtracks-1, 0, 0, 0); - * } - * // Play first and second track and 10 seconds of third track: - * if ( CD_INDRIVE(SDL_CDStatus(cdrom)) ) - * SDL_CDPlayTracks(cdrom, 0, 0, 2, 10); + * // Play entire CD: + * if ( CD_INDRIVE(SDL_CDStatus(cdrom)) ) + * SDL_CDPlayTracks(cdrom, 0, 0, 0, 0); + * // Play last track: + * if ( CD_INDRIVE(SDL_CDStatus(cdrom)) ) { + * SDL_CDPlayTracks(cdrom, cdrom->numtracks-1, 0, 0, 0); + * } + * // Play first and second track and 10 seconds of third track: + * if ( CD_INDRIVE(SDL_CDStatus(cdrom)) ) + * SDL_CDPlayTracks(cdrom, 0, 0, 2, 10); * @endcode * * @return This function returns 0, or -1 if there was an error. */ extern DECLSPEC int SDLCALL SDL_CDPlayTracks(SDL_CD *cdrom, - int start_track, int start_frame, int ntracks, int nframes); + int start_track, int start_frame, int ntracks, int nframes); /** * Play the given CD starting at 'start' frame for 'length' frames. diff -r 31570b766315 -r ed5a6478e710 misc/winutils/include/SDL_config_win32.h --- a/misc/winutils/include/SDL_config_win32.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/winutils/include/SDL_config_win32.h Tue Nov 10 20:43:13 2015 +0100 @@ -28,16 +28,16 @@ /* This is a set of defines to configure the SDL features */ #if defined(__GNUC__) || defined(__DMC__) -#define HAVE_STDINT_H 1 +#define HAVE_STDINT_H 1 #elif defined(_MSC_VER) -typedef signed __int8 int8_t; -typedef unsigned __int8 uint8_t; -typedef signed __int16 int16_t; -typedef unsigned __int16 uint16_t; -typedef signed __int32 int32_t; -typedef unsigned __int32 uint32_t; -typedef signed __int64 int64_t; -typedef unsigned __int64 uint64_t; +typedef signed __int8 int8_t; +typedef unsigned __int8 uint8_t; +typedef signed __int16 int16_t; +typedef unsigned __int16 uint16_t; +typedef signed __int32 int32_t; +typedef unsigned __int32 uint32_t; +typedef signed __int64 int64_t; +typedef unsigned __int64 uint64_t; #ifndef _UINTPTR_T_DEFINED #ifdef _WIN64 typedef unsigned __int64 uintptr_t; @@ -53,7 +53,7 @@ #if ((_MSC_VER <= 1200) && (!defined(LONG_PTR))) #define LONG_PTR LONG #endif -#else /* !__GNUC__ && !_MSC_VER */ +#else /* !__GNUC__ && !_MSC_VER */ typedef signed char int8_t; typedef unsigned char uint8_t; typedef signed short int16_t; @@ -68,10 +68,10 @@ #endif typedef unsigned int uintptr_t; #endif /* __GNUC__ || _MSC_VER */ -#define SDL_HAS_64BIT_TYPE 1 +#define SDL_HAS_64BIT_TYPE 1 /* Enabled for SDL 1.2 (binary compatibility) */ -#define HAVE_LIBC 1 +#define HAVE_LIBC 1 #ifdef HAVE_LIBC /* Useful headers */ #define HAVE_STDIO_H 1 @@ -117,67 +117,67 @@ #define HAVE__STRNICMP 1 #define HAVE_SSCANF 1 #else -#define HAVE_STDARG_H 1 -#define HAVE_STDDEF_H 1 +#define HAVE_STDARG_H 1 +#define HAVE_STDDEF_H 1 #endif /* Enable various audio drivers */ #ifndef _WIN32_WCE -#define SDL_AUDIO_DRIVER_DSOUND 1 +#define SDL_AUDIO_DRIVER_DSOUND 1 #endif -#define SDL_AUDIO_DRIVER_WAVEOUT 1 -#define SDL_AUDIO_DRIVER_DISK 1 -#define SDL_AUDIO_DRIVER_DUMMY 1 +#define SDL_AUDIO_DRIVER_WAVEOUT 1 +#define SDL_AUDIO_DRIVER_DISK 1 +#define SDL_AUDIO_DRIVER_DUMMY 1 /* Enable various cdrom drivers */ #ifdef _WIN32_WCE #define SDL_CDROM_DISABLED 1 #else -#define SDL_CDROM_WIN32 1 +#define SDL_CDROM_WIN32 1 #endif /* Enable various input drivers */ #ifdef _WIN32_WCE #define SDL_JOYSTICK_DISABLED 1 #else -#define SDL_JOYSTICK_WINMM 1 +#define SDL_JOYSTICK_WINMM 1 #endif /* Enable various shared object loading systems */ -#define SDL_LOADSO_WIN32 1 +#define SDL_LOADSO_WIN32 1 /* Enable various threading systems */ -#define SDL_THREAD_WIN32 1 +#define SDL_THREAD_WIN32 1 /* Enable various timer systems */ #ifdef _WIN32_WCE -#define SDL_TIMER_WINCE 1 +#define SDL_TIMER_WINCE 1 #else -#define SDL_TIMER_WIN32 1 +#define SDL_TIMER_WIN32 1 #endif /* Enable various video drivers */ #ifdef _WIN32_WCE -#define SDL_VIDEO_DRIVER_GAPI 1 +#define SDL_VIDEO_DRIVER_GAPI 1 #endif #ifndef _WIN32_WCE -#define SDL_VIDEO_DRIVER_DDRAW 1 +#define SDL_VIDEO_DRIVER_DDRAW 1 #endif -#define SDL_VIDEO_DRIVER_DUMMY 1 -#define SDL_VIDEO_DRIVER_WINDIB 1 +#define SDL_VIDEO_DRIVER_DUMMY 1 +#define SDL_VIDEO_DRIVER_WINDIB 1 /* Enable OpenGL support */ #ifndef _WIN32_WCE -#define SDL_VIDEO_OPENGL 1 -#define SDL_VIDEO_OPENGL_WGL 1 +#define SDL_VIDEO_OPENGL 1 +#define SDL_VIDEO_OPENGL_WGL 1 #endif /* Disable screensaver */ -#define SDL_VIDEO_DISABLE_SCREENSAVER 1 +#define SDL_VIDEO_DISABLE_SCREENSAVER 1 /* Enable assembly routines (Win64 doesn't have inline asm) */ #ifndef _WIN64 -#define SDL_ASSEMBLY_ROUTINES 1 +#define SDL_ASSEMBLY_ROUTINES 1 #endif #endif /* _SDL_config_win32_h */ diff -r 31570b766315 -r ed5a6478e710 misc/winutils/include/SDL_endian.h --- a/misc/winutils/include/SDL_endian.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/winutils/include/SDL_endian.h Tue Nov 10 20:43:13 2015 +0100 @@ -31,14 +31,14 @@ #include "SDL_stdinc.h" /** @name SDL_ENDIANs - * The two types of endianness + * The two types of endianness */ /*@{*/ -#define SDL_LIL_ENDIAN 1234 -#define SDL_BIG_ENDIAN 4321 +#define SDL_LIL_ENDIAN 1234 +#define SDL_BIG_ENDIAN 4321 /*@}*/ -#ifndef SDL_BYTEORDER /* Not defined in SDL_config.h? */ +#ifndef SDL_BYTEORDER /* Not defined in SDL_config.h? */ #ifdef __linux__ #include #define SDL_BYTEORDER __BYTE_ORDER @@ -48,9 +48,9 @@ (defined(__MIPS__) && defined(__MISPEB__)) || \ defined(__ppc__) || defined(__POWERPC__) || defined(_M_PPC) || \ defined(__sparc__) -#define SDL_BYTEORDER SDL_BIG_ENDIAN +#define SDL_BYTEORDER SDL_BIG_ENDIAN #else -#define SDL_BYTEORDER SDL_LIL_ENDIAN +#define SDL_BYTEORDER SDL_LIL_ENDIAN #endif #endif /* __linux __ */ #endif /* !SDL_BYTEORDER */ @@ -74,32 +74,32 @@ !(__GNUC__ == 2 && __GNUC_MINOR__ <= 95 /* broken gcc version */) static __inline__ Uint16 SDL_Swap16(Uint16 x) { - __asm__("xchgb %b0,%h0" : "=q" (x) : "0" (x)); - return x; + __asm__("xchgb %b0,%h0" : "=q" (x) : "0" (x)); + return x; } #elif defined(__GNUC__) && defined(__x86_64__) static __inline__ Uint16 SDL_Swap16(Uint16 x) { - __asm__("xchgb %b0,%h0" : "=Q" (x) : "0" (x)); - return x; + __asm__("xchgb %b0,%h0" : "=Q" (x) : "0" (x)); + return x; } #elif defined(__GNUC__) && (defined(__powerpc__) || defined(__ppc__)) static __inline__ Uint16 SDL_Swap16(Uint16 x) { - Uint16 result; + Uint16 result; - __asm__("rlwimi %0,%2,8,16,23" : "=&r" (result) : "0" (x >> 8), "r" (x)); - return result; + __asm__("rlwimi %0,%2,8,16,23" : "=&r" (result) : "0" (x >> 8), "r" (x)); + return result; } #elif defined(__GNUC__) && (defined(__m68k__) && !defined(__mcoldfire__)) static __inline__ Uint16 SDL_Swap16(Uint16 x) { - __asm__("rorw #8,%0" : "=d" (x) : "0" (x) : "cc"); - return x; + __asm__("rorw #8,%0" : "=d" (x) : "0" (x) : "cc"); + return x; } #else static __inline__ Uint16 SDL_Swap16(Uint16 x) { - return SDL_static_cast(Uint16, ((x<<8)|(x>>8))); + return SDL_static_cast(Uint16, ((x<<8)|(x>>8))); } #endif @@ -107,34 +107,34 @@ !(__GNUC__ == 2 && __GNUC_MINOR__ <= 95 /* broken gcc version */) static __inline__ Uint32 SDL_Swap32(Uint32 x) { - __asm__("bswap %0" : "=r" (x) : "0" (x)); - return x; + __asm__("bswap %0" : "=r" (x) : "0" (x)); + return x; } #elif defined(__GNUC__) && defined(__x86_64__) static __inline__ Uint32 SDL_Swap32(Uint32 x) { - __asm__("bswapl %0" : "=r" (x) : "0" (x)); - return x; + __asm__("bswapl %0" : "=r" (x) : "0" (x)); + return x; } #elif defined(__GNUC__) && (defined(__powerpc__) || defined(__ppc__)) static __inline__ Uint32 SDL_Swap32(Uint32 x) { - Uint32 result; + Uint32 result; - __asm__("rlwimi %0,%2,24,16,23" : "=&r" (result) : "0" (x>>24), "r" (x)); - __asm__("rlwimi %0,%2,8,8,15" : "=&r" (result) : "0" (result), "r" (x)); - __asm__("rlwimi %0,%2,24,0,7" : "=&r" (result) : "0" (result), "r" (x)); - return result; + __asm__("rlwimi %0,%2,24,16,23" : "=&r" (result) : "0" (x>>24), "r" (x)); + __asm__("rlwimi %0,%2,8,8,15" : "=&r" (result) : "0" (result), "r" (x)); + __asm__("rlwimi %0,%2,24,0,7" : "=&r" (result) : "0" (result), "r" (x)); + return result; } #elif defined(__GNUC__) && (defined(__m68k__) && !defined(__mcoldfire__)) static __inline__ Uint32 SDL_Swap32(Uint32 x) { - __asm__("rorw #8,%0\n\tswap %0\n\trorw #8,%0" : "=d" (x) : "0" (x) : "cc"); - return x; + __asm__("rorw #8,%0\n\tswap %0\n\trorw #8,%0" : "=d" (x) : "0" (x) : "cc"); + return x; } #else static __inline__ Uint32 SDL_Swap32(Uint32 x) { - return SDL_static_cast(Uint32, ((x<<24)|((x<<8)&0x00FF0000)|((x>>8)&0x0000FF00)|(x>>24))); + return SDL_static_cast(Uint32, ((x<<24)|((x<<8)&0x00FF0000)|((x>>8)&0x0000FF00)|(x>>24))); } #endif @@ -143,35 +143,35 @@ !(__GNUC__ == 2 && __GNUC_MINOR__ <= 95 /* broken gcc version */) static __inline__ Uint64 SDL_Swap64(Uint64 x) { - union { - struct { Uint32 a,b; } s; - Uint64 u; - } v; - v.u = x; - __asm__("bswapl %0 ; bswapl %1 ; xchgl %0,%1" - : "=r" (v.s.a), "=r" (v.s.b) - : "0" (v.s.a), "1" (v.s.b)); - return v.u; + union { + struct { Uint32 a,b; } s; + Uint64 u; + } v; + v.u = x; + __asm__("bswapl %0 ; bswapl %1 ; xchgl %0,%1" + : "=r" (v.s.a), "=r" (v.s.b) + : "0" (v.s.a), "1" (v.s.b)); + return v.u; } #elif defined(__GNUC__) && defined(__x86_64__) static __inline__ Uint64 SDL_Swap64(Uint64 x) { - __asm__("bswapq %0" : "=r" (x) : "0" (x)); - return x; + __asm__("bswapq %0" : "=r" (x) : "0" (x)); + return x; } #else static __inline__ Uint64 SDL_Swap64(Uint64 x) { - Uint32 hi, lo; + Uint32 hi, lo; - /* Separate into high and low 32-bit values and swap them */ - lo = SDL_static_cast(Uint32, x & 0xFFFFFFFF); - x >>= 32; - hi = SDL_static_cast(Uint32, x & 0xFFFFFFFF); - x = SDL_Swap32(lo); - x <<= 32; - x |= SDL_Swap32(hi); - return (x); + /* Separate into high and low 32-bit values and swap them */ + lo = SDL_static_cast(Uint32, x & 0xFFFFFFFF); + x >>= 32; + hi = SDL_static_cast(Uint32, x & 0xFFFFFFFF); + x = SDL_Swap32(lo); + x <<= 32; + x |= SDL_Swap32(hi); + return (x); } #endif #else @@ -179,7 +179,7 @@ * If there is no real 64-bit datatype, then compilers will complain about * the fake 64-bit datatype that SDL provides when it compiles user code. */ -#define SDL_Swap64(X) (X) +#define SDL_Swap64(X) (X) #endif /* SDL_HAS_64BIT_TYPE */ /*@}*/ @@ -189,19 +189,19 @@ */ /*@{*/ #if SDL_BYTEORDER == SDL_LIL_ENDIAN -#define SDL_SwapLE16(X) (X) -#define SDL_SwapLE32(X) (X) -#define SDL_SwapLE64(X) (X) -#define SDL_SwapBE16(X) SDL_Swap16(X) -#define SDL_SwapBE32(X) SDL_Swap32(X) -#define SDL_SwapBE64(X) SDL_Swap64(X) +#define SDL_SwapLE16(X) (X) +#define SDL_SwapLE32(X) (X) +#define SDL_SwapLE64(X) (X) +#define SDL_SwapBE16(X) SDL_Swap16(X) +#define SDL_SwapBE32(X) SDL_Swap32(X) +#define SDL_SwapBE64(X) SDL_Swap64(X) #else -#define SDL_SwapLE16(X) SDL_Swap16(X) -#define SDL_SwapLE32(X) SDL_Swap32(X) -#define SDL_SwapLE64(X) SDL_Swap64(X) -#define SDL_SwapBE16(X) (X) -#define SDL_SwapBE32(X) (X) -#define SDL_SwapBE64(X) (X) +#define SDL_SwapLE16(X) SDL_Swap16(X) +#define SDL_SwapLE32(X) SDL_Swap32(X) +#define SDL_SwapLE64(X) SDL_Swap64(X) +#define SDL_SwapBE16(X) (X) +#define SDL_SwapBE32(X) (X) +#define SDL_SwapBE64(X) (X) #endif /*@}*/ diff -r 31570b766315 -r ed5a6478e710 misc/winutils/include/SDL_error.h --- a/misc/winutils/include/SDL_error.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/winutils/include/SDL_error.h Tue Nov 10 20:43:13 2015 +0100 @@ -36,7 +36,7 @@ extern "C" { #endif -/** +/** * @name Public functions */ /*@{*/ @@ -50,15 +50,15 @@ * @internal Private error message function - used internally */ /*@{*/ -#define SDL_OutOfMemory() SDL_Error(SDL_ENOMEM) -#define SDL_Unsupported() SDL_Error(SDL_UNSUPPORTED) +#define SDL_OutOfMemory() SDL_Error(SDL_ENOMEM) +#define SDL_Unsupported() SDL_Error(SDL_UNSUPPORTED) typedef enum { - SDL_ENOMEM, - SDL_EFREAD, - SDL_EFWRITE, - SDL_EFSEEK, - SDL_UNSUPPORTED, - SDL_LASTERROR + SDL_ENOMEM, + SDL_EFREAD, + SDL_EFWRITE, + SDL_EFSEEK, + SDL_UNSUPPORTED, + SDL_LASTERROR } SDL_errorcode; extern DECLSPEC void SDLCALL SDL_Error(SDL_errorcode code); /*@}*/ diff -r 31570b766315 -r ed5a6478e710 misc/winutils/include/SDL_events.h --- a/misc/winutils/include/SDL_events.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/winutils/include/SDL_events.h Tue Nov 10 20:43:13 2015 +0100 @@ -44,147 +44,147 @@ /** @name General keyboard/mouse state definitions */ /*@{*/ -#define SDL_RELEASED 0 -#define SDL_PRESSED 1 +#define SDL_RELEASED 0 +#define SDL_PRESSED 1 /*@}*/ /** Event enumerations */ typedef enum { - SDL_NOEVENT = 0, /**< Unused (do not remove) */ - SDL_ACTIVEEVENT, /**< Application loses/gains visibility */ - SDL_KEYDOWN, /**< Keys pressed */ - SDL_KEYUP, /**< Keys released */ - SDL_MOUSEMOTION, /**< Mouse moved */ - SDL_MOUSEBUTTONDOWN, /**< Mouse button pressed */ - SDL_MOUSEBUTTONUP, /**< Mouse button released */ - SDL_JOYAXISMOTION, /**< Joystick axis motion */ - SDL_JOYBALLMOTION, /**< Joystick trackball motion */ - SDL_JOYHATMOTION, /**< Joystick hat position change */ - SDL_JOYBUTTONDOWN, /**< Joystick button pressed */ - SDL_JOYBUTTONUP, /**< Joystick button released */ - SDL_QUIT, /**< User-requested quit */ - SDL_SYSWMEVENT, /**< System specific event */ - SDL_EVENT_RESERVEDA, /**< Reserved for future use.. */ - SDL_EVENT_RESERVEDB, /**< Reserved for future use.. */ - SDL_VIDEORESIZE, /**< User resized video mode */ - SDL_VIDEOEXPOSE, /**< Screen needs to be redrawn */ - SDL_EVENT_RESERVED2, /**< Reserved for future use.. */ - SDL_EVENT_RESERVED3, /**< Reserved for future use.. */ - SDL_EVENT_RESERVED4, /**< Reserved for future use.. */ - SDL_EVENT_RESERVED5, /**< Reserved for future use.. */ - SDL_EVENT_RESERVED6, /**< Reserved for future use.. */ - SDL_EVENT_RESERVED7, /**< Reserved for future use.. */ + SDL_NOEVENT = 0, /**< Unused (do not remove) */ + SDL_ACTIVEEVENT, /**< Application loses/gains visibility */ + SDL_KEYDOWN, /**< Keys pressed */ + SDL_KEYUP, /**< Keys released */ + SDL_MOUSEMOTION, /**< Mouse moved */ + SDL_MOUSEBUTTONDOWN, /**< Mouse button pressed */ + SDL_MOUSEBUTTONUP, /**< Mouse button released */ + SDL_JOYAXISMOTION, /**< Joystick axis motion */ + SDL_JOYBALLMOTION, /**< Joystick trackball motion */ + SDL_JOYHATMOTION, /**< Joystick hat position change */ + SDL_JOYBUTTONDOWN, /**< Joystick button pressed */ + SDL_JOYBUTTONUP, /**< Joystick button released */ + SDL_QUIT, /**< User-requested quit */ + SDL_SYSWMEVENT, /**< System specific event */ + SDL_EVENT_RESERVEDA, /**< Reserved for future use.. */ + SDL_EVENT_RESERVEDB, /**< Reserved for future use.. */ + SDL_VIDEORESIZE, /**< User resized video mode */ + SDL_VIDEOEXPOSE, /**< Screen needs to be redrawn */ + SDL_EVENT_RESERVED2, /**< Reserved for future use.. */ + SDL_EVENT_RESERVED3, /**< Reserved for future use.. */ + SDL_EVENT_RESERVED4, /**< Reserved for future use.. */ + SDL_EVENT_RESERVED5, /**< Reserved for future use.. */ + SDL_EVENT_RESERVED6, /**< Reserved for future use.. */ + SDL_EVENT_RESERVED7, /**< Reserved for future use.. */ /** Events SDL_USEREVENT through SDL_MAXEVENTS-1 are for your use */ SDL_USEREVENT = 24, /** This last event is only for bounding internal arrays - * It is the number of bits in the event mask datatype -- Uint32 + * It is the number of bits in the event mask datatype -- Uint32 */ SDL_NUMEVENTS = 32 } SDL_EventType; /** @name Predefined event masks */ /*@{*/ -#define SDL_EVENTMASK(X) (1<<(X)) +#define SDL_EVENTMASK(X) (1<<(X)) typedef enum { - SDL_ACTIVEEVENTMASK = SDL_EVENTMASK(SDL_ACTIVEEVENT), - SDL_KEYDOWNMASK = SDL_EVENTMASK(SDL_KEYDOWN), - SDL_KEYUPMASK = SDL_EVENTMASK(SDL_KEYUP), - SDL_KEYEVENTMASK = SDL_EVENTMASK(SDL_KEYDOWN)| - SDL_EVENTMASK(SDL_KEYUP), - SDL_MOUSEMOTIONMASK = SDL_EVENTMASK(SDL_MOUSEMOTION), - SDL_MOUSEBUTTONDOWNMASK = SDL_EVENTMASK(SDL_MOUSEBUTTONDOWN), - SDL_MOUSEBUTTONUPMASK = SDL_EVENTMASK(SDL_MOUSEBUTTONUP), - SDL_MOUSEEVENTMASK = SDL_EVENTMASK(SDL_MOUSEMOTION)| - SDL_EVENTMASK(SDL_MOUSEBUTTONDOWN)| - SDL_EVENTMASK(SDL_MOUSEBUTTONUP), - SDL_JOYAXISMOTIONMASK = SDL_EVENTMASK(SDL_JOYAXISMOTION), - SDL_JOYBALLMOTIONMASK = SDL_EVENTMASK(SDL_JOYBALLMOTION), - SDL_JOYHATMOTIONMASK = SDL_EVENTMASK(SDL_JOYHATMOTION), - SDL_JOYBUTTONDOWNMASK = SDL_EVENTMASK(SDL_JOYBUTTONDOWN), - SDL_JOYBUTTONUPMASK = SDL_EVENTMASK(SDL_JOYBUTTONUP), - SDL_JOYEVENTMASK = SDL_EVENTMASK(SDL_JOYAXISMOTION)| - SDL_EVENTMASK(SDL_JOYBALLMOTION)| - SDL_EVENTMASK(SDL_JOYHATMOTION)| - SDL_EVENTMASK(SDL_JOYBUTTONDOWN)| - SDL_EVENTMASK(SDL_JOYBUTTONUP), - SDL_VIDEORESIZEMASK = SDL_EVENTMASK(SDL_VIDEORESIZE), - SDL_VIDEOEXPOSEMASK = SDL_EVENTMASK(SDL_VIDEOEXPOSE), - SDL_QUITMASK = SDL_EVENTMASK(SDL_QUIT), - SDL_SYSWMEVENTMASK = SDL_EVENTMASK(SDL_SYSWMEVENT) + SDL_ACTIVEEVENTMASK = SDL_EVENTMASK(SDL_ACTIVEEVENT), + SDL_KEYDOWNMASK = SDL_EVENTMASK(SDL_KEYDOWN), + SDL_KEYUPMASK = SDL_EVENTMASK(SDL_KEYUP), + SDL_KEYEVENTMASK = SDL_EVENTMASK(SDL_KEYDOWN)| + SDL_EVENTMASK(SDL_KEYUP), + SDL_MOUSEMOTIONMASK = SDL_EVENTMASK(SDL_MOUSEMOTION), + SDL_MOUSEBUTTONDOWNMASK = SDL_EVENTMASK(SDL_MOUSEBUTTONDOWN), + SDL_MOUSEBUTTONUPMASK = SDL_EVENTMASK(SDL_MOUSEBUTTONUP), + SDL_MOUSEEVENTMASK = SDL_EVENTMASK(SDL_MOUSEMOTION)| + SDL_EVENTMASK(SDL_MOUSEBUTTONDOWN)| + SDL_EVENTMASK(SDL_MOUSEBUTTONUP), + SDL_JOYAXISMOTIONMASK = SDL_EVENTMASK(SDL_JOYAXISMOTION), + SDL_JOYBALLMOTIONMASK = SDL_EVENTMASK(SDL_JOYBALLMOTION), + SDL_JOYHATMOTIONMASK = SDL_EVENTMASK(SDL_JOYHATMOTION), + SDL_JOYBUTTONDOWNMASK = SDL_EVENTMASK(SDL_JOYBUTTONDOWN), + SDL_JOYBUTTONUPMASK = SDL_EVENTMASK(SDL_JOYBUTTONUP), + SDL_JOYEVENTMASK = SDL_EVENTMASK(SDL_JOYAXISMOTION)| + SDL_EVENTMASK(SDL_JOYBALLMOTION)| + SDL_EVENTMASK(SDL_JOYHATMOTION)| + SDL_EVENTMASK(SDL_JOYBUTTONDOWN)| + SDL_EVENTMASK(SDL_JOYBUTTONUP), + SDL_VIDEORESIZEMASK = SDL_EVENTMASK(SDL_VIDEORESIZE), + SDL_VIDEOEXPOSEMASK = SDL_EVENTMASK(SDL_VIDEOEXPOSE), + SDL_QUITMASK = SDL_EVENTMASK(SDL_QUIT), + SDL_SYSWMEVENTMASK = SDL_EVENTMASK(SDL_SYSWMEVENT) } SDL_EventMask ; -#define SDL_ALLEVENTS 0xFFFFFFFF +#define SDL_ALLEVENTS 0xFFFFFFFF /*@}*/ /** Application visibility event structure */ typedef struct SDL_ActiveEvent { - Uint8 type; /**< SDL_ACTIVEEVENT */ - Uint8 gain; /**< Whether given states were gained or lost (1/0) */ - Uint8 state; /**< A mask of the focus states */ + Uint8 type; /**< SDL_ACTIVEEVENT */ + Uint8 gain; /**< Whether given states were gained or lost (1/0) */ + Uint8 state; /**< A mask of the focus states */ } SDL_ActiveEvent; /** Keyboard event structure */ typedef struct SDL_KeyboardEvent { - Uint8 type; /**< SDL_KEYDOWN or SDL_KEYUP */ - Uint8 which; /**< The keyboard device index */ - Uint8 state; /**< SDL_PRESSED or SDL_RELEASED */ - SDL_keysym keysym; + Uint8 type; /**< SDL_KEYDOWN or SDL_KEYUP */ + Uint8 which; /**< The keyboard device index */ + Uint8 state; /**< SDL_PRESSED or SDL_RELEASED */ + SDL_keysym keysym; } SDL_KeyboardEvent; /** Mouse motion event structure */ typedef struct SDL_MouseMotionEvent { - Uint8 type; /**< SDL_MOUSEMOTION */ - Uint8 which; /**< The mouse device index */ - Uint8 state; /**< The current button state */ - Uint16 x, y; /**< The X/Y coordinates of the mouse */ - Sint16 xrel; /**< The relative motion in the X direction */ - Sint16 yrel; /**< The relative motion in the Y direction */ + Uint8 type; /**< SDL_MOUSEMOTION */ + Uint8 which; /**< The mouse device index */ + Uint8 state; /**< The current button state */ + Uint16 x, y; /**< The X/Y coordinates of the mouse */ + Sint16 xrel; /**< The relative motion in the X direction */ + Sint16 yrel; /**< The relative motion in the Y direction */ } SDL_MouseMotionEvent; /** Mouse button event structure */ typedef struct SDL_MouseButtonEvent { - Uint8 type; /**< SDL_MOUSEBUTTONDOWN or SDL_MOUSEBUTTONUP */ - Uint8 which; /**< The mouse device index */ - Uint8 button; /**< The mouse button index */ - Uint8 state; /**< SDL_PRESSED or SDL_RELEASED */ - Uint16 x, y; /**< The X/Y coordinates of the mouse at press time */ + Uint8 type; /**< SDL_MOUSEBUTTONDOWN or SDL_MOUSEBUTTONUP */ + Uint8 which; /**< The mouse device index */ + Uint8 button; /**< The mouse button index */ + Uint8 state; /**< SDL_PRESSED or SDL_RELEASED */ + Uint16 x, y; /**< The X/Y coordinates of the mouse at press time */ } SDL_MouseButtonEvent; /** Joystick axis motion event structure */ typedef struct SDL_JoyAxisEvent { - Uint8 type; /**< SDL_JOYAXISMOTION */ - Uint8 which; /**< The joystick device index */ - Uint8 axis; /**< The joystick axis index */ - Sint16 value; /**< The axis value (range: -32768 to 32767) */ + Uint8 type; /**< SDL_JOYAXISMOTION */ + Uint8 which; /**< The joystick device index */ + Uint8 axis; /**< The joystick axis index */ + Sint16 value; /**< The axis value (range: -32768 to 32767) */ } SDL_JoyAxisEvent; /** Joystick trackball motion event structure */ typedef struct SDL_JoyBallEvent { - Uint8 type; /**< SDL_JOYBALLMOTION */ - Uint8 which; /**< The joystick device index */ - Uint8 ball; /**< The joystick trackball index */ - Sint16 xrel; /**< The relative motion in the X direction */ - Sint16 yrel; /**< The relative motion in the Y direction */ + Uint8 type; /**< SDL_JOYBALLMOTION */ + Uint8 which; /**< The joystick device index */ + Uint8 ball; /**< The joystick trackball index */ + Sint16 xrel; /**< The relative motion in the X direction */ + Sint16 yrel; /**< The relative motion in the Y direction */ } SDL_JoyBallEvent; /** Joystick hat position change event structure */ typedef struct SDL_JoyHatEvent { - Uint8 type; /**< SDL_JOYHATMOTION */ - Uint8 which; /**< The joystick device index */ - Uint8 hat; /**< The joystick hat index */ - Uint8 value; /**< The hat position value: - * SDL_HAT_LEFTUP SDL_HAT_UP SDL_HAT_RIGHTUP - * SDL_HAT_LEFT SDL_HAT_CENTERED SDL_HAT_RIGHT - * SDL_HAT_LEFTDOWN SDL_HAT_DOWN SDL_HAT_RIGHTDOWN - * Note that zero means the POV is centered. - */ + Uint8 type; /**< SDL_JOYHATMOTION */ + Uint8 which; /**< The joystick device index */ + Uint8 hat; /**< The joystick hat index */ + Uint8 value; /**< The hat position value: + * SDL_HAT_LEFTUP SDL_HAT_UP SDL_HAT_RIGHTUP + * SDL_HAT_LEFT SDL_HAT_CENTERED SDL_HAT_RIGHT + * SDL_HAT_LEFTDOWN SDL_HAT_DOWN SDL_HAT_RIGHTDOWN + * Note that zero means the POV is centered. + */ } SDL_JoyHatEvent; /** Joystick button event structure */ typedef struct SDL_JoyButtonEvent { - Uint8 type; /**< SDL_JOYBUTTONDOWN or SDL_JOYBUTTONUP */ - Uint8 which; /**< The joystick device index */ - Uint8 button; /**< The joystick button index */ - Uint8 state; /**< SDL_PRESSED or SDL_RELEASED */ + Uint8 type; /**< SDL_JOYBUTTONDOWN or SDL_JOYBUTTONUP */ + Uint8 which; /**< The joystick device index */ + Uint8 button; /**< The joystick button index */ + Uint8 state; /**< SDL_PRESSED or SDL_RELEASED */ } SDL_JoyButtonEvent; /** The "window resized" event @@ -192,53 +192,53 @@ * mode with the new width and height. */ typedef struct SDL_ResizeEvent { - Uint8 type; /**< SDL_VIDEORESIZE */ - int w; /**< New width */ - int h; /**< New height */ + Uint8 type; /**< SDL_VIDEORESIZE */ + int w; /**< New width */ + int h; /**< New height */ } SDL_ResizeEvent; /** The "screen redraw" event */ typedef struct SDL_ExposeEvent { - Uint8 type; /**< SDL_VIDEOEXPOSE */ + Uint8 type; /**< SDL_VIDEOEXPOSE */ } SDL_ExposeEvent; /** The "quit requested" event */ typedef struct SDL_QuitEvent { - Uint8 type; /**< SDL_QUIT */ + Uint8 type; /**< SDL_QUIT */ } SDL_QuitEvent; /** A user-defined event type */ typedef struct SDL_UserEvent { - Uint8 type; /**< SDL_USEREVENT through SDL_NUMEVENTS-1 */ - int code; /**< User defined event code */ - void *data1; /**< User defined data pointer */ - void *data2; /**< User defined data pointer */ + Uint8 type; /**< SDL_USEREVENT through SDL_NUMEVENTS-1 */ + int code; /**< User defined event code */ + void *data1; /**< User defined data pointer */ + void *data2; /**< User defined data pointer */ } SDL_UserEvent; /** If you want to use this event, you should include SDL_syswm.h */ struct SDL_SysWMmsg; typedef struct SDL_SysWMmsg SDL_SysWMmsg; typedef struct SDL_SysWMEvent { - Uint8 type; - SDL_SysWMmsg *msg; + Uint8 type; + SDL_SysWMmsg *msg; } SDL_SysWMEvent; /** General event structure */ typedef union SDL_Event { - Uint8 type; - SDL_ActiveEvent active; - SDL_KeyboardEvent key; - SDL_MouseMotionEvent motion; - SDL_MouseButtonEvent button; - SDL_JoyAxisEvent jaxis; - SDL_JoyBallEvent jball; - SDL_JoyHatEvent jhat; - SDL_JoyButtonEvent jbutton; - SDL_ResizeEvent resize; - SDL_ExposeEvent expose; - SDL_QuitEvent quit; - SDL_UserEvent user; - SDL_SysWMEvent syswm; + Uint8 type; + SDL_ActiveEvent active; + SDL_KeyboardEvent key; + SDL_MouseMotionEvent motion; + SDL_MouseButtonEvent button; + SDL_JoyAxisEvent jaxis; + SDL_JoyBallEvent jball; + SDL_JoyHatEvent jhat; + SDL_JoyButtonEvent jbutton; + SDL_ResizeEvent resize; + SDL_ExposeEvent expose; + SDL_QuitEvent quit; + SDL_UserEvent user; + SDL_SysWMEvent syswm; } SDL_Event; @@ -251,9 +251,9 @@ extern DECLSPEC void SDLCALL SDL_PumpEvents(void); typedef enum { - SDL_ADDEVENT, - SDL_PEEKEVENT, - SDL_GETEVENT + SDL_ADDEVENT, + SDL_PEEKEVENT, + SDL_GETEVENT } SDL_eventaction; /** @@ -264,7 +264,7 @@ * If 'action' is SDL_PEEKEVENT, up to 'numevents' events at the front * of the event queue, matching 'mask', will be returned and will not * be removed from the queue. - * If 'action' is SDL_GETEVENT, up to 'numevents' events at the front + * If 'action' is SDL_GETEVENT, up to 'numevents' events at the front * of the event queue, matching 'mask', will be returned and will be * removed from the queue. * @@ -275,7 +275,7 @@ * This function is thread-safe. */ extern DECLSPEC int SDLCALL SDL_PeepEvents(SDL_Event *events, int numevents, - SDL_eventaction action, Uint32 mask); + SDL_eventaction action, Uint32 mask); /** Polls for currently pending events, and returns 1 if there are any pending * events, or 0 if there are none available. If 'event' is not NULL, the next @@ -306,11 +306,11 @@ * @code typedef int (SDLCALL *SDL_EventFilter)(const SDL_Event *event); @endcode * * If the filter returns 1, then the event will be added to the internal queue. - * If it returns 0, then the event will be dropped from the queue, but the + * If it returns 0, then the event will be dropped from the queue, but the * internal state will still be updated. This allows selective filtering of * dynamically arriving events. * - * @warning Be very careful of what you do in the event filter function, as + * @warning Be very careful of what you do in the event filter function, as * it may run in a different thread! * * There is one caveat when dealing with the SDL_QUITEVENT event type. The @@ -331,10 +331,10 @@ /** @name Event State */ /*@{*/ -#define SDL_QUERY -1 -#define SDL_IGNORE 0 -#define SDL_DISABLE 0 -#define SDL_ENABLE 1 +#define SDL_QUERY -1 +#define SDL_IGNORE 0 +#define SDL_DISABLE 0 +#define SDL_ENABLE 1 /*@}*/ /** @@ -342,7 +342,7 @@ * If 'state' is set to SDL_IGNORE, that event will be automatically dropped * from the event queue and will not event be filtered. * If 'state' is set to SDL_ENABLE, that event will be processed normally. -* If 'state' is set to SDL_QUERY, SDL_EventState() will return the +* If 'state' is set to SDL_QUERY, SDL_EventState() will return the * current processing state of the specified event. */ extern DECLSPEC Uint8 SDLCALL SDL_EventState(Uint8 type, int state); diff -r 31570b766315 -r ed5a6478e710 misc/winutils/include/SDL_joystick.h --- a/misc/winutils/include/SDL_joystick.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/winutils/include/SDL_joystick.h Tue Nov 10 20:43:13 2015 +0100 @@ -138,18 +138,18 @@ * The return value of SDL_JoystickGetHat() is one of the following positions: */ /*@{*/ -#define SDL_HAT_CENTERED 0x00 -#define SDL_HAT_UP 0x01 -#define SDL_HAT_RIGHT 0x02 -#define SDL_HAT_DOWN 0x04 -#define SDL_HAT_LEFT 0x08 -#define SDL_HAT_RIGHTUP (SDL_HAT_RIGHT|SDL_HAT_UP) -#define SDL_HAT_RIGHTDOWN (SDL_HAT_RIGHT|SDL_HAT_DOWN) -#define SDL_HAT_LEFTUP (SDL_HAT_LEFT|SDL_HAT_UP) -#define SDL_HAT_LEFTDOWN (SDL_HAT_LEFT|SDL_HAT_DOWN) +#define SDL_HAT_CENTERED 0x00 +#define SDL_HAT_UP 0x01 +#define SDL_HAT_RIGHT 0x02 +#define SDL_HAT_DOWN 0x04 +#define SDL_HAT_LEFT 0x08 +#define SDL_HAT_RIGHTUP (SDL_HAT_RIGHT|SDL_HAT_UP) +#define SDL_HAT_RIGHTDOWN (SDL_HAT_RIGHT|SDL_HAT_DOWN) +#define SDL_HAT_LEFTUP (SDL_HAT_LEFT|SDL_HAT_UP) +#define SDL_HAT_LEFTDOWN (SDL_HAT_LEFT|SDL_HAT_DOWN) /*@}*/ -/** +/** * Get the current state of a POV hat on a joystick * * @param[in] hat The hat indices start at index 0. diff -r 31570b766315 -r ed5a6478e710 misc/winutils/include/SDL_keyboard.h --- a/misc/winutils/include/SDL_keyboard.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/winutils/include/SDL_keyboard.h Tue Nov 10 20:43:13 2015 +0100 @@ -48,23 +48,23 @@ * high 9 bits of the character are 0, then this maps to the equivalent * ASCII character: * @code - * char ch; - * if ( (keysym.unicode & 0xFF80) == 0 ) { - * ch = keysym.unicode & 0x7F; - * } else { - * An international character.. - * } + * char ch; + * if ( (keysym.unicode & 0xFF80) == 0 ) { + * ch = keysym.unicode & 0x7F; + * } else { + * An international character.. + * } * @endcode */ typedef struct SDL_keysym { - Uint8 scancode; /**< hardware specific scancode */ - SDLKey sym; /**< SDL virtual keysym */ - SDLMod mod; /**< current key modifiers */ - Uint16 unicode; /**< translated character */ + Uint8 scancode; /**< hardware specific scancode */ + SDLKey sym; /**< SDL virtual keysym */ + SDLMod mod; /**< current key modifiers */ + Uint16 unicode; /**< translated character */ } SDL_keysym; /** This is the mask which refers to all hotkey bindings */ -#define SDL_ALL_HOTKEYS 0xFFFFFFFF +#define SDL_ALL_HOTKEYS 0xFFFFFFFF /* Function prototypes */ /** @@ -81,8 +81,8 @@ */ extern DECLSPEC int SDLCALL SDL_EnableUNICODE(int enable); -#define SDL_DEFAULT_REPEAT_DELAY 500 -#define SDL_DEFAULT_REPEAT_INTERVAL 30 +#define SDL_DEFAULT_REPEAT_DELAY 500 +#define SDL_DEFAULT_REPEAT_INTERVAL 30 /** * Enable/Disable keyboard repeat. Keyboard repeat defaults to off. * @@ -102,10 +102,10 @@ * Get a snapshot of the current state of the keyboard. * Returns an array of keystates, indexed by the SDLK_* syms. * Usage: - * @code - * Uint8 *keystate = SDL_GetKeyState(NULL); - * if ( keystate[SDLK_RETURN] ) //... \ is pressed. - * @endcode + * @code + * Uint8 *keystate = SDL_GetKeyState(NULL); + * if ( keystate[SDLK_RETURN] ) //... \ is pressed. + * @endcode */ extern DECLSPEC Uint8 * SDLCALL SDL_GetKeyState(int *numkeys); diff -r 31570b766315 -r ed5a6478e710 misc/winutils/include/SDL_keysym.h --- a/misc/winutils/include/SDL_keysym.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/winutils/include/SDL_keysym.h Tue Nov 10 20:43:13 2015 +0100 @@ -33,294 +33,294 @@ * The keyboard syms have been cleverly chosen to map to ASCII */ /*@{*/ - SDLK_UNKNOWN = 0, - SDLK_FIRST = 0, - SDLK_BACKSPACE = 8, - SDLK_TAB = 9, - SDLK_CLEAR = 12, - SDLK_RETURN = 13, - SDLK_PAUSE = 19, - SDLK_ESCAPE = 27, - SDLK_SPACE = 32, - SDLK_EXCLAIM = 33, - SDLK_QUOTEDBL = 34, - SDLK_HASH = 35, - SDLK_DOLLAR = 36, - SDLK_AMPERSAND = 38, - SDLK_QUOTE = 39, - SDLK_LEFTPAREN = 40, - SDLK_RIGHTPAREN = 41, - SDLK_ASTERISK = 42, - SDLK_PLUS = 43, - SDLK_COMMA = 44, - SDLK_MINUS = 45, - SDLK_PERIOD = 46, - SDLK_SLASH = 47, - SDLK_0 = 48, - SDLK_1 = 49, - SDLK_2 = 50, - SDLK_3 = 51, - SDLK_4 = 52, - SDLK_5 = 53, - SDLK_6 = 54, - SDLK_7 = 55, - SDLK_8 = 56, - SDLK_9 = 57, - SDLK_COLON = 58, - SDLK_SEMICOLON = 59, - SDLK_LESS = 60, - SDLK_EQUALS = 61, - SDLK_GREATER = 62, - SDLK_QUESTION = 63, - SDLK_AT = 64, - /* - Skip uppercase letters - */ - SDLK_LEFTBRACKET = 91, - SDLK_BACKSLASH = 92, - SDLK_RIGHTBRACKET = 93, - SDLK_CARET = 94, - SDLK_UNDERSCORE = 95, - SDLK_BACKQUOTE = 96, - SDLK_a = 97, - SDLK_b = 98, - SDLK_c = 99, - SDLK_d = 100, - SDLK_e = 101, - SDLK_f = 102, - SDLK_g = 103, - SDLK_h = 104, - SDLK_i = 105, - SDLK_j = 106, - SDLK_k = 107, - SDLK_l = 108, - SDLK_m = 109, - SDLK_n = 110, - SDLK_o = 111, - SDLK_p = 112, - SDLK_q = 113, - SDLK_r = 114, - SDLK_s = 115, - SDLK_t = 116, - SDLK_u = 117, - SDLK_v = 118, - SDLK_w = 119, - SDLK_x = 120, - SDLK_y = 121, - SDLK_z = 122, - SDLK_DELETE = 127, - /* End of ASCII mapped keysyms */ + SDLK_UNKNOWN = 0, + SDLK_FIRST = 0, + SDLK_BACKSPACE = 8, + SDLK_TAB = 9, + SDLK_CLEAR = 12, + SDLK_RETURN = 13, + SDLK_PAUSE = 19, + SDLK_ESCAPE = 27, + SDLK_SPACE = 32, + SDLK_EXCLAIM = 33, + SDLK_QUOTEDBL = 34, + SDLK_HASH = 35, + SDLK_DOLLAR = 36, + SDLK_AMPERSAND = 38, + SDLK_QUOTE = 39, + SDLK_LEFTPAREN = 40, + SDLK_RIGHTPAREN = 41, + SDLK_ASTERISK = 42, + SDLK_PLUS = 43, + SDLK_COMMA = 44, + SDLK_MINUS = 45, + SDLK_PERIOD = 46, + SDLK_SLASH = 47, + SDLK_0 = 48, + SDLK_1 = 49, + SDLK_2 = 50, + SDLK_3 = 51, + SDLK_4 = 52, + SDLK_5 = 53, + SDLK_6 = 54, + SDLK_7 = 55, + SDLK_8 = 56, + SDLK_9 = 57, + SDLK_COLON = 58, + SDLK_SEMICOLON = 59, + SDLK_LESS = 60, + SDLK_EQUALS = 61, + SDLK_GREATER = 62, + SDLK_QUESTION = 63, + SDLK_AT = 64, + /* + Skip uppercase letters + */ + SDLK_LEFTBRACKET = 91, + SDLK_BACKSLASH = 92, + SDLK_RIGHTBRACKET = 93, + SDLK_CARET = 94, + SDLK_UNDERSCORE = 95, + SDLK_BACKQUOTE = 96, + SDLK_a = 97, + SDLK_b = 98, + SDLK_c = 99, + SDLK_d = 100, + SDLK_e = 101, + SDLK_f = 102, + SDLK_g = 103, + SDLK_h = 104, + SDLK_i = 105, + SDLK_j = 106, + SDLK_k = 107, + SDLK_l = 108, + SDLK_m = 109, + SDLK_n = 110, + SDLK_o = 111, + SDLK_p = 112, + SDLK_q = 113, + SDLK_r = 114, + SDLK_s = 115, + SDLK_t = 116, + SDLK_u = 117, + SDLK_v = 118, + SDLK_w = 119, + SDLK_x = 120, + SDLK_y = 121, + SDLK_z = 122, + SDLK_DELETE = 127, + /* End of ASCII mapped keysyms */ /*@}*/ - /** @name International keyboard syms */ + /** @name International keyboard syms */ /*@{*/ - SDLK_WORLD_0 = 160, /* 0xA0 */ - SDLK_WORLD_1 = 161, - SDLK_WORLD_2 = 162, - SDLK_WORLD_3 = 163, - SDLK_WORLD_4 = 164, - SDLK_WORLD_5 = 165, - SDLK_WORLD_6 = 166, - SDLK_WORLD_7 = 167, - SDLK_WORLD_8 = 168, - SDLK_WORLD_9 = 169, - SDLK_WORLD_10 = 170, - SDLK_WORLD_11 = 171, - SDLK_WORLD_12 = 172, - SDLK_WORLD_13 = 173, - SDLK_WORLD_14 = 174, - SDLK_WORLD_15 = 175, - SDLK_WORLD_16 = 176, - SDLK_WORLD_17 = 177, - SDLK_WORLD_18 = 178, - SDLK_WORLD_19 = 179, - SDLK_WORLD_20 = 180, - SDLK_WORLD_21 = 181, - SDLK_WORLD_22 = 182, - SDLK_WORLD_23 = 183, - SDLK_WORLD_24 = 184, - SDLK_WORLD_25 = 185, - SDLK_WORLD_26 = 186, - SDLK_WORLD_27 = 187, - SDLK_WORLD_28 = 188, - SDLK_WORLD_29 = 189, - SDLK_WORLD_30 = 190, - SDLK_WORLD_31 = 191, - SDLK_WORLD_32 = 192, - SDLK_WORLD_33 = 193, - SDLK_WORLD_34 = 194, - SDLK_WORLD_35 = 195, - SDLK_WORLD_36 = 196, - SDLK_WORLD_37 = 197, - SDLK_WORLD_38 = 198, - SDLK_WORLD_39 = 199, - SDLK_WORLD_40 = 200, - SDLK_WORLD_41 = 201, - SDLK_WORLD_42 = 202, - SDLK_WORLD_43 = 203, - SDLK_WORLD_44 = 204, - SDLK_WORLD_45 = 205, - SDLK_WORLD_46 = 206, - SDLK_WORLD_47 = 207, - SDLK_WORLD_48 = 208, - SDLK_WORLD_49 = 209, - SDLK_WORLD_50 = 210, - SDLK_WORLD_51 = 211, - SDLK_WORLD_52 = 212, - SDLK_WORLD_53 = 213, - SDLK_WORLD_54 = 214, - SDLK_WORLD_55 = 215, - SDLK_WORLD_56 = 216, - SDLK_WORLD_57 = 217, - SDLK_WORLD_58 = 218, - SDLK_WORLD_59 = 219, - SDLK_WORLD_60 = 220, - SDLK_WORLD_61 = 221, - SDLK_WORLD_62 = 222, - SDLK_WORLD_63 = 223, - SDLK_WORLD_64 = 224, - SDLK_WORLD_65 = 225, - SDLK_WORLD_66 = 226, - SDLK_WORLD_67 = 227, - SDLK_WORLD_68 = 228, - SDLK_WORLD_69 = 229, - SDLK_WORLD_70 = 230, - SDLK_WORLD_71 = 231, - SDLK_WORLD_72 = 232, - SDLK_WORLD_73 = 233, - SDLK_WORLD_74 = 234, - SDLK_WORLD_75 = 235, - SDLK_WORLD_76 = 236, - SDLK_WORLD_77 = 237, - SDLK_WORLD_78 = 238, - SDLK_WORLD_79 = 239, - SDLK_WORLD_80 = 240, - SDLK_WORLD_81 = 241, - SDLK_WORLD_82 = 242, - SDLK_WORLD_83 = 243, - SDLK_WORLD_84 = 244, - SDLK_WORLD_85 = 245, - SDLK_WORLD_86 = 246, - SDLK_WORLD_87 = 247, - SDLK_WORLD_88 = 248, - SDLK_WORLD_89 = 249, - SDLK_WORLD_90 = 250, - SDLK_WORLD_91 = 251, - SDLK_WORLD_92 = 252, - SDLK_WORLD_93 = 253, - SDLK_WORLD_94 = 254, - SDLK_WORLD_95 = 255, /* 0xFF */ + SDLK_WORLD_0 = 160, /* 0xA0 */ + SDLK_WORLD_1 = 161, + SDLK_WORLD_2 = 162, + SDLK_WORLD_3 = 163, + SDLK_WORLD_4 = 164, + SDLK_WORLD_5 = 165, + SDLK_WORLD_6 = 166, + SDLK_WORLD_7 = 167, + SDLK_WORLD_8 = 168, + SDLK_WORLD_9 = 169, + SDLK_WORLD_10 = 170, + SDLK_WORLD_11 = 171, + SDLK_WORLD_12 = 172, + SDLK_WORLD_13 = 173, + SDLK_WORLD_14 = 174, + SDLK_WORLD_15 = 175, + SDLK_WORLD_16 = 176, + SDLK_WORLD_17 = 177, + SDLK_WORLD_18 = 178, + SDLK_WORLD_19 = 179, + SDLK_WORLD_20 = 180, + SDLK_WORLD_21 = 181, + SDLK_WORLD_22 = 182, + SDLK_WORLD_23 = 183, + SDLK_WORLD_24 = 184, + SDLK_WORLD_25 = 185, + SDLK_WORLD_26 = 186, + SDLK_WORLD_27 = 187, + SDLK_WORLD_28 = 188, + SDLK_WORLD_29 = 189, + SDLK_WORLD_30 = 190, + SDLK_WORLD_31 = 191, + SDLK_WORLD_32 = 192, + SDLK_WORLD_33 = 193, + SDLK_WORLD_34 = 194, + SDLK_WORLD_35 = 195, + SDLK_WORLD_36 = 196, + SDLK_WORLD_37 = 197, + SDLK_WORLD_38 = 198, + SDLK_WORLD_39 = 199, + SDLK_WORLD_40 = 200, + SDLK_WORLD_41 = 201, + SDLK_WORLD_42 = 202, + SDLK_WORLD_43 = 203, + SDLK_WORLD_44 = 204, + SDLK_WORLD_45 = 205, + SDLK_WORLD_46 = 206, + SDLK_WORLD_47 = 207, + SDLK_WORLD_48 = 208, + SDLK_WORLD_49 = 209, + SDLK_WORLD_50 = 210, + SDLK_WORLD_51 = 211, + SDLK_WORLD_52 = 212, + SDLK_WORLD_53 = 213, + SDLK_WORLD_54 = 214, + SDLK_WORLD_55 = 215, + SDLK_WORLD_56 = 216, + SDLK_WORLD_57 = 217, + SDLK_WORLD_58 = 218, + SDLK_WORLD_59 = 219, + SDLK_WORLD_60 = 220, + SDLK_WORLD_61 = 221, + SDLK_WORLD_62 = 222, + SDLK_WORLD_63 = 223, + SDLK_WORLD_64 = 224, + SDLK_WORLD_65 = 225, + SDLK_WORLD_66 = 226, + SDLK_WORLD_67 = 227, + SDLK_WORLD_68 = 228, + SDLK_WORLD_69 = 229, + SDLK_WORLD_70 = 230, + SDLK_WORLD_71 = 231, + SDLK_WORLD_72 = 232, + SDLK_WORLD_73 = 233, + SDLK_WORLD_74 = 234, + SDLK_WORLD_75 = 235, + SDLK_WORLD_76 = 236, + SDLK_WORLD_77 = 237, + SDLK_WORLD_78 = 238, + SDLK_WORLD_79 = 239, + SDLK_WORLD_80 = 240, + SDLK_WORLD_81 = 241, + SDLK_WORLD_82 = 242, + SDLK_WORLD_83 = 243, + SDLK_WORLD_84 = 244, + SDLK_WORLD_85 = 245, + SDLK_WORLD_86 = 246, + SDLK_WORLD_87 = 247, + SDLK_WORLD_88 = 248, + SDLK_WORLD_89 = 249, + SDLK_WORLD_90 = 250, + SDLK_WORLD_91 = 251, + SDLK_WORLD_92 = 252, + SDLK_WORLD_93 = 253, + SDLK_WORLD_94 = 254, + SDLK_WORLD_95 = 255, /* 0xFF */ /*@}*/ - /** @name Numeric keypad */ + /** @name Numeric keypad */ /*@{*/ - SDLK_KP0 = 256, - SDLK_KP1 = 257, - SDLK_KP2 = 258, - SDLK_KP3 = 259, - SDLK_KP4 = 260, - SDLK_KP5 = 261, - SDLK_KP6 = 262, - SDLK_KP7 = 263, - SDLK_KP8 = 264, - SDLK_KP9 = 265, - SDLK_KP_PERIOD = 266, - SDLK_KP_DIVIDE = 267, - SDLK_KP_MULTIPLY = 268, - SDLK_KP_MINUS = 269, - SDLK_KP_PLUS = 270, - SDLK_KP_ENTER = 271, - SDLK_KP_EQUALS = 272, + SDLK_KP0 = 256, + SDLK_KP1 = 257, + SDLK_KP2 = 258, + SDLK_KP3 = 259, + SDLK_KP4 = 260, + SDLK_KP5 = 261, + SDLK_KP6 = 262, + SDLK_KP7 = 263, + SDLK_KP8 = 264, + SDLK_KP9 = 265, + SDLK_KP_PERIOD = 266, + SDLK_KP_DIVIDE = 267, + SDLK_KP_MULTIPLY = 268, + SDLK_KP_MINUS = 269, + SDLK_KP_PLUS = 270, + SDLK_KP_ENTER = 271, + SDLK_KP_EQUALS = 272, /*@}*/ - /** @name Arrows + Home/End pad */ + /** @name Arrows + Home/End pad */ /*@{*/ - SDLK_UP = 273, - SDLK_DOWN = 274, - SDLK_RIGHT = 275, - SDLK_LEFT = 276, - SDLK_INSERT = 277, - SDLK_HOME = 278, - SDLK_END = 279, - SDLK_PAGEUP = 280, - SDLK_PAGEDOWN = 281, + SDLK_UP = 273, + SDLK_DOWN = 274, + SDLK_RIGHT = 275, + SDLK_LEFT = 276, + SDLK_INSERT = 277, + SDLK_HOME = 278, + SDLK_END = 279, + SDLK_PAGEUP = 280, + SDLK_PAGEDOWN = 281, /*@}*/ - /** @name Function keys */ + /** @name Function keys */ /*@{*/ - SDLK_F1 = 282, - SDLK_F2 = 283, - SDLK_F3 = 284, - SDLK_F4 = 285, - SDLK_F5 = 286, - SDLK_F6 = 287, - SDLK_F7 = 288, - SDLK_F8 = 289, - SDLK_F9 = 290, - SDLK_F10 = 291, - SDLK_F11 = 292, - SDLK_F12 = 293, - SDLK_F13 = 294, - SDLK_F14 = 295, - SDLK_F15 = 296, + SDLK_F1 = 282, + SDLK_F2 = 283, + SDLK_F3 = 284, + SDLK_F4 = 285, + SDLK_F5 = 286, + SDLK_F6 = 287, + SDLK_F7 = 288, + SDLK_F8 = 289, + SDLK_F9 = 290, + SDLK_F10 = 291, + SDLK_F11 = 292, + SDLK_F12 = 293, + SDLK_F13 = 294, + SDLK_F14 = 295, + SDLK_F15 = 296, /*@}*/ - /** @name Key state modifier keys */ + /** @name Key state modifier keys */ /*@{*/ - SDLK_NUMLOCK = 300, - SDLK_CAPSLOCK = 301, - SDLK_SCROLLOCK = 302, - SDLK_RSHIFT = 303, - SDLK_LSHIFT = 304, - SDLK_RCTRL = 305, - SDLK_LCTRL = 306, - SDLK_RALT = 307, - SDLK_LALT = 308, - SDLK_RMETA = 309, - SDLK_LMETA = 310, - SDLK_LSUPER = 311, /**< Left "Windows" key */ - SDLK_RSUPER = 312, /**< Right "Windows" key */ - SDLK_MODE = 313, /**< "Alt Gr" key */ - SDLK_COMPOSE = 314, /**< Multi-key compose key */ + SDLK_NUMLOCK = 300, + SDLK_CAPSLOCK = 301, + SDLK_SCROLLOCK = 302, + SDLK_RSHIFT = 303, + SDLK_LSHIFT = 304, + SDLK_RCTRL = 305, + SDLK_LCTRL = 306, + SDLK_RALT = 307, + SDLK_LALT = 308, + SDLK_RMETA = 309, + SDLK_LMETA = 310, + SDLK_LSUPER = 311, /**< Left "Windows" key */ + SDLK_RSUPER = 312, /**< Right "Windows" key */ + SDLK_MODE = 313, /**< "Alt Gr" key */ + SDLK_COMPOSE = 314, /**< Multi-key compose key */ /*@}*/ - /** @name Miscellaneous function keys */ + /** @name Miscellaneous function keys */ /*@{*/ - SDLK_HELP = 315, - SDLK_PRINT = 316, - SDLK_SYSREQ = 317, - SDLK_BREAK = 318, - SDLK_MENU = 319, - SDLK_POWER = 320, /**< Power Macintosh power key */ - SDLK_EURO = 321, /**< Some european keyboards */ - SDLK_UNDO = 322, /**< Atari keyboard has Undo */ + SDLK_HELP = 315, + SDLK_PRINT = 316, + SDLK_SYSREQ = 317, + SDLK_BREAK = 318, + SDLK_MENU = 319, + SDLK_POWER = 320, /**< Power Macintosh power key */ + SDLK_EURO = 321, /**< Some european keyboards */ + SDLK_UNDO = 322, /**< Atari keyboard has Undo */ /*@}*/ - /* Add any other keys here */ + /* Add any other keys here */ - SDLK_LAST + SDLK_LAST } SDLKey; /** Enumeration of valid key mods (possibly OR'd together) */ typedef enum { - KMOD_NONE = 0x0000, - KMOD_LSHIFT= 0x0001, - KMOD_RSHIFT= 0x0002, - KMOD_LCTRL = 0x0040, - KMOD_RCTRL = 0x0080, - KMOD_LALT = 0x0100, - KMOD_RALT = 0x0200, - KMOD_LMETA = 0x0400, - KMOD_RMETA = 0x0800, - KMOD_NUM = 0x1000, - KMOD_CAPS = 0x2000, - KMOD_MODE = 0x4000, - KMOD_RESERVED = 0x8000 + KMOD_NONE = 0x0000, + KMOD_LSHIFT= 0x0001, + KMOD_RSHIFT= 0x0002, + KMOD_LCTRL = 0x0040, + KMOD_RCTRL = 0x0080, + KMOD_LALT = 0x0100, + KMOD_RALT = 0x0200, + KMOD_LMETA = 0x0400, + KMOD_RMETA = 0x0800, + KMOD_NUM = 0x1000, + KMOD_CAPS = 0x2000, + KMOD_MODE = 0x4000, + KMOD_RESERVED = 0x8000 } SDLMod; -#define KMOD_CTRL (KMOD_LCTRL|KMOD_RCTRL) -#define KMOD_SHIFT (KMOD_LSHIFT|KMOD_RSHIFT) -#define KMOD_ALT (KMOD_LALT|KMOD_RALT) -#define KMOD_META (KMOD_LMETA|KMOD_RMETA) +#define KMOD_CTRL (KMOD_LCTRL|KMOD_RCTRL) +#define KMOD_SHIFT (KMOD_LSHIFT|KMOD_RSHIFT) +#define KMOD_ALT (KMOD_LALT|KMOD_RALT) +#define KMOD_META (KMOD_LMETA|KMOD_RMETA) #endif /* _SDL_keysym_h */ diff -r 31570b766315 -r ed5a6478e710 misc/winutils/include/SDL_loadso.h --- a/misc/winutils/include/SDL_loadso.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/winutils/include/SDL_loadso.h Tue Nov 10 20:43:13 2015 +0100 @@ -25,7 +25,7 @@ */ /** @file SDL_loadso.h - * Some things to keep in mind: + * Some things to keep in mind: * - These functions only work on C function names. Other languages may * have name mangling and intrinsic language support that varies from * compiler to compiler. diff -r 31570b766315 -r ed5a6478e710 misc/winutils/include/SDL_main.h --- a/misc/winutils/include/SDL_main.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/winutils/include/SDL_main.h Tue Nov 10 20:43:13 2015 +0100 @@ -35,7 +35,7 @@ defined(__SYMBIAN32__) || defined(QWS) #ifdef __cplusplus -#define C_LINKAGE "C" +#define C_LINKAGE "C" #else #define C_LINKAGE #endif /* __cplusplus */ @@ -46,12 +46,12 @@ * #ifdef __cplusplus * extern "C" * #endif - * int main(int argc, char *argv[]) - * { - * } + * int main(int argc, char *argv[]) + * { + * } * @endcode */ -#define main SDL_main +#define main SDL_main /** The prototype for the application's main() function */ extern C_LINKAGE int SDL_main(int argc, char *argv[]); diff -r 31570b766315 -r ed5a6478e710 misc/winutils/include/SDL_mixer.h --- a/misc/winutils/include/SDL_mixer.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/winutils/include/SDL_mixer.h Tue Nov 10 20:43:13 2015 +0100 @@ -38,25 +38,25 @@ /* Printable format: "%d.%d.%d", MAJOR, MINOR, PATCHLEVEL */ -#define SDL_MIXER_MAJOR_VERSION 1 -#define SDL_MIXER_MINOR_VERSION 2 +#define SDL_MIXER_MAJOR_VERSION 1 +#define SDL_MIXER_MINOR_VERSION 2 #define SDL_MIXER_PATCHLEVEL 12 /* This macro can be used to fill a version structure with the compile-time * version of the SDL_mixer library. */ -#define SDL_MIXER_VERSION(X) \ -{ \ - (X)->major = SDL_MIXER_MAJOR_VERSION; \ - (X)->minor = SDL_MIXER_MINOR_VERSION; \ - (X)->patch = SDL_MIXER_PATCHLEVEL; \ +#define SDL_MIXER_VERSION(X) \ +{ \ + (X)->major = SDL_MIXER_MAJOR_VERSION; \ + (X)->minor = SDL_MIXER_MINOR_VERSION; \ + (X)->patch = SDL_MIXER_PATCHLEVEL; \ } /* Backwards compatibility */ -#define MIX_MAJOR_VERSION SDL_MIXER_MAJOR_VERSION -#define MIX_MINOR_VERSION SDL_MIXER_MINOR_VERSION -#define MIX_PATCHLEVEL SDL_MIXER_PATCHLEVEL -#define MIX_VERSION(X) SDL_MIXER_VERSION(X) +#define MIX_MAJOR_VERSION SDL_MIXER_MAJOR_VERSION +#define MIX_MINOR_VERSION SDL_MIXER_MINOR_VERSION +#define MIX_PATCHLEVEL SDL_MIXER_PATCHLEVEL +#define MIX_VERSION(X) SDL_MIXER_VERSION(X) /* This function gets the version of the dynamically linked SDL_mixer library. it should NOT be used to fill a version structure, instead you should @@ -85,45 +85,45 @@ /* The default mixer has 8 simultaneous mixing channels */ #ifndef MIX_CHANNELS -#define MIX_CHANNELS 8 +#define MIX_CHANNELS 8 #endif /* Good default values for a PC soundcard */ -#define MIX_DEFAULT_FREQUENCY 22050 +#define MIX_DEFAULT_FREQUENCY 22050 #if SDL_BYTEORDER == SDL_LIL_ENDIAN -#define MIX_DEFAULT_FORMAT AUDIO_S16LSB +#define MIX_DEFAULT_FORMAT AUDIO_S16LSB #else -#define MIX_DEFAULT_FORMAT AUDIO_S16MSB +#define MIX_DEFAULT_FORMAT AUDIO_S16MSB #endif -#define MIX_DEFAULT_CHANNELS 2 -#define MIX_MAX_VOLUME 128 /* Volume of a chunk */ +#define MIX_DEFAULT_CHANNELS 2 +#define MIX_MAX_VOLUME 128 /* Volume of a chunk */ /* The internal format for an audio chunk */ typedef struct Mix_Chunk { - int allocated; - Uint8 *abuf; - Uint32 alen; - Uint8 volume; /* Per-sample volume, 0-128 */ + int allocated; + Uint8 *abuf; + Uint32 alen; + Uint8 volume; /* Per-sample volume, 0-128 */ } Mix_Chunk; /* The different fading types supported */ typedef enum { - MIX_NO_FADING, - MIX_FADING_OUT, - MIX_FADING_IN + MIX_NO_FADING, + MIX_FADING_OUT, + MIX_FADING_IN } Mix_Fading; typedef enum { - MUS_NONE, - MUS_CMD, - MUS_WAV, - MUS_MOD, - MUS_MID, - MUS_OGG, - MUS_MP3, - MUS_MP3_MAD, - MUS_FLAC, - MUS_MODPLUG + MUS_NONE, + MUS_CMD, + MUS_WAV, + MUS_MOD, + MUS_MID, + MUS_OGG, + MUS_MP3, + MUS_MP3_MAD, + MUS_FLAC, + MUS_MODPLUG } Mix_MusicType; /* The internal format for a music chunk interpreted via mikmod */ @@ -131,7 +131,7 @@ /* Open the mixer with a certain audio format */ extern DECLSPEC int SDLCALL Mix_OpenAudio(int frequency, Uint16 format, int channels, - int chunksize); + int chunksize); /* Dynamically change the number of channels managed by the mixer. If decreasing the number of channels, the upper channels are @@ -147,7 +147,7 @@ /* Load a wave file or a music (.mod .s3m .it .xm) file */ extern DECLSPEC Mix_Chunk * SDLCALL Mix_LoadWAV_RW(SDL_RWops *src, int freesrc); -#define Mix_LoadWAV(file) Mix_LoadWAV_RW(SDL_RWFromFile(file, "rb"), 1) +#define Mix_LoadWAV(file) Mix_LoadWAV_RW(SDL_RWFromFile(file, "rb"), 1) extern DECLSPEC Mix_Music * SDLCALL Mix_LoadMUS(const char *file); /* Load a music file from an SDL_RWop object (Ogg and MikMod specific currently) @@ -219,9 +219,9 @@ /* * Add your own callback when a channel has finished playing. NULL - * to disable callback. The callback may be called from the mixer's audio + * to disable callback. The callback may be called from the mixer's audio * callback or it could be called as a result of Mix_HaltChannel(), etc. - * do not call SDL_LockAudio() from this callback; you will either be + * do not call SDL_LockAudio() from this callback; you will either be * inside the audio callback, or SDL_mixer will explicitly lock the audio * before calling your callback. */ @@ -302,7 +302,7 @@ * * After all these effects have finished processing, the callback registered * through Mix_SetPostMix() runs, and then the stream goes to the audio - * device. + * device. * * DO NOT EVER call SDL_LockAudio() from your callback function! * @@ -310,7 +310,7 @@ * Error messages can be retrieved from Mix_GetError(). */ extern DECLSPEC int SDLCALL Mix_RegisterEffect(int chan, Mix_EffectFunc_t f, - Mix_EffectDone_t d, void *arg); + Mix_EffectDone_t d, void *arg); /* You may not need to call this explicitly, unless you need to stop an @@ -590,7 +590,7 @@ /* Set the current position in the music stream. This returns 0 if successful, or -1 if it failed or isn't implemented. This function is only implemented for MOD music formats (set pattern - order number) and for OGG, FLAC, MP3_MAD, and MODPLUG music (set + order number) and for OGG, FLAC, MP3_MAD, and MODPLUG music (set position in seconds), at the moment. */ extern DECLSPEC int SDLCALL Mix_SetMusicPosition(double position); @@ -622,8 +622,8 @@ extern DECLSPEC void SDLCALL Mix_CloseAudio(void); /* We'll use SDL for reporting errors */ -#define Mix_SetError SDL_SetError -#define Mix_GetError SDL_GetError +#define Mix_SetError SDL_SetError +#define Mix_GetError SDL_GetError /* Ends C function definitions when using C++ */ #ifdef __cplusplus diff -r 31570b766315 -r ed5a6478e710 misc/winutils/include/SDL_mouse.h --- a/misc/winutils/include/SDL_mouse.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/winutils/include/SDL_mouse.h Tue Nov 10 20:43:13 2015 +0100 @@ -37,14 +37,14 @@ extern "C" { #endif -typedef struct WMcursor WMcursor; /**< Implementation dependent */ +typedef struct WMcursor WMcursor; /**< Implementation dependent */ typedef struct SDL_Cursor { - SDL_Rect area; /**< The area of the mouse cursor */ - Sint16 hot_x, hot_y; /**< The "tip" of the cursor */ - Uint8 *data; /**< B/W cursor data */ - Uint8 *mask; /**< B/W cursor mask */ - Uint8 *save[2]; /**< Place to save cursor area */ - WMcursor *wm_cursor; /**< Window-manager cursor */ + SDL_Rect area; /**< The area of the mouse cursor */ + Sint16 hot_x, hot_y; /**< The "tip" of the cursor */ + Uint8 *data; /**< B/W cursor data */ + Uint8 *mask; /**< B/W cursor mask */ + Uint8 *save[2]; /**< Place to save cursor area */ + WMcursor *wm_cursor; /**< Window-manager cursor */ } SDL_Cursor; /* Function prototypes */ @@ -83,11 +83,11 @@ * Cursors created with this function must be freed with SDL_FreeCursor(). */ extern DECLSPEC SDL_Cursor * SDLCALL SDL_CreateCursor - (Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y); + (Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y); /** * Set the currently active cursor to the specified one. - * If the cursor is currently visible, the change will be immediately + * If the cursor is currently visible, the change will be immediately * represented on the display. */ extern DECLSPEC void SDLCALL SDL_SetCursor(SDL_Cursor *cursor); @@ -113,25 +113,25 @@ /*@{*/ /** Used as a mask when testing buttons in buttonstate - * Button 1: Left mouse button - * Button 2: Middle mouse button - * Button 3: Right mouse button - * Button 4: Mouse wheel up (may also be a real button) - * Button 5: Mouse wheel down (may also be a real button) + * Button 1: Left mouse button + * Button 2: Middle mouse button + * Button 3: Right mouse button + * Button 4: Mouse wheel up (may also be a real button) + * Button 5: Mouse wheel down (may also be a real button) */ -#define SDL_BUTTON(X) (1 << ((X)-1)) -#define SDL_BUTTON_LEFT 1 -#define SDL_BUTTON_MIDDLE 2 -#define SDL_BUTTON_RIGHT 3 -#define SDL_BUTTON_WHEELUP 4 -#define SDL_BUTTON_WHEELDOWN 5 -#define SDL_BUTTON_X1 6 -#define SDL_BUTTON_X2 7 -#define SDL_BUTTON_LMASK SDL_BUTTON(SDL_BUTTON_LEFT) -#define SDL_BUTTON_MMASK SDL_BUTTON(SDL_BUTTON_MIDDLE) -#define SDL_BUTTON_RMASK SDL_BUTTON(SDL_BUTTON_RIGHT) -#define SDL_BUTTON_X1MASK SDL_BUTTON(SDL_BUTTON_X1) -#define SDL_BUTTON_X2MASK SDL_BUTTON(SDL_BUTTON_X2) +#define SDL_BUTTON(X) (1 << ((X)-1)) +#define SDL_BUTTON_LEFT 1 +#define SDL_BUTTON_MIDDLE 2 +#define SDL_BUTTON_RIGHT 3 +#define SDL_BUTTON_WHEELUP 4 +#define SDL_BUTTON_WHEELDOWN 5 +#define SDL_BUTTON_X1 6 +#define SDL_BUTTON_X2 7 +#define SDL_BUTTON_LMASK SDL_BUTTON(SDL_BUTTON_LEFT) +#define SDL_BUTTON_MMASK SDL_BUTTON(SDL_BUTTON_MIDDLE) +#define SDL_BUTTON_RMASK SDL_BUTTON(SDL_BUTTON_RIGHT) +#define SDL_BUTTON_X1MASK SDL_BUTTON(SDL_BUTTON_X1) +#define SDL_BUTTON_X2MASK SDL_BUTTON(SDL_BUTTON_X2) /*@}*/ /* Ends C function definitions when using C++ */ diff -r 31570b766315 -r ed5a6478e710 misc/winutils/include/SDL_mutex.h --- a/misc/winutils/include/SDL_mutex.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/winutils/include/SDL_mutex.h Tue Nov 10 20:43:13 2015 +0100 @@ -41,10 +41,10 @@ /** Synchronization functions which can time out return this value * if they time out. */ -#define SDL_MUTEX_TIMEDOUT 1 +#define SDL_MUTEX_TIMEDOUT 1 /** This is the timeout value which corresponds to never time out */ -#define SDL_MUTEX_MAXWAIT (~(Uint32)0) +#define SDL_MUTEX_MAXWAIT (~(Uint32)0) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ @@ -58,13 +58,13 @@ /** Create a mutex, initialized unlocked */ extern DECLSPEC SDL_mutex * SDLCALL SDL_CreateMutex(void); -#define SDL_LockMutex(m) SDL_mutexP(m) +#define SDL_LockMutex(m) SDL_mutexP(m) /** Lock the mutex * @return 0, or -1 on error */ extern DECLSPEC int SDLCALL SDL_mutexP(SDL_mutex *mutex); -#define SDL_UnlockMutex(m) SDL_mutexV(m) +#define SDL_UnlockMutex(m) SDL_mutexV(m) /** Unlock the mutex * @return 0, or -1 on error * @@ -93,7 +93,7 @@ extern DECLSPEC void SDLCALL SDL_DestroySemaphore(SDL_sem *sem); /** - * This function suspends the calling thread until the semaphore pointed + * This function suspends the calling thread until the semaphore pointed * to by sem has a positive count. It then atomically decreases the semaphore * count. */ diff -r 31570b766315 -r ed5a6478e710 misc/winutils/include/SDL_name.h --- a/misc/winutils/include/SDL_name.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/winutils/include/SDL_name.h Tue Nov 10 20:43:13 2015 +0100 @@ -6,6 +6,6 @@ #define NeedFunctionPrototypes 1 #endif -#define SDL_NAME(X) SDL_##X +#define SDL_NAME(X) SDL_##X #endif /* _SDLname_h_ */ diff -r 31570b766315 -r ed5a6478e710 misc/winutils/include/SDL_net.h --- a/misc/winutils/include/SDL_net.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/winutils/include/SDL_net.h Tue Nov 10 20:43:13 2015 +0100 @@ -38,18 +38,18 @@ /* Printable format: "%d.%d.%d", MAJOR, MINOR, PATCHLEVEL */ -#define SDL_NET_MAJOR_VERSION 1 -#define SDL_NET_MINOR_VERSION 2 -#define SDL_NET_PATCHLEVEL 8 +#define SDL_NET_MAJOR_VERSION 1 +#define SDL_NET_MINOR_VERSION 2 +#define SDL_NET_PATCHLEVEL 8 /* This macro can be used to fill a version structure with the compile-time * version of the SDL_net library. */ -#define SDL_NET_VERSION(X) \ -{ \ - (X)->major = SDL_NET_MAJOR_VERSION; \ - (X)->minor = SDL_NET_MINOR_VERSION; \ - (X)->patch = SDL_NET_PATCHLEVEL; \ +#define SDL_NET_VERSION(X) \ +{ \ + (X)->major = SDL_NET_MAJOR_VERSION; \ + (X)->minor = SDL_NET_MINOR_VERSION; \ + (X)->patch = SDL_NET_PATCHLEVEL; \ } /* This function gets the version of the dynamically linked SDL_net library. @@ -70,8 +70,8 @@ /***********************************************************************/ typedef struct { - Uint32 host; /* 32-bit IPv4 host address */ - Uint16 port; /* 16-bit protocol port */ + Uint32 host; /* 32-bit IPv4 host address */ + Uint16 port; /* 16-bit protocol port */ } IPaddress; /* Resolve a host name and port to an IP address in network form. @@ -81,13 +81,13 @@ If 'host' is NULL, the resolved host will be set to INADDR_ANY. */ #ifndef INADDR_ANY -#define INADDR_ANY 0x00000000 +#define INADDR_ANY 0x00000000 #endif #ifndef INADDR_NONE -#define INADDR_NONE 0xFFFFFFFF +#define INADDR_NONE 0xFFFFFFFF #endif #ifndef INADDR_BROADCAST -#define INADDR_BROADCAST 0xFFFFFFFF +#define INADDR_BROADCAST 0xFFFFFFFF #endif extern DECLSPEC int SDLCALL SDLNet_ResolveHost(IPaddress *address, const char *host, Uint16 port); @@ -113,7 +113,7 @@ If ip.host is INADDR_NONE or INADDR_ANY, this creates a local server socket on the given port, otherwise a TCP connection to the remote host and port is attempted. The address passed in should already be - swapped to network byte order (addresses returned from + swapped to network byte order (addresses returned from SDLNet_ResolveHost() are already in the correct form). The newly created socket is returned, or NULL if there was an error. */ @@ -135,7 +135,7 @@ closed, or an unknown socket error occurred. */ extern DECLSPEC int SDLCALL SDLNet_TCP_Send(TCPsocket sock, const void *data, - int len); + int len); /* Receive up to 'maxlen' bytes of data over the non-server socket 'sock', and store them in the buffer pointed to by 'data'. @@ -154,18 +154,18 @@ /***********************************************************************/ /* The maximum channels on a a UDP socket */ -#define SDLNET_MAX_UDPCHANNELS 32 +#define SDLNET_MAX_UDPCHANNELS 32 /* The maximum addresses bound to a single UDP socket channel */ -#define SDLNET_MAX_UDPADDRESSES 4 +#define SDLNET_MAX_UDPADDRESSES 4 typedef struct _UDPsocket *UDPsocket; typedef struct { - int channel; /* The src/dst channel of the packet */ - Uint8 *data; /* The packet data */ - int len; /* The length of the packet data */ - int maxlen; /* The size of the data buffer */ - int status; /* packet status after sending */ - IPaddress address; /* The source/dest address of an incoming/outgoing packet */ + int channel; /* The src/dst channel of the packet */ + Uint8 *data; /* The packet data */ + int len; /* The length of the packet data */ + int maxlen; /* The size of the data buffer */ + int status; /* packet status after sending */ + IPaddress address; /* The source/dest address of an incoming/outgoing packet */ } UDPpacket; /* Allocate/resize/free a single UDP packet 'size' bytes long. @@ -210,7 +210,7 @@ /* Unbind all addresses from the given channel */ extern DECLSPEC void SDLCALL SDLNet_UDP_Unbind(UDPsocket sock, int channel); -/* Get the primary IP address of the remote system associated with the +/* Get the primary IP address of the remote system associated with the socket and channel. If the channel is -1, then the primary IP port of the UDP socket is returned -- this is only meaningful for sockets opened with a specific port. @@ -221,7 +221,7 @@ /* Send a vector of packets to the the channels specified within the packet. If the channel specified in the packet is -1, the packet will be sent to the address in the 'src' member of the packet. - Each packet will be updated with the status of the packet after it has + Each packet will be updated with the status of the packet after it has been sent, -1 if the packet send failed. This function returns the number of packets sent. */ @@ -277,7 +277,7 @@ /* Any network socket can be safely cast to this socket type */ typedef struct _SDLNet_GenericSocket { - int ready; + int ready; } *SDLNet_GenericSocket; /* Allocate a socket set for use with SDLNet_CheckSockets() @@ -288,23 +288,23 @@ /* Add a socket to a set of sockets to be checked for available data */ #define SDLNet_TCP_AddSocket(set, sock) \ - SDLNet_AddSocket(set, SDL_reinterpret_cast(SDLNet_GenericSocket, sock)) + SDLNet_AddSocket(set, SDL_reinterpret_cast(SDLNet_GenericSocket, sock)) #define SDLNet_UDP_AddSocket(set, sock) \ - SDLNet_AddSocket(set, SDL_reinterpret_cast(SDLNet_GenericSocket, sock)) + SDLNet_AddSocket(set, SDL_reinterpret_cast(SDLNet_GenericSocket, sock)) extern DECLSPEC int SDLCALL SDLNet_AddSocket(SDLNet_SocketSet set, SDLNet_GenericSocket sock); /* Remove a socket from a set of sockets to be checked for available data */ #define SDLNet_TCP_DelSocket(set, sock) \ - SDLNet_DelSocket(set, SDL_reinterpret_cast(SDLNet_GenericSocket, sock)) + SDLNet_DelSocket(set, SDL_reinterpret_cast(SDLNet_GenericSocket, sock)) #define SDLNet_UDP_DelSocket(set, sock) \ - SDLNet_DelSocket(set, SDL_reinterpret_cast(SDLNet_GenericSocket, sock)) + SDLNet_DelSocket(set, SDL_reinterpret_cast(SDLNet_GenericSocket, sock)) extern DECLSPEC int SDLCALL SDLNet_DelSocket(SDLNet_SocketSet set, SDLNet_GenericSocket sock); /* This function checks to see if data is available for reading on the given set of sockets. If 'timeout' is 0, it performs a quick poll, otherwise the function returns when either data is available for reading, or the timeout in milliseconds has elapsed, which ever occurs - first. This function returns the number of sockets ready for reading, + first. This function returns the number of sockets ready for reading, or -1 if there was an error with the select() system call. */ extern DECLSPEC int SDLCALL SDLNet_CheckSockets(SDLNet_SocketSet set, Uint32 timeout); @@ -314,7 +314,7 @@ for reading. */ #define SDLNet_SocketReady(sock) \ - ((sock != NULL) && SDL_reinterpret_cast(SDLNet_GenericSocket, sock)->ready) + ((sock != NULL) && SDL_reinterpret_cast(SDLNet_GenericSocket, sock)->ready) /* Free a set of sockets allocated by SDL_NetAllocSocketSet() */ extern DECLSPEC void SDLCALL SDLNet_FreeSocketSet(SDLNet_SocketSet set); @@ -337,8 +337,8 @@ /***********************************************************************/ /* We'll use SDL's functions for error reporting */ -#define SDLNet_SetError SDL_SetError -#define SDLNet_GetError SDL_GetError +#define SDLNet_SetError SDL_SetError +#define SDLNet_GetError SDL_GetError /* I'm eventually going to try to disentangle SDL_net from SDL, thus making SDL_net an independent X-platform networking toolkit. Not today though.... @@ -352,91 +352,91 @@ /* Warning, some systems have data access alignment restrictions */ #if defined(sparc) || defined(mips) -#define SDL_DATA_ALIGNED 1 +#define SDL_DATA_ALIGNED 1 #endif #ifndef SDL_DATA_ALIGNED -#define SDL_DATA_ALIGNED 0 +#define SDL_DATA_ALIGNED 0 #endif /* Write a 16 bit value to network packet buffer */ #if !SDL_DATA_ALIGNED -#define SDLNet_Write16(value, areap) \ - (*SDL_reinterpret_cast(Uint16 *, areap) = SDL_SwapBE16(value)) +#define SDLNet_Write16(value, areap) \ + (*SDL_reinterpret_cast(Uint16 *, areap) = SDL_SwapBE16(value)) #else #if SDL_BYTEORDER == SDL_BIG_ENDIAN -#define SDLNet_Write16(value, areap) \ -do \ -{ \ - Uint8 *area = SDL_reinterpret_cast(Uint8 *, areap); \ - area[0] = (value >> 8) & 0xFF; \ - area[1] = value & 0xFF; \ +#define SDLNet_Write16(value, areap) \ +do \ +{ \ + Uint8 *area = SDL_reinterpret_cast(Uint8 *, areap); \ + area[0] = (value >> 8) & 0xFF; \ + area[1] = value & 0xFF; \ } while ( 0 ) #else -#define SDLNet_Write16(value, areap) \ -do \ -{ \ - Uint8 *area = SDL_reinterpret_cast(Uint8 *, areap); \ - area[1] = (value >> 8) & 0xFF; \ - area[0] = value & 0xFF; \ +#define SDLNet_Write16(value, areap) \ +do \ +{ \ + Uint8 *area = SDL_reinterpret_cast(Uint8 *, areap); \ + area[1] = (value >> 8) & 0xFF; \ + area[0] = value & 0xFF; \ } while ( 0 ) #endif #endif /* !SDL_DATA_ALIGNED */ /* Write a 32 bit value to network packet buffer */ #if !SDL_DATA_ALIGNED -#define SDLNet_Write32(value, areap) \ - *SDL_reinterpret_cast(Uint32 *, areap) = SDL_SwapBE32(value); +#define SDLNet_Write32(value, areap) \ + *SDL_reinterpret_cast(Uint32 *, areap) = SDL_SwapBE32(value); #else #if SDL_BYTEORDER == SDL_BIG_ENDIAN -#define SDLNet_Write32(value, areap) \ -do \ -{ \ - Uint8 *area = SDL_reinterpret_cast(Uint8 *, areap); \ - area[0] = (value >> 24) & 0xFF; \ - area[1] = (value >> 16) & 0xFF; \ - area[2] = (value >> 8) & 0xFF; \ - area[3] = value & 0xFF; \ +#define SDLNet_Write32(value, areap) \ +do \ +{ \ + Uint8 *area = SDL_reinterpret_cast(Uint8 *, areap); \ + area[0] = (value >> 24) & 0xFF; \ + area[1] = (value >> 16) & 0xFF; \ + area[2] = (value >> 8) & 0xFF; \ + area[3] = value & 0xFF; \ } while ( 0 ) #else -#define SDLNet_Write32(value, areap) \ -do \ -{ \ - Uint8 *area = SDL_reinterpret_cast(Uint8 *, areap); \ - area[3] = (value >> 24) & 0xFF; \ - area[2] = (value >> 16) & 0xFF; \ - area[1] = (value >> 8) & 0xFF; \ - area[0] = value & 0xFF; \ +#define SDLNet_Write32(value, areap) \ +do \ +{ \ + Uint8 *area = SDL_reinterpret_cast(Uint8 *, areap); \ + area[3] = (value >> 24) & 0xFF; \ + area[2] = (value >> 16) & 0xFF; \ + area[1] = (value >> 8) & 0xFF; \ + area[0] = value & 0xFF; \ } while ( 0 ) #endif #endif /* !SDL_DATA_ALIGNED */ /* Read a 16 bit value from network packet buffer */ #if !SDL_DATA_ALIGNED -#define SDLNet_Read16(areap) \ - (SDL_SwapBE16(*SDL_reinterpret_cast(Uint16 *, areap))) +#define SDLNet_Read16(areap) \ + (SDL_SwapBE16(*SDL_reinterpret_cast(Uint16 *, areap))) #else #if SDL_BYTEORDER == SDL_BIG_ENDIAN -#define SDLNet_Read16(areap) \ - (((SDL_reinterpret_cast(Uint8 *, areap))[0] << 8) | (SDL_reinterpret_cast(Uint8 *, areap))[1] << 0) +#define SDLNet_Read16(areap) \ + (((SDL_reinterpret_cast(Uint8 *, areap))[0] << 8) | (SDL_reinterpret_cast(Uint8 *, areap))[1] << 0) #else -#define SDLNet_Read16(areap) \ - (((SDL_reinterpret_cast(Uint8 *, areap))[1] << 8) | (SDL_reinterpret_cast(Uint8 *, areap))[0] << 0) +#define SDLNet_Read16(areap) \ + (((SDL_reinterpret_cast(Uint8 *, areap))[1] << 8) | (SDL_reinterpret_cast(Uint8 *, areap))[0] << 0) #endif #endif /* !SDL_DATA_ALIGNED */ /* Read a 32 bit value from network packet buffer */ #if !SDL_DATA_ALIGNED -#define SDLNet_Read32(areap) \ - (SDL_SwapBE32(*SDL_reinterpret_cast(Uint32 *, areap))) +#define SDLNet_Read32(areap) \ + (SDL_SwapBE32(*SDL_reinterpret_cast(Uint32 *, areap))) #else #if SDL_BYTEORDER == SDL_BIG_ENDIAN -#define SDLNet_Read32(areap) \ - (((SDL_reinterpret_cast(Uint8 *, areap))[0] << 24) | ((SDL_reinterpret_cast(Uint8 *, areap))[1] << 16) | \ - ((SDL_reinterpret_cast(Uint8 *, areap))[2] << 8) | (SDL_reinterpret_cast(Uint8 *, areap))[3] << 0) +#define SDLNet_Read32(areap) \ + (((SDL_reinterpret_cast(Uint8 *, areap))[0] << 24) | ((SDL_reinterpret_cast(Uint8 *, areap))[1] << 16) | \ + ((SDL_reinterpret_cast(Uint8 *, areap))[2] << 8) | (SDL_reinterpret_cast(Uint8 *, areap))[3] << 0) #else -#define SDLNet_Read32(areap) \ - (((SDL_reinterpret_cast(Uint8 *, areap))[3] << 24) | ((SDL_reinterpret_cast(Uint8 *, areap))[2] << 16) | \ - ((SDL_reinterpret_cast(Uint8 *, areap))[1] << 8) | (SDL_reinterpret_cast(Uint8 *, areap))[0] << 0) +#define SDLNet_Read32(areap) \ + (((SDL_reinterpret_cast(Uint8 *, areap))[3] << 24) | ((SDL_reinterpret_cast(Uint8 *, areap))[2] << 16) | \ + ((SDL_reinterpret_cast(Uint8 *, areap))[1] << 8) | (SDL_reinterpret_cast(Uint8 *, areap))[0] << 0) #endif #endif /* !SDL_DATA_ALIGNED */ diff -r 31570b766315 -r ed5a6478e710 misc/winutils/include/SDL_opengl.h --- a/misc/winutils/include/SDL_opengl.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/winutils/include/SDL_opengl.h Tue Nov 10 20:43:13 2015 +0100 @@ -29,7 +29,7 @@ #ifdef __WIN32__ #define WIN32_LEAN_AND_MEAN #ifndef NOMINMAX -#define NOMINMAX /* Don't defined min() and max() */ +#define NOMINMAX /* Don't defined min() and max() */ #endif #include #endif @@ -37,14 +37,14 @@ #define __glext_h_ /* Don't let gl.h include glext.h */ #endif #if defined(__MACOSX__) -#include /* Header File For The OpenGL Library */ -#include /* Header File For The GLU Library */ +#include /* Header File For The OpenGL Library */ +#include /* Header File For The GLU Library */ #elif defined(__MACOS__) -#include /* Header File For The OpenGL Library */ -#include /* Header File For The GLU Library */ +#include /* Header File For The OpenGL Library */ +#include /* Header File For The GLU Library */ #else -#include /* Header File For The OpenGL Library */ -#include /* Header File For The GLU Library */ +#include /* Header File For The OpenGL Library */ +#include /* Header File For The GLU Library */ #endif #ifndef NO_SDL_GLEXT #undef __glext_h_ @@ -72,21 +72,21 @@ ** this file except in compliance with the License. You may obtain a copy ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: -** +** ** http://oss.sgi.com/projects/FreeB -** +** ** Note that, as provided in the License, the Software is distributed on an ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. -** +** ** Original Code. The Original Code is: OpenGL Sample Implementation, ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, ** Inc. The Original Code is Copyright (c) 1991-2004 Silicon Graphics, Inc. ** Copyright in any portions created by third parties is as indicated ** elsewhere herein. All Rights Reserved. -** +** ** Additional Notice Provisions: This software was created using the ** OpenGL(R) version 1.2.1 Sample Implementation published by SGI, but has ** not been independently verified as being compliant with the OpenGL(R) @@ -3103,7 +3103,7 @@ #include #ifndef GL_VERSION_2_0 /* GL type for program/shader text */ -typedef char GLchar; /* native character */ +typedef char GLchar; /* native character */ #endif #ifndef GL_VERSION_1_5 @@ -3130,11 +3130,11 @@ #ifndef GL_ARB_shader_objects /* GL types for handling shader object handles and program/shader text */ -typedef char GLcharARB; /* native character */ +typedef char GLcharARB; /* native character */ #if defined(__APPLE__) -typedef void *GLhandleARB; /* shader object handle */ +typedef void *GLhandleARB; /* shader object handle */ #else -typedef unsigned int GLhandleARB; /* shader object handle */ +typedef unsigned int GLhandleARB; /* shader object handle */ #endif #endif diff -r 31570b766315 -r ed5a6478e710 misc/winutils/include/SDL_platform.h --- a/misc/winutils/include/SDL_platform.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/winutils/include/SDL_platform.h Tue Nov 10 20:43:13 2015 +0100 @@ -29,11 +29,11 @@ #if defined(_AIX) #undef __AIX__ -#define __AIX__ 1 +#define __AIX__ 1 #endif #if defined(__BEOS__) #undef __BEOS__ -#define __BEOS__ 1 +#define __BEOS__ 1 #endif #if defined(__HAIKU__) #undef __HAIKU__ @@ -41,70 +41,70 @@ #endif #if defined(bsdi) || defined(__bsdi) || defined(__bsdi__) #undef __BSDI__ -#define __BSDI__ 1 +#define __BSDI__ 1 #endif #if defined(_arch_dreamcast) #undef __DREAMCAST__ -#define __DREAMCAST__ 1 +#define __DREAMCAST__ 1 #endif #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) #undef __FREEBSD__ -#define __FREEBSD__ 1 +#define __FREEBSD__ 1 #endif #if defined(__HAIKU__) #undef __HAIKU__ -#define __HAIKU__ 1 +#define __HAIKU__ 1 #endif #if defined(hpux) || defined(__hpux) || defined(__hpux__) #undef __HPUX__ -#define __HPUX__ 1 +#define __HPUX__ 1 #endif #if defined(sgi) || defined(__sgi) || defined(__sgi__) || defined(_SGI_SOURCE) #undef __IRIX__ -#define __IRIX__ 1 +#define __IRIX__ 1 #endif #if defined(linux) || defined(__linux) || defined(__linux__) #undef __LINUX__ -#define __LINUX__ 1 +#define __LINUX__ 1 #endif #if defined(__APPLE__) #undef __MACOSX__ -#define __MACOSX__ 1 +#define __MACOSX__ 1 #elif defined(macintosh) #undef __MACOS__ -#define __MACOS__ 1 +#define __MACOS__ 1 #endif #if defined(__NetBSD__) #undef __NETBSD__ -#define __NETBSD__ 1 +#define __NETBSD__ 1 #endif #if defined(__OpenBSD__) #undef __OPENBSD__ -#define __OPENBSD__ 1 +#define __OPENBSD__ 1 #endif #if defined(__OS2__) #undef __OS2__ -#define __OS2__ 1 +#define __OS2__ 1 #endif #if defined(osf) || defined(__osf) || defined(__osf__) || defined(_OSF_SOURCE) #undef __OSF__ -#define __OSF__ 1 +#define __OSF__ 1 #endif #if defined(__QNXNTO__) #undef __QNXNTO__ -#define __QNXNTO__ 1 +#define __QNXNTO__ 1 #endif #if defined(riscos) || defined(__riscos) || defined(__riscos__) #undef __RISCOS__ -#define __RISCOS__ 1 +#define __RISCOS__ 1 #endif #if defined(__SVR4) #undef __SOLARIS__ -#define __SOLARIS__ 1 +#define __SOLARIS__ 1 #endif #if defined(WIN32) || defined(_WIN32) #undef __WIN32__ -#define __WIN32__ 1 +#define __WIN32__ 1 #endif #endif /* _SDL_platform_h */ diff -r 31570b766315 -r ed5a6478e710 misc/winutils/include/SDL_quit.h --- a/misc/winutils/include/SDL_quit.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/winutils/include/SDL_quit.h Tue Nov 10 20:43:13 2015 +0100 @@ -34,7 +34,7 @@ * An SDL_QUITEVENT is generated when the user tries to close the application * window. If it is ignored or filtered out, the window will remain open. * If it is not ignored or filtered, it is queued normally and the window - * is allowed to close. When the window is closed, screen updates will + * is allowed to close. When the window is closed, screen updates will * complete, but have no effect. * * SDL_Init() installs signal handlers for SIGINT (keyboard interrupt) @@ -46,7 +46,7 @@ */ /** @file SDL_quit.h - * There are no functions directly affecting the quit event + * There are no functions directly affecting the quit event */ #define SDL_QuitRequested() \ diff -r 31570b766315 -r ed5a6478e710 misc/winutils/include/SDL_rwops.h --- a/misc/winutils/include/SDL_rwops.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/winutils/include/SDL_rwops.h Tue Nov 10 20:43:13 2015 +0100 @@ -40,55 +40,55 @@ /** This is the read/write operation structure -- very basic */ typedef struct SDL_RWops { - /** Seek to 'offset' relative to whence, one of stdio's whence values: - * SEEK_SET, SEEK_CUR, SEEK_END - * Returns the final offset in the data source. - */ - int (SDLCALL *seek)(struct SDL_RWops *context, int offset, int whence); + /** Seek to 'offset' relative to whence, one of stdio's whence values: + * SEEK_SET, SEEK_CUR, SEEK_END + * Returns the final offset in the data source. + */ + int (SDLCALL *seek)(struct SDL_RWops *context, int offset, int whence); - /** Read up to 'maxnum' objects each of size 'size' from the data - * source to the area pointed at by 'ptr'. - * Returns the number of objects read, or -1 if the read failed. - */ - int (SDLCALL *read)(struct SDL_RWops *context, void *ptr, int size, int maxnum); + /** Read up to 'maxnum' objects each of size 'size' from the data + * source to the area pointed at by 'ptr'. + * Returns the number of objects read, or -1 if the read failed. + */ + int (SDLCALL *read)(struct SDL_RWops *context, void *ptr, int size, int maxnum); - /** Write exactly 'num' objects each of size 'objsize' from the area - * pointed at by 'ptr' to data source. - * Returns 'num', or -1 if the write failed. - */ - int (SDLCALL *write)(struct SDL_RWops *context, const void *ptr, int size, int num); + /** Write exactly 'num' objects each of size 'objsize' from the area + * pointed at by 'ptr' to data source. + * Returns 'num', or -1 if the write failed. + */ + int (SDLCALL *write)(struct SDL_RWops *context, const void *ptr, int size, int num); - /** Close and free an allocated SDL_FSops structure */ - int (SDLCALL *close)(struct SDL_RWops *context); + /** Close and free an allocated SDL_FSops structure */ + int (SDLCALL *close)(struct SDL_RWops *context); - Uint32 type; - union { + Uint32 type; + union { #if defined(__WIN32__) && !defined(__SYMBIAN32__) - struct { - int append; - void *h; - struct { - void *data; - int size; - int left; - } buffer; - } win32io; + struct { + int append; + void *h; + struct { + void *data; + int size; + int left; + } buffer; + } win32io; #endif -#ifdef HAVE_STDIO_H - struct { - int autoclose; - FILE *fp; - } stdio; +#ifdef HAVE_STDIO_H + struct { + int autoclose; + FILE *fp; + } stdio; #endif - struct { - Uint8 *base; - Uint8 *here; - Uint8 *stop; - } mem; - struct { - void *data1; - } unknown; - } hidden; + struct { + Uint8 *base; + Uint8 *here; + Uint8 *stop; + } mem; + struct { + void *data1; + } unknown; + } hidden; } SDL_RWops; @@ -112,18 +112,18 @@ /** @name Seek Reference Points */ /*@{*/ -#define RW_SEEK_SET 0 /**< Seek from the beginning of data */ -#define RW_SEEK_CUR 1 /**< Seek relative to current read point */ -#define RW_SEEK_END 2 /**< Seek relative to the end of data */ +#define RW_SEEK_SET 0 /**< Seek from the beginning of data */ +#define RW_SEEK_CUR 1 /**< Seek relative to current read point */ +#define RW_SEEK_END 2 /**< Seek relative to the end of data */ /*@}*/ /** @name Macros to easily read and write from an SDL_RWops structure */ /*@{*/ -#define SDL_RWseek(ctx, offset, whence) (ctx)->seek(ctx, offset, whence) -#define SDL_RWtell(ctx) (ctx)->seek(ctx, 0, RW_SEEK_CUR) -#define SDL_RWread(ctx, ptr, size, n) (ctx)->read(ctx, ptr, size, n) -#define SDL_RWwrite(ctx, ptr, size, n) (ctx)->write(ctx, ptr, size, n) -#define SDL_RWclose(ctx) (ctx)->close(ctx) +#define SDL_RWseek(ctx, offset, whence) (ctx)->seek(ctx, offset, whence) +#define SDL_RWtell(ctx) (ctx)->seek(ctx, 0, RW_SEEK_CUR) +#define SDL_RWread(ctx, ptr, size, n) (ctx)->read(ctx, ptr, size, n) +#define SDL_RWwrite(ctx, ptr, size, n) (ctx)->write(ctx, ptr, size, n) +#define SDL_RWclose(ctx) (ctx)->close(ctx) /*@}*/ /** @name Read an item of the specified endianness and return in native format */ diff -r 31570b766315 -r ed5a6478e710 misc/winutils/include/SDL_stdinc.h --- a/misc/winutils/include/SDL_stdinc.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/winutils/include/SDL_stdinc.h Tue Nov 10 20:43:13 2015 +0100 @@ -75,8 +75,8 @@ #endif /** The number of elements in an array */ -#define SDL_arraysize(array) (sizeof(array)/sizeof(array[0])) -#define SDL_TABLESIZE(table) SDL_arraysize(table) +#define SDL_arraysize(array) (sizeof(array)/sizeof(array[0])) +#define SDL_TABLESIZE(table) SDL_arraysize(table) /* Use proper C++ casts when compiled as C++ to be compatible with the option -Wold-style-cast of GCC (and -Werror=old-style-cast in GCC 4.2 and above. */ @@ -91,27 +91,27 @@ /** @name Basic data types */ /*@{*/ typedef enum { - SDL_FALSE = 0, - SDL_TRUE = 1 + SDL_FALSE = 0, + SDL_TRUE = 1 } SDL_bool; -typedef int8_t Sint8; -typedef uint8_t Uint8; -typedef int16_t Sint16; -typedef uint16_t Uint16; -typedef int32_t Sint32; -typedef uint32_t Uint32; +typedef int8_t Sint8; +typedef uint8_t Uint8; +typedef int16_t Sint16; +typedef uint16_t Uint16; +typedef int32_t Sint32; +typedef uint32_t Uint32; #ifdef SDL_HAS_64BIT_TYPE -typedef int64_t Sint64; +typedef int64_t Sint64; #ifndef SYMBIAN32_GCCE -typedef uint64_t Uint64; +typedef uint64_t Uint64; #endif #else /* This is really just a hack to prevent the compiler from complaining */ typedef struct { - Uint32 hi; - Uint32 lo; + Uint32 hi; + Uint32 lo; } Uint64, Sint64; #endif @@ -144,7 +144,7 @@ #endif typedef enum { - DUMMY_ENUM_VALUE + DUMMY_ENUM_VALUE } SDL_DUMMY_ENUM; #ifndef __NDS__ @@ -159,25 +159,25 @@ #endif #ifdef HAVE_MALLOC -#define SDL_malloc malloc +#define SDL_malloc malloc #else extern DECLSPEC void * SDLCALL SDL_malloc(size_t size); #endif #ifdef HAVE_CALLOC -#define SDL_calloc calloc +#define SDL_calloc calloc #else extern DECLSPEC void * SDLCALL SDL_calloc(size_t nmemb, size_t size); #endif #ifdef HAVE_REALLOC -#define SDL_realloc realloc +#define SDL_realloc realloc #else extern DECLSPEC void * SDLCALL SDL_realloc(void *mem, size_t size); #endif #ifdef HAVE_FREE -#define SDL_free free +#define SDL_free free #else extern DECLSPEC void SDLCALL SDL_free(void *mem); #endif @@ -213,32 +213,32 @@ #endif #ifdef HAVE_GETENV -#define SDL_getenv getenv +#define SDL_getenv getenv #else extern DECLSPEC char * SDLCALL SDL_getenv(const char *name); #endif #ifdef HAVE_PUTENV -#define SDL_putenv putenv +#define SDL_putenv putenv #else extern DECLSPEC int SDLCALL SDL_putenv(const char *variable); #endif #ifdef HAVE_QSORT -#define SDL_qsort qsort +#define SDL_qsort qsort #else extern DECLSPEC void SDLCALL SDL_qsort(void *base, size_t nmemb, size_t size, int (*compare)(const void *, const void *)); #endif #ifdef HAVE_ABS -#define SDL_abs abs +#define SDL_abs abs #else -#define SDL_abs(X) ((X) < 0 ? -(X) : (X)) +#define SDL_abs(X) ((X) < 0 ? -(X) : (X)) #endif -#define SDL_min(x, y) (((x) < (y)) ? (x) : (y)) -#define SDL_max(x, y) (((x) > (y)) ? (x) : (y)) +#define SDL_min(x, y) (((x) < (y)) ? (x) : (y)) +#define SDL_max(x, y) (((x) > (y)) ? (x) : (y)) #ifdef HAVE_CTYPE_H #define SDL_isdigit(X) isdigit(X) @@ -259,32 +259,32 @@ #endif #if defined(__GNUC__) && defined(i386) -#define SDL_memset4(dst, val, len) \ -do { \ - int u0, u1, u2; \ - __asm__ __volatile__ ( \ - "cld\n\t" \ - "rep ; stosl\n\t" \ - : "=&D" (u0), "=&a" (u1), "=&c" (u2) \ - : "0" (dst), "1" (val), "2" (SDL_static_cast(Uint32, len)) \ - : "memory" ); \ +#define SDL_memset4(dst, val, len) \ +do { \ + int u0, u1, u2; \ + __asm__ __volatile__ ( \ + "cld\n\t" \ + "rep ; stosl\n\t" \ + : "=&D" (u0), "=&a" (u1), "=&c" (u2) \ + : "0" (dst), "1" (val), "2" (SDL_static_cast(Uint32, len)) \ + : "memory" ); \ } while(0) #endif #ifndef SDL_memset4 -#define SDL_memset4(dst, val, len) \ -do { \ - unsigned _count = (len); \ - unsigned _n = (_count + 3) / 4; \ - Uint32 *_p = SDL_static_cast(Uint32 *, dst); \ - Uint32 _val = (val); \ - if (len == 0) break; \ - switch (_count % 4) { \ - case 0: do { *_p++ = _val; \ - case 3: *_p++ = _val; \ - case 2: *_p++ = _val; \ - case 1: *_p++ = _val; \ - } while ( --_n ); \ - } \ +#define SDL_memset4(dst, val, len) \ +do { \ + unsigned _count = (len); \ + unsigned _n = (_count + 3) / 4; \ + Uint32 *_p = SDL_static_cast(Uint32 *, dst); \ + Uint32 _val = (val); \ + if (len == 0) break; \ + switch (_count % 4) { \ + case 0: do { *_p++ = _val; \ + case 3: *_p++ = _val; \ + case 2: *_p++ = _val; \ + case 1: *_p++ = _val; \ + } while ( --_n ); \ + } \ } while(0) #endif @@ -292,29 +292,29 @@ #if defined(__MACH__) && defined(__APPLE__) #define SDL_memcpy(dst, src, len) memcpy(dst, src, len) #elif defined(__GNUC__) && defined(i386) -#define SDL_memcpy(dst, src, len) \ -do { \ - int u0, u1, u2; \ - __asm__ __volatile__ ( \ - "cld\n\t" \ - "rep ; movsl\n\t" \ - "testb $2,%b4\n\t" \ - "je 1f\n\t" \ - "movsw\n" \ - "1:\ttestb $1,%b4\n\t" \ - "je 2f\n\t" \ - "movsb\n" \ - "2:" \ - : "=&c" (u0), "=&D" (u1), "=&S" (u2) \ - : "0" (SDL_static_cast(unsigned, len)/4), "q" (len), "1" (dst),"2" (src) \ - : "memory" ); \ +#define SDL_memcpy(dst, src, len) \ +do { \ + int u0, u1, u2; \ + __asm__ __volatile__ ( \ + "cld\n\t" \ + "rep ; movsl\n\t" \ + "testb $2,%b4\n\t" \ + "je 1f\n\t" \ + "movsw\n" \ + "1:\ttestb $1,%b4\n\t" \ + "je 2f\n\t" \ + "movsb\n" \ + "2:" \ + : "=&c" (u0), "=&D" (u1), "=&S" (u2) \ + : "0" (SDL_static_cast(unsigned, len)/4), "q" (len), "1" (dst),"2" (src) \ + : "memory" ); \ } while(0) #endif #ifndef SDL_memcpy #ifdef HAVE_MEMCPY #define SDL_memcpy memcpy #elif defined(HAVE_BCOPY) -#define SDL_memcpy(d, s, n) bcopy((s), (d), (n)) +#define SDL_memcpy(d, s, n) bcopy((s), (d), (n)) #else extern DECLSPEC void * SDLCALL SDL_memcpy(void *dst, const void *src, size_t len); #endif @@ -324,46 +324,46 @@ #if defined(__MACH__) && defined(__APPLE__) #define SDL_memcpy4(dst, src, len) memcpy(dst, src, (len)*4) #elif defined(__GNUC__) && defined(i386) -#define SDL_memcpy4(dst, src, len) \ -do { \ - int ecx, edi, esi; \ - __asm__ __volatile__ ( \ - "cld\n\t" \ - "rep ; movsl" \ - : "=&c" (ecx), "=&D" (edi), "=&S" (esi) \ - : "0" (SDL_static_cast(unsigned, len)), "1" (dst), "2" (src) \ - : "memory" ); \ +#define SDL_memcpy4(dst, src, len) \ +do { \ + int ecx, edi, esi; \ + __asm__ __volatile__ ( \ + "cld\n\t" \ + "rep ; movsl" \ + : "=&c" (ecx), "=&D" (edi), "=&S" (esi) \ + : "0" (SDL_static_cast(unsigned, len)), "1" (dst), "2" (src) \ + : "memory" ); \ } while(0) #endif #ifndef SDL_memcpy4 -#define SDL_memcpy4(dst, src, len) SDL_memcpy(dst, src, (len) << 2) +#define SDL_memcpy4(dst, src, len) SDL_memcpy(dst, src, (len) << 2) #endif #if defined(__GNUC__) && defined(i386) -#define SDL_revcpy(dst, src, len) \ -do { \ - int u0, u1, u2; \ - char *dstp = SDL_static_cast(char *, dst); \ - char *srcp = SDL_static_cast(char *, src); \ - int n = (len); \ - if ( n >= 4 ) { \ - __asm__ __volatile__ ( \ - "std\n\t" \ - "rep ; movsl\n\t" \ - "cld\n\t" \ - : "=&c" (u0), "=&D" (u1), "=&S" (u2) \ - : "0" (n >> 2), \ - "1" (dstp+(n-4)), "2" (srcp+(n-4)) \ - : "memory" ); \ - } \ - switch (n & 3) { \ - case 3: dstp[2] = srcp[2]; \ - case 2: dstp[1] = srcp[1]; \ - case 1: dstp[0] = srcp[0]; \ - break; \ - default: \ - break; \ - } \ +#define SDL_revcpy(dst, src, len) \ +do { \ + int u0, u1, u2; \ + char *dstp = SDL_static_cast(char *, dst); \ + char *srcp = SDL_static_cast(char *, src); \ + int n = (len); \ + if ( n >= 4 ) { \ + __asm__ __volatile__ ( \ + "std\n\t" \ + "rep ; movsl\n\t" \ + "cld\n\t" \ + : "=&c" (u0), "=&D" (u1), "=&S" (u2) \ + : "0" (n >> 2), \ + "1" (dstp+(n-4)), "2" (srcp+(n-4)) \ + : "memory" ); \ + } \ + switch (n & 3) { \ + case 3: dstp[2] = srcp[2]; \ + case 2: dstp[1] = srcp[1]; \ + case 1: dstp[0] = srcp[0]; \ + break; \ + default: \ + break; \ + } \ } while(0) #endif #ifndef SDL_revcpy @@ -373,15 +373,15 @@ #ifdef HAVE_MEMMOVE #define SDL_memmove memmove #elif defined(HAVE_BCOPY) -#define SDL_memmove(d, s, n) bcopy((s), (d), (n)) +#define SDL_memmove(d, s, n) bcopy((s), (d), (n)) #else -#define SDL_memmove(dst, src, len) \ -do { \ - if ( dst < src ) { \ - SDL_memcpy(dst, src, len); \ - } else { \ - SDL_revcpy(dst, src, len); \ - } \ +#define SDL_memmove(dst, src, len) \ +do { \ + if ( dst < src ) { \ + SDL_memcpy(dst, src, len); \ + } else { \ + SDL_revcpy(dst, src, len); \ + } \ } while(0) #endif @@ -458,7 +458,7 @@ #ifdef HAVE_ITOA #define SDL_itoa itoa #else -#define SDL_itoa(value, string, radix) SDL_ltoa((long)value, string, radix) +#define SDL_itoa(value, string, radix) SDL_ltoa((long)value, string, radix) #endif #ifdef HAVE__LTOA @@ -470,7 +470,7 @@ #ifdef HAVE__UITOA #define SDL_uitoa _uitoa #else -#define SDL_uitoa(value, string, radix) SDL_ultoa((long)value, string, radix) +#define SDL_uitoa(value, string, radix) SDL_ultoa((long)value, string, radix) #endif #ifdef HAVE__ULTOA @@ -584,13 +584,13 @@ #endif /** @name SDL_ICONV Error Codes - * The SDL implementation of iconv() returns these error codes + * The SDL implementation of iconv() returns these error codes */ /*@{*/ -#define SDL_ICONV_ERROR (size_t)-1 -#define SDL_ICONV_E2BIG (size_t)-2 -#define SDL_ICONV_EILSEQ (size_t)-3 -#define SDL_ICONV_EINVAL (size_t)-4 +#define SDL_ICONV_ERROR (size_t)-1 +#define SDL_ICONV_E2BIG (size_t)-2 +#define SDL_ICONV_EILSEQ (size_t)-3 +#define SDL_ICONV_EINVAL (size_t)-4 /*@}*/ #if defined(HAVE_ICONV) && defined(HAVE_ICONV_H) @@ -607,9 +607,9 @@ * string that must be freed with SDL_free() or NULL on error. */ extern DECLSPEC char * SDLCALL SDL_iconv_string(const char *tocode, const char *fromcode, const char *inbuf, size_t inbytesleft); -#define SDL_iconv_utf8_locale(S) SDL_iconv_string("", "UTF-8", S, SDL_strlen(S)+1) -#define SDL_iconv_utf8_ucs2(S) (Uint16 *)SDL_iconv_string("UCS-2", "UTF-8", S, SDL_strlen(S)+1) -#define SDL_iconv_utf8_ucs4(S) (Uint32 *)SDL_iconv_string("UCS-4", "UTF-8", S, SDL_strlen(S)+1) +#define SDL_iconv_utf8_locale(S) SDL_iconv_string("", "UTF-8", S, SDL_strlen(S)+1) +#define SDL_iconv_utf8_ucs2(S) (Uint16 *)SDL_iconv_string("UCS-2", "UTF-8", S, SDL_strlen(S)+1) +#define SDL_iconv_utf8_ucs4(S) (Uint32 *)SDL_iconv_string("UCS-4", "UTF-8", S, SDL_strlen(S)+1) /* Ends C function definitions when using C++ */ #ifdef __cplusplus diff -r 31570b766315 -r ed5a6478e710 misc/winutils/include/SDL_syswm.h --- a/misc/winutils/include/SDL_syswm.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/winutils/include/SDL_syswm.h Tue Nov 10 20:43:13 2015 +0100 @@ -65,16 +65,16 @@ /** These are the various supported subsystems under UNIX */ typedef enum { - SDL_SYSWM_X11 + SDL_SYSWM_X11 } SDL_SYSWM_TYPE; /** The UNIX custom event structure */ struct SDL_SysWMmsg { - SDL_version version; - SDL_SYSWM_TYPE subsystem; - union { - XEvent xevent; - } event; + SDL_version version; + SDL_SYSWM_TYPE subsystem; + union { + XEvent xevent; + } event; }; /** The UNIX custom window manager information structure. @@ -82,35 +82,35 @@ * low level system it is using, and will be one of SDL_SYSWM_TYPE. */ typedef struct SDL_SysWMinfo { - SDL_version version; - SDL_SYSWM_TYPE subsystem; - union { - struct { - Display *display; /**< The X11 display */ - Window window; /**< The X11 display window */ - /** These locking functions should be called around - * any X11 functions using the display variable, + SDL_version version; + SDL_SYSWM_TYPE subsystem; + union { + struct { + Display *display; /**< The X11 display */ + Window window; /**< The X11 display window */ + /** These locking functions should be called around + * any X11 functions using the display variable, * but not the gfxdisplay variable. * They lock the event thread, so should not be - * called around event functions or from event filters. - */ + * called around event functions or from event filters. + */ /*@{*/ - void (*lock_func)(void); - void (*unlock_func)(void); + void (*lock_func)(void); + void (*unlock_func)(void); /*@}*/ - /** @name Introduced in SDL 1.0.2 */ + /** @name Introduced in SDL 1.0.2 */ /*@{*/ - Window fswindow; /**< The X11 fullscreen window */ - Window wmwindow; /**< The X11 managed input window */ + Window fswindow; /**< The X11 fullscreen window */ + Window wmwindow; /**< The X11 managed input window */ /*@}*/ - /** @name Introduced in SDL 1.2.12 */ + /** @name Introduced in SDL 1.2.12 */ /*@{*/ - Display *gfxdisplay; /**< The X11 display to which rendering is done */ + Display *gfxdisplay; /**< The X11 display to which rendering is done */ /*@}*/ - } x11; - } info; + } x11; + } info; } SDL_SysWMinfo; #elif defined(SDL_VIDEO_DRIVER_NANOX) @@ -118,14 +118,14 @@ /** The generic custom event structure */ struct SDL_SysWMmsg { - SDL_version version; - int data; + SDL_version version; + int data; }; /** The windows custom window manager information structure */ typedef struct SDL_SysWMinfo { - SDL_version version ; - GR_WINDOW_ID window ; /* The display window */ + SDL_version version ; + GR_WINDOW_ID window ; /* The display window */ } SDL_SysWMinfo; #elif defined(SDL_VIDEO_DRIVER_WINDIB) || defined(SDL_VIDEO_DRIVER_DDRAW) || defined(SDL_VIDEO_DRIVER_GAPI) @@ -134,35 +134,35 @@ /** The windows custom event structure */ struct SDL_SysWMmsg { - SDL_version version; - HWND hwnd; /**< The window for the message */ - UINT msg; /**< The type of message */ - WPARAM wParam; /**< WORD message parameter */ - LPARAM lParam; /**< LONG message parameter */ + SDL_version version; + HWND hwnd; /**< The window for the message */ + UINT msg; /**< The type of message */ + WPARAM wParam; /**< WORD message parameter */ + LPARAM lParam; /**< LONG message parameter */ }; /** The windows custom window manager information structure */ typedef struct SDL_SysWMinfo { - SDL_version version; - HWND window; /**< The Win32 display window */ - HGLRC hglrc; /**< The OpenGL context, if any */ + SDL_version version; + HWND window; /**< The Win32 display window */ + HGLRC hglrc; /**< The OpenGL context, if any */ } SDL_SysWMinfo; #elif defined(SDL_VIDEO_DRIVER_RISCOS) /** RISC OS custom event structure */ struct SDL_SysWMmsg { - SDL_version version; - int eventCode; /**< The window for the message */ - int pollBlock[64]; + SDL_version version; + int eventCode; /**< The window for the message */ + int pollBlock[64]; }; /** The RISC OS custom window manager information structure */ typedef struct SDL_SysWMinfo { - SDL_version version; - int wimpVersion; /**< Wimp version running under */ - int taskHandle; /**< The RISC OS task handle */ - int window; /**< The RISC OS display window */ + SDL_version version; + int wimpVersion; /**< Wimp version running under */ + int taskHandle; /**< The RISC OS task handle */ + int window; /**< The RISC OS display window */ } SDL_SysWMinfo; #elif defined(SDL_VIDEO_DRIVER_PHOTON) @@ -171,28 +171,28 @@ /** The QNX custom event structure */ struct SDL_SysWMmsg { - SDL_version version; - int data; + SDL_version version; + int data; }; /** The QNX custom window manager information structure */ typedef struct SDL_SysWMinfo { - SDL_version version; - int data; + SDL_version version; + int data; } SDL_SysWMinfo; #else /** The generic custom event structure */ struct SDL_SysWMmsg { - SDL_version version; - int data; + SDL_version version; + int data; }; /** The generic custom window manager information structure */ typedef struct SDL_SysWMinfo { - SDL_version version; - int data; + SDL_version version; + int data; } SDL_SysWMinfo; #endif /* video driver type */ @@ -203,7 +203,7 @@ /** * This function gives you custom hooks into the window manager information. * It fills the structure pointed to by 'info' with custom information and - * returns 0 if the function is not implemented, 1 if the function is + * returns 0 if the function is not implemented, 1 if the function is * implemented and no error occurred, and -1 if the version member of * the 'info' structure is not filled in or not supported. * diff -r 31570b766315 -r ed5a6478e710 misc/winutils/include/SDL_thread.h --- a/misc/winutils/include/SDL_thread.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/winutils/include/SDL_thread.h Tue Nov 10 20:43:13 2015 +0100 @@ -24,7 +24,7 @@ #define _SDL_thread_h /** @file SDL_thread.h - * Header for the SDL thread management routines + * Header for the SDL thread management routines * * @note These are independent of the other SDL routines. */ @@ -66,11 +66,11 @@ #endif #ifdef __OS2__ -typedef int (*pfnSDL_CurrentBeginThread)(void (*func)(void *), void *, unsigned, void *arg); +typedef int (*pfnSDL_CurrentBeginThread)(void (*func)(void *), void *, unsigned, void *arg); typedef void (*pfnSDL_CurrentEndThread)(void); #else typedef uintptr_t (__cdecl *pfnSDL_CurrentBeginThread) (void *, unsigned, - unsigned (__stdcall *func)(void *), void *arg, + unsigned (__stdcall *func)(void *), void *arg, unsigned, unsigned *threadID); typedef void (__cdecl *pfnSDL_CurrentEndThread)(unsigned code); #endif diff -r 31570b766315 -r ed5a6478e710 misc/winutils/include/SDL_timer.h --- a/misc/winutils/include/SDL_timer.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/winutils/include/SDL_timer.h Tue Nov 10 20:43:13 2015 +0100 @@ -37,15 +37,15 @@ #endif /** This is the OS scheduler timeslice, in milliseconds */ -#define SDL_TIMESLICE 10 +#define SDL_TIMESLICE 10 /** This is the maximum resolution of the SDL timer on all platforms */ -#define TIMER_RESOLUTION 10 /**< Experimentally determined */ +#define TIMER_RESOLUTION 10 /**< Experimentally determined */ /** * Get the number of milliseconds since the SDL library initialization. * Note that this value wraps if the program runs for more than ~49 days. - */ + */ extern DECLSPEC Uint32 SDLCALL SDL_GetTicks(void); /** Wait a specified number of milliseconds before returning */ @@ -57,7 +57,7 @@ /** * Set a callback to run after the specified number of milliseconds has * elapsed. The callback function is passed the current timer interval - * and returns the next timer interval. If the returned value is the + * and returns the next timer interval. If the returned value is the * same as the one passed in, the periodic alarm continues, otherwise a * new alarm is scheduled. If the callback returns 0, the periodic alarm * is cancelled. @@ -70,7 +70,7 @@ * The maximum resolution of this timer is 10 ms, which means that if * you request a 16 ms timer, your callback will run approximately 20 ms * later on an unloaded system. If you wanted to set a flag signaling - * a frame update at 30 frames per second (every 33 ms), you might set a + * a frame update at 30 frames per second (every 33 ms), you might set a * timer for 30 ms: * @code SDL_SetTimer((33/10)*10, flag_update); @endcode * diff -r 31570b766315 -r ed5a6478e710 misc/winutils/include/SDL_version.h --- a/misc/winutils/include/SDL_version.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/winutils/include/SDL_version.h Tue Nov 10 20:43:13 2015 +0100 @@ -39,42 +39,42 @@ * Printable format: "%d.%d.%d", MAJOR, MINOR, PATCHLEVEL */ /*@{*/ -#define SDL_MAJOR_VERSION 1 -#define SDL_MINOR_VERSION 2 -#define SDL_PATCHLEVEL 15 +#define SDL_MAJOR_VERSION 1 +#define SDL_MINOR_VERSION 2 +#define SDL_PATCHLEVEL 15 /*@}*/ typedef struct SDL_version { - Uint8 major; - Uint8 minor; - Uint8 patch; + Uint8 major; + Uint8 minor; + Uint8 patch; } SDL_version; /** * This macro can be used to fill a version structure with the compile-time * version of the SDL library. */ -#define SDL_VERSION(X) \ -{ \ - (X)->major = SDL_MAJOR_VERSION; \ - (X)->minor = SDL_MINOR_VERSION; \ - (X)->patch = SDL_PATCHLEVEL; \ +#define SDL_VERSION(X) \ +{ \ + (X)->major = SDL_MAJOR_VERSION; \ + (X)->minor = SDL_MINOR_VERSION; \ + (X)->patch = SDL_PATCHLEVEL; \ } /** This macro turns the version numbers into a numeric value: * (1,2,3) -> (1203) * This assumes that there will never be more than 100 patchlevels */ -#define SDL_VERSIONNUM(X, Y, Z) \ - ((X)*1000 + (Y)*100 + (Z)) +#define SDL_VERSIONNUM(X, Y, Z) \ + ((X)*1000 + (Y)*100 + (Z)) /** This is the version number macro for the current SDL version */ #define SDL_COMPILEDVERSION \ - SDL_VERSIONNUM(SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL) + SDL_VERSIONNUM(SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL) /** This macro will evaluate to true if compiled with SDL at least X.Y.Z */ #define SDL_VERSION_ATLEAST(X, Y, Z) \ - (SDL_COMPILEDVERSION >= SDL_VERSIONNUM(X, Y, Z)) + (SDL_COMPILEDVERSION >= SDL_VERSIONNUM(X, Y, Z)) /** This function gets the version of the dynamically linked SDL library. * it should NOT be used to fill a version structure, instead you should diff -r 31570b766315 -r ed5a6478e710 misc/winutils/include/SDL_video.h --- a/misc/winutils/include/SDL_video.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/winutils/include/SDL_video.h Tue Nov 10 20:43:13 2015 +0100 @@ -48,77 +48,77 @@ /** @name Useful data types */ /*@{*/ typedef struct SDL_Rect { - Sint16 x, y; - Uint16 w, h; + Sint16 x, y; + Uint16 w, h; } SDL_Rect; typedef struct SDL_Color { - Uint8 r; - Uint8 g; - Uint8 b; - Uint8 unused; + Uint8 r; + Uint8 g; + Uint8 b; + Uint8 unused; } SDL_Color; #define SDL_Colour SDL_Color typedef struct SDL_Palette { - int ncolors; - SDL_Color *colors; + int ncolors; + SDL_Color *colors; } SDL_Palette; /*@}*/ /** Everything in the pixel format structure is read-only */ typedef struct SDL_PixelFormat { - SDL_Palette *palette; - Uint8 BitsPerPixel; - Uint8 BytesPerPixel; - Uint8 Rloss; - Uint8 Gloss; - Uint8 Bloss; - Uint8 Aloss; - Uint8 Rshift; - Uint8 Gshift; - Uint8 Bshift; - Uint8 Ashift; - Uint32 Rmask; - Uint32 Gmask; - Uint32 Bmask; - Uint32 Amask; + SDL_Palette *palette; + Uint8 BitsPerPixel; + Uint8 BytesPerPixel; + Uint8 Rloss; + Uint8 Gloss; + Uint8 Bloss; + Uint8 Aloss; + Uint8 Rshift; + Uint8 Gshift; + Uint8 Bshift; + Uint8 Ashift; + Uint32 Rmask; + Uint32 Gmask; + Uint32 Bmask; + Uint32 Amask; - /** RGB color key information */ - Uint32 colorkey; - /** Alpha value information (per-surface alpha) */ - Uint8 alpha; + /** RGB color key information */ + Uint32 colorkey; + /** Alpha value information (per-surface alpha) */ + Uint8 alpha; } SDL_PixelFormat; /** This structure should be treated as read-only, except for 'pixels', * which, if not NULL, contains the raw pixel data for the surface. */ typedef struct SDL_Surface { - Uint32 flags; /**< Read-only */ - SDL_PixelFormat *format; /**< Read-only */ - int w, h; /**< Read-only */ - Uint16 pitch; /**< Read-only */ - void *pixels; /**< Read-write */ - int offset; /**< Private */ + Uint32 flags; /**< Read-only */ + SDL_PixelFormat *format; /**< Read-only */ + int w, h; /**< Read-only */ + Uint16 pitch; /**< Read-only */ + void *pixels; /**< Read-write */ + int offset; /**< Private */ - /** Hardware-specific surface info */ - struct private_hwdata *hwdata; + /** Hardware-specific surface info */ + struct private_hwdata *hwdata; - /** clipping information */ - SDL_Rect clip_rect; /**< Read-only */ - Uint32 unused1; /**< for binary compatibility */ + /** clipping information */ + SDL_Rect clip_rect; /**< Read-only */ + Uint32 unused1; /**< for binary compatibility */ - /** Allow recursive locks */ - Uint32 locked; /**< Private */ + /** Allow recursive locks */ + Uint32 locked; /**< Private */ - /** info for fast blit mapping to other surfaces */ - struct SDL_BlitMap *map; /**< Private */ + /** info for fast blit mapping to other surfaces */ + struct SDL_BlitMap *map; /**< Private */ - /** format version, bumped at every change to invalidate blit maps */ - unsigned int format_version; /**< Private */ + /** format version, bumped at every change to invalidate blit maps */ + unsigned int format_version; /**< Private */ - /** Reference count -- used when freeing surface */ - int refcount; /**< Read-mostly */ + /** Reference count -- used when freeing surface */ + int refcount; /**< Read-mostly */ } SDL_Surface; /** @name SDL_Surface Flags @@ -128,100 +128,100 @@ /** Available for SDL_CreateRGBSurface() or SDL_SetVideoMode() */ /*@{*/ -#define SDL_SWSURFACE 0x00000000 /**< Surface is in system memory */ -#define SDL_HWSURFACE 0x00000001 /**< Surface is in video memory */ -#define SDL_ASYNCBLIT 0x00000004 /**< Use asynchronous blits if possible */ +#define SDL_SWSURFACE 0x00000000 /**< Surface is in system memory */ +#define SDL_HWSURFACE 0x00000001 /**< Surface is in video memory */ +#define SDL_ASYNCBLIT 0x00000004 /**< Use asynchronous blits if possible */ /*@}*/ /** Available for SDL_SetVideoMode() */ /*@{*/ -#define SDL_ANYFORMAT 0x10000000 /**< Allow any video depth/pixel-format */ -#define SDL_HWPALETTE 0x20000000 /**< Surface has exclusive palette */ -#define SDL_DOUBLEBUF 0x40000000 /**< Set up double-buffered video mode */ -#define SDL_FULLSCREEN 0x80000000 /**< Surface is a full screen display */ +#define SDL_ANYFORMAT 0x10000000 /**< Allow any video depth/pixel-format */ +#define SDL_HWPALETTE 0x20000000 /**< Surface has exclusive palette */ +#define SDL_DOUBLEBUF 0x40000000 /**< Set up double-buffered video mode */ +#define SDL_FULLSCREEN 0x80000000 /**< Surface is a full screen display */ #define SDL_OPENGL 0x00000002 /**< Create an OpenGL rendering context */ -#define SDL_OPENGLBLIT 0x0000000A /**< Create an OpenGL rendering context and use it for blitting */ -#define SDL_RESIZABLE 0x00000010 /**< This video mode may be resized */ -#define SDL_NOFRAME 0x00000020 /**< No window caption or edge frame */ +#define SDL_OPENGLBLIT 0x0000000A /**< Create an OpenGL rendering context and use it for blitting */ +#define SDL_RESIZABLE 0x00000010 /**< This video mode may be resized */ +#define SDL_NOFRAME 0x00000020 /**< No window caption or edge frame */ /*@}*/ /** Used internally (read-only) */ /*@{*/ -#define SDL_HWACCEL 0x00000100 /**< Blit uses hardware acceleration */ -#define SDL_SRCCOLORKEY 0x00001000 /**< Blit uses a source color key */ -#define SDL_RLEACCELOK 0x00002000 /**< Private flag */ -#define SDL_RLEACCEL 0x00004000 /**< Surface is RLE encoded */ -#define SDL_SRCALPHA 0x00010000 /**< Blit uses source alpha blending */ -#define SDL_PREALLOC 0x01000000 /**< Surface uses preallocated memory */ +#define SDL_HWACCEL 0x00000100 /**< Blit uses hardware acceleration */ +#define SDL_SRCCOLORKEY 0x00001000 /**< Blit uses a source color key */ +#define SDL_RLEACCELOK 0x00002000 /**< Private flag */ +#define SDL_RLEACCEL 0x00004000 /**< Surface is RLE encoded */ +#define SDL_SRCALPHA 0x00010000 /**< Blit uses source alpha blending */ +#define SDL_PREALLOC 0x01000000 /**< Surface uses preallocated memory */ /*@}*/ /*@}*/ /** Evaluates to true if the surface needs to be locked before access */ -#define SDL_MUSTLOCK(surface) \ - (surface->offset || \ +#define SDL_MUSTLOCK(surface) \ + (surface->offset || \ ((surface->flags & (SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_RLEACCEL)) != 0)) /** typedef for private surface blitting functions */ typedef int (*SDL_blit)(struct SDL_Surface *src, SDL_Rect *srcrect, - struct SDL_Surface *dst, SDL_Rect *dstrect); + struct SDL_Surface *dst, SDL_Rect *dstrect); /** Useful for determining the video hardware capabilities */ typedef struct SDL_VideoInfo { - Uint32 hw_available :1; /**< Flag: Can you create hardware surfaces? */ - Uint32 wm_available :1; /**< Flag: Can you talk to a window manager? */ - Uint32 UnusedBits1 :6; - Uint32 UnusedBits2 :1; - Uint32 blit_hw :1; /**< Flag: Accelerated blits HW --> HW */ - Uint32 blit_hw_CC :1; /**< Flag: Accelerated blits with Colorkey */ - Uint32 blit_hw_A :1; /**< Flag: Accelerated blits with Alpha */ - Uint32 blit_sw :1; /**< Flag: Accelerated blits SW --> HW */ - Uint32 blit_sw_CC :1; /**< Flag: Accelerated blits with Colorkey */ - Uint32 blit_sw_A :1; /**< Flag: Accelerated blits with Alpha */ - Uint32 blit_fill :1; /**< Flag: Accelerated color fill */ - Uint32 UnusedBits3 :16; - Uint32 video_mem; /**< The total amount of video memory (in K) */ - SDL_PixelFormat *vfmt; /**< Value: The format of the video surface */ - int current_w; /**< Value: The current video mode width */ - int current_h; /**< Value: The current video mode height */ + Uint32 hw_available :1; /**< Flag: Can you create hardware surfaces? */ + Uint32 wm_available :1; /**< Flag: Can you talk to a window manager? */ + Uint32 UnusedBits1 :6; + Uint32 UnusedBits2 :1; + Uint32 blit_hw :1; /**< Flag: Accelerated blits HW --> HW */ + Uint32 blit_hw_CC :1; /**< Flag: Accelerated blits with Colorkey */ + Uint32 blit_hw_A :1; /**< Flag: Accelerated blits with Alpha */ + Uint32 blit_sw :1; /**< Flag: Accelerated blits SW --> HW */ + Uint32 blit_sw_CC :1; /**< Flag: Accelerated blits with Colorkey */ + Uint32 blit_sw_A :1; /**< Flag: Accelerated blits with Alpha */ + Uint32 blit_fill :1; /**< Flag: Accelerated color fill */ + Uint32 UnusedBits3 :16; + Uint32 video_mem; /**< The total amount of video memory (in K) */ + SDL_PixelFormat *vfmt; /**< Value: The format of the video surface */ + int current_w; /**< Value: The current video mode width */ + int current_h; /**< Value: The current video mode height */ } SDL_VideoInfo; /** @name Overlay Formats * The most common video overlay formats. * For an explanation of these pixel formats, see: - * http://www.webartz.com/fourcc/indexyuv.htm + * http://www.webartz.com/fourcc/indexyuv.htm * * For information on the relationship between color spaces, see: * http://www.neuro.sfc.keio.ac.jp/~aly/polygon/info/color-space-faq.html */ /*@{*/ -#define SDL_YV12_OVERLAY 0x32315659 /**< Planar mode: Y + V + U (3 planes) */ -#define SDL_IYUV_OVERLAY 0x56555949 /**< Planar mode: Y + U + V (3 planes) */ -#define SDL_YUY2_OVERLAY 0x32595559 /**< Packed mode: Y0+U0+Y1+V0 (1 plane) */ -#define SDL_UYVY_OVERLAY 0x59565955 /**< Packed mode: U0+Y0+V0+Y1 (1 plane) */ -#define SDL_YVYU_OVERLAY 0x55595659 /**< Packed mode: Y0+V0+Y1+U0 (1 plane) */ +#define SDL_YV12_OVERLAY 0x32315659 /**< Planar mode: Y + V + U (3 planes) */ +#define SDL_IYUV_OVERLAY 0x56555949 /**< Planar mode: Y + U + V (3 planes) */ +#define SDL_YUY2_OVERLAY 0x32595559 /**< Packed mode: Y0+U0+Y1+V0 (1 plane) */ +#define SDL_UYVY_OVERLAY 0x59565955 /**< Packed mode: U0+Y0+V0+Y1 (1 plane) */ +#define SDL_YVYU_OVERLAY 0x55595659 /**< Packed mode: Y0+V0+Y1+U0 (1 plane) */ /*@}*/ /** The YUV hardware video overlay */ typedef struct SDL_Overlay { - Uint32 format; /**< Read-only */ - int w, h; /**< Read-only */ - int planes; /**< Read-only */ - Uint16 *pitches; /**< Read-only */ - Uint8 **pixels; /**< Read-write */ + Uint32 format; /**< Read-only */ + int w, h; /**< Read-only */ + int planes; /**< Read-only */ + Uint16 *pitches; /**< Read-only */ + Uint8 **pixels; /**< Read-write */ - /** @name Hardware-specific surface info */ + /** @name Hardware-specific surface info */ /*@{*/ - struct private_yuvhwfuncs *hwfuncs; - struct private_yuvhwdata *hwdata; + struct private_yuvhwfuncs *hwfuncs; + struct private_yuvhwdata *hwdata; /*@{*/ - /** @name Special flags */ + /** @name Special flags */ /*@{*/ - Uint32 hw_overlay :1; /**< Flag: This overlay hardware accelerated? */ - Uint32 UnusedBits :31; + Uint32 hw_overlay :1; /**< Flag: This overlay hardware accelerated? */ + Uint32 UnusedBits :31; /*@}*/ } SDL_Overlay; @@ -314,11 +314,11 @@ /** * Return a pointer to an array of available screen dimensions for the - * given format and video flags, sorted largest to smallest. Returns - * NULL if there are no dimensions available for a particular format, + * given format and video flags, sorted largest to smallest. Returns + * NULL if there are no dimensions available for a particular format, * or (SDL_Rect **)-1 if any dimension is okay for the given format. * - * If 'format' is NULL, the mode list will be for the format given + * If 'format' is NULL, the mode list will be for the format given * by SDL_GetVideoInfo()->vfmt */ extern DECLSPEC SDL_Rect ** SDLCALL SDL_ListModes(SDL_PixelFormat *format, Uint32 flags); @@ -347,21 +347,21 @@ * Otherwise, in 8-bit mode, SDL_SetColors() may not be able to set all * of the colors exactly the way they are requested, and you should look * at the video surface structure to determine the actual palette. - * If SDL cannot guarantee that the colors you request can be set, + * If SDL cannot guarantee that the colors you request can be set, * i.e. if the colormap is shared, then the video surface may be created * under emulation in system memory, overriding the SDL_HWSURFACE flag. * * If SDL_FULLSCREEN is set in 'flags', the SDL library will try to set * a fullscreen video mode. The default is to create a windowed mode * if the current graphics system has a window manager. - * If the SDL library is able to set a fullscreen video mode, this flag + * If the SDL library is able to set a fullscreen video mode, this flag * will be set in the surface that is returned. * * If SDL_DOUBLEBUF is set in 'flags', the SDL library will try to set up - * two surfaces in video memory and swap between them when you call + * two surfaces in video memory and swap between them when you call * SDL_Flip(). This is usually slower than the normal single-buffering - * scheme, but prevents "tearing" artifacts caused by modifying video - * memory while the monitor is refreshing. It should only be used by + * scheme, but prevents "tearing" artifacts caused by modifying video + * memory while the monitor is refreshing. It should only be used by * applications that redraw the entire screen on every update. * * If SDL_RESIZABLE is set in 'flags', the SDL library will allow the @@ -382,7 +382,7 @@ * are not available. */ extern DECLSPEC SDL_Surface * SDLCALL SDL_SetVideoMode - (int width, int height, int bpp, Uint32 flags); + (int width, int height, int bpp, Uint32 flags); /** @name SDL_Update Functions * These functions should not be called while 'screen' is locked. @@ -392,13 +392,13 @@ * Makes sure the given list of rectangles is updated on the given screen. */ extern DECLSPEC void SDLCALL SDL_UpdateRects - (SDL_Surface *screen, int numrects, SDL_Rect *rects); + (SDL_Surface *screen, int numrects, SDL_Rect *rects); /** * If 'x', 'y', 'w' and 'h' are all 0, SDL_UpdateRect will update the entire * screen. */ extern DECLSPEC void SDLCALL SDL_UpdateRect - (SDL_Surface *screen, Sint32 x, Sint32 y, Uint32 w, Uint32 h); + (SDL_Surface *screen, Sint32 x, Sint32 y, Uint32 w, Uint32 h); /*@}*/ /** @@ -416,7 +416,7 @@ /** * Set the gamma correction for each of the color channels. * The gamma values range (approximately) between 0.1 and 10.0 - * + * * If this function isn't supported directly by the hardware, it will * be emulated using gamma ramps, if available. If successful, this * function returns 0, otherwise it returns -1. @@ -429,7 +429,7 @@ * representing a mapping between the input and output for that channel. * The input is the index into the array, and the output is the 16-bit * gamma value at that index, scaled to the output color precision. - * + * * You may pass NULL for any of the channels to leave it unchanged. * If the call succeeds, it will return 0. If the display driver or * hardware does not support gamma translation, or otherwise fails, @@ -439,7 +439,7 @@ /** * Retrieve the current values of the gamma translation tables. - * + * * You must pass in valid pointers to arrays of 256 16-bit quantities. * Any of the pointers may be NULL to ignore that channel. * If the call succeeds, it will return 0. If the display driver or @@ -457,14 +457,14 @@ * determine the actual color palette. * * When 'surface' is the surface associated with the current display, the - * display colormap will be updated with the requested colors. If + * display colormap will be updated with the requested colors. If * SDL_HWPALETTE was set in SDL_SetVideoMode() flags, SDL_SetColors() * will always return 1, and the palette is guaranteed to be set the way * you desire, even if the window colormap has to be warped or run under * emulation. */ -extern DECLSPEC int SDLCALL SDL_SetColors(SDL_Surface *surface, - SDL_Color *colors, int firstcolor, int ncolors); +extern DECLSPEC int SDLCALL SDL_SetColors(SDL_Surface *surface, + SDL_Color *colors, int firstcolor, int ncolors); /** * Sets a portion of the colormap for a given 8-bit surface. @@ -483,8 +483,8 @@ * flags = (SDL_LOGPAL|SDL_PHYSPAL). */ extern DECLSPEC int SDLCALL SDL_SetPalette(SDL_Surface *surface, int flags, - SDL_Color *colors, int firstcolor, - int ncolors); + SDL_Color *colors, int firstcolor, + int ncolors); /** * Maps an RGB triple to an opaque pixel value for a given pixel format @@ -504,15 +504,15 @@ * Maps a pixel value into the RGB components for a given pixel format */ extern DECLSPEC void SDLCALL SDL_GetRGB(Uint32 pixel, - const SDL_PixelFormat * const fmt, - Uint8 *r, Uint8 *g, Uint8 *b); + const SDL_PixelFormat * const fmt, + Uint8 *r, Uint8 *g, Uint8 *b); /** * Maps a pixel value into the RGBA components for a given pixel format */ extern DECLSPEC void SDLCALL SDL_GetRGBA(Uint32 pixel, - const SDL_PixelFormat * const fmt, - Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a); + const SDL_PixelFormat * const fmt, + Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a); /** @sa SDL_CreateRGBSurface */ #define SDL_AllocSurface SDL_CreateRGBSurface @@ -537,7 +537,7 @@ * two surfaces in video memory, SDL will try to place the surface in * video memory. If this isn't possible or if there is no hardware * acceleration available, the surface will be placed in system memory. - * SDL_SRCALPHA means that the surface will be used for alpha blits and + * SDL_SRCALPHA means that the surface will be used for alpha blits and * if the hardware supports hardware acceleration of alpha blits between * two surfaces in video memory, to place the surface in video memory * if possible, otherwise it will be placed in system memory. @@ -551,19 +551,19 @@ * the SDL_HWSURFACE flag set, and will be created in system memory instead. */ extern DECLSPEC SDL_Surface * SDLCALL SDL_CreateRGBSurface - (Uint32 flags, int width, int height, int depth, - Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask); + (Uint32 flags, int width, int height, int depth, + Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask); /** @sa SDL_CreateRGBSurface */ extern DECLSPEC SDL_Surface * SDLCALL SDL_CreateRGBSurfaceFrom(void *pixels, - int width, int height, int depth, int pitch, - Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask); + int width, int height, int depth, int pitch, + Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask); extern DECLSPEC void SDLCALL SDL_FreeSurface(SDL_Surface *surface); /** * SDL_LockSurface() sets up a surface for directly accessing the pixels. * Between calls to SDL_LockSurface()/SDL_UnlockSurface(), you can write - * to and read from 'surface->pixels', using the pixel format stored in - * 'surface->format'. Once you are done accessing the surface, you should + * to and read from 'surface->pixels', using the pixel format stored in + * 'surface->format'. Once you are done accessing the surface, you should * use SDL_UnlockSurface() to release it. * * Not all surfaces require locking. If SDL_MUSTLOCK(surface) evaluates @@ -571,7 +571,7 @@ * pixel format of the surface will not change. In particular, if the * SDL_HWSURFACE flag is not given when calling SDL_SetVideoMode(), you * will not need to lock the display surface before accessing it. - * + * * No operating system or library calls should be made between lock/unlock * pairs, as critical system locks may be held during this time. * @@ -589,7 +589,7 @@ extern DECLSPEC SDL_Surface * SDLCALL SDL_LoadBMP_RW(SDL_RWops *src, int freesrc); /** Convenience macro -- load a surface from a file */ -#define SDL_LoadBMP(file) SDL_LoadBMP_RW(SDL_RWFromFile(file, "rb"), 1) +#define SDL_LoadBMP(file) SDL_LoadBMP_RW(SDL_RWFromFile(file, "rb"), 1) /** * Save a surface to a seekable SDL data source (memory or file.) @@ -597,15 +597,15 @@ * Returns 0 if successful or -1 if there was an error. */ extern DECLSPEC int SDLCALL SDL_SaveBMP_RW - (SDL_Surface *surface, SDL_RWops *dst, int freedst); + (SDL_Surface *surface, SDL_RWops *dst, int freedst); /** Convenience macro -- save a surface to a file */ #define SDL_SaveBMP(surface, file) \ - SDL_SaveBMP_RW(surface, SDL_RWFromFile(file, "wb"), 1) + SDL_SaveBMP_RW(surface, SDL_RWFromFile(file, "wb"), 1) /** * Sets the color key (transparent pixel) in a blittable surface. - * If 'flag' is SDL_SRCCOLORKEY (optionally OR'd with SDL_RLEACCEL), + * If 'flag' is SDL_SRCCOLORKEY (optionally OR'd with SDL_RLEACCEL), * 'key' will be the transparent pixel in the source image of a blit. * SDL_RLEACCEL requests RLE acceleration for the surface if present, * and removes RLE acceleration if absent. @@ -613,7 +613,7 @@ * This function returns 0, or -1 if there was an error. */ extern DECLSPEC int SDLCALL SDL_SetColorKey - (SDL_Surface *surface, Uint32 flag, Uint32 key); + (SDL_Surface *surface, Uint32 flag, Uint32 key); /** * This function sets the alpha value for the entire surface, as opposed to @@ -654,11 +654,11 @@ extern DECLSPEC void SDLCALL SDL_GetClipRect(SDL_Surface *surface, SDL_Rect *rect); /** - * Creates a new surface of the specified format, and then copies and maps - * the given surface to it so the blit of the converted surface will be as + * Creates a new surface of the specified format, and then copies and maps + * the given surface to it so the blit of the converted surface will be as * fast as possible. If this function fails, it returns NULL. * - * The 'flags' parameter is passed to SDL_CreateRGBSurface() and has those + * The 'flags' parameter is passed to SDL_CreateRGBSurface() and has those * semantics. You can also pass SDL_RLEACCEL in the flags parameter and * SDL will try to RLE accelerate colorkey and alpha blits in the resulting * surface. @@ -666,7 +666,7 @@ * This function is used internally by SDL_DisplayFormat(). */ extern DECLSPEC SDL_Surface * SDLCALL SDL_ConvertSurface - (SDL_Surface *src, SDL_PixelFormat *fmt, Uint32 flags); + (SDL_Surface *src, SDL_PixelFormat *fmt, Uint32 flags); /** * This performs a fast blit from the source surface to the destination @@ -683,54 +683,54 @@ * * RGBA->RGB: * SDL_SRCALPHA set: - * alpha-blend (using alpha-channel). - * SDL_SRCCOLORKEY ignored. + * alpha-blend (using alpha-channel). + * SDL_SRCCOLORKEY ignored. * SDL_SRCALPHA not set: - * copy RGB. - * if SDL_SRCCOLORKEY set, only copy the pixels matching the - * RGB values of the source colour key, ignoring alpha in the - * comparison. - * + * copy RGB. + * if SDL_SRCCOLORKEY set, only copy the pixels matching the + * RGB values of the source colour key, ignoring alpha in the + * comparison. + * * RGB->RGBA: * SDL_SRCALPHA set: - * alpha-blend (using the source per-surface alpha value); - * set destination alpha to opaque. + * alpha-blend (using the source per-surface alpha value); + * set destination alpha to opaque. * SDL_SRCALPHA not set: - * copy RGB, set destination alpha to source per-surface alpha value. + * copy RGB, set destination alpha to source per-surface alpha value. * both: - * if SDL_SRCCOLORKEY set, only copy the pixels matching the - * source colour key. - * + * if SDL_SRCCOLORKEY set, only copy the pixels matching the + * source colour key. + * * RGBA->RGBA: * SDL_SRCALPHA set: - * alpha-blend (using the source alpha channel) the RGB values; - * leave destination alpha untouched. [Note: is this correct?] - * SDL_SRCCOLORKEY ignored. + * alpha-blend (using the source alpha channel) the RGB values; + * leave destination alpha untouched. [Note: is this correct?] + * SDL_SRCCOLORKEY ignored. * SDL_SRCALPHA not set: - * copy all of RGBA to the destination. - * if SDL_SRCCOLORKEY set, only copy the pixels matching the - * RGB values of the source colour key, ignoring alpha in the - * comparison. - * - * RGB->RGB: + * copy all of RGBA to the destination. + * if SDL_SRCCOLORKEY set, only copy the pixels matching the + * RGB values of the source colour key, ignoring alpha in the + * comparison. + * + * RGB->RGB: * SDL_SRCALPHA set: - * alpha-blend (using the source per-surface alpha value). + * alpha-blend (using the source per-surface alpha value). * SDL_SRCALPHA not set: - * copy RGB. + * copy RGB. * both: - * if SDL_SRCCOLORKEY set, only copy the pixels matching the - * source colour key. + * if SDL_SRCCOLORKEY set, only copy the pixels matching the + * source colour key. * * If either of the surfaces were in video memory, and the blit returns -2, - * the video memory was lost, so it should be reloaded with artwork and + * the video memory was lost, so it should be reloaded with artwork and * re-blitted: * @code - * while ( SDL_BlitSurface(image, imgrect, screen, dstrect) == -2 ) { - * while ( SDL_LockSurface(image) < 0 ) - * Sleep(10); - * -- Write image pixels to image->pixels -- - * SDL_UnlockSurface(image); - * } + * while ( SDL_BlitSurface(image, imgrect, screen, dstrect) == -2 ) { + * while ( SDL_LockSurface(image) < 0 ) + * Sleep(10); + * -- Write image pixels to image->pixels -- + * SDL_UnlockSurface(image); + * } * @endcode * * This happens under DirectX 5.0 when the system switches away from your @@ -746,26 +746,26 @@ * rectangle validation and clipping before passing it to SDL_LowerBlit() */ extern DECLSPEC int SDLCALL SDL_UpperBlit - (SDL_Surface *src, SDL_Rect *srcrect, - SDL_Surface *dst, SDL_Rect *dstrect); + (SDL_Surface *src, SDL_Rect *srcrect, + SDL_Surface *dst, SDL_Rect *dstrect); /** This is a semi-private blit function and it performs low-level surface * blitting only. */ extern DECLSPEC int SDLCALL SDL_LowerBlit - (SDL_Surface *src, SDL_Rect *srcrect, - SDL_Surface *dst, SDL_Rect *dstrect); + (SDL_Surface *src, SDL_Rect *srcrect, + SDL_Surface *dst, SDL_Rect *dstrect); /** * This function performs a fast fill of the given rectangle with 'color' * The given rectangle is clipped to the destination surface clip area * and the final fill rectangle is saved in the passed in pointer. * If 'dstrect' is NULL, the whole surface will be filled with 'color' - * The color should be a pixel of the format used by the surface, and + * The color should be a pixel of the format used by the surface, and * can be generated by the SDL_MapRGB() function. * This function returns 0 on success, or -1 on error. */ extern DECLSPEC int SDLCALL SDL_FillRect - (SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color); + (SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color); /** * This function takes a surface and copies it to a new surface of the @@ -805,7 +805,7 @@ * is shown is undefined - it may be overwritten with the converted YUV data. */ extern DECLSPEC SDL_Overlay * SDLCALL SDL_CreateYUVOverlay(int width, int height, - Uint32 format, SDL_Surface *display); + Uint32 format, SDL_Surface *display); /** Lock an overlay for direct access, and unlock it when you are done */ extern DECLSPEC int SDLCALL SDL_LockYUVOverlay(SDL_Overlay *overlay); @@ -813,7 +813,7 @@ /** Blit a video overlay to the display surface. * The contents of the video surface underneath the blit destination are - * not defined. + * not defined. * The width and height of the destination rectangle may be different from * that of the overlay, but currently only 2x scaling is supported. */ @@ -908,7 +908,7 @@ * If the display surface does not require locking before accessing * the pixel information, then the memory pointers will not change. * - * If this function was able to toggle fullscreen mode (change from + * If this function was able to toggle fullscreen mode (change from * running in a window to fullscreen, or vice-versa), it will return 1. * If it is not implemented, or fails, it returns 0. * @@ -921,10 +921,10 @@ extern DECLSPEC int SDLCALL SDL_WM_ToggleFullScreen(SDL_Surface *surface); typedef enum { - SDL_GRAB_QUERY = -1, - SDL_GRAB_OFF = 0, - SDL_GRAB_ON = 1, - SDL_GRAB_FULLSCREEN /**< Used internally */ + SDL_GRAB_QUERY = -1, + SDL_GRAB_OFF = 0, + SDL_GRAB_ON = 1, + SDL_GRAB_FULLSCREEN /**< Used internally */ } SDL_GrabMode; /** * This function allows you to set and query the input grab state of @@ -941,7 +941,7 @@ /** @internal Not in public API at the moment - do not use! */ extern DECLSPEC int SDLCALL SDL_SoftStretch(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect); - + /* Ends C function definitions when using C++ */ #ifdef __cplusplus } diff -r 31570b766315 -r ed5a6478e710 misc/winutils/include/begin_code.h --- a/misc/winutils/include/begin_code.h Tue Nov 10 18:16:35 2015 +0100 +++ b/misc/winutils/include/begin_code.h Tue Nov 10 20:43:13 2015 +0100 @@ -20,14 +20,14 @@ slouken@libsdl.org */ -/** +/** * @file begin_code.h * This file sets things up for C dynamic library function definitions, * static inlined functions, and structures aligned at 4-byte alignment. * If you don't like ugly C preprocessor code, don't look at this file. :) */ -/** +/** * @file begin_code.h * This shouldn't be nested -- included it around code only. */ @@ -36,7 +36,7 @@ #endif #define _begin_code_h -/** +/** * @def DECLSPEC * Some compilers use a special export keyword */ @@ -45,22 +45,22 @@ # if defined(__GNUC__) # define DECLSPEC # else -# define DECLSPEC __declspec(export) +# define DECLSPEC __declspec(export) # endif # elif defined(__WIN32__) # ifdef __BORLANDC__ # ifdef BUILD_SDL -# define DECLSPEC +# define DECLSPEC # else -# define DECLSPEC __declspec(dllimport) +# define DECLSPEC __declspec(dllimport) # endif # else -# define DECLSPEC __declspec(dllexport) +# define DECLSPEC __declspec(dllexport) # endif # elif defined(__OS2__) # ifdef __WATCOMC__ # ifdef BUILD_SDL -# define DECLSPEC __declspec(dllexport) +# define DECLSPEC __declspec(dllexport) # else # define DECLSPEC # endif @@ -78,14 +78,14 @@ # endif # else # if defined(__GNUC__) && __GNUC__ >= 4 -# define DECLSPEC __attribute__ ((visibility("default"))) +# define DECLSPEC __attribute__ ((visibility("default"))) # else # define DECLSPEC # endif # endif #endif -/** +/** * @def SDLCALL * By default SDL uses the C calling convention */ @@ -108,8 +108,8 @@ # endif #endif /* SDLCALL */ -#ifdef __SYMBIAN32__ -#ifndef EKA2 +#ifdef __SYMBIAN32__ +#ifndef EKA2 #undef DECLSPEC #define DECLSPEC #elif !defined(__WINS__) @@ -123,7 +123,7 @@ * Force structure packing at 4 byte alignment. * This is necessary if the header is included in code which has structure * packing set to an alternate value, say for loading structures from disk. - * The packing is reset to the previous value in close_code.h + * The packing is reset to the previous value in close_code.h */ #if defined(_MSC_VER) || defined(__MWERKS__) || defined(__BORLANDC__) #ifdef _MSC_VER @@ -157,7 +157,7 @@ defined(__WATCOMC__) || defined(__LCC__) || \ defined(__DECC) || defined(__EABI__) #ifndef __inline__ -#define __inline__ __inline +#define __inline__ __inline #endif #define SDL_INLINE_OKAY #else diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/CMakeLists.txt --- a/project_files/Android-build/CMakeLists.txt Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/CMakeLists.txt Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ################################################################################### find_program(ANT ant DOC "Path to the java package creator: ant") @@ -26,8 +26,8 @@ endif() if(IS_DIRECTORY "${ANDROID_NDK}") - message(STATUS "Detected the android NDK directory at: " ${ANDROID_NDK}) -else () + message(STATUS "Detected the android NDK directory at: " ${ANDROID_NDK}) +else() message(FATAL_ERROR "Couldn't detect the Android NDK directory") endif() @@ -39,35 +39,35 @@ endif() if(IS_DIRECTORY "${ANDROID_NDK_TOOLCHAINDIR}") - message(STATUS "Detected the Android NDK toolchain at: ${ANDROID_NDK_TOOLCHAINDIR}") -else () + message(STATUS "Detected the Android NDK toolchain at: ${ANDROID_NDK_TOOLCHAINDIR}") +else() message(FATAL_ERROR "Couldn't detect the Android NDK toolchain directory: ${ANDROID_NDK_TOOLCHAINDIR}") endif() -if(NOT ANDROID_SDK)#Check if its defined at the cmdline +if(NOT ANDROID_SDK) #Check if its defined at the cmdline find_program(ANDROID_SDK adb) #assume they've added platform-tools to their path get_filename_component(ANDROID_SDK "${ANDROID_SDK}" PATH) get_filename_component(ANDROID_SDK "${ANDROID_SDK}" PATH) set(ANDROID_SDK "${ANDROID_SDK}" CACHE PATH "Path to the android sdk" FORCE) endif() -if( IS_DIRECTORY "${ANDROID_SDK}") - message(STATUS "Detected the android SDK directory at: " ${ANDROID_SDK}) -else () +if(IS_DIRECTORY "${ANDROID_SDK}") + message(STATUS "Detected the android SDK directory at: " ${ANDROID_SDK}) +else() message(FATAL_ERROR "Couldn't detect the Android SDK directory") endif() -if( NOT FPC_DIR) +if(NOT FPC_DIR) find_program(FPC_DIR ppcrossarm) get_filename_component(FPC_DIR "${FPC_DIR}" PATH) - if(IS_DIRECTORY "${FPC_DIR}") - set(FPC_DIR "${FPC_DIR}" CACHE PATH "Path to fpc dir used in the android port" FORCE) + if(IS_DIRECTORY "${FPC_DIR}") + set(FPC_DIR "${FPC_DIR}" CACHE PATH "Path to fpc dir used in the android port" FORCE) endif() endif() -if( IS_DIRECTORY "${FPC_DIR}") - message(STATUS "Detected the FreePascal directory at: " "${FPC_DIR}") -else () +if(IS_DIRECTORY "${FPC_DIR}") + message(STATUS "Detected the FreePascal directory at: ${FPC_DIR}") +else() message(FATAL_ERROR "Couldn't detect the FreePascal directory") endif() diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/AndroidManifest.xml --- a/project_files/Android-build/SDL-android-project/AndroidManifest.xml Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/AndroidManifest.xml Tue Nov 10 20:43:13 2015 +0100 @@ -46,7 +46,7 @@ android:theme="@android:style/Theme.NoTitleBar.Fullscreen" /> - + GetStaticMethodID(mActivityClass, "flipBuffers","()V"); - midAudioInit = mEnv->GetStaticMethodID(mActivityClass, + midAudioInit = mEnv->GetStaticMethodID(mActivityClass, "audioInit", "(IZZI)Ljava/lang/Object;"); midAudioWriteShortBuffer = mEnv->GetStaticMethodID(mActivityClass, "audioWriteShortBuffer", "([S)V"); @@ -165,7 +165,7 @@ // Quit extern "C" void Java_org_hedgewars_hedgeroid_SDLActivity_nativeQuit( JNIEnv* env, jclass cls) -{ +{ // Inject a SDL_QUIT event SDL_SendQuit(); } @@ -214,7 +214,7 @@ extern "C" void Android_JNI_SwapWindow() { - mEnv->CallStaticVoidMethod(mActivityClass, midFlipBuffers); + mEnv->CallStaticVoidMethod(mActivityClass, midFlipBuffers); } extern "C" void Android_JNI_SetActivityTitle(const char *title) @@ -257,7 +257,7 @@ int status; JNIEnv *env; - static bool isAttached = false; + static bool isAttached = false; status = mJavaVM->GetEnv((void **) &env, JNI_VERSION_1_4); if(status < 0) { LOGE("callback_handler: failed to get JNI environment, assuming native thread"); @@ -269,7 +269,7 @@ isAttached = true; } - + __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "SDL audio: opening device"); audioBuffer16Bit = is16Bit; audioBufferStereo = channelCount > 1; @@ -293,7 +293,7 @@ if (audioBufferStereo) { audioBufferFrames /= 2; } - + if (isAttached) { mJavaVM->DetachCurrentThread(); } @@ -323,7 +323,7 @@ { int status; JNIEnv *env; - static bool isAttached = false; + static bool isAttached = false; status = mJavaVM->GetEnv((void **) &env, JNI_VERSION_1_4); if(status < 0) { LOGE("callback_handler: failed to get JNI environment, assuming native thread"); @@ -335,7 +335,7 @@ isAttached = true; } - env->CallStaticVoidMethod(mActivityClass, midAudioQuit); + env->CallStaticVoidMethod(mActivityClass, midAudioQuit); if (audioBuffer) { env->DeleteGlobalRef(audioBuffer); diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/jni/SDL/src/file/SDL_rwops.c --- a/project_files/Android-build/SDL-android-project/jni/SDL/src/file/SDL_rwops.c Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/jni/SDL/src/file/SDL_rwops.c Tue Nov 10 20:43:13 2015 +0100 @@ -45,7 +45,7 @@ /* Functions to read/write Win32 API file pointers */ /* Will not use it on WinCE because stdio is buffered, it means - faster, and all stdio functions anyway are embedded in coredll.dll - + faster, and all stdio functions anyway are embedded in coredll.dll - the main wince dll*/ #include "../core/windows/SDL_windows.h" @@ -54,7 +54,7 @@ #define INVALID_SET_FILE_POINTER 0xFFFFFFFF #endif -#define READAHEAD_BUFFER_SIZE 1024 +#define READAHEAD_BUFFER_SIZE 1024 static int SDLCALL windows_file_open(SDL_RWops * context, const char *filename, const char *mode) @@ -473,12 +473,12 @@ rwops->close = windows_file_close; #elif HAVE_STDIO_H - #ifdef __APPLE__ - fp = SDL_OpenFPFromBundleOrFallback(file, mode); + #ifdef __APPLE__ + fp = SDL_OpenFPFromBundleOrFallback(file, mode); #else - fp = fopen(file, mode); - #endif - if (fp == NULL) { + fp = fopen(file, mode); + #endif + if (fp == NULL) { SDL_SetError("Couldn't open %s", file); } else { rwops = SDL_RWFromFP(fp, 1); diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/jni/SDL/src/main/android/SDL_android_main.cpp --- a/project_files/Android-build/SDL-android-project/jni/SDL/src/main/android/SDL_android_main.cpp Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/jni/SDL/src/main/android/SDL_android_main.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -27,19 +27,19 @@ char *argv[argc]; jstring jstringArgv[argc]; for(int i = 0; i < argc; i++){ - jstringArgv[i] = (jstring)env->GetObjectArrayElement(strArray, i); //get the element - argv[i] = (char*)malloc(env->GetStringUTFLength(jstringArgv[i]) + 1); - const char *str = env->GetStringUTFChars(jstringArgv[i], NULL); - strcpy(argv[i], str); //copy it to a mutable location - env->ReleaseStringUTFChars(jstringArgv[i], str); + jstringArgv[i] = (jstring)env->GetObjectArrayElement(strArray, i); //get the element + argv[i] = (char*)malloc(env->GetStringUTFLength(jstringArgv[i]) + 1); + const char *str = env->GetStringUTFChars(jstringArgv[i], NULL); + strcpy(argv[i], str); //copy it to a mutable location + env->ReleaseStringUTFChars(jstringArgv[i], str); } - + /* Run the application code! */ int status = SDL_main(argc, argv); //Clean up argv for(int i = 0; i < argc; i++){ - free(argv[i]); + free(argv[i]); } } diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/jni/SDL_mixer/Android.mk --- a/project_files/Android-build/SDL-android-project/jni/SDL_mixer/Android.mk Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/jni/SDL_mixer/Android.mk Tue Nov 10 20:43:13 2015 +0100 @@ -5,9 +5,9 @@ LOCAL_MODULE := SDL_mixer LOCAL_C_INCLUDES := \ - $(LOCAL_PATH)/.. \ - $(LOCAL_PATH)/../SDL/include \ - $(LOCAL_PATH)/../mikmod/include \ + $(LOCAL_PATH)/.. \ + $(LOCAL_PATH)/../SDL/include \ + $(LOCAL_PATH)/../mikmod/include \ LOCAL_CFLAGS := -DWAV_MUSIC -DOGG_MUSIC -DOGG_USE_TREMOR -DMOD_MUSIC diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/jni/jnidispatch/Android.mk --- a/project_files/Android-build/SDL-android-project/jni/jnidispatch/Android.mk Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/jni/jnidispatch/Android.mk Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ -LOCAL_PATH := $(call my-dir) - -include $(CLEAR_VARS) -LOCAL_MODULE := libjnidispatch -LOCAL_SRC_FILES := libjnidispatch.so +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_MODULE := libjnidispatch +LOCAL_SRC_FILES := libjnidispatch.so include $(PREBUILT_SHARED_LIBRARY) \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/jni/src/Android.mk --- a/project_files/Android-build/SDL-android-project/jni/src/Android.mk Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/jni/src/Android.mk Tue Nov 10 20:43:13 2015 +0100 @@ -7,7 +7,7 @@ LOCAL_C_INCLUDES := $(LOCAL_PATH)/../SDL/include # Add your application source files here... -LOCAL_SRC_FILES := ../SDL/src/main/android/SDL_android_main.cpp hedgewars_main.c +LOCAL_SRC_FILES := ../SDL/src/main/android/SDL_android_main.cpp hedgewars_main.c LOCAL_SHARED_LIBRARIES := SDL diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/jni/src/hedgewars_main.c --- a/project_files/Android-build/SDL-android-project/jni/src/hedgewars_main.c Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/jni/src/hedgewars_main.c Tue Nov 10 20:43:13 2015 +0100 @@ -10,32 +10,32 @@ typedef (*HWEngine_Game)(int32_t argc, char** argv); main(int argc, char *argv[]){ - void *handle; - char *error; - HWEngine_Game Game; - + void *handle; + char *error; + HWEngine_Game Game; + __android_log_print(ANDROID_LOG_INFO, TAG, "HWEngine being loaded"); - handle = dlopen("libhwengine.so", RTLD_NOW|RTLD_GLOBAL); - if(!handle){ - __android_log_print(ANDROID_LOG_INFO, TAG, dlerror()); - __android_log_print(ANDROID_LOG_INFO, TAG, "error dlopen"); - exit(EXIT_FAILURE); - } - dlerror(); + handle = dlopen("libhwengine.so", RTLD_NOW|RTLD_GLOBAL); + if(!handle){ + __android_log_print(ANDROID_LOG_INFO, TAG, dlerror()); + __android_log_print(ANDROID_LOG_INFO, TAG, "error dlopen"); + exit(EXIT_FAILURE); + } + dlerror(); __android_log_print(ANDROID_LOG_INFO, TAG, "HWEngine successfully loaded.."); - Game = (HWEngine_Game) dlsym(handle,"Game"); - if((error = dlerror()) != NULL){ - __android_log_print(ANDROID_LOG_INFO, TAG, error); - __android_log_print(ANDROID_LOG_INFO, TAG, "error dlsym"); - exit(EXIT_FAILURE); - } - __android_log_print(ANDROID_LOG_INFO, TAG, "dlsym succeeded"); - Game(argc, argv); - __android_log_print(ANDROID_LOG_INFO, TAG, "Game() ended"); + Game = (HWEngine_Game) dlsym(handle,"Game"); + if((error = dlerror()) != NULL){ + __android_log_print(ANDROID_LOG_INFO, TAG, error); + __android_log_print(ANDROID_LOG_INFO, TAG, "error dlsym"); + exit(EXIT_FAILURE); + } + __android_log_print(ANDROID_LOG_INFO, TAG, "dlsym succeeded"); + Game(argc, argv); + __android_log_print(ANDROID_LOG_INFO, TAG, "Game() ended"); - dlclose(handle); + dlclose(handle); } diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/res/raw/team_one.hwt --- a/project_files/Android-build/SDL-android-project/res/raw/team_one.hwt Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/res/raw/team_one.hwt Tue Nov 10 20:43:13 2015 +0100 @@ -1,74 +1,74 @@ -[Team] -Name=Team 1 -Grave=Bone -Fort=Lego -Voicepack=Classic -Flag=hedgewars -Difficulty=0 -Rounds=0 -Wins=0 -CampaignProgress=0 - -[Hedgehog0] -Name=Leonidas -Hat=NoHat -Rounds=0 -Kills=0 -Deaths=0 -Suicides=0 - -[Hedgehog1] -Name=Pipo -Hat=NoHat -Rounds=0 -Kills=0 -Deaths=0 -Suicides=0 - -[Hedgehog2] -Name=Sonic -Hat=NoHat -Rounds=0 -Kills=0 -Deaths=0 -Suicides=0 - -[Hedgehog3] -Name=Xin -Hat=NoHat -Rounds=0 -Kills=0 -Deaths=0 -Suicides=0 - -[Hedgehog4] -Name=Arnold -Hat=NoHat -Rounds=0 -Kills=0 -Deaths=0 -Suicides=0 - -[Hedgehog5] -Name=Jack -Hat=NoHat -Rounds=0 -Kills=0 -Deaths=0 -Suicides=0 - -[Hedgehog6] -Name=Tom -Hat=NoHat -Rounds=0 -Kills=0 -Deaths=0 -Suicides=0 - -[Hedgehog7] -Name=Goldie -Hat=NoHat -Rounds=0 -Kills=0 -Deaths=0 -Suicides=0 +[Team] +Name=Team 1 +Grave=Bone +Fort=Lego +Voicepack=Classic +Flag=hedgewars +Difficulty=0 +Rounds=0 +Wins=0 +CampaignProgress=0 + +[Hedgehog0] +Name=Leonidas +Hat=NoHat +Rounds=0 +Kills=0 +Deaths=0 +Suicides=0 + +[Hedgehog1] +Name=Pipo +Hat=NoHat +Rounds=0 +Kills=0 +Deaths=0 +Suicides=0 + +[Hedgehog2] +Name=Sonic +Hat=NoHat +Rounds=0 +Kills=0 +Deaths=0 +Suicides=0 + +[Hedgehog3] +Name=Xin +Hat=NoHat +Rounds=0 +Kills=0 +Deaths=0 +Suicides=0 + +[Hedgehog4] +Name=Arnold +Hat=NoHat +Rounds=0 +Kills=0 +Deaths=0 +Suicides=0 + +[Hedgehog5] +Name=Jack +Hat=NoHat +Rounds=0 +Kills=0 +Deaths=0 +Suicides=0 + +[Hedgehog6] +Name=Tom +Hat=NoHat +Rounds=0 +Kills=0 +Deaths=0 +Suicides=0 + +[Hedgehog7] +Name=Goldie +Hat=NoHat +Rounds=0 +Kills=0 +Deaths=0 +Suicides=0 diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/res/raw/team_two.hwt --- a/project_files/Android-build/SDL-android-project/res/raw/team_two.hwt Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/res/raw/team_two.hwt Tue Nov 10 20:43:13 2015 +0100 @@ -1,74 +1,74 @@ -[Team] -Name=Team 2 -Grave=Bone -Fort=Lego -Voicepack=Classic -Flag=cm_binary -Difficulty=2 -Rounds=0 -Wins=0 -CampaignProgress=0 - -[Hedgehog0] -Name=Paris -Hat=NoHat -Rounds=0 -Kills=0 -Deaths=0 -Suicides=0 - -[Hedgehog1] -Name=Knut -Hat=NoHat -Rounds=0 -Kills=0 -Deaths=0 -Suicides=0 - -[Hedgehog2] -Name=Ash -Hat=NoHat -Rounds=0 -Kills=0 -Deaths=0 -Suicides=0 - -[Hedgehog3] -Name=Woad -Hat=NoHat -Rounds=0 -Kills=0 -Deaths=0 -Suicides=0 - -[Hedgehog4] -Name=Bob -Hat=NoHat -Rounds=0 -Kills=0 -Deaths=0 -Suicides=0 - -[Hedgehog5] -Name=Corky -Hat=NoHat -Rounds=0 -Kills=0 -Deaths=0 -Suicides=0 - -[Hedgehog6] -Name=Bea -Hat=NoHat -Rounds=0 -Kills=0 -Deaths=0 -Suicides=0 - -[Hedgehog7] -Name=Silvia -Hat=NoHat -Rounds=0 -Kills=0 -Deaths=0 -Suicides=0 +[Team] +Name=Team 2 +Grave=Bone +Fort=Lego +Voicepack=Classic +Flag=cm_binary +Difficulty=2 +Rounds=0 +Wins=0 +CampaignProgress=0 + +[Hedgehog0] +Name=Paris +Hat=NoHat +Rounds=0 +Kills=0 +Deaths=0 +Suicides=0 + +[Hedgehog1] +Name=Knut +Hat=NoHat +Rounds=0 +Kills=0 +Deaths=0 +Suicides=0 + +[Hedgehog2] +Name=Ash +Hat=NoHat +Rounds=0 +Kills=0 +Deaths=0 +Suicides=0 + +[Hedgehog3] +Name=Woad +Hat=NoHat +Rounds=0 +Kills=0 +Deaths=0 +Suicides=0 + +[Hedgehog4] +Name=Bob +Hat=NoHat +Rounds=0 +Kills=0 +Deaths=0 +Suicides=0 + +[Hedgehog5] +Name=Corky +Hat=NoHat +Rounds=0 +Kills=0 +Deaths=0 +Suicides=0 + +[Hedgehog6] +Name=Bea +Hat=NoHat +Rounds=0 +Kills=0 +Deaths=0 +Suicides=0 + +[Hedgehog7] +Name=Silvia +Hat=NoHat +Rounds=0 +Kills=0 +Deaths=0 +Suicides=0 diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/res/raw/weapons_builtin.ini --- a/project_files/Android-build/SDL-android-project/res/raw/weapons_builtin.ini Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/res/raw/weapons_builtin.ini Tue Nov 10 20:43:13 2015 +0100 @@ -1,8 +1,8 @@ -[General] -%44efault=9391929422199121032235111001201000000211110101011111011040504054160065554655446477657666666615551010111541101100000000000002055000000400070040000000002200000006000001311110312111111123114111111111111111211111101111111010 -%43razy=9999999999999999992999999999999999299999999909999992099111111011111111111111111111111111111111111110111111101100000000000000000000000000000000000000000000000000000001311110312111111123114111111111111111211110101111111011 -%50ro%20%4dode=9090009000000000000009000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002055000000400070040000000002000000000000001111111111111111111111111111111111111111100101111111011 -%53hoppa=0000009900000000000000000000000000000000000000000000000444441004424440221011212122242200000000200040001001100000000000000000000000000000000000000000000000000000000001111111111111111111111111111111111111111101101111111001 -%43lean%20%53late=1010009000010000011000000000000000000000000000001000000040504054160065554655446477657666666615551010111541101100000000000000000000000000000000000000000000000000000001311110312111111123114111111111111111211111101111111011 -%4dinefield=0000009900090000000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002055000000400070040000000002000000006000001111111111111111111111111111111111111111111101111111011 -%54hinking%20with%20%50ortals=9000009002000000002100000000000000110000090000000000000040504054160065554655446477657666666615551010111541101100000000000002055000000400070040000000002000000006000001311110312111111123114111111111111111211111101111111011 +[General] +%44efault=9391929422199121032235111001201000000211110101011111011040504054160065554655446477657666666615551010111541101100000000000002055000000400070040000000002200000006000001311110312111111123114111111111111111211111101111111010 +%43razy=9999999999999999992999999999999999299999999909999992099111111011111111111111111111111111111111111110111111101100000000000000000000000000000000000000000000000000000001311110312111111123114111111111111111211110101111111011 +%50ro%20%4dode=9090009000000000000009000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002055000000400070040000000002000000000000001111111111111111111111111111111111111111100101111111011 +%53hoppa=0000009900000000000000000000000000000000000000000000000444441004424440221011212122242200000000200040001001100000000000000000000000000000000000000000000000000000000001111111111111111111111111111111111111111101101111111001 +%43lean%20%53late=1010009000010000011000000000000000000000000000001000000040504054160065554655446477657666666615551010111541101100000000000000000000000000000000000000000000000000000001311110312111111123114111111111111111211111101111111011 +%4dinefield=0000009900090000000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002055000000400070040000000002000000006000001111111111111111111111111111111111111111111101111111011 +%54hinking%20with%20%50ortals=9000009002000000002100000000000000110000090000000000000040504054160065554655446477657666666615551010111541101100000000000002055000000400070040000000002000000006000001311110312111111123114111111111111111211111101111111011 diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/BasicRoomState.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/BasicRoomState.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/BasicRoomState.java Tue Nov 10 20:43:13 2015 +0100 @@ -37,125 +37,125 @@ * Common base implementation for a roomstate that will call listeners on every * change. The derived classes have to coordinate how state is changed to * complete the implementation of the RoomStateManager interface. - * + * * See {@link RoomStateManager} for a description of what this is for. */ public abstract class BasicRoomState implements RoomStateManager { - private final List observers = new LinkedList(); - - private boolean chief; - private String gameStyle; - private Scheme scheme; - private MapRecipe map; - private Weaponset weaponset; - private Map teams = Collections.emptyMap(); - - public final MapRecipe getMapRecipe() { - return map; - } + private final List observers = new LinkedList(); + + private boolean chief; + private String gameStyle; + private Scheme scheme; + private MapRecipe map; + private Weaponset weaponset; + private Map teams = Collections.emptyMap(); + + public final MapRecipe getMapRecipe() { + return map; + } + + public final boolean getChiefStatus() { + return chief; + } + + public final Scheme getScheme() { + return scheme; + } + + public final String getGameStyle() { + return gameStyle; + } - public final boolean getChiefStatus() { - return chief; - } + public final Weaponset getWeaponset() { + return weaponset; + } + + public final Map getTeams() { + return teams; + } - public final Scheme getScheme() { - return scheme; - } + public final void setWeaponset(Weaponset weaponset) { + if(!equal(weaponset, this.weaponset)) { + this.weaponset = weaponset; + for(RoomStateManager.Listener observer : observers) { + observer.onWeaponsetChanged(weaponset); + } + } + } - public final String getGameStyle() { - return gameStyle; - } + public final void setMapRecipe(MapRecipe map) { + if(!equal(map, this.map)) { + this.map = map; + for(RoomStateManager.Listener observer : observers) { + observer.onMapChanged(map); + } + } + } - public final Weaponset getWeaponset() { - return weaponset; - } - - public final Map getTeams() { - return teams; - } - - public final void setWeaponset(Weaponset weaponset) { - if(!equal(weaponset, this.weaponset)) { - this.weaponset = weaponset; - for(RoomStateManager.Listener observer : observers) { - observer.onWeaponsetChanged(weaponset); - } - } - } - - public final void setMapRecipe(MapRecipe map) { - if(!equal(map, this.map)) { - this.map = map; - for(RoomStateManager.Listener observer : observers) { - observer.onMapChanged(map); - } - } - } - - public final void setGameStyle(String gameStyle) { - if(!equal(gameStyle, this.gameStyle)) { - this.gameStyle = gameStyle; - for(RoomStateManager.Listener observer : observers) { - observer.onGameStyleChanged(gameStyle); - } - } - } - - public final void setScheme(Scheme scheme) { - if(!equal(scheme, this.scheme)) { - this.scheme = scheme; - for(RoomStateManager.Listener observer : observers) { - observer.onSchemeChanged(scheme); - } - } - } - - public final void setChief(boolean chief) { - if(chief != this.chief) { - this.chief = chief; - for(RoomStateManager.Listener observer : observers) { - observer.onChiefStatusChanged(chief); - } - } - } - - public final void putTeam(TeamInGame team) { - TeamInGame oldEntry = teams.get(team.team.name); - if(!equal(team, oldEntry)) { - Map changedMap = new TreeMap(teams); - changedMap.put(team.team.name, team); - teams = Collections.unmodifiableMap(changedMap); - for(RoomStateManager.Listener observer : observers) { - observer.onTeamsChanged(teams); - } - } - } - - public final void removeTeam(String teamname) { - if(teams.containsKey(teamname)) { - Map changedMap = new TreeMap(teams); - changedMap.remove(teamname); - teams = Collections.unmodifiableMap(changedMap); - for(RoomStateManager.Listener observer : observers) { - observer.onTeamsChanged(teams); - } - } - } - - public final void setTeams(Map newTeams) { - if(!newTeams.equals(teams)) { - teams = Collections.unmodifiableMap(new TreeMap(newTeams)); - for(RoomStateManager.Listener observer : observers) { - observer.onTeamsChanged(teams); - } - } - } - - public final void addListener(Listener observer) { - observers.add(observer); - } + public final void setGameStyle(String gameStyle) { + if(!equal(gameStyle, this.gameStyle)) { + this.gameStyle = gameStyle; + for(RoomStateManager.Listener observer : observers) { + observer.onGameStyleChanged(gameStyle); + } + } + } + + public final void setScheme(Scheme scheme) { + if(!equal(scheme, this.scheme)) { + this.scheme = scheme; + for(RoomStateManager.Listener observer : observers) { + observer.onSchemeChanged(scheme); + } + } + } + + public final void setChief(boolean chief) { + if(chief != this.chief) { + this.chief = chief; + for(RoomStateManager.Listener observer : observers) { + observer.onChiefStatusChanged(chief); + } + } + } - public final void removeListener(Listener observer) { - observers.remove(observer); - } + public final void putTeam(TeamInGame team) { + TeamInGame oldEntry = teams.get(team.team.name); + if(!equal(team, oldEntry)) { + Map changedMap = new TreeMap(teams); + changedMap.put(team.team.name, team); + teams = Collections.unmodifiableMap(changedMap); + for(RoomStateManager.Listener observer : observers) { + observer.onTeamsChanged(teams); + } + } + } + + public final void removeTeam(String teamname) { + if(teams.containsKey(teamname)) { + Map changedMap = new TreeMap(teams); + changedMap.remove(teamname); + teams = Collections.unmodifiableMap(changedMap); + for(RoomStateManager.Listener observer : observers) { + observer.onTeamsChanged(teams); + } + } + } + + public final void setTeams(Map newTeams) { + if(!newTeams.equals(teams)) { + teams = Collections.unmodifiableMap(new TreeMap(newTeams)); + for(RoomStateManager.Listener observer : observers) { + observer.onTeamsChanged(teams); + } + } + } + + public final void addListener(Listener observer) { + observers.add(observer); + } + + public final void removeListener(Listener observer) { + observers.remove(observer); + } } diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/ChatFragment.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/ChatFragment.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/ChatFragment.java Tue Nov 10 20:43:13 2015 +0100 @@ -39,61 +39,61 @@ * the lobby or a room. */ public class ChatFragment extends Fragment { - private ChatlogAdapter adapter; - private Netplay netplay; - private MessageLog messageLog; - private boolean inRoom; - - public void setInRoom(boolean inRoom) { - this.inRoom = inRoom; - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - netplay = Netplay.getAppInstance(getActivity().getApplicationContext()); - adapter = new ChatlogAdapter(getActivity()); - } - - @Override - public void onStart() { - super.onStart(); - messageLog = inRoom ? netplay.roomChatlog : netplay.lobbyChatlog; - adapter.setLog(messageLog.getLog()); - messageLog.addListener(adapter); - } - - @Override - public void onStop() { - super.onStop(); - messageLog.removeListener(adapter); - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.fragment_chat, container, false); - - ListView listView = (ListView) view.findViewById(R.id.chatConsole); - listView.setAdapter(adapter); - listView.setDivider(null); - listView.setDividerHeight(0); - listView.setVerticalFadingEdgeEnabled(true); - - EditText editText = (EditText) view.findViewById(R.id.chatInput); + private ChatlogAdapter adapter; + private Netplay netplay; + private MessageLog messageLog; + private boolean inRoom; + + public void setInRoom(boolean inRoom) { + this.inRoom = inRoom; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + netplay = Netplay.getAppInstance(getActivity().getApplicationContext()); + adapter = new ChatlogAdapter(getActivity()); + } + + @Override + public void onStart() { + super.onStart(); + messageLog = inRoom ? netplay.roomChatlog : netplay.lobbyChatlog; + adapter.setLog(messageLog.getLog()); + messageLog.addListener(adapter); + } + + @Override + public void onStop() { + super.onStop(); + messageLog.removeListener(adapter); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_chat, container, false); + + ListView listView = (ListView) view.findViewById(R.id.chatConsole); + listView.setAdapter(adapter); + listView.setDivider(null); + listView.setDividerHeight(0); + listView.setVerticalFadingEdgeEnabled(true); + + EditText editText = (EditText) view.findViewById(R.id.chatInput); editText.setOnEditorActionListener(new ChatSendListener()); - - return view; - } - - private final class ChatSendListener implements OnEditorActionListener { - public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { - String text = v.getText().toString(); - if(text.length()>0) { - v.setText(""); - netplay.sendChat(text); - } - return true; - } - } + + return view; + } + + private final class ChatSendListener implements OnEditorActionListener { + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + String text = v.getText().toString(); + if(text.length()>0) { + v.setText(""); + netplay.sendChat(text); + } + return true; + } + } } diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/ChatlogAdapter.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/ChatlogAdapter.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/ChatlogAdapter.java Tue Nov 10 20:43:13 2015 +0100 @@ -39,14 +39,14 @@ * Since lines with a given ID never change in our chatlog, we can avoid the effort * of TextView.setText in many cases by checking if the view is already set up for the * line with the right ID - but to do that, the view needs to remember the ID it's - * holding the text for. That's what the LoglineView does. + * holding the text for. That's what the LoglineView does. */ class LoglineView extends TextView { - long chatlogId = -1; - - public LoglineView(Context context) { - super(context); - } + long chatlogId = -1; + + public LoglineView(Context context) { + super(context); + } } /** @@ -57,65 +57,65 @@ * the textviews from a messagelog in an efficient way. */ public class ChatlogAdapter extends BaseAdapter implements MessageLog.Listener { - long idOffset = 0; - private List log = new ArrayList(); - private Context context; - - public ChatlogAdapter(Context context) { - this.context = context; - } - - public int getCount() { - return log.size(); - } + long idOffset = 0; + private List log = new ArrayList(); + private Context context; + + public ChatlogAdapter(Context context) { + this.context = context; + } + + public int getCount() { + return log.size(); + } - public Object getItem(int position) { - return log.get(position); - } + public Object getItem(int position) { + return log.get(position); + } + + public long getItemId(int position) { + return position+idOffset; + } - public long getItemId(int position) { - return position+idOffset; - } + public boolean hasStableIds() { + return true; + } - public boolean hasStableIds() { - return true; - } + public void clear() { + idOffset += log.size(); + log.clear(); + notifyDataSetChanged(); + } - public void clear() { - idOffset += log.size(); - log.clear(); - notifyDataSetChanged(); - } - - public void lineAdded(CharSequence text) { - log.add(text); - notifyDataSetChanged(); - } - - public void lineRemoved() { - log.remove(0); - idOffset += 1; - notifyDataSetChanged(); - } - - public void setLog(Collection log) { - idOffset += log.size(); - this.log = new ArrayList(log); - notifyDataSetChanged(); - } - - public View getView(int position, View convertView, ViewGroup parent) { - LoglineView v = (LoglineView)convertView; - if (v == null) { - v = new LoglineView(context); - v.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT)); - v.setMovementMethod(LinkMovementMethod.getInstance()); - } - long id = getItemId(position); - if(id != v.chatlogId) { - v.setText(log.get(position)); - v.chatlogId = id; - } - return v; - } + public void lineAdded(CharSequence text) { + log.add(text); + notifyDataSetChanged(); + } + + public void lineRemoved() { + log.remove(0); + idOffset += 1; + notifyDataSetChanged(); + } + + public void setLog(Collection log) { + idOffset += log.size(); + this.log = new ArrayList(log); + notifyDataSetChanged(); + } + + public View getView(int position, View convertView, ViewGroup parent) { + LoglineView v = (LoglineView)convertView; + if (v == null) { + v = new LoglineView(context); + v.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT)); + v.setMovementMethod(LinkMovementMethod.getInstance()); + } + long id = getItemId(position); + if(id != v.chatlogId) { + v.setText(log.get(position)); + v.chatlogId = id; + } + return v; + } } \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/ConnectingDialog.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/ConnectingDialog.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/ConnectingDialog.java Tue Nov 10 20:43:13 2015 +0100 @@ -37,58 +37,58 @@ * Indeterminate progress dialog that is shown in the MainActivity while trying * to connect to the server. If the connection fails (disconnect before we reach * lobby state), an error toast with the disconnect message is shown. - * + * */ public class ConnectingDialog extends ConnectionDependendDialogFragment { - @Override - public void onStart() { - super.onStart(); - LocalBroadcastManager.getInstance(getActivity().getApplicationContext()).registerReceiver(connectedReceiver, new IntentFilter(Netplay.ACTION_CONNECTED)); - LocalBroadcastManager.getInstance(getActivity().getApplicationContext()).registerReceiver(disconnectedReceiver, new IntentFilter(Netplay.ACTION_DISCONNECTED)); - - if(Netplay.getAppInstance(getActivity().getApplicationContext()).getState() != State.CONNECTING) { - dismiss(); - } - } - - @Override - public void onStop() { - super.onStop(); - LocalBroadcastManager.getInstance(getActivity().getApplicationContext()).unregisterReceiver(connectedReceiver); - LocalBroadcastManager.getInstance(getActivity().getApplicationContext()).unregisterReceiver(disconnectedReceiver); - } - - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - ProgressDialog dialog = new ProgressDialog(getActivity()); - dialog.setIndeterminate(true); - dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); - dialog.setTitle(R.string.dialog_connecting_title); - dialog.setMessage(getString(R.string.dialog_connecting_message)); - return dialog; - } - - private BroadcastReceiver connectedReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - Dialog dialog = getDialog(); - if(dialog != null) { - dialog.dismiss(); - } else { - dismiss(); - } - } - }; - - private BroadcastReceiver disconnectedReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - Toast.makeText(getActivity(), intent.getExtras().getString(Netplay.EXTRA_MESSAGE), Toast.LENGTH_LONG).show(); - } - }; - - public void onCancel(DialogInterface dialog) { - super.onCancel(dialog); - Netplay.getAppInstance(getActivity().getApplicationContext()).disconnect(); - }; + @Override + public void onStart() { + super.onStart(); + LocalBroadcastManager.getInstance(getActivity().getApplicationContext()).registerReceiver(connectedReceiver, new IntentFilter(Netplay.ACTION_CONNECTED)); + LocalBroadcastManager.getInstance(getActivity().getApplicationContext()).registerReceiver(disconnectedReceiver, new IntentFilter(Netplay.ACTION_DISCONNECTED)); + + if(Netplay.getAppInstance(getActivity().getApplicationContext()).getState() != State.CONNECTING) { + dismiss(); + } + } + + @Override + public void onStop() { + super.onStop(); + LocalBroadcastManager.getInstance(getActivity().getApplicationContext()).unregisterReceiver(connectedReceiver); + LocalBroadcastManager.getInstance(getActivity().getApplicationContext()).unregisterReceiver(disconnectedReceiver); + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + ProgressDialog dialog = new ProgressDialog(getActivity()); + dialog.setIndeterminate(true); + dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); + dialog.setTitle(R.string.dialog_connecting_title); + dialog.setMessage(getString(R.string.dialog_connecting_message)); + return dialog; + } + + private BroadcastReceiver connectedReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + Dialog dialog = getDialog(); + if(dialog != null) { + dialog.dismiss(); + } else { + dismiss(); + } + } + }; + + private BroadcastReceiver disconnectedReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + Toast.makeText(getActivity(), intent.getExtras().getString(Netplay.EXTRA_MESSAGE), Toast.LENGTH_LONG).show(); + } + }; + + public void onCancel(DialogInterface dialog) { + super.onCancel(dialog); + Netplay.getAppInstance(getActivity().getApplicationContext()).disconnect(); + }; } diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/ConnectionDependendDialogFragment.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/ConnectionDependendDialogFragment.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/ConnectionDependendDialogFragment.java Tue Nov 10 20:43:13 2015 +0100 @@ -36,30 +36,30 @@ * appear during connecting (e.g. username input) */ public class ConnectionDependendDialogFragment extends DialogFragment { - @Override - public void onStart() { - super.onStart(); - LocalBroadcastManager.getInstance(getActivity().getApplicationContext()).registerReceiver(dismissReceiver, new IntentFilter(Netplay.ACTION_DISCONNECTED)); - if(Netplay.getAppInstance(getActivity().getApplicationContext()).getState() == State.NOT_CONNECTED) { - dismiss(); - } - } - - @Override - public void onStop() { - super.onStop(); - LocalBroadcastManager.getInstance(getActivity().getApplicationContext()).unregisterReceiver(dismissReceiver); - } - - private BroadcastReceiver dismissReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - Dialog dialog = getDialog(); - if(dialog != null) { - dialog.dismiss(); - } else { - dismiss(); - } - } - }; + @Override + public void onStart() { + super.onStart(); + LocalBroadcastManager.getInstance(getActivity().getApplicationContext()).registerReceiver(dismissReceiver, new IntentFilter(Netplay.ACTION_DISCONNECTED)); + if(Netplay.getAppInstance(getActivity().getApplicationContext()).getState() == State.NOT_CONNECTED) { + dismiss(); + } + } + + @Override + public void onStop() { + super.onStop(); + LocalBroadcastManager.getInstance(getActivity().getApplicationContext()).unregisterReceiver(dismissReceiver); + } + + private BroadcastReceiver dismissReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + Dialog dialog = getDialog(); + if(dialog != null) { + dialog.dismiss(); + } else { + dismiss(); + } + } + }; } diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadAssets.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadAssets.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadAssets.java Tue Nov 10 20:43:13 2015 +0100 @@ -36,48 +36,48 @@ import android.util.Log; public class DownloadAssets extends AsyncTask { - private static final String VERSION_FILENAME = "assetsversion.txt"; - private final MainActivity act; - - public DownloadAssets(MainActivity act){ - this.act = act; - } - - private void copyFileOrDir(AssetManager assetManager, File target, String assetPath) throws IOException { - try { - FileUtils.writeStreamToFile(assetManager.open(assetPath), target); - } catch(FileNotFoundException e) { - /* - * I can't find a better way to figure out whether an asset entry is - * a file or a directory. Checking if assetManager.list(assetPath) - * is empty is a bit cleaner, but SLOW. - */ - if (!target.isDirectory() && !target.mkdir()) { - throw new IOException("Unable to create directory "+target); - } - for (String asset : assetManager.list(assetPath)) { - copyFileOrDir(assetManager, new File(target, asset), assetPath + "/" + asset); - } - } - } - - @Override - protected Boolean doInBackground(Object... params) { - try { - FileUtils.writeStreamToFile(act.getResources().openRawResource(R.raw.schemes_builtin), Schemes.getBuiltinSchemesFile(act)); - FileUtils.writeStreamToFile(act.getResources().openRawResource(R.raw.weapons_builtin), Weaponsets.getBuiltinWeaponsetsFile(act)); - FileUtils.resRawToFilesDir(act, R.array.teams, R.array.teamFilenames, Team.DIRECTORY_TEAMS); - copyFileOrDir(act.getAssets(), FileUtils.getDataPathFile(act), "Data"); - copyFileOrDir(act.getAssets(), new File(FileUtils.getCachePath(act), VERSION_FILENAME), VERSION_FILENAME); - return Boolean.TRUE; - } catch(IOException e) { - Log.e("DownloadAssets", e.getMessage(), e); - return Boolean.FALSE; - } - } - - @Override - protected void onPostExecute(Boolean result){ - act.onAssetsDownloaded(result); - } + private static final String VERSION_FILENAME = "assetsversion.txt"; + private final MainActivity act; + + public DownloadAssets(MainActivity act){ + this.act = act; + } + + private void copyFileOrDir(AssetManager assetManager, File target, String assetPath) throws IOException { + try { + FileUtils.writeStreamToFile(assetManager.open(assetPath), target); + } catch(FileNotFoundException e) { + /* + * I can't find a better way to figure out whether an asset entry is + * a file or a directory. Checking if assetManager.list(assetPath) + * is empty is a bit cleaner, but SLOW. + */ + if (!target.isDirectory() && !target.mkdir()) { + throw new IOException("Unable to create directory "+target); + } + for (String asset : assetManager.list(assetPath)) { + copyFileOrDir(assetManager, new File(target, asset), assetPath + "/" + asset); + } + } + } + + @Override + protected Boolean doInBackground(Object... params) { + try { + FileUtils.writeStreamToFile(act.getResources().openRawResource(R.raw.schemes_builtin), Schemes.getBuiltinSchemesFile(act)); + FileUtils.writeStreamToFile(act.getResources().openRawResource(R.raw.weapons_builtin), Weaponsets.getBuiltinWeaponsetsFile(act)); + FileUtils.resRawToFilesDir(act, R.array.teams, R.array.teamFilenames, Team.DIRECTORY_TEAMS); + copyFileOrDir(act.getAssets(), FileUtils.getDataPathFile(act), "Data"); + copyFileOrDir(act.getAssets(), new File(FileUtils.getCachePath(act), VERSION_FILENAME), VERSION_FILENAME); + return Boolean.TRUE; + } catch(IOException e) { + Log.e("DownloadAssets", e.getMessage(), e); + return Boolean.FALSE; + } + } + + @Override + protected void onPostExecute(Boolean result){ + act.onAssetsDownloaded(result); + } } diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadAsyncTask.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadAsyncTask.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadAsyncTask.java Tue Nov 10 20:43:13 2015 +0100 @@ -37,188 +37,188 @@ import android.os.AsyncTask; /** * This is an AsyncTask which will download a zip from an URL and unzip it to a specified path - * + * * a typical call to start the task would be new DownloadAsyncTask().execute(getExternalStorage(), "www.hedgewars.org/data.zip"); * @author Xeli * */ public class DownloadAsyncTask extends AsyncTask { - //private final static String URL_WITHOUT_SUFFIX = "http://www.xelification.com/tmp/firebutton."; - private final static String URL_ZIP_SUFFIX = ".zip"; - private final static String URL_HASH_SUFFIX = ".hash"; + //private final static String URL_WITHOUT_SUFFIX = "http://www.xelification.com/tmp/firebutton."; + private final static String URL_ZIP_SUFFIX = ".zip"; + private final static String URL_HASH_SUFFIX = ".hash"; - public static final int EXIT_SUCCESS = 0; - public static final int EXIT_URLFAIL = 1; - public static final int EXIT_CONNERROR = 2; - public static final int EXIT_FNF = 3; - public static final int EXIT_MD5 = 4; - public static final int EXIT_CANCELLED = 5; + public static final int EXIT_SUCCESS = 0; + public static final int EXIT_URLFAIL = 1; + public static final int EXIT_CONNERROR = 2; + public static final int EXIT_FNF = 3; + public static final int EXIT_MD5 = 4; + public static final int EXIT_CANCELLED = 5; - private DownloadTask task; - private long lastUpdateMillis = 0; + private DownloadTask task; + private long lastUpdateMillis = 0; - public DownloadAsyncTask(DownloadTask _task){ - task = _task; - } + public DownloadAsyncTask(DownloadTask _task){ + task = _task; + } - /** - * - * @param params - A {@link}DownloadTask which gives information about where to download from and store the files to - */ - protected Integer doInBackground(DownloadPackage...packages) { - DownloadPackage pack = packages[0];//just use one task per execute call for now + /** + * + * @param params - A {@link}DownloadTask which gives information about where to download from and store the files to + */ + protected Integer doInBackground(DownloadPackage...packages) { + DownloadPackage pack = packages[0];//just use one task per execute call for now - HttpURLConnection conn = null; - MessageDigest digester = null; - String rootZipDest = pack.getPathToStore(); + HttpURLConnection conn = null; + MessageDigest digester = null; + String rootZipDest = pack.getPathToStore(); - File rootDest = new File(rootZipDest);//TODO check for nullpointer, it hints to the absence of an sdcard - rootDest.mkdirs(); + File rootDest = new File(rootZipDest);//TODO check for nullpointer, it hints to the absence of an sdcard + rootDest.mkdirs(); - try { - URL url = new URL(pack.getURL() + URL_ZIP_SUFFIX); - conn = (HttpURLConnection)url.openConnection(); - } catch (IOException e) { - e.printStackTrace(); - return EXIT_URLFAIL; - } + try { + URL url = new URL(pack.getURL() + URL_ZIP_SUFFIX); + conn = (HttpURLConnection)url.openConnection(); + } catch (IOException e) { + e.printStackTrace(); + return EXIT_URLFAIL; + } - String contentType = conn.getContentType(); + String contentType = conn.getContentType(); - if(contentType == null || contentType.contains("zip")){ //Seeing as we provide the url if the contentType is unknown lets assume zips - int bytesDecompressed = 0; - ZipEntry entry = null; - ZipInputStream input = null; - FileOutputStream output = null; - int kbytesToProcess = conn.getContentLength()/1024; + if(contentType == null || contentType.contains("zip")){ //Seeing as we provide the url if the contentType is unknown lets assume zips + int bytesDecompressed = 0; + ZipEntry entry = null; + ZipInputStream input = null; + FileOutputStream output = null; + int kbytesToProcess = conn.getContentLength()/1024; - byte[] buffer = new byte[1024]; - task.start(kbytesToProcess); + byte[] buffer = new byte[1024]; + task.start(kbytesToProcess); - try { - digester = MessageDigest.getInstance("MD5"); + try { + digester = MessageDigest.getInstance("MD5"); - } catch (NoSuchAlgorithmException e1) { - e1.printStackTrace(); - } + } catch (NoSuchAlgorithmException e1) { + e1.printStackTrace(); + } - try{ - input = new ZipInputStream(conn.getInputStream()); - entry = input.getNextEntry(); - }catch(IOException e){ - e.printStackTrace(); - conn.disconnect(); - return EXIT_CONNERROR; - } + try{ + input = new ZipInputStream(conn.getInputStream()); + entry = input.getNextEntry(); + }catch(IOException e){ + e.printStackTrace(); + conn.disconnect(); + return EXIT_CONNERROR; + } - while(entry != null){ + while(entry != null){ - if(isCancelled()) break; + if(isCancelled()) break; - try { - String fileName = entry.getName(); - File f = new File(rootZipDest + fileName); - bytesDecompressed += entry.getCompressedSize(); + try { + String fileName = entry.getName(); + File f = new File(rootZipDest + fileName); + bytesDecompressed += entry.getCompressedSize(); - if(entry.isDirectory()){ - f.mkdir(); - }else{ - if(f.exists()){ - f.delete(); - } - f.createNewFile(); - output = new FileOutputStream(f); + if(entry.isDirectory()){ + f.mkdir(); + }else{ + if(f.exists()){ + f.delete(); + } + f.createNewFile(); + output = new FileOutputStream(f); - int count = 0; - while((count = input.read(buffer)) != -1){ - output.write(buffer, 0, count); - digester.update(buffer, 0, count); - if(System.currentTimeMillis() - lastUpdateMillis > 1000){ - lastUpdateMillis = System.currentTimeMillis(); - publishProgress(bytesDecompressed, kbytesToProcess, fileName); - } - } - output.flush(); - input.closeEntry(); - }//if isDir - entry = input.getNextEntry(); - } catch (FileNotFoundException e) { - e.printStackTrace(); - if(conn != null) conn.disconnect(); - return EXIT_FNF; - } catch (IOException e) { - e.printStackTrace(); - if(conn != null) conn.disconnect(); - return EXIT_CONNERROR; - }finally{ - try { - if( output != null) output.close(); + int count = 0; + while((count = input.read(buffer)) != -1){ + output.write(buffer, 0, count); + digester.update(buffer, 0, count); + if(System.currentTimeMillis() - lastUpdateMillis > 1000){ + lastUpdateMillis = System.currentTimeMillis(); + publishProgress(bytesDecompressed, kbytesToProcess, fileName); + } + } + output.flush(); + input.closeEntry(); + }//if isDir + entry = input.getNextEntry(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + if(conn != null) conn.disconnect(); + return EXIT_FNF; + } catch (IOException e) { + e.printStackTrace(); + if(conn != null) conn.disconnect(); + return EXIT_CONNERROR; + }finally{ + try { + if( output != null) output.close(); - } catch (IOException e) {} - } - }//end while(entry != null) - if( input != null) - try { - input.close(); - } catch (IOException e) {} - }else{//end if contentType == "zip" - return EXIT_URLFAIL; - } - if(conn != null) conn.disconnect(); + } catch (IOException e) {} + } + }//end while(entry != null) + if( input != null) + try { + input.close(); + } catch (IOException e) {} + }else{//end if contentType == "zip" + return EXIT_URLFAIL; + } + if(conn != null) conn.disconnect(); - if(checkMD5(digester, pack))return EXIT_SUCCESS; - else return EXIT_MD5; - } + if(checkMD5(digester, pack))return EXIT_SUCCESS; + else return EXIT_MD5; + } - //TODO proper result handling - protected void onPostExecute(Integer result){ - task.done(result); - } + //TODO proper result handling + protected void onPostExecute(Integer result){ + task.done(result); + } - protected void onProgressUpdate(Object...objects){ - task.update((Integer)objects[0], (Integer)objects[1], (String)objects[2]); - } + protected void onProgressUpdate(Object...objects){ + task.update((Integer)objects[0], (Integer)objects[1], (String)objects[2]); + } - protected void onCancelled(){ - onPostExecute(EXIT_CANCELLED); - } + protected void onCancelled(){ + onPostExecute(EXIT_CANCELLED); + } - private boolean checkMD5(MessageDigest digester, DownloadPackage task){ - if(digester != null) { - byte[] messageDigest = digester.digest(); + private boolean checkMD5(MessageDigest digester, DownloadPackage task){ + if(digester != null) { + byte[] messageDigest = digester.digest(); - try { - URL url = new URL(task.getURL() + URL_HASH_SUFFIX); - HttpURLConnection conn = (HttpURLConnection)url.openConnection(); + try { + URL url = new URL(task.getURL() + URL_HASH_SUFFIX); + HttpURLConnection conn = (HttpURLConnection)url.openConnection(); - byte[] buffer = new byte[1024];//size is large enough to hold the entire hash - BufferedInputStream bis = new BufferedInputStream(conn.getInputStream()); - int bytesRead = bis.read(buffer); - String hash = null; - if(bytesRead > -1){ - hash = new String(buffer, 0, bytesRead); - } - StringBuffer sb = new StringBuffer(); - Integer tmp = 0; - for(int i = 0; i < messageDigest.length; i++){ - tmp = 0xFF & messageDigest[i]; - if(tmp < 0xF) sb.append('0'); - sb.append(Integer.toHexString(tmp)); - } - sb.append('\n');//add newline to become identical with the hash file + byte[] buffer = new byte[1024];//size is large enough to hold the entire hash + BufferedInputStream bis = new BufferedInputStream(conn.getInputStream()); + int bytesRead = bis.read(buffer); + String hash = null; + if(bytesRead > -1){ + hash = new String(buffer, 0, bytesRead); + } + StringBuffer sb = new StringBuffer(); + Integer tmp = 0; + for(int i = 0; i < messageDigest.length; i++){ + tmp = 0xFF & messageDigest[i]; + if(tmp < 0xF) sb.append('0'); + sb.append(Integer.toHexString(tmp)); + } + sb.append('\n');//add newline to become identical with the hash file - return hash.equals(sb.toString()); - } catch (IOException e) { - e.printStackTrace(); - return true; - } - }else{ - return true; - } + return hash.equals(sb.toString()); + } catch (IOException e) { + e.printStackTrace(); + return true; + } + }else{ + return true; + } - } + } } diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadDialogFragment.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadDialogFragment.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadDialogFragment.java Tue Nov 10 20:43:13 2015 +0100 @@ -32,57 +32,57 @@ public class DownloadDialogFragment extends DialogFragment { - public static final int NUM_ALREADYDOWNLOADED = 0; - public static final int NUM_AREYOUSURE = 1; + public static final int NUM_ALREADYDOWNLOADED = 0; + public static final int NUM_AREYOUSURE = 1; - private final static String BUNDLE_TASK = "task"; + private final static String BUNDLE_TASK = "task"; - static DownloadDialogFragment newInstance(DownloadPackage task){ - DownloadDialogFragment dialog = new DownloadDialogFragment(); + static DownloadDialogFragment newInstance(DownloadPackage task){ + DownloadDialogFragment dialog = new DownloadDialogFragment(); - Bundle args = new Bundle(); - args.putParcelable(DownloadDialogFragment.BUNDLE_TASK, task); - dialog.setArguments(args); + Bundle args = new Bundle(); + args.putParcelable(DownloadDialogFragment.BUNDLE_TASK, task); + dialog.setArguments(args); - return dialog; - } + return dialog; + } - public Dialog onCreateDialog(Bundle savedInstanceState){ - DownloadPackage task = (DownloadPackage)getArguments().getParcelable(DownloadDialogFragment.BUNDLE_TASK); + public Dialog onCreateDialog(Bundle savedInstanceState){ + DownloadPackage task = (DownloadPackage)getArguments().getParcelable(DownloadDialogFragment.BUNDLE_TASK); - Builder builder = new AlertDialog.Builder(getActivity()); + Builder builder = new AlertDialog.Builder(getActivity()); - switch(task.getStatus()){ - case CURRENTVERSION: - case NEWERVERSION: - builder.setMessage(R.string.download_areyousure); - break; - case OLDERVERSION: - builder.setMessage(R.string.download_alreadydownloaded); - break; - } + switch(task.getStatus()){ + case CURRENTVERSION: + case NEWERVERSION: + builder.setMessage(R.string.download_areyousure); + break; + case OLDERVERSION: + builder.setMessage(R.string.download_alreadydownloaded); + break; + } - DownloadClicker clicker = new DownloadClicker(task); - builder.setPositiveButton(android.R.string.yes, clicker); - builder.setNegativeButton(android.R.string.no, clicker); + DownloadClicker clicker = new DownloadClicker(task); + builder.setPositiveButton(android.R.string.yes, clicker); + builder.setNegativeButton(android.R.string.no, clicker); - return builder.create(); - } + return builder.create(); + } - class DownloadClicker implements OnClickListener{ + class DownloadClicker implements OnClickListener{ - DownloadPackage task = null; + DownloadPackage task = null; - public DownloadClicker(DownloadPackage _task){ - task = _task; - } + public DownloadClicker(DownloadPackage _task){ + task = _task; + } - public void onClick(DialogInterface dialog, int which) { - if(which == Dialog.BUTTON_POSITIVE){ - Intent i = new Intent(getActivity(), DownloadListActivity.class); - i.putExtra(DownloadFragment.EXTRA_TASK, task); - getActivity().startActivity(i); - } - } - } + public void onClick(DialogInterface dialog, int which) { + if(which == Dialog.BUTTON_POSITIVE){ + Intent i = new Intent(getActivity(), DownloadListActivity.class); + i.putExtra(DownloadFragment.EXTRA_TASK, task); + getActivity().startActivity(i); + } + } + } } diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadFragment.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadFragment.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadFragment.java Tue Nov 10 20:43:13 2015 +0100 @@ -41,177 +41,177 @@ import android.widget.TextView; public class DownloadFragment extends Fragment{ - public static final String EXTRA_TASK = "task"; + public static final String EXTRA_TASK = "task"; - public static final int MSG_START = 0; - public static final int MSG_UPDATE = 1; - public static final int MSG_DONE = 2; - public static final int MSG_FAILED = 3; + public static final int MSG_START = 0; + public static final int MSG_UPDATE = 1; + public static final int MSG_DONE = 2; + public static final int MSG_FAILED = 3; - private boolean boundToService = false; + private boolean boundToService = false; - private TextView progress_sub; - private ProgressBar progress; - private Button /*positive,*/ negative; + private TextView progress_sub; + private ProgressBar progress; + private Button /*positive,*/ negative; - private DownloadPackage pack; + private DownloadPackage pack; - private Handler messageHandler; - private Messenger messenger, messengerService; + private Handler messageHandler; + private Messenger messenger, messengerService; - public static DownloadFragment getInstance(DownloadPackage task){ - DownloadFragment df = new DownloadFragment(); - Bundle args = new Bundle(); - args.putParcelable(DownloadFragment.EXTRA_TASK, task); + public static DownloadFragment getInstance(DownloadPackage task){ + DownloadFragment df = new DownloadFragment(); + Bundle args = new Bundle(); + args.putParcelable(DownloadFragment.EXTRA_TASK, task); - df.setArguments(args); + df.setArguments(args); - return df; - } + return df; + } - public void onActivityCreated(Bundle savedInstanceState){ - super.onActivityCreated(savedInstanceState); + public void onActivityCreated(Bundle savedInstanceState){ + super.onActivityCreated(savedInstanceState); - messageHandler = new Handler(messageCallback); - messenger = new Messenger(messageHandler); - Intent i = new Intent(getActivity().getApplicationContext(), DownloadService.class); - getActivity().startService(i); - getActivity().bindService(new Intent(getActivity().getApplicationContext(), DownloadService.class), connection, Context.BIND_AUTO_CREATE); - } + messageHandler = new Handler(messageCallback); + messenger = new Messenger(messageHandler); + Intent i = new Intent(getActivity().getApplicationContext(), DownloadService.class); + getActivity().startService(i); + getActivity().bindService(new Intent(getActivity().getApplicationContext(), DownloadService.class), connection, Context.BIND_AUTO_CREATE); + } - public View onCreateView(LayoutInflater inflater, ViewGroup viewgroup, Bundle savedInstanceState){ - View v = inflater.inflate(R.layout.download_progress, viewgroup, false); - progress_sub = (TextView)v.findViewById(R.id.progressbar_sub); - progress = (ProgressBar)v.findViewById(R.id.progressbar); + public View onCreateView(LayoutInflater inflater, ViewGroup viewgroup, Bundle savedInstanceState){ + View v = inflater.inflate(R.layout.download_progress, viewgroup, false); + progress_sub = (TextView)v.findViewById(R.id.progressbar_sub); + progress = (ProgressBar)v.findViewById(R.id.progressbar); - //positive = (Button) v.findViewById(R.id.background); - negative = (Button) v.findViewById(R.id.cancelDownload); - //positive.setOnClickListener(backgroundClicker); - negative.setOnClickListener(cancelClicker); + //positive = (Button) v.findViewById(R.id.background); + negative = (Button) v.findViewById(R.id.cancelDownload); + //positive.setOnClickListener(backgroundClicker); + negative.setOnClickListener(cancelClicker); - pack = getArguments().getParcelable(DownloadFragment.EXTRA_TASK); + pack = getArguments().getParcelable(DownloadFragment.EXTRA_TASK); - return v; - } + return v; + } - private OnClickListener backgroundClicker = new OnClickListener(){ - public void onClick(View v){ - getActivity().finish(); - } - }; - private OnClickListener cancelClicker = new OnClickListener(){ - public void onClick(View v){ - if(messengerService != null){ - Message message = Message.obtain(messageHandler, DownloadService.MSG_CANCEL, pack); - try { - messengerService.send(message); - } catch (RemoteException e) {} - } - //getActivity().finish(); - } - }; - private OnClickListener doneClicker = new OnClickListener(){ - public void onClick(View v){ - getActivity().finish(); - } - }; + private OnClickListener backgroundClicker = new OnClickListener(){ + public void onClick(View v){ + getActivity().finish(); + } + }; + private OnClickListener cancelClicker = new OnClickListener(){ + public void onClick(View v){ + if(messengerService != null){ + Message message = Message.obtain(messageHandler, DownloadService.MSG_CANCEL, pack); + try { + messengerService.send(message); + } catch (RemoteException e) {} + } + //getActivity().finish(); + } + }; + private OnClickListener doneClicker = new OnClickListener(){ + public void onClick(View v){ + getActivity().finish(); + } + }; - private OnClickListener tryAgainClicker = new OnClickListener(){ - public void onClick(View v){ - if(messengerService != null){ - Message message = Message.obtain(messageHandler, DownloadService.MSG_ADDTASK, pack); - message.replyTo = messenger; - try { - messengerService.send(message); - } catch (RemoteException e) { - e.printStackTrace(); - } - } - } - }; + private OnClickListener tryAgainClicker = new OnClickListener(){ + public void onClick(View v){ + if(messengerService != null){ + Message message = Message.obtain(messageHandler, DownloadService.MSG_ADDTASK, pack); + message.replyTo = messenger; + try { + messengerService.send(message); + } catch (RemoteException e) { + e.printStackTrace(); + } + } + } + }; - public void onDestroy(){ - unBindFromService(); - super.onDestroy(); - } + public void onDestroy(){ + unBindFromService(); + super.onDestroy(); + } - private ServiceConnection connection = new ServiceConnection(){ + private ServiceConnection connection = new ServiceConnection(){ - public void onServiceConnected(ComponentName name, IBinder service) { - messengerService = new Messenger(service); + public void onServiceConnected(ComponentName name, IBinder service) { + messengerService = new Messenger(service); - try{ - //give the service a task - if(messengerService != null){ - Message message = Message.obtain(messageHandler, DownloadService.MSG_ADDTASK, pack); - message.replyTo = messenger; - messengerService.send(message); - } + try{ + //give the service a task + if(messengerService != null){ + Message message = Message.obtain(messageHandler, DownloadService.MSG_ADDTASK, pack); + message.replyTo = messenger; + messengerService.send(message); + } - }catch (RemoteException e){} - } + }catch (RemoteException e){} + } - public void onServiceDisconnected(ComponentName name) { - messengerService = null; - } + public void onServiceDisconnected(ComponentName name) { + messengerService = null; + } - }; + }; - public void unBindFromService(){ - if(messengerService != null){ - try { - Message message = Message.obtain(messageHandler, DownloadService.MSG_UNREGISTER_CLIENT, pack); - message.replyTo = messenger; - messengerService.send(message); - } catch (RemoteException e) { - e.printStackTrace(); - } - } + public void unBindFromService(){ + if(messengerService != null){ + try { + Message message = Message.obtain(messageHandler, DownloadService.MSG_UNREGISTER_CLIENT, pack); + message.replyTo = messenger; + messengerService.send(message); + } catch (RemoteException e) { + e.printStackTrace(); + } + } - getActivity().unbindService(connection); - } + getActivity().unbindService(connection); + } - private Handler.Callback messageCallback = new Handler.Callback() { + private Handler.Callback messageCallback = new Handler.Callback() { - public boolean handleMessage(Message msg) { - switch(msg.what){ - case MSG_START: - progress.setMax(msg.arg1); - progress_sub.setText(String.format("%dkb/%dkb\n%s", 0, msg.arg1, "")); - //positive.setText(R.string.download_background); - //positive.setOnClickListener(backgroundClicker); - negative.setText(R.string.download_cancel); - negative.setOnClickListener(cancelClicker); - break; - case MSG_UPDATE: - progress_sub.setText(String.format("%d%% - %dkb/%dkb\n%s",(msg.arg1*100)/msg.arg2, msg.arg1, msg.arg2, msg.obj)); - progress.setProgress(msg.arg1); - break; - case MSG_DONE: - progress.setProgress(progress.getMax()); - progress_sub.setText(R.string.download_done); + public boolean handleMessage(Message msg) { + switch(msg.what){ + case MSG_START: + progress.setMax(msg.arg1); + progress_sub.setText(String.format("%dkb/%dkb\n%s", 0, msg.arg1, "")); + //positive.setText(R.string.download_background); + //positive.setOnClickListener(backgroundClicker); + negative.setText(R.string.download_cancel); + negative.setOnClickListener(cancelClicker); + break; + case MSG_UPDATE: + progress_sub.setText(String.format("%d%% - %dkb/%dkb\n%s",(msg.arg1*100)/msg.arg2, msg.arg1, msg.arg2, msg.obj)); + progress.setProgress(msg.arg1); + break; + case MSG_DONE: + progress.setProgress(progress.getMax()); + progress_sub.setText(R.string.download_done); - // positive.setText(R.string.download_back); - // positive.setOnClickListener(doneClicker); + // positive.setText(R.string.download_back); + // positive.setOnClickListener(doneClicker); + + negative.setVisibility(View.INVISIBLE); + break; + case MSG_FAILED: + progress.setProgress(progress.getMax()); - negative.setVisibility(View.INVISIBLE); - break; - case MSG_FAILED: - progress.setProgress(progress.getMax()); - - String errorMsg = getString(R.string.download_failed); - switch(msg.arg1){ - case DownloadAsyncTask.EXIT_CONNERROR: progress_sub.setText(errorMsg + " " + "Connection error"); break; - case DownloadAsyncTask.EXIT_FNF: progress_sub.setText(errorMsg + " " + "File not found"); break; - case DownloadAsyncTask.EXIT_MD5: progress_sub.setText(errorMsg + " " + "MD5 check failed"); break; - case DownloadAsyncTask.EXIT_URLFAIL: progress_sub.setText(errorMsg + " " + "Invalid url"); break; - } - negative.setText(R.string.download_tryagain); - negative.setOnClickListener(tryAgainClicker); - break; - } - return false; - } - }; + String errorMsg = getString(R.string.download_failed); + switch(msg.arg1){ + case DownloadAsyncTask.EXIT_CONNERROR: progress_sub.setText(errorMsg + " " + "Connection error"); break; + case DownloadAsyncTask.EXIT_FNF: progress_sub.setText(errorMsg + " " + "File not found"); break; + case DownloadAsyncTask.EXIT_MD5: progress_sub.setText(errorMsg + " " + "MD5 check failed"); break; + case DownloadAsyncTask.EXIT_URLFAIL: progress_sub.setText(errorMsg + " " + "Invalid url"); break; + } + negative.setText(R.string.download_tryagain); + negative.setOnClickListener(tryAgainClicker); + break; + } + return false; + } + }; } diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadListActivity.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadListActivity.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadListActivity.java Tue Nov 10 20:43:13 2015 +0100 @@ -35,99 +35,99 @@ public class DownloadListActivity extends FragmentActivity implements OnItemMovementListener{ - private FrameLayout layout = null; - private LinearLayout downloadQueueContainer = null; - private View infoView = null; - private ImageView arrow = null; - private int halfSize = 0; - private DownloadPackage task = null; + private FrameLayout layout = null; + private LinearLayout downloadQueueContainer = null; + private View infoView = null; + private ImageView arrow = null; + private int halfSize = 0; + private DownloadPackage task = null; + + public void onCreate(Bundle savedInstanceState){ + super.onCreate(savedInstanceState); - public void onCreate(Bundle savedInstanceState){ - super.onCreate(savedInstanceState); + setContentView(R.layout.download_listactivity); + //FragmentManager fm = this.getSupportFragmentManager(); + //if(fm.findFragmentById(android.R.id.content) == null){ + // DownloadListFragment listfrag = new DownloadListFragment(); + // fm.beginTransaction().add(android.R.id.content, listfrag).commit(); + //} - setContentView(R.layout.download_listactivity); - //FragmentManager fm = this.getSupportFragmentManager(); - //if(fm.findFragmentById(android.R.id.content) == null){ - // DownloadListFragment listfrag = new DownloadListFragment(); - // fm.beginTransaction().add(android.R.id.content, listfrag).commit(); - //} + layout = (FrameLayout)findViewById(R.id.downloadFrameLayout); + downloadQueueContainer = (LinearLayout) findViewById(R.id.downloadQueueContainer); + } - layout = (FrameLayout)findViewById(R.id.downloadFrameLayout); - downloadQueueContainer = (LinearLayout) findViewById(R.id.downloadQueueContainer); - } - - public void onNewItemSelected(DownloadPackage _task, int x, int minX, int maxX, int size) { - if(layout != null){ - if(!_task.equals(task)){//if it's a new task refresh the whole thing - task = _task; - layout.removeView(infoView); - infoView = null; - } - - if(infoView == null){//build iv if it hasn't been created yet - infoView = this.getLayoutInflater().inflate(R.layout.download_info, layout, false); - FrameLayout.LayoutParams params = (android.widget.FrameLayout.LayoutParams) infoView.getLayoutParams(); - params.gravity = Gravity.NO_GRAVITY; - params.height = size; - arrow = (ImageView)infoView.findViewById(R.id.arrow); - arrow.setVisibility(View.INVISIBLE); - halfSize = size/2; - - Button yes = (Button)infoView.findViewById(R.id.download); - Button no = (Button)infoView.findViewById(R.id.cancel); - yes.setOnClickListener(yesClicker); - no.setOnClickListener(noClicker); - - layout.addView(infoView, params); - } - } - } + public void onNewItemSelected(DownloadPackage _task, int x, int minX, int maxX, int size) { + if(layout != null){ + if(!_task.equals(task)){//if it's a new task refresh the whole thing + task = _task; + layout.removeView(infoView); + infoView = null; + } + + if(infoView == null){//build iv if it hasn't been created yet + infoView = this.getLayoutInflater().inflate(R.layout.download_info, layout, false); + FrameLayout.LayoutParams params = (android.widget.FrameLayout.LayoutParams) infoView.getLayoutParams(); + params.gravity = Gravity.NO_GRAVITY; + params.height = size; + arrow = (ImageView)infoView.findViewById(R.id.arrow); + arrow.setVisibility(View.INVISIBLE); + halfSize = size/2; + + Button yes = (Button)infoView.findViewById(R.id.download); + Button no = (Button)infoView.findViewById(R.id.cancel); + yes.setOnClickListener(yesClicker); + no.setOnClickListener(noClicker); + + layout.addView(infoView, params); + } + } + } - public void onViewMoved(int x, int minX, int maxX) { - if(halfSize == -1){ - if(infoView.getHeight() != 0){ - halfSize = infoView.getHeight()/2; - } - } - if(layout != null && infoView != null){ - FrameLayout.LayoutParams params = ((FrameLayout.LayoutParams)infoView.getLayoutParams()); - if(x - halfSize < minX){ - params.topMargin = 0; - arrow.setVisibility(View.INVISIBLE); - params.gravity = Gravity.TOP; - }else if (x + halfSize >= maxX){ - params.topMargin = 0; - arrow.setVisibility(View.INVISIBLE); - params.gravity = Gravity.BOTTOM; - }else{ - params.topMargin = x - halfSize; - params.gravity = Gravity.NO_GRAVITY; - arrow.setVisibility(View.VISIBLE); - } - - infoView.requestLayout(); - - } - } - - private OnClickListener yesClicker = new OnClickListener(){ - public void onClick(View v){ - FragmentManager fm = getSupportFragmentManager(); - FragmentTransaction ft= fm.beginTransaction(); - DownloadFragment df = DownloadFragment.getInstance(task); - - ft.add(R.id.downloadQueueContainer, df).commit(); - //ft.show(new DownloadFragment()); - - task = null; - layout.removeView(infoView); - } - }; - - private OnClickListener noClicker = new OnClickListener(){ - public void onClick(View v){ - task = null; - layout.removeView(infoView); - } - }; + public void onViewMoved(int x, int minX, int maxX) { + if(halfSize == -1){ + if(infoView.getHeight() != 0){ + halfSize = infoView.getHeight()/2; + } + } + if(layout != null && infoView != null){ + FrameLayout.LayoutParams params = ((FrameLayout.LayoutParams)infoView.getLayoutParams()); + if(x - halfSize < minX){ + params.topMargin = 0; + arrow.setVisibility(View.INVISIBLE); + params.gravity = Gravity.TOP; + }else if (x + halfSize >= maxX){ + params.topMargin = 0; + arrow.setVisibility(View.INVISIBLE); + params.gravity = Gravity.BOTTOM; + }else{ + params.topMargin = x - halfSize; + params.gravity = Gravity.NO_GRAVITY; + arrow.setVisibility(View.VISIBLE); + } + + infoView.requestLayout(); + + } + } + + private OnClickListener yesClicker = new OnClickListener(){ + public void onClick(View v){ + FragmentManager fm = getSupportFragmentManager(); + FragmentTransaction ft= fm.beginTransaction(); + DownloadFragment df = DownloadFragment.getInstance(task); + + ft.add(R.id.downloadQueueContainer, df).commit(); + //ft.show(new DownloadFragment()); + + task = null; + layout.removeView(infoView); + } + }; + + private OnClickListener noClicker = new OnClickListener(){ + public void onClick(View v){ + task = null; + layout.removeView(infoView); + } + }; } diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadListFragment.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadListFragment.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadListFragment.java Tue Nov 10 20:43:13 2015 +0100 @@ -43,172 +43,172 @@ public class DownloadListFragment extends ListFragment implements OnItemClickListener, OnScrollListener, Runnable{ - private View targetView = null; - private ArrayList listeners = new ArrayList(); + private View targetView = null; + private ArrayList listeners = new ArrayList(); - public void onActivityCreated(Bundle savedInstanceState){ - super.onActivityCreated(savedInstanceState); + public void onActivityCreated(Bundle savedInstanceState){ + super.onActivityCreated(savedInstanceState); - ArrayList tasks = new ArrayList(); + ArrayList tasks = new ArrayList(); - ArrayAdapter adapter = new ArrayAdapter(getActivity().getApplicationContext(), android.R.layout.simple_list_item_1, tasks); - setListAdapter(adapter); - getListView().setOnItemClickListener(this); - getListView().setOnScrollListener(this); + ArrayAdapter adapter = new ArrayAdapter(getActivity().getApplicationContext(), android.R.layout.simple_list_item_1, tasks); + setListAdapter(adapter); + getListView().setOnItemClickListener(this); + getListView().setOnScrollListener(this); - if(getActivity() instanceof OnItemMovementListener){ - listeners.add((OnItemMovementListener)getActivity()); - } + if(getActivity() instanceof OnItemMovementListener){ + listeners.add((OnItemMovementListener)getActivity()); + } + + getListView().setCacheColorHint(Color.TRANSPARENT);//To prevent a blackish background while scrolling + - getListView().setCacheColorHint(Color.TRANSPARENT);//To prevent a blackish background while scrolling - - - Thread t = new Thread(this, "DownloadListParser"); - t.start(); - } + Thread t = new Thread(this, "DownloadListParser"); + t.start(); + } - public void run(){ - XmlPullParserFactory xmlPullFactory; - try { - xmlPullFactory = XmlPullParserFactory.newInstance(); - XmlPullParser xmlPuller = xmlPullFactory.newPullParser(); + public void run(){ + XmlPullParserFactory xmlPullFactory; + try { + xmlPullFactory = XmlPullParserFactory.newInstance(); + XmlPullParser xmlPuller = xmlPullFactory.newPullParser(); - URL url = new URL("http://www.xelification.com/tmp/downloads.xml"); - HttpURLConnection conn = (HttpURLConnection)url.openConnection(); + URL url = new URL("http://www.xelification.com/tmp/downloads.xml"); + HttpURLConnection conn = (HttpURLConnection)url.openConnection(); + + BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()), 1024); + xmlPuller.setInput(br); - BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()), 1024); - xmlPuller.setInput(br); + final ArrayAdapter adapter = (ArrayAdapter) getListAdapter(); + + int eventType = xmlPuller.getEventType(); + while(eventType != XmlPullParser.END_DOCUMENT){ + + if(eventType == XmlPullParser.START_TAG){ + if(xmlPuller.getName().toLowerCase().equals("task")){ + final DownloadPackage task = DownloadPackage.getTaskFromXML(getActivity(), xmlPuller); - final ArrayAdapter adapter = (ArrayAdapter) getListAdapter(); - - int eventType = xmlPuller.getEventType(); - while(eventType != XmlPullParser.END_DOCUMENT){ - - if(eventType == XmlPullParser.START_TAG){ - if(xmlPuller.getName().toLowerCase().equals("task")){ - final DownloadPackage task = DownloadPackage.getTaskFromXML(getActivity(), xmlPuller); - - getActivity().runOnUiThread(new Runnable(){ - public void run() { - adapter.add(task); - } - }); - } - } - eventType = getEventType(xmlPuller); - } - - - } catch (XmlPullParserException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - } - + getActivity().runOnUiThread(new Runnable(){ + public void run() { + adapter.add(task); + } + }); + } + } + eventType = getEventType(xmlPuller); + } + + + } catch (XmlPullParserException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + - /** - * Skips whitespaces.. - */ - private static int getEventType(XmlPullParser xmlPuller)throws XmlPullParserException, IOException{ - int eventType = xmlPuller.next(); - while(eventType == XmlPullParser.TEXT && xmlPuller.isWhitespace()){ - eventType = xmlPuller.next(); - } - return eventType; - } + /** + * Skips whitespaces.. + */ + private static int getEventType(XmlPullParser xmlPuller)throws XmlPullParserException, IOException{ + int eventType = xmlPuller.next(); + while(eventType == XmlPullParser.TEXT && xmlPuller.isWhitespace()){ + eventType = xmlPuller.next(); + } + return eventType; + } - public void onItemClick(AdapterView arg0, View arg1, int position, long arg3) { - DownloadPackage task = (DownloadPackage)arg0.getAdapter().getItem(position); - /* - FragmentTransaction ft = getFragmentManager().beginTransaction(); - Fragment prev = getFragmentManager().findFragmentByTag("dialog"); + public void onItemClick(AdapterView arg0, View arg1, int position, long arg3) { + DownloadPackage task = (DownloadPackage)arg0.getAdapter().getItem(position); + /* + FragmentTransaction ft = getFragmentManager().beginTransaction(); + Fragment prev = getFragmentManager().findFragmentByTag("dialog"); - //remove any old dialogs - if(prev != null) ft.remove(prev); - ft.addToBackStack(null); + //remove any old dialogs + if(prev != null) ft.remove(prev); + ft.addToBackStack(null); - //create a new dialog based on this task - - DialogFragment newFragment = DownloadDialogFragment.newInstance(task); + //create a new dialog based on this task + + DialogFragment newFragment = DownloadDialogFragment.newInstance(task); - //show it - newFragment.show(ft, "dialog"); - */ - targetView = arg1; + //show it + newFragment.show(ft, "dialog"); + */ + targetView = arg1; - //determine state - int min = arg0.getTop(); - int max = arg0.getBottom(); - int top = targetView.getTop(); + //determine state + int min = arg0.getTop(); + int max = arg0.getBottom(); + int top = targetView.getTop(); - previousXCoord = top; - for(OnItemMovementListener listener : listeners){ - listener.onNewItemSelected(task, top, min, max, targetView.getHeight()*2); - } - } + previousXCoord = top; + for(OnItemMovementListener listener : listeners){ + listener.onNewItemSelected(task, top, min, max, targetView.getHeight()*2); + } + } - private int previousXCoord = 0; + private int previousXCoord = 0; - /* - * (non-Javadoc) - * @see android.widget.AbsListView.OnScrollListener#onScroll(android.widget.AbsListView, int, int, int) - * - * Android renews the Items used in the view, so when a user scroll down the list, - * as soon as the item has dissapeard from the list it gets reused at the bottom. - * - * For this reason we cannot just keep sending the targetView.getTop() but we must - * remember if the view is supposed to be at the top or bottom of the list. We - * remember this with int state, - * - 0 means we've got accurate reading from getTop() - * - -1 means it's somewhere at the top of the list - * - 1 means it's at the bottom somewhere - */ - public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { - if(targetView != null){ - int top = targetView.getTop() + (targetView.getHeight()/2); - int min = view.getTop(); - int max = view.getBottom(); + /* + * (non-Javadoc) + * @see android.widget.AbsListView.OnScrollListener#onScroll(android.widget.AbsListView, int, int, int) + * + * Android renews the Items used in the view, so when a user scroll down the list, + * as soon as the item has dissapeard from the list it gets reused at the bottom. + * + * For this reason we cannot just keep sending the targetView.getTop() but we must + * remember if the view is supposed to be at the top or bottom of the list. We + * remember this with int state, + * - 0 means we've got accurate reading from getTop() + * - -1 means it's somewhere at the top of the list + * - 1 means it's at the bottom somewhere + */ + public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { + if(targetView != null){ + int top = targetView.getTop() + (targetView.getHeight()/2); + int min = view.getTop(); + int max = view.getBottom(); - if(Math.abs(previousXCoord - top) > targetView.getHeight()*2 ){ - top = previousXCoord; - } + if(Math.abs(previousXCoord - top) > targetView.getHeight()*2 ){ + top = previousXCoord; + } - for(OnItemMovementListener listener : listeners){ - listener.onViewMoved(top, min, max); - } + for(OnItemMovementListener listener : listeners){ + listener.onViewMoved(top, min, max); + } - previousXCoord = top; - } - } + previousXCoord = top; + } + } - public void onScrollStateChanged(AbsListView view, int scrollState) { - switch(scrollState){ - case OnScrollListener.SCROLL_STATE_FLING: Log.d("tag", "fling"); break; - case OnScrollListener.SCROLL_STATE_IDLE:Log.d("tag", "idle"); break; - case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:Log.d("tag", "scroll"); break; + public void onScrollStateChanged(AbsListView view, int scrollState) { + switch(scrollState){ + case OnScrollListener.SCROLL_STATE_FLING: Log.d("tag", "fling"); break; + case OnScrollListener.SCROLL_STATE_IDLE:Log.d("tag", "idle"); break; + case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:Log.d("tag", "scroll"); break; - } + } - } + } } interface OnItemMovementListener{ - /** - * When I new item has been selected this method will be called - * @param task The task which goes with this item - * @param x The middle of this item - * @param minX The top of the parent of this item - * @param maxX The bottom of the parent of this item - */ - void onNewItemSelected(DownloadPackage task, int x, int minX, int maxX, int size); + /** + * When I new item has been selected this method will be called + * @param task The task which goes with this item + * @param x The middle of this item + * @param minX The top of the parent of this item + * @param maxX The bottom of the parent of this item + */ + void onNewItemSelected(DownloadPackage task, int x, int minX, int maxX, int size); - /** - * When the item has been moved this method is called - * @param x The middle of this item - * @param minX The top of the parent of this item - * @param maxX The bottom of the parent of this item - */ - void onViewMoved(int x, int minX, int maxX); + /** + * When the item has been moved this method is called + * @param x The middle of this item + * @param minX The top of the parent of this item + * @param maxX The bottom of the parent of this item + */ + void onViewMoved(int x, int minX, int maxX); } diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadPackage.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadPackage.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadPackage.java Tue Nov 10 20:43:13 2015 +0100 @@ -32,155 +32,155 @@ import android.preference.PreferenceManager; public class DownloadPackage implements Parcelable{ - private String url_without_suffix; - private String pathToStore; - private String representation; - private String description; - private int versionNumber; - private final Status status; - private int uniqueId; + private String url_without_suffix; + private String pathToStore; + private String representation; + private String description; + private int versionNumber; + private final Status status; + private int uniqueId; - public DownloadPackage(Parcel src){ - url_without_suffix = src.readString(); - pathToStore = src.readString(); - representation = src.readString(); - versionNumber = src.readInt(); - status = Status.values()[src.readInt()]; - description = src.readString(); - uniqueId = src.readInt(); - } + public DownloadPackage(Parcel src){ + url_without_suffix = src.readString(); + pathToStore = src.readString(); + representation = src.readString(); + versionNumber = src.readInt(); + status = Status.values()[src.readInt()]; + description = src.readString(); + uniqueId = src.readInt(); + } - public DownloadPackage(Context c, String _url_without_suffix, String path, int version, String _representation, String _description, int _uniqueId){ - url_without_suffix = _url_without_suffix; - pathToStore = path; - representation = _representation; - versionNumber = version; - description = _description; - uniqueId = _uniqueId; + public DownloadPackage(Context c, String _url_without_suffix, String path, int version, String _representation, String _description, int _uniqueId){ + url_without_suffix = _url_without_suffix; + pathToStore = path; + representation = _representation; + versionNumber = version; + description = _description; + uniqueId = _uniqueId; - //determine if the user has already downloaded this version - SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(c); - int currentVersion = sharedPref.getInt(representation, -1); - if(currentVersion == versionNumber) status = Status.CURRENTVERSION; - else if (currentVersion < versionNumber) status = Status.NEWERVERSION; - else status = Status.OLDERVERSION; - } + //determine if the user has already downloaded this version + SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(c); + int currentVersion = sharedPref.getInt(representation, -1); + if(currentVersion == versionNumber) status = Status.CURRENTVERSION; + else if (currentVersion < versionNumber) status = Status.NEWERVERSION; + else status = Status.OLDERVERSION; + } - public Status getStatus(){ - return status; - } + public Status getStatus(){ + return status; + } - public String getURL(){ - return url_without_suffix; - } + public String getURL(){ + return url_without_suffix; + } - public String getPathToStore(){ - return pathToStore; - } + public String getPathToStore(){ + return pathToStore; + } - public String toString(){ - return representation; - } + public String toString(){ + return representation; + } - public int describeContents() { - return 0; - } - public int getId(){ - return uniqueId; - } + public int describeContents() { + return 0; + } + public int getId(){ + return uniqueId; + } - public void writeToParcel(Parcel dest, int flags) { - dest.writeString(url_without_suffix); - dest.writeString(pathToStore); - dest.writeString(representation); - dest.writeInt(versionNumber); - dest.writeInt(status.ordinal()); - dest.writeString(description); - } + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(url_without_suffix); + dest.writeString(pathToStore); + dest.writeString(representation); + dest.writeInt(versionNumber); + dest.writeInt(status.ordinal()); + dest.writeString(description); + } - public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { - public DownloadPackage createFromParcel(Parcel source) { - return new DownloadPackage(source); - } - public DownloadPackage[] newArray(int size) { - return new DownloadPackage[size]; - } - }; + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + public DownloadPackage createFromParcel(Parcel source) { + return new DownloadPackage(source); + } + public DownloadPackage[] newArray(int size) { + return new DownloadPackage[size]; + } + }; - /* - * We enter with a XmlPullParser.Start_tag with name "task" - */ - public static DownloadPackage getTaskFromXML(Context c, XmlPullParser xmlPuller) throws XmlPullParserException, IOException{ - String url = null; - String path = null; - String representation = null; - String description = null; - int uniqueId = -1; - int version = -1; + /* + * We enter with a XmlPullParser.Start_tag with name "task" + */ + public static DownloadPackage getTaskFromXML(Context c, XmlPullParser xmlPuller) throws XmlPullParserException, IOException{ + String url = null; + String path = null; + String representation = null; + String description = null; + int uniqueId = -1; + int version = -1; - int eventType = DownloadPackage.getEventType(xmlPuller);//get the next token, should be a start tag - while(eventType != XmlPullParser.END_DOCUMENT){ - switch(eventType){ - case XmlPullParser.START_TAG: - String name = xmlPuller.getName().toLowerCase(); - if(DownloadPackage.getEventType(xmlPuller) == XmlPullParser.TEXT){ - String text = xmlPuller.getText().trim(); - if(name.equals("url")){ - url = text; - }else if(name.equals("version")){ - try{ - version = Integer.parseInt(text); - }catch (NumberFormatException e){ - e.printStackTrace(); - version = -1; - } - }else if(name.equals("path")){ - path = FileUtils.getDataPathFile(c, text).getAbsolutePath(); - }else if(name.equals("representation")){ - representation = text; - }else if(name.equals("description")){ - description = text; - }else if(name.equals("uniqueid")){ - try{ - uniqueId = Integer.parseInt(text); - }catch (NumberFormatException e){ - e.printStackTrace(); - version = -1; - } - } - } - DownloadPackage.getEventType(xmlPuller);//endtag - break; - case XmlPullParser.END_TAG: - if(xmlPuller.getName().toLowerCase().equals("task") && url != null && path != null && version != -1 && representation != null){ - return new DownloadPackage(c, url, path, version, representation, description, uniqueId); - }else{ - throw new XmlPullParserException("XML download parsing: missing tags"); - } - case XmlPullParser.TEXT: - throw new XmlPullParserException("Wrong tag recieved got TEXT : " + xmlPuller.getText()); - default: - throw new XmlPullParserException("Wrong tag recieved got: " + eventType); - } - eventType = DownloadPackage.getEventType(xmlPuller); - } - throw new XmlPullParserException("Xml: unexpected endofdocument tag"); - } + int eventType = DownloadPackage.getEventType(xmlPuller);//get the next token, should be a start tag + while(eventType != XmlPullParser.END_DOCUMENT){ + switch(eventType){ + case XmlPullParser.START_TAG: + String name = xmlPuller.getName().toLowerCase(); + if(DownloadPackage.getEventType(xmlPuller) == XmlPullParser.TEXT){ + String text = xmlPuller.getText().trim(); + if(name.equals("url")){ + url = text; + }else if(name.equals("version")){ + try{ + version = Integer.parseInt(text); + }catch (NumberFormatException e){ + e.printStackTrace(); + version = -1; + } + }else if(name.equals("path")){ + path = FileUtils.getDataPathFile(c, text).getAbsolutePath(); + }else if(name.equals("representation")){ + representation = text; + }else if(name.equals("description")){ + description = text; + }else if(name.equals("uniqueid")){ + try{ + uniqueId = Integer.parseInt(text); + }catch (NumberFormatException e){ + e.printStackTrace(); + version = -1; + } + } + } + DownloadPackage.getEventType(xmlPuller);//endtag + break; + case XmlPullParser.END_TAG: + if(xmlPuller.getName().toLowerCase().equals("task") && url != null && path != null && version != -1 && representation != null){ + return new DownloadPackage(c, url, path, version, representation, description, uniqueId); + }else{ + throw new XmlPullParserException("XML download parsing: missing tags"); + } + case XmlPullParser.TEXT: + throw new XmlPullParserException("Wrong tag recieved got TEXT : " + xmlPuller.getText()); + default: + throw new XmlPullParserException("Wrong tag recieved got: " + eventType); + } + eventType = DownloadPackage.getEventType(xmlPuller); + } + throw new XmlPullParserException("Xml: unexpected endofdocument tag"); + } - /** - * Skips whitespaces.. - */ - private static int getEventType(XmlPullParser xmlPuller)throws XmlPullParserException, IOException{ - int eventType = xmlPuller.next(); - while(eventType == XmlPullParser.TEXT && xmlPuller.isWhitespace()){ - eventType = xmlPuller.next(); - } - return eventType; - } + /** + * Skips whitespaces.. + */ + private static int getEventType(XmlPullParser xmlPuller)throws XmlPullParserException, IOException{ + int eventType = xmlPuller.next(); + while(eventType == XmlPullParser.TEXT && xmlPuller.isWhitespace()){ + eventType = xmlPuller.next(); + } + return eventType; + } } enum Status{ - CURRENTVERSION, NEWERVERSION, OLDERVERSION; + CURRENTVERSION, NEWERVERSION, OLDERVERSION; } diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadService.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadService.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadService.java Tue Nov 10 20:43:13 2015 +0100 @@ -37,194 +37,194 @@ import android.widget.RemoteViews; public class DownloadService extends Service { - public final static String INTENT_TASKID = "taskId"; - public final static String INTENT_TASK = "task"; + public final static String INTENT_TASKID = "taskId"; + public final static String INTENT_TASK = "task"; - public static final String PREF_DOWNLOADED = "downloaded"; - public static final int MSG_CANCEL = 0; - public static final int MSG_UNREGISTER_CLIENT = 2; - public final static int MSG_ADDTASK = 4; + public static final String PREF_DOWNLOADED = "downloaded"; + public static final int MSG_CANCEL = 0; + public static final int MSG_UNREGISTER_CLIENT = 2; + public final static int MSG_ADDTASK = 4; - public static final int NOTIFICATION_PROCESSING = 0; - public static final int NOTIFICATION_DONE = 1; + public static final int NOTIFICATION_PROCESSING = 0; + public static final int NOTIFICATION_DONE = 1; - private DownloadAsyncTask asyncExecutor; + private DownloadAsyncTask asyncExecutor; - private DownloadHandler handler = new DownloadHandler(); - private final Messenger messenger = new Messenger(handler); + private DownloadHandler handler = new DownloadHandler(); + private final Messenger messenger = new Messenger(handler); - private NotificationManager nM; - private RemoteViews contentView; + private NotificationManager nM; + private RemoteViews contentView; - private LinkedList downloadTasks = new LinkedList(); - private DownloadTask currentTask = null; + private LinkedList downloadTasks = new LinkedList(); + private DownloadTask currentTask = null; - public class DownloadHandler extends Handler{ + public class DownloadHandler extends Handler{ - public void handleMessage(Message msg){ - if(msg.obj != null){ - DownloadPackage pack = (DownloadPackage) msg.obj; - DownloadTask task = null; - Messenger replyToMessenger = msg.replyTo; - for(DownloadTask _task : downloadTasks){ - if(_task.getPackage().equals(pack)){ - task = _task; - break; - } - } + public void handleMessage(Message msg){ + if(msg.obj != null){ + DownloadPackage pack = (DownloadPackage) msg.obj; + DownloadTask task = null; + Messenger replyToMessenger = msg.replyTo; + for(DownloadTask _task : downloadTasks){ + if(_task.getPackage().equals(pack)){ + task = _task; + break; + } + } - switch(msg.what){ - case MSG_ADDTASK: - if(task == null){ - task = new DownloadTask(pack); - downloadTasks.add(task); - } + switch(msg.what){ + case MSG_ADDTASK: + if(task == null){ + task = new DownloadTask(pack); + downloadTasks.add(task); + } - task.addClient(replyToMessenger); - runNextTask(); - return; - case MSG_CANCEL: - if(task != null && task.getPackage().equals(pack) && task.getStatus() == TASK_STATE.PENDING){ - downloadTasks.remove(task); - } - if(currentTask != null && currentTask.getPackage().equals(pack)){//TODO synchronization problem? - asyncExecutor.cancel(false); - } - return; - case MSG_UNREGISTER_CLIENT: - if(task != null){ - task.removeClient(replyToMessenger); - } - return; - } - } - } - } + task.addClient(replyToMessenger); + runNextTask(); + return; + case MSG_CANCEL: + if(task != null && task.getPackage().equals(pack) && task.getStatus() == TASK_STATE.PENDING){ + downloadTasks.remove(task); + } + if(currentTask != null && currentTask.getPackage().equals(pack)){//TODO synchronization problem? + asyncExecutor.cancel(false); + } + return; + case MSG_UNREGISTER_CLIENT: + if(task != null){ + task.removeClient(replyToMessenger); + } + return; + } + } + } + } - public void onCreate(){ - super.onCreate(); - nM = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); - } - public IBinder onBind(Intent intent) { - return messenger.getBinder(); - } + public void onCreate(){ + super.onCreate(); + nM = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); + } + public IBinder onBind(Intent intent) { + return messenger.getBinder(); + } - private void runNextTask(){ - if(asyncExecutor == null){//if (task isnt running right now) ... - currentTask = downloadTasks.poll(); - if(currentTask != null){ - asyncExecutor = new DownloadAsyncTask(currentTask); - asyncExecutor.execute(currentTask.getPackage()); - } - } - } + private void runNextTask(){ + if(asyncExecutor == null){//if (task isnt running right now) ... + currentTask = downloadTasks.poll(); + if(currentTask != null){ + asyncExecutor = new DownloadAsyncTask(currentTask); + asyncExecutor.execute(currentTask.getPackage()); + } + } + } - public void onDestroy(){ - super.onDestroy(); - asyncExecutor.cancel(false); - } + public void onDestroy(){ + super.onDestroy(); + asyncExecutor.cancel(false); + } - class DownloadTask { - private final DownloadPackage pack; - private TASK_STATE status = TASK_STATE.PENDING; - private Notification progressNotification, doneNotification; + class DownloadTask { + private final DownloadPackage pack; + private TASK_STATE status = TASK_STATE.PENDING; + private Notification progressNotification, doneNotification; - //I expect little to no removeClient calls that's why we go for a list rather than a map - private final List clients; + //I expect little to no removeClient calls that's why we go for a list rather than a map + private final List clients; - public DownloadTask(DownloadPackage _pack){ - pack = _pack; - clients = new LinkedList(); - } + public DownloadTask(DownloadPackage _pack){ + pack = _pack; + clients = new LinkedList(); + } - public void addClient(Messenger messenger){ - clients.add(messenger); - } - public void removeClient(Messenger messenger){ - clients.remove(messenger); - } + public void addClient(Messenger messenger){ + clients.add(messenger); + } + public void removeClient(Messenger messenger){ + clients.remove(messenger); + } - public DownloadPackage getPackage(){ - return pack; - } + public DownloadPackage getPackage(){ + return pack; + } - public TASK_STATE getStatus(){ - return status; - } + public TASK_STATE getStatus(){ + return status; + } - public void sendMessageToClients(Message msg){ - for(Messenger messenger : clients){ - try { - messenger.send(msg); - } catch (RemoteException e) { - e.printStackTrace(); - } - } - } + public void sendMessageToClients(Message msg){ + for(Messenger messenger : clients){ + try { + messenger.send(msg); + } catch (RemoteException e) { + e.printStackTrace(); + } + } + } - /* - * Callbacks called from the async tasks - */ + /* + * Callbacks called from the async tasks + */ - //Thread safe method to let clients know the processing is starting and will process int max kbytes - public void start(int max){ - progressNotification = new Notification(R.drawable.statusbar, getString(R.string.notification_title), System.currentTimeMillis()); - progressNotification.flags |= Notification.FLAG_ONGOING_EVENT; + //Thread safe method to let clients know the processing is starting and will process int max kbytes + public void start(int max){ + progressNotification = new Notification(R.drawable.statusbar, getString(R.string.notification_title), System.currentTimeMillis()); + progressNotification.flags |= Notification.FLAG_ONGOING_EVENT; - contentView = new RemoteViews(getPackageName(), R.layout.notification); - contentView.setProgressBar(R.id.notification_progress, 100, 34, false); - progressNotification.contentView = contentView; + contentView = new RemoteViews(getPackageName(), R.layout.notification); + contentView.setProgressBar(R.id.notification_progress, 100, 34, false); + progressNotification.contentView = contentView; - PendingIntent contentIntent = PendingIntent.getActivity(DownloadService.this, 0, new Intent(DownloadService.this, DownloadListActivity.class), Intent.FLAG_ACTIVITY_NEW_TASK); - progressNotification.contentIntent = contentIntent; + PendingIntent contentIntent = PendingIntent.getActivity(DownloadService.this, 0, new Intent(DownloadService.this, DownloadListActivity.class), Intent.FLAG_ACTIVITY_NEW_TASK); + progressNotification.contentIntent = contentIntent; - startForeground(NOTIFICATION_PROCESSING, progressNotification); + startForeground(NOTIFICATION_PROCESSING, progressNotification); - Message msg = Message.obtain(null, DownloadFragment.MSG_START, max, 0); - sendMessageToClients(msg); - } + Message msg = Message.obtain(null, DownloadFragment.MSG_START, max, 0); + sendMessageToClients(msg); + } - //periodically gets called by the ASyncTask, we can't tell for sure when it's called - public void update(int progress, int max, String fileName){ - progress = (progress/1024); + //periodically gets called by the ASyncTask, we can't tell for sure when it's called + public void update(int progress, int max, String fileName){ + progress = (progress/1024); - contentView.setProgressBar(R.id.notification_progress, max, progress, false); - contentView.setTextViewText(R.id.progressbar_sub, String.format("%dkb/%dkb (Compressed sizes)", progress, max)); - nM.notify(NOTIFICATION_PROCESSING, progressNotification); + contentView.setProgressBar(R.id.notification_progress, max, progress, false); + contentView.setTextViewText(R.id.progressbar_sub, String.format("%dkb/%dkb (Compressed sizes)", progress, max)); + nM.notify(NOTIFICATION_PROCESSING, progressNotification); - sendMessageToClients(Message.obtain(handler, DownloadFragment.MSG_UPDATE, progress, max, fileName)); - } + sendMessageToClients(Message.obtain(handler, DownloadFragment.MSG_UPDATE, progress, max, fileName)); + } - //Call back from the ASync task when the task has either run into an error or finished otherwise - public void done(int result){ - switch(result){ - case DownloadAsyncTask.EXIT_SUCCESS: sendMessageToClients(Message.obtain(handler, DownloadFragment.MSG_DONE)); break; - case DownloadAsyncTask.EXIT_CONNERROR: sendMessageToClients(Message.obtain(handler, DownloadFragment.MSG_FAILED, DownloadAsyncTask.EXIT_CONNERROR, 0)); break; - case DownloadAsyncTask.EXIT_FNF: sendMessageToClients(Message.obtain(handler, DownloadFragment.MSG_FAILED, DownloadAsyncTask.EXIT_FNF, 0)); break; - case DownloadAsyncTask.EXIT_MD5: sendMessageToClients(Message.obtain(handler, DownloadFragment.MSG_FAILED, DownloadAsyncTask.EXIT_MD5, 0)); break; - case DownloadAsyncTask.EXIT_URLFAIL: sendMessageToClients(Message.obtain(handler, DownloadFragment.MSG_FAILED, DownloadAsyncTask.EXIT_URLFAIL, 0)); break; - case DownloadAsyncTask.EXIT_CANCELLED: sendMessageToClients(Message.obtain(handler, DownloadFragment.MSG_DONE)); break; - } - - stopForeground(true); - nM.cancel(NOTIFICATION_PROCESSING); + //Call back from the ASync task when the task has either run into an error or finished otherwise + public void done(int result){ + switch(result){ + case DownloadAsyncTask.EXIT_SUCCESS: sendMessageToClients(Message.obtain(handler, DownloadFragment.MSG_DONE)); break; + case DownloadAsyncTask.EXIT_CONNERROR: sendMessageToClients(Message.obtain(handler, DownloadFragment.MSG_FAILED, DownloadAsyncTask.EXIT_CONNERROR, 0)); break; + case DownloadAsyncTask.EXIT_FNF: sendMessageToClients(Message.obtain(handler, DownloadFragment.MSG_FAILED, DownloadAsyncTask.EXIT_FNF, 0)); break; + case DownloadAsyncTask.EXIT_MD5: sendMessageToClients(Message.obtain(handler, DownloadFragment.MSG_FAILED, DownloadAsyncTask.EXIT_MD5, 0)); break; + case DownloadAsyncTask.EXIT_URLFAIL: sendMessageToClients(Message.obtain(handler, DownloadFragment.MSG_FAILED, DownloadAsyncTask.EXIT_URLFAIL, 0)); break; + case DownloadAsyncTask.EXIT_CANCELLED: sendMessageToClients(Message.obtain(handler, DownloadFragment.MSG_DONE)); break; + } - String title = getString(R.string.notification_title); + stopForeground(true); + nM.cancel(NOTIFICATION_PROCESSING); + + String title = getString(R.string.notification_title); - doneNotification = new Notification(R.drawable.icon, title, System.currentTimeMillis()); - doneNotification.flags |= Notification.FLAG_AUTO_CANCEL; - PendingIntent contentIntent = PendingIntent.getActivity(DownloadService.this, 0, new Intent(DownloadService.this, DownloadListActivity.class), Intent.FLAG_ACTIVITY_NEW_TASK); - doneNotification.setLatestEventInfo(DownloadService.this, title, getString(R.string.notification_done) + pack, contentIntent); - nM.notify(pack.getId(), doneNotification); + doneNotification = new Notification(R.drawable.icon, title, System.currentTimeMillis()); + doneNotification.flags |= Notification.FLAG_AUTO_CANCEL; + PendingIntent contentIntent = PendingIntent.getActivity(DownloadService.this, 0, new Intent(DownloadService.this, DownloadListActivity.class), Intent.FLAG_ACTIVITY_NEW_TASK); + doneNotification.setLatestEventInfo(DownloadService.this, title, getString(R.string.notification_done) + pack, contentIntent); + nM.notify(pack.getId(), doneNotification); - asyncExecutor = null; - runNextTask();//see if there are more tasks - } + asyncExecutor = null; + runNextTask();//see if there are more tasks + } - } + } - enum TASK_STATE{ - RUNNING, FINISHED, PENDING; - } + enum TASK_STATE{ + RUNNING, FINISHED, PENDING; + } } diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/EngineProtocol/PascalExports.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/EngineProtocol/PascalExports.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/EngineProtocol/PascalExports.java Tue Nov 10 20:43:13 2015 +0100 @@ -21,28 +21,28 @@ package org.hedgewars.hedgeroid.EngineProtocol; public class PascalExports { - public static Object engineMutex = new Object(); + public static Object engineMutex = new Object(); - static{ - System.loadLibrary("SDL"); - System.loadLibrary("SDL_image"); - System.loadLibrary("mikmod"); - System.loadLibrary("SDL_net"); - System.loadLibrary("SDL_mixer"); - System.loadLibrary("SDL_ttf"); - System.loadLibrary("lua5.1"); - System.loadLibrary("physfs"); - System.loadLibrary("physlayer"); - System.loadLibrary("hwengine"); - } - - public static native int HWgetMaxNumberOfTeams(); + static{ + System.loadLibrary("SDL"); + System.loadLibrary("SDL_image"); + System.loadLibrary("mikmod"); + System.loadLibrary("SDL_net"); + System.loadLibrary("SDL_mixer"); + System.loadLibrary("SDL_ttf"); + System.loadLibrary("lua5.1"); + System.loadLibrary("physfs"); + System.loadLibrary("physlayer"); + System.loadLibrary("hwengine"); + } + + public static native int HWgetMaxNumberOfTeams(); private static native void HWGenLandPreview(int port); public static void synchronizedGenLandPreview(int port) { - synchronized(engineMutex) { - HWGenLandPreview(port); - } + synchronized(engineMutex) { + HWGenLandPreview(port); + } } - + } diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/GameConnection.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/GameConnection.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/GameConnection.java Tue Nov 10 20:43:13 2015 +0100 @@ -48,175 +48,175 @@ * This class handles both talking to the engine (IPC) for running a game, and * coordinating with the netconn if it is a netgame, using the frontlib for the * actual IPC networking communication. - * + * * After creating the GameConnection object, it will communicate with the engine * on its own thread. It shuts itself down as soon as the connection to the engine * is lost. */ public final class GameConnection { - private static final Handler mainHandler = new Handler(Looper.getMainLooper()); - - public final int port; - private final HandlerThread thread; - private final Handler handler; - private TickHandler tickHandler; - private final Netplay netplay; // ==null if not a netgame - private GameconnPtr conn; - - private GameConnection(GameconnPtr conn, Netplay netplay) { - this.conn = conn; - this.port = Flib.INSTANCE.flib_gameconn_getport(conn); - this.netplay = netplay; - this.thread = new HandlerThread("IPCThread"); - thread.start(); - this.handler = new Handler(thread.getLooper()); - } - - private void setupConnection() { - tickHandler = new TickHandler(thread.getLooper(), 50, tickCb); - tickHandler.start(); - - if(netplay != null) { - mainHandler.post(new Runnable() { - public void run() { - netplay.registerGameMessageListener(gameMessageListener); - } - }); - Flib.INSTANCE.flib_gameconn_onChat(conn, chatCb, null); - Flib.INSTANCE.flib_gameconn_onEngineMessage(conn, engineMessageCb, null); - } - Flib.INSTANCE.flib_gameconn_onConnect(conn, connectCb, null); - Flib.INSTANCE.flib_gameconn_onDisconnect(conn, disconnectCb, null); - Flib.INSTANCE.flib_gameconn_onErrorMessage(conn, errorMessageCb, null); - } - - /** - * Start a new IPC server to communicate with the engine. - * Performs networking operations, don't run on the UI thread. - * @throws ConnectException if we can't set up the IPC server - */ - public static GameConnection forNetgame(final GameConfig config, Netplay netplay) throws ConnectException { - final String playerName = netplay.getPlayerName(); - GameconnPtr conn = Flib.INSTANCE.flib_gameconn_create(playerName, GameSetupPtr.createJavaOwned(config), true); - if(conn == null) { - throw new ConnectException(); - } - GameConnection result = new GameConnection(conn, netplay); - result.setupConnection(); - return result; - } - - /** - * Start a new IPC server to communicate with the engine. - * Performs networking operations, don't run on the UI thread. - * @throws ConnectException if we can't set up the IPC server - */ - public static GameConnection forLocalGame(final GameConfig config) throws ConnectException { - GameconnPtr conn = Flib.INSTANCE.flib_gameconn_create("Player", GameSetupPtr.createJavaOwned(config), false); - if(conn == null) { - throw new ConnectException(); - } - GameConnection result = new GameConnection(conn, null); - result.setupConnection(); - return result; - } - - private final Runnable tickCb = new Runnable() { - public void run() { - Flib.INSTANCE.flib_gameconn_tick(conn); - } - }; - - // runs on the IPCThread - private void shutdown() { - tickHandler.stop(); - thread.quit(); - Flib.INSTANCE.flib_gameconn_destroy(conn); - conn = null; - if(netplay != null) { - mainHandler.post(new Runnable() { - public void run() { - netplay.unregisterGameMessageListener(gameMessageListener); - } - }); - } - } - - // runs on the IPCThread - private final StrBoolCallback chatCb = new StrBoolCallback() { - public void callback(Pointer context, String message, boolean teamChat) { - if(teamChat) { - netplay.sendTeamChat(message); - } else { - netplay.sendChat(message); - } - } - }; - - // runs on the IPCThread - private final VoidCallback connectCb = new VoidCallback() { - public void callback(Pointer context) { - Log.i("GameConnection", "Connected"); - } - }; - - // runs on the IPCThread - private final IntCallback disconnectCb = new IntCallback() { - public void callback(Pointer context, int reason) { - if(netplay != null) { - netplay.sendRoundFinished(reason==Frontlib.GAME_END_FINISHED); - } - shutdown(); - } - }; - - // runs on the IPCThread - private final BytesCallback engineMessageCb = new BytesCallback() { - public void callback(Pointer context, ByteArrayPtr buffer, NativeSizeT size) { - netplay.sendEngineMessage(buffer.deref(size.intValue())); - } - }; - - // runs on the IPCThread - private final StrCallback errorMessageCb = new StrCallback() { - public void callback(Pointer context, String message) { - Log.e("GameConnection", message); - } - }; - - // runs on any thread - private final GameMessageListener gameMessageListener = new GameMessageListener() { - public void onNetDisconnected() { - handler.post(new Runnable() { - public void run() { - Flib.INSTANCE.flib_gameconn_send_quit(conn); - } - }); - } - - public void onMessage(final int type, final String message) { - handler.post(new Runnable() { - public void run() { - Flib.INSTANCE.flib_gameconn_send_textmsg(conn, type, message); - } - }); - } - - public void onEngineMessage(final byte[] em) { - handler.post(new Runnable() { - public void run() { - ByteArrayPtr ptr = ByteArrayPtr.createJavaOwned(em); - Flib.INSTANCE.flib_gameconn_send_enginemsg(conn, ptr, NativeSizeT.valueOf(em.length)); - } - }); - } - - public void onChatMessage(final String nick, final String message) { - handler.post(new Runnable() { - public void run() { - Flib.INSTANCE.flib_gameconn_send_chatmsg(conn, nick, message); - } - }); - } - }; + private static final Handler mainHandler = new Handler(Looper.getMainLooper()); + + public final int port; + private final HandlerThread thread; + private final Handler handler; + private TickHandler tickHandler; + private final Netplay netplay; // ==null if not a netgame + private GameconnPtr conn; + + private GameConnection(GameconnPtr conn, Netplay netplay) { + this.conn = conn; + this.port = Flib.INSTANCE.flib_gameconn_getport(conn); + this.netplay = netplay; + this.thread = new HandlerThread("IPCThread"); + thread.start(); + this.handler = new Handler(thread.getLooper()); + } + + private void setupConnection() { + tickHandler = new TickHandler(thread.getLooper(), 50, tickCb); + tickHandler.start(); + + if(netplay != null) { + mainHandler.post(new Runnable() { + public void run() { + netplay.registerGameMessageListener(gameMessageListener); + } + }); + Flib.INSTANCE.flib_gameconn_onChat(conn, chatCb, null); + Flib.INSTANCE.flib_gameconn_onEngineMessage(conn, engineMessageCb, null); + } + Flib.INSTANCE.flib_gameconn_onConnect(conn, connectCb, null); + Flib.INSTANCE.flib_gameconn_onDisconnect(conn, disconnectCb, null); + Flib.INSTANCE.flib_gameconn_onErrorMessage(conn, errorMessageCb, null); + } + + /** + * Start a new IPC server to communicate with the engine. + * Performs networking operations, don't run on the UI thread. + * @throws ConnectException if we can't set up the IPC server + */ + public static GameConnection forNetgame(final GameConfig config, Netplay netplay) throws ConnectException { + final String playerName = netplay.getPlayerName(); + GameconnPtr conn = Flib.INSTANCE.flib_gameconn_create(playerName, GameSetupPtr.createJavaOwned(config), true); + if(conn == null) { + throw new ConnectException(); + } + GameConnection result = new GameConnection(conn, netplay); + result.setupConnection(); + return result; + } + + /** + * Start a new IPC server to communicate with the engine. + * Performs networking operations, don't run on the UI thread. + * @throws ConnectException if we can't set up the IPC server + */ + public static GameConnection forLocalGame(final GameConfig config) throws ConnectException { + GameconnPtr conn = Flib.INSTANCE.flib_gameconn_create("Player", GameSetupPtr.createJavaOwned(config), false); + if(conn == null) { + throw new ConnectException(); + } + GameConnection result = new GameConnection(conn, null); + result.setupConnection(); + return result; + } + + private final Runnable tickCb = new Runnable() { + public void run() { + Flib.INSTANCE.flib_gameconn_tick(conn); + } + }; + + // runs on the IPCThread + private void shutdown() { + tickHandler.stop(); + thread.quit(); + Flib.INSTANCE.flib_gameconn_destroy(conn); + conn = null; + if(netplay != null) { + mainHandler.post(new Runnable() { + public void run() { + netplay.unregisterGameMessageListener(gameMessageListener); + } + }); + } + } + + // runs on the IPCThread + private final StrBoolCallback chatCb = new StrBoolCallback() { + public void callback(Pointer context, String message, boolean teamChat) { + if(teamChat) { + netplay.sendTeamChat(message); + } else { + netplay.sendChat(message); + } + } + }; + + // runs on the IPCThread + private final VoidCallback connectCb = new VoidCallback() { + public void callback(Pointer context) { + Log.i("GameConnection", "Connected"); + } + }; + + // runs on the IPCThread + private final IntCallback disconnectCb = new IntCallback() { + public void callback(Pointer context, int reason) { + if(netplay != null) { + netplay.sendRoundFinished(reason==Frontlib.GAME_END_FINISHED); + } + shutdown(); + } + }; + + // runs on the IPCThread + private final BytesCallback engineMessageCb = new BytesCallback() { + public void callback(Pointer context, ByteArrayPtr buffer, NativeSizeT size) { + netplay.sendEngineMessage(buffer.deref(size.intValue())); + } + }; + + // runs on the IPCThread + private final StrCallback errorMessageCb = new StrCallback() { + public void callback(Pointer context, String message) { + Log.e("GameConnection", message); + } + }; + + // runs on any thread + private final GameMessageListener gameMessageListener = new GameMessageListener() { + public void onNetDisconnected() { + handler.post(new Runnable() { + public void run() { + Flib.INSTANCE.flib_gameconn_send_quit(conn); + } + }); + } + + public void onMessage(final int type, final String message) { + handler.post(new Runnable() { + public void run() { + Flib.INSTANCE.flib_gameconn_send_textmsg(conn, type, message); + } + }); + } + + public void onEngineMessage(final byte[] em) { + handler.post(new Runnable() { + public void run() { + ByteArrayPtr ptr = ByteArrayPtr.createJavaOwned(em); + Flib.INSTANCE.flib_gameconn_send_enginemsg(conn, ptr, NativeSizeT.valueOf(em.length)); + } + }); + } + + public void onChatMessage(final String nick, final String message) { + handler.post(new Runnable() { + public void run() { + Flib.INSTANCE.flib_gameconn_send_chatmsg(conn, nick, message); + } + }); + } + }; } diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/LobbyActivity.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/LobbyActivity.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/LobbyActivity.java Tue Nov 10 20:43:13 2015 +0100 @@ -38,103 +38,103 @@ /** * Activity for the server lobby of a hedgewars server. Allows you to chat, join * and create rooms and interact with a list of players. - * + * * Most of the functionality is handled by various fragments. */ public class LobbyActivity extends FragmentActivity implements TextInputDialogListener, NetplayStateListener { - private static final int DIALOG_CREATE_ROOM = 0; - + private static final int DIALOG_CREATE_ROOM = 0; + private TabHost tabHost; private Netplay netplay; - + @Override protected void onCreate(Bundle icicle) { super.onCreate(icicle); - + setContentView(R.layout.activity_lobby); ChatFragment chatFragment = (ChatFragment)getSupportFragmentManager().findFragmentById(R.id.chatFragment); chatFragment.setInRoom(false); - + FragmentTransaction trans = getSupportFragmentManager().beginTransaction(); trans.add(new NetplayStateFragment(), "netplayFragment"); trans.commit(); - + netplay = Netplay.getAppInstance(getApplicationContext()); - + // Set up a tabbed UI for medium and small screens tabHost = (TabHost)findViewById(android.R.id.tabhost); if(tabHost != null) { - tabHost.setup(); - tabHost.getTabWidget().setOrientation(LinearLayout.VERTICAL); + tabHost.setup(); + tabHost.getTabWidget().setOrientation(LinearLayout.VERTICAL); - tabHost.addTab(tabHost.newTabSpec("rooms").setIndicator(UiUtils.createVerticalTabIndicator(tabHost, R.string.lobby_tab_rooms, R.drawable.roomlist_ingame)).setContent(R.id.roomListFragment)); - tabHost.addTab(tabHost.newTabSpec("chat").setIndicator(UiUtils.createVerticalTabIndicator(tabHost, R.string.lobby_tab_chat, R.drawable.edit)).setContent(R.id.chatFragment)); - tabHost.addTab(tabHost.newTabSpec("players").setIndicator(UiUtils.createVerticalTabIndicator(tabHost, R.string.lobby_tab_players, R.drawable.human)).setContent(R.id.playerListFragment)); - - if (icicle != null) { - tabHost.setCurrentTabByTag(icicle.getString("currentTab")); - } + tabHost.addTab(tabHost.newTabSpec("rooms").setIndicator(UiUtils.createVerticalTabIndicator(tabHost, R.string.lobby_tab_rooms, R.drawable.roomlist_ingame)).setContent(R.id.roomListFragment)); + tabHost.addTab(tabHost.newTabSpec("chat").setIndicator(UiUtils.createVerticalTabIndicator(tabHost, R.string.lobby_tab_chat, R.drawable.edit)).setContent(R.id.chatFragment)); + tabHost.addTab(tabHost.newTabSpec("players").setIndicator(UiUtils.createVerticalTabIndicator(tabHost, R.string.lobby_tab_players, R.drawable.human)).setContent(R.id.playerListFragment)); + + if (icicle != null) { + tabHost.setCurrentTabByTag(icicle.getString("currentTab")); + } } } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - super.onCreateOptionsMenu(menu); - getMenuInflater().inflate(R.menu.lobby_options, menu); - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch(item.getItemId()) { - case R.id.room_create: - TextInputDialog dialog = new TextInputDialog(DIALOG_CREATE_ROOM, R.string.dialog_create_room_title, 0, R.string.dialog_create_room_hint); - dialog.show(getSupportFragmentManager(), "create_room_dialog"); - return true; - case R.id.disconnect: - netplay.disconnect(); - return true; - default: - return super.onOptionsItemSelected(item); - } - } - - @Override - public void onBackPressed() { - netplay.disconnect(); - } - + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + super.onCreateOptionsMenu(menu); + getMenuInflater().inflate(R.menu.lobby_options, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch(item.getItemId()) { + case R.id.room_create: + TextInputDialog dialog = new TextInputDialog(DIALOG_CREATE_ROOM, R.string.dialog_create_room_title, 0, R.string.dialog_create_room_hint); + dialog.show(getSupportFragmentManager(), "create_room_dialog"); + return true; + case R.id.disconnect: + netplay.disconnect(); + return true; + default: + return super.onOptionsItemSelected(item); + } + } + + @Override + public void onBackPressed() { + netplay.disconnect(); + } + @Override protected void onSaveInstanceState(Bundle icicle) { super.onSaveInstanceState(icicle); if(tabHost != null) { - icicle.putString("currentTab", tabHost.getCurrentTabTag()); + icicle.putString("currentTab", tabHost.getCurrentTabTag()); } } - + public void onTextInputDialogSubmitted(int dialogId, String text) { - if(text != null && text.length()>0) { - netplay.sendCreateRoom(text); - } + if(text != null && text.length()>0) { + netplay.sendCreateRoom(text); + } } - + public void onTextInputDialogCancelled(int dialogId) { } - + public void onNetplayStateChanged(State newState) { - switch(newState) { - case CONNECTING: - case NOT_CONNECTED: - finish(); - break; - case ROOM: - startActivity(new Intent(getApplicationContext(), NetRoomActivity.class)); - break; - case LOBBY: - // Do nothing - break; - default: - throw new IllegalStateException("Unknown connection state: "+newState); - } + switch(newState) { + case CONNECTING: + case NOT_CONNECTED: + finish(); + break; + case ROOM: + startActivity(new Intent(getApplicationContext(), NetRoomActivity.class)); + break; + case LOBBY: + // Do nothing + break; + default: + throw new IllegalStateException("Unknown connection state: "+newState); + } } } diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/LobbyPlayerlistAdapter.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/LobbyPlayerlistAdapter.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/LobbyPlayerlistAdapter.java Tue Nov 10 20:43:13 2015 +0100 @@ -41,28 +41,28 @@ * Simple adapter for displaying the list of players in the lobby. */ public class LobbyPlayerlistAdapter extends ObservableTreeMapAdapter { - @Override - protected Comparator getEntryOrder() { - return Player.ADMIN_NAME_ORDER; - } + @Override + protected Comparator getEntryOrder() { + return Player.ADMIN_NAME_ORDER; + } - public View getView(int position, View convertView, ViewGroup parent) { - View v = convertView; - if (v == null) { - LayoutInflater vi = LayoutInflater.from(parent.getContext()); - v = vi.inflate(R.layout.listview_player, null); - } + public View getView(int position, View convertView, ViewGroup parent) { + View v = convertView; + if (v == null) { + LayoutInflater vi = LayoutInflater.from(parent.getContext()); + v = vi.inflate(R.layout.listview_player, null); + } - Player player = getItem(position); - TextView username = (TextView) v.findViewById(android.R.id.text1); - Spannable spannable = new SpannableString(player.name); - if(player.registered) { - spannable.setSpan(new StyleSpan(Typeface.BOLD), 0, spannable.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - } - if(player.admin) { - spannable.setSpan(new ForegroundColorSpan(Color.YELLOW), 0, spannable.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - } - username.setText(spannable); - return v; - } + Player player = getItem(position); + TextView username = (TextView) v.findViewById(android.R.id.text1); + Spannable spannable = new SpannableString(player.name); + if(player.registered) { + spannable.setSpan(new StyleSpan(Typeface.BOLD), 0, spannable.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } + if(player.admin) { + spannable.setSpan(new ForegroundColorSpan(Color.YELLOW), 0, spannable.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } + username.setText(spannable); + return v; + } } \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/LobbyPlayerlistFragment.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/LobbyPlayerlistFragment.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/LobbyPlayerlistFragment.java Tue Nov 10 20:43:13 2015 +0100 @@ -39,60 +39,60 @@ * over the context menu. */ public class LobbyPlayerlistFragment extends ListFragment { - private Netplay netplay; - private LobbyPlayerlistAdapter adapter; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - netplay = Netplay.getAppInstance(getActivity().getApplicationContext()); - adapter = new LobbyPlayerlistAdapter(); - adapter.setSource(netplay.lobbyPlayerlist); - setListAdapter(adapter); - } + private Netplay netplay; + private LobbyPlayerlistAdapter adapter; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + netplay = Netplay.getAppInstance(getActivity().getApplicationContext()); + adapter = new LobbyPlayerlistAdapter(); + adapter.setSource(netplay.lobbyPlayerlist); + setListAdapter(adapter); + } - @Override - public void onDestroy() { - super.onDestroy(); - adapter.invalidate(); - } - - @Override - public void onActivityCreated(Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - registerForContextMenu(getListView()); - } + @Override + public void onDestroy() { + super.onDestroy(); + adapter.invalidate(); + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + registerForContextMenu(getListView()); + } - @Override - public void onCreateContextMenu(ContextMenu menu, View v, - ContextMenuInfo menuInfo) { - super.onCreateContextMenu(menu, v, menuInfo); - AdapterContextMenuInfo info = (AdapterContextMenuInfo)menuInfo; - MenuInflater inflater = getActivity().getMenuInflater(); - inflater.inflate(R.menu.lobby_playerlist_context, menu); - menu.setHeaderIcon(R.drawable.human); - menu.setHeaderTitle(adapter.getItem(info.position).name); - } - - @Override - public boolean onContextItemSelected(MenuItem item) { - AdapterContextMenuInfo info = (AdapterContextMenuInfo)item.getMenuInfo(); - Player player = adapter.getItem(info.position); - switch(item.getItemId()) { - case R.id.player_info: - netplay.sendPlayerInfoQuery(player.name); - return true; - case R.id.player_follow: - netplay.sendFollowPlayer(player.name); - return true; - default: - return super.onContextItemSelected(item); - } - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - return inflater.inflate(R.layout.fragment_playerlist, container, false); - } + @Override + public void onCreateContextMenu(ContextMenu menu, View v, + ContextMenuInfo menuInfo) { + super.onCreateContextMenu(menu, v, menuInfo); + AdapterContextMenuInfo info = (AdapterContextMenuInfo)menuInfo; + MenuInflater inflater = getActivity().getMenuInflater(); + inflater.inflate(R.menu.lobby_playerlist_context, menu); + menu.setHeaderIcon(R.drawable.human); + menu.setHeaderTitle(adapter.getItem(info.position).name); + } + + @Override + public boolean onContextItemSelected(MenuItem item) { + AdapterContextMenuInfo info = (AdapterContextMenuInfo)item.getMenuInfo(); + Player player = adapter.getItem(info.position); + switch(item.getItemId()) { + case R.id.player_info: + netplay.sendPlayerInfoQuery(player.name); + return true; + case R.id.player_follow: + netplay.sendFollowPlayer(player.name); + return true; + default: + return super.onContextItemSelected(item); + } + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + return inflater.inflate(R.layout.fragment_playerlist, container, false); + } } diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/LocalRoomActivity.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/LocalRoomActivity.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/LocalRoomActivity.java Tue Nov 10 20:43:13 2015 +0100 @@ -44,78 +44,78 @@ * This activity is used to set up and start a local game. */ public class LocalRoomActivity extends FragmentActivity implements RoomStateManager.Provider, TeamAddDialog.Listener { - private TabHost tabHost; - private RoomStateManager stateManager; - private Button startButton; - + private TabHost tabHost; + private RoomStateManager stateManager; + private Button startButton; + @Override protected void onCreate(Bundle icicle) { super.onCreate(icicle); // TODO find a better central location / way to set up the default scheme and weaponset Netplay netplay = Netplay.getAppInstance(getApplicationContext()); stateManager = new LocalRoomStateManager(netplay.defaultScheme, netplay.defaultWeaponset); - + setContentView(R.layout.activity_localroom); startButton = (Button)findViewById(R.id.startGame); - + startButton.setOnClickListener(startButtonClickListener); - + // Set up a tabbed UI for medium and small screens tabHost = (TabHost)findViewById(android.R.id.tabhost); if(tabHost != null) { - tabHost.setup(); - tabHost.getTabWidget().setOrientation(LinearLayout.VERTICAL); + tabHost.setup(); + tabHost.getTabWidget().setOrientation(LinearLayout.VERTICAL); - tabHost.addTab(tabHost.newTabSpec("map").setIndicator(UiUtils.createVerticalTabIndicator(tabHost, R.string.room_tab_map, 0)).setContent(R.id.mapFragment)); - tabHost.addTab(tabHost.newTabSpec("settings").setIndicator(UiUtils.createVerticalTabIndicator(tabHost, R.string.room_tab_settings, 0)).setContent(R.id.settingsFragment)); - tabHost.addTab(tabHost.newTabSpec("teams").setIndicator(UiUtils.createVerticalTabIndicator(tabHost, R.string.room_tab_teams, 0)).setContent(R.id.teamlistContainer)); - - if (icicle != null) { - tabHost.setCurrentTabByTag(icicle.getString("currentTab")); - } + tabHost.addTab(tabHost.newTabSpec("map").setIndicator(UiUtils.createVerticalTabIndicator(tabHost, R.string.room_tab_map, 0)).setContent(R.id.mapFragment)); + tabHost.addTab(tabHost.newTabSpec("settings").setIndicator(UiUtils.createVerticalTabIndicator(tabHost, R.string.room_tab_settings, 0)).setContent(R.id.settingsFragment)); + tabHost.addTab(tabHost.newTabSpec("teams").setIndicator(UiUtils.createVerticalTabIndicator(tabHost, R.string.room_tab_teams, 0)).setContent(R.id.teamlistContainer)); + + if (icicle != null) { + tabHost.setCurrentTabByTag(icicle.getString("currentTab")); + } } } - + @Override protected void onSaveInstanceState(Bundle icicle) { super.onSaveInstanceState(icicle); if(tabHost != null) { - icicle.putString("currentTab", tabHost.getCurrentTabTag()); + icicle.putString("currentTab", tabHost.getCurrentTabTag()); } } - - public void onTeamAddDialogSubmitted(Team newTeam) { - stateManager.requestAddTeam(newTeam, TeamInGame.getUnusedOrRandomColorIndex(stateManager.getTeams().values())); - } - - public RoomStateManager getRoomStateManager() { - return stateManager; - } + + public void onTeamAddDialogSubmitted(Team newTeam) { + stateManager.requestAddTeam(newTeam, TeamInGame.getUnusedOrRandomColorIndex(stateManager.getTeams().values())); + } + + public RoomStateManager getRoomStateManager() { + return stateManager; + } - private final OnClickListener startButtonClickListener = new OnClickListener() { - public void onClick(View v) { - Map teams = stateManager.getTeams(); - Set clanColors = new TreeSet(); - for(TeamInGame t : teams.values()) { - clanColors.add(t.ingameAttribs.colorIndex); - } - if(clanColors.size()<2) { - if(tabHost != null) { - tabHost.setCurrentTabByTag("teams"); - } - int errortext = teams.size()<2 ? R.string.not_enough_teams : R.string.not_enough_clans; - Toast.makeText(getApplicationContext(), errortext, Toast.LENGTH_SHORT).show(); - return; - } - - SDLActivity.startNetgame = false; - SDLActivity.startConfig = new GameConfig( - stateManager.getGameStyle(), - stateManager.getScheme(), - stateManager.getMapRecipe(), - new ArrayList(stateManager.getTeams().values()), - stateManager.getWeaponset()); - startActivity(new Intent(LocalRoomActivity.this, SDLActivity.class)); - } - }; + private final OnClickListener startButtonClickListener = new OnClickListener() { + public void onClick(View v) { + Map teams = stateManager.getTeams(); + Set clanColors = new TreeSet(); + for(TeamInGame t : teams.values()) { + clanColors.add(t.ingameAttribs.colorIndex); + } + if(clanColors.size()<2) { + if(tabHost != null) { + tabHost.setCurrentTabByTag("teams"); + } + int errortext = teams.size()<2 ? R.string.not_enough_teams : R.string.not_enough_clans; + Toast.makeText(getApplicationContext(), errortext, Toast.LENGTH_SHORT).show(); + return; + } + + SDLActivity.startNetgame = false; + SDLActivity.startConfig = new GameConfig( + stateManager.getGameStyle(), + stateManager.getScheme(), + stateManager.getMapRecipe(), + new ArrayList(stateManager.getTeams().values()), + stateManager.getWeaponset()); + startActivity(new Intent(LocalRoomActivity.this, SDLActivity.class)); + } + }; } diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/LocalRoomStateManager.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/LocalRoomStateManager.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/LocalRoomStateManager.java Tue Nov 10 20:43:13 2015 +0100 @@ -35,80 +35,80 @@ * state. */ public class LocalRoomStateManager extends BasicRoomState { - private static final String TAG = LocalRoomStateManager.class.getSimpleName(); + private static final String TAG = LocalRoomStateManager.class.getSimpleName(); - public LocalRoomStateManager(Scheme defaultScheme, Weaponset defaultWeaponset) { - setChief(true); - setGameStyle(GameConfig.DEFAULT_STYLE); - setMapRecipe(MapRecipe.makeRandomMap(0, MapRecipe.makeRandomSeed(), GameConfig.DEFAULT_THEME)); - setScheme(defaultScheme); - setWeaponset(defaultWeaponset); - } - - public void changeMapRecipe(MapRecipe map) { - setMapRecipe(map); - } + public LocalRoomStateManager(Scheme defaultScheme, Weaponset defaultWeaponset) { + setChief(true); + setGameStyle(GameConfig.DEFAULT_STYLE); + setMapRecipe(MapRecipe.makeRandomMap(0, MapRecipe.makeRandomSeed(), GameConfig.DEFAULT_THEME)); + setScheme(defaultScheme); + setWeaponset(defaultWeaponset); + } - public void changeMapTheme(String theme) { - setMapRecipe(getMapRecipe().withTheme(theme)); - } + public void changeMapRecipe(MapRecipe map) { + setMapRecipe(map); + } + + public void changeMapTheme(String theme) { + setMapRecipe(getMapRecipe().withTheme(theme)); + } - public void changeMapNameAndGenerator(String mapName) { - int newGenerator = MapRecipe.generatorForMapname(mapName); - setMapRecipe(getMapRecipe().withName(mapName).withMapgen(newGenerator)); - } + public void changeMapNameAndGenerator(String mapName) { + int newGenerator = MapRecipe.generatorForMapname(mapName); + setMapRecipe(getMapRecipe().withName(mapName).withMapgen(newGenerator)); + } - public void changeMapTemplate(int template) { - setMapRecipe(getMapRecipe().withTemplateFilter(template)); - } + public void changeMapTemplate(int template) { + setMapRecipe(getMapRecipe().withTemplateFilter(template)); + } - public void changeMazeSize(int mazeSize) { - setMapRecipe(getMapRecipe().withMazeSize(mazeSize)); - } + public void changeMazeSize(int mazeSize) { + setMapRecipe(getMapRecipe().withMazeSize(mazeSize)); + } - public void changeMapSeed(String seed) { - setMapRecipe(getMapRecipe().withSeed(seed)); - } + public void changeMapSeed(String seed) { + setMapRecipe(getMapRecipe().withSeed(seed)); + } - public void changeMapDrawdata(byte[] drawdata) { - setMapRecipe(getMapRecipe().withDrawData(drawdata)); - } + public void changeMapDrawdata(byte[] drawdata) { + setMapRecipe(getMapRecipe().withDrawData(drawdata)); + } - public void changeScheme(Scheme scheme) { - setScheme(scheme); - } + public void changeScheme(Scheme scheme) { + setScheme(scheme); + } - public void changeGameStyle(String style) { - setGameStyle(style); - } + public void changeGameStyle(String style) { + setGameStyle(style); + } - public void changeWeaponset(Weaponset weaponset) { - setWeaponset(weaponset); - } + public void changeWeaponset(Weaponset weaponset) { + setWeaponset(weaponset); + } - public void requestAddTeam(Team team, int colorIndex) { - putTeam(new TeamInGame(team, new TeamIngameAttributes("Player", colorIndex, TeamIngameAttributes.DEFAULT_HOG_COUNT, false))); - } + public void requestAddTeam(Team team, int colorIndex) { + putTeam(new TeamInGame(team, new TeamIngameAttributes("Player", colorIndex, TeamIngameAttributes.DEFAULT_HOG_COUNT, false))); + } - public void requestRemoveTeam(String teamname) { - removeTeam(teamname); - } + public void requestRemoveTeam(String teamname) { + removeTeam(teamname); + } - public void changeTeamColorIndex(String teamname, int colorIndex) { - TeamInGame oldTeam = getTeams().get(teamname); - if(oldTeam != null) { - putTeam(oldTeam.withAttribs(oldTeam.ingameAttribs.withColorIndex(colorIndex))); - } else { - Log.e(TAG, "Requested color change for unknown team "+ teamname); - } - } + public void changeTeamColorIndex(String teamname, int colorIndex) { + TeamInGame oldTeam = getTeams().get(teamname); + if(oldTeam != null) { + putTeam(oldTeam.withAttribs(oldTeam.ingameAttribs.withColorIndex(colorIndex))); + } else { + Log.e(TAG, "Requested color change for unknown team "+ teamname); + } + } - public void changeTeamHogCount(String teamname, int hogcount) { - TeamInGame oldTeam = getTeams().get(teamname); - if(oldTeam != null) { - putTeam(oldTeam.withAttribs(oldTeam.ingameAttribs.withHogCount(hogcount))); - } else { - Log.e(TAG, "Requested hog count change for unknown team "+ teamname); - } - } + public void changeTeamHogCount(String teamname, int hogcount) { + TeamInGame oldTeam = getTeams().get(teamname); + if(oldTeam != null) { + putTeam(oldTeam.withAttribs(oldTeam.ingameAttribs.withHogCount(hogcount))); + } else { + Log.e(TAG, "Requested hog count change for unknown team "+ teamname); + } + } } diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/MainActivity.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/MainActivity.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/MainActivity.java Tue Nov 10 20:43:13 2015 +0100 @@ -49,175 +49,175 @@ import android.widget.Toast; public class MainActivity extends FragmentActivity { - private static final int DIALOG_NO_SDCARD = 0; - - private LocalBroadcastManager broadcastManager; - private ProgressDialog assetsDialog; + private static final int DIALOG_NO_SDCARD = 0; + + private LocalBroadcastManager broadcastManager; + private ProgressDialog assetsDialog; + + public void onCreate(Bundle sis){ + super.onCreate(sis); + setContentView(R.layout.activity_main); + + broadcastManager = LocalBroadcastManager.getInstance(getApplicationContext()); + Button startLocalGame = (Button)findViewById(R.id.startGame); + Button startNetGame = (Button)findViewById(R.id.joinLobby); + + startLocalGame.setOnClickListener(startGameListener); + startNetGame.setOnClickListener(startNetGameListener); - public void onCreate(Bundle sis){ - super.onCreate(sis); - setContentView(R.layout.activity_main); + if(!FileUtils.isDataPathAvailable()){ + showDialog(DIALOG_NO_SDCARD); + } else { + String existingVersion = ""; + try { + File versionFile = new File(FileUtils.getCachePath(this), "assetsversion.txt"); + existingVersion = FileUtils.readToString(new FileInputStream(versionFile)); + } catch(IOException e) { + } - broadcastManager = LocalBroadcastManager.getInstance(getApplicationContext()); - Button startLocalGame = (Button)findViewById(R.id.startGame); - Button startNetGame = (Button)findViewById(R.id.joinLobby); - - startLocalGame.setOnClickListener(startGameListener); - startNetGame.setOnClickListener(startNetGameListener); + String newVersion = ""; + try { + newVersion = FileUtils.readToString(getAssets().open("assetsversion.txt")); + } catch(IOException e) { + } - if(!FileUtils.isDataPathAvailable()){ - showDialog(DIALOG_NO_SDCARD); - } else { - String existingVersion = ""; - try { - File versionFile = new File(FileUtils.getCachePath(this), "assetsversion.txt"); - existingVersion = FileUtils.readToString(new FileInputStream(versionFile)); - } catch(IOException e) { - } - - String newVersion = ""; - try { - newVersion = FileUtils.readToString(getAssets().open("assetsversion.txt")); - } catch(IOException e) { - } - - if(!existingVersion.equals(newVersion)) { - DownloadAssets assetsAsyncTask = new DownloadAssets(this); - assetsDialog = ProgressDialog.show(this, "Please wait a moment", "Moving assets to SD card..."); - assetsAsyncTask.execute(); - } - } - } + if(!existingVersion.equals(newVersion)) { + DownloadAssets assetsAsyncTask = new DownloadAssets(this); + assetsDialog = ProgressDialog.show(this, "Please wait a moment", "Moving assets to SD card..."); + assetsAsyncTask.execute(); + } + } + } + + @Override + protected void onResume() { + super.onResume(); + broadcastManager.registerReceiver(connectedReceiver, new IntentFilter(Netplay.ACTION_CONNECTED)); + broadcastManager.registerReceiver(connectionFailedReceiver, new IntentFilter(Netplay.ACTION_DISCONNECTED)); + broadcastManager.registerReceiver(passwordRequestedReceiver, new IntentFilter(Netplay.ACTION_PASSWORD_REQUESTED)); + } + + @Override + protected void onPause() { + super.onPause(); + broadcastManager.unregisterReceiver(connectedReceiver); + broadcastManager.unregisterReceiver(connectionFailedReceiver); + broadcastManager.unregisterReceiver(passwordRequestedReceiver); + Netplay netplay = Netplay.getAppInstance(getApplicationContext()); + if(netplay.getState() == State.CONNECTING) { + netplay.disconnect(); + } + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + super.onCreateOptionsMenu(menu); + getMenuInflater().inflate(R.menu.main_options, menu); + return true; + } - @Override - protected void onResume() { - super.onResume(); - broadcastManager.registerReceiver(connectedReceiver, new IntentFilter(Netplay.ACTION_CONNECTED)); - broadcastManager.registerReceiver(connectionFailedReceiver, new IntentFilter(Netplay.ACTION_DISCONNECTED)); - broadcastManager.registerReceiver(passwordRequestedReceiver, new IntentFilter(Netplay.ACTION_PASSWORD_REQUESTED)); - } - - @Override - protected void onPause() { - super.onPause(); - broadcastManager.unregisterReceiver(connectedReceiver); - broadcastManager.unregisterReceiver(connectionFailedReceiver); - broadcastManager.unregisterReceiver(passwordRequestedReceiver); - Netplay netplay = Netplay.getAppInstance(getApplicationContext()); - if(netplay.getState() == State.CONNECTING) { - netplay.disconnect(); - } - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - super.onCreateOptionsMenu(menu); - getMenuInflater().inflate(R.menu.main_options, menu); - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch(item.getItemId()) { - case R.id.download: - startActivityForResult(new Intent(this, DownloadListActivity.class), 0); - return true; - case R.id.preferences: - Toast.makeText(this, R.string.not_implemented_yet, Toast.LENGTH_SHORT).show(); - return true; - case R.id.edit_weaponsets: - startActivity(new Intent(this, WeaponsetListActivity.class)); - return true; - case R.id.edit_teams: - startActivity(new Intent(this, TeamListActivity.class)); - return true; - default: - return super.onOptionsItemSelected(item); - } - } - - public Dialog onCreateDialog(int id, Bundle args){ - switch(id) { - case DIALOG_NO_SDCARD: - return createNoSdcardDialog(); - default: - throw new IndexOutOfBoundsException(); - } - } + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch(item.getItemId()) { + case R.id.download: + startActivityForResult(new Intent(this, DownloadListActivity.class), 0); + return true; + case R.id.preferences: + Toast.makeText(this, R.string.not_implemented_yet, Toast.LENGTH_SHORT).show(); + return true; + case R.id.edit_weaponsets: + startActivity(new Intent(this, WeaponsetListActivity.class)); + return true; + case R.id.edit_teams: + startActivity(new Intent(this, TeamListActivity.class)); + return true; + default: + return super.onOptionsItemSelected(item); + } + } + + public Dialog onCreateDialog(int id, Bundle args){ + switch(id) { + case DIALOG_NO_SDCARD: + return createNoSdcardDialog(); + default: + throw new IndexOutOfBoundsException(); + } + } + + private Dialog createNoSdcardDialog() { + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setTitle(R.string.sdcard_not_mounted_title); + builder.setMessage(R.string.sdcard_not_mounted); + builder.setNegativeButton(android.R.string.ok, new DialogInterface.OnClickListener(){ + public void onClick(DialogInterface dialog, int which) { + finish(); + } + }); + + return builder.create(); + } + + public void onAssetsDownloaded(boolean result){ + if(!result){ + Toast.makeText(this, R.string.download_failed, Toast.LENGTH_LONG).show(); + } + assetsDialog.dismiss(); + } - private Dialog createNoSdcardDialog() { - AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setTitle(R.string.sdcard_not_mounted_title); - builder.setMessage(R.string.sdcard_not_mounted); - builder.setNegativeButton(android.R.string.ok, new DialogInterface.OnClickListener(){ - public void onClick(DialogInterface dialog, int which) { - finish(); - } - }); + private final OnClickListener startGameListener = new OnClickListener(){ + public void onClick(View v){ + startActivity(new Intent(getApplicationContext(), LocalRoomActivity.class)); + } + }; - return builder.create(); - } - - public void onAssetsDownloaded(boolean result){ - if(!result){ - Toast.makeText(this, R.string.download_failed, Toast.LENGTH_LONG).show(); - } - assetsDialog.dismiss(); - } + private final OnClickListener startNetGameListener = new OnClickListener() { + public void onClick(View v) { + State state = Netplay.getAppInstance(getApplicationContext()).getState(); + switch(state) { + case NOT_CONNECTED: + FragmentManager fm = getSupportFragmentManager(); + StartNetgameDialog startNetgameDialog = new StartNetgameDialog(); + startNetgameDialog.show(fm, "start_netgame_dialog"); + break; + case CONNECTING: + onNetConnectingStarted(); + break; + default: + startActivity(new Intent(getApplicationContext(), LobbyActivity.class)); + break; + } + } + }; - private final OnClickListener startGameListener = new OnClickListener(){ - public void onClick(View v){ - startActivity(new Intent(getApplicationContext(), LocalRoomActivity.class)); - } - }; - - private final OnClickListener startNetGameListener = new OnClickListener() { - public void onClick(View v) { - State state = Netplay.getAppInstance(getApplicationContext()).getState(); - switch(state) { - case NOT_CONNECTED: - FragmentManager fm = getSupportFragmentManager(); - StartNetgameDialog startNetgameDialog = new StartNetgameDialog(); - startNetgameDialog.show(fm, "start_netgame_dialog"); - break; - case CONNECTING: - onNetConnectingStarted(); - break; - default: - startActivity(new Intent(getApplicationContext(), LobbyActivity.class)); - break; - } - } - }; - - private BroadcastReceiver connectedReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - startActivity(new Intent(getApplicationContext(), LobbyActivity.class)); - } - }; - - private BroadcastReceiver connectionFailedReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if(intent.getBooleanExtra(Netplay.EXTRA_HAS_ERROR, true)) { - Toast.makeText(getApplicationContext(), intent.getStringExtra(Netplay.EXTRA_MESSAGE), Toast.LENGTH_LONG).show(); - } - } - }; - - private BroadcastReceiver passwordRequestedReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - FragmentManager fm = getSupportFragmentManager(); - PasswordDialog passwordDialog = new PasswordDialog(intent.getStringExtra(Netplay.EXTRA_PLAYERNAME)); - passwordDialog.show(fm, "fragment_password_dialog"); - } - }; + private BroadcastReceiver connectedReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + startActivity(new Intent(getApplicationContext(), LobbyActivity.class)); + } + }; - public void onNetConnectingStarted() { + private BroadcastReceiver connectionFailedReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if(intent.getBooleanExtra(Netplay.EXTRA_HAS_ERROR, true)) { + Toast.makeText(getApplicationContext(), intent.getStringExtra(Netplay.EXTRA_MESSAGE), Toast.LENGTH_LONG).show(); + } + } + }; + + private BroadcastReceiver passwordRequestedReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + FragmentManager fm = getSupportFragmentManager(); + PasswordDialog passwordDialog = new PasswordDialog(intent.getStringExtra(Netplay.EXTRA_PLAYERNAME)); + passwordDialog.show(fm, "fragment_password_dialog"); + } + }; + + public void onNetConnectingStarted() { FragmentManager fm = getSupportFragmentManager(); ConnectingDialog connectingDialog = new ConnectingDialog(); connectingDialog.show(fm, "fragment_connecting_dialog"); - } + } } diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/MapFragment.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/MapFragment.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/MapFragment.java Tue Nov 10 20:43:13 2015 +0100 @@ -50,225 +50,225 @@ /** * Display a map preview, and configuration options for the map. - * + * * Mostly for layout reasons, this does not include the theme setting, which * (arguably) is more a map setting than a general game setting. */ public class MapFragment extends Fragment { - private Spinner mapTypeSpinner, mapNameSpinner, templateSpinner, mazeSizeSpinner; - private TableRow nameRow, templateRow, mazeSizeRow; - private ImageView mapPreview; - - private List mapFiles; - private RoomStateManager stateManager; - private Random random = new Random(); - private CalmDownHandler mapPreviewHandler; - - /* - * Rendering the preview can take a few seconds on Android, so we want to prevent preview - * requests from queueing up if maps are changed quickly. So if there is already a preview - * being generated, we store our latest request in the newPreviewRequest variable instead. - * Once the current preview is finished generating it will start on that one. - */ - private boolean previewGenerationInProgress; - private MapRecipe newPreviewRequest; - private MapRecipe currentMap; // kept for reference on every change to find out what changed - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View v = inflater.inflate(R.layout.fragment_map, container, false); - final Context appContext = getActivity().getApplicationContext(); + private Spinner mapTypeSpinner, mapNameSpinner, templateSpinner, mazeSizeSpinner; + private TableRow nameRow, templateRow, mazeSizeRow; + private ImageView mapPreview; + + private List mapFiles; + private RoomStateManager stateManager; + private Random random = new Random(); + private CalmDownHandler mapPreviewHandler; + + /* + * Rendering the preview can take a few seconds on Android, so we want to prevent preview + * requests from queueing up if maps are changed quickly. So if there is already a preview + * being generated, we store our latest request in the newPreviewRequest variable instead. + * Once the current preview is finished generating it will start on that one. + */ + private boolean previewGenerationInProgress; + private MapRecipe newPreviewRequest; + private MapRecipe currentMap; // kept for reference on every change to find out what changed + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.fragment_map, container, false); + final Context appContext = getActivity().getApplicationContext(); + + /* + * This handler will start the map preview after none of the map settings + * have been updated for a short time. + */ + mapPreviewHandler = new CalmDownHandler(getActivity().getMainLooper(), new Runnable() { + public void run() { + if(!previewGenerationInProgress) { + mapPreview.setImageResource(R.drawable.roomlist_preparing); + MapPreviewGenerator.startPreviewGeneration(appContext, stateManager.getMapRecipe(), mapPreviewListener); + previewGenerationInProgress = true; + } else { + newPreviewRequest = stateManager.getMapRecipe(); + } + } + }, 250); + + nameRow = (TableRow) v.findViewById(R.id.rowMapName); + templateRow = (TableRow) v.findViewById(R.id.rowTemplateFilter); + mazeSizeRow = (TableRow) v.findViewById(R.id.rowMazeSize); + mapPreview = (ImageView) v.findViewById(R.id.mapPreview); + mapPreview.setImageDrawable(null);; + mapPreview.setOnClickListener(mapClickListener); - /* - * This handler will start the map preview after none of the map settings - * have been updated for a short time. - */ - mapPreviewHandler = new CalmDownHandler(getActivity().getMainLooper(), new Runnable() { - public void run() { - if(!previewGenerationInProgress) { - mapPreview.setImageResource(R.drawable.roomlist_preparing); - MapPreviewGenerator.startPreviewGeneration(appContext, stateManager.getMapRecipe(), mapPreviewListener); - previewGenerationInProgress = true; - } else { - newPreviewRequest = stateManager.getMapRecipe(); - } - } - }, 250); - - nameRow = (TableRow) v.findViewById(R.id.rowMapName); - templateRow = (TableRow) v.findViewById(R.id.rowTemplateFilter); - mazeSizeRow = (TableRow) v.findViewById(R.id.rowMazeSize); - mapPreview = (ImageView) v.findViewById(R.id.mapPreview); - mapPreview.setImageDrawable(null);; - mapPreview.setOnClickListener(mapClickListener); - - try { - mapFiles = FrontendDataUtils.getMaps(getActivity()); - } catch (IOException e) { - Toast.makeText(getActivity().getApplicationContext(), R.string.error_missing_sdcard_or_files, Toast.LENGTH_LONG).show(); - getActivity().finish(); - return null; - } - Collections.sort(mapFiles, MapFile.MISSIONS_FIRST_NAME_ORDER); - - List mapNames = MapFile.toDisplayNameList(mapFiles, getResources()); - mapTypeSpinner = prepareSpinner(v, R.id.spinMapType, Arrays.asList(getResources().getStringArray(R.array.map_types)), mapTypeSelectedListener); - mapNameSpinner = prepareSpinner(v, R.id.spinMapName, mapNames, mapNameSelectedListener); - templateSpinner = prepareSpinner(v, R.id.spinTemplateFilter, Arrays.asList(getResources().getStringArray(R.array.map_templates)), mapTemplateSelectedListener); - mazeSizeSpinner = prepareSpinner(v, R.id.spinMazeSize, Arrays.asList(getResources().getStringArray(R.array.map_maze_sizes)), mazeSizeSelectedListener); + try { + mapFiles = FrontendDataUtils.getMaps(getActivity()); + } catch (IOException e) { + Toast.makeText(getActivity().getApplicationContext(), R.string.error_missing_sdcard_or_files, Toast.LENGTH_LONG).show(); + getActivity().finish(); + return null; + } + Collections.sort(mapFiles, MapFile.MISSIONS_FIRST_NAME_ORDER); + + List mapNames = MapFile.toDisplayNameList(mapFiles, getResources()); + mapTypeSpinner = prepareSpinner(v, R.id.spinMapType, Arrays.asList(getResources().getStringArray(R.array.map_types)), mapTypeSelectedListener); + mapNameSpinner = prepareSpinner(v, R.id.spinMapName, mapNames, mapNameSelectedListener); + templateSpinner = prepareSpinner(v, R.id.spinTemplateFilter, Arrays.asList(getResources().getStringArray(R.array.map_templates)), mapTemplateSelectedListener); + mazeSizeSpinner = prepareSpinner(v, R.id.spinMazeSize, Arrays.asList(getResources().getStringArray(R.array.map_maze_sizes)), mazeSizeSelectedListener); + + stateManager.addListener(roomStateChangeListener); + currentMap = stateManager.getMapRecipe(); + if(currentMap != null) { + updateDisplay(currentMap); + } + setChiefState(stateManager.getChiefStatus()); + mapPreviewHandler.activity(); + return v; + } + + private static Spinner prepareSpinner(View v, int id, List items, OnItemSelectedListener itemSelectedListener) { + Spinner spinner = (Spinner)v.findViewById(id); + ArrayAdapter adapter = new ArrayAdapter(v.getContext(), R.layout.listview_item, items); + adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + spinner.setAdapter(adapter); + spinner.setOnItemSelectedListener(itemSelectedListener); + return spinner; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + try { + stateManager = ((RoomStateManager.Provider)getActivity()).getRoomStateManager(); + } catch(ClassCastException e) { + throw new RuntimeException("Hosting activity must implement RoomStateManager.Provider.", e); + } + } + + @Override + public void onDestroy() { + super.onDestroy(); + mapPreviewHandler.stop(); + newPreviewRequest = null; + + stateManager.removeListener(roomStateChangeListener); + } + + private void setChiefState(boolean chiefState) { + mapTypeSpinner.setEnabled(chiefState); + mapNameSpinner.setEnabled(chiefState); + templateSpinner.setEnabled(chiefState); + mazeSizeSpinner.setEnabled(chiefState); + mapPreview.setEnabled(chiefState); - stateManager.addListener(roomStateChangeListener); - currentMap = stateManager.getMapRecipe(); - if(currentMap != null) { - updateDisplay(currentMap); - } - setChiefState(stateManager.getChiefStatus()); - mapPreviewHandler.activity(); - return v; - } - - private static Spinner prepareSpinner(View v, int id, List items, OnItemSelectedListener itemSelectedListener) { - Spinner spinner = (Spinner)v.findViewById(id); - ArrayAdapter adapter = new ArrayAdapter(v.getContext(), R.layout.listview_item, items); - adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - spinner.setAdapter(adapter); - spinner.setOnItemSelectedListener(itemSelectedListener); - return spinner; - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - try { - stateManager = ((RoomStateManager.Provider)getActivity()).getRoomStateManager(); - } catch(ClassCastException e) { - throw new RuntimeException("Hosting activity must implement RoomStateManager.Provider.", e); - } - } - - @Override - public void onDestroy() { - super.onDestroy(); - mapPreviewHandler.stop(); - newPreviewRequest = null; - - stateManager.removeListener(roomStateChangeListener); - } - - private void setChiefState(boolean chiefState) { - mapTypeSpinner.setEnabled(chiefState); - mapNameSpinner.setEnabled(chiefState); - templateSpinner.setEnabled(chiefState); - mazeSizeSpinner.setEnabled(chiefState); - mapPreview.setEnabled(chiefState); - - if(chiefState) { - sendMapnameAndGenerator(); - stateManager.changeMapTemplate(templateSpinner.getSelectedItemPosition()); - stateManager.changeMazeSize(mazeSizeSpinner.getSelectedItemPosition()); - } - } - - private void updateDisplay(MapRecipe map) { - nameRow.setVisibility(map.mapgen == Frontlib.MAPGEN_NAMED ? View.VISIBLE : View.GONE); - templateRow.setVisibility(map.mapgen == Frontlib.MAPGEN_REGULAR ? View.VISIBLE : View.GONE); - mazeSizeRow.setVisibility(map.mapgen == Frontlib.MAPGEN_MAZE ? View.VISIBLE : View.GONE); - - mapTypeSpinner.setSelection(map.mapgen); - int mapPosition = findMapPosition(mapFiles, map.name); - if(mapPosition >= 0) { - mapNameSpinner.setSelection(mapPosition); - } - templateSpinner.setSelection(map.templateFilter); - mazeSizeSpinner.setSelection(map.mazeSize); - } - - private static int findMapPosition(List mapFiles, String mapName) { - for(int i=0; i adapter, View v, int position, long arg3) { - sendMapnameAndGenerator(); - } - public void onNothingSelected(AdapterView arg0) {} - }; - - private final OnItemSelectedListener mapNameSelectedListener = new OnItemSelectedListener() { - public void onItemSelected(AdapterView adapter, View v, int position, long arg3) { - sendMapnameAndGenerator(); - } - public void onNothingSelected(AdapterView arg0) {} - }; - - private final OnItemSelectedListener mapTemplateSelectedListener = new OnItemSelectedListener() { - public void onItemSelected(AdapterView adapter, View v, int position, long arg3) { - stateManager.changeMapTemplate(position); - } - public void onNothingSelected(AdapterView arg0) {} - }; - - private final OnItemSelectedListener mazeSizeSelectedListener = new OnItemSelectedListener() { - public void onItemSelected(AdapterView adapter, View v, int position, long arg3) { - stateManager.changeMazeSize(position); - } - public void onNothingSelected(AdapterView arg0) {} - }; - - private final OnClickListener mapClickListener = new OnClickListener() { - public void onClick(View v) { - stateManager.changeMapSeed(MapRecipe.makeRandomSeed()); - if(mapTypeSpinner.getSelectedItemPosition() == Frontlib.MAPGEN_NAMED) { - mapNameSpinner.setSelection(random.nextInt(mapNameSpinner.getCount())); - } - } - }; - - private final RoomStateManager.Listener roomStateChangeListener = new RoomStateManager.ListenerAdapter() { - @Override - public void onChiefStatusChanged(boolean isChief) { - setChiefState(isChief); - }; - - @Override - public void onMapChanged(MapRecipe recipe) { - // Only trigger a preview update if a relevant field changed (not theme) - if(currentMap==null - || currentMap.mapgen != recipe.mapgen - || currentMap.mazeSize != recipe.mazeSize - || !currentMap.name.equals(recipe.name) - || !currentMap.seed.equals(recipe.seed) - || currentMap.templateFilter != recipe.templateFilter - || !Arrays.equals(currentMap.getDrawData(), recipe.getDrawData())) { - mapPreviewHandler.activity(); - } - updateDisplay(recipe); - currentMap = recipe; - }; - }; - - private MapPreviewGenerator.Listener mapPreviewListener = new MapPreviewGenerator.Listener() { - public void onMapPreviewResult(Drawable preview) { - if(newPreviewRequest != null) { - MapPreviewGenerator.startPreviewGeneration(getActivity().getApplicationContext(), newPreviewRequest, mapPreviewListener); - newPreviewRequest = null; - } else { - if(mapPreview != null) { - mapPreview.setImageDrawable(preview); - } - previewGenerationInProgress = false; - } - } - }; + if(chiefState) { + sendMapnameAndGenerator(); + stateManager.changeMapTemplate(templateSpinner.getSelectedItemPosition()); + stateManager.changeMazeSize(mazeSizeSpinner.getSelectedItemPosition()); + } + } + + private void updateDisplay(MapRecipe map) { + nameRow.setVisibility(map.mapgen == Frontlib.MAPGEN_NAMED ? View.VISIBLE : View.GONE); + templateRow.setVisibility(map.mapgen == Frontlib.MAPGEN_REGULAR ? View.VISIBLE : View.GONE); + mazeSizeRow.setVisibility(map.mapgen == Frontlib.MAPGEN_MAZE ? View.VISIBLE : View.GONE); + + mapTypeSpinner.setSelection(map.mapgen); + int mapPosition = findMapPosition(mapFiles, map.name); + if(mapPosition >= 0) { + mapNameSpinner.setSelection(mapPosition); + } + templateSpinner.setSelection(map.templateFilter); + mazeSizeSpinner.setSelection(map.mazeSize); + } + + private static int findMapPosition(List mapFiles, String mapName) { + for(int i=0; i adapter, View v, int position, long arg3) { + sendMapnameAndGenerator(); + } + public void onNothingSelected(AdapterView arg0) {} + }; + + private final OnItemSelectedListener mapNameSelectedListener = new OnItemSelectedListener() { + public void onItemSelected(AdapterView adapter, View v, int position, long arg3) { + sendMapnameAndGenerator(); + } + public void onNothingSelected(AdapterView arg0) {} + }; + + private final OnItemSelectedListener mapTemplateSelectedListener = new OnItemSelectedListener() { + public void onItemSelected(AdapterView adapter, View v, int position, long arg3) { + stateManager.changeMapTemplate(position); + } + public void onNothingSelected(AdapterView arg0) {} + }; + + private final OnItemSelectedListener mazeSizeSelectedListener = new OnItemSelectedListener() { + public void onItemSelected(AdapterView adapter, View v, int position, long arg3) { + stateManager.changeMazeSize(position); + } + public void onNothingSelected(AdapterView arg0) {} + }; + + private final OnClickListener mapClickListener = new OnClickListener() { + public void onClick(View v) { + stateManager.changeMapSeed(MapRecipe.makeRandomSeed()); + if(mapTypeSpinner.getSelectedItemPosition() == Frontlib.MAPGEN_NAMED) { + mapNameSpinner.setSelection(random.nextInt(mapNameSpinner.getCount())); + } + } + }; + + private final RoomStateManager.Listener roomStateChangeListener = new RoomStateManager.ListenerAdapter() { + @Override + public void onChiefStatusChanged(boolean isChief) { + setChiefState(isChief); + }; + + @Override + public void onMapChanged(MapRecipe recipe) { + // Only trigger a preview update if a relevant field changed (not theme) + if(currentMap==null + || currentMap.mapgen != recipe.mapgen + || currentMap.mazeSize != recipe.mazeSize + || !currentMap.name.equals(recipe.name) + || !currentMap.seed.equals(recipe.seed) + || currentMap.templateFilter != recipe.templateFilter + || !Arrays.equals(currentMap.getDrawData(), recipe.getDrawData())) { + mapPreviewHandler.activity(); + } + updateDisplay(recipe); + currentMap = recipe; + }; + }; + + private MapPreviewGenerator.Listener mapPreviewListener = new MapPreviewGenerator.Listener() { + public void onMapPreviewResult(Drawable preview) { + if(newPreviewRequest != null) { + MapPreviewGenerator.startPreviewGeneration(getActivity().getApplicationContext(), newPreviewRequest, mapPreviewListener); + newPreviewRequest = null; + } else { + if(mapPreview != null) { + mapPreview.setImageDrawable(preview); + } + previewGenerationInProgress = false; + } + } + }; } diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/MapPreviewGenerator.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/MapPreviewGenerator.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/MapPreviewGenerator.java Tue Nov 10 20:43:13 2015 +0100 @@ -48,176 +48,176 @@ /** * A class that asynchronously generates a map preview from a MapRecipe. - * + * * For named maps, this will load the preview image from the filesystem. For others, * it will call the Hedgewars engine to generate a preview image. The result is sent * back to a listener on the UI thread. */ public final class MapPreviewGenerator implements Runnable { - private static final String TAG = MapPreviewGenerator.class.getSimpleName(); - private static final Handler mainHandler = new Handler(Looper.getMainLooper()); - private static final long TIMEOUT_NS = 20l * 1000 * 1000 * 1000; + private static final String TAG = MapPreviewGenerator.class.getSimpleName(); + private static final Handler mainHandler = new Handler(Looper.getMainLooper()); + private static final long TIMEOUT_NS = 20l * 1000 * 1000 * 1000; + + private final Context appContext; + private final MapRecipe map; + private final Listener listener; + + private boolean resultAvailable; + private Drawable result; + + public static interface Listener { + /** + * This is called on the UI thread once the preview is ready or failed. + * In case of failure, null is passed. + */ + void onMapPreviewResult(Drawable preview); + } + + private MapPreviewGenerator(Context appContext, MapRecipe map, Listener listener) { + this.appContext = appContext; + this.map = map; + this.listener = listener; + } - private final Context appContext; - private final MapRecipe map; - private final Listener listener; - - private boolean resultAvailable; - private Drawable result; - - public static interface Listener { - /** - * This is called on the UI thread once the preview is ready or failed. - * In case of failure, null is passed. - */ - void onMapPreviewResult(Drawable preview); - } + public void run() { + if (map.mapgen == Frontlib.MAPGEN_NAMED) { + postToListener(loadPreviewFromFile(appContext, map.name)); + } else { + resultAvailable = false; + result = null; + MapconnPtr conn = Flib.INSTANCE.flib_mapconn_create(MapRecipePtr.createJavaOwned(map)); + if (conn == null) { + postToListener(null); + return; + } + try { + int port = Flib.INSTANCE.flib_mapconn_getport(conn); + Flib.INSTANCE.flib_mapconn_onSuccess(conn, successCb, null); + Flib.INSTANCE.flib_mapconn_onFailure(conn, failureCb, null); + + String configPath; + try { + configPath = FileUtils.getCachePath(appContext).getAbsolutePath(); + } catch(FileNotFoundException e) { + return; + } + + startEngine(configPath, port); + long startTime = System.nanoTime(); + do { + Flib.INSTANCE.flib_mapconn_tick(conn); + try { + Thread.sleep(50); + } catch (InterruptedException e) { + // ignore + } + if(System.nanoTime()-startTime > TIMEOUT_NS) { + Log.w(TAG, "Error generating map preview: timeout"); + resultAvailable = true; + } + } while(!resultAvailable); + } finally { + Flib.INSTANCE.flib_mapconn_destroy(conn); + postToListener(result); + } + } + } + + public static void startPreviewGeneration(Context appContext, MapRecipe map, Listener listener) { + new Thread(new MapPreviewGenerator(appContext, map, listener)).start(); + } - private MapPreviewGenerator(Context appContext, MapRecipe map, Listener listener) { - this.appContext = appContext; - this.map = map; - this.listener = listener; - } - - public void run() { - if (map.mapgen == Frontlib.MAPGEN_NAMED) { - postToListener(loadPreviewFromFile(appContext, map.name)); - } else { - resultAvailable = false; - result = null; - MapconnPtr conn = Flib.INSTANCE.flib_mapconn_create(MapRecipePtr.createJavaOwned(map)); - if (conn == null) { - postToListener(null); - return; - } - try { - int port = Flib.INSTANCE.flib_mapconn_getport(conn); - Flib.INSTANCE.flib_mapconn_onSuccess(conn, successCb, null); - Flib.INSTANCE.flib_mapconn_onFailure(conn, failureCb, null); - - String configPath; - try { - configPath = FileUtils.getCachePath(appContext).getAbsolutePath(); - } catch(FileNotFoundException e) { - return; - } - - startEngine(configPath, port); - long startTime = System.nanoTime(); - do { - Flib.INSTANCE.flib_mapconn_tick(conn); - try { - Thread.sleep(50); - } catch (InterruptedException e) { - // ignore - } - if(System.nanoTime()-startTime > TIMEOUT_NS) { - Log.w(TAG, "Error generating map preview: timeout"); - resultAvailable = true; - } - } while(!resultAvailable); - } finally { - Flib.INSTANCE.flib_mapconn_destroy(conn); - postToListener(result); - } - } - } - - public static void startPreviewGeneration(Context appContext, MapRecipe map, Listener listener) { - new Thread(new MapPreviewGenerator(appContext, map, listener)).start(); - } - - private static Drawable loadPreviewFromFile(Context appContext, String mapName) { - if(!mapName.startsWith("+")) { - try { - File previewFile = MapFile.getPreviewFile(appContext, mapName); - return Drawable.createFromPath(previewFile.getAbsolutePath()); - } catch (FileNotFoundException e) { - Log.w("MapPreviewGenerator", "Preview for map "+mapName+" not found."); - } - } - return null; - } - - private static void startEngine(final String configPath, final int port) { - new Thread(new Runnable() { - public void run() { - Log.d(TAG, "Starting engine "+port); - PascalExports.synchronizedGenLandPreview(port); - Log.d(TAG, "Engine finished"); - } - }).start(); - } - - private void postToListener(final Drawable result) { - mainHandler.post(new Runnable() { - public void run() { - listener.onMapPreviewResult(result); - } - }); - } - - /** - * Let's be extra nice here and clip off the left and right sides, so the preview is centered... - * Since the image is present in bytes, we can save some effort by checking entire byte-columns first. - */ - private final MapimageCallback successCb = new MapimageCallback() { - public void callback(Pointer context, ByteArrayPtr buffer, int hedgehogCount) { - byte[] mapdata = buffer.deref(Frontlib.MAPIMAGE_BYTES); - - int leftmostPixel = Frontlib.MAPIMAGE_WIDTH; - int rightmostPixel = -1; - int bytesPerLine = Frontlib.MAPIMAGE_WIDTH/8; - - // Find the leftmost pixel - for(int xbyte=0; xbyte=0; xbyte--) { - for(int y=0; y use default width - if(rightmostPixel==-1) { - leftmostPixel = 0; - rightmostPixel = Frontlib.MAPIMAGE_WIDTH-1; - } - - Bitmap bitmap = Bitmap.createBitmap(rightmostPixel-leftmostPixel+1, Frontlib.MAPIMAGE_HEIGHT, Config.ARGB_8888); - for(int y=0; y>3] & (128>>(pixelnum&7))) != 0; - } - - private final StrCallback failureCb = new StrCallback() { - public void callback(Pointer context, String reason) { - Log.w(TAG, "Error generating map preview: "+reason); - result = null; - resultAvailable = true; - } - }; + private static Drawable loadPreviewFromFile(Context appContext, String mapName) { + if(!mapName.startsWith("+")) { + try { + File previewFile = MapFile.getPreviewFile(appContext, mapName); + return Drawable.createFromPath(previewFile.getAbsolutePath()); + } catch (FileNotFoundException e) { + Log.w("MapPreviewGenerator", "Preview for map "+mapName+" not found."); + } + } + return null; + } + + private static void startEngine(final String configPath, final int port) { + new Thread(new Runnable() { + public void run() { + Log.d(TAG, "Starting engine "+port); + PascalExports.synchronizedGenLandPreview(port); + Log.d(TAG, "Engine finished"); + } + }).start(); + } + + private void postToListener(final Drawable result) { + mainHandler.post(new Runnable() { + public void run() { + listener.onMapPreviewResult(result); + } + }); + } + + /** + * Let's be extra nice here and clip off the left and right sides, so the preview is centered... + * Since the image is present in bytes, we can save some effort by checking entire byte-columns first. + */ + private final MapimageCallback successCb = new MapimageCallback() { + public void callback(Pointer context, ByteArrayPtr buffer, int hedgehogCount) { + byte[] mapdata = buffer.deref(Frontlib.MAPIMAGE_BYTES); + + int leftmostPixel = Frontlib.MAPIMAGE_WIDTH; + int rightmostPixel = -1; + int bytesPerLine = Frontlib.MAPIMAGE_WIDTH/8; + + // Find the leftmost pixel + for(int xbyte=0; xbyte=0; xbyte--) { + for(int y=0; y use default width + if(rightmostPixel==-1) { + leftmostPixel = 0; + rightmostPixel = Frontlib.MAPIMAGE_WIDTH-1; + } + + Bitmap bitmap = Bitmap.createBitmap(rightmostPixel-leftmostPixel+1, Frontlib.MAPIMAGE_HEIGHT, Config.ARGB_8888); + for(int y=0; y>3] & (128>>(pixelnum&7))) != 0; + } + + private final StrCallback failureCb = new StrCallback() { + public void callback(Pointer context, String reason) { + Log.w(TAG, "Error generating map preview: "+reason); + result = null; + resultAvailable = true; + } + }; } \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/NetRoomActivity.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/NetRoomActivity.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/NetRoomActivity.java Tue Nov 10 20:43:13 2015 +0100 @@ -43,11 +43,11 @@ * This activity is used to set up and start a game on the server. */ public class NetRoomActivity extends FragmentActivity implements NetplayStateListener, TeamAddDialog.Listener, RoomStateManager.Provider, RunGameListener { - private TabHost tabHost; - private Netplay netplay; - private RoomStateManager stateManager; - private Button startButton; - + private TabHost tabHost; + private Netplay netplay; + private RoomStateManager stateManager; + private Button startButton; + @Override protected void onCreate(Bundle icicle) { super.onCreate(icicle); @@ -55,97 +55,97 @@ netplay.registerRunGameListener(this); stateManager = netplay.getRoomStateManager(); stateManager.addListener(roomStateChangeListener); - + setContentView(R.layout.activity_netroom); startButton = (Button)findViewById(R.id.startGame); - + ChatFragment chatFragment = (ChatFragment)getSupportFragmentManager().findFragmentById(R.id.chatFragment); chatFragment.setInRoom(true); - + FragmentTransaction trans = getSupportFragmentManager().beginTransaction(); trans.add(new NetplayStateFragment(), "netplayFragment"); trans.commit(); - + startButton.setVisibility(netplay.isChief() ? View.VISIBLE : View.GONE); startButton.setOnClickListener(startButtonClickListener); - + // Set up a tabbed UI for medium and small screens tabHost = (TabHost)findViewById(android.R.id.tabhost); if(tabHost != null) { - tabHost.setup(); - tabHost.getTabWidget().setOrientation(LinearLayout.VERTICAL); + tabHost.setup(); + tabHost.getTabWidget().setOrientation(LinearLayout.VERTICAL); - tabHost.addTab(tabHost.newTabSpec("map").setIndicator(UiUtils.createVerticalTabIndicator(tabHost, R.string.room_tab_map, 0)).setContent(R.id.mapFragment)); - tabHost.addTab(tabHost.newTabSpec("settings").setIndicator(UiUtils.createVerticalTabIndicator(tabHost, R.string.room_tab_settings, 0)).setContent(R.id.settingsFragment)); - tabHost.addTab(tabHost.newTabSpec("teams").setIndicator(UiUtils.createVerticalTabIndicator(tabHost, R.string.room_tab_teams, 0)).setContent(R.id.teamlistFragment)); - tabHost.addTab(tabHost.newTabSpec("chat").setIndicator(UiUtils.createVerticalTabIndicator(tabHost, R.string.room_tab_chat, 0)).setContent(R.id.chatFragment)); - tabHost.addTab(tabHost.newTabSpec("players").setIndicator(UiUtils.createVerticalTabIndicator(tabHost, R.string.room_tab_players, 0)).setContent(R.id.playerListContainer)); - - if (icicle != null) { - tabHost.setCurrentTabByTag(icicle.getString("currentTab")); - } + tabHost.addTab(tabHost.newTabSpec("map").setIndicator(UiUtils.createVerticalTabIndicator(tabHost, R.string.room_tab_map, 0)).setContent(R.id.mapFragment)); + tabHost.addTab(tabHost.newTabSpec("settings").setIndicator(UiUtils.createVerticalTabIndicator(tabHost, R.string.room_tab_settings, 0)).setContent(R.id.settingsFragment)); + tabHost.addTab(tabHost.newTabSpec("teams").setIndicator(UiUtils.createVerticalTabIndicator(tabHost, R.string.room_tab_teams, 0)).setContent(R.id.teamlistFragment)); + tabHost.addTab(tabHost.newTabSpec("chat").setIndicator(UiUtils.createVerticalTabIndicator(tabHost, R.string.room_tab_chat, 0)).setContent(R.id.chatFragment)); + tabHost.addTab(tabHost.newTabSpec("players").setIndicator(UiUtils.createVerticalTabIndicator(tabHost, R.string.room_tab_players, 0)).setContent(R.id.playerListContainer)); + + if (icicle != null) { + tabHost.setCurrentTabByTag(icicle.getString("currentTab")); + } } } @Override protected void onDestroy() { - super.onDestroy(); - stateManager.removeListener(roomStateChangeListener); - netplay.unregisterRunGameListener(this); + super.onDestroy(); + stateManager.removeListener(roomStateChangeListener); + netplay.unregisterRunGameListener(this); } - - @Override - public void onBackPressed() { - netplay.sendLeaveRoom(null); - } - + + @Override + public void onBackPressed() { + netplay.sendLeaveRoom(null); + } + @Override protected void onSaveInstanceState(Bundle icicle) { super.onSaveInstanceState(icicle); if(tabHost != null) { - icicle.putString("currentTab", tabHost.getCurrentTabTag()); + icicle.putString("currentTab", tabHost.getCurrentTabTag()); + } + } + + public void onNetplayStateChanged(State newState) { + switch(newState) { + case NOT_CONNECTED: + case CONNECTING: + case LOBBY: + finish(); + break; + case ROOM: + // Do nothing + break; + default: + throw new IllegalStateException("Unknown connection state: "+newState); } } - - public void onNetplayStateChanged(State newState) { - switch(newState) { - case NOT_CONNECTED: - case CONNECTING: - case LOBBY: - finish(); - break; - case ROOM: - // Do nothing - break; - default: - throw new IllegalStateException("Unknown connection state: "+newState); - } + + public void onTeamAddDialogSubmitted(Team newTeam) { + stateManager.requestAddTeam(newTeam, TeamInGame.getUnusedOrRandomColorIndex(stateManager.getTeams().values())); + } + + public RoomStateManager getRoomStateManager() { + return stateManager; } - - public void onTeamAddDialogSubmitted(Team newTeam) { - stateManager.requestAddTeam(newTeam, TeamInGame.getUnusedOrRandomColorIndex(stateManager.getTeams().values())); - } - - public RoomStateManager getRoomStateManager() { - return stateManager; - } + + private final OnClickListener startButtonClickListener = new OnClickListener() { + public void onClick(View v) { + netplay.sendStartGame(); + } + }; - private final OnClickListener startButtonClickListener = new OnClickListener() { - public void onClick(View v) { - netplay.sendStartGame(); - } - }; - - private final RoomStateManager.Listener roomStateChangeListener = new RoomStateManager.ListenerAdapter() { - @Override - public void onChiefStatusChanged(boolean isChief) { - startButton.setVisibility(isChief ? View.VISIBLE : View.GONE); - } - }; - - public void runGame(GameConfig config) { - SDLActivity.startConfig = config; - SDLActivity.startNetgame = true; - startActivity(new Intent(this, SDLActivity.class)); - } + private final RoomStateManager.Listener roomStateChangeListener = new RoomStateManager.ListenerAdapter() { + @Override + public void onChiefStatusChanged(boolean isChief) { + startButton.setVisibility(isChief ? View.VISIBLE : View.GONE); + } + }; + + public void runGame(GameConfig config) { + SDLActivity.startConfig = config; + SDLActivity.startNetgame = true; + startActivity(new Intent(this, SDLActivity.class)); + } } diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/NetplayStateFragment.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/NetplayStateFragment.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/NetplayStateFragment.java Tue Nov 10 20:43:13 2015 +0100 @@ -37,7 +37,7 @@ /** * Fragment for use by an activity that depends on the state of the network * connection. The activity must implement the NetplayStateListener interface. - * + * * This fragment manages reacting to changes in the networking state by calling * a callback method on the activity. */ @@ -47,91 +47,91 @@ private LocalBroadcastManager broadcastManager; private NetplayStateListener listener; private State knownState; - + interface NetplayStateListener { - /** - * This is called while the activity is running, and every time during resume, if - * a change in the networking state is detected. It is also called once - * with the initial state (which could be called a change from the "unknown" state). - */ - void onNetplayStateChanged(State newState); - } - + /** + * This is called while the activity is running, and every time during resume, if + * a change in the networking state is detected. It is also called once + * with the initial state (which could be called a change from the "unknown" state). + */ + void onNetplayStateChanged(State newState); + } + @Override - public void onAttach(Activity activity) { - super.onAttach(activity); - try { - listener = (NetplayStateListener) activity; - } catch(ClassCastException e) { - throw new ClassCastException("Activity " + activity + " must implement NetplayStateListener to use NetplayStateFragment."); - } - } - - @Override - public void onDetach() { - super.onDetach(); - listener = null; - } - + public void onAttach(Activity activity) { + super.onAttach(activity); + try { + listener = (NetplayStateListener) activity; + } catch(ClassCastException e) { + throw new ClassCastException("Activity " + activity + " must implement NetplayStateListener to use NetplayStateFragment."); + } + } + + @Override + public void onDetach() { + super.onDetach(); + listener = null; + } + @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); appContext = getActivity().getApplicationContext(); broadcastManager = LocalBroadcastManager.getInstance(appContext); netplay = Netplay.getAppInstance(appContext); - } + } @Override public void onResume() { - super.onResume(); - broadcastManager.registerReceiver(disconnectReceiver, new IntentFilter(Netplay.ACTION_DISCONNECTED)); - broadcastManager.registerReceiver(leaveRoomReceiver, new IntentFilter(Netplay.ACTION_LEFT_ROOM)); - broadcastManager.registerReceiver(stateChangeReceiver, new IntentFilter(Netplay.ACTION_STATE_CHANGED)); - - State newState = netplay.getState(); - if(knownState != newState) { - listener.onNetplayStateChanged(newState); - knownState = newState; - } + super.onResume(); + broadcastManager.registerReceiver(disconnectReceiver, new IntentFilter(Netplay.ACTION_DISCONNECTED)); + broadcastManager.registerReceiver(leaveRoomReceiver, new IntentFilter(Netplay.ACTION_LEFT_ROOM)); + broadcastManager.registerReceiver(stateChangeReceiver, new IntentFilter(Netplay.ACTION_STATE_CHANGED)); + + State newState = netplay.getState(); + if(knownState != newState) { + listener.onNetplayStateChanged(newState); + knownState = newState; + } } - + @Override public void onPause() { - super.onPause(); - broadcastManager.unregisterReceiver(disconnectReceiver); - broadcastManager.unregisterReceiver(leaveRoomReceiver); - broadcastManager.unregisterReceiver(stateChangeReceiver); + super.onPause(); + broadcastManager.unregisterReceiver(disconnectReceiver); + broadcastManager.unregisterReceiver(leaveRoomReceiver); + broadcastManager.unregisterReceiver(stateChangeReceiver); } - private final BroadcastReceiver disconnectReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if(intent.getBooleanExtra(Netplay.EXTRA_HAS_ERROR, true)) { - String message = intent.getStringExtra(Netplay.EXTRA_MESSAGE); - String toastText = getString(R.string.toast_disconnected, message); - Toast.makeText(appContext, toastText, Toast.LENGTH_LONG).show(); - } - } - }; - - private final BroadcastReceiver leaveRoomReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - int reason = intent.getIntExtra(Netplay.EXTRA_REASON, -1); - if(reason == Frontlib.NETCONN_ROOMLEAVE_ABANDONED) { - Toast.makeText(appContext, R.string.toast_room_abandoned, Toast.LENGTH_LONG).show(); - } else if(reason == Frontlib.NETCONN_ROOMLEAVE_KICKED) { - Toast.makeText(appContext, R.string.toast_kicked, Toast.LENGTH_LONG).show(); - } - } - }; - - private final BroadcastReceiver stateChangeReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - State newState = netplay.getState(); - listener.onNetplayStateChanged(newState); - knownState = newState; - } - }; + private final BroadcastReceiver disconnectReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if(intent.getBooleanExtra(Netplay.EXTRA_HAS_ERROR, true)) { + String message = intent.getStringExtra(Netplay.EXTRA_MESSAGE); + String toastText = getString(R.string.toast_disconnected, message); + Toast.makeText(appContext, toastText, Toast.LENGTH_LONG).show(); + } + } + }; + + private final BroadcastReceiver leaveRoomReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + int reason = intent.getIntExtra(Netplay.EXTRA_REASON, -1); + if(reason == Frontlib.NETCONN_ROOMLEAVE_ABANDONED) { + Toast.makeText(appContext, R.string.toast_room_abandoned, Toast.LENGTH_LONG).show(); + } else if(reason == Frontlib.NETCONN_ROOMLEAVE_KICKED) { + Toast.makeText(appContext, R.string.toast_kicked, Toast.LENGTH_LONG).show(); + } + } + }; + + private final BroadcastReceiver stateChangeReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + State newState = netplay.getState(); + listener.onNetplayStateChanged(newState); + knownState = newState; + } + }; } diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/PasswordDialog.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/PasswordDialog.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/PasswordDialog.java Tue Nov 10 20:43:13 2015 +0100 @@ -33,50 +33,50 @@ * Shown when connecting to the server, and the server requests a password. */ public class PasswordDialog extends ConnectionDependendDialogFragment { - String username; - - public PasswordDialog() { - } - - public PasswordDialog(String username) { - this.username = username; - } - - @Override - public void onSaveInstanceState(Bundle icicle) { - super.onSaveInstanceState(icicle); - icicle.putString("username", username); - } - - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - if(savedInstanceState != null) { - username = savedInstanceState.getString("username"); - } - final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); - final EditText editText = new EditText(getActivity()); - final Netplay netplay = Netplay.getAppInstance(getActivity().getApplicationContext()); - - editText.setHint(R.string.dialog_password_hint); - editText.setId(android.R.id.text1); - editText.setInputType(InputType.TYPE_TEXT_VARIATION_PASSWORD); - editText.setTransformationMethod(PasswordTransformationMethod.getInstance()); - builder.setView(editText); - builder.setTitle(R.string.dialog_password_title); - builder.setMessage(getString(R.string.dialog_password_message, username)); - builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - String password = editText.getText().toString(); - editText.setText(""); - netplay.sendPassword(password); - } - }); - return builder.create(); - } - - @Override - public void onCancel(DialogInterface dialog) { - super.onCancel(dialog); - Netplay.getAppInstance(getActivity().getApplicationContext()).disconnect(); - } + String username; + + public PasswordDialog() { + } + + public PasswordDialog(String username) { + this.username = username; + } + + @Override + public void onSaveInstanceState(Bundle icicle) { + super.onSaveInstanceState(icicle); + icicle.putString("username", username); + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + if(savedInstanceState != null) { + username = savedInstanceState.getString("username"); + } + final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + final EditText editText = new EditText(getActivity()); + final Netplay netplay = Netplay.getAppInstance(getActivity().getApplicationContext()); + + editText.setHint(R.string.dialog_password_hint); + editText.setId(android.R.id.text1); + editText.setInputType(InputType.TYPE_TEXT_VARIATION_PASSWORD); + editText.setTransformationMethod(PasswordTransformationMethod.getInstance()); + builder.setView(editText); + builder.setTitle(R.string.dialog_password_title); + builder.setMessage(getString(R.string.dialog_password_message, username)); + builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + String password = editText.getText().toString(); + editText.setText(""); + netplay.sendPassword(password); + } + }); + return builder.create(); + } + + @Override + public void onCancel(DialogInterface dialog) { + super.onCancel(dialog); + Netplay.getAppInstance(getActivity().getApplicationContext()).disconnect(); + } } diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/RoomPlayerlistAdapter.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/RoomPlayerlistAdapter.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/RoomPlayerlistAdapter.java Tue Nov 10 20:43:13 2015 +0100 @@ -31,30 +31,30 @@ import android.widget.TextView; public class RoomPlayerlistAdapter extends ObservableTreeMapAdapter { - @Override - protected Comparator getEntryOrder() { - return AlphabeticalOrderComparator.INSTANCE; - } + @Override + protected Comparator getEntryOrder() { + return AlphabeticalOrderComparator.INSTANCE; + } - public View getView(int position, View convertView, ViewGroup parent) { - View v = convertView; - if (v == null) { - LayoutInflater vi = LayoutInflater.from(parent.getContext()); - v = vi.inflate(R.layout.listview_player, null); - } + public View getView(int position, View convertView, ViewGroup parent) { + View v = convertView; + if (v == null) { + LayoutInflater vi = LayoutInflater.from(parent.getContext()); + v = vi.inflate(R.layout.listview_player, null); + } - PlayerInRoom player = getItem(position); - TextView username = (TextView) v.findViewById(android.R.id.text1); - username.setText(player.player.name); - int readyDrawable = player.ready ? R.drawable.lightbulb_on : R.drawable.lightbulb_off; - username.setCompoundDrawablesWithIntrinsicBounds(readyDrawable, 0, 0, 0); - return v; - } - - private static final class AlphabeticalOrderComparator implements Comparator { - public static final AlphabeticalOrderComparator INSTANCE = new AlphabeticalOrderComparator(); - public int compare(PlayerInRoom lhs, PlayerInRoom rhs) { - return lhs.player.name.compareToIgnoreCase(rhs.player.name); - }; - } + PlayerInRoom player = getItem(position); + TextView username = (TextView) v.findViewById(android.R.id.text1); + username.setText(player.player.name); + int readyDrawable = player.ready ? R.drawable.lightbulb_on : R.drawable.lightbulb_off; + username.setCompoundDrawablesWithIntrinsicBounds(readyDrawable, 0, 0, 0); + return v; + } + + private static final class AlphabeticalOrderComparator implements Comparator { + public static final AlphabeticalOrderComparator INSTANCE = new AlphabeticalOrderComparator(); + public int compare(PlayerInRoom lhs, PlayerInRoom rhs) { + return lhs.player.name.compareToIgnoreCase(rhs.player.name); + }; + } } \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/RoomPlayerlistFragment.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/RoomPlayerlistFragment.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/RoomPlayerlistFragment.java Tue Nov 10 20:43:13 2015 +0100 @@ -38,73 +38,73 @@ import android.widget.AdapterView.OnItemClickListener; public class RoomPlayerlistFragment extends ListFragment implements OnItemClickListener { - private Netplay netplay; - private RoomPlayerlistAdapter adapter; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - netplay = Netplay.getAppInstance(getActivity().getApplicationContext()); - adapter = new RoomPlayerlistAdapter(); - adapter.setSource(netplay.roomPlayerlist); - setListAdapter(adapter); - } + private Netplay netplay; + private RoomPlayerlistAdapter adapter; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + netplay = Netplay.getAppInstance(getActivity().getApplicationContext()); + adapter = new RoomPlayerlistAdapter(); + adapter.setSource(netplay.roomPlayerlist); + setListAdapter(adapter); + } - @Override - public void onDestroy() { - super.onDestroy(); - adapter.invalidate(); - } - - @Override - public void onActivityCreated(Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - registerForContextMenu(getListView()); - getListView().setOnItemClickListener(this); - } + @Override + public void onDestroy() { + super.onDestroy(); + adapter.invalidate(); + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + registerForContextMenu(getListView()); + getListView().setOnItemClickListener(this); + } + + @Override + public void onCreateContextMenu(ContextMenu menu, View v, + ContextMenuInfo menuInfo) { + super.onCreateContextMenu(menu, v, menuInfo); + AdapterContextMenuInfo info = (AdapterContextMenuInfo)menuInfo; + String playerName = adapter.getItem(info.position).player.name; - @Override - public void onCreateContextMenu(ContextMenu menu, View v, - ContextMenuInfo menuInfo) { - super.onCreateContextMenu(menu, v, menuInfo); - AdapterContextMenuInfo info = (AdapterContextMenuInfo)menuInfo; - String playerName = adapter.getItem(info.position).player.name; - - MenuInflater inflater = getActivity().getMenuInflater(); - inflater.inflate(R.menu.room_playerlist_context, menu); - if(netplay.isChief() && !playerName.equals(netplay.getPlayerName())) { - inflater.inflate(R.menu.room_playerlist_chief_context, menu); - } - menu.setHeaderIcon(R.drawable.human); - menu.setHeaderTitle(playerName); - } - - @Override - public boolean onContextItemSelected(MenuItem item) { - AdapterContextMenuInfo info = (AdapterContextMenuInfo)item.getMenuInfo(); - PlayerInRoom player = adapter.getItem(info.position); - switch(item.getItemId()) { - case R.id.player_info: - netplay.sendPlayerInfoQuery(player.player.name); - return true; - case R.id.player_kick: - netplay.sendKick(player.player.name); - return true; - default: - return super.onContextItemSelected(item); - } - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - return inflater.inflate(R.layout.fragment_playerlist, container, false); - } - - public void onItemClick(AdapterView parent, View view, int position, long id) { - Player player = adapter.getItem(position).player; - if(player.name.equals(netplay.getPlayerName())) { - netplay.sendToggleReady(); - } - } + MenuInflater inflater = getActivity().getMenuInflater(); + inflater.inflate(R.menu.room_playerlist_context, menu); + if(netplay.isChief() && !playerName.equals(netplay.getPlayerName())) { + inflater.inflate(R.menu.room_playerlist_chief_context, menu); + } + menu.setHeaderIcon(R.drawable.human); + menu.setHeaderTitle(playerName); + } + + @Override + public boolean onContextItemSelected(MenuItem item) { + AdapterContextMenuInfo info = (AdapterContextMenuInfo)item.getMenuInfo(); + PlayerInRoom player = adapter.getItem(info.position); + switch(item.getItemId()) { + case R.id.player_info: + netplay.sendPlayerInfoQuery(player.player.name); + return true; + case R.id.player_kick: + netplay.sendKick(player.player.name); + return true; + default: + return super.onContextItemSelected(item); + } + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + return inflater.inflate(R.layout.fragment_playerlist, container, false); + } + + public void onItemClick(AdapterView parent, View view, int position, long id) { + Player player = adapter.getItem(position).player; + if(player.name.equals(netplay.getPlayerName())) { + netplay.sendToggleReady(); + } + } } diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/RoomStateManager.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/RoomStateManager.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/RoomStateManager.java Tue Nov 10 20:43:13 2015 +0100 @@ -33,78 +33,78 @@ * using these fragments both for setting up networked and local games, despite * the fact that for local games the settings can be changed immediately in * memory, while they have to be sent out to the server for networked games. - * + * * If/when the state changes as result of calling one of the "changeX" or * "requestX" functions, that will also trigger the corresponding change * listener method. There is no guarantee that calling a changeX method will * actually change the setting (e.g. if you're not room chief). - * + * * For local games, getChiefStatus is always true. - * + * * Implementations of this interface are probably not thread safe and should * only be used on the UI thread. */ public interface RoomStateManager { - // Query current state - MapRecipe getMapRecipe(); - boolean getChiefStatus(); - Scheme getScheme(); - String getGameStyle(); - Weaponset getWeaponset(); - Map getTeams(); - - // Manipulate state - void changeMapRecipe(MapRecipe map); - void changeMapTheme(String theme); + // Query current state + MapRecipe getMapRecipe(); + boolean getChiefStatus(); + Scheme getScheme(); + String getGameStyle(); + Weaponset getWeaponset(); + Map getTeams(); + + // Manipulate state + void changeMapRecipe(MapRecipe map); + void changeMapTheme(String theme); + + /** + * This function sets both the map's name and generator. There is no function + * to change them independendly since e.g. the QtFrontend relies on them being + * consistent. + * + * If the name parameter is equal to one of the MapRecipe.MAPNAME_REGULAR, MAPNAME_MAZE + * or MAPNAME_DRAWN constants, the map generator is set accordingly. Otherwise, the + * map generator is set to represent a mapfile. The map's name is always set to + * the parameter. + */ + void changeMapNameAndGenerator(String mapName); + void changeMapTemplate(int template); + void changeMazeSize(int mazeSize); + void changeMapSeed(String seed); + void changeMapDrawdata(byte[] drawdata); + + void changeScheme(Scheme scheme); + void changeGameStyle(String style); + void changeWeaponset(Weaponset weaponset); - /** - * This function sets both the map's name and generator. There is no function - * to change them independendly since e.g. the QtFrontend relies on them being - * consistent. - * - * If the name parameter is equal to one of the MapRecipe.MAPNAME_REGULAR, MAPNAME_MAZE - * or MAPNAME_DRAWN constants, the map generator is set accordingly. Otherwise, the - * map generator is set to represent a mapfile. The map's name is always set to - * the parameter. - */ - void changeMapNameAndGenerator(String mapName); - void changeMapTemplate(int template); - void changeMazeSize(int mazeSize); - void changeMapSeed(String seed); - void changeMapDrawdata(byte[] drawdata); - - void changeScheme(Scheme scheme); - void changeGameStyle(String style); - void changeWeaponset(Weaponset weaponset); - - void requestAddTeam(Team team, int colorIndex); - void requestRemoveTeam(String teamname); - void changeTeamColorIndex(String teamname, int colorIndex); - void changeTeamHogCount(String teamname, int hogcount); - - // Observe changes - void addListener(Listener observer); - void removeListener(Listener observer); - - public interface Listener { - void onMapChanged(MapRecipe recipe); - void onChiefStatusChanged(boolean isChief); - void onSchemeChanged(Scheme scheme); - void onGameStyleChanged(String gameStyle); - void onWeaponsetChanged(Weaponset weaponset); - void onTeamsChanged(Map teams); - } - - public static class ListenerAdapter implements Listener { - public void onMapChanged(MapRecipe recipe) {} - public void onChiefStatusChanged(boolean isChief) {} - public void onSchemeChanged(Scheme scheme) {} - public void onGameStyleChanged(String gameStyle) {} - public void onWeaponsetChanged(Weaponset weaponset) {} - public void onTeamsChanged(Map teams) {} - } - - public interface Provider { - RoomStateManager getRoomStateManager(); - } + void requestAddTeam(Team team, int colorIndex); + void requestRemoveTeam(String teamname); + void changeTeamColorIndex(String teamname, int colorIndex); + void changeTeamHogCount(String teamname, int hogcount); + + // Observe changes + void addListener(Listener observer); + void removeListener(Listener observer); + + public interface Listener { + void onMapChanged(MapRecipe recipe); + void onChiefStatusChanged(boolean isChief); + void onSchemeChanged(Scheme scheme); + void onGameStyleChanged(String gameStyle); + void onWeaponsetChanged(Weaponset weaponset); + void onTeamsChanged(Map teams); + } + + public static class ListenerAdapter implements Listener { + public void onMapChanged(MapRecipe recipe) {} + public void onChiefStatusChanged(boolean isChief) {} + public void onSchemeChanged(Scheme scheme) {} + public void onGameStyleChanged(String gameStyle) {} + public void onWeaponsetChanged(Weaponset weaponset) {} + public void onTeamsChanged(Map teams) {} + } + + public interface Provider { + RoomStateManager getRoomStateManager(); + } } diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/RoomlistAdapter.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/RoomlistAdapter.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/RoomlistAdapter.java Tue Nov 10 20:43:13 2015 +0100 @@ -37,77 +37,77 @@ * Displays the list of all rooms in the lobby */ public class RoomlistAdapter extends ObservableTreeMapAdapter { - private Context context; - - public RoomlistAdapter(Context context) { - this.context = context; - } - - @Override - protected Comparator getEntryOrder() { - return RoomWithId.NEWEST_FIRST_ORDER; - } - - @Override - public long getItemId(int position) { - return getItem(position).id; - } - - @Override - public boolean hasStableIds() { - return true; - } - - private static CharSequence formatExtra(Resources res, Room room) { - String ownermsg = res.getString(R.string.roomlist_owner, room.owner); - String mapmsg = res.getString(R.string.roomlist_map, room.formatMapName(res)); - String scheme = room.scheme.equals(room.weapons) ? room.scheme : room.scheme + " / " + room.weapons; - String schememsg = res.getString(R.string.roomlist_scheme, scheme); - return ownermsg + ". " + mapmsg + ", " + schememsg; - } - - public View getView(int position, View convertView, ViewGroup parent) { - View v = convertView; - if (v == null) { - LayoutInflater vi = LayoutInflater.from(context); - v = vi.inflate(R.layout.listview_room, null); - } - - Room room = getItem(position).room; - int iconRes = room.inProgress ? R.drawable.roomlist_ingame : R.drawable.roomlist_preparing; - - if(v.findViewById(android.R.id.text1) == null) { - // Tabular room list - TextView roomnameView = (TextView)v.findViewById(R.id.roomname); - TextView playerCountView = (TextView)v.findViewById(R.id.playercount); - TextView teamCountView = (TextView)v.findViewById(R.id.teamcount); - TextView ownerView = (TextView)v.findViewById(R.id.owner); - TextView mapView = (TextView)v.findViewById(R.id.map); - TextView schemeView = (TextView)v.findViewById(R.id.scheme); - TextView weaponView = (TextView)v.findViewById(R.id.weapons); - - roomnameView.setCompoundDrawablesWithIntrinsicBounds(iconRes, 0, 0, 0); - roomnameView.setText(room.name); - if(playerCountView != null) { - playerCountView.setText(String.valueOf(room.playerCount)); - } - if(teamCountView != null) { - teamCountView.setText(String.valueOf(room.teamCount)); - } - ownerView.setText(room.owner); - mapView.setText(room.formatMapName(context.getResources())); - schemeView.setText(room.scheme); - weaponView.setText(room.weapons); - } else { - // Small room list - TextView v1 = (TextView)v.findViewById(android.R.id.text1); - TextView v2 = (TextView)v.findViewById(android.R.id.text2); - - v1.setCompoundDrawablesWithIntrinsicBounds(iconRes, 0, 0, 0); - v1.setText(room.name); - v2.setText(formatExtra(context.getResources(), room)); - } - - return v; - } + private Context context; + + public RoomlistAdapter(Context context) { + this.context = context; + } + + @Override + protected Comparator getEntryOrder() { + return RoomWithId.NEWEST_FIRST_ORDER; + } + + @Override + public long getItemId(int position) { + return getItem(position).id; + } + + @Override + public boolean hasStableIds() { + return true; + } + + private static CharSequence formatExtra(Resources res, Room room) { + String ownermsg = res.getString(R.string.roomlist_owner, room.owner); + String mapmsg = res.getString(R.string.roomlist_map, room.formatMapName(res)); + String scheme = room.scheme.equals(room.weapons) ? room.scheme : room.scheme + " / " + room.weapons; + String schememsg = res.getString(R.string.roomlist_scheme, scheme); + return ownermsg + ". " + mapmsg + ", " + schememsg; + } + + public View getView(int position, View convertView, ViewGroup parent) { + View v = convertView; + if (v == null) { + LayoutInflater vi = LayoutInflater.from(context); + v = vi.inflate(R.layout.listview_room, null); + } + + Room room = getItem(position).room; + int iconRes = room.inProgress ? R.drawable.roomlist_ingame : R.drawable.roomlist_preparing; + + if(v.findViewById(android.R.id.text1) == null) { + // Tabular room list + TextView roomnameView = (TextView)v.findViewById(R.id.roomname); + TextView playerCountView = (TextView)v.findViewById(R.id.playercount); + TextView teamCountView = (TextView)v.findViewById(R.id.teamcount); + TextView ownerView = (TextView)v.findViewById(R.id.owner); + TextView mapView = (TextView)v.findViewById(R.id.map); + TextView schemeView = (TextView)v.findViewById(R.id.scheme); + TextView weaponView = (TextView)v.findViewById(R.id.weapons); + + roomnameView.setCompoundDrawablesWithIntrinsicBounds(iconRes, 0, 0, 0); + roomnameView.setText(room.name); + if(playerCountView != null) { + playerCountView.setText(String.valueOf(room.playerCount)); + } + if(teamCountView != null) { + teamCountView.setText(String.valueOf(room.teamCount)); + } + ownerView.setText(room.owner); + mapView.setText(room.formatMapName(context.getResources())); + schemeView.setText(room.scheme); + weaponView.setText(room.weapons); + } else { + // Small room list + TextView v1 = (TextView)v.findViewById(android.R.id.text1); + TextView v2 = (TextView)v.findViewById(android.R.id.text2); + + v1.setCompoundDrawablesWithIntrinsicBounds(iconRes, 0, 0, 0); + v1.setText(room.name); + v2.setText(formatExtra(context.getResources(), room)); + } + + return v; + } } \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/RoomlistFragment.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/RoomlistFragment.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/RoomlistFragment.java Tue Nov 10 20:43:13 2015 +0100 @@ -35,60 +35,60 @@ * Displays the list of all rooms in the lobby */ public class RoomlistFragment extends ListFragment implements OnItemClickListener { - private static final int AUTO_REFRESH_INTERVAL_MS = 15000; - - private Netplay netplay; - private RoomlistAdapter adapter; - private CountDownTimer autoRefreshTimer = new CountDownTimer(Long.MAX_VALUE, AUTO_REFRESH_INTERVAL_MS) { - @Override - public void onTick(long millisUntilFinished) { - netplay.sendRoomlistRequest(); - } - - @Override - public void onFinish() { } - }; + private static final int AUTO_REFRESH_INTERVAL_MS = 15000; + + private Netplay netplay; + private RoomlistAdapter adapter; + private CountDownTimer autoRefreshTimer = new CountDownTimer(Long.MAX_VALUE, AUTO_REFRESH_INTERVAL_MS) { + @Override + public void onTick(long millisUntilFinished) { + netplay.sendRoomlistRequest(); + } + + @Override + public void onFinish() { } + }; - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - netplay = Netplay.getAppInstance(getActivity().getApplicationContext()); - adapter = new RoomlistAdapter(getActivity()); - adapter.setSource(netplay.roomList); - setListAdapter(adapter); - } + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + netplay = Netplay.getAppInstance(getActivity().getApplicationContext()); + adapter = new RoomlistAdapter(getActivity()); + adapter.setSource(netplay.roomList); + setListAdapter(adapter); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + return inflater.inflate(R.layout.fragment_roomlist, container, false); + } - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - return inflater.inflate(R.layout.fragment_roomlist, container, false); - } - - @Override - public void onActivityCreated(Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - getListView().setOnItemClickListener(this); - } - - @Override - public void onResume() { - super.onResume(); - autoRefreshTimer.start(); - } - - @Override - public void onPause() { - super.onPause(); - autoRefreshTimer.cancel(); - } - - @Override - public void onDestroy() { - super.onDestroy(); - adapter.invalidate(); - } - - public void onItemClick(AdapterView parent, View view, int position, long id) { - netplay.sendJoinRoom(adapter.getItem(position).room.name); - } + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + getListView().setOnItemClickListener(this); + } + + @Override + public void onResume() { + super.onResume(); + autoRefreshTimer.start(); + } + + @Override + public void onPause() { + super.onPause(); + autoRefreshTimer.cancel(); + } + + @Override + public void onDestroy() { + super.onDestroy(); + adapter.invalidate(); + } + + public void onItemClick(AdapterView parent, View view, int position, long id) { + netplay.sendJoinRoom(adapter.getItem(position).room.name); + } } diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/SDLActivity.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/SDLActivity.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/SDLActivity.java Tue Nov 10 20:43:13 2015 +0100 @@ -2,7 +2,7 @@ * Hedgewars for Android. An Android port of Hedgewars, a free turn based strategy game * Copyright (c) 2011-2012 Richard Deurwaarder * Copyright (C) 2012 Simeon Maxein - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -62,358 +62,358 @@ SDL Activity */ public class SDLActivity extends Activity { - /** - * Set startConfig to the desired config when starting this activity. This avoids having to parcel all - * the config objects into the Intent. Not particularly elegant, but it's actually a recommended - * way to do this (http://developer.android.com/guide/faq/framework.html#3) - */ - public static volatile GameConfig startConfig; - public static volatile boolean startNetgame; - - // Main components - public static SDLActivity mSingleton; - private static SDLSurface mSurface; - private static Thread mSDLThread; + /** + * Set startConfig to the desired config when starting this activity. This avoids having to parcel all + * the config objects into the Intent. Not particularly elegant, but it's actually a recommended + * way to do this (http://developer.android.com/guide/faq/framework.html#3) + */ + public static volatile GameConfig startConfig; + public static volatile boolean startNetgame; - // Audio - private static Thread mAudioThread; - private static AudioTrack mAudioTrack; + // Main components + public static SDLActivity mSingleton; + private static SDLSurface mSurface; + private static Thread mSDLThread; - // EGL private objects - private static EGLContext mEGLContext; - private static EGLSurface mEGLSurface; - private static EGLDisplay mEGLDisplay; - private static EGLConfig mEGLConfig; - private static int mGLMajor, mGLMinor; + // Audio + private static Thread mAudioThread; + private static AudioTrack mAudioTrack; + + // EGL private objects + private static EGLContext mEGLContext; + private static EGLSurface mEGLSurface; + private static EGLDisplay mEGLDisplay; + private static EGLConfig mEGLConfig; + private static int mGLMajor, mGLMinor; - // Load the .so - static { - System.loadLibrary("SDL"); - System.loadLibrary("main"); - } + // Load the .so + static { + System.loadLibrary("SDL"); + System.loadLibrary("main"); + } - // Setup - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); + // Setup + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); - // So we can call stuff from static callbacks - mSingleton = this; + // So we can call stuff from static callbacks + mSingleton = this; - // Set up the surface - mSurface = new SDLSurface(getApplication(), startConfig, startNetgame); - startConfig = null; - setContentView(mSurface); - } + // Set up the surface + mSurface = new SDLSurface(getApplication(), startConfig, startNetgame); + startConfig = null; + setContentView(mSurface); + } - // Events - protected void onPause() { - Log.v("SDL", "onPause()"); - super.onPause(); + // Events + protected void onPause() { + Log.v("SDL", "onPause()"); + super.onPause(); - if(mEGLDisplay != null && mEGLContext != null){ - EGL10 egl = (EGL10)EGLContext.getEGL(); - egl.eglDestroyContext(mEGLDisplay, mEGLContext); - mEGLDisplay = null; - mEGLContext = null; - } + if(mEGLDisplay != null && mEGLContext != null){ + EGL10 egl = (EGL10)EGLContext.getEGL(); + egl.eglDestroyContext(mEGLDisplay, mEGLContext); + mEGLDisplay = null; + mEGLContext = null; + } - SDLActivity.nativePause(); - } + SDLActivity.nativePause(); + } - protected void onResume() { - Log.v("SDL", "onResume()"); - super.onResume(); - } + protected void onResume() { + Log.v("SDL", "onResume()"); + super.onResume(); + } - protected void onDestroy() { - super.onDestroy(); - Log.v("SDL", "onDestroy()"); - // Send a quit message to the application - SDLActivity.nativeQuit(); - // Now wait for the SDL thread to quit - if (mSDLThread != null) { - try { - mSDLThread.join(); - } catch(Exception e) { - Log.w("SDL", "Problem stopping thread: " + e); - } - mSDLThread = null; - } - mSingleton = null; - } - - public static void synchronizedNativeInit(String...args) { - synchronized(PascalExports.engineMutex) { - nativeInit(args); - } - } - - // C functions we call - private static native void nativeInit(String...args); - public static native void nativeQuit(); - public static native void nativePause(); - public static native void nativeResume(); - public static native void onNativeResize(int x, int y, int format); - public static native void onNativeKeyDown(int keycode); - public static native void onNativeKeyUp(int keycode); - public static native void onNativeTouch(int touchDevId, int pointerFingerId, - int action, float x, - float y, float p); - public static native void onNativeAccel(float x, float y, float z); - public static native void nativeRunAudioThread(); + protected void onDestroy() { + super.onDestroy(); + Log.v("SDL", "onDestroy()"); + // Send a quit message to the application + SDLActivity.nativeQuit(); + // Now wait for the SDL thread to quit + if (mSDLThread != null) { + try { + mSDLThread.join(); + } catch(Exception e) { + Log.w("SDL", "Problem stopping thread: " + e); + } + mSDLThread = null; + } + mSingleton = null; + } + + public static void synchronizedNativeInit(String...args) { + synchronized(PascalExports.engineMutex) { + nativeInit(args); + } + } + + // C functions we call + private static native void nativeInit(String...args); + public static native void nativeQuit(); + public static native void nativePause(); + public static native void nativeResume(); + public static native void onNativeResize(int x, int y, int format); + public static native void onNativeKeyDown(int keycode); + public static native void onNativeKeyUp(int keycode); + public static native void onNativeTouch(int touchDevId, int pointerFingerId, + int action, float x, + float y, float p); + public static native void onNativeAccel(float x, float y, float z); + public static native void nativeRunAudioThread(); - // Java functions called from C + // Java functions called from C - public static boolean createGLContext(int majorVersion, int minorVersion) { - return initEGL(majorVersion, minorVersion); - } + public static boolean createGLContext(int majorVersion, int minorVersion) { + return initEGL(majorVersion, minorVersion); + } - public static void flipBuffers() { - flipEGL(); - } + public static void flipBuffers() { + flipEGL(); + } - public static void setActivityTitle(final String title) { - // Called from SDLMain() thread and can't directly affect the view - mSingleton.runOnUiThread(new Runnable() { - public void run() { - mSingleton.setTitle(title); - } - }); - } + public static void setActivityTitle(final String title) { + // Called from SDLMain() thread and can't directly affect the view + mSingleton.runOnUiThread(new Runnable() { + public void run() { + mSingleton.setTitle(title); + } + }); + } - public static Context getContext() { - return mSingleton; - } + public static Context getContext() { + return mSingleton; + } - public static void startApp(final int width, final int height, GameConfig config, boolean netgame) { - // Start up the C app thread - if (mSDLThread == null) { - mSDLThread = new Thread(new SDLMain(width, height, config, netgame)); - mSDLThread.start(); - } else { - SDLActivity.nativeResume(); - } - } + public static void startApp(final int width, final int height, GameConfig config, boolean netgame) { + // Start up the C app thread + if (mSDLThread == null) { + mSDLThread = new Thread(new SDLMain(width, height, config, netgame)); + mSDLThread.start(); + } else { + SDLActivity.nativeResume(); + } + } - // EGL functions - public static boolean initEGL(int majorVersion, int minorVersion) { - if (SDLActivity.mEGLDisplay == null) { - try { - EGL10 egl = (EGL10)EGLContext.getEGL(); + // EGL functions + public static boolean initEGL(int majorVersion, int minorVersion) { + if (SDLActivity.mEGLDisplay == null) { + try { + EGL10 egl = (EGL10)EGLContext.getEGL(); - EGLDisplay dpy = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); + EGLDisplay dpy = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); - int[] version = new int[2]; - egl.eglInitialize(dpy, version); + int[] version = new int[2]; + egl.eglInitialize(dpy, version); - int EGL_OPENGL_ES_BIT = 1; - int EGL_OPENGL_ES2_BIT = 4; - int renderableType = 0; - if (majorVersion == 2) { - renderableType = EGL_OPENGL_ES2_BIT; - } else if (majorVersion == 1) { - renderableType = EGL_OPENGL_ES_BIT; - } - int[] configSpec = { - EGL10.EGL_RENDERABLE_TYPE, renderableType, - EGL10.EGL_NONE - }; - EGLConfig[] configs = new EGLConfig[1]; - int[] num_config = new int[1]; - if (!egl.eglChooseConfig(dpy, configSpec, configs, 1, num_config) || num_config[0] == 0) { - Log.e("SDL", "No EGL config available"); - return false; - } - EGLConfig config = configs[0]; + int EGL_OPENGL_ES_BIT = 1; + int EGL_OPENGL_ES2_BIT = 4; + int renderableType = 0; + if (majorVersion == 2) { + renderableType = EGL_OPENGL_ES2_BIT; + } else if (majorVersion == 1) { + renderableType = EGL_OPENGL_ES_BIT; + } + int[] configSpec = { + EGL10.EGL_RENDERABLE_TYPE, renderableType, + EGL10.EGL_NONE + }; + EGLConfig[] configs = new EGLConfig[1]; + int[] num_config = new int[1]; + if (!egl.eglChooseConfig(dpy, configSpec, configs, 1, num_config) || num_config[0] == 0) { + Log.e("SDL", "No EGL config available"); + return false; + } + EGLConfig config = configs[0]; - SDLActivity.mEGLDisplay = dpy; - SDLActivity.mEGLConfig = config; - SDLActivity.mGLMajor = majorVersion; - SDLActivity.mGLMinor = minorVersion; + SDLActivity.mEGLDisplay = dpy; + SDLActivity.mEGLConfig = config; + SDLActivity.mGLMajor = majorVersion; + SDLActivity.mGLMinor = minorVersion; - SDLActivity.createEGLSurface(); - } catch(Exception e) { - Log.v("SDL", e + ""); - for (StackTraceElement s : e.getStackTrace()) { - Log.v("SDL", s.toString()); - } - } - } - else SDLActivity.createEGLSurface(); + SDLActivity.createEGLSurface(); + } catch(Exception e) { + Log.v("SDL", e + ""); + for (StackTraceElement s : e.getStackTrace()) { + Log.v("SDL", s.toString()); + } + } + } + else SDLActivity.createEGLSurface(); - return true; - } + return true; + } - public static boolean createEGLContext() { - EGL10 egl = (EGL10)EGLContext.getEGL(); - int EGL_CONTEXT_CLIENT_VERSION=0x3098; - int contextAttrs[] = new int[] { EGL_CONTEXT_CLIENT_VERSION, SDLActivity.mGLMajor, EGL10.EGL_NONE }; - SDLActivity.mEGLContext = egl.eglCreateContext(SDLActivity.mEGLDisplay, SDLActivity.mEGLConfig, EGL10.EGL_NO_CONTEXT, contextAttrs); - if (SDLActivity.mEGLContext == EGL10.EGL_NO_CONTEXT) { - Log.e("SDL", "Couldn't create context"); - return false; - } - return true; - } + public static boolean createEGLContext() { + EGL10 egl = (EGL10)EGLContext.getEGL(); + int EGL_CONTEXT_CLIENT_VERSION=0x3098; + int contextAttrs[] = new int[] { EGL_CONTEXT_CLIENT_VERSION, SDLActivity.mGLMajor, EGL10.EGL_NONE }; + SDLActivity.mEGLContext = egl.eglCreateContext(SDLActivity.mEGLDisplay, SDLActivity.mEGLConfig, EGL10.EGL_NO_CONTEXT, contextAttrs); + if (SDLActivity.mEGLContext == EGL10.EGL_NO_CONTEXT) { + Log.e("SDL", "Couldn't create context"); + return false; + } + return true; + } - public static boolean createEGLSurface() { - if (SDLActivity.mEGLDisplay != null && SDLActivity.mEGLConfig != null) { - EGL10 egl = (EGL10)EGLContext.getEGL(); - if (SDLActivity.mEGLContext == null) createEGLContext(); + public static boolean createEGLSurface() { + if (SDLActivity.mEGLDisplay != null && SDLActivity.mEGLConfig != null) { + EGL10 egl = (EGL10)EGLContext.getEGL(); + if (SDLActivity.mEGLContext == null) createEGLContext(); - Log.v("SDL", "Creating new EGL Surface"); - EGLSurface surface = egl.eglCreateWindowSurface(SDLActivity.mEGLDisplay, SDLActivity.mEGLConfig, SDLActivity.mSurface, null); - if (surface == EGL10.EGL_NO_SURFACE) { - Log.e("SDL", "Couldn't create surface"); - return false; - } + Log.v("SDL", "Creating new EGL Surface"); + EGLSurface surface = egl.eglCreateWindowSurface(SDLActivity.mEGLDisplay, SDLActivity.mEGLConfig, SDLActivity.mSurface, null); + if (surface == EGL10.EGL_NO_SURFACE) { + Log.e("SDL", "Couldn't create surface"); + return false; + } - if (!egl.eglMakeCurrent(SDLActivity.mEGLDisplay, surface, surface, SDLActivity.mEGLContext)) { - Log.e("SDL", "Old EGL Context doesnt work, trying with a new one"); - createEGLContext(); - if (!egl.eglMakeCurrent(SDLActivity.mEGLDisplay, surface, surface, SDLActivity.mEGLContext)) { - Log.e("SDL", "Failed making EGL Context current"); - return false; - } - } - SDLActivity.mEGLSurface = surface; - return true; - } - return false; - } + if (!egl.eglMakeCurrent(SDLActivity.mEGLDisplay, surface, surface, SDLActivity.mEGLContext)) { + Log.e("SDL", "Old EGL Context doesnt work, trying with a new one"); + createEGLContext(); + if (!egl.eglMakeCurrent(SDLActivity.mEGLDisplay, surface, surface, SDLActivity.mEGLContext)) { + Log.e("SDL", "Failed making EGL Context current"); + return false; + } + } + SDLActivity.mEGLSurface = surface; + return true; + } + return false; + } - // EGL buffer flip - public static void flipEGL() { - try { - EGL10 egl = (EGL10)EGLContext.getEGL(); + // EGL buffer flip + public static void flipEGL() { + try { + EGL10 egl = (EGL10)EGLContext.getEGL(); - egl.eglWaitNative(EGL10.EGL_CORE_NATIVE_ENGINE, null); + egl.eglWaitNative(EGL10.EGL_CORE_NATIVE_ENGINE, null); - // drawing here + // drawing here - egl.eglWaitGL(); + egl.eglWaitGL(); - egl.eglSwapBuffers(SDLActivity.mEGLDisplay, SDLActivity.mEGLSurface); + egl.eglSwapBuffers(SDLActivity.mEGLDisplay, SDLActivity.mEGLSurface); - } catch(Exception e) { - Log.v("SDL", "flipEGL(): " + e); - for (StackTraceElement s : e.getStackTrace()) { - Log.v("SDL", s.toString()); - } - } - } + } catch(Exception e) { + Log.v("SDL", "flipEGL(): " + e); + for (StackTraceElement s : e.getStackTrace()) { + Log.v("SDL", s.toString()); + } + } + } - // Audio - private static Object buf; + // Audio + private static Object buf; - public static Object audioInit(int sampleRate, boolean is16Bit, boolean isStereo, int desiredFrames) { - int channelConfig = isStereo ? AudioFormat.CHANNEL_CONFIGURATION_STEREO : AudioFormat.CHANNEL_CONFIGURATION_MONO; - int audioFormat = is16Bit ? AudioFormat.ENCODING_PCM_16BIT : AudioFormat.ENCODING_PCM_8BIT; - int frameSize = (isStereo ? 2 : 1) * (is16Bit ? 2 : 1); + public static Object audioInit(int sampleRate, boolean is16Bit, boolean isStereo, int desiredFrames) { + int channelConfig = isStereo ? AudioFormat.CHANNEL_CONFIGURATION_STEREO : AudioFormat.CHANNEL_CONFIGURATION_MONO; + int audioFormat = is16Bit ? AudioFormat.ENCODING_PCM_16BIT : AudioFormat.ENCODING_PCM_8BIT; + int frameSize = (isStereo ? 2 : 1) * (is16Bit ? 2 : 1); - Log.v("SDL", "SDL audio: wanted " + (isStereo ? "stereo" : "mono") + " " + (is16Bit ? "16-bit" : "8-bit") + " " + ((float)sampleRate / 1000f) + "kHz, " + desiredFrames + " frames buffer"); + Log.v("SDL", "SDL audio: wanted " + (isStereo ? "stereo" : "mono") + " " + (is16Bit ? "16-bit" : "8-bit") + " " + ((float)sampleRate / 1000f) + "kHz, " + desiredFrames + " frames buffer"); - // Let the user pick a larger buffer if they really want -- but ye - // gods they probably shouldn't, the minimums are horrifyingly high - // latency already - desiredFrames = Math.max(desiredFrames, (AudioTrack.getMinBufferSize(sampleRate, channelConfig, audioFormat) + frameSize - 1) / frameSize); + // Let the user pick a larger buffer if they really want -- but ye + // gods they probably shouldn't, the minimums are horrifyingly high + // latency already + desiredFrames = Math.max(desiredFrames, (AudioTrack.getMinBufferSize(sampleRate, channelConfig, audioFormat) + frameSize - 1) / frameSize); - mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRate, - channelConfig, audioFormat, desiredFrames * frameSize, AudioTrack.MODE_STREAM); + mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRate, + channelConfig, audioFormat, desiredFrames * frameSize, AudioTrack.MODE_STREAM); - audioStartThread(); + audioStartThread(); - Log.v("SDL", "SDL audio: got " + ((mAudioTrack.getChannelCount() >= 2) ? "stereo" : "mono") + " " + ((mAudioTrack.getAudioFormat() == AudioFormat.ENCODING_PCM_16BIT) ? "16-bit" : "8-bit") + " " + ((float)mAudioTrack.getSampleRate() / 1000f) + "kHz, " + desiredFrames + " frames buffer"); + Log.v("SDL", "SDL audio: got " + ((mAudioTrack.getChannelCount() >= 2) ? "stereo" : "mono") + " " + ((mAudioTrack.getAudioFormat() == AudioFormat.ENCODING_PCM_16BIT) ? "16-bit" : "8-bit") + " " + ((float)mAudioTrack.getSampleRate() / 1000f) + "kHz, " + desiredFrames + " frames buffer"); - if (is16Bit) { - buf = new short[desiredFrames * (isStereo ? 2 : 1)]; - } else { - buf = new byte[desiredFrames * (isStereo ? 2 : 1)]; - } - return buf; - } + if (is16Bit) { + buf = new short[desiredFrames * (isStereo ? 2 : 1)]; + } else { + buf = new byte[desiredFrames * (isStereo ? 2 : 1)]; + } + return buf; + } - public static void audioStartThread() { - mAudioThread = new Thread(new Runnable() { - public void run() { - mAudioTrack.play(); - nativeRunAudioThread(); - } - }); + public static void audioStartThread() { + mAudioThread = new Thread(new Runnable() { + public void run() { + mAudioTrack.play(); + nativeRunAudioThread(); + } + }); - // I'd take REALTIME if I could get it! - mAudioThread.setPriority(Thread.MAX_PRIORITY); - mAudioThread.start(); - } + // I'd take REALTIME if I could get it! + mAudioThread.setPriority(Thread.MAX_PRIORITY); + mAudioThread.start(); + } - public static void audioWriteShortBuffer(short[] buffer) { - for (int i = 0; i < buffer.length; ) { - int result = mAudioTrack.write(buffer, i, buffer.length - i); - if (result > 0) { - i += result; - } else if (result == 0) { - try { - Thread.sleep(1); - } catch(InterruptedException e) { - // Nom nom - } - } else { - Log.w("SDL", "SDL audio: error return from write(short)"); - return; - } - } - } + public static void audioWriteShortBuffer(short[] buffer) { + for (int i = 0; i < buffer.length; ) { + int result = mAudioTrack.write(buffer, i, buffer.length - i); + if (result > 0) { + i += result; + } else if (result == 0) { + try { + Thread.sleep(1); + } catch(InterruptedException e) { + // Nom nom + } + } else { + Log.w("SDL", "SDL audio: error return from write(short)"); + return; + } + } + } - public static void audioWriteByteBuffer(byte[] buffer) { - for (int i = 0; i < buffer.length; ) { - int result = mAudioTrack.write(buffer, i, buffer.length - i); - if (result > 0) { - i += result; - } else if (result == 0) { - try { - Thread.sleep(1); - } catch(InterruptedException e) { - // Nom nom - } - } else { - Log.w("SDL", "SDL audio: error return from write(short)"); - return; - } - } - } + public static void audioWriteByteBuffer(byte[] buffer) { + for (int i = 0; i < buffer.length; ) { + int result = mAudioTrack.write(buffer, i, buffer.length - i); + if (result > 0) { + i += result; + } else if (result == 0) { + try { + Thread.sleep(1); + } catch(InterruptedException e) { + // Nom nom + } + } else { + Log.w("SDL", "SDL audio: error return from write(short)"); + return; + } + } + } - public static void audioQuit() { - if (mAudioThread != null) { - try { - mAudioThread.join(); - } catch(Exception e) { - Log.v("SDL", "Problem stopping audio thread: " + e); - } - mAudioThread = null; + public static void audioQuit() { + if (mAudioThread != null) { + try { + mAudioThread.join(); + } catch(Exception e) { + Log.v("SDL", "Problem stopping audio thread: " + e); + } + mAudioThread = null; - //Log.v("SDL", "Finished waiting for audio thread"); - } + //Log.v("SDL", "Finished waiting for audio thread"); + } - if (mAudioTrack != null) { - mAudioTrack.stop(); - mAudioTrack = null; - } - } - - public static int getDensity(){ - DisplayMetrics dm = SDLActivity.getContext().getResources().getDisplayMetrics(); - return dm.densityDpi; - } + if (mAudioTrack != null) { + mAudioTrack.stop(); + mAudioTrack = null; + } + } + + public static int getDensity(){ + DisplayMetrics dm = SDLActivity.getContext().getResources().getDisplayMetrics(); + return dm.densityDpi; + } } /** Simple nativeInit() runnable */ class SDLMain implements Runnable { - public static final String TAG = "SDLMain"; - + public static final String TAG = "SDLMain"; + public static final int RQ_LOWRES = 0x00000001; // use half land array public static final int RQ_BLURRY_LAND = 0x00000002; // downscaled terrain public static final int RQ_NO_BACKGROUND = 0x00000004; // don't draw background @@ -426,246 +426,246 @@ public static final int RQ_NO_CLAMPING = 0x00000200; // don't clamp textures public static final int RQ_NO_TOOLTIPS = 0x00000400; // tooltips are not drawn public static final int RQ_NO_VSYNC = 0x00000800; // don't sync on vblank - - private final int surfaceWidth, surfaceHeight; - private final String playerName; - private final GameConfig config; - private final boolean netgame; - - public SDLMain(int width, int height, GameConfig config, boolean netgame) { - surfaceWidth = width; - surfaceHeight = height; - if(netgame) { - playerName = Netplay.getAppInstance(SDLActivity.getContext().getApplicationContext()).getPlayerName(); - } else { - playerName = "Player"; - } - this.config = config; - this.netgame = netgame; - } + + private final int surfaceWidth, surfaceHeight; + private final String playerName; + private final GameConfig config; + private final boolean netgame; + + public SDLMain(int width, int height, GameConfig config, boolean netgame) { + surfaceWidth = width; + surfaceHeight = height; + if(netgame) { + playerName = Netplay.getAppInstance(SDLActivity.getContext().getApplicationContext()).getPlayerName(); + } else { + playerName = "Player"; + } + this.config = config; + this.netgame = netgame; + } - public void run() { - //Set up the IPC socket server to communicate with the engine - GameConnection gameConn; - String path; - try { - if(netgame) { - Netplay netplay = Netplay.getAppInstance(SDLActivity.mSingleton.getApplicationContext()); - gameConn = GameConnection.forNetgame(config, netplay); - } else { - gameConn = GameConnection.forLocalGame(config); - } - - path = FileUtils.getDataPathFile(SDLActivity.mSingleton).getAbsolutePath(); - Log.d(TAG, "Starting engine"); - // Runs SDL_main() with added parameters - try { - String pPort = String.valueOf(gameConn.port); - String pWidth = String.valueOf(surfaceWidth); - String pHeight = String.valueOf(surfaceHeight); - String pQuality = Integer.toString(RQ_NO_FLAKES|RQ_NO_DROPLETS|RQ_SIMPLE_EXPLOSIONS); - String pPlayerName = Base64.encodeToString(playerName.getBytes("UTF-8"), 0); - SDLActivity.synchronizedNativeInit(new String[] { pPort, pWidth, pHeight, pQuality, "en.txt", pPlayerName, "1", "1", "1", path, "" }); - } catch (UnsupportedEncodingException e) { - throw new AssertionError(e); // never happens - } - Log.d(TAG, "Engine stopped"); - } catch(ConnectException e) { - Log.e(TAG, "Error starting IPC connection"); - } catch (IOException e) { - Log.e(TAG, "Missing SDCard"); - } - SDLActivity.mSingleton.runOnUiThread(new Runnable() { public void run() { - if(SDLActivity.mSingleton != null) { - SDLActivity.mSingleton.finish(); - } - }}); - } + public void run() { + //Set up the IPC socket server to communicate with the engine + GameConnection gameConn; + String path; + try { + if(netgame) { + Netplay netplay = Netplay.getAppInstance(SDLActivity.mSingleton.getApplicationContext()); + gameConn = GameConnection.forNetgame(config, netplay); + } else { + gameConn = GameConnection.forLocalGame(config); + } + + path = FileUtils.getDataPathFile(SDLActivity.mSingleton).getAbsolutePath(); + Log.d(TAG, "Starting engine"); + // Runs SDL_main() with added parameters + try { + String pPort = String.valueOf(gameConn.port); + String pWidth = String.valueOf(surfaceWidth); + String pHeight = String.valueOf(surfaceHeight); + String pQuality = Integer.toString(RQ_NO_FLAKES|RQ_NO_DROPLETS|RQ_SIMPLE_EXPLOSIONS); + String pPlayerName = Base64.encodeToString(playerName.getBytes("UTF-8"), 0); + SDLActivity.synchronizedNativeInit(new String[] { pPort, pWidth, pHeight, pQuality, "en.txt", pPlayerName, "1", "1", "1", path, "" }); + } catch (UnsupportedEncodingException e) { + throw new AssertionError(e); // never happens + } + Log.d(TAG, "Engine stopped"); + } catch(ConnectException e) { + Log.e(TAG, "Error starting IPC connection"); + } catch (IOException e) { + Log.e(TAG, "Missing SDCard"); + } + SDLActivity.mSingleton.runOnUiThread(new Runnable() { public void run() { + if(SDLActivity.mSingleton != null) { + SDLActivity.mSingleton.finish(); + } + }}); + } } /** SDLSurface. This is what we draw on, so we need to know when it's created - in order to do anything useful. + in order to do anything useful. Because of this, that's where we set up the SDL thread */ -class SDLSurface extends SurfaceView implements SurfaceHolder.Callback, +class SDLSurface extends SurfaceView implements SurfaceHolder.Callback, View.OnKeyListener, View.OnTouchListener, SensorEventListener { - private GameConfig config; - private boolean netgame; - - // Sensors - private static SensorManager mSensorManager; + private GameConfig config; + private boolean netgame; + + // Sensors + private static SensorManager mSensorManager; - // Startup - public SDLSurface(Context context, GameConfig _config, boolean netgame) { - super(context); - getHolder().addCallback(this); + // Startup + public SDLSurface(Context context, GameConfig _config, boolean netgame) { + super(context); + getHolder().addCallback(this); - setFocusable(true); - setFocusableInTouchMode(true); - requestFocus(); - setOnKeyListener(this); - setOnTouchListener(this); + setFocusable(true); + setFocusableInTouchMode(true); + requestFocus(); + setOnKeyListener(this); + setOnTouchListener(this); - mSensorManager = (SensorManager)context.getSystemService("sensor"); - config = _config; - this.netgame = netgame; - } + mSensorManager = (SensorManager)context.getSystemService("sensor"); + config = _config; + this.netgame = netgame; + } - // Called when we have a valid drawing surface - public void surfaceCreated(SurfaceHolder holder) { - Log.v("SDL", "surfaceCreated()"); - holder.setType(SurfaceHolder.SURFACE_TYPE_GPU); - SDLActivity.createEGLSurface(); - // enableSensor(Sensor.TYPE_ACCELEROMETER, true); - } + // Called when we have a valid drawing surface + public void surfaceCreated(SurfaceHolder holder) { + Log.v("SDL", "surfaceCreated()"); + holder.setType(SurfaceHolder.SURFACE_TYPE_GPU); + SDLActivity.createEGLSurface(); + // enableSensor(Sensor.TYPE_ACCELEROMETER, true); + } - // Called when we lose the surface - public void surfaceDestroyed(SurfaceHolder holder) { - Log.v("SDL", "surfaceDestroyed()"); - SDLActivity.nativePause(); - // enableSensor(Sensor.TYPE_ACCELEROMETER, false); - } + // Called when we lose the surface + public void surfaceDestroyed(SurfaceHolder holder) { + Log.v("SDL", "surfaceDestroyed()"); + SDLActivity.nativePause(); + // enableSensor(Sensor.TYPE_ACCELEROMETER, false); + } - // Called when the surface is resized - public void surfaceChanged(SurfaceHolder holder, - int format, int width, int height) { - Log.v("SDL", "surfaceChanged()"); + // Called when the surface is resized + public void surfaceChanged(SurfaceHolder holder, + int format, int width, int height) { + Log.v("SDL", "surfaceChanged()"); - int sdlFormat = 0x85151002; // SDL_PIXELFORMAT_RGB565 by default - switch (format) { - case PixelFormat.A_8: - Log.v("SDL", "pixel format A_8"); - break; - case PixelFormat.LA_88: - Log.v("SDL", "pixel format LA_88"); - break; - case PixelFormat.L_8: - Log.v("SDL", "pixel format L_8"); - break; - case PixelFormat.RGBA_4444: - Log.v("SDL", "pixel format RGBA_4444"); - sdlFormat = 0x85421002; // SDL_PIXELFORMAT_RGBA4444 - break; - case PixelFormat.RGBA_5551: - Log.v("SDL", "pixel format RGBA_5551"); - sdlFormat = 0x85441002; // SDL_PIXELFORMAT_RGBA5551 - break; - case PixelFormat.RGBA_8888: - Log.v("SDL", "pixel format RGBA_8888"); - sdlFormat = 0x86462004; // SDL_PIXELFORMAT_RGBA8888 - break; - case PixelFormat.RGBX_8888: - Log.v("SDL", "pixel format RGBX_8888"); - sdlFormat = 0x86262004; // SDL_PIXELFORMAT_RGBX8888 - break; - case PixelFormat.RGB_332: - Log.v("SDL", "pixel format RGB_332"); - sdlFormat = 0x84110801; // SDL_PIXELFORMAT_RGB332 - break; - case PixelFormat.RGB_565: - Log.v("SDL", "pixel format RGB_565"); - sdlFormat = 0x85151002; // SDL_PIXELFORMAT_RGB565 - break; - case PixelFormat.RGB_888: - Log.v("SDL", "pixel format RGB_888"); - // Not sure this is right, maybe SDL_PIXELFORMAT_RGB24 instead? - sdlFormat = 0x86161804; // SDL_PIXELFORMAT_RGB888 - break; - default: - Log.v("SDL", "pixel format unknown " + format); - break; - } - SDLActivity.onNativeResize(width, height, sdlFormat); - Log.v("SDL", "Window size:" + width + "x"+height); + int sdlFormat = 0x85151002; // SDL_PIXELFORMAT_RGB565 by default + switch (format) { + case PixelFormat.A_8: + Log.v("SDL", "pixel format A_8"); + break; + case PixelFormat.LA_88: + Log.v("SDL", "pixel format LA_88"); + break; + case PixelFormat.L_8: + Log.v("SDL", "pixel format L_8"); + break; + case PixelFormat.RGBA_4444: + Log.v("SDL", "pixel format RGBA_4444"); + sdlFormat = 0x85421002; // SDL_PIXELFORMAT_RGBA4444 + break; + case PixelFormat.RGBA_5551: + Log.v("SDL", "pixel format RGBA_5551"); + sdlFormat = 0x85441002; // SDL_PIXELFORMAT_RGBA5551 + break; + case PixelFormat.RGBA_8888: + Log.v("SDL", "pixel format RGBA_8888"); + sdlFormat = 0x86462004; // SDL_PIXELFORMAT_RGBA8888 + break; + case PixelFormat.RGBX_8888: + Log.v("SDL", "pixel format RGBX_8888"); + sdlFormat = 0x86262004; // SDL_PIXELFORMAT_RGBX8888 + break; + case PixelFormat.RGB_332: + Log.v("SDL", "pixel format RGB_332"); + sdlFormat = 0x84110801; // SDL_PIXELFORMAT_RGB332 + break; + case PixelFormat.RGB_565: + Log.v("SDL", "pixel format RGB_565"); + sdlFormat = 0x85151002; // SDL_PIXELFORMAT_RGB565 + break; + case PixelFormat.RGB_888: + Log.v("SDL", "pixel format RGB_888"); + // Not sure this is right, maybe SDL_PIXELFORMAT_RGB24 instead? + sdlFormat = 0x86161804; // SDL_PIXELFORMAT_RGB888 + break; + default: + Log.v("SDL", "pixel format unknown " + format); + break; + } + SDLActivity.onNativeResize(width, height, sdlFormat); + Log.v("SDL", "Window size:" + width + "x"+height); - SDLActivity.startApp(width, height, config, netgame); - } + SDLActivity.startApp(width, height, config, netgame); + } - // unused - public void onDraw(Canvas canvas) {} + // unused + public void onDraw(Canvas canvas) {} - // Key events - public boolean onKey(View v, int keyCode, KeyEvent event) { - switch(keyCode){ - case KeyEvent.KEYCODE_BACK: - Log.d("SDL", "KEYCODE_BACK"); - SDLActivity.nativeQuit(); + // Key events + public boolean onKey(View v, int keyCode, KeyEvent event) { + switch(keyCode){ + case KeyEvent.KEYCODE_BACK: + Log.d("SDL", "KEYCODE_BACK"); + SDLActivity.nativeQuit(); return true; - case KeyEvent.KEYCODE_VOLUME_DOWN: - case KeyEvent.KEYCODE_VOLUME_UP: - case KeyEvent.KEYCODE_VOLUME_MUTE: - return false; - } - if (event.getAction() == KeyEvent.ACTION_DOWN) { - //Log.v("SDL", "key down: " + keyCode); - SDLActivity.onNativeKeyDown(keyCode); - return true; - } - else if (event.getAction() == KeyEvent.ACTION_UP) { - //Log.v("SDL", "key up: " + keyCode); - SDLActivity.onNativeKeyUp(keyCode); - return true; - } + case KeyEvent.KEYCODE_VOLUME_DOWN: + case KeyEvent.KEYCODE_VOLUME_UP: + case KeyEvent.KEYCODE_VOLUME_MUTE: + return false; + } + if (event.getAction() == KeyEvent.ACTION_DOWN) { + //Log.v("SDL", "key down: " + keyCode); + SDLActivity.onNativeKeyDown(keyCode); + return true; + } + else if (event.getAction() == KeyEvent.ACTION_UP) { + //Log.v("SDL", "key up: " + keyCode); + SDLActivity.onNativeKeyUp(keyCode); + return true; + } - return false; - } + return false; + } - // Touch events - public boolean onTouch(View v, MotionEvent event) { - final int action = event.getAction() & MotionEvent.ACTION_MASK; - final int actionPointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; + // Touch events + public boolean onTouch(View v, MotionEvent event) { + final int action = event.getAction() & MotionEvent.ACTION_MASK; + final int actionPointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; - if (action == MotionEvent.ACTION_MOVE) { - // TODO send motion to every pointer if its position has - // changed since prev event. - for (int i = 0; i < event.getPointerCount(); i++) { - sendNativeTouch(event, action, i); - } - } else { - sendNativeTouch(event, action, actionPointerIndex); - } - return true; - } - - private static void sendNativeTouch(MotionEvent event, int action, int pointerIndex) { - int touchDevId = event.getDeviceId(); - int pointerFingerId = event.getPointerId(pointerIndex); - float x = event.getX(pointerIndex); - float y = event.getY(pointerIndex); - float pressure = event.getPressure(pointerIndex); - SDLActivity.onNativeTouch(touchDevId, pointerFingerId, action, x, y, pressure); - } + if (action == MotionEvent.ACTION_MOVE) { + // TODO send motion to every pointer if its position has + // changed since prev event. + for (int i = 0; i < event.getPointerCount(); i++) { + sendNativeTouch(event, action, i); + } + } else { + sendNativeTouch(event, action, actionPointerIndex); + } + return true; + } + + private static void sendNativeTouch(MotionEvent event, int action, int pointerIndex) { + int touchDevId = event.getDeviceId(); + int pointerFingerId = event.getPointerId(pointerIndex); + float x = event.getX(pointerIndex); + float y = event.getY(pointerIndex); + float pressure = event.getPressure(pointerIndex); + SDLActivity.onNativeTouch(touchDevId, pointerFingerId, action, x, y, pressure); + } - // Sensor events - public void enableSensor(int sensortype, boolean enabled) { - // TODO: This uses getDefaultSensor - what if we have >1 accels? - if (enabled) { - mSensorManager.registerListener(this, - mSensorManager.getDefaultSensor(sensortype), - SensorManager.SENSOR_DELAY_GAME, null); - } else { - mSensorManager.unregisterListener(this, - mSensorManager.getDefaultSensor(sensortype)); - } - } + // Sensor events + public void enableSensor(int sensortype, boolean enabled) { + // TODO: This uses getDefaultSensor - what if we have >1 accels? + if (enabled) { + mSensorManager.registerListener(this, + mSensorManager.getDefaultSensor(sensortype), + SensorManager.SENSOR_DELAY_GAME, null); + } else { + mSensorManager.unregisterListener(this, + mSensorManager.getDefaultSensor(sensortype)); + } + } - public void onAccuracyChanged(Sensor sensor, int accuracy) { - // TODO - } + public void onAccuracyChanged(Sensor sensor, int accuracy) { + // TODO + } - public void onSensorChanged(SensorEvent event) { - if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { - SDLActivity.onNativeAccel(event.values[0] / SensorManager.GRAVITY_EARTH, - event.values[1] / SensorManager.GRAVITY_EARTH, - event.values[2] / SensorManager.GRAVITY_EARTH); - } - } + public void onSensorChanged(SensorEvent event) { + if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { + SDLActivity.onNativeAccel(event.values[0] / SensorManager.GRAVITY_EARTH, + event.values[1] / SensorManager.GRAVITY_EARTH, + event.values[2] / SensorManager.GRAVITY_EARTH); + } + } } diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/SettingsFragment.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/SettingsFragment.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/SettingsFragment.java Tue Nov 10 20:43:13 2015 +0100 @@ -51,177 +51,177 @@ import android.widget.Toast; public class SettingsFragment extends Fragment { - private Spinner styleSpinner, schemeSpinner, weaponsetSpinner, themeSpinner; - private ImageView themeIcon; - - private List styles; - private List schemes; - private List weaponsets; - private List themes; - - private RoomStateManager stateManager; + private Spinner styleSpinner, schemeSpinner, weaponsetSpinner, themeSpinner; + private ImageView themeIcon; + + private List styles; + private List schemes; + private List weaponsets; + private List themes; + + private RoomStateManager stateManager; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.fragment_settings, container, false); + themeIcon = (ImageView)v.findViewById(R.id.imgTheme); + + try { + styles = FrontendDataUtils.getGameStyles(getActivity()); + schemes = Schemes.loadAllSchemes(getActivity()); + weaponsets = Weaponsets.loadAllWeaponsets(getActivity()); + themes = FrontendDataUtils.getThemes(getActivity()); + } catch (IOException e) { + Toast.makeText(getActivity().getApplicationContext(), R.string.error_missing_sdcard_or_files, Toast.LENGTH_LONG).show(); + getActivity().finish(); + return null; + } + + Collections.sort(styles, String.CASE_INSENSITIVE_ORDER); + Collections.sort(schemes, Scheme.NAME_ORDER); + Collections.sort(weaponsets, Weaponset.NAME_ORDER); + Collections.sort(themes, String.CASE_INSENSITIVE_ORDER); + + styleSpinner = prepareSpinner(v, R.id.spinGameplay, styles, styleSelectedListener); + schemeSpinner = prepareSpinner(v, R.id.spinGamescheme, Schemes.toNameList(schemes), schemeSelectedListener); + weaponsetSpinner = prepareSpinner(v, R.id.spinweapons, Weaponsets.toNameList(weaponsets), weaponsetSelectedListener); + themeSpinner = prepareSpinner(v, R.id.spinTheme, themes, themeSelectedListener); + + stateManager.addListener(roomStateChangeListener); - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - View v = inflater.inflate(R.layout.fragment_settings, container, false); - themeIcon = (ImageView)v.findViewById(R.id.imgTheme); - - try { - styles = FrontendDataUtils.getGameStyles(getActivity()); - schemes = Schemes.loadAllSchemes(getActivity()); - weaponsets = Weaponsets.loadAllWeaponsets(getActivity()); - themes = FrontendDataUtils.getThemes(getActivity()); - } catch (IOException e) { - Toast.makeText(getActivity().getApplicationContext(), R.string.error_missing_sdcard_or_files, Toast.LENGTH_LONG).show(); - getActivity().finish(); - return null; - } - - Collections.sort(styles, String.CASE_INSENSITIVE_ORDER); - Collections.sort(schemes, Scheme.NAME_ORDER); - Collections.sort(weaponsets, Weaponset.NAME_ORDER); - Collections.sort(themes, String.CASE_INSENSITIVE_ORDER); - - styleSpinner = prepareSpinner(v, R.id.spinGameplay, styles, styleSelectedListener); - schemeSpinner = prepareSpinner(v, R.id.spinGamescheme, Schemes.toNameList(schemes), schemeSelectedListener); - weaponsetSpinner = prepareSpinner(v, R.id.spinweapons, Weaponsets.toNameList(weaponsets), weaponsetSelectedListener); - themeSpinner = prepareSpinner(v, R.id.spinTheme, themes, themeSelectedListener); - - stateManager.addListener(roomStateChangeListener); + if(stateManager.getGameStyle() != null) { + styleSpinner.setSelection(styles.indexOf(stateManager.getGameStyle()), false); + } + if(stateManager.getScheme() != null) { + schemeSpinner.setSelection(getSchemePosition(schemes, stateManager.getScheme().name), false); + } + if(stateManager.getWeaponset() != null) { + weaponsetSpinner.setSelection(getWeaponsetPosition(weaponsets, stateManager.getWeaponset().name), false); + } + if(stateManager.getMapRecipe() != null) { + themeSpinner.setSelection(themes.indexOf(stateManager.getMapRecipe().theme), false); + } + + setChiefState(stateManager.getChiefStatus()); + + return v; + } + + private static Spinner prepareSpinner(View v, int id, List items, OnItemSelectedListener itemSelectedListener) { + Spinner spinner = (Spinner)v.findViewById(id); + ArrayAdapter adapter = new ArrayAdapter(v.getContext(), R.layout.listview_item, items); + adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + spinner.setAdapter(adapter); + spinner.setOnItemSelectedListener(itemSelectedListener); + return spinner; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + try { + stateManager = ((RoomStateManager.Provider)getActivity()).getRoomStateManager(); + } catch(ClassCastException e) { + throw new RuntimeException("Hosting activity must implement RoomStateManager.Provider.", e); + } + } + + @Override + public void onDestroy() { + super.onDestroy(); + stateManager.removeListener(roomStateChangeListener); + } - if(stateManager.getGameStyle() != null) { - styleSpinner.setSelection(styles.indexOf(stateManager.getGameStyle()), false); - } - if(stateManager.getScheme() != null) { - schemeSpinner.setSelection(getSchemePosition(schemes, stateManager.getScheme().name), false); - } - if(stateManager.getWeaponset() != null) { - weaponsetSpinner.setSelection(getWeaponsetPosition(weaponsets, stateManager.getWeaponset().name), false); - } - if(stateManager.getMapRecipe() != null) { - themeSpinner.setSelection(themes.indexOf(stateManager.getMapRecipe().theme), false); - } - - setChiefState(stateManager.getChiefStatus()); - - return v; - } - - private static Spinner prepareSpinner(View v, int id, List items, OnItemSelectedListener itemSelectedListener) { - Spinner spinner = (Spinner)v.findViewById(id); - ArrayAdapter adapter = new ArrayAdapter(v.getContext(), R.layout.listview_item, items); - adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - spinner.setAdapter(adapter); - spinner.setOnItemSelectedListener(itemSelectedListener); - return spinner; - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - try { - stateManager = ((RoomStateManager.Provider)getActivity()).getRoomStateManager(); - } catch(ClassCastException e) { - throw new RuntimeException("Hosting activity must implement RoomStateManager.Provider.", e); - } - } - - @Override - public void onDestroy() { - super.onDestroy(); - stateManager.removeListener(roomStateChangeListener); - } - - private static int getSchemePosition(List schemes, String scheme) { - for(int i=0; i weaponsets, String weaponset) { - for(int i=0; i adapter, View v, int position, long arg3) { - stateManager.changeGameStyle(styles.get(position)); - } - public void onNothingSelected(AdapterView arg0) {} - }; - - private final OnItemSelectedListener schemeSelectedListener = new OnItemSelectedListener() { - public void onItemSelected(AdapterView adapter, View v, int position, long arg3) { - stateManager.changeScheme(schemes.get(position)); - } - public void onNothingSelected(AdapterView arg0) {} - }; - - private final OnItemSelectedListener weaponsetSelectedListener = new OnItemSelectedListener() { - public void onItemSelected(AdapterView adapter, View v, int position, long arg3) { - stateManager.changeWeaponset(weaponsets.get(position)); - } - public void onNothingSelected(AdapterView arg0) {} - }; - - private final OnItemSelectedListener themeSelectedListener = new OnItemSelectedListener() { - public void onItemSelected(AdapterView adapter, View v, int position, long arg3) { - stateManager.changeMapTheme(themes.get(position)); - String theme = themes.get(position); - try { - File iconFile = FileUtils.getDataPathFile(getActivity(), "Themes", theme, "icon@2X.png"); - Drawable themeIconDrawable = Drawable.createFromPath(iconFile.getAbsolutePath()); - themeIcon.setImageDrawable(themeIconDrawable); - } catch (FileNotFoundException e) { - Log.e("SettingsFragment", "Unable to find preview for theme "+theme, e); - } - }; - public void onNothingSelected(AdapterView arg0) {}; - }; - - private final RoomStateManager.Listener roomStateChangeListener = new RoomStateManager.Listener() { - public void onWeaponsetChanged(Weaponset weaponset) { - weaponsetSpinner.setSelection(getWeaponsetPosition(weaponsets, weaponset.name)); - } - - public void onTeamsChanged(Map teams) {} - - public void onSchemeChanged(Scheme scheme) { - schemeSpinner.setSelection(getSchemePosition(schemes, scheme.name)); - } - - public void onMapChanged(MapRecipe recipe) { - themeSpinner.setSelection(themes.indexOf(recipe.theme)); - } - - public void onGameStyleChanged(String gameStyle) { - styleSpinner.setSelection(styles.indexOf(gameStyle)); - } - - public void onChiefStatusChanged(boolean isChief) { - setChiefState(isChief); - } - }; + private static int getSchemePosition(List schemes, String scheme) { + for(int i=0; i weaponsets, String weaponset) { + for(int i=0; i adapter, View v, int position, long arg3) { + stateManager.changeGameStyle(styles.get(position)); + } + public void onNothingSelected(AdapterView arg0) {} + }; + + private final OnItemSelectedListener schemeSelectedListener = new OnItemSelectedListener() { + public void onItemSelected(AdapterView adapter, View v, int position, long arg3) { + stateManager.changeScheme(schemes.get(position)); + } + public void onNothingSelected(AdapterView arg0) {} + }; + + private final OnItemSelectedListener weaponsetSelectedListener = new OnItemSelectedListener() { + public void onItemSelected(AdapterView adapter, View v, int position, long arg3) { + stateManager.changeWeaponset(weaponsets.get(position)); + } + public void onNothingSelected(AdapterView arg0) {} + }; + + private final OnItemSelectedListener themeSelectedListener = new OnItemSelectedListener() { + public void onItemSelected(AdapterView adapter, View v, int position, long arg3) { + stateManager.changeMapTheme(themes.get(position)); + String theme = themes.get(position); + try { + File iconFile = FileUtils.getDataPathFile(getActivity(), "Themes", theme, "icon@2X.png"); + Drawable themeIconDrawable = Drawable.createFromPath(iconFile.getAbsolutePath()); + themeIcon.setImageDrawable(themeIconDrawable); + } catch (FileNotFoundException e) { + Log.e("SettingsFragment", "Unable to find preview for theme "+theme, e); + } + }; + public void onNothingSelected(AdapterView arg0) {}; + }; + + private final RoomStateManager.Listener roomStateChangeListener = new RoomStateManager.Listener() { + public void onWeaponsetChanged(Weaponset weaponset) { + weaponsetSpinner.setSelection(getWeaponsetPosition(weaponsets, weaponset.name)); + } + + public void onTeamsChanged(Map teams) {} + + public void onSchemeChanged(Scheme scheme) { + schemeSpinner.setSelection(getSchemePosition(schemes, scheme.name)); + } + + public void onMapChanged(MapRecipe recipe) { + themeSpinner.setSelection(themes.indexOf(recipe.theme)); + } + + public void onGameStyleChanged(String gameStyle) { + styleSpinner.setSelection(styles.indexOf(gameStyle)); + } + + public void onChiefStatusChanged(boolean isChief) { + setChiefState(isChief); + } + }; } diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/StartNetgameDialog.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/StartNetgameDialog.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/StartNetgameDialog.java Tue Nov 10 20:43:13 2015 +0100 @@ -36,60 +36,60 @@ import android.widget.TextView.OnEditorActionListener; public class StartNetgameDialog extends DialogFragment { - private static final String PREF_PLAYERNAME = "playerName"; - - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - SharedPreferences prefs = getActivity().getSharedPreferences("settings", Context.MODE_PRIVATE); - final String playerName = prefs.getString(PREF_PLAYERNAME, "Player"); - final EditText editText = new EditText(getActivity()); - final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); - - editText.setText(playerName); - editText.setHint(R.string.start_netgame_dialog_playername_hint); - editText.setId(android.R.id.text1); - editText.setImeOptions(EditorInfo.IME_ACTION_DONE); - editText.setSingleLine(); + private static final String PREF_PLAYERNAME = "playerName"; + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + SharedPreferences prefs = getActivity().getSharedPreferences("settings", Context.MODE_PRIVATE); + final String playerName = prefs.getString(PREF_PLAYERNAME, "Player"); + final EditText editText = new EditText(getActivity()); + final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + + editText.setText(playerName); + editText.setHint(R.string.start_netgame_dialog_playername_hint); + editText.setId(android.R.id.text1); + editText.setImeOptions(EditorInfo.IME_ACTION_DONE); + editText.setSingleLine(); + + builder.setTitle(R.string.start_netgame_dialog_title); + builder.setMessage(R.string.start_netgame_dialog_message); + builder.setView(editText); + builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + editText.setText(playerName); + } + }); - builder.setTitle(R.string.start_netgame_dialog_title); - builder.setMessage(R.string.start_netgame_dialog_message); - builder.setView(editText); - builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - editText.setText(playerName); - } - }); - - editText.setOnEditorActionListener(new OnEditorActionListener() { - public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { - boolean handled = false; - if(actionId == EditorInfo.IME_ACTION_DONE) { - startConnection(v.getText().toString()); - handled = true; - } - return handled; - } - }); - - builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - startConnection(editText.getText().toString()); - } - }); + editText.setOnEditorActionListener(new OnEditorActionListener() { + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + boolean handled = false; + if(actionId == EditorInfo.IME_ACTION_DONE) { + startConnection(v.getText().toString()); + handled = true; + } + return handled; + } + }); + + builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + startConnection(editText.getText().toString()); + } + }); - return builder.create(); - } - - private void startConnection(String username) { - if(username.length() > 0) { - SharedPreferences prefs = getActivity().getSharedPreferences("settings", Context.MODE_PRIVATE); - Editor edit = prefs.edit(); - edit.putString(PREF_PLAYERNAME, username); - edit.commit(); - - Netplay.getAppInstance(getActivity().getApplicationContext()).connectToDefaultServer(username); - getDialog().dismiss(); - ((MainActivity)getActivity()).onNetConnectingStarted(); - } - } + return builder.create(); + } + + private void startConnection(String username) { + if(username.length() > 0) { + SharedPreferences prefs = getActivity().getSharedPreferences("settings", Context.MODE_PRIVATE); + Editor edit = prefs.edit(); + edit.putString(PREF_PLAYERNAME, username); + edit.commit(); + + Netplay.getAppInstance(getActivity().getApplicationContext()).connectToDefaultServer(username); + getDialog().dismiss(); + ((MainActivity)getActivity()).onNetConnectingStarted(); + } + } } diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/TeamAddDialog.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/TeamAddDialog.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/TeamAddDialog.java Tue Nov 10 20:43:13 2015 +0100 @@ -37,76 +37,76 @@ import android.support.v4.app.DialogFragment; public class TeamAddDialog extends DialogFragment { - private static final String STATE_TEAMS_ALREADY_IN_GAME = "teamAlreadyInGame"; - private ArrayList teamsAlreadyInGame; - private List availableTeams; - private Listener listener; - - public static interface Listener { - void onTeamAddDialogSubmitted(Team newTeam); - } - - public TeamAddDialog() { - // Only for reflection-based instantiation by the framework - } - - TeamAddDialog(Collection teamsAlreadyInGame) { - this.teamsAlreadyInGame = new ArrayList(teamsAlreadyInGame); - } - - @Override - public void onAttach(Activity activity) { - super.onAttach(activity); - try { - listener = (Listener) activity; - } catch(ClassCastException e) { - throw new ClassCastException("Activity " + activity + " must implement TeamAddDialog.Listener to use TeamAddDialog."); - } - } - - @Override - public void onDetach() { - super.onDetach(); - listener = null; - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - if(savedInstanceState != null) { - teamsAlreadyInGame = savedInstanceState.getStringArrayList(STATE_TEAMS_ALREADY_IN_GAME); - } - availableTeams = new ArrayList(); - List teams = FrontendDataUtils.getTeams(getActivity()); - for(Team team : teams) { - if(!teamsAlreadyInGame.contains(team.name)) { - availableTeams.add(team); - } - } - Collections.sort(availableTeams, Team.NAME_ORDER); - } - - // TODO use icons for the teams (corresponding to botlevel) - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); - builder.setTitle(R.string.dialog_addteam_title); - builder.setIcon(R.drawable.human); - String[] teamNames = new String[availableTeams.size()]; - for(int i=0; i teamsAlreadyInGame; + private List availableTeams; + private Listener listener; + + public static interface Listener { + void onTeamAddDialogSubmitted(Team newTeam); + } + + public TeamAddDialog() { + // Only for reflection-based instantiation by the framework + } + + TeamAddDialog(Collection teamsAlreadyInGame) { + this.teamsAlreadyInGame = new ArrayList(teamsAlreadyInGame); + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + try { + listener = (Listener) activity; + } catch(ClassCastException e) { + throw new ClassCastException("Activity " + activity + " must implement TeamAddDialog.Listener to use TeamAddDialog."); + } + } + + @Override + public void onDetach() { + super.onDetach(); + listener = null; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if(savedInstanceState != null) { + teamsAlreadyInGame = savedInstanceState.getStringArrayList(STATE_TEAMS_ALREADY_IN_GAME); + } + availableTeams = new ArrayList(); + List teams = FrontendDataUtils.getTeams(getActivity()); + for(Team team : teams) { + if(!teamsAlreadyInGame.contains(team.name)) { + availableTeams.add(team); + } + } + Collections.sort(availableTeams, Team.NAME_ORDER); + } + + // TODO use icons for the teams (corresponding to botlevel) + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + builder.setTitle(R.string.dialog_addteam_title); + builder.setIcon(R.drawable.human); + String[] teamNames = new String[availableTeams.size()]; + for(int i=0; i hogDice = new ArrayList(); - private ArrayList hogHat = new ArrayList(); - private ArrayList hogName = new ArrayList(); - private ImageButton voiceButton; - private ScrollView scroller; - private MediaPlayer mp = null; - private boolean initComplete = false; - - private String existingTeamName = null; + public static final String PARAMETER_EXISTING_TEAMNAME = "existingTeamName"; + private static final String TAG = TeamCreatorActivity.class.getSimpleName(); + + private TextView name; + private Spinner difficulty, grave, flag, voice, fort; + private ImageView imgFort; + private ArrayList hogDice = new ArrayList(); + private ArrayList hogHat = new ArrayList(); + private ArrayList hogName = new ArrayList(); + private ImageButton voiceButton; + private ScrollView scroller; + private MediaPlayer mp = null; + private boolean initComplete = false; + + private String existingTeamName = null; - private final List> flagsData = new ArrayList>(); - private final List> typesData = new ArrayList>(); - private final List> gravesData = new ArrayList>(); - private final List> hatsData = new ArrayList>(); - private final List voicesData = new ArrayList(); - private final List fortsData = new ArrayList(); + private final List> flagsData = new ArrayList>(); + private final List> typesData = new ArrayList>(); + private final List> gravesData = new ArrayList>(); + private final List> hatsData = new ArrayList>(); + private final List voicesData = new ArrayList(); + private final List fortsData = new ArrayList(); + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + initComplete = false; + + // Restore state and read parameters + if(savedInstanceState != null) { + existingTeamName = savedInstanceState.getString(PARAMETER_EXISTING_TEAMNAME); + } else { + existingTeamName = getIntent().getStringExtra(PARAMETER_EXISTING_TEAMNAME); + } - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - initComplete = false; - - // Restore state and read parameters - if(savedInstanceState != null) { - existingTeamName = savedInstanceState.getString(PARAMETER_EXISTING_TEAMNAME); - } else { - existingTeamName = getIntent().getStringExtra(PARAMETER_EXISTING_TEAMNAME); - } - - // Set up view - setContentView(R.layout.team_creation); + // Set up view + setContentView(R.layout.team_creation); - name = (TextView) findViewById(R.id.txtName); - difficulty = (Spinner) findViewById(R.id.spinType); - grave = (Spinner) findViewById(R.id.spinGrave); - flag = (Spinner) findViewById(R.id.spinFlag); - voice = (Spinner) findViewById(R.id.spinVoice); - fort = (Spinner) findViewById(R.id.spinFort); + name = (TextView) findViewById(R.id.txtName); + difficulty = (Spinner) findViewById(R.id.spinType); + grave = (Spinner) findViewById(R.id.spinGrave); + flag = (Spinner) findViewById(R.id.spinFlag); + voice = (Spinner) findViewById(R.id.spinVoice); + fort = (Spinner) findViewById(R.id.spinFort); - imgFort = (ImageView) findViewById(R.id.imgFort); + imgFort = (ImageView) findViewById(R.id.imgFort); + + voiceButton = (ImageButton) findViewById(R.id.btnPlay); + + scroller = (ScrollView) findViewById(R.id.scroller); - voiceButton = (ImageButton) findViewById(R.id.btnPlay); - - scroller = (ScrollView) findViewById(R.id.scroller); - - // Wire view elements - LinearLayout ll = (LinearLayout) findViewById(R.id.HogsContainer); - for (int i = 0; i < ll.getChildCount(); i++) { - RelativeLayout team_creation_entry = (RelativeLayout) ll.getChildAt(i); + // Wire view elements + LinearLayout ll = (LinearLayout) findViewById(R.id.HogsContainer); + for (int i = 0; i < ll.getChildCount(); i++) { + RelativeLayout team_creation_entry = (RelativeLayout) ll.getChildAt(i); - hogHat.add((Spinner) team_creation_entry - .findViewById(R.id.spinTeam1)); - hogDice.add((ImageButton) team_creation_entry - .findViewById(R.id.btnTeam1)); - hogName.add((EditText) team_creation_entry - .findViewById(R.id.txtTeam1)); - } + hogHat.add((Spinner) team_creation_entry + .findViewById(R.id.spinTeam1)); + hogDice.add((ImageButton) team_creation_entry + .findViewById(R.id.btnTeam1)); + hogName.add((EditText) team_creation_entry + .findViewById(R.id.txtTeam1)); + } - grave.setAdapter(createMapSpinnerAdapter(gravesData)); - flag.setAdapter(createMapSpinnerAdapter(flagsData)); - difficulty.setAdapter(createMapSpinnerAdapter(typesData)); - SpinnerAdapter hatAdapter = createMapSpinnerAdapter(hatsData); - for (Spinner spin : hogHat) { - spin.setAdapter(hatAdapter); - } + grave.setAdapter(createMapSpinnerAdapter(gravesData)); + flag.setAdapter(createMapSpinnerAdapter(flagsData)); + difficulty.setAdapter(createMapSpinnerAdapter(typesData)); + SpinnerAdapter hatAdapter = createMapSpinnerAdapter(hatsData); + for (Spinner spin : hogHat) { + spin.setAdapter(hatAdapter); + } - voice.setAdapter(createListSpinnerAdapter(voicesData)); - voiceButton.setOnClickListener(voiceClicker); + voice.setAdapter(createListSpinnerAdapter(voicesData)); + voiceButton.setOnClickListener(voiceClicker); + + fort.setAdapter(createListSpinnerAdapter(fortsData)); + fort.setOnItemSelectedListener(fortSelector); + + new Thread(this).start(); + } + + private SpinnerAdapter createMapSpinnerAdapter(List> data) { + SimpleAdapter sa = new SimpleAdapter(this, data, + R.layout.spinner_textimg_entry, new String[] { "txt", "img" }, + new int[] { R.id.spinner_txt, R.id.spinner_img }); + sa.setDropDownViewResource(R.layout.spinner_textimg_dropdown_entry); + sa.setViewBinder(viewBinder); + return sa; + } + + private SpinnerAdapter createListSpinnerAdapter(List data) { + ArrayAdapter adapter = new ArrayAdapter(this, R.layout.listview_item, data); + adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + return adapter; + } - fort.setAdapter(createListSpinnerAdapter(fortsData)); - fort.setOnItemSelectedListener(fortSelector); + public void run(){ + try { + final List> gravesDataNew = FrontendDataUtils.getGraves(this); + runOnUiThread(new Runnable(){ + public void run() { + gravesData.addAll(gravesDataNew); + ((SimpleAdapter)grave.getAdapter()).notifyDataSetChanged(); + } + }); - new Thread(this).start(); - } + final List> flagsDataNew = FrontendDataUtils.getFlags(this); + runOnUiThread(new Runnable(){ + public void run() { + flagsData.addAll(flagsDataNew); + ((SimpleAdapter)flag.getAdapter()).notifyDataSetChanged(); + } + }); + + final List> typesDataNew = FrontendDataUtils.getTypes(this); + runOnUiThread(new Runnable(){ + public void run() { + typesData.addAll(typesDataNew); + ((SimpleAdapter)difficulty.getAdapter()).notifyDataSetChanged(); + } + }); + + final List> hatsDataNew = FrontendDataUtils.getHats(this); + runOnUiThread(new Runnable(){ + public void run() { + hatsData.addAll(hatsDataNew); + ((SimpleAdapter)hogHat.get(0).getAdapter()).notifyDataSetChanged(); + } + }); - private SpinnerAdapter createMapSpinnerAdapter(List> data) { - SimpleAdapter sa = new SimpleAdapter(this, data, - R.layout.spinner_textimg_entry, new String[] { "txt", "img" }, - new int[] { R.id.spinner_txt, R.id.spinner_img }); - sa.setDropDownViewResource(R.layout.spinner_textimg_dropdown_entry); - sa.setViewBinder(viewBinder); - return sa; - } - - private SpinnerAdapter createListSpinnerAdapter(List data) { - ArrayAdapter adapter = new ArrayAdapter(this, R.layout.listview_item, data); - adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - return adapter; - } - - public void run(){ - try { - final List> gravesDataNew = FrontendDataUtils.getGraves(this); - runOnUiThread(new Runnable(){ - public void run() { - gravesData.addAll(gravesDataNew); - ((SimpleAdapter)grave.getAdapter()).notifyDataSetChanged(); - } - }); - - final List> flagsDataNew = FrontendDataUtils.getFlags(this); - runOnUiThread(new Runnable(){ - public void run() { - flagsData.addAll(flagsDataNew); - ((SimpleAdapter)flag.getAdapter()).notifyDataSetChanged(); - } - }); - - final List> typesDataNew = FrontendDataUtils.getTypes(this); - runOnUiThread(new Runnable(){ - public void run() { - typesData.addAll(typesDataNew); - ((SimpleAdapter)difficulty.getAdapter()).notifyDataSetChanged(); - } - }); - - final List> hatsDataNew = FrontendDataUtils.getHats(this); - runOnUiThread(new Runnable(){ - public void run() { - hatsData.addAll(hatsDataNew); - ((SimpleAdapter)hogHat.get(0).getAdapter()).notifyDataSetChanged(); - } - }); - - final List voicesDataNew = FrontendDataUtils.getVoices(this); - runOnUiThread(new Runnable(){ - public void run() { - voicesData.addAll(voicesDataNew); - ((ArrayAdapter)voice.getAdapter()).notifyDataSetChanged(); - } - }); - - final List fortsDataNew = FrontendDataUtils.getForts(this); - runOnUiThread(new Runnable(){ - public void run() { - fortsData.addAll(fortsDataNew); - ((ArrayAdapter)fort.getAdapter()).notifyDataSetChanged(); - } - }); - - if(existingTeamName!=null) { - final Team loadedTeam = Team.load(Team.getTeamfileByName(getApplicationContext(), existingTeamName)); - if(loadedTeam==null) { - existingTeamName = null; - } else { - runOnUiThread(new Runnable(){ - public void run() { - setTeamValues(loadedTeam); - } - }); - } - } - runOnUiThread(new Runnable(){ - public void run() { - initComplete = true; - } - }); - } catch(FileNotFoundException e) { - this.runOnUiThread(new Runnable(){ - public void run() { - Toast.makeText(getApplicationContext(), R.string.error_missing_sdcard_or_files, Toast.LENGTH_LONG).show(); - finish(); - } - }); - } - } - - public void onDestroy() { - super.onDestroy(); - if (mp != null) { - mp.release(); - mp = null; - } - } + final List voicesDataNew = FrontendDataUtils.getVoices(this); + runOnUiThread(new Runnable(){ + public void run() { + voicesData.addAll(voicesDataNew); + ((ArrayAdapter)voice.getAdapter()).notifyDataSetChanged(); + } + }); + + final List fortsDataNew = FrontendDataUtils.getForts(this); + runOnUiThread(new Runnable(){ + public void run() { + fortsData.addAll(fortsDataNew); + ((ArrayAdapter)fort.getAdapter()).notifyDataSetChanged(); + } + }); - @Override - protected void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - outState.putString(PARAMETER_EXISTING_TEAMNAME, existingTeamName); - } + if(existingTeamName!=null) { + final Team loadedTeam = Team.load(Team.getTeamfileByName(getApplicationContext(), existingTeamName)); + if(loadedTeam==null) { + existingTeamName = null; + } else { + runOnUiThread(new Runnable(){ + public void run() { + setTeamValues(loadedTeam); + } + }); + } + } + runOnUiThread(new Runnable(){ + public void run() { + initComplete = true; + } + }); + } catch(FileNotFoundException e) { + this.runOnUiThread(new Runnable(){ + public void run() { + Toast.makeText(getApplicationContext(), R.string.error_missing_sdcard_or_files, Toast.LENGTH_LONG).show(); + finish(); + } + }); + } + } - public void onBackPressed() { - if(initComplete) { - saveTeam(); - } - setResult(RESULT_OK); - super.onBackPressed(); - } + public void onDestroy() { + super.onDestroy(); + if (mp != null) { + mp.release(); + mp = null; + } + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putString(PARAMETER_EXISTING_TEAMNAME, existingTeamName); + } + + public void onBackPressed() { + if(initComplete) { + saveTeam(); + } + setResult(RESULT_OK); + super.onBackPressed(); + } + + private void saveTeam() { + String teamName = name.getText().toString(); + String teamFlag = (String)((Map) flag.getSelectedItem()).get("txt"); + String teamFort = fort.getSelectedItem().toString(); + String teamGrave = (String)((Map) grave.getSelectedItem()).get("txt"); + String teamVoice = voice.getSelectedItem().toString(); + int levelInt = (Integer)((Map) difficulty.getSelectedItem()).get("level"); - private void saveTeam() { - String teamName = name.getText().toString(); - String teamFlag = (String)((Map) flag.getSelectedItem()).get("txt"); - String teamFort = fort.getSelectedItem().toString(); - String teamGrave = (String)((Map) grave.getSelectedItem()).get("txt"); - String teamVoice = voice.getSelectedItem().toString(); - int levelInt = (Integer)((Map) difficulty.getSelectedItem()).get("level"); - - List hogs = new ArrayList(); - for (int i = 0; i < hogName.size(); i++) { - String name = hogName.get(i).getText().toString(); - String hat = ((Map) hogHat.get(i).getSelectedItem()).get("txt").toString(); - hogs.add(new Hog(name, hat, levelInt)); - } - - Team team = new Team(teamName, teamGrave, teamFlag, teamVoice, teamFort, hogs); - File teamsDir = new File(getFilesDir(), Team.DIRECTORY_TEAMS); - if (!teamsDir.exists()) teamsDir.mkdir(); - - File newFile = Team.getTeamfileByName(this, teamName); - File oldFile = null; - if(existingTeamName != null) { - oldFile = Team.getTeamfileByName(this, existingTeamName); - } - try { - team.save(newFile); - // If the team was renamed, delete the old file. - if(oldFile != null && oldFile.isFile() && !oldFile.equals(newFile)) { - oldFile.delete(); - } - existingTeamName = teamName; - } catch(IOException e) { - Toast.makeText(getApplicationContext(), R.string.error_save_failed, Toast.LENGTH_SHORT).show(); - } - }; + List hogs = new ArrayList(); + for (int i = 0; i < hogName.size(); i++) { + String name = hogName.get(i).getText().toString(); + String hat = ((Map) hogHat.get(i).getSelectedItem()).get("txt").toString(); + hogs.add(new Hog(name, hat, levelInt)); + } + + Team team = new Team(teamName, teamGrave, teamFlag, teamVoice, teamFort, hogs); + File teamsDir = new File(getFilesDir(), Team.DIRECTORY_TEAMS); + if (!teamsDir.exists()) teamsDir.mkdir(); + + File newFile = Team.getTeamfileByName(this, teamName); + File oldFile = null; + if(existingTeamName != null) { + oldFile = Team.getTeamfileByName(this, existingTeamName); + } + try { + team.save(newFile); + // If the team was renamed, delete the old file. + if(oldFile != null && oldFile.isFile() && !oldFile.equals(newFile)) { + oldFile.delete(); + } + existingTeamName = teamName; + } catch(IOException e) { + Toast.makeText(getApplicationContext(), R.string.error_save_failed, Toast.LENGTH_SHORT).show(); + } + }; - private OnItemSelectedListener fortSelector = new OnItemSelectedListener() { - public void onItemSelected(AdapterView arg0, View arg1, - int position, long arg3) { - String fortName = (String) arg0.getAdapter().getItem(position); - try { - File fortImage = FileUtils.getDataPathFile(TeamCreatorActivity.this, "Forts", fortName, "L.png"); - Drawable fortIconDrawable = Drawable.createFromPath(fortImage.getAbsolutePath()); - imgFort.setImageDrawable(fortIconDrawable); - } catch(IOException e) { - Log.e(TAG, "Unable to show fort image", e); - } - scroller.fullScroll(ScrollView.FOCUS_DOWN);// Scroll the scrollview - // to the bottom, work - // around for scrollview - // invalidation (scrolls - // back to top) - } + private OnItemSelectedListener fortSelector = new OnItemSelectedListener() { + public void onItemSelected(AdapterView arg0, View arg1, + int position, long arg3) { + String fortName = (String) arg0.getAdapter().getItem(position); + try { + File fortImage = FileUtils.getDataPathFile(TeamCreatorActivity.this, "Forts", fortName, "L.png"); + Drawable fortIconDrawable = Drawable.createFromPath(fortImage.getAbsolutePath()); + imgFort.setImageDrawable(fortIconDrawable); + } catch(IOException e) { + Log.e(TAG, "Unable to show fort image", e); + } + scroller.fullScroll(ScrollView.FOCUS_DOWN);// Scroll the scrollview + // to the bottom, work + // around for scrollview + // invalidation (scrolls + // back to top) + } - public void onNothingSelected(AdapterView arg0) { - } + public void onNothingSelected(AdapterView arg0) { + } - }; + }; - private OnClickListener voiceClicker = new OnClickListener() { - public void onClick(View v) { - try { - File dir = FileUtils.getDataPathFile(TeamCreatorActivity.this, "Sounds", "voices", (String)voice.getSelectedItem()); - String file = ""; - File[] dirs = dir.listFiles(); - File f = dirs[(int) Math.round(Math.random() * dirs.length)]; - if (f.getName().endsWith(".ogg")) - file = f.getAbsolutePath(); + private OnClickListener voiceClicker = new OnClickListener() { + public void onClick(View v) { + try { + File dir = FileUtils.getDataPathFile(TeamCreatorActivity.this, "Sounds", "voices", (String)voice.getSelectedItem()); + String file = ""; + File[] dirs = dir.listFiles(); + File f = dirs[(int) Math.round(Math.random() * dirs.length)]; + if (f.getName().endsWith(".ogg")) + file = f.getAbsolutePath(); - if (mp == null) - mp = new MediaPlayer(); - else - mp.reset(); - mp.setDataSource(file); - mp.prepare(); - mp.start(); - } catch (IllegalArgumentException e) { - Log.e(TAG, "Unable to play voice sample", e); - } catch (IllegalStateException e) { - Log.e(TAG, "Unable to play voice sample", e); - } catch (IOException e) { - Log.e(TAG, "Unable to play voice sample", e); - } - } - }; + if (mp == null) + mp = new MediaPlayer(); + else + mp.reset(); + mp.setDataSource(file); + mp.prepare(); + mp.start(); + } catch (IllegalArgumentException e) { + Log.e(TAG, "Unable to play voice sample", e); + } catch (IllegalStateException e) { + Log.e(TAG, "Unable to play voice sample", e); + } catch (IOException e) { + Log.e(TAG, "Unable to play voice sample", e); + } + } + }; + + @SuppressWarnings("unchecked") + private void setTeamValues(Team t){ + if (t == null) { + return; + } + + try { + name.setText(t.name); + voice.setSelection(findPosition((ArrayAdapter) voice.getAdapter(), t.voice)); + fort.setSelection(findPosition((ArrayAdapter) fort.getAdapter(), t.fort)); + difficulty.setSelection(findPosition(typesData, "level", Integer.valueOf(t.hogs.get(0).level))); + grave.setSelection(findPosition(gravesData, "txt", t.grave)); + flag.setSelection(findPosition(flagsData, "txt", t.flag)); - @SuppressWarnings("unchecked") - private void setTeamValues(Team t){ - if (t == null) { - return; - } - - try { - name.setText(t.name); - voice.setSelection(findPosition((ArrayAdapter) voice.getAdapter(), t.voice)); - fort.setSelection(findPosition((ArrayAdapter) fort.getAdapter(), t.fort)); - difficulty.setSelection(findPosition(typesData, "level", Integer.valueOf(t.hogs.get(0).level))); - grave.setSelection(findPosition(gravesData, "txt", t.grave)); - flag.setSelection(findPosition(flagsData, "txt", t.flag)); - - for (int i = 0; i < Team.HEDGEHOGS_PER_TEAM; i++) { - hogHat.get(i).setSelection(findPosition(hatsData, "txt", t.hogs.get(i).hat)); - hogName.get(i).setText(t.hogs.get(i).name); - } - } catch(NoSuchElementException e) { - Toast.makeText(getApplicationContext(), R.string.error_team_attribute_not_found, Toast.LENGTH_LONG).show(); - finish(); - } - } + for (int i = 0; i < Team.HEDGEHOGS_PER_TEAM; i++) { + hogHat.get(i).setSelection(findPosition(hatsData, "txt", t.hogs.get(i).hat)); + hogName.get(i).setText(t.hogs.get(i).name); + } + } catch(NoSuchElementException e) { + Toast.makeText(getApplicationContext(), R.string.error_team_attribute_not_found, Toast.LENGTH_LONG).show(); + finish(); + } + } + + int findPosition(ArrayAdapter adapter, String value) throws NoSuchElementException { + int position = adapter.getPosition(value); + if(position<0) { + throw new NoSuchElementException(); + } + return position; + } - int findPosition(ArrayAdapter adapter, String value) throws NoSuchElementException { - int position = adapter.getPosition(value); - if(position<0) { - throw new NoSuchElementException(); - } - return position; - } - - int findPosition(List> data, String key, Object value) throws NoSuchElementException { - int position = 0; - for (Map map : data) { - if (map.get(key).equals(value)) { - return position; - } - position++; - } - throw new NoSuchElementException(); - } + int findPosition(List> data, String key, Object value) throws NoSuchElementException { + int position = 0; + for (Map map : data) { + if (map.get(key).equals(value)) { + return position; + } + position++; + } + throw new NoSuchElementException(); + } + + private SimpleAdapter.ViewBinder viewBinder = new SimpleAdapter.ViewBinder() { - private SimpleAdapter.ViewBinder viewBinder = new SimpleAdapter.ViewBinder() { - - public boolean setViewValue(View view, Object data, - String textRepresentation) { - if (view instanceof ImageView && data instanceof Bitmap) { - ImageView v = (ImageView) view; - v.setImageBitmap((Bitmap) data); - return true; - } else { - return false; - } - } - }; + public boolean setViewValue(View view, Object data, + String textRepresentation) { + if (view instanceof ImageView && data instanceof Bitmap) { + ImageView v = (ImageView) view; + v.setImageBitmap((Bitmap) data); + return true; + } else { + return false; + } + } + }; } diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/TeamListActivity.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/TeamListActivity.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/TeamListActivity.java Tue Nov 10 20:43:13 2015 +0100 @@ -43,87 +43,87 @@ import android.widget.SimpleAdapter; public class TeamListActivity extends ListActivity implements OnItemClickListener { - private List teams; - private ImageButton addButton; + private List teams; + private ImageButton addButton; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_teamlist); + addButton = (ImageButton)findViewById(R.id.btnAdd); + addButton.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + editTeam(null); + } + }); + } + + @Override + public void onResume() { + super.onResume(); + updateList(); + getListView().setOnItemClickListener(this); + registerForContextMenu(getListView()); + } + + public void onItemClick(AdapterView adapterView, View v, int position, long arg3) { + editTeam(teams.get(position).name); + } + + @Override + public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuinfo){ + menu.add(ContextMenu.NONE, 0, ContextMenu.NONE, R.string.edit); + menu.add(ContextMenu.NONE, 1, ContextMenu.NONE, R.string.delete); + } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_teamlist); - addButton = (ImageButton)findViewById(R.id.btnAdd); - addButton.setOnClickListener(new OnClickListener() { - public void onClick(View v) { - editTeam(null); - } - }); - } - - @Override - public void onResume() { - super.onResume(); - updateList(); - getListView().setOnItemClickListener(this); - registerForContextMenu(getListView()); - } - - public void onItemClick(AdapterView adapterView, View v, int position, long arg3) { - editTeam(teams.get(position).name); - } - - @Override - public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuinfo){ - menu.add(ContextMenu.NONE, 0, ContextMenu.NONE, R.string.edit); - menu.add(ContextMenu.NONE, 1, ContextMenu.NONE, R.string.delete); - } - - @Override - public boolean onContextItemSelected(MenuItem item){ - AdapterView.AdapterContextMenuInfo menuInfo = (AdapterContextMenuInfo) item.getMenuInfo(); - int position = menuInfo.position; - Team team = teams.get(position); - switch(item.getItemId()){ - case 0: - editTeam(team.name); - return true; - case 1: - Team.getTeamfileByName(getApplicationContext(), team.name).delete(); - updateList(); - return true; - } - return false; - } - - private void updateList() { - teams = FrontendDataUtils.getTeams(getApplicationContext()); - Collections.sort(teams, Team.NAME_ORDER); - SimpleAdapter adapter = new SimpleAdapter(this, teamsToMaps(teams), R.layout.team_selection_entry_simple, new String[]{"txt", "img"}, new int[]{R.id.txtName, R.id.imgDifficulty}); - setListAdapter(adapter); - } - - private void editTeam(String teamName) { - Intent i = new Intent(this, TeamCreatorActivity.class); - i.putExtra(TeamCreatorActivity.PARAMETER_EXISTING_TEAMNAME, teamName); - startActivity(i); - } + @Override + public boolean onContextItemSelected(MenuItem item){ + AdapterView.AdapterContextMenuInfo menuInfo = (AdapterContextMenuInfo) item.getMenuInfo(); + int position = menuInfo.position; + Team team = teams.get(position); + switch(item.getItemId()){ + case 0: + editTeam(team.name); + return true; + case 1: + Team.getTeamfileByName(getApplicationContext(), team.name).delete(); + updateList(); + return true; + } + return false; + } + + private void updateList() { + teams = FrontendDataUtils.getTeams(getApplicationContext()); + Collections.sort(teams, Team.NAME_ORDER); + SimpleAdapter adapter = new SimpleAdapter(this, teamsToMaps(teams), R.layout.team_selection_entry_simple, new String[]{"txt", "img"}, new int[]{R.id.txtName, R.id.imgDifficulty}); + setListAdapter(adapter); + } - private static final int[] botlevelDrawables = new int[] { - R.drawable.human, R.drawable.bot5, R.drawable.bot4, R.drawable.bot3, R.drawable.bot2, R.drawable.bot1 - }; - - private List> teamsToMaps(List teams) { - List> result = new ArrayList>(); - for(Team t : teams) { - HashMap map = new HashMap(); - map.put("team", t); - map.put("txt", t.name); - int botlevel = t.hogs.get(0).level; - if(botlevel<0 || botlevel>=botlevelDrawables.length) { - map.put("img", R.drawable.bot1); - } else { - map.put("img", botlevelDrawables[botlevel]); - } - result.add(map); - } - return result; - } + private void editTeam(String teamName) { + Intent i = new Intent(this, TeamCreatorActivity.class); + i.putExtra(TeamCreatorActivity.PARAMETER_EXISTING_TEAMNAME, teamName); + startActivity(i); + } + + private static final int[] botlevelDrawables = new int[] { + R.drawable.human, R.drawable.bot5, R.drawable.bot4, R.drawable.bot3, R.drawable.bot2, R.drawable.bot1 + }; + + private List> teamsToMaps(List teams) { + List> result = new ArrayList>(); + for(Team t : teams) { + HashMap map = new HashMap(); + map.put("team", t); + map.put("txt", t.name); + int botlevel = t.hogs.get(0).level; + if(botlevel<0 || botlevel>=botlevelDrawables.length) { + map.put("img", R.drawable.bot1); + } else { + map.put("img", botlevelDrawables[botlevel]); + } + result.add(map); + } + return result; + } } diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/TeamlistAdapter.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/TeamlistAdapter.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/TeamlistAdapter.java Tue Nov 10 20:43:13 2015 +0100 @@ -39,116 +39,116 @@ import android.widget.TextView; public class TeamlistAdapter extends BaseAdapter { - private boolean colorHogcountEnabled = false; - private Listener listener; - private List teams = new ArrayList(); - - public void setColorHogcountEnabled(boolean colorHogcountEnabled) { - this.colorHogcountEnabled = colorHogcountEnabled; - notifyDataSetChanged(); - } - - public void setListener(Listener listener) { - this.listener = listener; - } - - public int getCount() { - return teams.size(); - } - - public TeamInGame getItem(int position) { - return teams.get(position); - } - - public long getItemId(int position) { - return position; - } - - @Override - public boolean hasStableIds() { - return false; - } - - public void updateTeamlist(Collection newTeams) { - teams.clear(); - teams.addAll(newTeams); - Collections.sort(teams, TeamInGame.NAME_ORDER); - notifyDataSetChanged(); - } - - public View getView(int position, View convertView, ViewGroup parent) { - View v = convertView; - if (v == null) { - LayoutInflater vi = LayoutInflater.from(parent.getContext()); - v = vi.inflate(R.layout.listview_team, null); - } + private boolean colorHogcountEnabled = false; + private Listener listener; + private List teams = new ArrayList(); + + public void setColorHogcountEnabled(boolean colorHogcountEnabled) { + this.colorHogcountEnabled = colorHogcountEnabled; + notifyDataSetChanged(); + } + + public void setListener(Listener listener) { + this.listener = listener; + } + + public int getCount() { + return teams.size(); + } + + public TeamInGame getItem(int position) { + return teams.get(position); + } + + public long getItemId(int position) { + return position; + } + + @Override + public boolean hasStableIds() { + return false; + } + + public void updateTeamlist(Collection newTeams) { + teams.clear(); + teams.addAll(newTeams); + Collections.sort(teams, TeamInGame.NAME_ORDER); + notifyDataSetChanged(); + } + + public View getView(int position, View convertView, ViewGroup parent) { + View v = convertView; + if (v == null) { + LayoutInflater vi = LayoutInflater.from(parent.getContext()); + v = vi.inflate(R.layout.listview_team, null); + } + + TeamInGame team = getItem(position); + TextView teamNameView = (TextView) v.findViewById(android.R.id.text1); + ImageButton colorButton = (ImageButton) v.findViewById(R.id.colorButton); + ImageButton hogCountButton = (ImageButton) v.findViewById(R.id.hogCountButton); + + teamNameView.setText(team.team.name); + int teamImage; + if(team.ingameAttribs.remoteDriven) { + teamImage = R.drawable.team_net_by_level; + } else { + teamImage = R.drawable.team_local_by_level; + } - TeamInGame team = getItem(position); - TextView teamNameView = (TextView) v.findViewById(android.R.id.text1); - ImageButton colorButton = (ImageButton) v.findViewById(R.id.colorButton); - ImageButton hogCountButton = (ImageButton) v.findViewById(R.id.hogCountButton); - - teamNameView.setText(team.team.name); - int teamImage; - if(team.ingameAttribs.remoteDriven) { - teamImage = R.drawable.team_net_by_level; - } else { - teamImage = R.drawable.team_local_by_level; - } - - Drawable d = parent.getContext().getResources().getDrawable(teamImage).mutate(); - d.setLevel(team.team.hogs.get(0).level); - teamNameView.setCompoundDrawablesWithIntrinsicBounds(d, null, null, null); - hogCountButton.getDrawable().setLevel(team.ingameAttribs.hogCount); - colorButton.setImageDrawable(new ColorDrawable(TeamIngameAttributes.TEAM_COLORS[team.ingameAttribs.colorIndex])); - - colorButton.setEnabled(colorHogcountEnabled); - hogCountButton.setEnabled(colorHogcountEnabled); - - colorButton.setOnClickListener(new ButtonClickListener(team, Type.COLOR_BUTTON)); - hogCountButton.setOnClickListener(new ButtonClickListener(team, Type.HOGCOUNT_BUTTON)); - - if(team.ingameAttribs.remoteDriven) { - teamNameView.setClickable(false); - } else { - teamNameView.setOnClickListener(new ButtonClickListener(team, Type.TEAM_VIEW)); - } - - return v; - } - - private static enum Type {COLOR_BUTTON, HOGCOUNT_BUTTON, TEAM_VIEW} - private final class ButtonClickListener implements OnClickListener { - private final TeamInGame team; - private final Type type; - - public ButtonClickListener(TeamInGame team, Type type) { - this.team = team; - this.type = type; - } - - public void onClick(View v) { - if(listener != null) { - switch(type) { - case COLOR_BUTTON: - listener.onColorClicked(team); - break; - case HOGCOUNT_BUTTON: - listener.onHogcountClicked(team); - break; - case TEAM_VIEW: - listener.onTeamClicked(team); - break; - default: - throw new IllegalStateException(); - } - } - } - } - - public interface Listener { - void onTeamClicked(TeamInGame team); - void onColorClicked(TeamInGame team); - void onHogcountClicked(TeamInGame team); - } + Drawable d = parent.getContext().getResources().getDrawable(teamImage).mutate(); + d.setLevel(team.team.hogs.get(0).level); + teamNameView.setCompoundDrawablesWithIntrinsicBounds(d, null, null, null); + hogCountButton.getDrawable().setLevel(team.ingameAttribs.hogCount); + colorButton.setImageDrawable(new ColorDrawable(TeamIngameAttributes.TEAM_COLORS[team.ingameAttribs.colorIndex])); + + colorButton.setEnabled(colorHogcountEnabled); + hogCountButton.setEnabled(colorHogcountEnabled); + + colorButton.setOnClickListener(new ButtonClickListener(team, Type.COLOR_BUTTON)); + hogCountButton.setOnClickListener(new ButtonClickListener(team, Type.HOGCOUNT_BUTTON)); + + if(team.ingameAttribs.remoteDriven) { + teamNameView.setClickable(false); + } else { + teamNameView.setOnClickListener(new ButtonClickListener(team, Type.TEAM_VIEW)); + } + + return v; + } + + private static enum Type {COLOR_BUTTON, HOGCOUNT_BUTTON, TEAM_VIEW} + private final class ButtonClickListener implements OnClickListener { + private final TeamInGame team; + private final Type type; + + public ButtonClickListener(TeamInGame team, Type type) { + this.team = team; + this.type = type; + } + + public void onClick(View v) { + if(listener != null) { + switch(type) { + case COLOR_BUTTON: + listener.onColorClicked(team); + break; + case HOGCOUNT_BUTTON: + listener.onHogcountClicked(team); + break; + case TEAM_VIEW: + listener.onTeamClicked(team); + break; + default: + throw new IllegalStateException(); + } + } + } + } + + public interface Listener { + void onTeamClicked(TeamInGame team); + void onColorClicked(TeamInGame team); + void onHogcountClicked(TeamInGame team); + } } \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/TeamlistFragment.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/TeamlistFragment.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/TeamlistFragment.java Tue Nov 10 20:43:13 2015 +0100 @@ -37,83 +37,83 @@ import android.widget.Button; public class TeamlistFragment extends ListFragment implements TeamlistAdapter.Listener { - private TeamlistAdapter adapter; - private Button addTeamButton; - private RoomStateManager stateManager; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - try { - stateManager = ((RoomStateManager.Provider)getActivity()).getRoomStateManager(); - } catch(ClassCastException e) { - throw new RuntimeException("Hosting activity must implement RoomStateManager.Provider.", e); - } - adapter = new TeamlistAdapter(); - adapter.updateTeamlist(stateManager.getTeams().values()); - adapter.setColorHogcountEnabled(stateManager.getChiefStatus()); - adapter.setListener(this); - setListAdapter(adapter); - stateManager.addListener(roomStateChangeListener); - } + private TeamlistAdapter adapter; + private Button addTeamButton; + private RoomStateManager stateManager; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + try { + stateManager = ((RoomStateManager.Provider)getActivity()).getRoomStateManager(); + } catch(ClassCastException e) { + throw new RuntimeException("Hosting activity must implement RoomStateManager.Provider.", e); + } + adapter = new TeamlistAdapter(); + adapter.updateTeamlist(stateManager.getTeams().values()); + adapter.setColorHogcountEnabled(stateManager.getChiefStatus()); + adapter.setListener(this); + setListAdapter(adapter); + stateManager.addListener(roomStateChangeListener); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.fragment_teamlist, container, false); + addTeamButton = (Button)v.findViewById(R.id.addTeamButton); + addTeamButton.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + new TeamAddDialog(getCurrentTeamNames()).show(getFragmentManager(), "team_add_dialog"); + } + }); + + addTeamButton.setEnabled(stateManager.getTeams().size() < Team.maxNumberOfTeams); + + return v; + } - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - View v = inflater.inflate(R.layout.fragment_teamlist, container, false); - addTeamButton = (Button)v.findViewById(R.id.addTeamButton); - addTeamButton.setOnClickListener(new OnClickListener() { - public void onClick(View v) { - new TeamAddDialog(getCurrentTeamNames()).show(getFragmentManager(), "team_add_dialog"); - } - }); - - addTeamButton.setEnabled(stateManager.getTeams().size() < Team.maxNumberOfTeams); - - return v; - } - - @Override - public void onDestroy() { - super.onDestroy(); - adapter.setListener(null); - stateManager.removeListener(roomStateChangeListener); - } + @Override + public void onDestroy() { + super.onDestroy(); + adapter.setListener(null); + stateManager.removeListener(roomStateChangeListener); + } + + private Collection getCurrentTeamNames() { + List names = new ArrayList(); + for(TeamInGame team : stateManager.getTeams().values()) { + names.add(team.team.name); + } + return names; + } + + public void onColorClicked(TeamInGame team) { + stateManager.changeTeamColorIndex(team.team.name, (team.ingameAttribs.colorIndex+1)%TeamIngameAttributes.TEAM_COLORS.length); + } - private Collection getCurrentTeamNames() { - List names = new ArrayList(); - for(TeamInGame team : stateManager.getTeams().values()) { - names.add(team.team.name); - } - return names; - } - - public void onColorClicked(TeamInGame team) { - stateManager.changeTeamColorIndex(team.team.name, (team.ingameAttribs.colorIndex+1)%TeamIngameAttributes.TEAM_COLORS.length); - } - - public void onHogcountClicked(TeamInGame team) { - int newHogCount = team.ingameAttribs.hogCount+1; - if(newHogCount>Team.HEDGEHOGS_PER_TEAM) { - newHogCount = 1; - } - stateManager.changeTeamHogCount(team.team.name, newHogCount); - } - - public void onTeamClicked(TeamInGame team) { - stateManager.requestRemoveTeam(team.team.name); - } - - private final RoomStateManager.Listener roomStateChangeListener = new RoomStateManager.ListenerAdapter() { - @Override - public void onChiefStatusChanged(boolean isChief) { - adapter.setColorHogcountEnabled(isChief); - }; - - @Override - public void onTeamsChanged(Map teams) { - adapter.updateTeamlist(teams.values()); - addTeamButton.setEnabled(teams.size() < Team.maxNumberOfTeams); - }; - }; + public void onHogcountClicked(TeamInGame team) { + int newHogCount = team.ingameAttribs.hogCount+1; + if(newHogCount>Team.HEDGEHOGS_PER_TEAM) { + newHogCount = 1; + } + stateManager.changeTeamHogCount(team.team.name, newHogCount); + } + + public void onTeamClicked(TeamInGame team) { + stateManager.requestRemoveTeam(team.team.name); + } + + private final RoomStateManager.Listener roomStateChangeListener = new RoomStateManager.ListenerAdapter() { + @Override + public void onChiefStatusChanged(boolean isChief) { + adapter.setColorHogcountEnabled(isChief); + }; + + @Override + public void onTeamsChanged(Map teams) { + adapter.updateTeamlist(teams.values()); + addTeamButton.setEnabled(teams.size() < Team.maxNumberOfTeams); + }; + }; } diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/TextImageAdapter.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/TextImageAdapter.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/TextImageAdapter.java Tue Nov 10 20:43:13 2015 +0100 @@ -35,40 +35,40 @@ public class TextImageAdapter extends SimpleAdapter { - private Context context; - private ArrayList> data; - - public TextImageAdapter(Context _context, ArrayList> _data, int resource, String[] from, int[] to) { - super(_context, _data, resource, from, to); - context = _context; - data = _data; - } - - public static TextImageAdapter createAdapter(Context c, String[] txt, String[] img, String[] from, int[] to){ - if(txt.length != img.length) throw new IllegalArgumentException("txt and img parameters not equal"); - - ArrayList> data = new ArrayList>(txt.length); - - for(int i = 0; i < txt.length; i++){ - HashMap map = new HashMap(); - map.put("txt", txt[i]); - map.put("img", BitmapFactory.decodeFile(img[i])); - data.add(map); - } - return new TextImageAdapter(c, data, R.layout.spinner_textimg_entry, from, to); - } + private Context context; + private ArrayList> data; + + public TextImageAdapter(Context _context, ArrayList> _data, int resource, String[] from, int[] to) { + super(_context, _data, resource, from, to); + context = _context; + data = _data; + } + + public static TextImageAdapter createAdapter(Context c, String[] txt, String[] img, String[] from, int[] to){ + if(txt.length != img.length) throw new IllegalArgumentException("txt and img parameters not equal"); + + ArrayList> data = new ArrayList>(txt.length); - public View getView(int position, View convertView, ViewGroup parent){ - if(convertView == null){ - LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - convertView = inflater.inflate(R.layout.spinner_textimg_entry, parent); - } - TextView tv = (TextView) convertView.findViewById(R.id.spinner_txt); - ImageView img = (ImageView) convertView.findViewById(R.id.spinner_img); - - tv.setText((String)data.get(position).get("txt")); - img.setImageBitmap((Bitmap)data.get(position).get("img")); - - return convertView; - } + for(int i = 0; i < txt.length; i++){ + HashMap map = new HashMap(); + map.put("txt", txt[i]); + map.put("img", BitmapFactory.decodeFile(img[i])); + data.add(map); + } + return new TextImageAdapter(c, data, R.layout.spinner_textimg_entry, from, to); + } + + public View getView(int position, View convertView, ViewGroup parent){ + if(convertView == null){ + LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + convertView = inflater.inflate(R.layout.spinner_textimg_entry, parent); + } + TextView tv = (TextView) convertView.findViewById(R.id.spinner_txt); + ImageView img = (ImageView) convertView.findViewById(R.id.spinner_img); + + tv.setText((String)data.get(position).get("txt")); + img.setImageBitmap((Bitmap)data.get(position).get("img")); + + return convertView; + } } diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/UserInput/TouchInterface.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/UserInput/TouchInterface.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/UserInput/TouchInterface.java Tue Nov 10 20:43:13 2015 +0100 @@ -28,63 +28,63 @@ public class TouchInterface{ - public static OnTouchListener getTouchInterface(){ - OnTouchListener toucher; - if(Build.VERSION.SDK_INT < 5){//8 == Build.VERSION_CODES.FROYO - toucher = new TouchInterfaceST(); - }else{ - toucher = new TouchInterfaceMT(); - } + public static OnTouchListener getTouchInterface(){ + OnTouchListener toucher; + if(Build.VERSION.SDK_INT < 5){//8 == Build.VERSION_CODES.FROYO + toucher = new TouchInterfaceST(); + }else{ + toucher = new TouchInterfaceMT(); + } - return toucher; - } + return toucher; + } } /** * Touch interface with multitouch */ class TouchInterfaceMT implements OnTouchListener { - - private boolean firstEvent = true; - - public boolean onTouch(View v, MotionEvent event) { - //dumpEvent(event); - - int action = event.getAction(); - int actionCode = action & MotionEvent.ACTION_MASK; - - for (int i = 0; i < event.getPointerCount(); i++) { - SDLActivity.onNativeTouch(event.getDeviceId(), event.getPointerId(i), actionCode, (int)event.getX(i), (int)event.getY(i), event.getPressure(i)); -// Log.d("Android", String.format("x=%f, y=%f, pntr=%d", event.getX(i), event.getY(i), event.getPointerId(i))); - } - return true; - } + + private boolean firstEvent = true; + + public boolean onTouch(View v, MotionEvent event) { + //dumpEvent(event); + + int action = event.getAction(); + int actionCode = action & MotionEvent.ACTION_MASK; + + for (int i = 0; i < event.getPointerCount(); i++) { + SDLActivity.onNativeTouch(event.getDeviceId(), event.getPointerId(i), actionCode, (int)event.getX(i), (int)event.getY(i), event.getPressure(i)); +// Log.d("Android", String.format("x=%f, y=%f, pntr=%d", event.getX(i), event.getY(i), event.getPointerId(i))); + } + return true; + } - /** Show an event in the LogCat view, for debugging */ - private void dumpEvent(MotionEvent event) { - String names[] = { "DOWN" , "UP" , "MOVE" , "CANCEL" , "OUTSIDE" , - "POINTER_DOWN" , "POINTER_UP" , "7?" , "8?" , "9?" }; - StringBuilder sb = new StringBuilder(); - int action = event.getAction(); - int actionCode = action & MotionEvent.ACTION_MASK; - sb.append("event ACTION_" ).append(names[actionCode]); - if (actionCode == MotionEvent.ACTION_POINTER_DOWN - || actionCode == MotionEvent.ACTION_POINTER_UP) { - sb.append("(pid " ).append( - action >> MotionEvent.ACTION_POINTER_ID_SHIFT); - sb.append(")" ); - } - sb.append("[" ); - for (int i = 0; i < event.getPointerCount(); i++) { - sb.append("#" ).append(i); - sb.append("(pid " ).append(event.getPointerId(i)); - sb.append(")=" ).append((int) event.getX(i)); - sb.append("," ).append((int) event.getY(i)); - if (i + 1 < event.getPointerCount()) - sb.append(";" ); - } - sb.append("]" ); - Log.d("HW_APP_TOUCH", sb.toString()); - } + /** Show an event in the LogCat view, for debugging */ + private void dumpEvent(MotionEvent event) { + String names[] = { "DOWN" , "UP" , "MOVE" , "CANCEL" , "OUTSIDE" , + "POINTER_DOWN" , "POINTER_UP" , "7?" , "8?" , "9?" }; + StringBuilder sb = new StringBuilder(); + int action = event.getAction(); + int actionCode = action & MotionEvent.ACTION_MASK; + sb.append("event ACTION_" ).append(names[actionCode]); + if (actionCode == MotionEvent.ACTION_POINTER_DOWN + || actionCode == MotionEvent.ACTION_POINTER_UP) { + sb.append("(pid " ).append( + action >> MotionEvent.ACTION_POINTER_ID_SHIFT); + sb.append(")" ); + } + sb.append("[" ); + for (int i = 0; i < event.getPointerCount(); i++) { + sb.append("#" ).append(i); + sb.append("(pid " ).append(event.getPointerId(i)); + sb.append(")=" ).append((int) event.getX(i)); + sb.append("," ).append((int) event.getY(i)); + if (i + 1 < event.getPointerCount()) + sb.append(";" ); + } + sb.append("]" ); + Log.d("HW_APP_TOUCH", sb.toString()); + } } @@ -93,9 +93,9 @@ */ class TouchInterfaceST implements OnTouchListener { - public boolean onTouch(View v, MotionEvent event) { - return false; - } + public boolean onTouch(View v, MotionEvent event) { + return false; + } diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/WeaponsetCreatorActivity.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/WeaponsetCreatorActivity.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/WeaponsetCreatorActivity.java Tue Nov 10 20:43:13 2015 +0100 @@ -4,5 +4,5 @@ // TODO public class WeaponsetCreatorActivity extends FragmentActivity { - public static final String PARAMETER_EXISTING_WEAPONSETNAME="existingWeaponsetName"; + public static final String PARAMETER_EXISTING_WEAPONSETNAME="existingWeaponsetName"; } diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/WeaponsetListActivity.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/WeaponsetListActivity.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/WeaponsetListActivity.java Tue Nov 10 20:43:13 2015 +0100 @@ -44,83 +44,83 @@ import android.widget.Toast; public class WeaponsetListActivity extends ListActivity implements OnItemClickListener { - private List userWeaponsets; - private Button addButton; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_weaponsetlist); - addButton = (Button)findViewById(R.id.addButton); - addButton.setOnClickListener(new OnClickListener() { - public void onClick(View v) { - editWeaponset(null); - } - }); - } - - @Override - public void onResume() { - super.onResume(); - updateList(); - getListView().setOnItemClickListener(this); - registerForContextMenu(getListView()); - } - - private List> weaponsetsToMap(List weaponsets) { - List> result = new ArrayList>(); - for(Weaponset weaponset : weaponsets) { - result.add(Collections.singletonMap("txt", weaponset.name)); - } - return result; - } - - public void onItemClick(AdapterView adapterView, View v, int position, long arg3) { - editWeaponset(userWeaponsets.get(position).name); - } - - @Override - public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuinfo){ - menu.add(ContextMenu.NONE, 0, ContextMenu.NONE, R.string.edit); - menu.add(ContextMenu.NONE, 1, ContextMenu.NONE, R.string.delete); - } - - @Override - public boolean onContextItemSelected(MenuItem item){ - AdapterView.AdapterContextMenuInfo menuInfo = (AdapterContextMenuInfo) item.getMenuInfo(); - int position = menuInfo.position; - Weaponset weaponset = userWeaponsets.get(position); - switch(item.getItemId()){ - case 0: - editWeaponset(weaponset.name); - return true; - case 1: - try { - Weaponsets.deleteUserWeaponset(this, weaponset.name); - } catch (IOException e) { - Toast.makeText(this.getApplicationContext(), R.string.error_missing_sdcard_or_files, Toast.LENGTH_SHORT).show(); - } - updateList(); - return true; - } - return false; - } - - private void updateList() { - try { - userWeaponsets = Weaponsets.loadUserWeaponsets(this); - } catch (IOException e) { - Toast.makeText(this, R.string.error_missing_sdcard_or_files, Toast.LENGTH_LONG).show(); - finish(); - } - Collections.sort(userWeaponsets, Weaponset.NAME_ORDER); - ListAdapter adapter = new SimpleAdapter(this, weaponsetsToMap(userWeaponsets), android.R.layout.simple_list_item_1, new String[]{"txt"}, new int[]{android.R.id.text1}); - setListAdapter(adapter); - } - - private void editWeaponset(String weaponsetName) { - Intent i = new Intent(this, WeaponsetCreatorActivity.class); - i.putExtra(WeaponsetCreatorActivity.PARAMETER_EXISTING_WEAPONSETNAME, weaponsetName); - startActivity(i); - } + private List userWeaponsets; + private Button addButton; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_weaponsetlist); + addButton = (Button)findViewById(R.id.addButton); + addButton.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + editWeaponset(null); + } + }); + } + + @Override + public void onResume() { + super.onResume(); + updateList(); + getListView().setOnItemClickListener(this); + registerForContextMenu(getListView()); + } + + private List> weaponsetsToMap(List weaponsets) { + List> result = new ArrayList>(); + for(Weaponset weaponset : weaponsets) { + result.add(Collections.singletonMap("txt", weaponset.name)); + } + return result; + } + + public void onItemClick(AdapterView adapterView, View v, int position, long arg3) { + editWeaponset(userWeaponsets.get(position).name); + } + + @Override + public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuinfo){ + menu.add(ContextMenu.NONE, 0, ContextMenu.NONE, R.string.edit); + menu.add(ContextMenu.NONE, 1, ContextMenu.NONE, R.string.delete); + } + + @Override + public boolean onContextItemSelected(MenuItem item){ + AdapterView.AdapterContextMenuInfo menuInfo = (AdapterContextMenuInfo) item.getMenuInfo(); + int position = menuInfo.position; + Weaponset weaponset = userWeaponsets.get(position); + switch(item.getItemId()){ + case 0: + editWeaponset(weaponset.name); + return true; + case 1: + try { + Weaponsets.deleteUserWeaponset(this, weaponset.name); + } catch (IOException e) { + Toast.makeText(this.getApplicationContext(), R.string.error_missing_sdcard_or_files, Toast.LENGTH_SHORT).show(); + } + updateList(); + return true; + } + return false; + } + + private void updateList() { + try { + userWeaponsets = Weaponsets.loadUserWeaponsets(this); + } catch (IOException e) { + Toast.makeText(this, R.string.error_missing_sdcard_or_files, Toast.LENGTH_LONG).show(); + finish(); + } + Collections.sort(userWeaponsets, Weaponset.NAME_ORDER); + ListAdapter adapter = new SimpleAdapter(this, weaponsetsToMap(userWeaponsets), android.R.layout.simple_list_item_1, new String[]{"txt"}, new int[]{android.R.id.text1}); + setListAdapter(adapter); + } + + private void editWeaponset(String weaponsetName) { + Intent i = new Intent(this, WeaponsetCreatorActivity.class); + i.putExtra(WeaponsetCreatorActivity.PARAMETER_EXISTING_WEAPONSETNAME, weaponsetName); + startActivity(i); + } } diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/frontlib/AndroidTypeMapper.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/frontlib/AndroidTypeMapper.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/frontlib/AndroidTypeMapper.java Tue Nov 10 20:43:13 2015 +0100 @@ -1,63 +1,63 @@ -/* - * Hedgewars for Android. An Android port of Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -package org.hedgewars.hedgeroid.frontlib; - -import com.sun.jna.DefaultTypeMapper; -import com.sun.jna.FromNativeContext; -import com.sun.jna.ToNativeContext; -import com.sun.jna.TypeConverter; -import com.sun.jna.TypeMapper; - -class AndroidTypeMapper extends DefaultTypeMapper { - static final int NATIVE_INT_SIZE = 4; - static final int NATIVE_SIZE_T_SIZE = 4; - static final int NATIVE_BOOL_SIZE = 1; - public static final TypeMapper INSTANCE = new AndroidTypeMapper(); - - protected AndroidTypeMapper() { - addTypeConverter(Boolean.class, new BooleanConverter()); - addTypeConverter(NativeSizeT.class, new SizeTConverter()); - } - - private static final class BooleanConverter implements TypeConverter { - public Class nativeType() { - return Byte.class; - } - public Object fromNative(Object value, FromNativeContext context) { - return ((Byte)value).intValue() != 0 ? Boolean.TRUE : Boolean.FALSE; - } - public Object toNative(Object value, ToNativeContext context) { - return Byte.valueOf((byte)(Boolean.TRUE.equals(value) ? 1 : 0)); - } - } - - private static final class SizeTConverter implements TypeConverter { - public Class nativeType() { - return Integer.class; - } - public Object fromNative(Object value, FromNativeContext context) { - return NativeSizeT.valueOf((Integer)value); - } - public Object toNative(Object value, ToNativeContext context) { - return Integer.valueOf(value==null ? 0 : ((NativeSizeT)value).intValue()); - } - } -} - +/* + * Hedgewars for Android. An Android port of Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package org.hedgewars.hedgeroid.frontlib; + +import com.sun.jna.DefaultTypeMapper; +import com.sun.jna.FromNativeContext; +import com.sun.jna.ToNativeContext; +import com.sun.jna.TypeConverter; +import com.sun.jna.TypeMapper; + +class AndroidTypeMapper extends DefaultTypeMapper { + static final int NATIVE_INT_SIZE = 4; + static final int NATIVE_SIZE_T_SIZE = 4; + static final int NATIVE_BOOL_SIZE = 1; + public static final TypeMapper INSTANCE = new AndroidTypeMapper(); + + protected AndroidTypeMapper() { + addTypeConverter(Boolean.class, new BooleanConverter()); + addTypeConverter(NativeSizeT.class, new SizeTConverter()); + } + + private static final class BooleanConverter implements TypeConverter { + public Class nativeType() { + return Byte.class; + } + public Object fromNative(Object value, FromNativeContext context) { + return ((Byte)value).intValue() != 0 ? Boolean.TRUE : Boolean.FALSE; + } + public Object toNative(Object value, ToNativeContext context) { + return Byte.valueOf((byte)(Boolean.TRUE.equals(value) ? 1 : 0)); + } + } + + private static final class SizeTConverter implements TypeConverter { + public Class nativeType() { + return Integer.class; + } + public Object fromNative(Object value, FromNativeContext context) { + return NativeSizeT.valueOf((Integer)value); + } + public Object toNative(Object value, ToNativeContext context) { + return Integer.valueOf(value==null ? 0 : ((NativeSizeT)value).intValue()); + } + } +} + diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/frontlib/Flib.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/frontlib/Flib.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/frontlib/Flib.java Tue Nov 10 20:43:13 2015 +0100 @@ -27,36 +27,36 @@ import com.sun.jna.Native; public class Flib { - static { - System.loadLibrary("SDL"); - System.loadLibrary("SDL_net"); - System.setProperty("jna.encoding", "UTF8"); // Ugly global setting, but it seems JNA doesn't allow setting this per-library... - } - public static final Frontlib INSTANCE = (Frontlib)Native.loadLibrary("frontlib", Frontlib.class, Collections.singletonMap(Library.OPTION_TYPE_MAPPER, AndroidTypeMapper.INSTANCE)); - - static { - // We'll just do it here and never quit it again... - if(Flib.INSTANCE.flib_init() != 0) { - throw new RuntimeException("Unable to initialize frontlib"); - } - } - - // Hook frontlib logging into Android logging - private static final Frontlib.LogCallback logCb = new Frontlib.LogCallback() { - public void callback(int level, String message) { - if(level >= Frontlib.FLIB_LOGLEVEL_ERROR) { - Log.e("Frontlib", message); - } else if(level == Frontlib.FLIB_LOGLEVEL_WARNING){ - Log.w("Frontlib", message); - } else if(level == Frontlib.FLIB_LOGLEVEL_INFO){ - Log.i("Frontlib", message); - } else if(level <= Frontlib.FLIB_LOGLEVEL_DEBUG){ - Log.d("Frontlib", message); - } - } - }; - static { - INSTANCE.flib_log_setLevel(Frontlib.FLIB_LOGLEVEL_INFO); - INSTANCE.flib_log_setCallback(logCb); - } + static { + System.loadLibrary("SDL"); + System.loadLibrary("SDL_net"); + System.setProperty("jna.encoding", "UTF8"); // Ugly global setting, but it seems JNA doesn't allow setting this per-library... + } + public static final Frontlib INSTANCE = (Frontlib)Native.loadLibrary("frontlib", Frontlib.class, Collections.singletonMap(Library.OPTION_TYPE_MAPPER, AndroidTypeMapper.INSTANCE)); + + static { + // We'll just do it here and never quit it again... + if(Flib.INSTANCE.flib_init() != 0) { + throw new RuntimeException("Unable to initialize frontlib"); + } + } + + // Hook frontlib logging into Android logging + private static final Frontlib.LogCallback logCb = new Frontlib.LogCallback() { + public void callback(int level, String message) { + if(level >= Frontlib.FLIB_LOGLEVEL_ERROR) { + Log.e("Frontlib", message); + } else if(level == Frontlib.FLIB_LOGLEVEL_WARNING){ + Log.w("Frontlib", message); + } else if(level == Frontlib.FLIB_LOGLEVEL_INFO){ + Log.i("Frontlib", message); + } else if(level <= Frontlib.FLIB_LOGLEVEL_DEBUG){ + Log.d("Frontlib", message); + } + } + }; + static { + INSTANCE.flib_log_setLevel(Frontlib.FLIB_LOGLEVEL_INFO); + INSTANCE.flib_log_setCallback(logCb); + } } diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/frontlib/Frontlib.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/frontlib/Frontlib.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/frontlib/Frontlib.java Tue Nov 10 20:43:13 2015 +0100 @@ -1,1263 +1,1263 @@ -/* - * Hedgewars for Android. An Android port of Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - - -package org.hedgewars.hedgeroid.frontlib; -import java.io.UnsupportedEncodingException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.hedgewars.hedgeroid.Datastructures.Hog; -import org.hedgewars.hedgeroid.Datastructures.MapRecipe; -import org.hedgewars.hedgeroid.Datastructures.MetaScheme; -import org.hedgewars.hedgeroid.Datastructures.MetaScheme.Mod; -import org.hedgewars.hedgeroid.Datastructures.MetaScheme.Setting; -import org.hedgewars.hedgeroid.Datastructures.GameConfig; -import org.hedgewars.hedgeroid.Datastructures.Room; -import org.hedgewars.hedgeroid.Datastructures.Scheme; -import org.hedgewars.hedgeroid.Datastructures.Team; -import org.hedgewars.hedgeroid.Datastructures.TeamInGame; -import org.hedgewars.hedgeroid.Datastructures.TeamIngameAttributes; -import org.hedgewars.hedgeroid.Datastructures.Weaponset; - -import com.sun.jna.Callback; -import com.sun.jna.Library; -import com.sun.jna.Memory; -import com.sun.jna.Pointer; -import com.sun.jna.PointerType; -import com.sun.jna.Structure; - -/** - * Here is an introduction to the most important aspects of the JNA code. - * - * This interface permits access to the Hedgewars frontend library (frontlib) - * from Java. Each function directly contained in the Frontlib interface - * represents a mapped C function. The Structure classes (ending in -Struct) are - * mappings of C structs, and the PointerType classes (ending in -Ptr) represent - * pointers to structs. - * - * Quick notes for USING these classes from outside this package: - * - * Usage should be fairly straightforward, but there are a few surprising - * gotchas. First, when you implement callbacks, YOU are responsible for - * ensuring that the callback objects are not garbage-collected while they might - * still be called! So make sure you keep them in member variables or similar, - * because Java will not know if there are still native references to them. - * - * When using Frontlib from outside its package, you only interact with structs - * via the PointerType classes. They allow you to get at the data of the struct - * with a function called deref(), which creates a plain normal Java object - * representing the data (e.g. SchemePtr.deref() will give you a Scheme object). - * - * Remember that you usually have to destroy structs that you receive from the - * library, because they are owned by the native code, not Java. The recommended - * pattern for most cases is to call deref() on the pointer to get a Java object - * (that you can keep as long as you like), and then immediately destroy the - * struct if it needs destroying. To find out whether and how the struct needs - * to be destroyed, see the library's documentation of the function that you got - * the struct from. - * - * To pass new structs to the library, you can use the static createJavaOwned() - * function in each PointerType, which creates a new struct from the Java object - * you provide, and returns a pointer to that struct that you can pass to - * library functions. This new structure's memory is owned and managed by Java - * code, so do not destroy it with frontlib functions! - * - * There is a slight mismatch between the data model for the game setup. The - * frontlib supports setting initial health and weaponset per-hog, because the - * engine allows for that, but currently neither the networking protocol nor the - * PC frontend support this feature, so the Android version does not take - * advantage of it either and treats both as per-game settings. The initial - * health is contained in the game scheme, the weaponset is explicitly part of - * the GameConfig. When converting GameConfig to a native flib_gamesetup, both - * are automatically copied to all hogs in the game, and for the reverse - * conversion the weaponset of the first hog of the first team is used as the - * GameConfig weaponset. This means that GameConfig.weaponset will be null if - * there are no teams in the game. - * - * When starting a network game, you only need to query the GameSetupPtr from - * the netconn and use it to create the gameconn - this is preferable to using - * your own recreation of the game setup, because that way the same piece of - * code is used to determine the game setup on all platforms. - * - * The "context" parameter of the callbacks is never needed here because JNA - * generates function code for each callback object. Don't worry about it, just - * pass null for context and ignore the context parameter in the callbacks. - * - * Finally, the library functions are documented in the actual library, not - * here, so check the docs there to find out what exactly each function does! - * - * Notes about the structure of this class (for the next one who has to touch - * this...): - * - * Java/C interop is quite fiddly and error-prone, so as long as things work, - * try to stick to the established patterns. - * - * Structure types should always be hidden from the outside world, because they - * can be misused too easily. For example, if you get a Structure from the - * library, change a String value in there and pass it back, JNA will re-write - * that string using Java-owned memory without freeing the old native-owned - * string, which causes a memory leak and possibly a double-free or other Bad - * Things (tm). To avoid problems like this, Structure types are only used - * internally, to map existing structures to Java types (without modifying them) - * or to create brand-new, Java-owned structures. Both operations are exposed to - * the outside through the PointerType classes corresponding to the structures - * in question. - * - * Since all of the struct mapping happens in Java, it is never checked against - * the actual struct declarations in the library. That means strange things can - * start happening at runtime if the frontlib structs are modified without - * changing the mappings here to match. This also applies to the function - * signatures: JNA checks whether the functions actually exist when loading the - * library, but it has no way of knowing whether the signatures are correct. If - * the signatures here deviate from those in the frontlib, you might get stack - * corruption. - * - * In order to check at least the function signatures, take a look at the file - * extra/jnacontrol.c in the frontlib sources. You can validate whether the - * function signatures are still correct by copy-pasting them into jnaControl.c - * and compiling it against the frontlib headers. The typedefs and #defines in - * that file will make the compiler see the Java method signatures as C function - * declarations. Since the same functions are already declared in the frontlib - * headers, the compiler will give you errors if the signatures don't match. - */ -public interface Frontlib extends Library { - public static class NetconnPtr extends PointerType { } - public static class MapconnPtr extends PointerType { } - public static class GameconnPtr extends PointerType { } - - public static class MetaschemePtr extends PointerType { - public MetaScheme deref() { - return deref(getPointer()); - } - - public static MetaScheme deref(Pointer p) { - MetaschemeStruct struct = new MetaschemeStruct(p); - struct.read(); - return struct.toMetaScheme(); - } - } - - public static class RoomArrayPtr extends PointerType { - public Room[] getRooms(int count) { - Pointer ptr = getPointer(); - if(ptr == null) { - return new Room[0]; - } - Pointer[] untypedPtrs = ptr.getPointerArray(0, count); - Room[] result = new Room[count]; - for(int i=0; i deref() { - WeaponsetListStruct struct = new WeaponsetListStruct(getPointer()); - struct.read(); - return struct.toWeaponsetList(); - } - - public static WeaponsetListPtr createJavaOwned(List list) { - WeaponsetListPtr result = new WeaponsetListPtr(); - result.javaOwnedInstance = new WeaponsetListStruct(); - result.javaOwnedInstance.fillFrom(list); - result.javaOwnedInstance.autoWrite(); - result.setPointer(result.javaOwnedInstance.getPointer()); - return result; - } - } - - public static class MapRecipePtr extends PointerType { - private MapRecipeStruct javaOwnedInstance; - - public MapRecipe deref() { - MapRecipeStruct struct = new MapRecipeStruct(getPointer()); - struct.read(); - return struct.toMapRecipe(); - } - - public static MapRecipePtr createJavaOwned(MapRecipe recipe) { - MapRecipePtr result = new MapRecipePtr(); - result.javaOwnedInstance = new MapRecipeStruct(); - result.javaOwnedInstance.fillFrom(recipe); - result.javaOwnedInstance.autoWrite(); - result.setPointer(result.javaOwnedInstance.getPointer()); - return result; - } - } - - public static class SchemePtr extends PointerType { - private SchemeStruct javaOwnedInstance; - - public Scheme deref() { - SchemeStruct struct = new SchemeStruct(getPointer()); - struct.read(); - return struct.toScheme(); - } - - public static SchemePtr createJavaOwned(Scheme scheme) { - SchemePtr result = new SchemePtr(); - result.javaOwnedInstance = new SchemeStruct(); - result.javaOwnedInstance.fillFrom(scheme); - result.javaOwnedInstance.autoWrite(); - result.setPointer(result.javaOwnedInstance.getPointer()); - return result; - } - } - - public static class SchemelistPtr extends PointerType { - private SchemelistStruct javaOwnedInstance; - - public List deref() { - SchemelistStruct struct = new SchemelistStruct(getPointer()); - struct.read(); - return struct.toSchemeList(); - } - - public static SchemelistPtr createJavaOwned(List schemes) { - SchemelistPtr result = new SchemelistPtr(); - result.javaOwnedInstance = new SchemelistStruct(); - result.javaOwnedInstance.fillFrom(schemes); - result.javaOwnedInstance.autoWrite(); - result.setPointer(result.javaOwnedInstance.getPointer()); - return result; - } - } - - public static class GameSetupPtr extends PointerType { - private GameSetupStruct javaOwnedInstance; - - public GameConfig deref() { - GameSetupStruct struct = new GameSetupStruct(getPointer()); - struct.read(); - return struct.toGameConfig(); - } - - public static GameSetupPtr createJavaOwned(GameConfig conf) { - GameSetupPtr result = new GameSetupPtr(); - result.javaOwnedInstance = new GameSetupStruct(); - result.javaOwnedInstance.fillFrom(conf); - result.javaOwnedInstance.autoWrite(); - result.setPointer(result.javaOwnedInstance.getPointer()); - return result; - } - } - - public static class ByteArrayPtr extends PointerType { - public byte[] deref(int size) { - return getPointer().getByteArray(0, size); - } - - public static byte[] deref(ByteArrayPtr ptr, int size) { - if(ptr==null && size==0) { - return null; - } else { - return ptr.deref(size); - } - } - - public static ByteArrayPtr createJavaOwned(byte[] buffer) { - if(buffer == null || buffer.length == 0) { - return null; - } - // no need for javaOwnedInstance here because PointerType - // remembers the memory as its Pointer - Pointer ptr = new Memory(buffer.length); - ptr.write(0, buffer, 0, buffer.length); - ByteArrayPtr result = new ByteArrayPtr(); - result.setPointer(ptr); - return result; - } - } - - static class HogStruct extends Structure { - public static class ByVal extends HogStruct implements Structure.ByValue {} - public static class ByRef extends HogStruct implements Structure.ByReference {} - - public HogStruct() { super(); } - public HogStruct(Pointer ptr) { super(ptr); } - - @Override - protected List getFieldOrder() { - return Arrays.asList("name", "hat", "rounds", "kills", "deaths", "suicides", "difficulty", "initialHealth", "weaponset"); - } - - public void fillFrom(Hog hog) { - difficulty = hog.level; - hat = hog.hat; - name = hog.name; - } - - public Hog toHog() { - return new Hog(name, hat, difficulty); - } - - public String name; - public String hat; - - public int rounds; - public int kills; - public int deaths; - public int suicides; - - public int difficulty; - - public int initialHealth; - public WeaponsetStruct.ByRef weaponset; - } - - static class TeamStruct extends Structure { - public static class ByVal extends TeamStruct implements Structure.ByValue {} - public static class ByRef extends TeamStruct implements Structure.ByReference {} - - public TeamStruct() { super(); } - public TeamStruct(Pointer ptr) { super(ptr); } - - @Override - protected List getFieldOrder() { - return Arrays.asList("hogs", "name", "grave", "fort", "voicepack", "flag", "bindings", "bindingCount", "rounds", "wins", "campaignProgress", "colorIndex", "hogsInGame", "remoteDriven", "ownerName"); - } - - public void fillFrom(Team team, TeamIngameAttributes attrs) { - if(team != null) { - name = team.name; - grave = team.grave; - flag = team.flag; - voicepack = team.voice; - fort = team.fort; - if(team.hogs.size() != Team.HEDGEHOGS_PER_TEAM) { - throw new IllegalArgumentException(); - } - for(int i=0; i hogList = new ArrayList(); - for(int i=0; i getFieldOrder() { - return Arrays.asList("loadout", "crateprob", "crateammo", "delay", "name"); - } - - public void fillFrom(Weaponset weaponset) { - fillWeaponInfo(loadout, weaponset.loadout); - fillWeaponInfo(crateprob, weaponset.crateProb); - fillWeaponInfo(crateammo, weaponset.crateAmmo); - fillWeaponInfo(delay, weaponset.delay); - name = weaponset.name; - } - - private static void fillWeaponInfo(byte[] array, String str) { - for(int i=0; i getFieldOrder() { - return Arrays.asList("weaponset"); - } - - public WeaponsetStruct.ByRef weaponset; - } - - static class WeaponsetListStruct extends Structure { - public static class ByVal extends WeaponsetListStruct implements Structure.ByValue {} - public static class ByRef extends WeaponsetListStruct implements Structure.ByReference {} - - public WeaponsetListStruct() { super(); } - public WeaponsetListStruct(Pointer ptr) { super(ptr); } - - @Override - protected List getFieldOrder() { - return Arrays.asList("weaponsetCount", "weaponsets"); - } - - public void fillFrom(List list) { - weaponsetCount = list.size(); - if(weaponsetCount<=0) { - weaponsets = null; - } else { - weaponsets = new WeaponsetPointerByReference(); - Structure[] structs = weaponsets.toArray(weaponsetCount); - - for(int i=0; i toWeaponsetList() { - if(weaponsetCount<=0) { - return new ArrayList(); - } else { - List list = new ArrayList(weaponsetCount); - Structure[] structs = weaponsets.toArray(weaponsetCount); - - for(int i=0; i getFieldOrder() { - return Arrays.asList("inProgress", "name", "playerCount", "teamCount", "owner", "map", "scheme", "weapons"); - } - - public Room toRoomlistRoom() { - return new Room(name, map, scheme, weapons, owner, playerCount, teamCount, inProgress); - } - - public boolean inProgress; - public String name; - public int playerCount; - public int teamCount; - public String owner; - public String map; - public String scheme; - public String weapons; - } - - static class MapRecipeStruct extends Structure { - public static class ByVal extends MapRecipeStruct implements Structure.ByValue {} - public static class ByRef extends MapRecipeStruct implements Structure.ByReference {} - - public MapRecipeStruct() { super(); } - public MapRecipeStruct(Pointer ptr) { super(ptr); } - - @Override - protected List getFieldOrder() { - return Arrays.asList("mapgen", "name", "seed", "theme", "drawData", "drawDataSize", "templateFilter", "mazeSize"); - } - - public void fillFrom(MapRecipe map) { - mapgen = map.mapgen; - name = map.name; - seed = map.seed; - theme = map.theme; - byte[] buf = map.getDrawData(); - drawData = ByteArrayPtr.createJavaOwned(buf); - drawDataSize = NativeSizeT.valueOf(buf==null ? 0 : buf.length); - templateFilter = map.templateFilter; - mazeSize = map.mazeSize; - } - - public MapRecipe toMapRecipe() { - byte[] buf = ByteArrayPtr.deref(drawData, drawDataSize.intValue()); - return new MapRecipe(mapgen, templateFilter, mazeSize, name, seed, theme, buf); - } - - public int mapgen; - public String name; - public String seed; - public String theme; - public ByteArrayPtr drawData; - public NativeSizeT drawDataSize; - public int templateFilter; - public int mazeSize; - } - - static class MetaschemeSettingStruct extends Structure { - public static class ByVal extends MetaschemeSettingStruct implements Structure.ByValue {} - public static class ByRef extends MetaschemeSettingStruct implements Structure.ByReference {} - - public MetaschemeSettingStruct() { super(); } - public MetaschemeSettingStruct(Pointer ptr) { super(ptr); } - - @Override - protected List getFieldOrder() { - return Arrays.asList("name", "engineCommand", "maxMeansInfinity", "times1000", "min", "max", "def"); - } - - public void fillFrom(Setting setting) { - name = setting.name; - engineCommand = setting.engineCommand; - maxMeansInfinity = setting.maxMeansInfinity; - times1000 = setting.times1000; - min = setting.min; - max = setting.max; - def = setting.def; - } - - public MetaScheme.Setting toMetaSchemeSetting() { - return new MetaScheme.Setting(name, engineCommand, maxMeansInfinity, times1000, min, max, def); - } - - public String name; - public String engineCommand; - public boolean maxMeansInfinity; - public boolean times1000; - public int min; - public int max; - public int def; - } - - static class MetaschemeModStruct extends Structure { - public static class ByVal extends MetaschemeModStruct implements Structure.ByValue {} - public static class ByRef extends MetaschemeModStruct implements Structure.ByReference {} - - public MetaschemeModStruct() { super(); } - public MetaschemeModStruct(Pointer ptr) { super(ptr); } - - @Override - protected List getFieldOrder() { - return Arrays.asList("name", "bitmaskIndex"); - } - - public void fillFrom(Mod mod) { - name = mod.name; - bitmaskIndex = mod.bitmaskIndex; - } - - public MetaScheme.Mod toMetaSchemeMod() { - return new MetaScheme.Mod(name, bitmaskIndex); - } - - public String name; - public int bitmaskIndex; - - } - - static class MetaschemeStruct extends Structure { - public static class ByVal extends MetaschemeStruct implements Structure.ByValue {} - public static class ByRef extends MetaschemeStruct implements Structure.ByReference {} - - public MetaschemeStruct() { super(); } - public MetaschemeStruct(Pointer ptr) { super(ptr); } - - @Override - protected List getFieldOrder() { - return Arrays.asList("settingCount", "modCount", "settings", "mods"); - } - - /** - * Only use on native-owned structs! - * Calling this method on a Java-owned struct could cause garbage collection of referenced - * structures. - */ - public MetaScheme toMetaScheme() { - List settingList = new ArrayList(settingCount); - List modList = new ArrayList(modCount); - - Structure[] settingStructs = settings.toArray(settingCount); - Structure[] modStructs = mods.toArray(modCount); - - for(int i=0; i getFieldOrder() { - return Arrays.asList("name", "settings", "mods"); - } - - public void fillFrom(Scheme scheme) { - MetaScheme meta = MetaScheme.INSTANCE; - name = scheme.name; - settings = new Memory(AndroidTypeMapper.NATIVE_INT_SIZE * meta.settings.size()); - for(int i=0; i settingsMap = new HashMap(); - MetaScheme meta = MetaScheme.INSTANCE; - for(int i=0; i modsMap = new HashMap(); - for(int i=0; i getFieldOrder() { - return Arrays.asList("scheme"); - } - - public SchemeStruct.ByRef scheme; - } - - static class SchemelistStruct extends Structure { - public static class ByVal extends SchemelistStruct implements Structure.ByValue {} - public static class ByRef extends SchemelistStruct implements Structure.ByReference {} - - public SchemelistStruct() { super(); } - public SchemelistStruct(Pointer ptr) { super(ptr); } - - @Override - protected List getFieldOrder() { - return Arrays.asList("schemeCount", "schemes"); - } - - public void fillFrom(List schemeList) { - schemeCount = schemeList.size(); - if(schemeCount<=0) { - schemes = null; - } else { - schemes = new SchemePointerByReference(); - Structure[] schemePtrStructs = schemes.toArray(schemeCount); - - for(int i=0; i toSchemeList() { - if(schemeCount<=0) { - return new ArrayList(); - } else { - List schemeList = new ArrayList(schemeCount); - - Structure[] schemePtrStructs = schemes.toArray(schemeCount); - - for(int i=0; i getFieldOrder() { - return Arrays.asList("team"); - } - - public TeamStruct.ByRef team; - } - - static class TeamlistStruct extends Structure { - public static class ByVal extends TeamlistStruct implements Structure.ByValue {} - public static class ByRef extends TeamlistStruct implements Structure.ByReference {} - - public TeamlistStruct() { super(); } - public TeamlistStruct(Pointer ptr) { super(ptr); } - - @Override - protected List getFieldOrder() { - return Arrays.asList("teamCount", "teams"); - } - - public void fillFrom(List teamList, WeaponsetStruct.ByRef weaponset, int initialHealth) { - teamCount = teamList.size(); - if(teamCount <= 0) { - teams = null; - } else { - teams = new TeamPointerByReference(); - Structure[] teamPtrStructs = teams.toArray(teamCount); - - for(int i=0; i toTeamInGameList() { - if(teamCount<=0) { - return new ArrayList(); - } else { - List result = new ArrayList(teamCount); - Structure[] structs = teams.toArray(teamCount); - - for(int i=0; i getFieldOrder() { - return Arrays.asList("script", "gamescheme", "map", "teamlist"); - } - - public void fillFrom(GameConfig conf) { - script = conf.style; - gamescheme = new SchemeStruct.ByRef(); - gamescheme.fillFrom(conf.scheme); - map = new MapRecipeStruct.ByRef(); - map.fillFrom(conf.map); - - /* - * At this point we deviate from the usual copying pattern because the frontlib - * expects per-hog weapons and initial health, but the UI models them as per- - * game, so we extract them from the config here and pass them on to be included - * in each hog. - */ - WeaponsetStruct.ByRef wss = new WeaponsetStruct.ByRef(); - wss.fillFrom(conf.weaponset); - int initialHealth = conf.scheme.getHealth(); - - teamlist = new TeamlistStruct.ByRef(); - teamlist.fillFrom(conf.teams, wss, initialHealth); - } - - public GameConfig toGameConfig() { - Scheme scheme = gamescheme != null ? gamescheme.toScheme() : null; - MapRecipe mapRecipe = map != null ? map.toMapRecipe() : null; - List teams = teamlist != null ? teamlist.toTeamInGameList() : null; - - WeaponsetStruct weaponsetStruct = teamlist != null && teamlist.teamCount>0 ? teamlist.teams.team.hogs[0].weaponset : null; - Weaponset weaponset = weaponsetStruct != null ? weaponsetStruct.toWeaponset() : null; - return new GameConfig(script, scheme, mapRecipe, teams, weaponset); - } - - public String script; - public SchemeStruct.ByRef gamescheme; - public MapRecipeStruct.ByRef map; - public TeamlistStruct.ByRef teamlist; - } - - /* - * Callback interfaces. The context parameter is never needed here and - * should always be ignored. Be sure to keep a reference to each callback - * for as long as they might be called by native code, to avoid premature - * garbage collection. - */ - public static interface VoidCallback extends Callback { - void callback(Pointer context); - } - - public static interface StrCallback extends Callback { - void callback(Pointer context, String arg1); - } - - public static interface IntCallback extends Callback { - void callback(Pointer context, int arg1); - } - - public static interface IntStrCallback extends Callback { - void callback(Pointer context, int arg1, String arg2); - } - - public static interface StrIntCallback extends Callback { - void callback(Pointer context, String arg1, int arg2); - } - - public static interface StrStrCallback extends Callback { - void callback(Pointer context, String arg1, String arg2); - } - - public static interface StrStrBoolCallback extends Callback { - void callback(Pointer context, String arg1, String arg2, boolean arg3); - } - - public static interface RoomCallback extends Callback { - void callback(Pointer context, RoomPtr arg1); - } - - public static interface RoomListCallback extends Callback { - void callback(Pointer context, RoomArrayPtr arg1, int count); - } - - public static interface StrRoomCallback extends Callback { - void callback(Pointer context, String arg1, RoomPtr arg2); - } - - public static interface BoolCallback extends Callback { - void callback(Pointer context, boolean arg1); - } - - public static interface StrBoolCallback extends Callback { - void callback(Pointer context, String arg1, boolean arg2); - } - - public static interface TeamCallback extends Callback { - void callback(Pointer context, TeamPtr arg1); - } - - public static interface BytesCallback extends Callback { - void callback(Pointer context, ByteArrayPtr buffer, NativeSizeT size); - } - - public static interface BytesBoolCallback extends Callback { - void callback(Pointer context, ByteArrayPtr buffer, NativeSizeT size, boolean arg3); - } - - public static interface SchemeCallback extends Callback { - void callback(Pointer context, SchemePtr arg1); - } - - public static interface MapIntCallback extends Callback { - void callback(Pointer context, MapRecipePtr arg1, int arg2); - } - - public static interface WeaponsetCallback extends Callback { - void callback(Pointer context, WeaponsetPtr arg1); - } - - public static interface MapimageCallback extends Callback { - void callback(Pointer context, ByteArrayPtr buffer, int hedgehogCount); - } - - public static interface LogCallback extends Callback { - void callback(int level, String logMessage); - } - - // frontlib.h - int flib_init(); - void flib_quit(); - - // hwconsts.h - int flib_get_teamcolor(int colorIndex); - int flib_get_teamcolor_count(); - int flib_get_hedgehogs_per_team(); - int flib_get_weapons_count(); - MetaschemePtr flib_get_metascheme(); - - // net/netconn.h - static final int NETCONN_STATE_CONNECTING = 0; - static final int NETCONN_STATE_LOBBY = 1; - static final int NETCONN_STATE_ROOM = 2; - static final int NETCONN_STATE_DISCONNECTED = 10; - - static final int NETCONN_DISCONNECT_NORMAL = 0; - static final int NETCONN_DISCONNECT_SERVER_TOO_OLD = 1; - static final int NETCONN_DISCONNECT_AUTH_FAILED = 2; - static final int NETCONN_DISCONNECT_CONNLOST = 3; - static final int NETCONN_DISCONNECT_INTERNAL_ERROR = 100; - - static final int NETCONN_ROOMLEAVE_ABANDONED = 0; - static final int NETCONN_ROOMLEAVE_KICKED = 1; - - static final int NETCONN_MSG_TYPE_PLAYERINFO = 0; - static final int NETCONN_MSG_TYPE_SERVERMESSAGE = 1; - static final int NETCONN_MSG_TYPE_WARNING = 2; - static final int NETCONN_MSG_TYPE_ERROR = 3; - - static final int NETCONN_MAPCHANGE_FULL = 0; - static final int NETCONN_MAPCHANGE_MAP = 1; - static final int NETCONN_MAPCHANGE_MAPGEN = 2; - static final int NETCONN_MAPCHANGE_DRAWNMAP = 3; - static final int NETCONN_MAPCHANGE_MAZE_SIZE = 4; - static final int NETCONN_MAPCHANGE_TEMPLATE = 5; - static final int NETCONN_MAPCHANGE_THEME = 6; - static final int NETCONN_MAPCHANGE_SEED = 7; - - NetconnPtr flib_netconn_create(String playerName, String dataDirPath, String host, int port); - void flib_netconn_destroy(NetconnPtr conn); - - void flib_netconn_tick(NetconnPtr conn); - boolean flib_netconn_is_chief(NetconnPtr conn); - String flib_netconn_get_playername(NetconnPtr conn); - GameSetupPtr flib_netconn_create_gamesetup(NetconnPtr conn); - int flib_netconn_send_quit(NetconnPtr conn, String quitmsg); - int flib_netconn_send_chat(NetconnPtr conn, String chat); - int flib_netconn_send_teamchat(NetconnPtr conn, String msg); - int flib_netconn_send_password(NetconnPtr conn, String passwd); - int flib_netconn_send_nick(NetconnPtr conn, String nick); - int flib_netconn_send_request_roomlist(NetconnPtr conn); - int flib_netconn_send_joinRoom(NetconnPtr conn, String room); - int flib_netconn_send_createRoom(NetconnPtr conn, String room); - int flib_netconn_send_renameRoom(NetconnPtr conn, String roomName); - int flib_netconn_send_leaveRoom(NetconnPtr conn, String msg); - int flib_netconn_send_toggleReady(NetconnPtr conn); - int flib_netconn_send_addTeam(NetconnPtr conn, TeamPtr team); - int flib_netconn_send_removeTeam(NetconnPtr conn, String teamname); - int flib_netconn_send_engineMessage(NetconnPtr conn, ByteArrayPtr message, NativeSizeT size); - int flib_netconn_send_teamHogCount(NetconnPtr conn, String teamname, int hogcount); - int flib_netconn_send_teamColor(NetconnPtr conn, String teamname, int colorIndex); - int flib_netconn_send_weaponset(NetconnPtr conn, WeaponsetPtr weaponset); - int flib_netconn_send_map(NetconnPtr conn, MapRecipePtr map); - int flib_netconn_send_mapName(NetconnPtr conn, String mapName); - int flib_netconn_send_mapGen(NetconnPtr conn, int mapGen); - int flib_netconn_send_mapTemplate(NetconnPtr conn, int templateFilter); - int flib_netconn_send_mapMazeSize(NetconnPtr conn, int mazeSize); - int flib_netconn_send_mapSeed(NetconnPtr conn, String seed); - int flib_netconn_send_mapTheme(NetconnPtr conn, String theme); - int flib_netconn_send_mapDrawdata(NetconnPtr conn, ByteArrayPtr drawData, NativeSizeT size); - int flib_netconn_send_script(NetconnPtr conn, String scriptName); - int flib_netconn_send_scheme(NetconnPtr conn, SchemePtr scheme); - int flib_netconn_send_roundfinished(NetconnPtr conn, boolean withoutError); - int flib_netconn_send_ban(NetconnPtr conn, String playerName); - int flib_netconn_send_kick(NetconnPtr conn, String playerName); - int flib_netconn_send_playerInfo(NetconnPtr conn, String playerName); - int flib_netconn_send_playerFollow(NetconnPtr conn, String playerName); - int flib_netconn_send_startGame(NetconnPtr conn); - int flib_netconn_send_toggleRestrictJoins(NetconnPtr conn); - int flib_netconn_send_toggleRestrictTeams(NetconnPtr conn); - int flib_netconn_send_clearAccountsCache(NetconnPtr conn); - int flib_netconn_send_setServerVar(NetconnPtr conn, String name, String value); - int flib_netconn_send_getServerVars(NetconnPtr conn); - - void flib_netconn_onMessage(NetconnPtr conn, IntStrCallback callback, Pointer context); - void flib_netconn_onClientFlags(NetconnPtr conn, StrStrBoolCallback callback, Pointer context); - void flib_netconn_onChat(NetconnPtr conn, StrStrCallback callback, Pointer context); - void flib_netconn_onConnected(NetconnPtr conn, VoidCallback callback, Pointer context); - void flib_netconn_onDisconnected(NetconnPtr conn, IntStrCallback callback, Pointer context); - void flib_netconn_onRoomlist(NetconnPtr conn, RoomListCallback callback, Pointer context); - void flib_netconn_onRoomAdd(NetconnPtr conn, RoomCallback callback, Pointer context); - void flib_netconn_onRoomDelete(NetconnPtr conn, StrCallback callback, Pointer context); - void flib_netconn_onRoomUpdate(NetconnPtr conn, StrRoomCallback callback, Pointer context); - void flib_netconn_onLobbyJoin(NetconnPtr conn, StrCallback callback, Pointer context); - void flib_netconn_onLobbyLeave(NetconnPtr conn, StrStrCallback callback, Pointer context); - void flib_netconn_onNickTaken(NetconnPtr conn, StrCallback callback, Pointer context); - void flib_netconn_onPasswordRequest(NetconnPtr conn, StrCallback callback, Pointer context); - void flib_netconn_onEnterRoom(NetconnPtr conn, BoolCallback callback, Pointer context); - void flib_netconn_onLeaveRoom(NetconnPtr conn, IntStrCallback callback, Pointer context); - void flib_netconn_onTeamAdd(NetconnPtr conn, TeamCallback callback, Pointer context); - void flib_netconn_onTeamDelete(NetconnPtr conn, StrCallback callback, Pointer context); - void flib_netconn_onRoomJoin(NetconnPtr conn, StrCallback callback, Pointer context); - void flib_netconn_onRoomLeave(NetconnPtr conn, StrStrCallback callback, Pointer context); - void flib_netconn_onRunGame(NetconnPtr conn, VoidCallback callback, Pointer context); - void flib_netconn_onTeamAccepted(NetconnPtr conn, StrCallback callback, Pointer context); - void flib_netconn_onHogCountChanged(NetconnPtr conn, StrIntCallback callback, Pointer context); - void flib_netconn_onTeamColorChanged(NetconnPtr conn, StrIntCallback callback, Pointer context); - void flib_netconn_onEngineMessage(NetconnPtr conn, BytesCallback callback, Pointer context); - void flib_netconn_onSchemeChanged(NetconnPtr conn, SchemeCallback callback, Pointer context); - void flib_netconn_onMapChanged(NetconnPtr conn, MapIntCallback callback, Pointer context); - void flib_netconn_onScriptChanged(NetconnPtr conn, StrCallback callback, Pointer context); - void flib_netconn_onWeaponsetChanged(NetconnPtr conn, WeaponsetCallback callback, Pointer context); - void flib_netconn_onServerVar(NetconnPtr conn, StrStrCallback callback, Pointer context); - - // ipc/gameconn.h - static final int GAME_END_FINISHED = 0; - static final int GAME_END_INTERRUPTED = 1; - static final int GAME_END_HALTED = 2; - static final int GAME_END_ERROR = 3; - - GameconnPtr flib_gameconn_create(String playerName, GameSetupPtr setup, boolean netgame); - GameconnPtr flib_gameconn_create_playdemo(ByteArrayPtr demo, NativeSizeT size); - GameconnPtr flib_gameconn_create_loadgame(String playerName, ByteArrayPtr save, NativeSizeT size); - GameconnPtr flib_gameconn_create_campaign(String playerName, String seed, String script); - - void flib_gameconn_destroy(GameconnPtr conn); - int flib_gameconn_getport(GameconnPtr conn); - void flib_gameconn_tick(GameconnPtr conn); - - int flib_gameconn_send_enginemsg(GameconnPtr conn, ByteArrayPtr data, NativeSizeT len); - int flib_gameconn_send_textmsg(GameconnPtr conn, int msgtype, String msg); - int flib_gameconn_send_chatmsg(GameconnPtr conn, String playername, String msg); - int flib_gameconn_send_quit(GameconnPtr conn); - int flib_gameconn_send_cmd(GameconnPtr conn, String cmdString); - - void flib_gameconn_onConnect(GameconnPtr conn, VoidCallback callback, Pointer context); - void flib_gameconn_onDisconnect(GameconnPtr conn, IntCallback callback, Pointer context); - void flib_gameconn_onErrorMessage(GameconnPtr conn, StrCallback callback, Pointer context); - void flib_gameconn_onChat(GameconnPtr conn, StrBoolCallback callback, Pointer context); - void flib_gameconn_onGameRecorded(GameconnPtr conn, BytesBoolCallback callback, Pointer context); - void flib_gameconn_onEngineMessage(GameconnPtr conn, BytesCallback callback, Pointer context); - - // ipc/mapconn.h - public static final int MAPIMAGE_WIDTH = 256; - public static final int MAPIMAGE_HEIGHT = 128; - public static final int MAPIMAGE_BYTES = (MAPIMAGE_WIDTH/8*MAPIMAGE_HEIGHT); - - MapconnPtr flib_mapconn_create(MapRecipePtr mapdesc); - void flib_mapconn_destroy(MapconnPtr conn); - int flib_mapconn_getport(MapconnPtr conn); - void flib_mapconn_onSuccess(MapconnPtr conn, MapimageCallback callback, Pointer context); - void flib_mapconn_onFailure(MapconnPtr conn, StrCallback callback, Pointer context); - void flib_mapconn_tick(MapconnPtr conn); - - // model/map.h - public static final int MAPGEN_REGULAR = 0; - public static final int MAPGEN_MAZE = 1; - public static final int MAPGEN_DRAWN = 2; - public static final int MAPGEN_NAMED = 3; - - public static final int TEMPLATEFILTER_ALL = 0; - public static final int TEMPLATEFILTER_SMALL = 1; - public static final int TEMPLATEFILTER_MEDIUM = 2; - public static final int TEMPLATEFILTER_LARGE = 3; - public static final int TEMPLATEFILTER_CAVERN = 4; - public static final int TEMPLATEFILTER_WACKY = 5; - - public static final int MAZE_SIZE_SMALL_TUNNELS = 0; - public static final int MAZE_SIZE_MEDIUM_TUNNELS = 1; - public static final int MAZE_SIZE_LARGE_TUNNELS = 2; - public static final int MAZE_SIZE_SMALL_ISLANDS = 3; - public static final int MAZE_SIZE_MEDIUM_ISLANDS = 4; - public static final int MAZE_SIZE_LARGE_ISLANDS = 5; - - // model/schemelist.h - SchemelistPtr flib_schemelist_from_ini(String filename); - int flib_schemelist_to_ini(String filename, SchemelistPtr list); - void flib_schemelist_destroy(SchemelistPtr list); - - // model/team.h - TeamPtr flib_team_from_ini(String filename); - int flib_team_to_ini(String filename, TeamPtr team); - void flib_team_destroy(TeamPtr team); - - // model/weapon.h - WeaponsetListPtr flib_weaponsetlist_from_ini(String filename); - int flib_weaponsetlist_to_ini(String filename, WeaponsetListPtr weaponsets); - void flib_weaponsetlist_destroy(WeaponsetListPtr list); - - // model/gamesetup.h - void flib_gamesetup_destroy(GameSetupPtr gamesetup); - - // util/logging.h - public static final int FLIB_LOGLEVEL_ALL = -100; - public static final int FLIB_LOGLEVEL_DEBUG = -1; - public static final int FLIB_LOGLEVEL_INFO = 0; - public static final int FLIB_LOGLEVEL_WARNING = 1; - public static final int FLIB_LOGLEVEL_ERROR = 2; - public static final int FLIB_LOGLEVEL_NONE = 100; - - void flib_log_setLevel(int level); - void flib_log_setCallback(LogCallback callback); +/* + * Hedgewars for Android. An Android port of Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +package org.hedgewars.hedgeroid.frontlib; +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.hedgewars.hedgeroid.Datastructures.Hog; +import org.hedgewars.hedgeroid.Datastructures.MapRecipe; +import org.hedgewars.hedgeroid.Datastructures.MetaScheme; +import org.hedgewars.hedgeroid.Datastructures.MetaScheme.Mod; +import org.hedgewars.hedgeroid.Datastructures.MetaScheme.Setting; +import org.hedgewars.hedgeroid.Datastructures.GameConfig; +import org.hedgewars.hedgeroid.Datastructures.Room; +import org.hedgewars.hedgeroid.Datastructures.Scheme; +import org.hedgewars.hedgeroid.Datastructures.Team; +import org.hedgewars.hedgeroid.Datastructures.TeamInGame; +import org.hedgewars.hedgeroid.Datastructures.TeamIngameAttributes; +import org.hedgewars.hedgeroid.Datastructures.Weaponset; + +import com.sun.jna.Callback; +import com.sun.jna.Library; +import com.sun.jna.Memory; +import com.sun.jna.Pointer; +import com.sun.jna.PointerType; +import com.sun.jna.Structure; + +/** + * Here is an introduction to the most important aspects of the JNA code. + * + * This interface permits access to the Hedgewars frontend library (frontlib) + * from Java. Each function directly contained in the Frontlib interface + * represents a mapped C function. The Structure classes (ending in -Struct) are + * mappings of C structs, and the PointerType classes (ending in -Ptr) represent + * pointers to structs. + * + * Quick notes for USING these classes from outside this package: + * + * Usage should be fairly straightforward, but there are a few surprising + * gotchas. First, when you implement callbacks, YOU are responsible for + * ensuring that the callback objects are not garbage-collected while they might + * still be called! So make sure you keep them in member variables or similar, + * because Java will not know if there are still native references to them. + * + * When using Frontlib from outside its package, you only interact with structs + * via the PointerType classes. They allow you to get at the data of the struct + * with a function called deref(), which creates a plain normal Java object + * representing the data (e.g. SchemePtr.deref() will give you a Scheme object). + * + * Remember that you usually have to destroy structs that you receive from the + * library, because they are owned by the native code, not Java. The recommended + * pattern for most cases is to call deref() on the pointer to get a Java object + * (that you can keep as long as you like), and then immediately destroy the + * struct if it needs destroying. To find out whether and how the struct needs + * to be destroyed, see the library's documentation of the function that you got + * the struct from. + * + * To pass new structs to the library, you can use the static createJavaOwned() + * function in each PointerType, which creates a new struct from the Java object + * you provide, and returns a pointer to that struct that you can pass to + * library functions. This new structure's memory is owned and managed by Java + * code, so do not destroy it with frontlib functions! + * + * There is a slight mismatch between the data model for the game setup. The + * frontlib supports setting initial health and weaponset per-hog, because the + * engine allows for that, but currently neither the networking protocol nor the + * PC frontend support this feature, so the Android version does not take + * advantage of it either and treats both as per-game settings. The initial + * health is contained in the game scheme, the weaponset is explicitly part of + * the GameConfig. When converting GameConfig to a native flib_gamesetup, both + * are automatically copied to all hogs in the game, and for the reverse + * conversion the weaponset of the first hog of the first team is used as the + * GameConfig weaponset. This means that GameConfig.weaponset will be null if + * there are no teams in the game. + * + * When starting a network game, you only need to query the GameSetupPtr from + * the netconn and use it to create the gameconn - this is preferable to using + * your own recreation of the game setup, because that way the same piece of + * code is used to determine the game setup on all platforms. + * + * The "context" parameter of the callbacks is never needed here because JNA + * generates function code for each callback object. Don't worry about it, just + * pass null for context and ignore the context parameter in the callbacks. + * + * Finally, the library functions are documented in the actual library, not + * here, so check the docs there to find out what exactly each function does! + * + * Notes about the structure of this class (for the next one who has to touch + * this...): + * + * Java/C interop is quite fiddly and error-prone, so as long as things work, + * try to stick to the established patterns. + * + * Structure types should always be hidden from the outside world, because they + * can be misused too easily. For example, if you get a Structure from the + * library, change a String value in there and pass it back, JNA will re-write + * that string using Java-owned memory without freeing the old native-owned + * string, which causes a memory leak and possibly a double-free or other Bad + * Things (tm). To avoid problems like this, Structure types are only used + * internally, to map existing structures to Java types (without modifying them) + * or to create brand-new, Java-owned structures. Both operations are exposed to + * the outside through the PointerType classes corresponding to the structures + * in question. + * + * Since all of the struct mapping happens in Java, it is never checked against + * the actual struct declarations in the library. That means strange things can + * start happening at runtime if the frontlib structs are modified without + * changing the mappings here to match. This also applies to the function + * signatures: JNA checks whether the functions actually exist when loading the + * library, but it has no way of knowing whether the signatures are correct. If + * the signatures here deviate from those in the frontlib, you might get stack + * corruption. + * + * In order to check at least the function signatures, take a look at the file + * extra/jnacontrol.c in the frontlib sources. You can validate whether the + * function signatures are still correct by copy-pasting them into jnaControl.c + * and compiling it against the frontlib headers. The typedefs and #defines in + * that file will make the compiler see the Java method signatures as C function + * declarations. Since the same functions are already declared in the frontlib + * headers, the compiler will give you errors if the signatures don't match. + */ +public interface Frontlib extends Library { + public static class NetconnPtr extends PointerType { } + public static class MapconnPtr extends PointerType { } + public static class GameconnPtr extends PointerType { } + + public static class MetaschemePtr extends PointerType { + public MetaScheme deref() { + return deref(getPointer()); + } + + public static MetaScheme deref(Pointer p) { + MetaschemeStruct struct = new MetaschemeStruct(p); + struct.read(); + return struct.toMetaScheme(); + } + } + + public static class RoomArrayPtr extends PointerType { + public Room[] getRooms(int count) { + Pointer ptr = getPointer(); + if(ptr == null) { + return new Room[0]; + } + Pointer[] untypedPtrs = ptr.getPointerArray(0, count); + Room[] result = new Room[count]; + for(int i=0; i deref() { + WeaponsetListStruct struct = new WeaponsetListStruct(getPointer()); + struct.read(); + return struct.toWeaponsetList(); + } + + public static WeaponsetListPtr createJavaOwned(List list) { + WeaponsetListPtr result = new WeaponsetListPtr(); + result.javaOwnedInstance = new WeaponsetListStruct(); + result.javaOwnedInstance.fillFrom(list); + result.javaOwnedInstance.autoWrite(); + result.setPointer(result.javaOwnedInstance.getPointer()); + return result; + } + } + + public static class MapRecipePtr extends PointerType { + private MapRecipeStruct javaOwnedInstance; + + public MapRecipe deref() { + MapRecipeStruct struct = new MapRecipeStruct(getPointer()); + struct.read(); + return struct.toMapRecipe(); + } + + public static MapRecipePtr createJavaOwned(MapRecipe recipe) { + MapRecipePtr result = new MapRecipePtr(); + result.javaOwnedInstance = new MapRecipeStruct(); + result.javaOwnedInstance.fillFrom(recipe); + result.javaOwnedInstance.autoWrite(); + result.setPointer(result.javaOwnedInstance.getPointer()); + return result; + } + } + + public static class SchemePtr extends PointerType { + private SchemeStruct javaOwnedInstance; + + public Scheme deref() { + SchemeStruct struct = new SchemeStruct(getPointer()); + struct.read(); + return struct.toScheme(); + } + + public static SchemePtr createJavaOwned(Scheme scheme) { + SchemePtr result = new SchemePtr(); + result.javaOwnedInstance = new SchemeStruct(); + result.javaOwnedInstance.fillFrom(scheme); + result.javaOwnedInstance.autoWrite(); + result.setPointer(result.javaOwnedInstance.getPointer()); + return result; + } + } + + public static class SchemelistPtr extends PointerType { + private SchemelistStruct javaOwnedInstance; + + public List deref() { + SchemelistStruct struct = new SchemelistStruct(getPointer()); + struct.read(); + return struct.toSchemeList(); + } + + public static SchemelistPtr createJavaOwned(List schemes) { + SchemelistPtr result = new SchemelistPtr(); + result.javaOwnedInstance = new SchemelistStruct(); + result.javaOwnedInstance.fillFrom(schemes); + result.javaOwnedInstance.autoWrite(); + result.setPointer(result.javaOwnedInstance.getPointer()); + return result; + } + } + + public static class GameSetupPtr extends PointerType { + private GameSetupStruct javaOwnedInstance; + + public GameConfig deref() { + GameSetupStruct struct = new GameSetupStruct(getPointer()); + struct.read(); + return struct.toGameConfig(); + } + + public static GameSetupPtr createJavaOwned(GameConfig conf) { + GameSetupPtr result = new GameSetupPtr(); + result.javaOwnedInstance = new GameSetupStruct(); + result.javaOwnedInstance.fillFrom(conf); + result.javaOwnedInstance.autoWrite(); + result.setPointer(result.javaOwnedInstance.getPointer()); + return result; + } + } + + public static class ByteArrayPtr extends PointerType { + public byte[] deref(int size) { + return getPointer().getByteArray(0, size); + } + + public static byte[] deref(ByteArrayPtr ptr, int size) { + if(ptr==null && size==0) { + return null; + } else { + return ptr.deref(size); + } + } + + public static ByteArrayPtr createJavaOwned(byte[] buffer) { + if(buffer == null || buffer.length == 0) { + return null; + } + // no need for javaOwnedInstance here because PointerType + // remembers the memory as its Pointer + Pointer ptr = new Memory(buffer.length); + ptr.write(0, buffer, 0, buffer.length); + ByteArrayPtr result = new ByteArrayPtr(); + result.setPointer(ptr); + return result; + } + } + + static class HogStruct extends Structure { + public static class ByVal extends HogStruct implements Structure.ByValue {} + public static class ByRef extends HogStruct implements Structure.ByReference {} + + public HogStruct() { super(); } + public HogStruct(Pointer ptr) { super(ptr); } + + @Override + protected List getFieldOrder() { + return Arrays.asList("name", "hat", "rounds", "kills", "deaths", "suicides", "difficulty", "initialHealth", "weaponset"); + } + + public void fillFrom(Hog hog) { + difficulty = hog.level; + hat = hog.hat; + name = hog.name; + } + + public Hog toHog() { + return new Hog(name, hat, difficulty); + } + + public String name; + public String hat; + + public int rounds; + public int kills; + public int deaths; + public int suicides; + + public int difficulty; + + public int initialHealth; + public WeaponsetStruct.ByRef weaponset; + } + + static class TeamStruct extends Structure { + public static class ByVal extends TeamStruct implements Structure.ByValue {} + public static class ByRef extends TeamStruct implements Structure.ByReference {} + + public TeamStruct() { super(); } + public TeamStruct(Pointer ptr) { super(ptr); } + + @Override + protected List getFieldOrder() { + return Arrays.asList("hogs", "name", "grave", "fort", "voicepack", "flag", "bindings", "bindingCount", "rounds", "wins", "campaignProgress", "colorIndex", "hogsInGame", "remoteDriven", "ownerName"); + } + + public void fillFrom(Team team, TeamIngameAttributes attrs) { + if(team != null) { + name = team.name; + grave = team.grave; + flag = team.flag; + voicepack = team.voice; + fort = team.fort; + if(team.hogs.size() != Team.HEDGEHOGS_PER_TEAM) { + throw new IllegalArgumentException(); + } + for(int i=0; i hogList = new ArrayList(); + for(int i=0; i getFieldOrder() { + return Arrays.asList("loadout", "crateprob", "crateammo", "delay", "name"); + } + + public void fillFrom(Weaponset weaponset) { + fillWeaponInfo(loadout, weaponset.loadout); + fillWeaponInfo(crateprob, weaponset.crateProb); + fillWeaponInfo(crateammo, weaponset.crateAmmo); + fillWeaponInfo(delay, weaponset.delay); + name = weaponset.name; + } + + private static void fillWeaponInfo(byte[] array, String str) { + for(int i=0; i getFieldOrder() { + return Arrays.asList("weaponset"); + } + + public WeaponsetStruct.ByRef weaponset; + } + + static class WeaponsetListStruct extends Structure { + public static class ByVal extends WeaponsetListStruct implements Structure.ByValue {} + public static class ByRef extends WeaponsetListStruct implements Structure.ByReference {} + + public WeaponsetListStruct() { super(); } + public WeaponsetListStruct(Pointer ptr) { super(ptr); } + + @Override + protected List getFieldOrder() { + return Arrays.asList("weaponsetCount", "weaponsets"); + } + + public void fillFrom(List list) { + weaponsetCount = list.size(); + if(weaponsetCount<=0) { + weaponsets = null; + } else { + weaponsets = new WeaponsetPointerByReference(); + Structure[] structs = weaponsets.toArray(weaponsetCount); + + for(int i=0; i toWeaponsetList() { + if(weaponsetCount<=0) { + return new ArrayList(); + } else { + List list = new ArrayList(weaponsetCount); + Structure[] structs = weaponsets.toArray(weaponsetCount); + + for(int i=0; i getFieldOrder() { + return Arrays.asList("inProgress", "name", "playerCount", "teamCount", "owner", "map", "scheme", "weapons"); + } + + public Room toRoomlistRoom() { + return new Room(name, map, scheme, weapons, owner, playerCount, teamCount, inProgress); + } + + public boolean inProgress; + public String name; + public int playerCount; + public int teamCount; + public String owner; + public String map; + public String scheme; + public String weapons; + } + + static class MapRecipeStruct extends Structure { + public static class ByVal extends MapRecipeStruct implements Structure.ByValue {} + public static class ByRef extends MapRecipeStruct implements Structure.ByReference {} + + public MapRecipeStruct() { super(); } + public MapRecipeStruct(Pointer ptr) { super(ptr); } + + @Override + protected List getFieldOrder() { + return Arrays.asList("mapgen", "name", "seed", "theme", "drawData", "drawDataSize", "templateFilter", "mazeSize"); + } + + public void fillFrom(MapRecipe map) { + mapgen = map.mapgen; + name = map.name; + seed = map.seed; + theme = map.theme; + byte[] buf = map.getDrawData(); + drawData = ByteArrayPtr.createJavaOwned(buf); + drawDataSize = NativeSizeT.valueOf(buf==null ? 0 : buf.length); + templateFilter = map.templateFilter; + mazeSize = map.mazeSize; + } + + public MapRecipe toMapRecipe() { + byte[] buf = ByteArrayPtr.deref(drawData, drawDataSize.intValue()); + return new MapRecipe(mapgen, templateFilter, mazeSize, name, seed, theme, buf); + } + + public int mapgen; + public String name; + public String seed; + public String theme; + public ByteArrayPtr drawData; + public NativeSizeT drawDataSize; + public int templateFilter; + public int mazeSize; + } + + static class MetaschemeSettingStruct extends Structure { + public static class ByVal extends MetaschemeSettingStruct implements Structure.ByValue {} + public static class ByRef extends MetaschemeSettingStruct implements Structure.ByReference {} + + public MetaschemeSettingStruct() { super(); } + public MetaschemeSettingStruct(Pointer ptr) { super(ptr); } + + @Override + protected List getFieldOrder() { + return Arrays.asList("name", "engineCommand", "maxMeansInfinity", "times1000", "min", "max", "def"); + } + + public void fillFrom(Setting setting) { + name = setting.name; + engineCommand = setting.engineCommand; + maxMeansInfinity = setting.maxMeansInfinity; + times1000 = setting.times1000; + min = setting.min; + max = setting.max; + def = setting.def; + } + + public MetaScheme.Setting toMetaSchemeSetting() { + return new MetaScheme.Setting(name, engineCommand, maxMeansInfinity, times1000, min, max, def); + } + + public String name; + public String engineCommand; + public boolean maxMeansInfinity; + public boolean times1000; + public int min; + public int max; + public int def; + } + + static class MetaschemeModStruct extends Structure { + public static class ByVal extends MetaschemeModStruct implements Structure.ByValue {} + public static class ByRef extends MetaschemeModStruct implements Structure.ByReference {} + + public MetaschemeModStruct() { super(); } + public MetaschemeModStruct(Pointer ptr) { super(ptr); } + + @Override + protected List getFieldOrder() { + return Arrays.asList("name", "bitmaskIndex"); + } + + public void fillFrom(Mod mod) { + name = mod.name; + bitmaskIndex = mod.bitmaskIndex; + } + + public MetaScheme.Mod toMetaSchemeMod() { + return new MetaScheme.Mod(name, bitmaskIndex); + } + + public String name; + public int bitmaskIndex; + + } + + static class MetaschemeStruct extends Structure { + public static class ByVal extends MetaschemeStruct implements Structure.ByValue {} + public static class ByRef extends MetaschemeStruct implements Structure.ByReference {} + + public MetaschemeStruct() { super(); } + public MetaschemeStruct(Pointer ptr) { super(ptr); } + + @Override + protected List getFieldOrder() { + return Arrays.asList("settingCount", "modCount", "settings", "mods"); + } + + /** + * Only use on native-owned structs! + * Calling this method on a Java-owned struct could cause garbage collection of referenced + * structures. + */ + public MetaScheme toMetaScheme() { + List settingList = new ArrayList(settingCount); + List modList = new ArrayList(modCount); + + Structure[] settingStructs = settings.toArray(settingCount); + Structure[] modStructs = mods.toArray(modCount); + + for(int i=0; i getFieldOrder() { + return Arrays.asList("name", "settings", "mods"); + } + + public void fillFrom(Scheme scheme) { + MetaScheme meta = MetaScheme.INSTANCE; + name = scheme.name; + settings = new Memory(AndroidTypeMapper.NATIVE_INT_SIZE * meta.settings.size()); + for(int i=0; i settingsMap = new HashMap(); + MetaScheme meta = MetaScheme.INSTANCE; + for(int i=0; i modsMap = new HashMap(); + for(int i=0; i getFieldOrder() { + return Arrays.asList("scheme"); + } + + public SchemeStruct.ByRef scheme; + } + + static class SchemelistStruct extends Structure { + public static class ByVal extends SchemelistStruct implements Structure.ByValue {} + public static class ByRef extends SchemelistStruct implements Structure.ByReference {} + + public SchemelistStruct() { super(); } + public SchemelistStruct(Pointer ptr) { super(ptr); } + + @Override + protected List getFieldOrder() { + return Arrays.asList("schemeCount", "schemes"); + } + + public void fillFrom(List schemeList) { + schemeCount = schemeList.size(); + if(schemeCount<=0) { + schemes = null; + } else { + schemes = new SchemePointerByReference(); + Structure[] schemePtrStructs = schemes.toArray(schemeCount); + + for(int i=0; i toSchemeList() { + if(schemeCount<=0) { + return new ArrayList(); + } else { + List schemeList = new ArrayList(schemeCount); + + Structure[] schemePtrStructs = schemes.toArray(schemeCount); + + for(int i=0; i getFieldOrder() { + return Arrays.asList("team"); + } + + public TeamStruct.ByRef team; + } + + static class TeamlistStruct extends Structure { + public static class ByVal extends TeamlistStruct implements Structure.ByValue {} + public static class ByRef extends TeamlistStruct implements Structure.ByReference {} + + public TeamlistStruct() { super(); } + public TeamlistStruct(Pointer ptr) { super(ptr); } + + @Override + protected List getFieldOrder() { + return Arrays.asList("teamCount", "teams"); + } + + public void fillFrom(List teamList, WeaponsetStruct.ByRef weaponset, int initialHealth) { + teamCount = teamList.size(); + if(teamCount <= 0) { + teams = null; + } else { + teams = new TeamPointerByReference(); + Structure[] teamPtrStructs = teams.toArray(teamCount); + + for(int i=0; i toTeamInGameList() { + if(teamCount<=0) { + return new ArrayList(); + } else { + List result = new ArrayList(teamCount); + Structure[] structs = teams.toArray(teamCount); + + for(int i=0; i getFieldOrder() { + return Arrays.asList("script", "gamescheme", "map", "teamlist"); + } + + public void fillFrom(GameConfig conf) { + script = conf.style; + gamescheme = new SchemeStruct.ByRef(); + gamescheme.fillFrom(conf.scheme); + map = new MapRecipeStruct.ByRef(); + map.fillFrom(conf.map); + + /* + * At this point we deviate from the usual copying pattern because the frontlib + * expects per-hog weapons and initial health, but the UI models them as per- + * game, so we extract them from the config here and pass them on to be included + * in each hog. + */ + WeaponsetStruct.ByRef wss = new WeaponsetStruct.ByRef(); + wss.fillFrom(conf.weaponset); + int initialHealth = conf.scheme.getHealth(); + + teamlist = new TeamlistStruct.ByRef(); + teamlist.fillFrom(conf.teams, wss, initialHealth); + } + + public GameConfig toGameConfig() { + Scheme scheme = gamescheme != null ? gamescheme.toScheme() : null; + MapRecipe mapRecipe = map != null ? map.toMapRecipe() : null; + List teams = teamlist != null ? teamlist.toTeamInGameList() : null; + + WeaponsetStruct weaponsetStruct = teamlist != null && teamlist.teamCount>0 ? teamlist.teams.team.hogs[0].weaponset : null; + Weaponset weaponset = weaponsetStruct != null ? weaponsetStruct.toWeaponset() : null; + return new GameConfig(script, scheme, mapRecipe, teams, weaponset); + } + + public String script; + public SchemeStruct.ByRef gamescheme; + public MapRecipeStruct.ByRef map; + public TeamlistStruct.ByRef teamlist; + } + + /* + * Callback interfaces. The context parameter is never needed here and + * should always be ignored. Be sure to keep a reference to each callback + * for as long as they might be called by native code, to avoid premature + * garbage collection. + */ + public static interface VoidCallback extends Callback { + void callback(Pointer context); + } + + public static interface StrCallback extends Callback { + void callback(Pointer context, String arg1); + } + + public static interface IntCallback extends Callback { + void callback(Pointer context, int arg1); + } + + public static interface IntStrCallback extends Callback { + void callback(Pointer context, int arg1, String arg2); + } + + public static interface StrIntCallback extends Callback { + void callback(Pointer context, String arg1, int arg2); + } + + public static interface StrStrCallback extends Callback { + void callback(Pointer context, String arg1, String arg2); + } + + public static interface StrStrBoolCallback extends Callback { + void callback(Pointer context, String arg1, String arg2, boolean arg3); + } + + public static interface RoomCallback extends Callback { + void callback(Pointer context, RoomPtr arg1); + } + + public static interface RoomListCallback extends Callback { + void callback(Pointer context, RoomArrayPtr arg1, int count); + } + + public static interface StrRoomCallback extends Callback { + void callback(Pointer context, String arg1, RoomPtr arg2); + } + + public static interface BoolCallback extends Callback { + void callback(Pointer context, boolean arg1); + } + + public static interface StrBoolCallback extends Callback { + void callback(Pointer context, String arg1, boolean arg2); + } + + public static interface TeamCallback extends Callback { + void callback(Pointer context, TeamPtr arg1); + } + + public static interface BytesCallback extends Callback { + void callback(Pointer context, ByteArrayPtr buffer, NativeSizeT size); + } + + public static interface BytesBoolCallback extends Callback { + void callback(Pointer context, ByteArrayPtr buffer, NativeSizeT size, boolean arg3); + } + + public static interface SchemeCallback extends Callback { + void callback(Pointer context, SchemePtr arg1); + } + + public static interface MapIntCallback extends Callback { + void callback(Pointer context, MapRecipePtr arg1, int arg2); + } + + public static interface WeaponsetCallback extends Callback { + void callback(Pointer context, WeaponsetPtr arg1); + } + + public static interface MapimageCallback extends Callback { + void callback(Pointer context, ByteArrayPtr buffer, int hedgehogCount); + } + + public static interface LogCallback extends Callback { + void callback(int level, String logMessage); + } + + // frontlib.h + int flib_init(); + void flib_quit(); + + // hwconsts.h + int flib_get_teamcolor(int colorIndex); + int flib_get_teamcolor_count(); + int flib_get_hedgehogs_per_team(); + int flib_get_weapons_count(); + MetaschemePtr flib_get_metascheme(); + + // net/netconn.h + static final int NETCONN_STATE_CONNECTING = 0; + static final int NETCONN_STATE_LOBBY = 1; + static final int NETCONN_STATE_ROOM = 2; + static final int NETCONN_STATE_DISCONNECTED = 10; + + static final int NETCONN_DISCONNECT_NORMAL = 0; + static final int NETCONN_DISCONNECT_SERVER_TOO_OLD = 1; + static final int NETCONN_DISCONNECT_AUTH_FAILED = 2; + static final int NETCONN_DISCONNECT_CONNLOST = 3; + static final int NETCONN_DISCONNECT_INTERNAL_ERROR = 100; + + static final int NETCONN_ROOMLEAVE_ABANDONED = 0; + static final int NETCONN_ROOMLEAVE_KICKED = 1; + + static final int NETCONN_MSG_TYPE_PLAYERINFO = 0; + static final int NETCONN_MSG_TYPE_SERVERMESSAGE = 1; + static final int NETCONN_MSG_TYPE_WARNING = 2; + static final int NETCONN_MSG_TYPE_ERROR = 3; + + static final int NETCONN_MAPCHANGE_FULL = 0; + static final int NETCONN_MAPCHANGE_MAP = 1; + static final int NETCONN_MAPCHANGE_MAPGEN = 2; + static final int NETCONN_MAPCHANGE_DRAWNMAP = 3; + static final int NETCONN_MAPCHANGE_MAZE_SIZE = 4; + static final int NETCONN_MAPCHANGE_TEMPLATE = 5; + static final int NETCONN_MAPCHANGE_THEME = 6; + static final int NETCONN_MAPCHANGE_SEED = 7; + + NetconnPtr flib_netconn_create(String playerName, String dataDirPath, String host, int port); + void flib_netconn_destroy(NetconnPtr conn); + + void flib_netconn_tick(NetconnPtr conn); + boolean flib_netconn_is_chief(NetconnPtr conn); + String flib_netconn_get_playername(NetconnPtr conn); + GameSetupPtr flib_netconn_create_gamesetup(NetconnPtr conn); + int flib_netconn_send_quit(NetconnPtr conn, String quitmsg); + int flib_netconn_send_chat(NetconnPtr conn, String chat); + int flib_netconn_send_teamchat(NetconnPtr conn, String msg); + int flib_netconn_send_password(NetconnPtr conn, String passwd); + int flib_netconn_send_nick(NetconnPtr conn, String nick); + int flib_netconn_send_request_roomlist(NetconnPtr conn); + int flib_netconn_send_joinRoom(NetconnPtr conn, String room); + int flib_netconn_send_createRoom(NetconnPtr conn, String room); + int flib_netconn_send_renameRoom(NetconnPtr conn, String roomName); + int flib_netconn_send_leaveRoom(NetconnPtr conn, String msg); + int flib_netconn_send_toggleReady(NetconnPtr conn); + int flib_netconn_send_addTeam(NetconnPtr conn, TeamPtr team); + int flib_netconn_send_removeTeam(NetconnPtr conn, String teamname); + int flib_netconn_send_engineMessage(NetconnPtr conn, ByteArrayPtr message, NativeSizeT size); + int flib_netconn_send_teamHogCount(NetconnPtr conn, String teamname, int hogcount); + int flib_netconn_send_teamColor(NetconnPtr conn, String teamname, int colorIndex); + int flib_netconn_send_weaponset(NetconnPtr conn, WeaponsetPtr weaponset); + int flib_netconn_send_map(NetconnPtr conn, MapRecipePtr map); + int flib_netconn_send_mapName(NetconnPtr conn, String mapName); + int flib_netconn_send_mapGen(NetconnPtr conn, int mapGen); + int flib_netconn_send_mapTemplate(NetconnPtr conn, int templateFilter); + int flib_netconn_send_mapMazeSize(NetconnPtr conn, int mazeSize); + int flib_netconn_send_mapSeed(NetconnPtr conn, String seed); + int flib_netconn_send_mapTheme(NetconnPtr conn, String theme); + int flib_netconn_send_mapDrawdata(NetconnPtr conn, ByteArrayPtr drawData, NativeSizeT size); + int flib_netconn_send_script(NetconnPtr conn, String scriptName); + int flib_netconn_send_scheme(NetconnPtr conn, SchemePtr scheme); + int flib_netconn_send_roundfinished(NetconnPtr conn, boolean withoutError); + int flib_netconn_send_ban(NetconnPtr conn, String playerName); + int flib_netconn_send_kick(NetconnPtr conn, String playerName); + int flib_netconn_send_playerInfo(NetconnPtr conn, String playerName); + int flib_netconn_send_playerFollow(NetconnPtr conn, String playerName); + int flib_netconn_send_startGame(NetconnPtr conn); + int flib_netconn_send_toggleRestrictJoins(NetconnPtr conn); + int flib_netconn_send_toggleRestrictTeams(NetconnPtr conn); + int flib_netconn_send_clearAccountsCache(NetconnPtr conn); + int flib_netconn_send_setServerVar(NetconnPtr conn, String name, String value); + int flib_netconn_send_getServerVars(NetconnPtr conn); + + void flib_netconn_onMessage(NetconnPtr conn, IntStrCallback callback, Pointer context); + void flib_netconn_onClientFlags(NetconnPtr conn, StrStrBoolCallback callback, Pointer context); + void flib_netconn_onChat(NetconnPtr conn, StrStrCallback callback, Pointer context); + void flib_netconn_onConnected(NetconnPtr conn, VoidCallback callback, Pointer context); + void flib_netconn_onDisconnected(NetconnPtr conn, IntStrCallback callback, Pointer context); + void flib_netconn_onRoomlist(NetconnPtr conn, RoomListCallback callback, Pointer context); + void flib_netconn_onRoomAdd(NetconnPtr conn, RoomCallback callback, Pointer context); + void flib_netconn_onRoomDelete(NetconnPtr conn, StrCallback callback, Pointer context); + void flib_netconn_onRoomUpdate(NetconnPtr conn, StrRoomCallback callback, Pointer context); + void flib_netconn_onLobbyJoin(NetconnPtr conn, StrCallback callback, Pointer context); + void flib_netconn_onLobbyLeave(NetconnPtr conn, StrStrCallback callback, Pointer context); + void flib_netconn_onNickTaken(NetconnPtr conn, StrCallback callback, Pointer context); + void flib_netconn_onPasswordRequest(NetconnPtr conn, StrCallback callback, Pointer context); + void flib_netconn_onEnterRoom(NetconnPtr conn, BoolCallback callback, Pointer context); + void flib_netconn_onLeaveRoom(NetconnPtr conn, IntStrCallback callback, Pointer context); + void flib_netconn_onTeamAdd(NetconnPtr conn, TeamCallback callback, Pointer context); + void flib_netconn_onTeamDelete(NetconnPtr conn, StrCallback callback, Pointer context); + void flib_netconn_onRoomJoin(NetconnPtr conn, StrCallback callback, Pointer context); + void flib_netconn_onRoomLeave(NetconnPtr conn, StrStrCallback callback, Pointer context); + void flib_netconn_onRunGame(NetconnPtr conn, VoidCallback callback, Pointer context); + void flib_netconn_onTeamAccepted(NetconnPtr conn, StrCallback callback, Pointer context); + void flib_netconn_onHogCountChanged(NetconnPtr conn, StrIntCallback callback, Pointer context); + void flib_netconn_onTeamColorChanged(NetconnPtr conn, StrIntCallback callback, Pointer context); + void flib_netconn_onEngineMessage(NetconnPtr conn, BytesCallback callback, Pointer context); + void flib_netconn_onSchemeChanged(NetconnPtr conn, SchemeCallback callback, Pointer context); + void flib_netconn_onMapChanged(NetconnPtr conn, MapIntCallback callback, Pointer context); + void flib_netconn_onScriptChanged(NetconnPtr conn, StrCallback callback, Pointer context); + void flib_netconn_onWeaponsetChanged(NetconnPtr conn, WeaponsetCallback callback, Pointer context); + void flib_netconn_onServerVar(NetconnPtr conn, StrStrCallback callback, Pointer context); + + // ipc/gameconn.h + static final int GAME_END_FINISHED = 0; + static final int GAME_END_INTERRUPTED = 1; + static final int GAME_END_HALTED = 2; + static final int GAME_END_ERROR = 3; + + GameconnPtr flib_gameconn_create(String playerName, GameSetupPtr setup, boolean netgame); + GameconnPtr flib_gameconn_create_playdemo(ByteArrayPtr demo, NativeSizeT size); + GameconnPtr flib_gameconn_create_loadgame(String playerName, ByteArrayPtr save, NativeSizeT size); + GameconnPtr flib_gameconn_create_campaign(String playerName, String seed, String script); + + void flib_gameconn_destroy(GameconnPtr conn); + int flib_gameconn_getport(GameconnPtr conn); + void flib_gameconn_tick(GameconnPtr conn); + + int flib_gameconn_send_enginemsg(GameconnPtr conn, ByteArrayPtr data, NativeSizeT len); + int flib_gameconn_send_textmsg(GameconnPtr conn, int msgtype, String msg); + int flib_gameconn_send_chatmsg(GameconnPtr conn, String playername, String msg); + int flib_gameconn_send_quit(GameconnPtr conn); + int flib_gameconn_send_cmd(GameconnPtr conn, String cmdString); + + void flib_gameconn_onConnect(GameconnPtr conn, VoidCallback callback, Pointer context); + void flib_gameconn_onDisconnect(GameconnPtr conn, IntCallback callback, Pointer context); + void flib_gameconn_onErrorMessage(GameconnPtr conn, StrCallback callback, Pointer context); + void flib_gameconn_onChat(GameconnPtr conn, StrBoolCallback callback, Pointer context); + void flib_gameconn_onGameRecorded(GameconnPtr conn, BytesBoolCallback callback, Pointer context); + void flib_gameconn_onEngineMessage(GameconnPtr conn, BytesCallback callback, Pointer context); + + // ipc/mapconn.h + public static final int MAPIMAGE_WIDTH = 256; + public static final int MAPIMAGE_HEIGHT = 128; + public static final int MAPIMAGE_BYTES = (MAPIMAGE_WIDTH/8*MAPIMAGE_HEIGHT); + + MapconnPtr flib_mapconn_create(MapRecipePtr mapdesc); + void flib_mapconn_destroy(MapconnPtr conn); + int flib_mapconn_getport(MapconnPtr conn); + void flib_mapconn_onSuccess(MapconnPtr conn, MapimageCallback callback, Pointer context); + void flib_mapconn_onFailure(MapconnPtr conn, StrCallback callback, Pointer context); + void flib_mapconn_tick(MapconnPtr conn); + + // model/map.h + public static final int MAPGEN_REGULAR = 0; + public static final int MAPGEN_MAZE = 1; + public static final int MAPGEN_DRAWN = 2; + public static final int MAPGEN_NAMED = 3; + + public static final int TEMPLATEFILTER_ALL = 0; + public static final int TEMPLATEFILTER_SMALL = 1; + public static final int TEMPLATEFILTER_MEDIUM = 2; + public static final int TEMPLATEFILTER_LARGE = 3; + public static final int TEMPLATEFILTER_CAVERN = 4; + public static final int TEMPLATEFILTER_WACKY = 5; + + public static final int MAZE_SIZE_SMALL_TUNNELS = 0; + public static final int MAZE_SIZE_MEDIUM_TUNNELS = 1; + public static final int MAZE_SIZE_LARGE_TUNNELS = 2; + public static final int MAZE_SIZE_SMALL_ISLANDS = 3; + public static final int MAZE_SIZE_MEDIUM_ISLANDS = 4; + public static final int MAZE_SIZE_LARGE_ISLANDS = 5; + + // model/schemelist.h + SchemelistPtr flib_schemelist_from_ini(String filename); + int flib_schemelist_to_ini(String filename, SchemelistPtr list); + void flib_schemelist_destroy(SchemelistPtr list); + + // model/team.h + TeamPtr flib_team_from_ini(String filename); + int flib_team_to_ini(String filename, TeamPtr team); + void flib_team_destroy(TeamPtr team); + + // model/weapon.h + WeaponsetListPtr flib_weaponsetlist_from_ini(String filename); + int flib_weaponsetlist_to_ini(String filename, WeaponsetListPtr weaponsets); + void flib_weaponsetlist_destroy(WeaponsetListPtr list); + + // model/gamesetup.h + void flib_gamesetup_destroy(GameSetupPtr gamesetup); + + // util/logging.h + public static final int FLIB_LOGLEVEL_ALL = -100; + public static final int FLIB_LOGLEVEL_DEBUG = -1; + public static final int FLIB_LOGLEVEL_INFO = 0; + public static final int FLIB_LOGLEVEL_WARNING = 1; + public static final int FLIB_LOGLEVEL_ERROR = 2; + public static final int FLIB_LOGLEVEL_NONE = 100; + + void flib_log_setLevel(int level); + void flib_log_setCallback(LogCallback callback); } \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/frontlib/NativeSizeT.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/frontlib/NativeSizeT.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/frontlib/NativeSizeT.java Tue Nov 10 20:43:13 2015 +0100 @@ -22,37 +22,37 @@ /** * This class represents the native C type size_t. On Android, this type could be mapped with int, * but we use a separate type to make it easier to adapt for other platforms if anyone wants to use - * the mappings elsewhere. + * the mappings elsewhere. */ public final class NativeSizeT extends Number { - private static final long serialVersionUID = 1L; - private final long value; - - private NativeSizeT(long value) { - this.value = value; - } - - public static NativeSizeT valueOf(long l) { - return new NativeSizeT(l); - } - - @Override - public int intValue() { - return (int)value; - } - - @Override - public long longValue() { - return value; - } + private static final long serialVersionUID = 1L; + private final long value; + + private NativeSizeT(long value) { + this.value = value; + } + + public static NativeSizeT valueOf(long l) { + return new NativeSizeT(l); + } + + @Override + public int intValue() { + return (int)value; + } - @Override - public double doubleValue() { - return value; - } + @Override + public long longValue() { + return value; + } - @Override - public float floatValue() { - return value; - } + @Override + public double doubleValue() { + return value; + } + + @Override + public float floatValue() { + return value; + } } diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/ClientFlagsUpdate.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/ClientFlagsUpdate.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/ClientFlagsUpdate.java Tue Nov 10 20:43:13 2015 +0100 @@ -4,45 +4,45 @@ import org.hedgewars.hedgeroid.Datastructures.PlayerInRoom; final class ClientFlagsUpdate { - public static final char FLAG_ADMIN = 'a'; - public static final char FLAG_CHIEF = 'h'; - public static final char FLAG_READY = 'r'; - public static final char FLAG_REGISTERED = 'u'; - - public final String nick, flags; - public final boolean newFlagState; - - public ClientFlagsUpdate(String nick, String flags, boolean newFlagState) { - this.nick = nick; - this.flags = flags; - this.newFlagState = newFlagState; - } + public static final char FLAG_ADMIN = 'a'; + public static final char FLAG_CHIEF = 'h'; + public static final char FLAG_READY = 'r'; + public static final char FLAG_REGISTERED = 'u'; + + public final String nick, flags; + public final boolean newFlagState; + + public ClientFlagsUpdate(String nick, String flags, boolean newFlagState) { + this.nick = nick; + this.flags = flags; + this.newFlagState = newFlagState; + } + + public Player applyTo(Player p) { + return new Player( + p.name, + updatedFlag(FLAG_REGISTERED, p.registered), + updatedFlag(FLAG_ADMIN, p.admin)); + } - public Player applyTo(Player p) { - return new Player( - p.name, - updatedFlag(FLAG_REGISTERED, p.registered), - updatedFlag(FLAG_ADMIN, p.admin)); - } - - public PlayerInRoom applyTo(PlayerInRoom p) { - return new PlayerInRoom( - this.applyTo(p.player), - updatedFlag(FLAG_READY, p.ready), - updatedFlag(FLAG_CHIEF, p.roomChief)); - } - - public boolean appliesTo(char flag) { - return flags.indexOf(flag) != -1; - } - - private boolean updatedFlag(char flag, boolean oldValue) { - return appliesTo(flag) ? newFlagState : oldValue; - } - - @Override - public String toString() { - return "ClientFlagsUpdate [nick=" + nick + ", flags=" + flags - + ", newFlagState=" + newFlagState + "]"; - } + public PlayerInRoom applyTo(PlayerInRoom p) { + return new PlayerInRoom( + this.applyTo(p.player), + updatedFlag(FLAG_READY, p.ready), + updatedFlag(FLAG_CHIEF, p.roomChief)); + } + + public boolean appliesTo(char flag) { + return flags.indexOf(flag) != -1; + } + + private boolean updatedFlag(char flag, boolean oldValue) { + return appliesTo(flag) ? newFlagState : oldValue; + } + + @Override + public String toString() { + return "ClientFlagsUpdate [nick=" + nick + ", flags=" + flags + + ", newFlagState=" + newFlagState + "]"; + } } diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/GameMessageListener.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/GameMessageListener.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/GameMessageListener.java Tue Nov 10 20:43:13 2015 +0100 @@ -23,12 +23,12 @@ * Interface with several event callbacks that represent network messages which are interesting * for a running game, e.g. because they concern the lifecycle of the game or because they contain * data that needs to be passed on. - * + * * These functions might be called on any thread. */ public interface GameMessageListener { - void onChatMessage(String nick, String message); - void onEngineMessage(byte[] em); - void onMessage(int type, String message); - void onNetDisconnected(); + void onChatMessage(String nick, String message); + void onEngineMessage(byte[] em); + void onMessage(int type, String message); + void onNetDisconnected(); } diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/MessageLog.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/MessageLog.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/MessageLog.java Tue Nov 10 20:43:13 2015 +0100 @@ -44,126 +44,126 @@ import android.util.Log; public class MessageLog { - private static final int BACKLOG_LINES = 200; - - private static final int INFO_COLOR = Color.GRAY; - private static final int PLAYERINFO_COLOR = Color.GREEN; - private static final int CHAT_COLOR = Color.GREEN; - private static final int MECHAT_COLOR = Color.CYAN; - private static final int WARN_COLOR = Color.RED; - private static final int ERROR_COLOR = Color.RED; - - private final Context context; - private List observers = new LinkedList(); - private List log = new LinkedList(); - - public MessageLog(Context context) { - this.context = context; - } - - private Spanned makeLogTime() { - String time = DateFormat.getTimeFormat(context).format(new Date()); - return withColor("[" + time + "] ", INFO_COLOR); - } - - private static Spanned span(CharSequence s, Object o) { - Spannable spannable = new SpannableString(s); - spannable.setSpan(o, 0, s.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - return spannable; - } - - private static Spanned withColor(CharSequence s, int color) { - return span(s, new ForegroundColorSpan(color)); - } - - private static Spanned bold(CharSequence s) { - return span(s, new StyleSpan(Typeface.BOLD)); - } - - private void append(CharSequence msg) { - SpannableStringBuilder ssb = new SpannableStringBuilder(); - ssb.append(makeLogTime()).append(msg); - appendRaw(ssb); - } - - private void appendRaw(CharSequence msg) { - if(log.size() > BACKLOG_LINES) { - log.remove(0); - for(Listener o : observers) { - o.lineRemoved(); - } - } - log.add(msg); - for(Listener o : observers) { - o.lineAdded(msg); - } - } - - void appendPlayerJoin(String playername) { - append(withColor("***" + context.getResources().getString(R.string.log_player_join, playername), INFO_COLOR)); - } - - void appendPlayerLeave(String playername, String partMsg) { - String msg = "***"; - if(partMsg != null) { - msg += context.getResources().getString(R.string.log_player_leave_with_msg, playername, partMsg); - } else { - msg += context.getResources().getString(R.string.log_player_leave, playername); - } - append(withColor(msg, INFO_COLOR)); - } - - void appendChat(String playerName, String msg) { - if(msg.startsWith("/me ")) { - append(withColor("*"+playerName+" "+msg.substring(4), MECHAT_COLOR)); - } else { - Spanned name = bold(playerName+": "); - Spanned fullMessage = withColor(TextUtils.concat(name, msg), CHAT_COLOR); - append(fullMessage); - } - } - - void appendMessage(int type, String msg) { - switch(type) { - case Frontlib.NETCONN_MSG_TYPE_ERROR: - append(withColor("***"+msg, ERROR_COLOR)); - break; - case Frontlib.NETCONN_MSG_TYPE_WARNING: - append(withColor("***"+msg, WARN_COLOR)); - break; - case Frontlib.NETCONN_MSG_TYPE_PLAYERINFO: - append(withColor(msg.replace("\n", " "), PLAYERINFO_COLOR)); - break; - case Frontlib.NETCONN_MSG_TYPE_SERVERMESSAGE: - appendRaw(span(TextUtils.concat("\n", Html.fromHtml(msg), "\n"), new RelativeSizeSpan(1.5f))); - break; - default: - Log.e("MessageLog", "Unknown messagetype "+type); - } - } - - void clear() { - for(Listener o : observers) { - o.clear(); - } - log.clear(); - } - - public void addListener(Listener o) { - observers.add(o); - } - - public void removeListener(Listener o) { - observers.remove(o); - } - - public static interface Listener { - void lineAdded(CharSequence text); - void lineRemoved(); - void clear(); - } + private static final int BACKLOG_LINES = 200; + + private static final int INFO_COLOR = Color.GRAY; + private static final int PLAYERINFO_COLOR = Color.GREEN; + private static final int CHAT_COLOR = Color.GREEN; + private static final int MECHAT_COLOR = Color.CYAN; + private static final int WARN_COLOR = Color.RED; + private static final int ERROR_COLOR = Color.RED; + + private final Context context; + private List observers = new LinkedList(); + private List log = new LinkedList(); + + public MessageLog(Context context) { + this.context = context; + } + + private Spanned makeLogTime() { + String time = DateFormat.getTimeFormat(context).format(new Date()); + return withColor("[" + time + "] ", INFO_COLOR); + } + + private static Spanned span(CharSequence s, Object o) { + Spannable spannable = new SpannableString(s); + spannable.setSpan(o, 0, s.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + return spannable; + } + + private static Spanned withColor(CharSequence s, int color) { + return span(s, new ForegroundColorSpan(color)); + } + + private static Spanned bold(CharSequence s) { + return span(s, new StyleSpan(Typeface.BOLD)); + } + + private void append(CharSequence msg) { + SpannableStringBuilder ssb = new SpannableStringBuilder(); + ssb.append(makeLogTime()).append(msg); + appendRaw(ssb); + } + + private void appendRaw(CharSequence msg) { + if(log.size() > BACKLOG_LINES) { + log.remove(0); + for(Listener o : observers) { + o.lineRemoved(); + } + } + log.add(msg); + for(Listener o : observers) { + o.lineAdded(msg); + } + } + + void appendPlayerJoin(String playername) { + append(withColor("***" + context.getResources().getString(R.string.log_player_join, playername), INFO_COLOR)); + } - public Collection getLog() { - return Collections.unmodifiableList(log); - } + void appendPlayerLeave(String playername, String partMsg) { + String msg = "***"; + if(partMsg != null) { + msg += context.getResources().getString(R.string.log_player_leave_with_msg, playername, partMsg); + } else { + msg += context.getResources().getString(R.string.log_player_leave, playername); + } + append(withColor(msg, INFO_COLOR)); + } + + void appendChat(String playerName, String msg) { + if(msg.startsWith("/me ")) { + append(withColor("*"+playerName+" "+msg.substring(4), MECHAT_COLOR)); + } else { + Spanned name = bold(playerName+": "); + Spanned fullMessage = withColor(TextUtils.concat(name, msg), CHAT_COLOR); + append(fullMessage); + } + } + + void appendMessage(int type, String msg) { + switch(type) { + case Frontlib.NETCONN_MSG_TYPE_ERROR: + append(withColor("***"+msg, ERROR_COLOR)); + break; + case Frontlib.NETCONN_MSG_TYPE_WARNING: + append(withColor("***"+msg, WARN_COLOR)); + break; + case Frontlib.NETCONN_MSG_TYPE_PLAYERINFO: + append(withColor(msg.replace("\n", " "), PLAYERINFO_COLOR)); + break; + case Frontlib.NETCONN_MSG_TYPE_SERVERMESSAGE: + appendRaw(span(TextUtils.concat("\n", Html.fromHtml(msg), "\n"), new RelativeSizeSpan(1.5f))); + break; + default: + Log.e("MessageLog", "Unknown messagetype "+type); + } + } + + void clear() { + for(Listener o : observers) { + o.clear(); + } + log.clear(); + } + + public void addListener(Listener o) { + observers.add(o); + } + + public void removeListener(Listener o) { + observers.remove(o); + } + + public static interface Listener { + void lineAdded(CharSequence text); + void lineRemoved(); + void clear(); + } + + public Collection getLog() { + return Collections.unmodifiableList(log); + } } diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/NetRoomState.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/NetRoomState.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/NetRoomState.java Tue Nov 10 20:43:13 2015 +0100 @@ -41,145 +41,145 @@ * This class manages the room state in a network game. */ class NetRoomState extends BasicRoomState { - final Map requestedTeams = new TreeMap(); - private Netplay netplay; - - public NetRoomState(Netplay netplay) { - this.netplay = netplay; - initRoomState(false); - } + final Map requestedTeams = new TreeMap(); + private Netplay netplay; + + public NetRoomState(Netplay netplay) { + this.netplay = netplay; + initRoomState(false); + } + + public void changeWeaponset(Weaponset weaponset) { + if(getChiefStatus() && !equal(weaponset, getWeaponset())) { + sendToNet(MSG_SEND_WEAPONSET, weaponset); + setWeaponset(weaponset); + } + } + + public void changeMapRecipe(MapRecipe mapRecipe) { + if(getChiefStatus() && !equal(mapRecipe, getMapRecipe())) { + sendToNet(MSG_SEND_MAP, mapRecipe); + setMapRecipe(mapRecipe); + } + } + + public void changeMapNameAndGenerator(String mapName) { + if(getChiefStatus() && !equal(mapName, getMapRecipe().name)) { + int newGenerator = MapRecipe.generatorForMapname(mapName); + if(newGenerator != getMapRecipe().mapgen) { + sendToNet(MSG_SEND_MAP_GENERATOR, newGenerator, null); + } + sendToNet(MSG_SEND_MAP_NAME, mapName); + setMapRecipe(getMapRecipe().withName(mapName).withMapgen(newGenerator)); + } + } + + public void changeMapTemplate(int template) { + if(getChiefStatus() && template != getMapRecipe().templateFilter) { + sendToNet(MSG_SEND_MAP_TEMPLATE, template, null); + setMapRecipe(getMapRecipe().withTemplateFilter(template)); + } + } + + public void changeMazeSize(int mazeSize) { + if(getChiefStatus() && mazeSize != getMapRecipe().mazeSize) { + sendToNet(MSG_SEND_MAZE_SIZE, mazeSize, 0); + setMapRecipe(getMapRecipe().withMazeSize(mazeSize)); + } + } + + public void changeMapSeed(String seed) { + if(getChiefStatus() && !equal(seed, getMapRecipe().seed)) { + sendToNet(MSG_SEND_MAP_SEED, seed); + setMapRecipe(getMapRecipe().withSeed(seed)); + } + } + + public void changeMapTheme(String theme) { + if(getChiefStatus() && !equal(theme, getMapRecipe().theme)) { + sendToNet(MSG_SEND_MAP_THEME, theme); + setMapRecipe(getMapRecipe().withTheme(theme)); + } + } + + public void changeMapDrawdata(byte[] drawdata) { + if(getChiefStatus() && !Arrays.equals(drawdata, getMapRecipe().getDrawData())) { + sendToNet(MSG_SEND_MAP_DRAWDATA, drawdata); + setMapRecipe(getMapRecipe().withDrawData(drawdata)); + } + } - public void changeWeaponset(Weaponset weaponset) { - if(getChiefStatus() && !equal(weaponset, getWeaponset())) { - sendToNet(MSG_SEND_WEAPONSET, weaponset); - setWeaponset(weaponset); - } - } - - public void changeMapRecipe(MapRecipe mapRecipe) { - if(getChiefStatus() && !equal(mapRecipe, getMapRecipe())) { - sendToNet(MSG_SEND_MAP, mapRecipe); - setMapRecipe(mapRecipe); - } - } - - public void changeMapNameAndGenerator(String mapName) { - if(getChiefStatus() && !equal(mapName, getMapRecipe().name)) { - int newGenerator = MapRecipe.generatorForMapname(mapName); - if(newGenerator != getMapRecipe().mapgen) { - sendToNet(MSG_SEND_MAP_GENERATOR, newGenerator, null); - } - sendToNet(MSG_SEND_MAP_NAME, mapName); - setMapRecipe(getMapRecipe().withName(mapName).withMapgen(newGenerator)); - } - } - - public void changeMapTemplate(int template) { - if(getChiefStatus() && template != getMapRecipe().templateFilter) { - sendToNet(MSG_SEND_MAP_TEMPLATE, template, null); - setMapRecipe(getMapRecipe().withTemplateFilter(template)); - } - } - - public void changeMazeSize(int mazeSize) { - if(getChiefStatus() && mazeSize != getMapRecipe().mazeSize) { - sendToNet(MSG_SEND_MAZE_SIZE, mazeSize, 0); - setMapRecipe(getMapRecipe().withMazeSize(mazeSize)); - } - } - - public void changeMapSeed(String seed) { - if(getChiefStatus() && !equal(seed, getMapRecipe().seed)) { - sendToNet(MSG_SEND_MAP_SEED, seed); - setMapRecipe(getMapRecipe().withSeed(seed)); - } - } - - public void changeMapTheme(String theme) { - if(getChiefStatus() && !equal(theme, getMapRecipe().theme)) { - sendToNet(MSG_SEND_MAP_THEME, theme); - setMapRecipe(getMapRecipe().withTheme(theme)); - } - } - - public void changeMapDrawdata(byte[] drawdata) { - if(getChiefStatus() && !Arrays.equals(drawdata, getMapRecipe().getDrawData())) { - sendToNet(MSG_SEND_MAP_DRAWDATA, drawdata); - setMapRecipe(getMapRecipe().withDrawData(drawdata)); - } - } - - public void changeGameStyle(String gameStyle) { - if(getChiefStatus() && !equal(gameStyle, getGameStyle())) { - sendToNet(MSG_SEND_GAMESTYLE, gameStyle); - setGameStyle(gameStyle); - } - } - - public void changeScheme(Scheme scheme) { - if(getChiefStatus() && !equal(scheme, getScheme())) { - sendToNet(MSG_SEND_SCHEME, scheme); - setScheme(scheme); - } - } - - void initRoomState(boolean chief) { - setTeams(Collections.emptyMap()); - requestedTeams.clear(); - - setChief(chief); - setGameStyle(GameConfig.DEFAULT_STYLE); - setMapRecipe(MapRecipe.makeRandomMap(0, "seed", GameConfig.DEFAULT_THEME)); - setScheme(netplay.defaultScheme); - setWeaponset(netplay.defaultWeaponset); - sendFullConfig(); - } - - void sendFullConfig() { - if(getChiefStatus()) { - sendToNet(MSG_SEND_GAMESTYLE, getGameStyle()); - sendToNet(MSG_SEND_SCHEME, getScheme()); - sendToNet(MSG_SEND_WEAPONSET, getWeaponset()); - sendToNet(MSG_SEND_MAP, getMapRecipe()); - } - } - - private boolean sendToNet(ToNetMsgType what, Object obj) { - return netplay.sendToNet(what, 0, obj); - } - - private boolean sendToNet(ToNetMsgType what, int arg1, Object obj) { - return netplay.sendToNet(what, arg1, obj); - } + public void changeGameStyle(String gameStyle) { + if(getChiefStatus() && !equal(gameStyle, getGameStyle())) { + sendToNet(MSG_SEND_GAMESTYLE, gameStyle); + setGameStyle(gameStyle); + } + } + + public void changeScheme(Scheme scheme) { + if(getChiefStatus() && !equal(scheme, getScheme())) { + sendToNet(MSG_SEND_SCHEME, scheme); + setScheme(scheme); + } + } + + void initRoomState(boolean chief) { + setTeams(Collections.emptyMap()); + requestedTeams.clear(); + + setChief(chief); + setGameStyle(GameConfig.DEFAULT_STYLE); + setMapRecipe(MapRecipe.makeRandomMap(0, "seed", GameConfig.DEFAULT_THEME)); + setScheme(netplay.defaultScheme); + setWeaponset(netplay.defaultWeaponset); + sendFullConfig(); + } + + void sendFullConfig() { + if(getChiefStatus()) { + sendToNet(MSG_SEND_GAMESTYLE, getGameStyle()); + sendToNet(MSG_SEND_SCHEME, getScheme()); + sendToNet(MSG_SEND_WEAPONSET, getWeaponset()); + sendToNet(MSG_SEND_MAP, getMapRecipe()); + } + } - public void requestAddTeam(Team team, int colorIndex) { - TeamIngameAttributes tia = new TeamIngameAttributes(netplay.getPlayerName(), colorIndex, TeamIngameAttributes.DEFAULT_HOG_COUNT, false); - TeamInGame newTeamInGame = new TeamInGame(team, tia); - requestedTeams.put(team.name, newTeamInGame); - sendToNet(MSG_SEND_ADD_TEAM, newTeamInGame); - } + private boolean sendToNet(ToNetMsgType what, Object obj) { + return netplay.sendToNet(what, 0, obj); + } + + private boolean sendToNet(ToNetMsgType what, int arg1, Object obj) { + return netplay.sendToNet(what, arg1, obj); + } - public void requestRemoveTeam(String teamname) { - sendToNet(MSG_SEND_REMOVE_TEAM, teamname); - } + public void requestAddTeam(Team team, int colorIndex) { + TeamIngameAttributes tia = new TeamIngameAttributes(netplay.getPlayerName(), colorIndex, TeamIngameAttributes.DEFAULT_HOG_COUNT, false); + TeamInGame newTeamInGame = new TeamInGame(team, tia); + requestedTeams.put(team.name, newTeamInGame); + sendToNet(MSG_SEND_ADD_TEAM, newTeamInGame); + } + + public void requestRemoveTeam(String teamname) { + sendToNet(MSG_SEND_REMOVE_TEAM, teamname); + } - public void changeTeamColorIndex(String teamname, int colorIndex) { - if(getChiefStatus()) { - TeamInGame team = getTeams().get(teamname); - if(team.ingameAttribs.colorIndex != colorIndex) { - sendToNet(MSG_SEND_TEAM_COLOR_INDEX, colorIndex, teamname); - putTeam(team.withAttribs(team.ingameAttribs.withColorIndex(colorIndex))); - } - } - } + public void changeTeamColorIndex(String teamname, int colorIndex) { + if(getChiefStatus()) { + TeamInGame team = getTeams().get(teamname); + if(team.ingameAttribs.colorIndex != colorIndex) { + sendToNet(MSG_SEND_TEAM_COLOR_INDEX, colorIndex, teamname); + putTeam(team.withAttribs(team.ingameAttribs.withColorIndex(colorIndex))); + } + } + } - public void changeTeamHogCount(String teamname, int hogcount) { - if(getChiefStatus()) { - TeamInGame team = getTeams().get(teamname); - if(team.ingameAttribs.hogCount != hogcount) { - sendToNet(MSG_SEND_TEAM_HOG_COUNT, hogcount, teamname); - putTeam(team.withAttribs(team.ingameAttribs.withHogCount(hogcount))); - } - } - } + public void changeTeamHogCount(String teamname, int hogcount) { + if(getChiefStatus()) { + TeamInGame team = getTeams().get(teamname); + if(team.ingameAttribs.hogCount != hogcount) { + sendToNet(MSG_SEND_TEAM_HOG_COUNT, hogcount, teamname); + putTeam(team.withAttribs(team.ingameAttribs.withHogCount(hogcount))); + } + } + } } diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/Netplay.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/Netplay.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/Netplay.java Tue Nov 10 20:43:13 2015 +0100 @@ -1,535 +1,535 @@ -/* - * Hedgewars for Android. An Android port of Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -package org.hedgewars.hedgeroid.netplay; - -import static org.hedgewars.hedgeroid.netplay.ThreadedNetConnection.ToNetMsgType.*; - -import java.io.IOException; -import java.util.Arrays; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; - -import org.hedgewars.hedgeroid.RoomStateManager; -import org.hedgewars.hedgeroid.Datastructures.GameConfig; -import org.hedgewars.hedgeroid.Datastructures.MapRecipe; -import org.hedgewars.hedgeroid.Datastructures.Player; -import org.hedgewars.hedgeroid.Datastructures.PlayerInRoom; -import org.hedgewars.hedgeroid.Datastructures.Room; -import org.hedgewars.hedgeroid.Datastructures.Scheme; -import org.hedgewars.hedgeroid.Datastructures.Schemes; -import org.hedgewars.hedgeroid.Datastructures.TeamInGame; -import org.hedgewars.hedgeroid.Datastructures.TeamIngameAttributes; -import org.hedgewars.hedgeroid.Datastructures.Weaponset; -import org.hedgewars.hedgeroid.Datastructures.Weaponsets; -import org.hedgewars.hedgeroid.netplay.ThreadedNetConnection.ToNetMsgType; -import org.hedgewars.hedgeroid.util.ObservableTreeMap; - -import android.annotation.SuppressLint; -import android.content.Context; -import android.content.Intent; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; -import android.support.v4.content.LocalBroadcastManager; -import android.util.Log; -import android.util.Pair; - - -/** - * This class manages the application's networking state. - */ -public class Netplay { - public static enum State { NOT_CONNECTED, CONNECTING, LOBBY, ROOM } - - // Extras in broadcasts - public static final String EXTRA_PLAYERNAME = "playerName"; - public static final String EXTRA_MESSAGE = "message"; - public static final String EXTRA_HAS_ERROR = "hasError"; - public static final String EXTRA_REASON = "reason"; - - private static final String ACTIONPREFIX = "org.hedgewars.hedgeroid.netconn."; - public static final String ACTION_DISCONNECTED = ACTIONPREFIX+"DISCONNECTED"; - public static final String ACTION_CONNECTED = ACTIONPREFIX+"CONNECTED"; - public static final String ACTION_PASSWORD_REQUESTED = ACTIONPREFIX+"PASSWORD_REQUESTED"; - public static final String ACTION_ENTERED_ROOM_FROM_LOBBY = ACTIONPREFIX+"ENTERED_ROOM"; - public static final String ACTION_LEFT_ROOM = ACTIONPREFIX+"LEFT_ROOM"; - public static final String ACTION_STATE_CHANGED = ACTIONPREFIX+"STATE_CHANGED"; - - public static final String DEFAULT_SERVER = "netserver.hedgewars.org"; - public static final int DEFAULT_PORT = 46631; - - private final Context appContext; - private final LocalBroadcastManager broadcastManager; - private final FromNetHandler fromNetHandler = new FromNetHandler(); - public final Scheme defaultScheme; - public final Weaponset defaultWeaponset; - - private State state = State.NOT_CONNECTED; - private String playerName; - - // null or stale if not in room state - private final NetRoomState netRoomState = new NetRoomState(this); - - // null if there is no running connection (==state is NOT_CONNECTED) - private ThreadedNetConnection connection; - - public final ObservableTreeMap lobbyPlayerlist = new ObservableTreeMap(); - public final ObservableTreeMap roomPlayerlist = new ObservableTreeMap(); - public final Roomlist roomList = new Roomlist(); - public final MessageLog lobbyChatlog; - public final MessageLog roomChatlog; - - private final List gameMessageListeners = new LinkedList(); - private final List runGameListeners = new LinkedList(); - - public Netplay(Context appContext, Scheme defaultScheme, Weaponset defaultWeaponset) { - this.appContext = appContext; - broadcastManager = LocalBroadcastManager.getInstance(appContext); - lobbyChatlog = new MessageLog(appContext); - roomChatlog = new MessageLog(appContext); - this.defaultScheme = defaultScheme; - this.defaultWeaponset = defaultWeaponset; - } - - public RoomStateManager getRoomStateManager() { - return netRoomState; - } - - private void clearLobbyState() { - lobbyPlayerlist.clear(); - roomList.clear(); - lobbyChatlog.clear(); - } - - private void initRoomState(boolean chief) { - roomChatlog.clear(); - roomPlayerlist.clear(); - netRoomState.initRoomState(chief); - } - - public void registerGameMessageListener(GameMessageListener listener) { - gameMessageListeners.add(listener); - } - - public void unregisterGameMessageListener(GameMessageListener listener) { - gameMessageListeners.remove(listener); - } - - public void registerRunGameListener(RunGameListener listener) { - runGameListeners.add(listener); - } - - public void unregisterRunGameListener(RunGameListener listener) { - runGameListeners.remove(listener); - } - - public void connectToDefaultServer(String playerName) { - connect(playerName, DEFAULT_SERVER, DEFAULT_PORT); - } - - /** - * Establish a new connection. Only call if the current state is NOT_CONNECTED. - * - * The state will switch to CONNECTING immediately. After that, it can asynchronously change to any other state. - * State changes are indicated by broadcasts. In particular, if an error occurs while trying to connect, the state - * will change back to NOT_CONNECTED and an ACTION_DISCONNECTED broadcast is sent. - */ - public void connect(String name, String host, int port) { - playerName = name; - if(state != State.NOT_CONNECTED) { - throw new IllegalStateException("Attempt to start a new connection while the old one was still running."); - } - - clearLobbyState(); - changeState(State.CONNECTING); - connection = ThreadedNetConnection.startConnection(appContext, fromNetHandler, name, host, port); - connection.setFastTickRate(true); - } - - public void sendNick(String nick) { - playerName = nick; - sendToNet(MSG_SEND_NICK, nick); - } - public void sendPassword(String password) { sendToNet(MSG_SEND_PASSWORD, password); } - public void sendQuit(String message) { sendToNet(MSG_SEND_QUIT, message); } - public void sendRoomlistRequest() { sendToNet(MSG_SEND_ROOMLIST_REQUEST); } - public void sendPlayerInfoQuery(String name) { sendToNet(MSG_SEND_PLAYER_INFO_REQUEST, name); } - public void sendChat(String s) { sendToNet(MSG_SEND_CHAT, s); } - public void sendTeamChat(String s) { sendToNet(MSG_SEND_TEAMCHAT, s); } - public void sendFollowPlayer(String nick) { sendToNet(MSG_SEND_FOLLOW_PLAYER, nick); } - public void sendJoinRoom(String name) { sendToNet(MSG_SEND_JOIN_ROOM, name); } - public void sendCreateRoom(String name) { sendToNet(MSG_SEND_CREATE_ROOM, name); } - public void sendLeaveRoom(String message) { sendToNet(MSG_SEND_LEAVE_ROOM, message); } - public void sendKick(String player) { sendToNet(MSG_SEND_KICK, player); } - public void sendEngineMessage(byte[] engineMessage) { sendToNet(MSG_SEND_ENGINE_MESSAGE, engineMessage); } - public void sendRoundFinished(boolean withoutError) { sendToNet(MSG_SEND_ROUND_FINISHED, Boolean.valueOf(withoutError)); } - public void sendToggleReady() { sendToNet(MSG_SEND_TOGGLE_READY); } - public void sendStartGame() { sendToNet(MSG_SEND_START_GAME); } - - public void disconnect() { sendToNet(MSG_DISCONNECT, "User Quit"); } - - private static Netplay instance; - - /** - * Retrieve the single app-wide instance of the netplay interface, creating it if it - * does not exist yet. - * - * @param applicationContext - * @return - */ - public static Netplay getAppInstance(Context applicationContext) { - if(instance == null) { - // We will need some default values for rooms, best load them here - Scheme defaultScheme = null; - Weaponset defaultWeaponset = null; - try { - List schemes = Schemes.loadBuiltinSchemes(applicationContext); - for(Scheme scheme : schemes) { - if(scheme.name.equals(GameConfig.DEFAULT_SCHEME)) { - defaultScheme = scheme; - } - } - List weaponsets = Weaponsets.loadBuiltinWeaponsets(applicationContext); - for(Weaponset weaponset : weaponsets) { - if(weaponset.name.equals(GameConfig.DEFAULT_WEAPONSET)) { - defaultWeaponset = weaponset; - } - } - } catch(IOException e) { - throw new RuntimeException(e); - } - - if(defaultScheme==null || defaultWeaponset==null) { - throw new RuntimeException("Unable to load default scheme or weaponset"); - } - - instance = new Netplay(applicationContext, defaultScheme, defaultWeaponset); - } - return instance; - } - - public State getState() { - return state; - } - - private void changeState(State newState) { - if(newState != state) { - state = newState; - broadcastManager.sendBroadcastSync(new Intent(ACTION_STATE_CHANGED)); - } - } - - public boolean isChief() { - if(netRoomState != null) { - return netRoomState.getChiefStatus(); - } else { - return false; - } - } - - public String getPlayerName() { - return playerName; - } - - boolean sendToNet(ToNetMsgType what) { - return sendToNet(what, 0, null); - } - - boolean sendToNet(ToNetMsgType what, Object obj) { - return sendToNet(what, 0, obj); - } - - boolean sendToNet(ToNetMsgType what, int arg1, Object obj) { - if(connection != null) { - Handler handler = connection.toNetHandler; - return handler.sendMessage(handler.obtainMessage(what.ordinal(), arg1, 0, obj)); - } else { - return false; - } - } - - private MessageLog getCurrentLog() { - if(state == State.ROOM) { - return roomChatlog; - } else { - return lobbyChatlog; - } - } - - public static enum FromNetMsgType { - MSG_LOBBY_JOIN, - MSG_LOBBY_LEAVE, - MSG_ROOM_JOIN, - MSG_ROOM_LEAVE, - MSG_CLIENT_FLAGS, - MSG_CHAT, - MSG_MESSAGE, - MSG_ROOM_ADD, - MSG_ROOM_UPDATE, - MSG_ROOM_DELETE, - MSG_ROOMLIST, - MSG_CONNECTED, - MSG_DISCONNECTED, - MSG_PASSWORD_REQUEST, - MSG_ENTER_ROOM_FROM_LOBBY, - MSG_LEAVE_ROOM, - MSG_TEAM_ADDED, - MSG_TEAM_DELETED, - MSG_TEAM_ACCEPTED, - MSG_TEAM_COLOR_CHANGED, - MSG_HOG_COUNT_CHANGED, - MSG_ENGINE_MESSAGE, - MSG_RUN_GAME, - MSG_SCHEME_CHANGED, - MSG_MAP_CHANGED, - MSG_SCRIPT_CHANGED, - MSG_WEAPONSET_CHANGED; - - static final List values = Collections.unmodifiableList(Arrays.asList(FromNetMsgType.values())); - } - - /** - * Processes messages from the networking system. Always runs on the main thread. - */ - @SuppressLint("HandlerLeak") - final class FromNetHandler extends Handler { - public FromNetHandler() { - super(Looper.getMainLooper()); - } - - @SuppressWarnings("unchecked") - @Override - public void handleMessage(Message msg) { - switch(FromNetMsgType.values.get(msg.what)) { - case MSG_LOBBY_JOIN: { - String name = (String)msg.obj; - lobbyPlayerlist.put(name, new Player(name, false, false)); - lobbyChatlog.appendPlayerJoin(name); - break; - } - case MSG_LOBBY_LEAVE: { - Pair args = (Pair)msg.obj; - lobbyPlayerlist.remove(args.first); - lobbyChatlog.appendPlayerLeave(args.first, args.second); - break; - } - case MSG_ROOM_JOIN: { - String name = (String)msg.obj; - Player p = lobbyPlayerlist.get(name); - if(p==null) { - Log.w("Netplay", "Unknown player joined room: "+name); - p = new Player(name, false, false); - } - roomPlayerlist.put(name, new PlayerInRoom(p, false, false)); - roomChatlog.appendPlayerJoin(name); - break; - } - case MSG_ROOM_LEAVE: { - Pair args = (Pair)msg.obj; - roomPlayerlist.remove(args.first); - roomChatlog.appendPlayerLeave(args.first, args.second); - break; - } - case MSG_CLIENT_FLAGS: { - ClientFlagsUpdate upd = (ClientFlagsUpdate)msg.obj; - PlayerInRoom pir = roomPlayerlist.get(upd.nick); - if(pir != null) { - roomPlayerlist.put(upd.nick, upd.applyTo(pir)); - } - Player p = lobbyPlayerlist.get(upd.nick); - if(p != null) { - lobbyPlayerlist.put(upd.nick, upd.applyTo(p)); - } else { - Log.w("Netplay", "Received client flags for unknown player "+upd.nick); - } - if(playerName.equals(upd.nick) && upd.appliesTo(ClientFlagsUpdate.FLAG_CHIEF)) { - netRoomState.setChief(upd.newFlagState); - } - break; - } - case MSG_CHAT: { - Pair args = (Pair)msg.obj; - getCurrentLog().appendChat(args.first, args.second); - for(GameMessageListener listener : gameMessageListeners) { - listener.onChatMessage(args.first, args.second); - } - break; - } - case MSG_MESSAGE: { - getCurrentLog().appendMessage(msg.arg1, (String)msg.obj); - for(GameMessageListener listener : gameMessageListeners) { - listener.onMessage(1, (String)msg.obj); - } - break; - } - case MSG_ROOM_ADD: { - Room room = (Room)msg.obj; - roomList.addRoomWithNewId(room); - break; - } - case MSG_ROOM_UPDATE: { - Pair args = (Pair)msg.obj; - roomList.updateRoom(args.first, args.second); - break; - } - case MSG_ROOM_DELETE: { - roomList.remove((String)msg.obj); - break; - } - case MSG_ROOMLIST: { - Room[] rooms = (Room[])msg.obj; - roomList.updateList(rooms); - break; - } - case MSG_CONNECTED: { - playerName = (String)msg.obj; - changeState(State.LOBBY); - broadcastManager.sendBroadcast(new Intent(ACTION_CONNECTED)); - break; - } - case MSG_DISCONNECTED: { - Pair args = (Pair)msg.obj; - for(GameMessageListener listener : gameMessageListeners) { - listener.onNetDisconnected(); - } - changeState(State.NOT_CONNECTED); - connection = null; - Intent intent = new Intent(ACTION_DISCONNECTED); - intent.putExtra(EXTRA_HAS_ERROR, args.first); - intent.putExtra(EXTRA_MESSAGE, args.second); - broadcastManager.sendBroadcastSync(intent); - break; - } - case MSG_PASSWORD_REQUEST: { - Intent intent = new Intent(ACTION_PASSWORD_REQUESTED); - intent.putExtra(EXTRA_PLAYERNAME, (String)msg.obj); - broadcastManager.sendBroadcast(intent); - break; - } - case MSG_ENTER_ROOM_FROM_LOBBY: { - initRoomState((Boolean)msg.obj); - changeState(State.ROOM); - Intent intent = new Intent(ACTION_ENTERED_ROOM_FROM_LOBBY); - broadcastManager.sendBroadcastSync(intent); - break; - } - case MSG_LEAVE_ROOM: { - changeState(State.LOBBY); - Intent intent = new Intent(ACTION_LEFT_ROOM); - intent.putExtra(EXTRA_MESSAGE, (String)msg.obj); - intent.putExtra(EXTRA_REASON, msg.arg1); - broadcastManager.sendBroadcastSync(intent); - break; - } - case MSG_TEAM_ADDED: { - TeamInGame newTeam = (TeamInGame)msg.obj; - if(isChief()) { - int freeColor = TeamInGame.getUnusedOrRandomColorIndex(netRoomState.getTeams().values()); - sendToNet(MSG_SEND_TEAM_HOG_COUNT, newTeam.ingameAttribs.hogCount, newTeam.team.name); - sendToNet(MSG_SEND_TEAM_COLOR_INDEX, freeColor, newTeam.team.name); - newTeam = newTeam.withAttribs(newTeam.ingameAttribs.withColorIndex(freeColor)); - } - netRoomState.putTeam(newTeam); - break; - } - case MSG_TEAM_DELETED: { - netRoomState.removeTeam((String)msg.obj); - break; - } - case MSG_TEAM_ACCEPTED: { - TeamInGame requestedTeam = netRoomState.requestedTeams.remove(msg.obj); - if(requestedTeam!=null) { - netRoomState.putTeam(requestedTeam); - if(isChief()) { - // Not strictly necessary, but QtFrontend does it... - sendToNet(MSG_SEND_TEAM_HOG_COUNT, requestedTeam.ingameAttribs.hogCount, requestedTeam.team.name); - } - } else { - Log.e("Netplay", "Got accepted message for team that was never requested."); - } - break; - } - case MSG_TEAM_COLOR_CHANGED: { - TeamInGame oldEntry = netRoomState.getTeams().get((String)msg.obj); - if(oldEntry != null) { - /* - * If we are chief, we ignore colors from the outside. They only come from the server - * when someone adds a team then, and we override that choice anyway. - * Worse, that color message arrives *after* we have overridden the color, so it would - * re-override it right back. - */ - if(!isChief()) { - TeamIngameAttributes newAttribs = oldEntry.ingameAttribs.withColorIndex(msg.arg1); - netRoomState.putTeam(oldEntry.withAttribs(newAttribs)); - } - } else { - Log.e("Netplay", "Color update for unknown team "+msg.obj); - } - break; - } - case MSG_HOG_COUNT_CHANGED: { - TeamInGame oldEntry = netRoomState.getTeams().get((String)msg.obj); - if(oldEntry != null) { - TeamIngameAttributes newAttribs = oldEntry.ingameAttribs.withHogCount(msg.arg1); - netRoomState.putTeam(oldEntry.withAttribs(newAttribs)); - } else { - Log.e("Netplay", "Hog count update for unknown team "+msg.obj); - } - break; - } - case MSG_ENGINE_MESSAGE: { - byte[] em = (byte[])msg.obj; - for(GameMessageListener listener : gameMessageListeners) { - listener.onEngineMessage(em); - } - break; - } - case MSG_RUN_GAME: { - GameConfig config = (GameConfig)msg.obj; - for(RunGameListener listener : runGameListeners) { - listener.runGame(config); - } - break; - } - case MSG_MAP_CHANGED: { - netRoomState.setMapRecipe((MapRecipe)msg.obj); - break; - } - case MSG_SCHEME_CHANGED: { - netRoomState.setScheme((Scheme)msg.obj); - break; - } - case MSG_SCRIPT_CHANGED: { - netRoomState.setGameStyle((String)msg.obj); - break; - } - case MSG_WEAPONSET_CHANGED: { - netRoomState.setWeaponset((Weaponset)msg.obj); - break; - } - default: { - Log.e("FromNetHandler", "Unknown message type: "+msg.what); - break; - } - } - } - } -} +/* + * Hedgewars for Android. An Android port of Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package org.hedgewars.hedgeroid.netplay; + +import static org.hedgewars.hedgeroid.netplay.ThreadedNetConnection.ToNetMsgType.*; + +import java.io.IOException; +import java.util.Arrays; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +import org.hedgewars.hedgeroid.RoomStateManager; +import org.hedgewars.hedgeroid.Datastructures.GameConfig; +import org.hedgewars.hedgeroid.Datastructures.MapRecipe; +import org.hedgewars.hedgeroid.Datastructures.Player; +import org.hedgewars.hedgeroid.Datastructures.PlayerInRoom; +import org.hedgewars.hedgeroid.Datastructures.Room; +import org.hedgewars.hedgeroid.Datastructures.Scheme; +import org.hedgewars.hedgeroid.Datastructures.Schemes; +import org.hedgewars.hedgeroid.Datastructures.TeamInGame; +import org.hedgewars.hedgeroid.Datastructures.TeamIngameAttributes; +import org.hedgewars.hedgeroid.Datastructures.Weaponset; +import org.hedgewars.hedgeroid.Datastructures.Weaponsets; +import org.hedgewars.hedgeroid.netplay.ThreadedNetConnection.ToNetMsgType; +import org.hedgewars.hedgeroid.util.ObservableTreeMap; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.Intent; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.support.v4.content.LocalBroadcastManager; +import android.util.Log; +import android.util.Pair; + + +/** + * This class manages the application's networking state. + */ +public class Netplay { + public static enum State { NOT_CONNECTED, CONNECTING, LOBBY, ROOM } + + // Extras in broadcasts + public static final String EXTRA_PLAYERNAME = "playerName"; + public static final String EXTRA_MESSAGE = "message"; + public static final String EXTRA_HAS_ERROR = "hasError"; + public static final String EXTRA_REASON = "reason"; + + private static final String ACTIONPREFIX = "org.hedgewars.hedgeroid.netconn."; + public static final String ACTION_DISCONNECTED = ACTIONPREFIX+"DISCONNECTED"; + public static final String ACTION_CONNECTED = ACTIONPREFIX+"CONNECTED"; + public static final String ACTION_PASSWORD_REQUESTED = ACTIONPREFIX+"PASSWORD_REQUESTED"; + public static final String ACTION_ENTERED_ROOM_FROM_LOBBY = ACTIONPREFIX+"ENTERED_ROOM"; + public static final String ACTION_LEFT_ROOM = ACTIONPREFIX+"LEFT_ROOM"; + public static final String ACTION_STATE_CHANGED = ACTIONPREFIX+"STATE_CHANGED"; + + public static final String DEFAULT_SERVER = "netserver.hedgewars.org"; + public static final int DEFAULT_PORT = 46631; + + private final Context appContext; + private final LocalBroadcastManager broadcastManager; + private final FromNetHandler fromNetHandler = new FromNetHandler(); + public final Scheme defaultScheme; + public final Weaponset defaultWeaponset; + + private State state = State.NOT_CONNECTED; + private String playerName; + + // null or stale if not in room state + private final NetRoomState netRoomState = new NetRoomState(this); + + // null if there is no running connection (==state is NOT_CONNECTED) + private ThreadedNetConnection connection; + + public final ObservableTreeMap lobbyPlayerlist = new ObservableTreeMap(); + public final ObservableTreeMap roomPlayerlist = new ObservableTreeMap(); + public final Roomlist roomList = new Roomlist(); + public final MessageLog lobbyChatlog; + public final MessageLog roomChatlog; + + private final List gameMessageListeners = new LinkedList(); + private final List runGameListeners = new LinkedList(); + + public Netplay(Context appContext, Scheme defaultScheme, Weaponset defaultWeaponset) { + this.appContext = appContext; + broadcastManager = LocalBroadcastManager.getInstance(appContext); + lobbyChatlog = new MessageLog(appContext); + roomChatlog = new MessageLog(appContext); + this.defaultScheme = defaultScheme; + this.defaultWeaponset = defaultWeaponset; + } + + public RoomStateManager getRoomStateManager() { + return netRoomState; + } + + private void clearLobbyState() { + lobbyPlayerlist.clear(); + roomList.clear(); + lobbyChatlog.clear(); + } + + private void initRoomState(boolean chief) { + roomChatlog.clear(); + roomPlayerlist.clear(); + netRoomState.initRoomState(chief); + } + + public void registerGameMessageListener(GameMessageListener listener) { + gameMessageListeners.add(listener); + } + + public void unregisterGameMessageListener(GameMessageListener listener) { + gameMessageListeners.remove(listener); + } + + public void registerRunGameListener(RunGameListener listener) { + runGameListeners.add(listener); + } + + public void unregisterRunGameListener(RunGameListener listener) { + runGameListeners.remove(listener); + } + + public void connectToDefaultServer(String playerName) { + connect(playerName, DEFAULT_SERVER, DEFAULT_PORT); + } + + /** + * Establish a new connection. Only call if the current state is NOT_CONNECTED. + * + * The state will switch to CONNECTING immediately. After that, it can asynchronously change to any other state. + * State changes are indicated by broadcasts. In particular, if an error occurs while trying to connect, the state + * will change back to NOT_CONNECTED and an ACTION_DISCONNECTED broadcast is sent. + */ + public void connect(String name, String host, int port) { + playerName = name; + if(state != State.NOT_CONNECTED) { + throw new IllegalStateException("Attempt to start a new connection while the old one was still running."); + } + + clearLobbyState(); + changeState(State.CONNECTING); + connection = ThreadedNetConnection.startConnection(appContext, fromNetHandler, name, host, port); + connection.setFastTickRate(true); + } + + public void sendNick(String nick) { + playerName = nick; + sendToNet(MSG_SEND_NICK, nick); + } + public void sendPassword(String password) { sendToNet(MSG_SEND_PASSWORD, password); } + public void sendQuit(String message) { sendToNet(MSG_SEND_QUIT, message); } + public void sendRoomlistRequest() { sendToNet(MSG_SEND_ROOMLIST_REQUEST); } + public void sendPlayerInfoQuery(String name) { sendToNet(MSG_SEND_PLAYER_INFO_REQUEST, name); } + public void sendChat(String s) { sendToNet(MSG_SEND_CHAT, s); } + public void sendTeamChat(String s) { sendToNet(MSG_SEND_TEAMCHAT, s); } + public void sendFollowPlayer(String nick) { sendToNet(MSG_SEND_FOLLOW_PLAYER, nick); } + public void sendJoinRoom(String name) { sendToNet(MSG_SEND_JOIN_ROOM, name); } + public void sendCreateRoom(String name) { sendToNet(MSG_SEND_CREATE_ROOM, name); } + public void sendLeaveRoom(String message) { sendToNet(MSG_SEND_LEAVE_ROOM, message); } + public void sendKick(String player) { sendToNet(MSG_SEND_KICK, player); } + public void sendEngineMessage(byte[] engineMessage) { sendToNet(MSG_SEND_ENGINE_MESSAGE, engineMessage); } + public void sendRoundFinished(boolean withoutError) { sendToNet(MSG_SEND_ROUND_FINISHED, Boolean.valueOf(withoutError)); } + public void sendToggleReady() { sendToNet(MSG_SEND_TOGGLE_READY); } + public void sendStartGame() { sendToNet(MSG_SEND_START_GAME); } + + public void disconnect() { sendToNet(MSG_DISCONNECT, "User Quit"); } + + private static Netplay instance; + + /** + * Retrieve the single app-wide instance of the netplay interface, creating it if it + * does not exist yet. + * + * @param applicationContext + * @return + */ + public static Netplay getAppInstance(Context applicationContext) { + if(instance == null) { + // We will need some default values for rooms, best load them here + Scheme defaultScheme = null; + Weaponset defaultWeaponset = null; + try { + List schemes = Schemes.loadBuiltinSchemes(applicationContext); + for(Scheme scheme : schemes) { + if(scheme.name.equals(GameConfig.DEFAULT_SCHEME)) { + defaultScheme = scheme; + } + } + List weaponsets = Weaponsets.loadBuiltinWeaponsets(applicationContext); + for(Weaponset weaponset : weaponsets) { + if(weaponset.name.equals(GameConfig.DEFAULT_WEAPONSET)) { + defaultWeaponset = weaponset; + } + } + } catch(IOException e) { + throw new RuntimeException(e); + } + + if(defaultScheme==null || defaultWeaponset==null) { + throw new RuntimeException("Unable to load default scheme or weaponset"); + } + + instance = new Netplay(applicationContext, defaultScheme, defaultWeaponset); + } + return instance; + } + + public State getState() { + return state; + } + + private void changeState(State newState) { + if(newState != state) { + state = newState; + broadcastManager.sendBroadcastSync(new Intent(ACTION_STATE_CHANGED)); + } + } + + public boolean isChief() { + if(netRoomState != null) { + return netRoomState.getChiefStatus(); + } else { + return false; + } + } + + public String getPlayerName() { + return playerName; + } + + boolean sendToNet(ToNetMsgType what) { + return sendToNet(what, 0, null); + } + + boolean sendToNet(ToNetMsgType what, Object obj) { + return sendToNet(what, 0, obj); + } + + boolean sendToNet(ToNetMsgType what, int arg1, Object obj) { + if(connection != null) { + Handler handler = connection.toNetHandler; + return handler.sendMessage(handler.obtainMessage(what.ordinal(), arg1, 0, obj)); + } else { + return false; + } + } + + private MessageLog getCurrentLog() { + if(state == State.ROOM) { + return roomChatlog; + } else { + return lobbyChatlog; + } + } + + public static enum FromNetMsgType { + MSG_LOBBY_JOIN, + MSG_LOBBY_LEAVE, + MSG_ROOM_JOIN, + MSG_ROOM_LEAVE, + MSG_CLIENT_FLAGS, + MSG_CHAT, + MSG_MESSAGE, + MSG_ROOM_ADD, + MSG_ROOM_UPDATE, + MSG_ROOM_DELETE, + MSG_ROOMLIST, + MSG_CONNECTED, + MSG_DISCONNECTED, + MSG_PASSWORD_REQUEST, + MSG_ENTER_ROOM_FROM_LOBBY, + MSG_LEAVE_ROOM, + MSG_TEAM_ADDED, + MSG_TEAM_DELETED, + MSG_TEAM_ACCEPTED, + MSG_TEAM_COLOR_CHANGED, + MSG_HOG_COUNT_CHANGED, + MSG_ENGINE_MESSAGE, + MSG_RUN_GAME, + MSG_SCHEME_CHANGED, + MSG_MAP_CHANGED, + MSG_SCRIPT_CHANGED, + MSG_WEAPONSET_CHANGED; + + static final List values = Collections.unmodifiableList(Arrays.asList(FromNetMsgType.values())); + } + + /** + * Processes messages from the networking system. Always runs on the main thread. + */ + @SuppressLint("HandlerLeak") + final class FromNetHandler extends Handler { + public FromNetHandler() { + super(Looper.getMainLooper()); + } + + @SuppressWarnings("unchecked") + @Override + public void handleMessage(Message msg) { + switch(FromNetMsgType.values.get(msg.what)) { + case MSG_LOBBY_JOIN: { + String name = (String)msg.obj; + lobbyPlayerlist.put(name, new Player(name, false, false)); + lobbyChatlog.appendPlayerJoin(name); + break; + } + case MSG_LOBBY_LEAVE: { + Pair args = (Pair)msg.obj; + lobbyPlayerlist.remove(args.first); + lobbyChatlog.appendPlayerLeave(args.first, args.second); + break; + } + case MSG_ROOM_JOIN: { + String name = (String)msg.obj; + Player p = lobbyPlayerlist.get(name); + if(p==null) { + Log.w("Netplay", "Unknown player joined room: "+name); + p = new Player(name, false, false); + } + roomPlayerlist.put(name, new PlayerInRoom(p, false, false)); + roomChatlog.appendPlayerJoin(name); + break; + } + case MSG_ROOM_LEAVE: { + Pair args = (Pair)msg.obj; + roomPlayerlist.remove(args.first); + roomChatlog.appendPlayerLeave(args.first, args.second); + break; + } + case MSG_CLIENT_FLAGS: { + ClientFlagsUpdate upd = (ClientFlagsUpdate)msg.obj; + PlayerInRoom pir = roomPlayerlist.get(upd.nick); + if(pir != null) { + roomPlayerlist.put(upd.nick, upd.applyTo(pir)); + } + Player p = lobbyPlayerlist.get(upd.nick); + if(p != null) { + lobbyPlayerlist.put(upd.nick, upd.applyTo(p)); + } else { + Log.w("Netplay", "Received client flags for unknown player "+upd.nick); + } + if(playerName.equals(upd.nick) && upd.appliesTo(ClientFlagsUpdate.FLAG_CHIEF)) { + netRoomState.setChief(upd.newFlagState); + } + break; + } + case MSG_CHAT: { + Pair args = (Pair)msg.obj; + getCurrentLog().appendChat(args.first, args.second); + for(GameMessageListener listener : gameMessageListeners) { + listener.onChatMessage(args.first, args.second); + } + break; + } + case MSG_MESSAGE: { + getCurrentLog().appendMessage(msg.arg1, (String)msg.obj); + for(GameMessageListener listener : gameMessageListeners) { + listener.onMessage(1, (String)msg.obj); + } + break; + } + case MSG_ROOM_ADD: { + Room room = (Room)msg.obj; + roomList.addRoomWithNewId(room); + break; + } + case MSG_ROOM_UPDATE: { + Pair args = (Pair)msg.obj; + roomList.updateRoom(args.first, args.second); + break; + } + case MSG_ROOM_DELETE: { + roomList.remove((String)msg.obj); + break; + } + case MSG_ROOMLIST: { + Room[] rooms = (Room[])msg.obj; + roomList.updateList(rooms); + break; + } + case MSG_CONNECTED: { + playerName = (String)msg.obj; + changeState(State.LOBBY); + broadcastManager.sendBroadcast(new Intent(ACTION_CONNECTED)); + break; + } + case MSG_DISCONNECTED: { + Pair args = (Pair)msg.obj; + for(GameMessageListener listener : gameMessageListeners) { + listener.onNetDisconnected(); + } + changeState(State.NOT_CONNECTED); + connection = null; + Intent intent = new Intent(ACTION_DISCONNECTED); + intent.putExtra(EXTRA_HAS_ERROR, args.first); + intent.putExtra(EXTRA_MESSAGE, args.second); + broadcastManager.sendBroadcastSync(intent); + break; + } + case MSG_PASSWORD_REQUEST: { + Intent intent = new Intent(ACTION_PASSWORD_REQUESTED); + intent.putExtra(EXTRA_PLAYERNAME, (String)msg.obj); + broadcastManager.sendBroadcast(intent); + break; + } + case MSG_ENTER_ROOM_FROM_LOBBY: { + initRoomState((Boolean)msg.obj); + changeState(State.ROOM); + Intent intent = new Intent(ACTION_ENTERED_ROOM_FROM_LOBBY); + broadcastManager.sendBroadcastSync(intent); + break; + } + case MSG_LEAVE_ROOM: { + changeState(State.LOBBY); + Intent intent = new Intent(ACTION_LEFT_ROOM); + intent.putExtra(EXTRA_MESSAGE, (String)msg.obj); + intent.putExtra(EXTRA_REASON, msg.arg1); + broadcastManager.sendBroadcastSync(intent); + break; + } + case MSG_TEAM_ADDED: { + TeamInGame newTeam = (TeamInGame)msg.obj; + if(isChief()) { + int freeColor = TeamInGame.getUnusedOrRandomColorIndex(netRoomState.getTeams().values()); + sendToNet(MSG_SEND_TEAM_HOG_COUNT, newTeam.ingameAttribs.hogCount, newTeam.team.name); + sendToNet(MSG_SEND_TEAM_COLOR_INDEX, freeColor, newTeam.team.name); + newTeam = newTeam.withAttribs(newTeam.ingameAttribs.withColorIndex(freeColor)); + } + netRoomState.putTeam(newTeam); + break; + } + case MSG_TEAM_DELETED: { + netRoomState.removeTeam((String)msg.obj); + break; + } + case MSG_TEAM_ACCEPTED: { + TeamInGame requestedTeam = netRoomState.requestedTeams.remove(msg.obj); + if(requestedTeam!=null) { + netRoomState.putTeam(requestedTeam); + if(isChief()) { + // Not strictly necessary, but QtFrontend does it... + sendToNet(MSG_SEND_TEAM_HOG_COUNT, requestedTeam.ingameAttribs.hogCount, requestedTeam.team.name); + } + } else { + Log.e("Netplay", "Got accepted message for team that was never requested."); + } + break; + } + case MSG_TEAM_COLOR_CHANGED: { + TeamInGame oldEntry = netRoomState.getTeams().get((String)msg.obj); + if(oldEntry != null) { + /* + * If we are chief, we ignore colors from the outside. They only come from the server + * when someone adds a team then, and we override that choice anyway. + * Worse, that color message arrives *after* we have overridden the color, so it would + * re-override it right back. + */ + if(!isChief()) { + TeamIngameAttributes newAttribs = oldEntry.ingameAttribs.withColorIndex(msg.arg1); + netRoomState.putTeam(oldEntry.withAttribs(newAttribs)); + } + } else { + Log.e("Netplay", "Color update for unknown team "+msg.obj); + } + break; + } + case MSG_HOG_COUNT_CHANGED: { + TeamInGame oldEntry = netRoomState.getTeams().get((String)msg.obj); + if(oldEntry != null) { + TeamIngameAttributes newAttribs = oldEntry.ingameAttribs.withHogCount(msg.arg1); + netRoomState.putTeam(oldEntry.withAttribs(newAttribs)); + } else { + Log.e("Netplay", "Hog count update for unknown team "+msg.obj); + } + break; + } + case MSG_ENGINE_MESSAGE: { + byte[] em = (byte[])msg.obj; + for(GameMessageListener listener : gameMessageListeners) { + listener.onEngineMessage(em); + } + break; + } + case MSG_RUN_GAME: { + GameConfig config = (GameConfig)msg.obj; + for(RunGameListener listener : runGameListeners) { + listener.runGame(config); + } + break; + } + case MSG_MAP_CHANGED: { + netRoomState.setMapRecipe((MapRecipe)msg.obj); + break; + } + case MSG_SCHEME_CHANGED: { + netRoomState.setScheme((Scheme)msg.obj); + break; + } + case MSG_SCRIPT_CHANGED: { + netRoomState.setGameStyle((String)msg.obj); + break; + } + case MSG_WEAPONSET_CHANGED: { + netRoomState.setWeaponset((Weaponset)msg.obj); + break; + } + default: { + Log.e("FromNetHandler", "Unknown message type: "+msg.what); + break; + } + } + } + } +} diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/Roomlist.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/Roomlist.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/Roomlist.java Tue Nov 10 20:43:13 2015 +0100 @@ -27,32 +27,32 @@ import org.hedgewars.hedgeroid.util.ObservableTreeMap; public class Roomlist extends ObservableTreeMap { - private long nextId = 1; - - public void updateList(Room[] newRooms) { - Map newMap = new TreeMap(); - for(Room room : newRooms) { - RoomWithId oldEntry = get(room.name); - if(oldEntry == null) { - newMap.put(room.name, new RoomWithId(room, nextId++)); - } else { - newMap.put(room.name, new RoomWithId(room, oldEntry.id)); - } - } - replaceContent(newMap); - } - - public void addRoomWithNewId(Room room) { - put(room.name, new RoomWithId(room, nextId++)); - } - - public void updateRoom(String name, Room room) { - RoomWithId oldEntry = get(name); - if(oldEntry == null) { - addRoomWithNewId(room); - } else { - remove(name); - put(room.name, new RoomWithId(room, oldEntry.id)); - } - } + private long nextId = 1; + + public void updateList(Room[] newRooms) { + Map newMap = new TreeMap(); + for(Room room : newRooms) { + RoomWithId oldEntry = get(room.name); + if(oldEntry == null) { + newMap.put(room.name, new RoomWithId(room, nextId++)); + } else { + newMap.put(room.name, new RoomWithId(room, oldEntry.id)); + } + } + replaceContent(newMap); + } + + public void addRoomWithNewId(Room room) { + put(room.name, new RoomWithId(room, nextId++)); + } + + public void updateRoom(String name, Room room) { + RoomWithId oldEntry = get(name); + if(oldEntry == null) { + addRoomWithNewId(room); + } else { + remove(name); + put(room.name, new RoomWithId(room, oldEntry.id)); + } + } } diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/RunGameListener.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/RunGameListener.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/RunGameListener.java Tue Nov 10 20:43:13 2015 +0100 @@ -22,5 +22,5 @@ import org.hedgewars.hedgeroid.Datastructures.GameConfig; public interface RunGameListener { - void runGame(GameConfig config); + void runGame(GameConfig config); } diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/ThreadedNetConnection.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/ThreadedNetConnection.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/ThreadedNetConnection.java Tue Nov 10 20:43:13 2015 +0100 @@ -78,501 +78,501 @@ /** * This class handles the actual communication with the networking library, running on a separate thread. - * + * * In order to process net messages, this class regularly runs a tick() function on the frontlib. This * usually happens several times per second, but it can be slowed down a lot if no fast reaction to * events is required (e.g. to conserve battery if the application is in the background). */ class ThreadedNetConnection { - private static final long TICK_INTERVAL_FAST = 100; - private static final long TICK_INTERVAL_SLOW = 5000; - private static final Frontlib FLIB = Flib.INSTANCE; - - public final ToNetHandler toNetHandler; - - private final Context appContext; - private final FromNetHandler fromNetHandler; - private final TickHandler tickHandler; + private static final long TICK_INTERVAL_FAST = 100; + private static final long TICK_INTERVAL_SLOW = 5000; + private static final Frontlib FLIB = Flib.INSTANCE; + + public final ToNetHandler toNetHandler; + + private final Context appContext; + private final FromNetHandler fromNetHandler; + private final TickHandler tickHandler; + + /** + * conn can only be null while connecting (the first thing in the thread), and directly after disconnecting, + * in the same message (the looper is shut down on disconnect, so there will be no messages after that). + */ + private NetconnPtr conn; + private String playerName; + + private ThreadedNetConnection(Context appContext, FromNetHandler fromNetHandler) { + this.appContext = appContext; + this.fromNetHandler = fromNetHandler; + + HandlerThread thread = new HandlerThread("NetThread"); + thread.start(); + toNetHandler = new ToNetHandler(thread.getLooper()); + tickHandler = new TickHandler(thread.getLooper(), TICK_INTERVAL_FAST, tickCb); + } + + private void connect(final String name, final String host, final int port) { + toNetHandler.post(new Runnable() { + public void run() { + playerName = name == null ? "Player" : name; + File dataPath; + try { + dataPath = FileUtils.getDataPathFile(appContext); + } catch (FileNotFoundException e) { + shutdown(true, appContext.getString(R.string.sdcard_not_mounted)); + return; + } + conn = FLIB.flib_netconn_create(playerName, dataPath.getAbsolutePath()+"/", host, port); + if(conn == null) { + shutdown(true, appContext.getString(R.string.error_connection_failed)); + return; + } + + FLIB.flib_netconn_onSchemeChanged(conn, cfgSchemeCb, null); + FLIB.flib_netconn_onClientFlags(conn, clientFlagsCb, null); + FLIB.flib_netconn_onChat(conn, chatCb, null); + FLIB.flib_netconn_onConnected(conn, connectedCb, null); + FLIB.flib_netconn_onDisconnected(conn, disconnectCb, null); + FLIB.flib_netconn_onEngineMessage(conn, engineMessageCb, null); + FLIB.flib_netconn_onEnterRoom(conn, enterRoomCb, null); + FLIB.flib_netconn_onHogCountChanged(conn, hogCountChangedCb, null); + FLIB.flib_netconn_onLeaveRoom(conn, leaveRoomCb, null); + FLIB.flib_netconn_onLobbyJoin(conn, lobbyJoinCb, null); + FLIB.flib_netconn_onLobbyLeave(conn, lobbyLeaveCb, null); + FLIB.flib_netconn_onMapChanged(conn, mapChangedCb, null); + FLIB.flib_netconn_onMessage(conn, messageCb, null); + FLIB.flib_netconn_onPasswordRequest(conn, passwordRequestCb, null); + FLIB.flib_netconn_onRoomAdd(conn, roomAddCb, null); + FLIB.flib_netconn_onRoomDelete(conn, roomDeleteCb, null); + FLIB.flib_netconn_onRoomJoin(conn, roomJoinCb, null); + FLIB.flib_netconn_onRoomLeave(conn, roomLeaveCb, null); + FLIB.flib_netconn_onRoomlist(conn, roomlistCb, null); + FLIB.flib_netconn_onRoomUpdate(conn, roomUpdateCb, null); + FLIB.flib_netconn_onRunGame(conn, runGameCb, null); + FLIB.flib_netconn_onScriptChanged(conn, scriptChangedCb, null); + // FLIB.flib_netconn_onServerVar(conn, serverVarCb, null); + FLIB.flib_netconn_onTeamAccepted(conn, teamAcceptedCb, null); + FLIB.flib_netconn_onTeamAdd(conn, teamAddedCb, null); + FLIB.flib_netconn_onTeamColorChanged(conn, teamColorChangedCb, null); + FLIB.flib_netconn_onTeamDelete(conn, teamDeletedCb, null); + FLIB.flib_netconn_onWeaponsetChanged(conn, weaponsetChangedCb, null); + + tickHandler.start(); + } + }); + } + + public static ThreadedNetConnection startConnection(Context appContext, FromNetHandler fromNetHandler, String playerName, String host, int port) { + ThreadedNetConnection result = new ThreadedNetConnection(appContext, fromNetHandler); + result.connect(playerName, host, port); + return result; + } + + public void setFastTickRate(boolean fastTickRate) { + tickHandler.setInterval(fastTickRate ? TICK_INTERVAL_FAST : TICK_INTERVAL_SLOW); + } + + private final Runnable tickCb = new Runnable() { + public void run() { + FLIB.flib_netconn_tick(conn); + } + }; + + private final SchemeCallback cfgSchemeCb = new SchemeCallback() { + public void callback(Pointer context, SchemePtr schemePtr) { + sendFromNet(MSG_SCHEME_CHANGED, schemePtr.deref()); + } + }; + + private final MapIntCallback mapChangedCb = new MapIntCallback() { + public void callback(Pointer context, MapRecipePtr mapPtr, int updateType) { + sendFromNet(MSG_MAP_CHANGED, updateType, mapPtr.deref()); + } + }; + + private final StrCallback scriptChangedCb = new StrCallback() { + public void callback(Pointer context, String script) { + sendFromNet(MSG_SCRIPT_CHANGED, script); + } + }; + + private final WeaponsetCallback weaponsetChangedCb = new WeaponsetCallback() { + public void callback(Pointer context, WeaponsetPtr weaponsetPtr) { + sendFromNet(MSG_WEAPONSET_CHANGED, weaponsetPtr.deref()); + } + }; - /** - * conn can only be null while connecting (the first thing in the thread), and directly after disconnecting, - * in the same message (the looper is shut down on disconnect, so there will be no messages after that). - */ - private NetconnPtr conn; - private String playerName; - - private ThreadedNetConnection(Context appContext, FromNetHandler fromNetHandler) { - this.appContext = appContext; - this.fromNetHandler = fromNetHandler; - - HandlerThread thread = new HandlerThread("NetThread"); - thread.start(); - toNetHandler = new ToNetHandler(thread.getLooper()); - tickHandler = new TickHandler(thread.getLooper(), TICK_INTERVAL_FAST, tickCb); - } - - private void connect(final String name, final String host, final int port) { - toNetHandler.post(new Runnable() { - public void run() { - playerName = name == null ? "Player" : name; - File dataPath; - try { - dataPath = FileUtils.getDataPathFile(appContext); - } catch (FileNotFoundException e) { - shutdown(true, appContext.getString(R.string.sdcard_not_mounted)); - return; - } - conn = FLIB.flib_netconn_create(playerName, dataPath.getAbsolutePath()+"/", host, port); - if(conn == null) { - shutdown(true, appContext.getString(R.string.error_connection_failed)); - return; - } + private final StrCallback lobbyJoinCb = new StrCallback() { + public void callback(Pointer context, String name) { + sendFromNet(MSG_LOBBY_JOIN, name); + } + }; + + private final StrStrCallback lobbyLeaveCb = new StrStrCallback() { + public void callback(Pointer context, String name, String msg) { + sendFromNet(MSG_LOBBY_LEAVE, Pair.create(name, msg)); + } + }; + + private final StrCallback roomJoinCb = new StrCallback() { + public void callback(Pointer context, String name) { + sendFromNet(MSG_ROOM_JOIN, name); + } + }; + + private final StrStrCallback roomLeaveCb = new StrStrCallback() { + public void callback(Pointer context, String name, String message) { + sendFromNet(MSG_ROOM_LEAVE, Pair.create(name, message)); + } + }; + + private final StrStrBoolCallback clientFlagsCb = new StrStrBoolCallback() { + public void callback(Pointer context, String nick, String flags, boolean newFlagsState) { + sendFromNet(MSG_CLIENT_FLAGS, new ClientFlagsUpdate(nick, flags, newFlagsState)); + } + }; + + private final StrStrCallback chatCb = new StrStrCallback() { + public void callback(Pointer context, String name, String msg) { + sendFromNet(MSG_CHAT, Pair.create(name, msg)); + } + }; + + private final IntStrCallback messageCb = new IntStrCallback() { + public void callback(Pointer context, int type, String msg) { + sendFromNet(MSG_MESSAGE, type, msg); + } + }; + + private final RoomCallback roomAddCb = new RoomCallback() { + public void callback(Pointer context, RoomPtr roomPtr) { + sendFromNet(MSG_ROOM_ADD, roomPtr.deref()); + } + }; + + private final StrRoomCallback roomUpdateCb = new StrRoomCallback() { + public void callback(Pointer context, String name, RoomPtr roomPtr) { + sendFromNet(MSG_ROOM_UPDATE, Pair.create(name, roomPtr.deref())); + } + }; + + private final StrCallback roomDeleteCb = new StrCallback() { + public void callback(Pointer context, final String name) { + sendFromNet(MSG_ROOM_DELETE, name); + } + }; + + private final RoomListCallback roomlistCb = new RoomListCallback() { + public void callback(Pointer context, RoomArrayPtr arg1, int count) { + sendFromNet(MSG_ROOMLIST, arg1.getRooms(count)); + } + }; + + private final VoidCallback connectedCb = new VoidCallback() { + public void callback(Pointer context) { + FLIB.flib_netconn_send_request_roomlist(conn); + playerName = FLIB.flib_netconn_get_playername(conn); + sendFromNet(MSG_CONNECTED, playerName); + } + }; + + private final StrCallback passwordRequestCb = new StrCallback() { + public void callback(Pointer context, String nickname) { + sendFromNet(MSG_PASSWORD_REQUEST, playerName); + } + }; + + private final BoolCallback enterRoomCb = new BoolCallback() { + public void callback(Pointer context, boolean isChief) { + sendFromNet(MSG_ENTER_ROOM_FROM_LOBBY, isChief); + } + }; + + private final IntStrCallback leaveRoomCb = new IntStrCallback() { + public void callback(Pointer context, int reason, String message) { + sendFromNet(MSG_LEAVE_ROOM, reason, message); + } + }; + + private final TeamCallback teamAddedCb = new TeamCallback() { + public void callback(Pointer context, TeamPtr team) { + sendFromNet(MSG_TEAM_ADDED, team.deref()); + } + }; + + private final StrCallback teamDeletedCb = new StrCallback() { + public void callback(Pointer context, String teamName) { + sendFromNet(MSG_TEAM_DELETED, teamName); + } + }; + + private final StrCallback teamAcceptedCb = new StrCallback() { + public void callback(Pointer context, String teamName) { + sendFromNet(MSG_TEAM_ACCEPTED, teamName); + } + }; + + private final StrIntCallback teamColorChangedCb = new StrIntCallback() { + public void callback(Pointer context, String teamName, int colorIndex) { + sendFromNet(MSG_TEAM_COLOR_CHANGED, colorIndex, teamName); + } + }; + + private final StrIntCallback hogCountChangedCb = new StrIntCallback() { + public void callback(Pointer context, String teamName, int hogCount) { + sendFromNet(MSG_HOG_COUNT_CHANGED, hogCount, teamName); + } + }; + + private final BytesCallback engineMessageCb = new BytesCallback() { + public void callback(Pointer context, ByteArrayPtr buffer, NativeSizeT size) { + sendFromNet(MSG_ENGINE_MESSAGE, buffer.deref(size.intValue())); + } + }; - FLIB.flib_netconn_onSchemeChanged(conn, cfgSchemeCb, null); - FLIB.flib_netconn_onClientFlags(conn, clientFlagsCb, null); - FLIB.flib_netconn_onChat(conn, chatCb, null); - FLIB.flib_netconn_onConnected(conn, connectedCb, null); - FLIB.flib_netconn_onDisconnected(conn, disconnectCb, null); - FLIB.flib_netconn_onEngineMessage(conn, engineMessageCb, null); - FLIB.flib_netconn_onEnterRoom(conn, enterRoomCb, null); - FLIB.flib_netconn_onHogCountChanged(conn, hogCountChangedCb, null); - FLIB.flib_netconn_onLeaveRoom(conn, leaveRoomCb, null); - FLIB.flib_netconn_onLobbyJoin(conn, lobbyJoinCb, null); - FLIB.flib_netconn_onLobbyLeave(conn, lobbyLeaveCb, null); - FLIB.flib_netconn_onMapChanged(conn, mapChangedCb, null); - FLIB.flib_netconn_onMessage(conn, messageCb, null); - FLIB.flib_netconn_onPasswordRequest(conn, passwordRequestCb, null); - FLIB.flib_netconn_onRoomAdd(conn, roomAddCb, null); - FLIB.flib_netconn_onRoomDelete(conn, roomDeleteCb, null); - FLIB.flib_netconn_onRoomJoin(conn, roomJoinCb, null); - FLIB.flib_netconn_onRoomLeave(conn, roomLeaveCb, null); - FLIB.flib_netconn_onRoomlist(conn, roomlistCb, null); - FLIB.flib_netconn_onRoomUpdate(conn, roomUpdateCb, null); - FLIB.flib_netconn_onRunGame(conn, runGameCb, null); - FLIB.flib_netconn_onScriptChanged(conn, scriptChangedCb, null); - // FLIB.flib_netconn_onServerVar(conn, serverVarCb, null); - FLIB.flib_netconn_onTeamAccepted(conn, teamAcceptedCb, null); - FLIB.flib_netconn_onTeamAdd(conn, teamAddedCb, null); - FLIB.flib_netconn_onTeamColorChanged(conn, teamColorChangedCb, null); - FLIB.flib_netconn_onTeamDelete(conn, teamDeletedCb, null); - FLIB.flib_netconn_onWeaponsetChanged(conn, weaponsetChangedCb, null); - - tickHandler.start(); - } - }); - } - - public static ThreadedNetConnection startConnection(Context appContext, FromNetHandler fromNetHandler, String playerName, String host, int port) { - ThreadedNetConnection result = new ThreadedNetConnection(appContext, fromNetHandler); - result.connect(playerName, host, port); - return result; - } - - public void setFastTickRate(boolean fastTickRate) { - tickHandler.setInterval(fastTickRate ? TICK_INTERVAL_FAST : TICK_INTERVAL_SLOW); - } - - private final Runnable tickCb = new Runnable() { - public void run() { - FLIB.flib_netconn_tick(conn); - } - }; - - private final SchemeCallback cfgSchemeCb = new SchemeCallback() { - public void callback(Pointer context, SchemePtr schemePtr) { - sendFromNet(MSG_SCHEME_CHANGED, schemePtr.deref()); - } - }; - - private final MapIntCallback mapChangedCb = new MapIntCallback() { - public void callback(Pointer context, MapRecipePtr mapPtr, int updateType) { - sendFromNet(MSG_MAP_CHANGED, updateType, mapPtr.deref()); - } - }; - - private final StrCallback scriptChangedCb = new StrCallback() { - public void callback(Pointer context, String script) { - sendFromNet(MSG_SCRIPT_CHANGED, script); - } - }; - - private final WeaponsetCallback weaponsetChangedCb = new WeaponsetCallback() { - public void callback(Pointer context, WeaponsetPtr weaponsetPtr) { - sendFromNet(MSG_WEAPONSET_CHANGED, weaponsetPtr.deref()); - } - }; - - private final StrCallback lobbyJoinCb = new StrCallback() { - public void callback(Pointer context, String name) { - sendFromNet(MSG_LOBBY_JOIN, name); - } - }; - - private final StrStrCallback lobbyLeaveCb = new StrStrCallback() { - public void callback(Pointer context, String name, String msg) { - sendFromNet(MSG_LOBBY_LEAVE, Pair.create(name, msg)); - } - }; - - private final StrCallback roomJoinCb = new StrCallback() { - public void callback(Pointer context, String name) { - sendFromNet(MSG_ROOM_JOIN, name); - } - }; - - private final StrStrCallback roomLeaveCb = new StrStrCallback() { - public void callback(Pointer context, String name, String message) { - sendFromNet(MSG_ROOM_LEAVE, Pair.create(name, message)); - } - }; - - private final StrStrBoolCallback clientFlagsCb = new StrStrBoolCallback() { - public void callback(Pointer context, String nick, String flags, boolean newFlagsState) { - sendFromNet(MSG_CLIENT_FLAGS, new ClientFlagsUpdate(nick, flags, newFlagsState)); - } - }; - - private final StrStrCallback chatCb = new StrStrCallback() { - public void callback(Pointer context, String name, String msg) { - sendFromNet(MSG_CHAT, Pair.create(name, msg)); - } - }; - - private final IntStrCallback messageCb = new IntStrCallback() { - public void callback(Pointer context, int type, String msg) { - sendFromNet(MSG_MESSAGE, type, msg); - } - }; - - private final RoomCallback roomAddCb = new RoomCallback() { - public void callback(Pointer context, RoomPtr roomPtr) { - sendFromNet(MSG_ROOM_ADD, roomPtr.deref()); - } - }; - - private final StrRoomCallback roomUpdateCb = new StrRoomCallback() { - public void callback(Pointer context, String name, RoomPtr roomPtr) { - sendFromNet(MSG_ROOM_UPDATE, Pair.create(name, roomPtr.deref())); - } - }; - - private final StrCallback roomDeleteCb = new StrCallback() { - public void callback(Pointer context, final String name) { - sendFromNet(MSG_ROOM_DELETE, name); - } - }; - - private final RoomListCallback roomlistCb = new RoomListCallback() { - public void callback(Pointer context, RoomArrayPtr arg1, int count) { - sendFromNet(MSG_ROOMLIST, arg1.getRooms(count)); - } - }; - - private final VoidCallback connectedCb = new VoidCallback() { - public void callback(Pointer context) { - FLIB.flib_netconn_send_request_roomlist(conn); - playerName = FLIB.flib_netconn_get_playername(conn); - sendFromNet(MSG_CONNECTED, playerName); - } - }; - - private final StrCallback passwordRequestCb = new StrCallback() { - public void callback(Pointer context, String nickname) { - sendFromNet(MSG_PASSWORD_REQUEST, playerName); - } - }; - - private final BoolCallback enterRoomCb = new BoolCallback() { - public void callback(Pointer context, boolean isChief) { - sendFromNet(MSG_ENTER_ROOM_FROM_LOBBY, isChief); - } - }; - - private final IntStrCallback leaveRoomCb = new IntStrCallback() { - public void callback(Pointer context, int reason, String message) { - sendFromNet(MSG_LEAVE_ROOM, reason, message); - } - }; - - private final TeamCallback teamAddedCb = new TeamCallback() { - public void callback(Pointer context, TeamPtr team) { - sendFromNet(MSG_TEAM_ADDED, team.deref()); - } - }; - - private final StrCallback teamDeletedCb = new StrCallback() { - public void callback(Pointer context, String teamName) { - sendFromNet(MSG_TEAM_DELETED, teamName); - } - }; - - private final StrCallback teamAcceptedCb = new StrCallback() { - public void callback(Pointer context, String teamName) { - sendFromNet(MSG_TEAM_ACCEPTED, teamName); - } - }; - - private final StrIntCallback teamColorChangedCb = new StrIntCallback() { - public void callback(Pointer context, String teamName, int colorIndex) { - sendFromNet(MSG_TEAM_COLOR_CHANGED, colorIndex, teamName); - } - }; - - private final StrIntCallback hogCountChangedCb = new StrIntCallback() { - public void callback(Pointer context, String teamName, int hogCount) { - sendFromNet(MSG_HOG_COUNT_CHANGED, hogCount, teamName); - } - }; - - private final BytesCallback engineMessageCb = new BytesCallback() { - public void callback(Pointer context, ByteArrayPtr buffer, NativeSizeT size) { - sendFromNet(MSG_ENGINE_MESSAGE, buffer.deref(size.intValue())); - } - }; - - private final VoidCallback runGameCb = new VoidCallback() { - public void callback(Pointer context) { - GameSetupPtr configPtr = FLIB.flib_netconn_create_gamesetup(conn); - sendFromNet(MSG_RUN_GAME, configPtr.deref()); - FLIB.flib_gamesetup_destroy(configPtr); - } - }; - - private void shutdown(boolean error, String message) { - if(conn != null) { - FLIB.flib_netconn_destroy(conn); - conn = null; - } - tickHandler.stop(); - toNetHandler.getLooper().quit(); - sendFromNet(MSG_DISCONNECTED, Pair.create(error, message)); - } - - private final IntStrCallback disconnectCb = new IntStrCallback() { - public void callback(Pointer context, int reason, String message) { - Boolean error = reason != Frontlib.NETCONN_DISCONNECT_NORMAL; - String messageForUser = createDisconnectUserMessage(appContext.getResources(), reason, message); - shutdown(error, messageForUser); - } - }; - - private static String createDisconnectUserMessage(Resources res, int reason, String message) { - switch(reason) { - case Frontlib.NETCONN_DISCONNECT_AUTH_FAILED: - return res.getString(R.string.error_auth_failed); - case Frontlib.NETCONN_DISCONNECT_CONNLOST: - return res.getString(R.string.error_connection_lost); - case Frontlib.NETCONN_DISCONNECT_INTERNAL_ERROR: - return res.getString(R.string.error_unexpected, message); - case Frontlib.NETCONN_DISCONNECT_SERVER_TOO_OLD: - return res.getString(R.string.error_server_too_old); - default: - return message; - } - } - - private boolean sendFromNet(FromNetMsgType what, Object obj) { - return fromNetHandler.sendMessage(fromNetHandler.obtainMessage(what.ordinal(), obj)); - } - - private boolean sendFromNet(FromNetMsgType what, int arg1, Object obj) { - return fromNetHandler.sendMessage(fromNetHandler.obtainMessage(what.ordinal(), arg1, 0, obj)); - } - - static enum ToNetMsgType { - MSG_SEND_NICK, - MSG_SEND_PASSWORD, - MSG_SEND_QUIT, - MSG_SEND_ROOMLIST_REQUEST, - MSG_SEND_PLAYER_INFO_REQUEST, - MSG_SEND_CHAT, - MSG_SEND_TEAMCHAT, - MSG_SEND_FOLLOW_PLAYER, - MSG_SEND_JOIN_ROOM, - MSG_SEND_CREATE_ROOM, - MSG_SEND_LEAVE_ROOM, - MSG_SEND_KICK, - MSG_SEND_ADD_TEAM, - MSG_SEND_REMOVE_TEAM, - MSG_DISCONNECT, - MSG_SEND_TEAM_COLOR_INDEX, - MSG_SEND_TEAM_HOG_COUNT, - MSG_SEND_ENGINE_MESSAGE, - MSG_SEND_ROUND_FINISHED, - MSG_SEND_TOGGLE_READY, - MSG_SEND_START_GAME, - MSG_SEND_WEAPONSET, - MSG_SEND_MAP, - MSG_SEND_MAP_NAME, - MSG_SEND_MAP_GENERATOR, - MSG_SEND_MAP_TEMPLATE, - MSG_SEND_MAZE_SIZE, - MSG_SEND_MAP_SEED, - MSG_SEND_MAP_THEME, - MSG_SEND_MAP_DRAWDATA, - MSG_SEND_GAMESTYLE, - MSG_SEND_SCHEME; - - static final List values = Collections.unmodifiableList(Arrays.asList(ToNetMsgType.values())); - } - - /** - * Processes messages to the networking system. Runs on a non-main thread. - */ - @SuppressLint("HandlerLeak") - public final class ToNetHandler extends Handler { - - public ToNetHandler(Looper looper) { - super(looper); - } - - @Override - public void handleMessage(Message msg) { - switch(ToNetMsgType.values.get(msg.what)) { - case MSG_SEND_NICK: { - FLIB.flib_netconn_send_nick(conn, (String)msg.obj); - break; - } - case MSG_SEND_PASSWORD: { - FLIB.flib_netconn_send_password(conn, (String)msg.obj); - break; - } - case MSG_SEND_QUIT: { - FLIB.flib_netconn_send_quit(conn, (String)msg.obj); - break; - } - case MSG_SEND_ROOMLIST_REQUEST: { - FLIB.flib_netconn_send_request_roomlist(conn); - break; - } - case MSG_SEND_PLAYER_INFO_REQUEST: { - FLIB.flib_netconn_send_playerInfo(conn, (String)msg.obj); - break; - } - case MSG_SEND_CHAT: { - if(FLIB.flib_netconn_send_chat(conn, (String)msg.obj) == 0) { - sendFromNet(MSG_CHAT, Pair.create(playerName, (String)msg.obj)); - } - break; - } - case MSG_SEND_TEAMCHAT: { - FLIB.flib_netconn_send_teamchat(conn, (String)msg.obj); - break; - } - case MSG_SEND_FOLLOW_PLAYER: { - FLIB.flib_netconn_send_playerFollow(conn, (String)msg.obj); - break; - } - case MSG_SEND_JOIN_ROOM: { - FLIB.flib_netconn_send_joinRoom(conn, (String)msg.obj); - break; - } - case MSG_SEND_CREATE_ROOM: { - FLIB.flib_netconn_send_createRoom(conn, (String)msg.obj); - break; - } - case MSG_SEND_LEAVE_ROOM: { - if(FLIB.flib_netconn_send_leaveRoom(conn, (String)msg.obj) == 0) { - sendFromNet(MSG_LEAVE_ROOM, -1, ""); - } - break; - } - case MSG_SEND_KICK: { - FLIB.flib_netconn_send_kick(conn, (String)msg.obj); - break; - } - case MSG_SEND_ADD_TEAM: { - FLIB.flib_netconn_send_addTeam(conn, TeamPtr.createJavaOwned((TeamInGame)msg.obj)); - break; - } - case MSG_SEND_REMOVE_TEAM: { - if(FLIB.flib_netconn_send_removeTeam(conn, (String)msg.obj)==0) { - sendFromNet(MSG_TEAM_DELETED, msg.obj); - } - break; - } - case MSG_DISCONNECT: { - FLIB.flib_netconn_send_quit(conn, (String)msg.obj); - shutdown(false, "User quit"); - break; - } - case MSG_SEND_TEAM_COLOR_INDEX: { - FLIB.flib_netconn_send_teamColor(conn, (String)msg.obj, msg.arg1); - break; - } - case MSG_SEND_TEAM_HOG_COUNT: { - FLIB.flib_netconn_send_teamHogCount(conn, (String)msg.obj, msg.arg1); - break; - } - case MSG_SEND_ENGINE_MESSAGE: { - byte[] message = (byte[])msg.obj; - ByteArrayPtr ptr = ByteArrayPtr.createJavaOwned(message); - FLIB.flib_netconn_send_engineMessage(conn, ptr, NativeSizeT.valueOf(message.length)); - break; - } - case MSG_SEND_ROUND_FINISHED: { - FLIB.flib_netconn_send_roundfinished(conn, (Boolean)msg.obj); - break; - } - case MSG_SEND_TOGGLE_READY: { - FLIB.flib_netconn_send_toggleReady(conn); - break; - } - case MSG_SEND_START_GAME: { - FLIB.flib_netconn_send_startGame(conn); - break; - } - case MSG_SEND_WEAPONSET: { - FLIB.flib_netconn_send_weaponset(conn, WeaponsetPtr.createJavaOwned((Weaponset)msg.obj)); - break; - } - case MSG_SEND_MAP: { - FLIB.flib_netconn_send_map(conn, MapRecipePtr.createJavaOwned((MapRecipe)msg.obj)); - break; - } - case MSG_SEND_MAP_NAME: { - FLIB.flib_netconn_send_mapName(conn, (String)msg.obj); - break; - } - case MSG_SEND_MAP_GENERATOR: { - FLIB.flib_netconn_send_mapGen(conn, msg.arg1); - break; - } - case MSG_SEND_MAP_TEMPLATE: { - FLIB.flib_netconn_send_mapTemplate(conn, msg.arg1); - break; - } - case MSG_SEND_MAZE_SIZE: { - FLIB.flib_netconn_send_mapMazeSize(conn, msg.arg1); - break; - } - case MSG_SEND_MAP_SEED: { - FLIB.flib_netconn_send_mapSeed(conn, (String) msg.obj); - break; - } - case MSG_SEND_MAP_THEME: { - FLIB.flib_netconn_send_mapTheme(conn, (String) msg.obj); - break; - } - case MSG_SEND_MAP_DRAWDATA: { - byte[] message = (byte[])msg.obj; - ByteArrayPtr ptr = ByteArrayPtr.createJavaOwned(message); - FLIB.flib_netconn_send_mapDrawdata(conn, ptr, NativeSizeT.valueOf(message.length)); - break; - } - case MSG_SEND_GAMESTYLE: { - FLIB.flib_netconn_send_script(conn, (String) msg.obj); - break; - } - case MSG_SEND_SCHEME: { - FLIB.flib_netconn_send_scheme(conn, SchemePtr.createJavaOwned((Scheme) msg.obj)); - break; - } - default: { - Log.e("ToNetHandler", "Unknown message type: "+msg.what); - break; - } - } - } - } + private final VoidCallback runGameCb = new VoidCallback() { + public void callback(Pointer context) { + GameSetupPtr configPtr = FLIB.flib_netconn_create_gamesetup(conn); + sendFromNet(MSG_RUN_GAME, configPtr.deref()); + FLIB.flib_gamesetup_destroy(configPtr); + } + }; + + private void shutdown(boolean error, String message) { + if(conn != null) { + FLIB.flib_netconn_destroy(conn); + conn = null; + } + tickHandler.stop(); + toNetHandler.getLooper().quit(); + sendFromNet(MSG_DISCONNECTED, Pair.create(error, message)); + } + + private final IntStrCallback disconnectCb = new IntStrCallback() { + public void callback(Pointer context, int reason, String message) { + Boolean error = reason != Frontlib.NETCONN_DISCONNECT_NORMAL; + String messageForUser = createDisconnectUserMessage(appContext.getResources(), reason, message); + shutdown(error, messageForUser); + } + }; + + private static String createDisconnectUserMessage(Resources res, int reason, String message) { + switch(reason) { + case Frontlib.NETCONN_DISCONNECT_AUTH_FAILED: + return res.getString(R.string.error_auth_failed); + case Frontlib.NETCONN_DISCONNECT_CONNLOST: + return res.getString(R.string.error_connection_lost); + case Frontlib.NETCONN_DISCONNECT_INTERNAL_ERROR: + return res.getString(R.string.error_unexpected, message); + case Frontlib.NETCONN_DISCONNECT_SERVER_TOO_OLD: + return res.getString(R.string.error_server_too_old); + default: + return message; + } + } + + private boolean sendFromNet(FromNetMsgType what, Object obj) { + return fromNetHandler.sendMessage(fromNetHandler.obtainMessage(what.ordinal(), obj)); + } + + private boolean sendFromNet(FromNetMsgType what, int arg1, Object obj) { + return fromNetHandler.sendMessage(fromNetHandler.obtainMessage(what.ordinal(), arg1, 0, obj)); + } + + static enum ToNetMsgType { + MSG_SEND_NICK, + MSG_SEND_PASSWORD, + MSG_SEND_QUIT, + MSG_SEND_ROOMLIST_REQUEST, + MSG_SEND_PLAYER_INFO_REQUEST, + MSG_SEND_CHAT, + MSG_SEND_TEAMCHAT, + MSG_SEND_FOLLOW_PLAYER, + MSG_SEND_JOIN_ROOM, + MSG_SEND_CREATE_ROOM, + MSG_SEND_LEAVE_ROOM, + MSG_SEND_KICK, + MSG_SEND_ADD_TEAM, + MSG_SEND_REMOVE_TEAM, + MSG_DISCONNECT, + MSG_SEND_TEAM_COLOR_INDEX, + MSG_SEND_TEAM_HOG_COUNT, + MSG_SEND_ENGINE_MESSAGE, + MSG_SEND_ROUND_FINISHED, + MSG_SEND_TOGGLE_READY, + MSG_SEND_START_GAME, + MSG_SEND_WEAPONSET, + MSG_SEND_MAP, + MSG_SEND_MAP_NAME, + MSG_SEND_MAP_GENERATOR, + MSG_SEND_MAP_TEMPLATE, + MSG_SEND_MAZE_SIZE, + MSG_SEND_MAP_SEED, + MSG_SEND_MAP_THEME, + MSG_SEND_MAP_DRAWDATA, + MSG_SEND_GAMESTYLE, + MSG_SEND_SCHEME; + + static final List values = Collections.unmodifiableList(Arrays.asList(ToNetMsgType.values())); + } + + /** + * Processes messages to the networking system. Runs on a non-main thread. + */ + @SuppressLint("HandlerLeak") + public final class ToNetHandler extends Handler { + + public ToNetHandler(Looper looper) { + super(looper); + } + + @Override + public void handleMessage(Message msg) { + switch(ToNetMsgType.values.get(msg.what)) { + case MSG_SEND_NICK: { + FLIB.flib_netconn_send_nick(conn, (String)msg.obj); + break; + } + case MSG_SEND_PASSWORD: { + FLIB.flib_netconn_send_password(conn, (String)msg.obj); + break; + } + case MSG_SEND_QUIT: { + FLIB.flib_netconn_send_quit(conn, (String)msg.obj); + break; + } + case MSG_SEND_ROOMLIST_REQUEST: { + FLIB.flib_netconn_send_request_roomlist(conn); + break; + } + case MSG_SEND_PLAYER_INFO_REQUEST: { + FLIB.flib_netconn_send_playerInfo(conn, (String)msg.obj); + break; + } + case MSG_SEND_CHAT: { + if(FLIB.flib_netconn_send_chat(conn, (String)msg.obj) == 0) { + sendFromNet(MSG_CHAT, Pair.create(playerName, (String)msg.obj)); + } + break; + } + case MSG_SEND_TEAMCHAT: { + FLIB.flib_netconn_send_teamchat(conn, (String)msg.obj); + break; + } + case MSG_SEND_FOLLOW_PLAYER: { + FLIB.flib_netconn_send_playerFollow(conn, (String)msg.obj); + break; + } + case MSG_SEND_JOIN_ROOM: { + FLIB.flib_netconn_send_joinRoom(conn, (String)msg.obj); + break; + } + case MSG_SEND_CREATE_ROOM: { + FLIB.flib_netconn_send_createRoom(conn, (String)msg.obj); + break; + } + case MSG_SEND_LEAVE_ROOM: { + if(FLIB.flib_netconn_send_leaveRoom(conn, (String)msg.obj) == 0) { + sendFromNet(MSG_LEAVE_ROOM, -1, ""); + } + break; + } + case MSG_SEND_KICK: { + FLIB.flib_netconn_send_kick(conn, (String)msg.obj); + break; + } + case MSG_SEND_ADD_TEAM: { + FLIB.flib_netconn_send_addTeam(conn, TeamPtr.createJavaOwned((TeamInGame)msg.obj)); + break; + } + case MSG_SEND_REMOVE_TEAM: { + if(FLIB.flib_netconn_send_removeTeam(conn, (String)msg.obj)==0) { + sendFromNet(MSG_TEAM_DELETED, msg.obj); + } + break; + } + case MSG_DISCONNECT: { + FLIB.flib_netconn_send_quit(conn, (String)msg.obj); + shutdown(false, "User quit"); + break; + } + case MSG_SEND_TEAM_COLOR_INDEX: { + FLIB.flib_netconn_send_teamColor(conn, (String)msg.obj, msg.arg1); + break; + } + case MSG_SEND_TEAM_HOG_COUNT: { + FLIB.flib_netconn_send_teamHogCount(conn, (String)msg.obj, msg.arg1); + break; + } + case MSG_SEND_ENGINE_MESSAGE: { + byte[] message = (byte[])msg.obj; + ByteArrayPtr ptr = ByteArrayPtr.createJavaOwned(message); + FLIB.flib_netconn_send_engineMessage(conn, ptr, NativeSizeT.valueOf(message.length)); + break; + } + case MSG_SEND_ROUND_FINISHED: { + FLIB.flib_netconn_send_roundfinished(conn, (Boolean)msg.obj); + break; + } + case MSG_SEND_TOGGLE_READY: { + FLIB.flib_netconn_send_toggleReady(conn); + break; + } + case MSG_SEND_START_GAME: { + FLIB.flib_netconn_send_startGame(conn); + break; + } + case MSG_SEND_WEAPONSET: { + FLIB.flib_netconn_send_weaponset(conn, WeaponsetPtr.createJavaOwned((Weaponset)msg.obj)); + break; + } + case MSG_SEND_MAP: { + FLIB.flib_netconn_send_map(conn, MapRecipePtr.createJavaOwned((MapRecipe)msg.obj)); + break; + } + case MSG_SEND_MAP_NAME: { + FLIB.flib_netconn_send_mapName(conn, (String)msg.obj); + break; + } + case MSG_SEND_MAP_GENERATOR: { + FLIB.flib_netconn_send_mapGen(conn, msg.arg1); + break; + } + case MSG_SEND_MAP_TEMPLATE: { + FLIB.flib_netconn_send_mapTemplate(conn, msg.arg1); + break; + } + case MSG_SEND_MAZE_SIZE: { + FLIB.flib_netconn_send_mapMazeSize(conn, msg.arg1); + break; + } + case MSG_SEND_MAP_SEED: { + FLIB.flib_netconn_send_mapSeed(conn, (String) msg.obj); + break; + } + case MSG_SEND_MAP_THEME: { + FLIB.flib_netconn_send_mapTheme(conn, (String) msg.obj); + break; + } + case MSG_SEND_MAP_DRAWDATA: { + byte[] message = (byte[])msg.obj; + ByteArrayPtr ptr = ByteArrayPtr.createJavaOwned(message); + FLIB.flib_netconn_send_mapDrawdata(conn, ptr, NativeSizeT.valueOf(message.length)); + break; + } + case MSG_SEND_GAMESTYLE: { + FLIB.flib_netconn_send_script(conn, (String) msg.obj); + break; + } + case MSG_SEND_SCHEME: { + FLIB.flib_netconn_send_scheme(conn, SchemePtr.createJavaOwned((Scheme) msg.obj)); + break; + } + default: { + Log.e("ToNetHandler", "Unknown message type: "+msg.what); + break; + } + } + } + } } \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/util/CalmDownHandler.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/util/CalmDownHandler.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/util/CalmDownHandler.java Tue Nov 10 20:43:13 2015 +0100 @@ -32,31 +32,31 @@ * information change. */ public final class CalmDownHandler extends Handler { - int runningMessagesCounter = 0; - final Runnable inactivityRunnable; - final long inactivityMs; - boolean stopped; + int runningMessagesCounter = 0; + final Runnable inactivityRunnable; + final long inactivityMs; + boolean stopped; + + public CalmDownHandler(Looper looper, Runnable runnable, long inactivityMs) { + super(looper); + this.inactivityRunnable = runnable; + this.inactivityMs = inactivityMs; + } - public CalmDownHandler(Looper looper, Runnable runnable, long inactivityMs) { - super(looper); - this.inactivityRunnable = runnable; - this.inactivityMs = inactivityMs; - } - - public void activity() { - runningMessagesCounter++; - sendMessageDelayed(obtainMessage(), inactivityMs); - } - - @Override - public void handleMessage(Message msg) { - runningMessagesCounter--; - if(runningMessagesCounter==0 && !stopped) { - inactivityRunnable.run(); - } - } - - public void stop() { - stopped = true; - } + public void activity() { + runningMessagesCounter++; + sendMessageDelayed(obtainMessage(), inactivityMs); + } + + @Override + public void handleMessage(Message msg) { + runningMessagesCounter--; + if(runningMessagesCounter==0 && !stopped) { + inactivityRunnable.run(); + } + } + + public void stop() { + stopped = true; + } } \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/util/FileUtils.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/util/FileUtils.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/util/FileUtils.java Tue Nov 10 20:43:13 2015 +0100 @@ -40,220 +40,220 @@ import android.util.Log; public class FileUtils { - private static final String ROOT_DIR = "Data"; - private static final String TAG = FileUtils.class.getSimpleName(); + private static final String ROOT_DIR = "Data"; + private static final String TAG = FileUtils.class.getSimpleName(); + + /** + * @return true if the data path is currently available. However, it can vanish at any time so + * normally you should just try to use it and rely on the exceptions. + */ + public static boolean isDataPathAvailable() { + return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()); + } - /** - * @return true if the data path is currently available. However, it can vanish at any time so - * normally you should just try to use it and rely on the exceptions. - */ - public static boolean isDataPathAvailable() { - return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()); - } - - /** - * get the path to which we should download all the data files - * @param c context - * @return The directory - * @throws FileNotFoundException if external storage is not available at the moment - */ - public static File getCachePath(Context c) throws FileNotFoundException { - File cachePath = null; - if(Build.VERSION.SDK_INT < 8){//8 == Build.VERSION_CODES.FROYO - cachePath = PreFroyoSDCardDir.getDownloadPath(c); - } else { - cachePath = FroyoSDCardDir.getDownloadPath(c); - } - if(cachePath==null) { - throw new FileNotFoundException("External storage is currently unavailable"); - } else { - return cachePath; - } - } + /** + * get the path to which we should download all the data files + * @param c context + * @return The directory + * @throws FileNotFoundException if external storage is not available at the moment + */ + public static File getCachePath(Context c) throws FileNotFoundException { + File cachePath = null; + if(Build.VERSION.SDK_INT < 8){//8 == Build.VERSION_CODES.FROYO + cachePath = PreFroyoSDCardDir.getDownloadPath(c); + } else { + cachePath = FroyoSDCardDir.getDownloadPath(c); + } + if(cachePath==null) { + throw new FileNotFoundException("External storage is currently unavailable"); + } else { + return cachePath; + } + } - public static File getDataPathFile(Context c, String...subpath) throws FileNotFoundException { - File file = new File(getCachePath(c), ROOT_DIR); - for(String pathcomponent : subpath) { - file = new File(file, pathcomponent); - } - return file; - } - - @TargetApi(8) - private static class FroyoSDCardDir{ - public static File getDownloadPath(Context c){ - return c.getExternalCacheDir(); - } - } + public static File getDataPathFile(Context c, String...subpath) throws FileNotFoundException { + File file = new File(getCachePath(c), ROOT_DIR); + for(String pathcomponent : subpath) { + file = new File(file, pathcomponent); + } + return file; + } + + @TargetApi(8) + private static class FroyoSDCardDir{ + public static File getDownloadPath(Context c){ + return c.getExternalCacheDir(); + } + } - private static class PreFroyoSDCardDir{ - public static File getDownloadPath(Context c){ - if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){ - File extStorageDir = Environment.getExternalStorageDirectory(); - if(extStorageDir != null) { - return new File(extStorageDir, "Hedgewars"); - } - } - return null; - } - } + private static class PreFroyoSDCardDir{ + public static File getDownloadPath(Context c){ + if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){ + File extStorageDir = Environment.getExternalStorageDirectory(); + if(extStorageDir != null) { + return new File(extStorageDir, "Hedgewars"); + } + } + return null; + } + } - /** - * Return a File array with all the files from dirName - * @param c - * @param dirName - * @return - * @throws FileNotFoundException If the sdcard is not available or the subdirectory "dirName" does not exist - */ - public static File[] getFilesFromRelativeDir(Context c, String dirName) throws FileNotFoundException { - File f = getDataPathFile(c, dirName); + /** + * Return a File array with all the files from dirName + * @param c + * @param dirName + * @return + * @throws FileNotFoundException If the sdcard is not available or the subdirectory "dirName" does not exist + */ + public static File[] getFilesFromRelativeDir(Context c, String dirName) throws FileNotFoundException { + File f = getDataPathFile(c, dirName); - if(f.isDirectory()) { - return f.listFiles(); - } else { - throw new FileNotFoundException("Directory "+dirName+" does not exist."); - } - } + if(f.isDirectory()) { + return f.listFiles(); + } else { + throw new FileNotFoundException("Directory "+dirName+" does not exist."); + } + } - /** - * Checks if this directory has a file with suffix suffix - * @param f - directory - * @return - */ - public static boolean hasFileWithSuffix(File f, String suffix){ - if(f.isDirectory()){ - for(String s : f.list()){ - if(s.endsWith(suffix)) return true; - } - return false; - }else{ - return false; - } - } + /** + * Checks if this directory has a file with suffix suffix + * @param f - directory + * @return + */ + public static boolean hasFileWithSuffix(File f, String suffix){ + if(f.isDirectory()){ + for(String s : f.list()){ + if(s.endsWith(suffix)) return true; + } + return false; + }else{ + return false; + } + } - /** - * Gives back all dirs which contain a file with suffix fileSuffix - * @param c - * @param path - * @param fileSuffix - * @return - * @throws FileNotFoundException If the sdcard is not available or the subdirectory "path" does not exist - */ - public static List getDirsWithFileSuffix(Context c, String path, String fileSuffix) throws FileNotFoundException{ - File[] files = getFilesFromRelativeDir(c,path); - ArrayList ret = new ArrayList(); + /** + * Gives back all dirs which contain a file with suffix fileSuffix + * @param c + * @param path + * @param fileSuffix + * @return + * @throws FileNotFoundException If the sdcard is not available or the subdirectory "path" does not exist + */ + public static List getDirsWithFileSuffix(Context c, String path, String fileSuffix) throws FileNotFoundException{ + File[] files = getFilesFromRelativeDir(c,path); + ArrayList ret = new ArrayList(); - for(File f : files){ - if(hasFileWithSuffix(f, fileSuffix)) ret.add(f.getName()); - } - return ret; - } + for(File f : files){ + if(hasFileWithSuffix(f, fileSuffix)) ret.add(f.getName()); + } + return ret; + } - /** - * Get all files from directory dir which have the given suffix - * @throws FileNotFoundException If the sdcard is not available or the subdirectory "dir" does not exist - */ - public static List getFileNamesFromDirWithSuffix(Context c, String dir, String suffix, boolean removeSuffix) throws FileNotFoundException{ - File[] files = FileUtils.getFilesFromRelativeDir(c, dir); - List ret = new ArrayList(); - for(File file : files){ - String s = file.getName(); - if(s.endsWith(suffix)){ - if(removeSuffix) ret.add(s.substring(0, s.length()-suffix.length())); - else ret.add(s); - } - } - return ret; - } + /** + * Get all files from directory dir which have the given suffix + * @throws FileNotFoundException If the sdcard is not available or the subdirectory "dir" does not exist + */ + public static List getFileNamesFromDirWithSuffix(Context c, String dir, String suffix, boolean removeSuffix) throws FileNotFoundException{ + File[] files = FileUtils.getFilesFromRelativeDir(c, dir); + List ret = new ArrayList(); + for(File file : files){ + String s = file.getName(); + if(s.endsWith(suffix)){ + if(removeSuffix) ret.add(s.substring(0, s.length()-suffix.length())); + else ret.add(s); + } + } + return ret; + } + + /** + * Close a resource (possibly null), ignoring any IOException. + */ + public static void closeQuietly(Closeable c) { + if(c!=null) { + try { + c.close(); + } catch(IOException e) { + Log.w(TAG, e); + } + } + } + + /** + * Write all data from the input stream to the file, creating or overwriting it. + * The input stream will be closed. + * + * @throws IOException + */ + public static void writeStreamToFile(InputStream is, File file) throws IOException { + OutputStream os = null; + byte[] buffer = new byte[8192]; + try { + os = new FileOutputStream(file); + int size; + while((size=is.read(buffer)) != -1) { + os.write(buffer, 0, size); + } + os.close(); // Important to close this non-quietly, in case of exceptions when flushing + } finally { + FileUtils.closeQuietly(is); + FileUtils.closeQuietly(os); + } + } - /** - * Close a resource (possibly null), ignoring any IOException. - */ - public static void closeQuietly(Closeable c) { - if(c!=null) { - try { - c.close(); - } catch(IOException e) { - Log.w(TAG, e); - } - } - } - - /** - * Write all data from the input stream to the file, creating or overwriting it. - * The input stream will be closed. - * - * @throws IOException - */ - public static void writeStreamToFile(InputStream is, File file) throws IOException { - OutputStream os = null; - byte[] buffer = new byte[8192]; - try { - os = new FileOutputStream(file); - int size; - while((size=is.read(buffer)) != -1) { - os.write(buffer, 0, size); - } - os.close(); // Important to close this non-quietly, in case of exceptions when flushing - } finally { - FileUtils.closeQuietly(is); - FileUtils.closeQuietly(os); - } - } - - /** - * Moves resources pointed to by sourceResId (from @res/raw/) to the app's private data directory - * @param c - * @param sourceResId - * @param directory - */ - public static void resRawToFilesDir(Context c, int sourceResId, int targetFilenames, String directory) throws IOException { - File targetDir = new File(c.getFilesDir(), directory); - targetDir.mkdirs(); + /** + * Moves resources pointed to by sourceResId (from @res/raw/) to the app's private data directory + * @param c + * @param sourceResId + * @param directory + */ + public static void resRawToFilesDir(Context c, int sourceResId, int targetFilenames, String directory) throws IOException { + File targetDir = new File(c.getFilesDir(), directory); + targetDir.mkdirs(); + + //Get an array with the resource files ID + Resources resources = c.getResources(); + TypedArray ta = resources.obtainTypedArray(sourceResId); + TypedArray filenames = resources.obtainTypedArray(targetFilenames); + for(int i = 0; i < ta.length(); i++){ + int resId = ta.getResourceId(i, 0); + String fileName = filenames.getString(i); + File f = new File(targetDir, fileName); + writeStreamToFile(resources.openRawResource(resId), f); + } + } - //Get an array with the resource files ID - Resources resources = c.getResources(); - TypedArray ta = resources.obtainTypedArray(sourceResId); - TypedArray filenames = resources.obtainTypedArray(targetFilenames); - for(int i = 0; i < ta.length(); i++){ - int resId = ta.getResourceId(i, 0); - String fileName = filenames.getString(i); - File f = new File(targetDir, fileName); - writeStreamToFile(resources.openRawResource(resId), f); - } - } + public static String readToString(InputStream is) throws IOException { + try { + ByteArrayOutputStream os = new ByteArrayOutputStream(); + byte[] buffer = new byte[8192]; + int size; + while((size=is.read(buffer)) != -1) { + os.write(buffer, 0, size); + } + return new String(os.toByteArray()); + } finally { + closeQuietly(is); + } + } + + private static final char[] badFilenameChars = new char[] { '/', '\\', ':', '*', '?', '\"', '<', '>', '|', '.', '\0' }; - public static String readToString(InputStream is) throws IOException { - try { - ByteArrayOutputStream os = new ByteArrayOutputStream(); - byte[] buffer = new byte[8192]; - int size; - while((size=is.read(buffer)) != -1) { - os.write(buffer, 0, size); - } - return new String(os.toByteArray()); - } finally { - closeQuietly(is); - } - } - - private static final char[] badFilenameChars = new char[] { '/', '\\', ':', '*', '?', '\"', '<', '>', '|', '.', '\0' }; - - /** - * Modify the given String so that it can be used as part of a filename - * without causing problems from illegal/special characters. - * - * The result should be similar to the input, but isn't necessarily - * reversible. - */ - public static String replaceBadChars(String name) { - if (name == null || name.trim().length()==0) { - return "_"; - } - name = name.trim(); - for (char badChar : badFilenameChars) { - name = name.replace(badChar, '_'); - } - return name; - } + /** + * Modify the given String so that it can be used as part of a filename + * without causing problems from illegal/special characters. + * + * The result should be similar to the input, but isn't necessarily + * reversible. + */ + public static String replaceBadChars(String name) { + if (name == null || name.trim().length()==0) { + return "_"; + } + name = name.trim(); + for (char badChar : badFilenameChars) { + name = name.replace(badChar, '_'); + } + return name; + } } diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/util/ObjectUtils.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/util/ObjectUtils.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/util/ObjectUtils.java Tue Nov 10 20:43:13 2015 +0100 @@ -20,13 +20,13 @@ package org.hedgewars.hedgeroid.util; public final class ObjectUtils { - public static boolean equal(Object o1, Object o2) { - if(o1==o2) { - return true; - } else if(o1==null || o2 == null) { - return false; - } else { - return o1.equals(o2); - } - } + public static boolean equal(Object o1, Object o2) { + if(o1==o2) { + return true; + } else if(o1==null || o2 == null) { + return false; + } else { + return o1.equals(o2); + } + } } diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/util/ObservableTreeMap.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/util/ObservableTreeMap.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/util/ObservableTreeMap.java Tue Nov 10 20:43:13 2015 +0100 @@ -26,37 +26,37 @@ import android.database.DataSetObservable; public class ObservableTreeMap extends DataSetObservable { - private final Map map = new TreeMap(); - - public void replaceContent(Map newMap) { - map.clear(); - map.putAll(newMap); - notifyChanged(); - } - - public void put(K key, V value) { - map.put(key, value); - notifyChanged(); - } - - public V get(K key) { - return map.get(key); - } - - public void remove(K key) { - if(map.remove(key) != null) { - notifyChanged(); - } - } - - public void clear() { - if(!map.isEmpty()) { - map.clear(); - notifyChanged(); - } - } - - public Map getMap() { - return Collections.unmodifiableMap(map); - } + private final Map map = new TreeMap(); + + public void replaceContent(Map newMap) { + map.clear(); + map.putAll(newMap); + notifyChanged(); + } + + public void put(K key, V value) { + map.put(key, value); + notifyChanged(); + } + + public V get(K key) { + return map.get(key); + } + + public void remove(K key) { + if(map.remove(key) != null) { + notifyChanged(); + } + } + + public void clear() { + if(!map.isEmpty()) { + map.clear(); + notifyChanged(); + } + } + + public Map getMap() { + return Collections.unmodifiableMap(map); + } } diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/util/ObservableTreeMapAdapter.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/util/ObservableTreeMapAdapter.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/util/ObservableTreeMapAdapter.java Tue Nov 10 20:43:13 2015 +0100 @@ -28,67 +28,67 @@ import android.widget.BaseAdapter; public abstract class ObservableTreeMapAdapter extends BaseAdapter { - private boolean sourceChanged = true; - private List entries = new ArrayList(); - private ObservableTreeMap source; - - private DataSetObserver observer = new DataSetObserver() { - @Override - public void onChanged() { - sourceChanged = true; - notifyDataSetChanged(); - } - - @Override - public void onInvalidated() { - invalidate(); - } - }; - - abstract protected Comparator getEntryOrder(); - - protected List getEntries() { - if(sourceChanged) { - entries.clear(); - entries.addAll(source.getMap().values()); - Collections.sort(entries, getEntryOrder()); - sourceChanged = false; - } - return entries; - } - - public int getCount() { - return getEntries().size(); - } + private boolean sourceChanged = true; + private List entries = new ArrayList(); + private ObservableTreeMap source; + + private DataSetObserver observer = new DataSetObserver() { + @Override + public void onChanged() { + sourceChanged = true; + notifyDataSetChanged(); + } + + @Override + public void onInvalidated() { + invalidate(); + } + }; + + abstract protected Comparator getEntryOrder(); + + protected List getEntries() { + if(sourceChanged) { + entries.clear(); + entries.addAll(source.getMap().values()); + Collections.sort(entries, getEntryOrder()); + sourceChanged = false; + } + return entries; + } - public V getItem(int position) { - return getEntries().get(position); - } - - public long getItemId(int position) { - return position; - } - - @Override - public boolean hasStableIds() { - return false; - } - - public void setSource(ObservableTreeMap source) { - if(this.source != null) { - this.source.unregisterObserver(observer); - } - this.source = source; - this.source.registerObserver(observer); - sourceChanged = true; - notifyDataSetChanged(); - } - - public void invalidate() { - if(source != null) { - source.unregisterObserver(observer); - } - source = null; - notifyDataSetInvalidated(); - } + public int getCount() { + return getEntries().size(); + } + + public V getItem(int position) { + return getEntries().get(position); + } + + public long getItemId(int position) { + return position; + } + + @Override + public boolean hasStableIds() { + return false; + } + + public void setSource(ObservableTreeMap source) { + if(this.source != null) { + this.source.unregisterObserver(observer); + } + this.source = source; + this.source.registerObserver(observer); + sourceChanged = true; + notifyDataSetChanged(); + } + + public void invalidate() { + if(source != null) { + source.unregisterObserver(observer); + } + source = null; + notifyDataSetInvalidated(); + } } \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/util/TextInputDialog.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/util/TextInputDialog.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/util/TextInputDialog.java Tue Nov 10 20:43:13 2015 +0100 @@ -36,113 +36,113 @@ * interface TextInputDialogListener, which will be called by the dialog if it is submitted or cancelled. */ public class TextInputDialog extends DialogFragment { - private static final String BUNDLE_DIALOG_ID = "dialogId"; - private static final String BUNDLE_TITLE_TEXT = "title"; - private static final String BUNDLE_MESSAGE_TEXT = "message"; - private static final String BUNDLE_HINT_TEXT = "hint"; - - private int dialogId, titleText, messageText, hintText; - private TextInputDialogListener listener; - - public interface TextInputDialogListener { - void onTextInputDialogSubmitted(int dialogId, String text); - void onTextInputDialogCancelled(int dialogId); - } - - /** - * The dialogId is only used for passing back to the callback on the activity, the - * other parameters are text resource IDs. Pass 0 for any of them to not use this - * text. - */ - public TextInputDialog(int dialogId, int titleText, int messageText, int hintText) { - this.dialogId = dialogId; - this.titleText = titleText; - this.messageText = messageText; - this.hintText = hintText; - } - - public TextInputDialog() { - // Only for reflection-based instantiation by the framework - } - - @Override - public void onAttach(Activity activity) { - super.onAttach(activity); - try { - listener = (TextInputDialogListener) activity; - } catch(ClassCastException e) { - throw new ClassCastException("Activity " + activity + " must implement TextInputDialogListener to use TextInputDialog."); - } - } - - @Override - public void onDetach() { - super.onDetach(); - listener = null; - } - - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - if(savedInstanceState != null) { - dialogId = savedInstanceState.getInt(BUNDLE_DIALOG_ID, dialogId); - titleText = savedInstanceState.getInt(BUNDLE_TITLE_TEXT, titleText); - messageText = savedInstanceState.getInt(BUNDLE_MESSAGE_TEXT, messageText); - hintText = savedInstanceState.getInt(BUNDLE_HINT_TEXT, hintText); - } - - final EditText editText = new EditText(getActivity()); - AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); - - if(titleText != 0) { - builder.setTitle(titleText); - } - if(messageText != 0) { - builder.setTitle(messageText); - } - if(hintText != 0) { - editText.setHint(hintText); - } - - editText.setId(android.R.id.text1); - editText.setImeOptions(EditorInfo.IME_ACTION_DONE); - editText.setSingleLine(); + private static final String BUNDLE_DIALOG_ID = "dialogId"; + private static final String BUNDLE_TITLE_TEXT = "title"; + private static final String BUNDLE_MESSAGE_TEXT = "message"; + private static final String BUNDLE_HINT_TEXT = "hint"; + + private int dialogId, titleText, messageText, hintText; + private TextInputDialogListener listener; + + public interface TextInputDialogListener { + void onTextInputDialogSubmitted(int dialogId, String text); + void onTextInputDialogCancelled(int dialogId); + } + + /** + * The dialogId is only used for passing back to the callback on the activity, the + * other parameters are text resource IDs. Pass 0 for any of them to not use this + * text. + */ + public TextInputDialog(int dialogId, int titleText, int messageText, int hintText) { + this.dialogId = dialogId; + this.titleText = titleText; + this.messageText = messageText; + this.hintText = hintText; + } + + public TextInputDialog() { + // Only for reflection-based instantiation by the framework + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + try { + listener = (TextInputDialogListener) activity; + } catch(ClassCastException e) { + throw new ClassCastException("Activity " + activity + " must implement TextInputDialogListener to use TextInputDialog."); + } + } + + @Override + public void onDetach() { + super.onDetach(); + listener = null; + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + if(savedInstanceState != null) { + dialogId = savedInstanceState.getInt(BUNDLE_DIALOG_ID, dialogId); + titleText = savedInstanceState.getInt(BUNDLE_TITLE_TEXT, titleText); + messageText = savedInstanceState.getInt(BUNDLE_MESSAGE_TEXT, messageText); + hintText = savedInstanceState.getInt(BUNDLE_HINT_TEXT, hintText); + } - builder.setView(editText); - builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - dialog.cancel(); - } - }); - - editText.setOnEditorActionListener(new OnEditorActionListener() { - public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { - listener.onTextInputDialogSubmitted(dialogId, v.getText().toString()); - dismiss(); - return true; - } - }); - - builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - listener.onTextInputDialogSubmitted(dialogId, editText.getText().toString()); - } - }); + final EditText editText = new EditText(getActivity()); + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + + if(titleText != 0) { + builder.setTitle(titleText); + } + if(messageText != 0) { + builder.setTitle(messageText); + } + if(hintText != 0) { + editText.setHint(hintText); + } + + editText.setId(android.R.id.text1); + editText.setImeOptions(EditorInfo.IME_ACTION_DONE); + editText.setSingleLine(); + + builder.setView(editText); + builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + dialog.cancel(); + } + }); - return builder.create(); - } - - @Override - public void onSaveInstanceState(Bundle icicle) { - super.onSaveInstanceState(icicle); - icicle.putInt(BUNDLE_DIALOG_ID, dialogId); - icicle.putInt(BUNDLE_TITLE_TEXT, titleText); - icicle.putInt(BUNDLE_MESSAGE_TEXT, messageText); - icicle.putInt(BUNDLE_HINT_TEXT, hintText); - } - - @Override - public void onCancel(DialogInterface dialog) { - super.onCancel(dialog); - listener.onTextInputDialogCancelled(dialogId); - } + editText.setOnEditorActionListener(new OnEditorActionListener() { + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + listener.onTextInputDialogSubmitted(dialogId, v.getText().toString()); + dismiss(); + return true; + } + }); + + builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + listener.onTextInputDialogSubmitted(dialogId, editText.getText().toString()); + } + }); + + return builder.create(); + } + + @Override + public void onSaveInstanceState(Bundle icicle) { + super.onSaveInstanceState(icicle); + icicle.putInt(BUNDLE_DIALOG_ID, dialogId); + icicle.putInt(BUNDLE_TITLE_TEXT, titleText); + icicle.putInt(BUNDLE_MESSAGE_TEXT, messageText); + icicle.putInt(BUNDLE_HINT_TEXT, hintText); + } + + @Override + public void onCancel(DialogInterface dialog) { + super.onCancel(dialog); + listener.onTextInputDialogCancelled(dialogId); + } } diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/util/TickHandler.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/util/TickHandler.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/util/TickHandler.java Tue Nov 10 20:43:13 2015 +0100 @@ -32,42 +32,42 @@ * an immediate execution of the runnable again. */ public class TickHandler extends Handler { - private final Runnable callback; - private int messageId; - private long interval; - private boolean running; - - public TickHandler(Looper looper, long interval, Runnable callback) { - super(looper); - this.callback = callback; - this.interval = interval; - } - - public synchronized void stop() { - messageId++; - running = false; - } - - public synchronized void start() { - messageId++; - sendMessage(obtainMessage(messageId)); - running = true; - } - - public synchronized void setInterval(long interval) { - this.interval = interval; - if(running) { - start(); - } - } - - @Override - public synchronized void handleMessage(Message msg) { - if(msg.what == messageId) { - callback.run(); - } - if(msg.what == messageId) { - sendMessageDelayed(obtainMessage(messageId), interval); - } - } + private final Runnable callback; + private int messageId; + private long interval; + private boolean running; + + public TickHandler(Looper looper, long interval, Runnable callback) { + super(looper); + this.callback = callback; + this.interval = interval; + } + + public synchronized void stop() { + messageId++; + running = false; + } + + public synchronized void start() { + messageId++; + sendMessage(obtainMessage(messageId)); + running = true; + } + + public synchronized void setInterval(long interval) { + this.interval = interval; + if(running) { + start(); + } + } + + @Override + public synchronized void handleMessage(Message msg) { + if(msg.what == messageId) { + callback.run(); + } + if(msg.what == messageId) { + sendMessageDelayed(obtainMessage(messageId), interval); + } + } } \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/util/UiUtils.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/util/UiUtils.java Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/util/UiUtils.java Tue Nov 10 20:43:13 2015 +0100 @@ -29,25 +29,25 @@ import android.widget.TextView; public final class UiUtils { - private UiUtils() { - throw new AssertionError("This class is not meant to be instantiated"); - } + private UiUtils() { + throw new AssertionError("This class is not meant to be instantiated"); + } - public static View createVerticalTabIndicator(TabHost tabHost, int label, int icon) { - LayoutInflater inflater = (LayoutInflater) tabHost.getContext() - .getSystemService(Context.LAYOUT_INFLATER_SERVICE); + public static View createVerticalTabIndicator(TabHost tabHost, int label, int icon) { + LayoutInflater inflater = (LayoutInflater) tabHost.getContext() + .getSystemService(Context.LAYOUT_INFLATER_SERVICE); - View view = inflater.inflate(R.layout.tab_indicator_vertical, - tabHost.getTabWidget(), false); + View view = inflater.inflate(R.layout.tab_indicator_vertical, + tabHost.getTabWidget(), false); - final TextView tv = (TextView) view.findViewById(R.id.title); - tv.setText(label); + final TextView tv = (TextView) view.findViewById(R.id.title); + tv.setText(label); - if (icon != 0) { - ImageView iconView = (ImageView) view.findViewById(R.id.icon); - iconView.setImageResource(icon); - } + if (icon != 0) { + ImageView iconView = (ImageView) view.findViewById(R.id.icon); + iconView.setImageResource(icon); + } - return view; - } + return view; + } } diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/gles11.pp --- a/project_files/Android-build/gles11.pp Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/gles11.pp Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$mode objfpc} diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/jni.pas --- a/project_files/Android-build/jni.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/jni.pas Tue Nov 10 20:43:13 2015 +0100 @@ -513,7 +513,7 @@ const curVM:PJavaVM=nil; curEnv:PJNIEnv=nil; - + (* function JNI_OnLoad(vm:PJavaVM;reserved:pointer):jint;{$ifdef mswindows}stdcall;{$else}cdecl;{$endif} procedure JNI_OnUnload(vm:PJavaVM;reserved:pointer);{$ifdef mswindows}stdcall;{$else}cdecl;{$endif} diff -r 31570b766315 -r ed5a6478e710 project_files/Android-build/log.pas --- a/project_files/Android-build/log.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/Android-build/log.pas Tue Nov 10 20:43:13 2015 +0100 @@ -22,7 +22,7 @@ function __android_log_write(prio:longint;tag,text:pchar):longint; cdecl; external libname name '__android_log_write'; //function __android_log_print(prio:longint;tag,print:pchar;params:array of pchar):longint; cdecl; external libname name '__android_log_print'; - + implementation end. diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/AboutViewController.h --- a/project_files/HedgewarsMobile/Classes/AboutViewController.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/AboutViewController.h Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/AboutViewController.m --- a/project_files/HedgewarsMobile/Classes/AboutViewController.m Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/AboutViewController.m Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ @@ -27,7 +27,10 @@ return rotationManager(interfaceOrientation); } --(void) viewDidLoad { +-(void) viewDidLoad +{ + [super viewDidLoad]; + [self.tableView setBackgroundColorForAnyTable:[UIColor clearColor]]; self.tableView.allowsSelection = NO; @@ -48,12 +51,23 @@ [self.view insertSubview:background atIndex:0]; [background release]; - [super viewDidLoad]; + [self localizeSegmentedControl]; } -(IBAction) buttonPressed:(id) sender { [[AudioManagerController mainManager] playBackSound]; - [[self parentViewController] dismissModalViewControllerAnimated:YES]; + [self.presentingViewController dismissViewControllerAnimated:YES completion:nil]; +} + +#pragma mark - Segmented Control + +- (void)localizeSegmentedControl +{ + for (NSUInteger i = 0; i < self.segmentedControl.numberOfSegments; i++) + { + NSString *oldTitle = [self.segmentedControl titleForSegmentAtIndex:i]; + [self.segmentedControl setTitle:NSLocalizedStringFromTable(oldTitle, @"About", nil) forSegmentAtIndex:i]; + } } -(IBAction) segmentedControlChanged:(id) sender { @@ -83,7 +97,8 @@ cell.textLabel.text = [[self.people objectAtIndex:self.segmentedControl.selectedSegmentIndex] objectAtIndex:[indexPath row]]; cell.textLabel.adjustsFontSizeToFitWidth = YES; cell.textLabel.minimumFontSize = 8; - cell.detailTextLabel.text = [[self.people objectAtIndex:(self.segmentedControl.selectedSegmentIndex + 5)] objectAtIndex:[indexPath row]]; + NSString *detailsKey = [[self.people objectAtIndex:(self.segmentedControl.selectedSegmentIndex + 5)] objectAtIndex:[indexPath row]]; + cell.detailTextLabel.text = NSLocalizedStringFromTable(detailsKey, @"About", nil); return cell; } @@ -118,6 +133,7 @@ label.textColor = [UIColor lightGrayColor]; label.numberOfLines = 5; label.text = footerString; + [footerString release]; label.backgroundColor = [UIColor clearColor]; [footer addSubview:label]; diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/Appirater.h --- a/project_files/HedgewarsMobile/Classes/Appirater.h Tue Nov 10 18:16:35 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,98 +0,0 @@ -/* - This file is part of Appirater, http://arashpayan.com - - Copyright (c) 2010, Arash Payan - All rights reserved. - - Permission is hereby granted, free of charge, to any person - obtaining a copy of this software and associated documentation - files (the "Software"), to deal in the Software without - restriction, including without limitation the rights to use, - copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following - conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - OTHER DEALINGS IN THE SOFTWARE. - */ - - -#import - -extern NSString *const kAppiraterLaunchDate; -extern NSString *const kAppiraterLaunchCount; -extern NSString *const kAppiraterCurrentVersion; -extern NSString *const kAppiraterRatedCurrentVersion; -extern NSString *const kAppiraterDeclinedToRate; - -/* - Place your Apple generated software id here. - */ -#define APPIRATER_APP_ID 391234866 - -/* - Your app's name. - */ -#define APPIRATER_APP_NAME [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey] - -/* - This is the message your users will see once they've passed the day+launches - threshold. - */ -#define APPIRATER_MESSAGE [NSString stringWithFormat:@"If you enjoy using %@, would you mind taking a moment to rate it? It won't take more than a minute. Thanks for your support!", APPIRATER_APP_NAME] - -/* - This is the title of the message alert that users will see. - */ -#define APPIRATER_MESSAGE_TITLE [NSString stringWithFormat:@"Rate %@", APPIRATER_APP_NAME] - -/* - The text of the button that rejects reviewing the app. - */ -#define APPIRATER_CANCEL_BUTTON NSLocalizedString(@"No thanks",@"") - -/* - Text of button that will send user to app review page. - */ -#define APPIRATER_RATE_BUTTON [NSString stringWithFormat:@"Rate %@", APPIRATER_APP_NAME] - -/* - Text for button to remind the user to review later. - */ -#define APPIRATER_RATE_LATER NSLocalizedString(@"Remind me later",@"") - -/* - Users will need to have the same version of your app installed for this many - days before they will be prompted to rate it. - */ -#define DAYS_UNTIL_PROMPT 3 // double - -/* - Users will need to launch the same version of the app this many times before - they will be prompted to rate it. - */ -#define LAUNCHES_UNTIL_PROMPT 5 // integer - -/* - 'YES' will show the Appirater alert everytime. Useful for testing how your message - looks and making sure the link to your app's review page works. - */ -#define APPIRATER_DEBUG NO // bool - -@interface Appirater : NSObject { - -} - -+(void) appLaunched; - -@end diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/Appirater.m --- a/project_files/HedgewarsMobile/Classes/Appirater.m Tue Nov 10 18:16:35 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,159 +0,0 @@ -/* - This file is part of Appirater, http://arashpayan.com - - Copyright (c) 2010, Arash Payan - All rights reserved. - - Permission is hereby granted, free of charge, to any person - obtaining a copy of this software and associated documentation - files (the "Software"), to deal in the Software without - restriction, including without limitation the rights to use, - copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following - conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - OTHER DEALINGS IN THE SOFTWARE. - */ - - -#import "Appirater.h" -#import -#import - -NSString *const kAppiraterLaunchDate = @"kAppiraterLaunchDate"; -NSString *const kAppiraterLaunchCount = @"kAppiraterLaunchCount"; -NSString *const kAppiraterCurrentVersion = @"kAppiraterCurrentVersion"; -NSString *const kAppiraterRatedCurrentVersion = @"kAppiraterRatedCurrentVersion"; -NSString *const kAppiraterDeclinedToRate = @"kAppiraterDeclinedToRate"; - -NSString *templateReviewURL = @"itms-apps://itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?id=APP_ID&onlyLatestVersion=true&pageNumber=0&sortOrdering=1&type=Purple+Software"; - -@implementation Appirater - -+(void) appLaunched { - Appirater *appirater = [[Appirater alloc] init]; - [NSThread detachNewThreadSelector:@selector(appLaunchedHandler) toTarget:appirater withObject:nil]; -} - --(void) appLaunchedHandler { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - if (APPIRATER_DEBUG) { - [self performSelectorOnMainThread:@selector(showPrompt) withObject:nil waitUntilDone:NO]; - return; - } - - BOOL willShowPrompt = NO; - - // get the app's version - NSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleVersionKey]; - - // get the version number that we've been tracking - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - NSString *trackingVersion = [userDefaults stringForKey:kAppiraterCurrentVersion]; - if (trackingVersion == nil) { - trackingVersion = version; - [userDefaults setObject:version forKey:kAppiraterCurrentVersion]; - } - - if (APPIRATER_DEBUG) - DLog(@"APPIRATER Tracking version: %@", trackingVersion); - - if ([trackingVersion isEqualToString:version]) { - // get the launch date - NSTimeInterval timeInterval = [userDefaults doubleForKey:kAppiraterLaunchDate]; - if (timeInterval == 0) { - timeInterval = [[NSDate date] timeIntervalSince1970]; - [userDefaults setDouble:timeInterval forKey:kAppiraterLaunchDate]; - } - - NSTimeInterval secondsSinceLaunch = [[NSDate date] timeIntervalSinceDate:[NSDate dateWithTimeIntervalSince1970:timeInterval]]; - double secondsUntilPrompt = 60 * 60 * 24 * DAYS_UNTIL_PROMPT; - - // get the launch count - int launchCount = [userDefaults integerForKey:kAppiraterLaunchCount]; - launchCount++; - [userDefaults setInteger:launchCount forKey:kAppiraterLaunchCount]; - if (APPIRATER_DEBUG) - NSLog(@"APPIRATER Launch count: %d", launchCount); - - // have they previously declined to rate this version of the app? - BOOL declinedToRate = [userDefaults boolForKey:kAppiraterDeclinedToRate]; - - // have they already rated the app? - BOOL ratedApp = [userDefaults boolForKey:kAppiraterRatedCurrentVersion]; - - if (secondsSinceLaunch > secondsUntilPrompt && - launchCount > LAUNCHES_UNTIL_PROMPT && - !declinedToRate && - !ratedApp) { - if ([HWUtils isNetworkReachable]) { // check if they can reach the app store - willShowPrompt = YES; - [self performSelectorOnMainThread:@selector(showPrompt) withObject:nil waitUntilDone:NO]; - } - } - } else { - // it's a new version of the app, so restart tracking - [userDefaults setObject:version forKey:kAppiraterCurrentVersion]; - [userDefaults setDouble:[[NSDate date] timeIntervalSince1970] forKey:kAppiraterLaunchDate]; - [userDefaults setInteger:1 forKey:kAppiraterLaunchCount]; - [userDefaults setBool:NO forKey:kAppiraterRatedCurrentVersion]; - [userDefaults setBool:NO forKey:kAppiraterDeclinedToRate]; - } - - [userDefaults synchronize]; - if (!willShowPrompt) - [self autorelease]; - - [pool release]; -} - --(void) showPrompt { - UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:APPIRATER_MESSAGE_TITLE - message:APPIRATER_MESSAGE - delegate:self - cancelButtonTitle:APPIRATER_CANCEL_BUTTON - otherButtonTitles:APPIRATER_RATE_BUTTON, APPIRATER_RATE_LATER, nil]; - [alertView show]; - [alertView release]; -} - --(void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger) buttonIndex { - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - - switch (buttonIndex) { - case 0: - // they don't want to rate it - [userDefaults setBool:YES forKey:kAppiraterDeclinedToRate]; - break; - case 1: - // they want to rate it - [[UIApplication sharedApplication] openURL: - [NSURL URLWithString:[templateReviewURL stringByReplacingOccurrencesOfString:@"APP_ID" withString:[NSString stringWithFormat:@"%d", APPIRATER_APP_ID]]]]; - - [userDefaults setBool:YES forKey:kAppiraterRatedCurrentVersion]; - break; - case 2: - // remind them later - break; - default: - break; - } - - [userDefaults synchronize]; - - [self release]; -} - -@end diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/ar.lproj/AppiraterLocalizable.strings --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/ar.lproj/AppiraterLocalizable.strings Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,4 @@ +"If you enjoy using %@, would you mind taking a moment to rate it? It won't take more than a minute. Thanks for your support!" = "إذا كنت تستمع باستخدام %@، فهل تمانع بأن تأخذ دقيقة من وقتك لتقيمه؟ لن يستغرق الأمر أكثر من دقيقة. شكرا لدعمك!"; +"Rate %@" = "قيم %@"; +"No, Thanks" = "لا شكرا"; +"Remind me later" = "ذكرني لاحقا"; \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/ca.lproj/AppiraterLocalizable.strings --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/ca.lproj/AppiraterLocalizable.strings Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,4 @@ +"If you enjoy using %@, would you mind taking a moment to rate it? It won't take more than a minute. Thanks for your support!" = "Si li agrada utilitzar %@, li importaria prendre’s un moment per a valorar-lo? No trigarà més d’un minut. Gràcies por la seva col·laboració!"; +"Rate %@" = "Valorar %@"; +"No, Thanks" = "No, gràcies"; +"Remind me later" = "Recordar-m’ho més tard"; \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/cs.lproj/AppiraterLocalizable.strings --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/cs.lproj/AppiraterLocalizable.strings Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,4 @@ +"If you enjoy using %@, would you mind taking a moment to rate it? It won't take more than a minute. Thanks for your support!" = "Pokud se Vám aplikace %@ líbí, mohli byste ji prosím ohodnotit v App Store? Zabere to jen chvilku. Díky za Vaši podporu!"; +"Rate %@" = "Ohodnotit %@"; +"No, Thanks" = "Ne, díky"; +"Remind me later" = "Možná později"; \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/da.lproj/AppiraterLocalizable.strings --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/da.lproj/AppiraterLocalizable.strings Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,4 @@ +"If you enjoy using %@, would you mind taking a moment to rate it? It won't take more than a minute. Thanks for your support!" = "Hvis du synes om at bruge %@, vil du have noget imod at bruge et kort øjeblik på at bedømme det? Det tager kun et minut. Tak for din støtte!"; +"Rate %@" = "Bedøm %@"; +"No, Thanks" = "Nej tak"; +"Remind me later" = "Påmind mig senere"; diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/de.lproj/AppiraterLocalizable.strings --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/de.lproj/AppiraterLocalizable.strings Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,4 @@ +"If you enjoy using %@, would you mind taking a moment to rate it? It won't take more than a minute. Thanks for your support!" = "Sie nutzen %@ gerne? Dann nehmen Sie sich bitte für eine Bewertung einen Moment Zeit! Es dauert nicht länger als eine Minute. Vielen Dank!"; +"Rate %@" = "Bewerte %@"; +"No, Thanks" = "Nein, danke"; +"Remind me later" = "Später erinnern"; diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/el.lproj/AppiraterLocalizable.strings --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/el.lproj/AppiraterLocalizable.strings Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,4 @@ +"If you enjoy using %@, would you mind taking a moment to rate it? It won't take more than a minute. Thanks for your support!" = "Αν σου αρέσει το %@, θα μπορούσες να αφιερώσεις μια στιγμή για να το βαθμολογήσεις; Η διαδικασία είναι πολύ σύντομη. Ευχαριστούμε για τη στήριξη!"; +"Rate %@" = "Βαθμολόγηση του %@"; +"No, Thanks" = "Όχι, ευχαριστώ"; +"Remind me later" = "Υπενθύμιση αργότερα"; \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/en.lproj/AppiraterLocalizable.strings --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/en.lproj/AppiraterLocalizable.strings Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,4 @@ +"If you enjoy using %@, would you mind taking a moment to rate it? It won't take more than a minute. Thanks for your support!" = "If you enjoy using %@, would you mind taking a moment to rate it? It won't take more than a minute. Thanks for your support!"; +"Rate %@" = "Rate %@"; +"No, Thanks" = "No, thanks"; +"Remind me later" = "Remind me later"; \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/es.lproj/AppiraterLocalizable.strings --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/es.lproj/AppiraterLocalizable.strings Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,4 @@ +"If you enjoy using %@, would you mind taking a moment to rate it? It won't take more than a minute. Thanks for your support!" = "Si te ha gustado %@, ¿te gustaría calificarnos? No te tomará más de un minuto. ¡Gracias por tu colaboración!"; +"Rate %@" = "Calificar %@"; +"No, Thanks" = "No, gracias"; +"Remind me later" = "Recuérdame más tarde"; diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/fi.lproj/AppiraterLocalizable.strings --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/fi.lproj/AppiraterLocalizable.strings Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,4 @@ +"If you enjoy using %@, would you mind taking a moment to rate it? It won't take more than a minute. Thanks for your support!" = "Jos käytät mielelläsi %@, voisitko käyttää hetken ja arvostella sen? Se ei kestä minuuttia kauempaa. Kiitos tuestasi!"; +"Rate %@" = "Arvioi %@"; +"No, Thanks" = "Ei kiitos"; +"Remind me later" = "Muistuta minua myöhemmin"; \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/fr.lproj/AppiraterLocalizable.strings --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/fr.lproj/AppiraterLocalizable.strings Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,4 @@ +"If you enjoy using %@, would you mind taking a moment to rate it? It won't take more than a minute. Thanks for your support!" = "Si vous aimez %@, voulez-vous prendre un moment pour l'évaluer ? Cela ne vous prendra pas plus d'une minute. Merci de votre soutien !"; +"Rate %@" = "Évaluer %@"; +"No, Thanks" = "Non, merci"; +"Remind me later" = "Me rappeler plus tard"; diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/he.lproj/AppiraterLocalizable.strings --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/he.lproj/AppiraterLocalizable.strings Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,4 @@ +"If you enjoy using %@, would you mind taking a moment to rate it? It won't take more than a minute. Thanks for your support!" = "אם נהנת להשתמש ב %@, האם תסכים לדרג אותה? זה לא יקח יותר מדקה. תודה על התמיכה!"; +"Rate %@" = "דרג את %@"; +"No, Thanks" = "לא תודה"; +"Remind me later" = "מאוחר יותר"; \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/hu.lproj/AppiraterLocalizable.strings --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/hu.lproj/AppiraterLocalizable.strings Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,4 @@ +"If you enjoy using %@, would you mind taking a moment to rate it? It won't take more than a minute. Thanks for your support!" = "Ha tetszik a %@, ne felejtsd el értékelni az App Store-ban! Csak egy perc az egész. Köszönet a támogatásért!"; +"Rate %@" = "%@ értékelése"; +"No, Thanks" = "Most inkább nem"; +"Remind me later" = "Emlékeztess később"; diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/id.lproj/AppiraterLocalizable.strings --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/id.lproj/AppiraterLocalizable.strings Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,4 @@ +"If you enjoy using %@, would you mind taking a moment to rate it? It won't take more than a minute. Thanks for your support!" = "Jika anda menyukai %@, maukah anda memberikan rating kepada aplikasi ini? Rating hanya memakan waktu kurang dari 1 menit. Terimakasih untuk dukungan anda!"; +"Rate %@" = "Rating %@"; +"No, Thanks" = "Tidak, terimakasih"; +"Remind me later" = "Silakan ingatkan saya lagi"; \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/it.lproj/AppiraterLocalizable.strings --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/it.lproj/AppiraterLocalizable.strings Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,4 @@ +"If you enjoy using %@, would you mind taking a moment to rate it? It won't take more than a minute. Thanks for your support!" = "Se ti piace %@, perché non dedichi qualche istante a darne una valutazione sull'App Store? Non richiederà più di un minuto. Grazie per il supporto!"; +"Rate %@" = "Valuta %@"; +"No, Thanks" = "No, grazie"; +"Remind me later" = "Ricordamelo più tardi"; \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/ja.lproj/AppiraterLocalizable.strings --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/ja.lproj/AppiraterLocalizable.strings Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,4 @@ +"If you enjoy using %@, would you mind taking a moment to rate it? It won't take more than a minute. Thanks for your support!" = "%@をお使いいただきありがとうございます。もしよろしければ、ほんの少しだけお時間をいただき評価をお願いできませんか?ご協力感謝いたします!"; +"Rate %@" = "%@を評価する"; +"No, Thanks" ="結構です"; +"Remind me later" = "あとで"; diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/ko.lproj/AppiraterLocalizable.strings --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/ko.lproj/AppiraterLocalizable.strings Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,4 @@ +"If you enjoy using %@, would you mind taking a moment to rate it? It won't take more than a minute. Thanks for your support!" = "%@ 사용이 맘에 드셨나요? 잠시만 시간을 내서 평가를 부탁드리겠습니다. 감사합니다!"; +"Rate %@" = "%@ 평가하기"; +"No, Thanks" = "평가하지 않겠습니다"; +"Remind me later" = "다음에 평가하겠습니다"; \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/ms.lproj/AppiraterLocalizable.strings --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/ms.lproj/AppiraterLocalizable.strings Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,4 @@ +"If you enjoy using %@, would you mind taking a moment to rate it? It won't take more than a minute. Thanks for your support!" = "Jika anda suka %@, bolehkah luangkan sedikit masa untuk beri penarafan? Tak sampai seminit pun. Terima kasih atas sokongan anda!"; +"Rate %@" = "Tarafkan %@"; +"No, Thanks" = "Terima kasih saja"; +"Remind me later" = "Ingatkan saya lain kali"; \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/nb.lproj/AppiraterLocalizable.strings --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/nb.lproj/AppiraterLocalizable.strings Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,4 @@ +"If you enjoy using %@, would you mind taking a moment to rate it? It won't take more than a minute. Thanks for your support!" = "Hvis du liker å bruke %@, kan du ta deg et øyeblikk for å vurdere den? Det vil ikke ta mer enn ett minutt. Takk for din støtte!"; +"Rate %@" = "Vurder %@"; +"No, Thanks" = "Nei, takk"; +"Remind me later" = "Påminn meg senere"; \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/nl.lproj/AppiraterLocalizable.strings --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/nl.lproj/AppiraterLocalizable.strings Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,4 @@ +"If you enjoy using %@, would you mind taking a moment to rate it? It won't take more than a minute. Thanks for your support!" = "Als het gebruik van %@ je bevalt, zou je dan een momentje de tijd willen nemen om het te beoordelen? Het duurt nog geen minuut. Bedankt voor je steun!"; +"Rate %@" = "%@ beoordelen"; +"No, Thanks" = "Nee, bedankt"; +"Remind me later" = "Herinner me er later aan"; diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/pl.lproj/AppiraterLocalizable.strings --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/pl.lproj/AppiraterLocalizable.strings Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,4 @@ +"If you enjoy using %@, would you mind taking a moment to rate it? It won't take more than a minute. Thanks for your support!" = "Jeżeli podoba Ci się korzystanie z %@, może zechciałbyś poświęcić chwilę czasu, aby ocenić aplikację? Nie zajmie Ci to więcej niż minutę. Dziękujemy za pomoc!"; +"Rate %@" = "Oceń %@"; +"No, Thanks" = "Nie, dziękuję"; +"Remind me later" = "Przypomnij później"; \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/pt-BR.lproj/AppiraterLocalizable.strings --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/pt-BR.lproj/AppiraterLocalizable.strings Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,4 @@ +"If you enjoy using %@, would you mind taking a moment to rate it? It won't take more than a minute. Thanks for your support!" = "Se você gosta de usar o %@, que tal avaliá-lo? Não levará mais de um minuto. Agradecemos o seu apoio!"; +"Rate %@" = "Avaliar o %@"; +"No, Thanks" = "Não, obrigado"; +"Remind me later" = "Mais tarde"; diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/pt.lproj/AppiraterLocalizable.strings --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/pt.lproj/AppiraterLocalizable.strings Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,4 @@ +"If you enjoy using %@, would you mind taking a moment to rate it? It won't take more than a minute. Thanks for your support!" = "Se você gosta de usar o %@, que tal avaliá-lo? Não levará mais de um minuto. Agradecemos o seu apoio!"; +"Rate %@" = "Avaliar o %@"; +"No, Thanks" = "Não, obrigado"; +"Remind me later" = "Mais tarde"; diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/ro.lproj/AppiraterLocalizable.strings --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/ro.lproj/AppiraterLocalizable.strings Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,4 @@ +"If you enjoy using %@, would you mind taking a moment to rate it? It won't take more than a minute. Thanks for your support!" = "Dacă îți place %@, acordă-i o notă te rog, nu durează mult. Mulțumim pentru susținere!"; +"Rate %@" = "Acordă notă pentru %@"; +"No, Thanks" = "Nu, mulțumesc"; +"Remind me later" = "Adu-mi aminte mai târziu"; \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/ru.lproj/AppiraterLocalizable.strings --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/ru.lproj/AppiraterLocalizable.strings Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,4 @@ +"If you enjoy using %@, would you mind taking a moment to rate it? It won't take more than a minute. Thanks for your support!" = "Если Вам нравится %@, пожалуйста, поставьте свою оценку. Это займет у Вас не больше одной минуты.\n Спасибо за поддержку!"; +"Rate %@" = "Оценить %@"; +"No, Thanks" = "Нет, спасибо"; +"Remind me later" = "Напомнить позже"; diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/sk.lproj/AppiraterLocalizable.strings --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/sk.lproj/AppiraterLocalizable.strings Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,4 @@ +"If you enjoy using %@, would you mind taking a moment to rate it? It won't take more than a minute. Thanks for your support!" = "Pokiaľ sa Vám páči aplikácia %@, mohli by ste ju prosím ohodnotiť v App Store? Zaberie to len chvíľu. Vďaka za Vašu podporu!"; +"Rate %@" = "Ohodnotiť %@"; +"No, Thanks" = "Nie, ďakujem"; +"Remind me later" = "Pripomenúť neskôr"; \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/sv.lproj/AppiraterLocalizable.strings --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/sv.lproj/AppiraterLocalizable.strings Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,4 @@ +"If you enjoy using %@, would you mind taking a moment to rate it? It won't take more than a minute. Thanks for your support!" = "Om du gillar att använda %@, kan du tänka dig att betygsätta det åt oss? Det tar bara en minut. Tack för hjälpen!"; +"Rate %@" = "Betygsätt %@"; +"No, Thanks" = "Nej tack"; +"Remind me later" = "Påminn mig senare"; diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/th.lproj/AppiraterLocalizable.strings --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/th.lproj/AppiraterLocalizable.strings Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,4 @@ +"If you enjoy using %@, would you mind taking a moment to rate it? It won't take more than a minute. Thanks for your support!" = "ถ้าคุณกำลังใช้ %@ โปรดสละเวลาสักครู่ในการให้อันดับแก่เรา คุณจะเสียเวลาไม่เกินหนึ่งนาที ขอบคุณสำหรับการสนับสนุน!"; +"Rate %@" = "ให้อันดับ %@"; +"No, Thanks" = "ไม่ ขอบคุณ"; +"Remind me later" = "เตือนฉันภายหลัง"; diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/tr.lproj/AppiraterLocalizable.strings --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/tr.lproj/AppiraterLocalizable.strings Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,4 @@ +"If you enjoy using %@, would you mind taking a moment to rate it? It won't take more than a minute. Thanks for your support!" = "Eğer %@ uygulamasını kullanmaktan keyif alıyorsanız, onu değerlendirmek için zaman ayırabilir misiniz? Desteğiniz için teşekkür ederiz!"; +"Rate %@" = "%@ uygulamasını değerlendir"; +"No, Thanks" = "Hayır, teşekkürler"; +"Remind me later" = "Daha sonra hatırlat"; \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/uk.lproj/AppiraterLocalizable.strings --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/uk.lproj/AppiraterLocalizable.strings Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,4 @@ +"If you enjoy using %@, would you mind taking a moment to rate it? It won't take more than a minute. Thanks for your support!" = "Якщо вам сподобалося %@, будь ласка, поставте свою оцінку. Це займає не більше однієї хвилини.\n Дякуємо за підтримку!"; +"Rate %@" = "Оцінити %@"; +"No, Thanks" = "Ні, дякую"; +"Remind me later" = "Нагадати пізніше"; diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/vi.lproj/AppiraterLocalizable.strings --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/vi.lproj/AppiraterLocalizable.strings Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,4 @@ +"If you enjoy using %@, would you mind taking a moment to rate it? It won't take more than a minute. Thanks for your support!" = "Cảm ơn bạn đã sử dụng ứng dụng %@ trong thời gian qua, bạn có thể dành chút thời gian để đánh giá ứng dụng trong AppStore không?"; +"Rate %@" = "Đánh giá %@"; +"No, Thanks" = "Không, xin cảm ơn"; +"Remind me later" = "Hãy nhắc nhở tôi sau"; \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/zh-Hans.lproj/AppiraterLocalizable.strings --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/zh-Hans.lproj/AppiraterLocalizable.strings Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,4 @@ +"If you enjoy using %@, would you mind taking a moment to rate it? It won't take more than a minute. Thanks for your support!" = "如果你喜欢使用%@,你介意花一点时间给它评分吗?不会超过一分钟。感谢您的支持!"; +"Rate %@" = "给%@评分"; +"No, Thanks" = "不,谢谢"; +"Remind me later" = "稍后提醒我"; diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/zh-Hant.lproj/AppiraterLocalizable.strings --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/Appirater/Appirater.bundle/zh-Hant.lproj/AppiraterLocalizable.strings Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,4 @@ +"If you enjoy using %@, would you mind taking a moment to rate it? It won't take more than a minute. Thanks for your support!" = "如果你喜歡使用%@,你介意花一點時間給它評分嗎?不會超過一分鐘。感謝您的支持!"; +"Rate %@" = "給%@評分"; +"No, Thanks" = "不,謝謝"; +"Remind me later" = "稍後提醒我"; diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/Appirater/Appirater.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/Appirater/Appirater.h Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,331 @@ +/* + This file is part of Appirater. + + Copyright (c) 2012, Arash Payan + All rights reserved. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. + */ +/* + * Appirater.h + * appirater + * + * Created by Arash Payan on 9/5/09. + * http://arashpayan.com + * Copyright 2012 Arash Payan. All rights reserved. + */ + +#import +#import "AppiraterDelegate.h" +#import + +extern NSString *const kAppiraterFirstUseDate; +extern NSString *const kAppiraterUseCount; +extern NSString *const kAppiraterSignificantEventCount; +extern NSString *const kAppiraterCurrentVersion; +extern NSString *const kAppiraterRatedCurrentVersion; +extern NSString *const kAppiraterDeclinedToRate; +extern NSString *const kAppiraterReminderRequestDate; + +/*! + Your localized app's name. + */ +#define APPIRATER_LOCALIZED_APP_NAME [[[NSBundle mainBundle] localizedInfoDictionary] objectForKey:@"CFBundleDisplayName"] + +/*! + Your app's name. + */ +#define APPIRATER_APP_NAME APPIRATER_LOCALIZED_APP_NAME ?: [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleDisplayName"] ?: [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"] + +/*! + This is the message your users will see once they've passed the day+launches + threshold. + */ +#define APPIRATER_LOCALIZED_MESSAGE NSLocalizedStringFromTableInBundle(@"If you enjoy using %@, would you mind taking a moment to rate it? It won't take more than a minute. Thanks for your support!", @"AppiraterLocalizable", [Appirater bundle], nil) +#define APPIRATER_MESSAGE [NSString stringWithFormat:APPIRATER_LOCALIZED_MESSAGE, APPIRATER_APP_NAME] + +/*! + This is the title of the message alert that users will see. + */ +#define APPIRATER_LOCALIZED_MESSAGE_TITLE NSLocalizedStringFromTableInBundle(@"Rate %@", @"AppiraterLocalizable", [Appirater bundle], nil) +#define APPIRATER_MESSAGE_TITLE [NSString stringWithFormat:APPIRATER_LOCALIZED_MESSAGE_TITLE, APPIRATER_APP_NAME] + +/*! + The text of the button that rejects reviewing the app. + */ +#define APPIRATER_CANCEL_BUTTON NSLocalizedStringFromTableInBundle(@"No, Thanks", @"AppiraterLocalizable", [Appirater bundle], nil) + +/*! + Text of button that will send user to app review page. + */ +#define APPIRATER_LOCALIZED_RATE_BUTTON NSLocalizedStringFromTableInBundle(@"Rate %@", @"AppiraterLocalizable", [Appirater bundle], nil) +#define APPIRATER_RATE_BUTTON [NSString stringWithFormat:APPIRATER_LOCALIZED_RATE_BUTTON, APPIRATER_APP_NAME] + +/*! + Text for button to remind the user to review later. + */ +#define APPIRATER_RATE_LATER NSLocalizedStringFromTableInBundle(@"Remind me later", @"AppiraterLocalizable", [Appirater bundle], nil) + +@interface Appirater : NSObject { + + UIAlertView *ratingAlert; +} + +@property(nonatomic, strong) UIAlertView *ratingAlert; +@property(nonatomic) BOOL openInAppStore; +#if __has_feature(objc_arc_weak) +@property(nonatomic, weak) NSObject *delegate; +#else +@property(nonatomic, unsafe_unretained) NSObject *delegate; +#endif + +/*! + Tells Appirater that the app has launched, and on devices that do NOT + support multitasking, the 'uses' count will be incremented. You should + call this method at the end of your application delegate's + application:didFinishLaunchingWithOptions: method. + + If the app has been used enough to be rated (and enough significant events), + you can suppress the rating alert + by passing NO for canPromptForRating. The rating alert will simply be postponed + until it is called again with YES for canPromptForRating. The rating alert + can also be triggered by appEnteredForeground: and userDidSignificantEvent: + (as long as you pass YES for canPromptForRating in those methods). + */ ++ (void)appLaunched:(BOOL)canPromptForRating; + +/*! + Tells Appirater that the app was brought to the foreground on multitasking + devices. You should call this method from the application delegate's + applicationWillEnterForeground: method. + + If the app has been used enough to be rated (and enough significant events), + you can suppress the rating alert + by passing NO for canPromptForRating. The rating alert will simply be postponed + until it is called again with YES for canPromptForRating. The rating alert + can also be triggered by appLaunched: and userDidSignificantEvent: + (as long as you pass YES for canPromptForRating in those methods). + */ ++ (void)appEnteredForeground:(BOOL)canPromptForRating; + +/*! + Tells Appirater that the user performed a significant event. A significant + event is whatever you want it to be. If you're app is used to make VoIP + calls, then you might want to call this method whenever the user places + a call. If it's a game, you might want to call this whenever the user + beats a level boss. + + If the user has performed enough significant events and used the app enough, + you can suppress the rating alert by passing NO for canPromptForRating. The + rating alert will simply be postponed until it is called again with YES for + canPromptForRating. The rating alert can also be triggered by appLaunched: + and appEnteredForeground: (as long as you pass YES for canPromptForRating + in those methods). + */ ++ (void)userDidSignificantEvent:(BOOL)canPromptForRating; + +/*! + Tells Appirater to try and show the prompt (a rating alert). The prompt will be showed + if there is connection available, the user hasn't declined to rate + or hasn't rated current version. + + You could call to show the prompt regardless Appirater settings, + e.g., in case of some special event in your app. + */ ++ (void)tryToShowPrompt; + +/*! + Tells Appirater to show the prompt (a rating alert). + Similar to tryToShowPrompt, but without checks (the prompt is always displayed). + Passing false will hide the rate later button on the prompt. + + The only case where you should call this is if your app has an + explicit "Rate this app" command somewhere. This is similar to rateApp, + but instead of jumping to the review directly, an intermediary prompt is displayed. + */ ++ (void)forceShowPrompt:(BOOL)displayRateLaterButton; + +/*! + Tells Appirater to open the App Store page where the user can specify a + rating for the app. Also records the fact that this has happened, so the + user won't be prompted again to rate the app. + + The only case where you should call this directly is if your app has an + explicit "Rate this app" command somewhere. In all other cases, don't worry + about calling this -- instead, just call the other functions listed above, + and let Appirater handle the bookkeeping of deciding when to ask the user + whether to rate the app. + */ ++ (void)rateApp; + +/*! + Tells Appirater to immediately close any open rating modals (e.g. StoreKit rating VCs). +*/ ++ (void)closeModal; + +/*! + Asks Appirater if the user has declined to rate; +*/ +- (BOOL)userHasDeclinedToRate; + +/*! + Asks Appirater if the user has rated the current version. + Note that this is not a guarantee that the user has actually rated the app in the + app store, but they've just clicked the rate button on the Appirater dialog. +*/ +- (BOOL)userHasRatedCurrentVersion; + +@end + +@interface Appirater(Configuration) + +/*! + Set your Apple generated software id here. + */ ++ (void) setAppId:(NSString*)appId; + +/*! + Users will need to have the same version of your app installed for this many + days before they will be prompted to rate it. + */ ++ (void) setDaysUntilPrompt:(double)value; + +/*! + An example of a 'use' would be if the user launched the app. Bringing the app + into the foreground (on devices that support it) would also be considered + a 'use'. You tell Appirater about these events using the two methods: + [Appirater appLaunched:] + [Appirater appEnteredForeground:] + + Users need to 'use' the same version of the app this many times before + before they will be prompted to rate it. + */ ++ (void) setUsesUntilPrompt:(NSInteger)value; + +/*! + A significant event can be anything you want to be in your app. In a + telephone app, a significant event might be placing or receiving a call. + In a game, it might be beating a level or a boss. This is just another + layer of filtering that can be used to make sure that only the most + loyal of your users are being prompted to rate you on the app store. + If you leave this at a value of -1, then this won't be a criterion + used for rating. To tell Appirater that the user has performed + a significant event, call the method: + [Appirater userDidSignificantEvent:]; + */ ++ (void) setSignificantEventsUntilPrompt:(NSInteger)value; + + +/*! + Once the rating alert is presented to the user, they might select + 'Remind me later'. This value specifies how long (in days) Appirater + will wait before reminding them. + */ ++ (void) setTimeBeforeReminding:(double)value; + +/*! + Set customized title for alert view. + */ ++ (void) setCustomAlertTitle:(NSString *)title; + +/*! + Set customized message for alert view. + */ ++ (void) setCustomAlertMessage:(NSString *)message; + +/*! + Set customized cancel button title for alert view. + */ ++ (void) setCustomAlertCancelButtonTitle:(NSString *)cancelTitle; + +/*! + Set customized rate button title for alert view. + */ ++ (void) setCustomAlertRateButtonTitle:(NSString *)rateTitle; + +/*! + Set customized rate later button title for alert view. + */ ++ (void) setCustomAlertRateLaterButtonTitle:(NSString *)rateLaterTitle; + +/*! + 'YES' will show the Appirater alert everytime. Useful for testing how your message + looks and making sure the link to your app's review page works. + */ ++ (void) setDebug:(BOOL)debug; + +/*! + Set the delegate if you want to know when Appirater does something + */ ++ (void)setDelegate:(id)delegate; + +/*! + Set whether or not Appirater uses animation (currently respected when pushing modal StoreKit rating VCs). + */ ++ (void)setUsesAnimation:(BOOL)animation; + +/*! + If set to YES, Appirater will open App Store link (instead of SKStoreProductViewController on iOS 6). Default YES. + */ ++ (void)setOpenInAppStore:(BOOL)openInAppStore; + +/*! + If set to YES, the main bundle will always be used to load localized strings. + Set this to YES if you have provided your own custom localizations in AppiraterLocalizable.strings + in your main bundle. Default is NO. + */ ++ (void)setAlwaysUseMainBundle:(BOOL)useMainBundle; + +@end + + +/*! + Methods in this interface are public out of necessity, but may change without notice + */ +@interface Appirater(Unsafe) + +/*! + The bundle localized strings will be loaded from. +*/ ++(NSBundle *)bundle; + +@end + +@interface Appirater(Deprecated) + +/*! + DEPRECATED: While still functional, it's better to use + appLaunched:(BOOL)canPromptForRating instead. + + Calls [Appirater appLaunched:YES]. See appLaunched: for details of functionality. + */ ++ (void)appLaunched __attribute__((deprecated)); + +/*! + DEPRECATED: While still functional, it's better to use + tryToShowPrompt instead. + + Calls [Appirater tryToShowPrompt]. See tryToShowPrompt for details of functionality. + */ ++ (void)showPrompt __attribute__((deprecated)); + +@end diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/Appirater/Appirater.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/Appirater/Appirater.m Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,732 @@ +/* + This file is part of Appirater. + + Copyright (c) 2012, Arash Payan + All rights reserved. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. + */ +/* + * Appirater.m + * appirater + * + * Created by Arash Payan on 9/5/09. + * http://arashpayan.com + * Copyright 2012 Arash Payan. All rights reserved. + */ + +#import "Appirater.h" +#import +#include + +#if ! __has_feature(objc_arc) +#warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC). +#endif + +NSString *const kAppiraterFirstUseDate = @"kAppiraterFirstUseDate"; +NSString *const kAppiraterUseCount = @"kAppiraterUseCount"; +NSString *const kAppiraterSignificantEventCount = @"kAppiraterSignificantEventCount"; +NSString *const kAppiraterCurrentVersion = @"kAppiraterCurrentVersion"; +NSString *const kAppiraterRatedCurrentVersion = @"kAppiraterRatedCurrentVersion"; +NSString *const kAppiraterDeclinedToRate = @"kAppiraterDeclinedToRate"; +NSString *const kAppiraterReminderRequestDate = @"kAppiraterReminderRequestDate"; + +NSString *templateReviewURL = @"itms-apps://ax.itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?type=Purple+Software&id=APP_ID"; +NSString *templateReviewURLiOS7 = @"itms-apps://itunes.apple.com/app/idAPP_ID"; +NSString *templateReviewURLiOS8 = @"itms-apps://itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?id=APP_ID&onlyLatestVersion=true&pageNumber=0&sortOrdering=1&type=Purple+Software"; + +static NSString *_appId; +static double _daysUntilPrompt = 30; +static NSInteger _usesUntilPrompt = 20; +static NSInteger _significantEventsUntilPrompt = -1; +static double _timeBeforeReminding = 1; +static BOOL _debug = NO; +#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_5_0 + static id _delegate; +#else + __weak static id _delegate; +#endif +static BOOL _usesAnimation = TRUE; +static UIStatusBarStyle _statusBarStyle; +static BOOL _modalOpen = false; +static BOOL _alwaysUseMainBundle = NO; + +@interface Appirater () +@property (nonatomic, copy) NSString *alertTitle; +@property (nonatomic, copy) NSString *alertMessage; +@property (nonatomic, copy) NSString *alertCancelTitle; +@property (nonatomic, copy) NSString *alertRateTitle; +@property (nonatomic, copy) NSString *alertRateLaterTitle; +- (BOOL)connectedToNetwork; ++ (Appirater*)sharedInstance; +- (void)showPromptWithChecks:(BOOL)withChecks + displayRateLaterButton:(BOOL)displayRateLaterButton; +- (void)showRatingAlert:(BOOL)displayRateLaterButton; +- (void)showRatingAlert; +- (BOOL)ratingAlertIsAppropriate; +- (BOOL)ratingConditionsHaveBeenMet; +- (void)incrementUseCount; +- (void)hideRatingAlert; +@end + +@implementation Appirater + +@synthesize ratingAlert; + ++ (void) setAppId:(NSString *)appId { + _appId = appId; +} + ++ (void) setDaysUntilPrompt:(double)value { + _daysUntilPrompt = value; +} + ++ (void) setUsesUntilPrompt:(NSInteger)value { + _usesUntilPrompt = value; +} + ++ (void) setSignificantEventsUntilPrompt:(NSInteger)value { + _significantEventsUntilPrompt = value; +} + ++ (void) setTimeBeforeReminding:(double)value { + _timeBeforeReminding = value; +} + ++ (void) setCustomAlertTitle:(NSString *)title +{ + [self sharedInstance].alertTitle = title; +} + ++ (void) setCustomAlertMessage:(NSString *)message +{ + [self sharedInstance].alertMessage = message; +} + ++ (void) setCustomAlertCancelButtonTitle:(NSString *)cancelTitle +{ + [self sharedInstance].alertCancelTitle = cancelTitle; +} + ++ (void) setCustomAlertRateButtonTitle:(NSString *)rateTitle +{ + [self sharedInstance].alertRateTitle = rateTitle; +} + ++ (void) setCustomAlertRateLaterButtonTitle:(NSString *)rateLaterTitle +{ + [self sharedInstance].alertRateLaterTitle = rateLaterTitle; +} + ++ (void) setDebug:(BOOL)debug { + _debug = debug; +} ++ (void)setDelegate:(id)delegate{ + _delegate = delegate; +} ++ (void)setUsesAnimation:(BOOL)animation { + _usesAnimation = animation; +} ++ (void)setOpenInAppStore:(BOOL)openInAppStore { + [Appirater sharedInstance].openInAppStore = openInAppStore; +} ++ (void)setStatusBarStyle:(UIStatusBarStyle)style { + _statusBarStyle = style; +} ++ (void)setModalOpen:(BOOL)open { + _modalOpen = open; +} ++ (void)setAlwaysUseMainBundle:(BOOL)alwaysUseMainBundle { + _alwaysUseMainBundle = alwaysUseMainBundle; +} + ++ (NSBundle *)bundle +{ + NSBundle *bundle; + + if (_alwaysUseMainBundle) { + bundle = [NSBundle mainBundle]; + } else { + NSURL *appiraterBundleURL = [[NSBundle mainBundle] URLForResource:@"Appirater" withExtension:@"bundle"]; + + if (appiraterBundleURL) { + // Appirater.bundle will likely only exist when used via CocoaPods + bundle = [NSBundle bundleWithURL:appiraterBundleURL]; + } else { + bundle = [NSBundle mainBundle]; + } + } + + return bundle; +} + +- (NSString *)alertTitle +{ + return _alertTitle ? _alertTitle : APPIRATER_MESSAGE_TITLE; +} + +- (NSString *)alertMessage +{ + return _alertMessage ? _alertMessage : APPIRATER_MESSAGE; +} + +- (NSString *)alertCancelTitle +{ + return _alertCancelTitle ? _alertCancelTitle : APPIRATER_CANCEL_BUTTON; +} + +- (NSString *)alertRateTitle +{ + return _alertRateTitle ? _alertRateTitle : APPIRATER_RATE_BUTTON; +} + +- (NSString *)alertRateLaterTitle +{ + return _alertRateLaterTitle ? _alertRateLaterTitle : APPIRATER_RATE_LATER; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +- (id)init { + self = [super init]; + if (self) { + if ([[UIDevice currentDevice].systemVersion floatValue] >= 7.0) { + self.openInAppStore = YES; + } else { + self.openInAppStore = NO; + } + } + + return self; +} + +- (BOOL)connectedToNetwork { + // Create zero addy + struct sockaddr_in zeroAddress; + bzero(&zeroAddress, sizeof(zeroAddress)); + zeroAddress.sin_len = sizeof(zeroAddress); + zeroAddress.sin_family = AF_INET; + + // Recover reachability flags + SCNetworkReachabilityRef defaultRouteReachability = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&zeroAddress); + SCNetworkReachabilityFlags flags; + + Boolean didRetrieveFlags = SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags); + CFRelease(defaultRouteReachability); + + if (!didRetrieveFlags) + { + NSLog(@"Error. Could not recover network reachability flags"); + return NO; + } + + BOOL isReachable = flags & kSCNetworkFlagsReachable; + BOOL needsConnection = flags & kSCNetworkFlagsConnectionRequired; + BOOL nonWiFi = flags & kSCNetworkReachabilityFlagsTransientConnection; + + NSURL *testURL = [NSURL URLWithString:@"http://www.apple.com/"]; + NSURLRequest *testRequest = [NSURLRequest requestWithURL:testURL cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:20.0]; + NSURLConnection *testConnection = [[NSURLConnection alloc] initWithRequest:testRequest delegate:self]; + + return ((isReachable && !needsConnection) || nonWiFi) ? (testConnection ? YES : NO) : NO; +} + ++ (Appirater*)sharedInstance { + static Appirater *appirater = nil; + if (appirater == nil) + { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + appirater = [[Appirater alloc] init]; + appirater.delegate = _delegate; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appWillResignActive) name: + UIApplicationWillResignActiveNotification object:nil]; + }); + } + + return appirater; +} + +- (void)showRatingAlert:(BOOL)displayRateLaterButton { + UIAlertView *alertView = nil; + id delegate = _delegate; + + if(delegate && [delegate respondsToSelector:@selector(appiraterShouldDisplayAlert:)] && ![delegate appiraterShouldDisplayAlert:self]) { + return; + } + + if (displayRateLaterButton) { + alertView = [[UIAlertView alloc] initWithTitle:self.alertTitle + message:self.alertMessage + delegate:self + cancelButtonTitle:self.alertCancelTitle + otherButtonTitles:self.alertRateTitle, self.alertRateLaterTitle, nil]; + } else { + alertView = [[UIAlertView alloc] initWithTitle:self.alertTitle + message:self.alertMessage + delegate:self + cancelButtonTitle:self.alertCancelTitle + otherButtonTitles:self.alertRateTitle, nil]; + } + + self.ratingAlert = alertView; + [alertView show]; + + if (delegate && [delegate respondsToSelector:@selector(appiraterDidDisplayAlert:)]) { + [delegate appiraterDidDisplayAlert:self]; + } +} + +- (void)showRatingAlert +{ + [self showRatingAlert:true]; +} + +// is this an ok time to show the alert? (regardless of whether the rating conditions have been met) +// +// things checked here: +// * connectivity with network +// * whether user has rated before +// * whether user has declined to rate +// * whether rating alert is currently showing visibly +// things NOT checked here: +// * time since first launch +// * number of uses of app +// * number of significant events +// * time since last reminder +- (BOOL)ratingAlertIsAppropriate { + return ([self connectedToNetwork] + && ![self userHasDeclinedToRate] + && !self.ratingAlert.visible + && ![self userHasRatedCurrentVersion]); +} + +// have the rating conditions been met/earned? (regardless of whether this would be a moment when it's appropriate to show a new rating alert) +// +// things checked here: +// * time since first launch +// * number of uses of app +// * number of significant events +// * time since last reminder +// things NOT checked here: +// * connectivity with network +// * whether user has rated before +// * whether user has declined to rate +// * whether rating alert is currently showing visibly +- (BOOL)ratingConditionsHaveBeenMet { + if (_debug) + return YES; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + + NSDate *dateOfFirstLaunch = [NSDate dateWithTimeIntervalSince1970:[userDefaults doubleForKey:kAppiraterFirstUseDate]]; + NSTimeInterval timeSinceFirstLaunch = [[NSDate date] timeIntervalSinceDate:dateOfFirstLaunch]; + NSTimeInterval timeUntilRate = 60 * 60 * 24 * _daysUntilPrompt; + if (timeSinceFirstLaunch < timeUntilRate) + return NO; + + // check if the app has been used enough + NSInteger useCount = [userDefaults integerForKey:kAppiraterUseCount]; + if (useCount < _usesUntilPrompt) + return NO; + + // check if the user has done enough significant events + NSInteger sigEventCount = [userDefaults integerForKey:kAppiraterSignificantEventCount]; + if (sigEventCount < _significantEventsUntilPrompt) + return NO; + + // if the user wanted to be reminded later, has enough time passed? + NSDate *reminderRequestDate = [NSDate dateWithTimeIntervalSince1970:[userDefaults doubleForKey:kAppiraterReminderRequestDate]]; + NSTimeInterval timeSinceReminderRequest = [[NSDate date] timeIntervalSinceDate:reminderRequestDate]; + NSTimeInterval timeUntilReminder = 60 * 60 * 24 * _timeBeforeReminding; + if (timeSinceReminderRequest < timeUntilReminder) + return NO; + + return YES; +} + +- (void)incrementUseCount { + // get the app's version + NSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleVersionKey]; + + // get the version number that we've been tracking + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + NSString *trackingVersion = [userDefaults stringForKey:kAppiraterCurrentVersion]; + if (trackingVersion == nil) + { + trackingVersion = version; + [userDefaults setObject:version forKey:kAppiraterCurrentVersion]; + } + + if (_debug) + NSLog(@"APPIRATER Tracking version: %@", trackingVersion); + + if ([trackingVersion isEqualToString:version]) + { + // check if the first use date has been set. if not, set it. + NSTimeInterval timeInterval = [userDefaults doubleForKey:kAppiraterFirstUseDate]; + if (timeInterval == 0) + { + timeInterval = [[NSDate date] timeIntervalSince1970]; + [userDefaults setDouble:timeInterval forKey:kAppiraterFirstUseDate]; + } + + // increment the use count + NSInteger useCount = [userDefaults integerForKey:kAppiraterUseCount]; + useCount++; + [userDefaults setInteger:useCount forKey:kAppiraterUseCount]; + if (_debug) + NSLog(@"APPIRATER Use count: %@", @(useCount)); + } + else + { + // it's a new version of the app, so restart tracking + [userDefaults setObject:version forKey:kAppiraterCurrentVersion]; + [userDefaults setDouble:[[NSDate date] timeIntervalSince1970] forKey:kAppiraterFirstUseDate]; + [userDefaults setInteger:1 forKey:kAppiraterUseCount]; + [userDefaults setInteger:0 forKey:kAppiraterSignificantEventCount]; + [userDefaults setBool:NO forKey:kAppiraterRatedCurrentVersion]; + [userDefaults setBool:NO forKey:kAppiraterDeclinedToRate]; + [userDefaults setDouble:0 forKey:kAppiraterReminderRequestDate]; + } + + [userDefaults synchronize]; +} + +- (void)incrementSignificantEventCount { + // get the app's version + NSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleVersionKey]; + + // get the version number that we've been tracking + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + NSString *trackingVersion = [userDefaults stringForKey:kAppiraterCurrentVersion]; + if (trackingVersion == nil) + { + trackingVersion = version; + [userDefaults setObject:version forKey:kAppiraterCurrentVersion]; + } + + if (_debug) + NSLog(@"APPIRATER Tracking version: %@", trackingVersion); + + if ([trackingVersion isEqualToString:version]) + { + // check if the first use date has been set. if not, set it. + NSTimeInterval timeInterval = [userDefaults doubleForKey:kAppiraterFirstUseDate]; + if (timeInterval == 0) + { + timeInterval = [[NSDate date] timeIntervalSince1970]; + [userDefaults setDouble:timeInterval forKey:kAppiraterFirstUseDate]; + } + + // increment the significant event count + NSInteger sigEventCount = [userDefaults integerForKey:kAppiraterSignificantEventCount]; + sigEventCount++; + [userDefaults setInteger:sigEventCount forKey:kAppiraterSignificantEventCount]; + if (_debug) + NSLog(@"APPIRATER Significant event count: %@", @(sigEventCount)); + } + else + { + // it's a new version of the app, so restart tracking + [userDefaults setObject:version forKey:kAppiraterCurrentVersion]; + [userDefaults setDouble:0 forKey:kAppiraterFirstUseDate]; + [userDefaults setInteger:0 forKey:kAppiraterUseCount]; + [userDefaults setInteger:1 forKey:kAppiraterSignificantEventCount]; + [userDefaults setBool:NO forKey:kAppiraterRatedCurrentVersion]; + [userDefaults setBool:NO forKey:kAppiraterDeclinedToRate]; + [userDefaults setDouble:0 forKey:kAppiraterReminderRequestDate]; + } + + [userDefaults synchronize]; +} + +- (void)incrementAndRate:(BOOL)canPromptForRating { + [self incrementUseCount]; + + if (canPromptForRating && + [self ratingConditionsHaveBeenMet] && + [self ratingAlertIsAppropriate]) + { + dispatch_async(dispatch_get_main_queue(), + ^{ + [self showRatingAlert]; + }); + } +} + +- (void)incrementSignificantEventAndRate:(BOOL)canPromptForRating { + [self incrementSignificantEventCount]; + + if (canPromptForRating && + [self ratingConditionsHaveBeenMet] && + [self ratingAlertIsAppropriate]) + { + dispatch_async(dispatch_get_main_queue(), + ^{ + [self showRatingAlert]; + }); + } +} + +- (BOOL)userHasDeclinedToRate { + return [[NSUserDefaults standardUserDefaults] boolForKey:kAppiraterDeclinedToRate]; +} + +- (BOOL)userHasRatedCurrentVersion { + return [[NSUserDefaults standardUserDefaults] boolForKey:kAppiraterRatedCurrentVersion]; +} + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-implementations" ++ (void)appLaunched { + [Appirater appLaunched:YES]; +} +#pragma GCC diagnostic pop + ++ (void)appLaunched:(BOOL)canPromptForRating { + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), + ^{ + Appirater *a = [Appirater sharedInstance]; + if (_debug) { + dispatch_async(dispatch_get_main_queue(), + ^{ + [a showRatingAlert]; + }); + } else { + [a incrementAndRate:canPromptForRating]; + } + }); +} + +- (void)hideRatingAlert { + if (self.ratingAlert.visible) { + if (_debug) + NSLog(@"APPIRATER Hiding Alert"); + [self.ratingAlert dismissWithClickedButtonIndex:-1 animated:NO]; + } +} + ++ (void)appWillResignActive { + if (_debug) + NSLog(@"APPIRATER appWillResignActive"); + [[Appirater sharedInstance] hideRatingAlert]; +} + ++ (void)appEnteredForeground:(BOOL)canPromptForRating { + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), + ^{ + [[Appirater sharedInstance] incrementAndRate:canPromptForRating]; + }); +} + ++ (void)userDidSignificantEvent:(BOOL)canPromptForRating { + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), + ^{ + [[Appirater sharedInstance] incrementSignificantEventAndRate:canPromptForRating]; + }); +} + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-implementations" ++ (void)showPrompt { + [Appirater tryToShowPrompt]; +} +#pragma GCC diagnostic pop + ++ (void)tryToShowPrompt { + [[Appirater sharedInstance] showPromptWithChecks:true + displayRateLaterButton:true]; +} + ++ (void)forceShowPrompt:(BOOL)displayRateLaterButton { + [[Appirater sharedInstance] showPromptWithChecks:false + displayRateLaterButton:displayRateLaterButton]; +} + +- (void)showPromptWithChecks:(BOOL)withChecks + displayRateLaterButton:(BOOL)displayRateLaterButton { + if (withChecks == NO || [self ratingAlertIsAppropriate]) { + [self showRatingAlert:displayRateLaterButton]; + } +} + ++ (id)getRootViewController { + UIWindow *window = [[UIApplication sharedApplication] keyWindow]; + if (window.windowLevel != UIWindowLevelNormal) { + NSArray *windows = [[UIApplication sharedApplication] windows]; + for(window in windows) { + if (window.windowLevel == UIWindowLevelNormal) { + break; + } + } + } + + return [Appirater iterateSubViewsForViewController:window]; // iOS 8+ deep traverse +} + ++ (id)iterateSubViewsForViewController:(UIView *) parentView { + for (UIView *subView in [parentView subviews]) { + UIResponder *responder = [subView nextResponder]; + if([responder isKindOfClass:[UIViewController class]]) { + return [self topMostViewController: (UIViewController *) responder]; + } + id found = [Appirater iterateSubViewsForViewController:subView]; + if( nil != found) { + return found; + } + } + return nil; +} + ++ (UIViewController *) topMostViewController: (UIViewController *) controller { + BOOL isPresenting = NO; + do { + // this path is called only on iOS 6+, so -presentedViewController is fine here. + UIViewController *presented = [controller presentedViewController]; + isPresenting = presented != nil; + if(presented != nil) { + controller = presented; + } + + } while (isPresenting); + + return controller; +} + ++ (void)rateApp { + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setBool:YES forKey:kAppiraterRatedCurrentVersion]; + [userDefaults synchronize]; + + //Use the in-app StoreKit view if available (iOS 6) and imported. This works in the simulator. + if (![Appirater sharedInstance].openInAppStore && NSStringFromClass([SKStoreProductViewController class]) != nil) { + + SKStoreProductViewController *storeViewController = [[SKStoreProductViewController alloc] init]; + NSNumber *appId = [NSNumber numberWithInteger:_appId.integerValue]; + [storeViewController loadProductWithParameters:@{SKStoreProductParameterITunesItemIdentifier:appId} completionBlock:nil]; + storeViewController.delegate = self.sharedInstance; + + id delegate = self.sharedInstance.delegate; + if ([delegate respondsToSelector:@selector(appiraterWillPresentModalView:animated:)]) { + [delegate appiraterWillPresentModalView:self.sharedInstance animated:_usesAnimation]; + } + [[self getRootViewController] presentViewController:storeViewController animated:_usesAnimation completion:^{ + [self setModalOpen:YES]; + //Temporarily use a black status bar to match the StoreKit view. + [self setStatusBarStyle:[UIApplication sharedApplication].statusBarStyle]; +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 + [[UIApplication sharedApplication]setStatusBarStyle:UIStatusBarStyleLightContent animated:_usesAnimation]; +#endif + }]; + + //Use the standard openUrl method if StoreKit is unavailable. + } else { + + #if TARGET_IPHONE_SIMULATOR + NSLog(@"APPIRATER NOTE: iTunes App Store is not supported on the iOS simulator. Unable to open App Store page."); + #else + NSString *reviewURL = [templateReviewURL stringByReplacingOccurrencesOfString:@"APP_ID" withString:[NSString stringWithFormat:@"%@", _appId]]; + + // iOS 7 needs a different templateReviewURL @see https://github.com/arashpayan/appirater/issues/131 + // Fixes condition @see https://github.com/arashpayan/appirater/issues/205 + if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0 && [[[UIDevice currentDevice] systemVersion] floatValue] < 8.0) { + reviewURL = [templateReviewURLiOS7 stringByReplacingOccurrencesOfString:@"APP_ID" withString:[NSString stringWithFormat:@"%@", _appId]]; + } + // iOS 8 needs a different templateReviewURL also @see https://github.com/arashpayan/appirater/issues/182 + else if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0) + { + reviewURL = [templateReviewURLiOS8 stringByReplacingOccurrencesOfString:@"APP_ID" withString:[NSString stringWithFormat:@"%@", _appId]]; + } + + [[UIApplication sharedApplication] openURL:[NSURL URLWithString:reviewURL]]; + #endif + } +} + +- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex { + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + + id delegate = _delegate; + + switch (buttonIndex) { + case 0: + { + // they don't want to rate it + [userDefaults setBool:YES forKey:kAppiraterDeclinedToRate]; + [userDefaults synchronize]; + if(delegate && [delegate respondsToSelector:@selector(appiraterDidDeclineToRate:)]){ + [delegate appiraterDidDeclineToRate:self]; + } + break; + } + case 1: + { + // they want to rate it + [Appirater rateApp]; + if(delegate&& [delegate respondsToSelector:@selector(appiraterDidOptToRate:)]){ + [delegate appiraterDidOptToRate:self]; + } + break; + } + case 2: + // remind them later + [userDefaults setDouble:[[NSDate date] timeIntervalSince1970] forKey:kAppiraterReminderRequestDate]; + [userDefaults synchronize]; + if(delegate && [delegate respondsToSelector:@selector(appiraterDidOptToRemindLater:)]){ + [delegate appiraterDidOptToRemindLater:self]; + } + break; + default: + break; + } +} + +//Delegate call from the StoreKit view. +- (void)productViewControllerDidFinish:(SKStoreProductViewController *)viewController { + [Appirater closeModal]; +} + +//Close the in-app rating (StoreKit) view and restore the previous status bar style. ++ (void)closeModal { + if (_modalOpen) { + [[UIApplication sharedApplication]setStatusBarStyle:_statusBarStyle animated:_usesAnimation]; + BOOL usedAnimation = _usesAnimation; + [self setModalOpen:NO]; + + // get the top most controller (= the StoreKit Controller) and dismiss it + UIViewController *presentingController = [UIApplication sharedApplication].keyWindow.rootViewController; + presentingController = [self topMostViewController: presentingController]; + [presentingController dismissViewControllerAnimated:_usesAnimation completion:^{ + id delegate = self.sharedInstance.delegate; + if ([delegate respondsToSelector:@selector(appiraterDidDismissModalView:animated:)]) { + [delegate appiraterDidDismissModalView:(Appirater *)self animated:usedAnimation]; + } + }]; + [self.class setStatusBarStyle:(UIStatusBarStyle)nil]; + } +} + +@end diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/Appirater/AppiraterDelegate.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/Appirater/AppiraterDelegate.h Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,23 @@ +// +// AppiraterDelegate.h +// Banana Stand +// +// Created by Robert Haining on 9/25/12. +// Copyright (c) 2012 News.me. All rights reserved. +// + +#import + +@class Appirater; + +@protocol AppiraterDelegate + +@optional +-(BOOL)appiraterShouldDisplayAlert:(Appirater *)appirater; +-(void)appiraterDidDisplayAlert:(Appirater *)appirater; +-(void)appiraterDidDeclineToRate:(Appirater *)appirater; +-(void)appiraterDidOptToRate:(Appirater *)appirater; +-(void)appiraterDidOptToRemindLater:(Appirater *)appirater; +-(void)appiraterWillPresentModalView:(Appirater *)appirater animated:(BOOL)animated; +-(void)appiraterDidDismissModalView:(Appirater *)appirater animated:(BOOL)animated; +@end diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/AudioManagerController.h --- a/project_files/HedgewarsMobile/Classes/AudioManagerController.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/AudioManagerController.h Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/AudioManagerController.m --- a/project_files/HedgewarsMobile/Classes/AudioManagerController.m Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/AudioManagerController.m Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/CGPointUtils.c --- a/project_files/HedgewarsMobile/Classes/CGPointUtils.c Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/CGPointUtils.c Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/CGPointUtils.h --- a/project_files/HedgewarsMobile/Classes/CGPointUtils.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/CGPointUtils.h Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/CreationChamber.h --- a/project_files/HedgewarsMobile/Classes/CreationChamber.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/CreationChamber.h Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/CreationChamber.m --- a/project_files/HedgewarsMobile/Classes/CreationChamber.m Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/CreationChamber.m Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ @@ -57,7 +57,7 @@ [[NSFileManager defaultManager] removeItemAtPath:SCHEMES_DIRECTORY() error:NULL]; NSArray *schemeNames = [[NSArray alloc] initWithObjects:@"Default",@"Pro Mode",@"Shoppa",@"Clean Slate", @"Minefield",@"Barrel Mayhem",@"Tunnel Hogs",@"Fort Mode",@"Timeless", - @"Thinking with Portals",@"King Mode",nil]; + @"Thinking with Portals",@"King Mode",@"Construction Mode",nil]; index = 0; for (NSString *name in schemeNames) [self createSchemeNamed:name ofType:index++]; @@ -65,7 +65,7 @@ // WEAPONS - always overwrite as merge is not needed (missing weaps are 0ed automatically) NSArray *weaponNames = [[NSArray alloc] initWithObjects:@"Default",@"Crazy",@"Pro Mode",@"Shoppa",@"Clean Slate", - @"Minefield",@"Thinking with Portals",nil]; + @"Minefield",@"Thinking with Portals",@"One of Everything",@"Highlander",@"Construction Mode",@"Shoppa Pro",nil]; index = 0; for (NSString *name in weaponNames) [self createWeaponNamed:name ofType:index++]; @@ -241,6 +241,30 @@ delay = [[NSString alloc] initWithBytes:AMMOLINE_PORTALS_DELAY length:ammolineSize encoding:NSUTF8StringEncoding]; crate = [[NSString alloc] initWithBytes:AMMOLINE_PORTALS_CRATE length:ammolineSize encoding:NSUTF8StringEncoding]; break; + case 7: //one of everything + qt = [[NSString alloc] initWithBytes:AMMOLINE_ONEEVERY_QT length:ammolineSize encoding:NSUTF8StringEncoding]; + prob = [[NSString alloc] initWithBytes:AMMOLINE_ONEEVERY_PROB length:ammolineSize encoding:NSUTF8StringEncoding]; + delay = [[NSString alloc] initWithBytes:AMMOLINE_ONEEVERY_DELAY length:ammolineSize encoding:NSUTF8StringEncoding]; + crate = [[NSString alloc] initWithBytes:AMMOLINE_ONEEVERY_CRATE length:ammolineSize encoding:NSUTF8StringEncoding]; + break; + case 8: //highlander + qt = [[NSString alloc] initWithBytes:AMMOLINE_HIGHLANDER_QT length:ammolineSize encoding:NSUTF8StringEncoding]; + prob = [[NSString alloc] initWithBytes:AMMOLINE_HIGHLANDER_PROB length:ammolineSize encoding:NSUTF8StringEncoding]; + delay = [[NSString alloc] initWithBytes:AMMOLINE_HIGHLANDER_DELAY length:ammolineSize encoding:NSUTF8StringEncoding]; + crate = [[NSString alloc] initWithBytes:AMMOLINE_HIGHLANDER_CRATE length:ammolineSize encoding:NSUTF8StringEncoding]; + break; + case 9: //construction mode + qt = [[NSString alloc] initWithBytes:AMMOLINE_CONSTRUCTION_QT length:ammolineSize encoding:NSUTF8StringEncoding]; + prob = [[NSString alloc] initWithBytes:AMMOLINE_CONSTRUCTION_PROB length:ammolineSize encoding:NSUTF8StringEncoding]; + delay = [[NSString alloc] initWithBytes:AMMOLINE_CONSTRUCTION_DELAY length:ammolineSize encoding:NSUTF8StringEncoding]; + crate = [[NSString alloc] initWithBytes:AMMOLINE_CONSTRUCTION_CRATE length:ammolineSize encoding:NSUTF8StringEncoding]; + break; + case 10: //shoppa pro + qt = [[NSString alloc] initWithBytes:AMMOLINE_SHOPPAPRO_QT length:ammolineSize encoding:NSUTF8StringEncoding]; + prob = [[NSString alloc] initWithBytes:AMMOLINE_SHOPPAPRO_PROB length:ammolineSize encoding:NSUTF8StringEncoding]; + delay = [[NSString alloc] initWithBytes:AMMOLINE_SHOPPAPRO_DELAY length:ammolineSize encoding:NSUTF8StringEncoding]; + crate = [[NSString alloc] initWithBytes:AMMOLINE_SHOPPAPRO_CRATE length:ammolineSize encoding:NSUTF8StringEncoding]; + break; } NSDictionary *theWeapon = [[NSDictionary alloc] initWithObjectsAndKeys: qt,@"ammostore_initialqt", @@ -303,6 +327,7 @@ [basicArray replaceObjectAtIndex:9 withObject:[NSNumber numberWithInt:25]]; [basicArray replaceObjectAtIndex:11 withObject:[NSNumber numberWithInt:0]]; [basicArray replaceObjectAtIndex:13 withObject:[NSNumber numberWithInt:0]]; + [basicArray replaceObjectAtIndex:15 withObject:[NSNumber numberWithInt:8]]; [gamemodArray replaceObjectAtIndex:1 withObject:[NSNumber numberWithBool:YES]]; [gamemodArray replaceObjectAtIndex:2 withObject:[NSNumber numberWithBool:YES]]; [gamemodArray replaceObjectAtIndex:11 withObject:[NSNumber numberWithBool:YES]]; @@ -342,6 +367,7 @@ [basicArray replaceObjectAtIndex:11 withObject:[NSNumber numberWithInt:10]]; [basicArray replaceObjectAtIndex:12 withObject:[NSNumber numberWithInt:10]]; [basicArray replaceObjectAtIndex:13 withObject:[NSNumber numberWithInt:10]]; + [basicArray replaceObjectAtIndex:15 withObject:[NSNumber numberWithInt:4]]; [gamemodArray replaceObjectAtIndex:2 withObject:[NSNumber numberWithBool:YES]]; [gamemodArray replaceObjectAtIndex:11 withObject:[NSNumber numberWithBool:YES]]; [gamemodArray replaceObjectAtIndex:14 withObject:[NSNumber numberWithBool:YES]]; @@ -373,6 +399,7 @@ [basicArray replaceObjectAtIndex:10 withObject:[NSNumber numberWithInt:4]]; [basicArray replaceObjectAtIndex:11 withObject:[NSNumber numberWithInt:5]]; [basicArray replaceObjectAtIndex:13 withObject:[NSNumber numberWithInt:5]]; + [basicArray replaceObjectAtIndex:15 withObject:[NSNumber numberWithInt:4]]; [gamemodArray replaceObjectAtIndex:9 withObject:[NSNumber numberWithBool:YES]]; [gamemodArray replaceObjectAtIndex:11 withObject:[NSNumber numberWithBool:YES]]; break; @@ -380,6 +407,15 @@ [gamemodArray replaceObjectAtIndex:11 withObject:[NSNumber numberWithBool:YES]]; [gamemodArray replaceObjectAtIndex:12 withObject:[NSNumber numberWithBool:YES]]; break; + case 11: // construction mode + [basicArray replaceObjectAtIndex:11 withObject:[NSNumber numberWithInt:0]]; + [basicArray replaceObjectAtIndex:13 withObject:[NSNumber numberWithInt:0]]; + [gamemodArray replaceObjectAtIndex:11 withObject:[NSNumber numberWithBool:YES]]; + [gamemodArray replaceObjectAtIndex:15 withObject:[NSNumber numberWithBool:YES]]; + [gamemodArray replaceObjectAtIndex:16 withObject:[NSNumber numberWithBool:YES]]; + [gamemodArray replaceObjectAtIndex:18 withObject:[NSNumber numberWithBool:YES]]; + [gamemodArray replaceObjectAtIndex:20 withObject:[NSNumber numberWithBool:YES]]; + break; } NSMutableDictionary *theScheme = [[NSMutableDictionary alloc] initWithObjectsAndKeys: diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/DefinesAndMacros.h --- a/project_files/HedgewarsMobile/Classes/DefinesAndMacros.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/DefinesAndMacros.h Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/EditableCellView.h --- a/project_files/HedgewarsMobile/Classes/EditableCellView.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/EditableCellView.h Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/EditableCellView.m --- a/project_files/HedgewarsMobile/Classes/EditableCellView.m Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/EditableCellView.m Tue Nov 10 20:43:13 2015 +0100 @@ -13,12 +13,12 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ #import "EditableCellView.h" - +#import "UITableViewCell+FindTable.h" @implementation EditableCellView @synthesize delegate, textField, titleLabel, minimumCharacters, maximumCharacters, respectEditing, oldValue; @@ -103,13 +103,13 @@ -(BOOL) textFieldShouldBeginEditing:(UITextField *)aTextField { return (delegate != nil) && [delegate respondsToSelector:@selector(saveTextFieldValue:withTag:)] && - (respectEditing) ? ((UITableView*)[self superview]).editing : YES; + (respectEditing) ? [self findTable].editing : YES; } // the textfield is being modified, update the navigation controller -(void) textFieldDidBeginEditing:(UITextField *)aTextField{ // don't interact with table below - ((UITableView*)[self superview]).scrollEnabled = NO; + [self findTable].scrollEnabled = NO; self.oldValue = self.textField.text; @@ -147,9 +147,9 @@ [self save:aTextField]; // restores default behaviour on caller - ((UITableView*)[self superview]).scrollEnabled = YES; - [(UITableViewController *)delegate navigationItem].rightBarButtonItem = [(UITableViewController *)delegate navigationItem].backBarButtonItem; - [(UITableViewController *)delegate navigationItem].leftBarButtonItem = nil; + [self findTable].scrollEnabled = YES; + [(UITableViewController *)delegate navigationItem].leftBarButtonItem = [(UITableViewController *)delegate navigationItem].backBarButtonItem; + [(UITableViewController *)delegate navigationItem].rightBarButtonItem = nil; } #pragma mark - diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/EngineProtocolNetwork.h --- a/project_files/HedgewarsMobile/Classes/EngineProtocolNetwork.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/EngineProtocolNetwork.h Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/EngineProtocolNetwork.m --- a/project_files/HedgewarsMobile/Classes/EngineProtocolNetwork.m Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/EngineProtocolNetwork.m Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ @@ -96,8 +96,8 @@ for (int i = 0; i < numberOfPlayingHogs; i++) { NSDictionary *hog = [hogs objectAtIndex:i]; - NSString *hogLevelHealthAndName = [[NSString alloc] initWithFormat:@"eaddhh %@ %d %@", - [hog objectForKey:@"level"], initialHealth, [hog objectForKey:@"hogname"]]; + NSString *hogLevelHealthAndName = [[NSString alloc] initWithFormat:@"eaddhh %@ %ld %@", + [hog objectForKey:@"level"], (long)initialHealth, [hog objectForKey:@"hogname"]]; [self sendToEngine: hogLevelHealthAndName]; [hogLevelHealthAndName release]; @@ -197,7 +197,7 @@ // wrapper that computes the length of the message and then sends the command string, saving the command on a file -(int) sendToEngine:(NSString *)string { - uint8_t length = [string length]; + uint8_t length = [string lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; [self dumpRawData:[string UTF8String] ofSize:length]; SDLNet_TCP_Send(csd, &length, 1); @@ -206,7 +206,7 @@ // wrapper that computes the length of the message and then sends the command string, skipping file writing -(int) sendToEngineNoSave:(NSString *)string { - uint8_t length = [string length]; + uint8_t length = [string lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; SDLNet_TCP_Send(csd, &length, 1); return SDLNet_TCP_Send(csd, [string UTF8String], length); @@ -214,7 +214,8 @@ // this is launched as thread and handles all IPC with engine -(void) engineProtocol:(id) object { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + @autoreleasepool { + NSDictionary *gameConfig = (NSDictionary *)object; NSMutableArray *statsArray = nil; TCPsocket sd; @@ -240,7 +241,7 @@ // Open a connection with the IP provided (listen on the host's port) if (!(sd = SDLNet_TCP_Open(&ip)) && !clientQuit) { - DLog(@"SDLNet_TCP_Open: %s %\n", SDLNet_GetError(), self.enginePort); + DLog(@"SDLNet_TCP_Open: %s %d\n", SDLNet_GetError(), self.enginePort); clientQuit = YES; } @@ -340,19 +341,25 @@ NSString *tempStr = [NSString stringWithUTF8String:&buffer[2]]; NSArray *info = [tempStr componentsSeparatedByString:@" "]; NSString *arg = [info objectAtIndex:0]; - int index = [arg length] + 3; + int index = [arg lengthOfBytesUsingEncoding:NSUTF8StringEncoding] + 3; switch (buffer[1]) { case 'r': // winning team [statsArray insertObject:[NSString stringWithUTF8String:&buffer[2]] atIndex:1]; break; case 'D': // best shot - [statsArray addObject:[NSString stringWithFormat:@"The best shot award won by %s (with %@ points)", &buffer[index], arg]]; + { + NSString *hogName = [NSString stringWithUTF8String:&buffer[index]]; + [statsArray addObject:[NSString stringWithFormat:NSLocalizedString(@"The best shot award won by %@ (with %@ points)", nil), hogName, arg]]; break; + } case 'k': // best hedgehog - [statsArray addObject:[NSString stringWithFormat:@"The best killer is %s with %@ kill(s) in a turn", &buffer[index], arg]]; + { + NSString *hogName = [NSString stringWithUTF8String:&buffer[index]]; + [statsArray addObject:[NSString stringWithFormat:NSLocalizedString(@"The best killer is %@ with %@ kill(s) in a turn", nil), hogName, arg]]; break; + } case 'K': // number of hogs killed - [statsArray addObject:[NSString stringWithFormat:@"%@ hedgehog(s) were killed during this round", arg]]; + [statsArray addObject:[NSString stringWithFormat:NSLocalizedString(@"%@ hedgehog(s) were killed during this round", nil), arg]]; break; case 'H': // team health/graph break; @@ -363,14 +370,23 @@ [[statsArray objectAtIndex:0] addObject:tempStr]; break; case 's': // self damage - [statsArray addObject:[NSString stringWithFormat:@"%s thought it's good to shoot his own hedgehogs with %@ points", &buffer[index], arg]]; + { + NSString *hogName = [NSString stringWithUTF8String:&buffer[index]]; + [statsArray addObject:[NSString stringWithFormat:NSLocalizedString(@"%@ thought it's good to shoot his own hedgehogs with %@ points", nil), hogName, arg]]; break; + } case 'S': // friendly fire - [statsArray addObject:[NSString stringWithFormat:@"%s killed %@ of his own hedgehogs", &buffer[index], arg]]; + { + NSString *hogName = [NSString stringWithUTF8String:&buffer[index]]; + [statsArray addObject:[NSString stringWithFormat:NSLocalizedString(@"%@ killed %@ of his own hedgehogs", nil), hogName, arg]]; break; + } case 'B': // turn skipped - [statsArray addObject:[NSString stringWithFormat:@"%s was scared and skipped turn %@ times", &buffer[index], arg]]; + { + NSString *hogName = [NSString stringWithUTF8String:&buffer[index]]; + [statsArray addObject:[NSString stringWithFormat:NSLocalizedString(@"%@ was scared and skipped turn %@ times", nil), hogName, arg]]; break; + } default: DLog(@"Unhandled stat message, see statsPage.cpp"); break; @@ -403,8 +419,9 @@ [HWUtils freePort:self.enginePort]; SDLNet_TCP_Close(csd); SDLNet_Quit(); + + } - [pool release]; // Invoking this method should be avoided as it does not give your thread a chance // to clean up any resources it allocated during its execution. //[NSThread exit]; diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/ExtraCategories.h --- a/project_files/HedgewarsMobile/Classes/ExtraCategories.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/ExtraCategories.h Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ @@ -50,6 +50,9 @@ -(id) initWithFrame:(CGRect) frame andTitle:(NSString *)title; +- (void)applyBlackQuickStyle; +- (void)applyDarkBlueQuickStyle; + @end diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/ExtraCategories.m --- a/project_files/HedgewarsMobile/Classes/ExtraCategories.m Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/ExtraCategories.m Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ @@ -27,17 +27,18 @@ -(CGFloat) safeScale { CGFloat theScale = 1.0f; - if ([self respondsToSelector:@selector(scale)]) - theScale = [self scale]; +// if ([self respondsToSelector:@selector(scale)]) +// theScale = [self scale]; return theScale; } -(CGRect) safeBounds { - CGRect original = [self bounds]; - if (IS_ON_PORTRAIT()) - return original; - else - return CGRectMake(original.origin.x, original.origin.y, original.size.height, original.size.width); + return [self bounds]; +// CGRect original = [self bounds]; +// if (IS_ON_PORTRAIT()) +// return original; +// else +// return CGRectMake(original.origin.x, original.origin.y, original.size.height, original.size.width); } @end @@ -99,17 +100,35 @@ -(id) initWithFrame:(CGRect) frame andTitle:(NSString *)title { [self initWithFrame:frame]; [self setTitle:title forState:UIControlStateNormal]; + [self applyBlackQuickStyle]; + + return self; +} + +- (void)applyBlackQuickStyle +{ [self setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; [self setTitleColor:[UIColor grayColor] forState:UIControlStateHighlighted]; self.titleLabel.font = [UIFont boldSystemFontOfSize:[UIFont labelFontSize]]; self.backgroundColor = [UIColor blackColorTransparent]; - - [self.layer setBorderWidth:1]; + + [self.layer setBorderWidth:1.0f]; [self.layer setBorderColor:[[UIColor darkYellowColor] CGColor]]; [self.layer setCornerRadius:9.0f]; [self.layer setMasksToBounds:YES]; +} - return self; +- (void)applyDarkBlueQuickStyle +{ + [self setTitleColor:[UIColor darkYellowColor] forState:UIControlStateNormal]; + [self setTitleColor:[UIColor grayColor] forState:UIControlStateHighlighted]; + self.titleLabel.font = [UIFont boldSystemFontOfSize:[UIFont labelFontSize]]; + self.backgroundColor = [UIColor darkBlueColorTransparent]; + + [self.layer setBorderWidth:2.0f]; + [self.layer setBorderColor:[[UIColor darkYellowColor] CGColor]]; + [self.layer setCornerRadius:9.0f]; + [self.layer setMasksToBounds:YES]; } @end diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/FlagsViewController.h --- a/project_files/HedgewarsMobile/Classes/FlagsViewController.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/FlagsViewController.h Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/FlagsViewController.m --- a/project_files/HedgewarsMobile/Classes/FlagsViewController.m Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/FlagsViewController.m Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ @@ -131,10 +131,10 @@ #pragma mark - #pragma mark Table view delegate -(void) tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - int newRow = [indexPath row]; - int oldRow = (lastIndexPath != nil) ? [lastIndexPath row] : -1; - int newSection = [indexPath section]; - int oldSection = (lastIndexPath != nil) ? [lastIndexPath section] : -1; + NSInteger newRow = [indexPath row]; + NSInteger oldRow = (lastIndexPath != nil) ? [lastIndexPath row] : -1; + NSInteger newSection = [indexPath section]; + NSInteger oldSection = (lastIndexPath != nil) ? [lastIndexPath section] : -1; if (newRow != oldRow || newSection != oldSection) { NSString *flag = nil; diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/FortsViewController.h --- a/project_files/HedgewarsMobile/Classes/FortsViewController.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/FortsViewController.h Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/FortsViewController.m --- a/project_files/HedgewarsMobile/Classes/FortsViewController.m Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/FortsViewController.m Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ @@ -38,11 +38,13 @@ NSArray *directoryContents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:FORTS_DIRECTORY() error:NULL]; NSMutableArray *filteredContents = [[NSMutableArray alloc] initWithCapacity:([directoryContents count] / IMGNUM_PER_FORT)]; - // we need to remove the double entries and the L.png suffix - for (NSUInteger i = 0; i < [directoryContents count]; i++) { - if (i % IMGNUM_PER_FORT == IMGNUM_PER_FORT-1) { - NSString *currentName = [directoryContents objectAtIndex:i]; - NSString *correctName = [currentName substringToIndex:([currentName length] - 5)]; + // we assume here that fort's images has one image with the 'L.png' suffix and we remove this suffix to get the correct name + for (NSUInteger i = 0; i < [directoryContents count]; i++) + { + NSString *currentName = [directoryContents objectAtIndex:i]; + if ([currentName rangeOfString:@"L.png"].location != NSNotFound) + { + NSString *correctName = [currentName stringByReplacingOccurrencesOfString:@"L.png" withString:@""]; [filteredContents addObject:correctName]; } } @@ -106,8 +108,8 @@ #pragma mark - #pragma mark Table view delegate -(void) tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - int newRow = [indexPath row]; - int oldRow = (lastIndexPath != nil) ? [lastIndexPath row] : -1; + NSInteger newRow = [indexPath row]; + NSInteger oldRow = (lastIndexPath != nil) ? [lastIndexPath row] : -1; if (newRow != oldRow) { // if the two selected rows differ update data on the hog dictionary and reload table content diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/GameConfigViewController-iPad.xib --- a/project_files/HedgewarsMobile/Classes/GameConfigViewController-iPad.xib Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/GameConfigViewController-iPad.xib Tue Nov 10 20:43:13 2015 +0100 @@ -1,34 +1,28 @@ - + - 1056 - 10K549 - 823 - 1038.36 - 461.00 + 1792 + 14E46 + 7706 + 1348.17 + 758.70 com.apple.InterfaceBuilder.IBCocoaTouchPlugin - 132 - - - YES - - - - YES - com.apple.InterfaceBuilder.IBCocoaTouchPlugin + 7703 - - YES - - YES - - - YES - - - - YES + + IBProxyObject + IBUIButton + IBUIImageView + IBUISlider + IBUIView + IBUIViewController + + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + IBFilesOwner IBIPadFramework @@ -38,10 +32,9 @@ IBIPadFramework - - 292 - - YES + + 256 + 274 @@ -66,7 +59,7 @@ IBIPadFramework NSImage - title~iphone.png + title.png @@ -79,19 +72,14 @@ IBIPadFramework 0 0 - - Helvetica-Bold - 15 - 16 + + 1 + MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA 3 MQA - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - 3 MC41AA @@ -100,6 +88,17 @@ NSImage startGameButton.png + + Helvetica-Bold + Helvetica + 2 + 15 + + + Helvetica-Bold + 15 + 16 + @@ -110,17 +109,18 @@ IBIPadFramework 0 0 - - 1 MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA + NSImage backButton.png + + @@ -132,17 +132,18 @@ IBIPadFramework 0 0 - - 1 MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA + NSImage helpButton.png + + @@ -179,27 +180,47 @@ 0.05000000074505806 0.05000000074505806 - + {1024, 768} - YES + 3 3 + + IBUIScreenMetrics + IBIPadFramework + iPad Full Screen + + YES + + + + + + {768, 1024} + {1024, 768} + + + 1 + IBIPadFramework NO + 3 3 + IBIPadFramework YES NO + IBIPadFramework YES @@ -207,13 +228,13 @@ NO MapConfigViewController-iPad + IBIPadFramework YES - + - - YES + view @@ -223,6 +244,47 @@ 3 + + teamConfigViewController + + + + 45 + + + + schemeWeaponConfigViewController + + + + 51 + + + + mapConfigViewController + + + + 57 + + + + titleImage + + + + 68 + + + + buttonPressed: + + + 7 + + 36 + + buttonPressed: @@ -234,15 +296,6 @@ buttonPressed: - - - 7 - - 36 - - - - buttonPressed: 7 @@ -251,14 +304,6 @@ - teamConfigViewController - - - - 45 - - - view @@ -275,19 +320,11 @@ - schemeWeaponConfigViewController - - + slider + + - 51 - - - - mapConfigViewController - - - - 57 + 69 @@ -307,29 +344,12 @@ 67 - - - titleImage - - - - 68 - - - - slider - - - - 69 - - + - - YES + 0 - + @@ -347,8 +367,7 @@ 2 - - YES + @@ -357,7 +376,7 @@ - + @@ -393,17 +412,13 @@ 44 - - YES - + 46 - - YES - + TeamConfigViewController View @@ -429,650 +444,52 @@ Filter Slider - + - - YES - - YES - -1.CustomClassName - -2.CustomClassName - 2.IBEditorWindowLastContentRect - 2.IBPluginDependency - 30.IBPluginDependency - 30.IBViewBoundsToFrameTransform - 31.IBPluginDependency - 31.IBViewBoundsToFrameTransform - 32.IBPluginDependency - 32.IBViewBoundsToFrameTransform - 33.IBPluginDependency - 33.IBViewBoundsToFrameTransform - 34.IBPluginDependency - 34.IBViewBoundsToFrameTransform - 44.CustomClassName - 44.IBEditorWindowLastContentRect - 44.IBPluginDependency - 46.IBPluginDependency - 46.IBViewBoundsToFrameTransform - 48.CustomClassName - 48.IBEditorWindowLastContentRect - 48.IBPluginDependency - 49.IBPluginDependency - 49.IBViewBoundsToFrameTransform - 55.CustomClassName - 55.IBEditorWindowLastContentRect - 55.IBPluginDependency - 60.CustomClassName - 60.IBPluginDependency - 60.IBViewBoundsToFrameTransform - - - YES - GameConfigViewController - UIResponder - {{252, 239}, {1024, 768}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABAoAAAxLrgAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDtQAAxGNAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABD3wAAxLqgAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABByAAAxLmAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABEbEAAxLmAAA - - TeamConfigViewController - {{63, 355}, {1024, 768}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUOogABDOwAAA - - SchemeWeaponConfigViewController - {{84, 388}, {1024, 768}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAAAAAAAAxHqAAA - - MapConfigViewController - {{126, 377}, {1024, 768}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - MNEValueTrackingSlider - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUNRAABEMoAAA - - - - - YES - - - YES - - + + GameConfigViewController + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + UIResponder + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + TeamConfigViewController + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + SchemeWeaponConfigViewController + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + MapConfigViewController + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + MNEValueTrackingSlider + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + - - YES - - - YES - - + 69 - - - YES - - GameConfigViewController - UIViewController - - YES - - YES - buttonPressed: - segmentPressed: - - - YES - id - id - - - - YES - - YES - buttonPressed: - segmentPressed: - - - YES - - buttonPressed: - id - - - segmentPressed: - id - - - - - YES - - YES - mapConfigViewController - schemeWeaponConfigViewController - teamConfigViewController - titleImage - - - YES - MapConfigViewController - SchemeWeaponConfigViewController - TeamConfigViewController - UIImageView - - - - YES - - YES - mapConfigViewController - schemeWeaponConfigViewController - teamConfigViewController - titleImage - - - YES - - mapConfigViewController - MapConfigViewController - - - schemeWeaponConfigViewController - SchemeWeaponConfigViewController - - - teamConfigViewController - TeamConfigViewController - - - titleImage - UIImageView - - - - - IBProjectSource - Classes/GameConfigViewController.h - - - - MNEValueTrackingSlider - UISlider - - IBProjectSource - Classes/MNEValueTrackingSlider.h - - - - MapConfigViewController - UIViewController - - YES - - YES - mapButtonPressed: - segmentedControlChanged: - sliderChanged: - sliderEndedChanging: - - - YES - id - id - id - id - - - - YES - - YES - mapButtonPressed: - segmentedControlChanged: - sliderChanged: - sliderEndedChanging: - - - YES - - mapButtonPressed: - id - - - segmentedControlChanged: - id - - - sliderChanged: - id - - - sliderEndedChanging: - id - - - - - YES - - YES - maxLabel - previewButton - segmentedControl - slider - tableView - - - YES - UILabel - MapPreviewButtonView - UISegmentedControl - MNEValueTrackingSlider - UITableView - - - - YES - - YES - maxLabel - previewButton - segmentedControl - slider - tableView - - - YES - - maxLabel - UILabel - - - previewButton - MapPreviewButtonView - - - segmentedControl - UISegmentedControl - - - slider - MNEValueTrackingSlider - - - tableView - UITableView - - - - - IBProjectSource - Classes/MapConfigViewController.h - - - - MapPreviewButtonView - UIButton - - delegate - id - - - delegate - - delegate - id - - - - IBProjectSource - Classes/MapPreviewButtonView.h - - - - SchemeWeaponConfigViewController - UIViewController - - IBProjectSource - Classes/SchemeWeaponConfigViewController.h - - - - TeamConfigViewController - UIViewController - - IBProjectSource - Classes/TeamConfigViewController.h - - - - UIButton - - IBProjectSource - Classes/ExtraCategories.h - - - - UILabel - - - - UITableView - - - - - YES - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSError.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSFileManager.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueCoding.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueObserving.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyedArchiver.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSObject.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSRunLoop.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSThread.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURL.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURLConnection.h - - - - NSObject - - IBFrameworkSource - QuartzCore.framework/Headers/CAAnimation.h - - - - NSObject - - IBFrameworkSource - QuartzCore.framework/Headers/CALayer.h - - - - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UIAccessibility.h - - - - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UINibLoading.h - - - - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UIResponder.h - - - - UIButton - UIControl - - IBFrameworkSource - UIKit.framework/Headers/UIButton.h - - - - UIControl - UIView - - IBFrameworkSource - UIKit.framework/Headers/UIControl.h - - - - UIImageView - UIView - - IBFrameworkSource - UIKit.framework/Headers/UIImageView.h - - - - UILabel - UIView - - IBFrameworkSource - UIKit.framework/Headers/UILabel.h - - - - UIResponder - NSObject - - - - UIScrollView - UIView - - IBFrameworkSource - UIKit.framework/Headers/UIScrollView.h - - - - UISearchBar - UIView - - IBFrameworkSource - UIKit.framework/Headers/UISearchBar.h - - - - UISearchDisplayController - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UISearchDisplayController.h - - - - UISegmentedControl - UIControl - - IBFrameworkSource - UIKit.framework/Headers/UISegmentedControl.h - - - - UISlider - UIControl - - IBFrameworkSource - UIKit.framework/Headers/UISlider.h - - - - UITableView - UIScrollView - - IBFrameworkSource - UIKit.framework/Headers/UITableView.h - - - - UIView - - IBFrameworkSource - UIKit.framework/Headers/UIPrintFormatter.h - - - - UIView - - IBFrameworkSource - UIKit.framework/Headers/UITextField.h - - - - UIView - UIResponder - - IBFrameworkSource - UIKit.framework/Headers/UIView.h - - - - UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UINavigationController.h - - - - UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UIPopoverController.h - - - - UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UISplitViewController.h - - - - UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UITabBarController.h - - - - UIViewController - UIResponder - - IBFrameworkSource - UIKit.framework/Headers/UIViewController.h - - - - + 0 IBIPadFramework - - com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS - - + NO com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 - + YES - ../Hedgewars.xcodeproj 3 - - YES - - YES - backButton.png - background.png - helpButton.png - startGameButton.png - title~iphone.png - - - YES - {64, 64} - {1024, 768} - {64, 64} - {142, 64} - {270, 150} - - - 132 + + {64, 64} + {1024, 768} + {64, 64} + {142, 64} + {540, 300} + diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/GameConfigViewController-iPhone.xib --- a/project_files/HedgewarsMobile/Classes/GameConfigViewController-iPhone.xib Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/GameConfigViewController-iPhone.xib Tue Nov 10 20:43:13 2015 +0100 @@ -1,1014 +1,105 @@ - - - - 1056 - 10K549 - 823 - 1038.36 - 461.00 - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - 132 - - - YES - - - - - YES - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - YES - - YES - - - YES - - - - YES - - IBFilesOwner - IBCocoaTouchFramework - - - IBFirstResponder - IBCocoaTouchFramework - - - - 292 - - YES - - - 266 - - YES - - - 292 - {{96, 8}, {270, 30}} - - NO - 12345 - IBCocoaTouchFramework - 2 - 4 - 0 - - YES - Map - Teams - Details - Help - - - YES - - - - - - - YES - - - - - - - YES - {0, 0} - {0, 0} - {0, 0} - {0, 0} - - - YES - - - - - - - 1 - MC42IDAuNiAwLjYAA - - - - {{0, 276}, {480, 44}} - - NO - NO - IBCocoaTouchFramework - 1 - - YES - - Back - IBCocoaTouchFramework - 1 - - - - IBCocoaTouchFramework - - 5 - - - IBCocoaTouchFramework - - - - - IBCocoaTouchFramework - - 5 - - - 1 - Start - IBCocoaTouchFramework - 68 - 2 - - - - - - - 274 - {480, 276} - - - 3 - MQA - - 2 - - - YES - IBCocoaTouchFramework - - - - 274 - {480, 276} - - - 3 - MQA - - - YES - IBCocoaTouchFramework - - - {480, 320} - - - 3 - MQA - - NO - - 3 - - IBCocoaTouchFramework - - - MapConfigViewController-iPhone - - - 3 - - IBCocoaTouchFramework - YES - - - - 1 - - - IBCocoaTouchFramework - YES - - - - - IBCocoaTouchFramework - YES - - - - - YES - - - view - - - - 3 - - - - buttonPressed: - - - - 17 - - - - buttonPressed: - - - - 23 - - - - segmentPressed: - - - 13 - - 29 - - - - mapConfigViewController - - - - 33 - - - - teamConfigViewController - - - - 34 - - - - schemeWeaponConfigViewController - - - - 35 - - - - view - - - - 42 - - - - view - - - - 43 - - - - - YES - - 0 - - - - - - -1 - - - File's Owner - - - -2 - - - - - 2 - - - YES - - - - - - - - 15 - - - YES - - - - - - - - - - 16 - - - - - 18 - - - - - 19 - - - - - 21 - - - YES - - - - - - 20 - - - - - 22 - - - - - 30 - - - - - 31 - - - - - 32 - - - - - 40 - - - TeamConfigViewController View - - - 41 - - - SchemeWeaponConfigViewController View - - - - - YES - - YES - -1.CustomClassName - -2.CustomClassName - 15.IBPluginDependency - 15.IBViewBoundsToFrameTransform - 16.IBPluginDependency - 18.IBPluginDependency - 19.IBPluginDependency - 2.IBEditorWindowLastContentRect - 2.IBPluginDependency - 20.IBPluginDependency - 22.IBPluginDependency - 30.CustomClassName - 30.IBEditorWindowLastContentRect - 30.IBPluginDependency - 31.CustomClassName - 31.IBEditorWindowLastContentRect - 31.IBPluginDependency - 32.CustomClassName - 32.IBEditorWindowLastContentRect - 32.IBPluginDependency - 40.IBPluginDependency - 40.IBViewBoundsToFrameTransform - 41.IBPluginDependency - 41.IBViewBoundsToFrameTransform - - - YES - GameConfigViewController - UIResponder - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAAAAAAAAw58AAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - {{40, 217}, {480, 320}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - MapConfigViewController - {{0, 825}, {480, 320}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - TeamConfigViewController - {{21, 802}, {480, 320}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - SchemeWeaponConfigViewController - {{42, 779}, {480, 320}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAAAAAAAAw5QAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAAAAAAAAw5QAAA - - - - - YES - - - YES - - - - - YES - - - YES - - - - 45 - - - - YES - - GameConfigViewController - UIViewController - - YES - - YES - buttonPressed: - segmentPressed: - - - YES - id - id - - - - YES - - YES - buttonPressed: - segmentPressed: - - - YES - - buttonPressed: - id - - - segmentPressed: - id - - - - - YES - - YES - mapConfigViewController - schemeWeaponConfigViewController - teamConfigViewController - titleImage - - - YES - MapConfigViewController - SchemeWeaponConfigViewController - TeamConfigViewController - UIImageView - - - - YES - - YES - mapConfigViewController - schemeWeaponConfigViewController - teamConfigViewController - titleImage - - - YES - - mapConfigViewController - MapConfigViewController - - - schemeWeaponConfigViewController - SchemeWeaponConfigViewController - - - teamConfigViewController - TeamConfigViewController - - - titleImage - UIImageView - - - - - IBProjectSource - Classes/GameConfigViewController.h - - - - MapConfigViewController - UIViewController - - YES - - YES - mapButtonPressed: - segmentedControlChanged: - sliderChanged: - sliderEndedChanging: - - - YES - id - id - id - id - - - - YES - - YES - mapButtonPressed: - segmentedControlChanged: - sliderChanged: - sliderEndedChanging: - - - YES - - mapButtonPressed: - id - - - segmentedControlChanged: - id - - - sliderChanged: - id - - - sliderEndedChanging: - id - - - - - YES - - YES - maxLabel - previewButton - segmentedControl - slider - tableView - - - YES - UILabel - MapPreviewButtonView - UISegmentedControl - ValueTrackingSliderView - UITableView - - - - YES - - YES - maxLabel - previewButton - segmentedControl - slider - tableView - - - YES - - maxLabel - UILabel - - - previewButton - MapPreviewButtonView - - - segmentedControl - UISegmentedControl - - - slider - ValueTrackingSliderView - - - tableView - UITableView - - - - - IBProjectSource - Classes/MapConfigViewController.h - - - - MapPreviewButtonView - UIButton - - delegate - id - - - delegate - - delegate - id - - - - IBProjectSource - Classes/MapPreviewButtonView.h - - - - SchemeWeaponConfigViewController - UIViewController - - IBProjectSource - Classes/SchemeWeaponConfigViewController.h - - - - TeamConfigViewController - UIViewController - - IBProjectSource - Classes/TeamConfigViewController.h - - - - UILabel - - IBProjectSource - Classes/ExtraCategories.h - - - - UITableView - - - - ValueTrackingSliderView - UISlider - - IBProjectSource - Classes/MNEValueTrackingSlider.h - - - - - YES - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSError.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSFileManager.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueCoding.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueObserving.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyedArchiver.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSObject.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSRunLoop.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSThread.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURL.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURLConnection.h - - - - NSObject - - IBFrameworkSource - QuartzCore.framework/Headers/CAAnimation.h - - - - NSObject - - IBFrameworkSource - QuartzCore.framework/Headers/CALayer.h - - - - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UIAccessibility.h - - - - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UINibLoading.h - - - - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UIResponder.h - - - - UIBarButtonItem - UIBarItem - - IBFrameworkSource - UIKit.framework/Headers/UIBarButtonItem.h - - - - UIBarItem - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UIBarItem.h - - - - UIButton - UIControl - - IBFrameworkSource - UIKit.framework/Headers/UIButton.h - - - - UIControl - UIView - - IBFrameworkSource - UIKit.framework/Headers/UIControl.h - - - - UIImageView - UIView - - IBFrameworkSource - UIKit.framework/Headers/UIImageView.h - - - - UILabel - UIView - - IBFrameworkSource - UIKit.framework/Headers/UILabel.h - - - - UIResponder - NSObject - - - - UIScrollView - UIView - - IBFrameworkSource - UIKit.framework/Headers/UIScrollView.h - - - - UISearchBar - UIView - - IBFrameworkSource - UIKit.framework/Headers/UISearchBar.h - - - - UISearchDisplayController - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UISearchDisplayController.h - - - - UISegmentedControl - UIControl - - IBFrameworkSource - UIKit.framework/Headers/UISegmentedControl.h - - - - UISlider - UIControl - - IBFrameworkSource - UIKit.framework/Headers/UISlider.h - - - - UITableView - UIScrollView - - IBFrameworkSource - UIKit.framework/Headers/UITableView.h - - - - UIToolbar - UIView - - IBFrameworkSource - UIKit.framework/Headers/UIToolbar.h - - - - UIView - - IBFrameworkSource - UIKit.framework/Headers/UIPrintFormatter.h - - - - UIView - - IBFrameworkSource - UIKit.framework/Headers/UITextField.h - - - - UIView - UIResponder - - IBFrameworkSource - UIKit.framework/Headers/UIView.h - - - - UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UINavigationController.h - - - - UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UIPopoverController.h - - - - UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UISplitViewController.h - - - - UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UITabBarController.h - - - - UIViewController - UIResponder - - IBFrameworkSource - UIKit.framework/Headers/UIViewController.h - - - - - 0 - IBCocoaTouchFramework - - com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS - - - - com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 - - - YES - ../Hedgewars.xcodeproj - 3 - 132 - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/GameConfigViewController.h --- a/project_files/HedgewarsMobile/Classes/GameConfigViewController.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/GameConfigViewController.h Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ @@ -23,7 +23,7 @@ @class SchemeWeaponConfigViewController; @class TeamConfigViewController; @class MapConfigViewController; -//@class HelpPageLobbyViewController; +@class HelpPageLobbyViewController; @interface GameConfigViewController : UIViewController { UIView *imgContainer; @@ -33,16 +33,17 @@ SchemeWeaponConfigViewController *schemeWeaponConfigViewController; TeamConfigViewController *teamConfigViewController; MapConfigViewController *mapConfigViewController; - //HelpPageLobbyViewController *helpPage; + HelpPageLobbyViewController *helpPage; } -@property (retain) UIView *imgContainer; +@property (atomic) BOOL isDrawingNiceHogs; +@property (nonatomic,retain) UIView *imgContainer; @property (nonatomic,retain) UILabel * sliderBackground; @property (nonatomic,retain) IBOutlet UIImageView *titleImage; @property (nonatomic,retain) IBOutlet SchemeWeaponConfigViewController *schemeWeaponConfigViewController; @property (nonatomic,retain) IBOutlet TeamConfigViewController *teamConfigViewController; @property (nonatomic,retain) IBOutlet MapConfigViewController *mapConfigViewController; -//@property (nonatomic,retain) HelpPageLobbyViewController *helpPage; +@property (nonatomic,retain) HelpPageLobbyViewController *helpPage; -(IBAction) buttonPressed:(id) sender; -(IBAction) segmentPressed:(id) sender; diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/GameConfigViewController.m --- a/project_files/HedgewarsMobile/Classes/GameConfigViewController.m Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/GameConfigViewController.m Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ @@ -22,16 +22,25 @@ #import "TeamConfigViewController.h" #import "SchemeWeaponConfigViewController.h" #import "GameInterfaceBridge.h" +#import "HelpPageLobbyViewController.h" +@interface GameConfigViewController () +@property (nonatomic, retain) IBOutlet UISegmentedControl *tabsSegmentedControl; //iPhone only + +@property (nonatomic, retain) IBOutlet UIBarButtonItem *backButton; //iPhone only +@property (nonatomic, retain) IBOutlet UIBarButtonItem *startButton; //iPhone only +@end @implementation GameConfigViewController -@synthesize imgContainer, titleImage, sliderBackground, //helpPage, +@synthesize imgContainer, titleImage, sliderBackground, helpPage, mapConfigViewController, teamConfigViewController, schemeWeaponConfigViewController; -(BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { return rotationManager(interfaceOrientation); } +#pragma mark - Buttons + -(IBAction) buttonPressed:(id) sender { UIButton *theButton = (UIButton *)sender; @@ -47,7 +56,7 @@ [alert release]; } else { [[AudioManagerController mainManager] playBackSound]; - [[self parentViewController] dismissModalViewControllerAnimated:YES]; + [[self presentingViewController] dismissViewControllerAnimated:YES completion:nil]; } break; case 1: @@ -55,26 +64,20 @@ if ([self isEverythingSet] == NO) return; theButton.enabled = NO; - for (UIView *oneView in self.imgContainer.subviews) { - if ([oneView isMemberOfClass:[UIImageView class]]) { - UIImageView *anImageView = (UIImageView *)oneView; - [anImageView removeFromSuperview]; - } - } + [self clearImgContainer]; [self startGame:theButton]; break; case 2: [[AudioManagerController mainManager] playClickSound]; - /* if (self.helpPage == nil) self.helpPage = [[HelpPageLobbyViewController alloc] initWithNibName:@"HelpPageLobbyViewController-iPad" bundle:nil]; self.helpPage.view.alpha = 0; + self.helpPage.view.frame = self.view.frame; [self.view addSubview:self.helpPage.view]; - [UIView beginAnimations:@"helplobby" context:NULL]; - self.helpPage.view.alpha = 1; - [UIView commitAnimations]; - */ + [UIView animateWithDuration:0.5 animations:^{ + self.helpPage.view.alpha = 1; + }]; break; default: DLog(@"Nope"); @@ -82,6 +85,17 @@ } } +#pragma mark - Tabs Segmented Control + +- (void)localizeTabsSegmentedControl +{ + for (NSUInteger i = 0; i < self.tabsSegmentedControl.numberOfSegments; i++) + { + NSString *oldTitle = [self.tabsSegmentedControl titleForSegmentAtIndex:i]; + [self.tabsSegmentedControl setTitle:NSLocalizedString(oldTitle, nil) forSegmentAtIndex:i]; + } +} + -(IBAction) segmentPressed:(id) sender { UISegmentedControl *theSegment = (UISegmentedControl *)sender; @@ -104,15 +118,16 @@ [self.view bringSubviewToFront:schemeWeaponConfigViewController.view]; break; case 3: - /* if (helpPage == nil) { helpPage = [[HelpPageLobbyViewController alloc] initWithNibName:@"HelpPageLobbyViewController-iPhone" bundle:nil]; + CGRect helpPageFrame = self.view.frame; + helpPageFrame.size.height -= 44; //toolbar height + self.helpPage.view.frame = helpPageFrame; [self.view addSubview:helpPage.view]; } // this message is compulsory otherwise the table won't be loaded at all [helpPage viewWillAppear:NO]; [self.view bringSubviewToFront:helpPage.view]; - */ break; default: DLog(@"Nope"); @@ -121,6 +136,8 @@ } +#pragma mark - + -(BOOL) isEverythingSet { // don't start playing if the preview is in progress if ([self.mapConfigViewController busy]) { @@ -229,71 +246,95 @@ [gameDictionary release]; } --(void) loadNiceHogs { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - srand(time(NULL)); - NSString *filePath = [[NSString alloc] initWithFormat:@"%@/Hedgehog/Idle.png",GRAPHICS_DIRECTORY()]; - UIImage *hogSprite = [[UIImage alloc] initWithContentsOfFile:filePath]; - [filePath release]; +-(void) loadNiceHogs +{ + @autoreleasepool + { + + NSString *filePath = [[NSString alloc] initWithFormat:@"%@/Hedgehog/Idle.png",GRAPHICS_DIRECTORY()]; + UIImage *hogSprite = [[UIImage alloc] initWithContentsOfFile:filePath]; + [filePath release]; - NSArray *hatArray = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:HATS_DIRECTORY() error:NULL]; - int numberOfHats = [hatArray count]; - int animationFrames = IS_VERY_POWERFUL([HWUtils modelType]) ? 18 : 1; - - if (self.imgContainer != nil) - [self.imgContainer removeFromSuperview]; - - self.imgContainer = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 40)]; - NSInteger numberOfHogs = 1 + random() % 20; - DLog(@"Drawing %d nice hedgehogs", numberOfHogs); - for (int i = 0; i < numberOfHogs; i++) { - NSString *hat = [hatArray objectAtIndex:random()%numberOfHats]; + NSArray *hatArray = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:HATS_DIRECTORY() error:NULL]; + NSUInteger numberOfHats = [hatArray count]; + int animationFrames = IS_VERY_POWERFUL([HWUtils modelType]) ? 16 : 1; + + self.imgContainer = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 40)]; + NSInteger numberOfHogs = 1 + arc4random_uniform(15); + DLog(@"Drawing %ld nice hedgehogs", (long)numberOfHogs); + for (int i = 0; i < numberOfHogs; i++) { + NSString *hat = [hatArray objectAtIndex:arc4random_uniform((int)numberOfHats)]; - NSString *hatFile = [[NSString alloc] initWithFormat:@"%@/%@", HATS_DIRECTORY(), hat]; - UIImage *hatSprite = [[UIImage alloc] initWithContentsOfFile:hatFile]; - NSMutableArray *animation = [[NSMutableArray alloc] initWithCapacity:animationFrames]; - for (int j = 0; j < animationFrames; j++) { - int x = ((j*32)/(int)hatSprite.size.height)*32; - int y = (j*32)%(int)hatSprite.size.height; - UIImage *hatSpriteFrame = [hatSprite cutAt:CGRectMake(x, y, 32, 32)]; - UIImage *hogSpriteFrame = [hogSprite cutAt:CGRectMake(x, y, 32, 32)]; - UIImage *hogWithHat = [hogSpriteFrame mergeWith:hatSpriteFrame atPoint:CGPointMake(0, 5)]; - [animation addObject:hogWithHat]; - } - [hatSprite release]; - [hatFile release]; + NSString *hatFile = [[NSString alloc] initWithFormat:@"%@/%@", HATS_DIRECTORY(), hat]; + UIImage *hatSprite = [[UIImage alloc] initWithContentsOfFile:hatFile]; + NSMutableArray *animation = [[NSMutableArray alloc] initWithCapacity:animationFrames]; + for (int j = 0; j < animationFrames; j++) { + int x = ((j*32)/(int)hatSprite.size.height)*32; + int y = (j*32)%(int)hatSprite.size.height; + UIImage *hatSpriteFrame = [hatSprite cutAt:CGRectMake(x, y, 32, 32)]; + UIImage *hogSpriteFrame = [hogSprite cutAt:CGRectMake(x, y, 32, 32)]; + UIImage *hogWithHat = [hogSpriteFrame mergeWith:hatSpriteFrame atPoint:CGPointMake(0, 5)]; + [animation addObject:hogWithHat]; + } + [hatSprite release]; + [hatFile release]; + + UIImageView *hog = [[UIImageView alloc] initWithImage:[animation objectAtIndex:0]]; + hog.animationImages = animation; + hog.animationDuration = 3; + [animation release]; - UIImageView *hog = [[UIImageView alloc] initWithImage:[animation objectAtIndex:0]]; - hog.animationImages = animation; - hog.animationDuration = 3; - [animation release]; - - int x = 20*i+random()%128; - if (x > 320 - 32) - x = i*random()%32; - hog.frame = CGRectMake(x, 25, hog.frame.size.width, hog.frame.size.height); - [self.imgContainer addSubview:hog]; - [hog startAnimating]; - [hog release]; + int x = 20*i+arc4random_uniform(128); + while (x > 320 - 32) + x = i*arc4random_uniform(32); + + hog.frame = CGRectMake(x, 25, hog.frame.size.width, hog.frame.size.height); + [self.imgContainer addSubview:hog]; + [hog startAnimating]; + [hog release]; + } + [hogSprite release]; + + dispatch_async(dispatch_get_main_queue(), ^{ + + [self.view addSubview:self.imgContainer]; + + // don't place the nice hogs if there is no space for them + if ((self.interfaceOrientation == UIInterfaceOrientationPortrait || + self.interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown)) + self.imgContainer.alpha = 0; + + self.isDrawingNiceHogs = NO; + }); } - - // don't place the nice hogs if there is no space for them - if ((self.interfaceOrientation == UIInterfaceOrientationPortrait || - self.interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown)) - self.imgContainer.alpha = 0; - - [self.view addSubview:self.imgContainer]; - [hogSprite release]; - [pool drain]; } --(void) viewDidLoad { +- (void)clearImgContainer +{ + for (UIView *oneView in [self.imgContainer subviews]) + { + if ([oneView isMemberOfClass:[UIImageView class]]) + { + UIImageView *anImageView = (UIImageView *)oneView; + [anImageView removeFromSuperview]; + } + } + + [self.imgContainer removeFromSuperview]; + self.imgContainer = nil; +} + +-(void) viewDidLoad +{ + [super viewDidLoad]; + self.view.backgroundColor = [UIColor blackColor]; CGRect screenRect = [[UIScreen mainScreen] safeBounds]; self.view.frame = screenRect; - if (IS_IPAD()) { + if (IS_IPAD()) + { // the label for the filter slider UILabel *backLabel = [[UILabel alloc] initWithFrame:CGRectMake(116, 714, 310, 40) andTitle:nil @@ -312,21 +353,37 @@ [self.view addSubview:maxLabel]; self.mapConfigViewController.maxLabel = maxLabel; [maxLabel release]; - } else { + } + else + { + [self localizeTabsSegmentedControl]; + + [self.backButton setTitle:NSLocalizedString(@"Back", nil)]; + [self.startButton setTitle:NSLocalizedString(@"Start", nil)]; + self.mapConfigViewController.view.frame = CGRectMake(0, 0, screenRect.size.width, screenRect.size.height-44); } + [self.view addSubview:self.mapConfigViewController.view]; [self.view bringSubviewToFront:self.mapConfigViewController.slider]; - - [super viewDidLoad]; } -(void) willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval) duration { if (IS_IPAD() == NO) return; - if ((toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft || - toInterfaceOrientation == UIInterfaceOrientationLandscapeRight)) { + [self updateiPadUIForInterfaceOrientation:toInterfaceOrientation]; + + if (self.helpPage) + { + self.helpPage.view.frame = self.view.frame; + } +} + +- (void)updateiPadUIForInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation +{ + if ((interfaceOrientation == UIInterfaceOrientationLandscapeLeft || + interfaceOrientation == UIInterfaceOrientationLandscapeRight)) { self.imgContainer.alpha = 1; self.titleImage.frame = CGRectMake(357, 17, 309, 165); self.schemeWeaponConfigViewController.view.frame = CGRectMake(0, 60, 320, 620); @@ -345,46 +402,41 @@ self.sliderBackground.frame = CGRectMake(465, 975, 200, 40); self.mapConfigViewController.slider.frame = CGRectMake(475, 983, 180, 23); } - - [self.schemeWeaponConfigViewController willAnimateRotationToInterfaceOrientation:toInterfaceOrientation - duration:duration]; -} - --(void) viewWillAppear:(BOOL)animated { - if (IS_IPAD()) - [NSThread detachNewThreadSelector:@selector(loadNiceHogs) toTarget:self withObject:nil]; - - [self.mapConfigViewController viewWillAppear:animated]; - [self.teamConfigViewController viewWillAppear:animated]; - [self.schemeWeaponConfigViewController viewWillAppear:animated]; - // add other controllers here and below - - [super viewWillAppear:animated]; } --(void) viewDidAppear:(BOOL)animated { - [self.mapConfigViewController viewDidAppear:animated]; - [self.teamConfigViewController viewDidAppear:animated]; - [self.schemeWeaponConfigViewController viewDidAppear:animated]; - [super viewDidAppear:animated]; +-(void) viewWillAppear:(BOOL)animated +{ + [super viewWillAppear:animated]; + + if (IS_IPAD() && !self.imgContainer && !self.isDrawingNiceHogs) + { + self.isDrawingNiceHogs = YES; + [NSThread detachNewThreadSelector:@selector(loadNiceHogs) toTarget:self withObject:nil]; + } + + if (IS_IPAD()) + { + // we assume here what 'statusBarOrientation' will never be changed manually! + UIInterfaceOrientation currentOrientation = [[UIApplication sharedApplication] statusBarOrientation]; + [self updateiPadUIForInterfaceOrientation:currentOrientation]; + } } --(void) viewWillDisappear:(BOOL)animated { - [self.mapConfigViewController viewWillDisappear:animated]; - [self.teamConfigViewController viewWillDisappear:animated]; - [self.schemeWeaponConfigViewController viewWillDisappear:animated]; - [super viewWillDisappear:animated]; +- (void)viewDidAppear:(BOOL)animated +{ + [super viewDidAppear:animated]; + + if (IS_IPAD()) + { + // need to call this again in order to fix layout on iOS 9 when going back from rotated stats page + UIInterfaceOrientation currentOrientation = [[UIApplication sharedApplication] statusBarOrientation]; + [self updateiPadUIForInterfaceOrientation:currentOrientation]; + } } --(void) viewDidDisappear:(BOOL)animated { - [self.mapConfigViewController viewDidDisappear:animated]; - [self.teamConfigViewController viewDidDisappear:animated]; - [self.schemeWeaponConfigViewController viewDidDisappear:animated]; - [super viewDidDisappear:animated]; -} - --(void) didReceiveMemoryWarning { - self.imgContainer = nil; +-(void) didReceiveMemoryWarning +{ + [self clearImgContainer]; if (self.titleImage.superview == nil) self.titleImage = nil; @@ -397,8 +449,8 @@ self.teamConfigViewController = nil; if (self.schemeWeaponConfigViewController.view.superview == nil) self.schemeWeaponConfigViewController = nil; - //if (self.helpPage.view.superview == nil) - // self.helpPage = nil; + if (self.helpPage.view.superview == nil) + self.helpPage = nil; MSG_MEMCLEAN(); [super didReceiveMemoryWarning]; } @@ -410,19 +462,22 @@ self.schemeWeaponConfigViewController = nil; self.teamConfigViewController = nil; self.mapConfigViewController = nil; - //self.helpPage = nil; + self.helpPage = nil; MSG_DIDUNLOAD(); [super viewDidUnload]; } -(void) dealloc { + releaseAndNil(_tabsSegmentedControl); + releaseAndNil(_backButton); + releaseAndNil(_startButton); releaseAndNil(imgContainer); releaseAndNil(titleImage); releaseAndNil(sliderBackground); releaseAndNil(schemeWeaponConfigViewController); releaseAndNil(teamConfigViewController); releaseAndNil(mapConfigViewController); - //releaseAndNil(helpPage); + releaseAndNil(helpPage); [super dealloc]; } diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/GameInterfaceBridge.h --- a/project_files/HedgewarsMobile/Classes/GameInterfaceBridge.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/GameInterfaceBridge.h Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/GameInterfaceBridge.m --- a/project_files/HedgewarsMobile/Classes/GameInterfaceBridge.m Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/GameInterfaceBridge.m Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ @@ -99,7 +99,9 @@ CGFloat width, height; CGFloat screenScale = [[UIScreen mainScreen] safeScale]; NSString *ipcString = [[NSString alloc] initWithFormat:@"%d",self.port]; - NSString *localeString = [[NSString alloc] initWithFormat:@"%@.txt",[[NSLocale preferredLanguages] objectAtIndex:0]]; + + NSString *localeString = [[NSString alloc] initWithFormat:@"%@.txt", [HWUtils languageID]]; + NSUserDefaults *settings = [NSUserDefaults standardUserDefaults]; CGRect screenBounds = [[UIScreen mainScreen] safeBounds]; @@ -176,7 +178,7 @@ [gameParameters release]; // this is the pascal function that starts the game - Game(argc, argv); + RunEngine(argc, argv); // cleanup for (int i = 0; i < argc; i++) @@ -201,7 +203,7 @@ statsPage.statsArray = stats; statsPage.modalTransitionStyle = UIModalTransitionStyleCoverVertical; - [callingController presentModalViewController:statsPage animated:YES]; + [callingController presentViewController:statsPage animated:YES completion:nil]; [statsPage release]; } } @@ -248,8 +250,6 @@ } +(void) startSimpleGame { - srand(time(0)); - // generate a seed CFUUIDRef uuid = CFUUIDCreate(kCFAllocatorDefault); NSString *seed = (NSString *)CFUUIDCreateString(kCFAllocatorDefault, uuid); @@ -259,7 +259,7 @@ // pick a random static map NSArray *listOfMaps = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:MAPS_DIRECTORY() error:NULL]; - NSString *mapName = [listOfMaps objectAtIndex:random()%[listOfMaps count]]; + NSString *mapName = [listOfMaps objectAtIndex:arc4random_uniform((int)[listOfMaps count])]; NSString *fileCfg = [[NSString alloc] initWithFormat:@"%@/%@/map.cfg",MAPS_DIRECTORY(),mapName]; NSString *contents = [[NSString alloc] initWithContentsOfFile:fileCfg encoding:NSUTF8StringEncoding error:NULL]; [fileCfg release]; @@ -272,8 +272,8 @@ NSArray *colorArray = [HWUtils teamColors]; NSInteger firstColorIndex, secondColorIndex; do { - firstColorIndex = random()%[colorArray count]; - secondColorIndex = random()%[colorArray count]; + firstColorIndex = arc4random_uniform((int)[colorArray count]); + secondColorIndex = arc4random_uniform((int)[colorArray count]); } while (firstColorIndex == secondColorIndex); unsigned int firstColor = [[colorArray objectAtIndex:firstColorIndex] intValue]; unsigned int secondColor = [[colorArray objectAtIndex:secondColorIndex] intValue]; diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/GameLogViewController.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/GameLogViewController.h Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,23 @@ +/* + * Hedgewars-iOS, a Hedgewars port for iOS devices + * Copyright (c) 2015 Anton Malmygin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#import + +@interface GameLogViewController : UIViewController + +@end diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/GameLogViewController.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/GameLogViewController.m Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,144 @@ +/* + * Hedgewars-iOS, a Hedgewars port for iOS devices + * Copyright (c) 2015 Anton Malmygin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#import "GameLogViewController.h" + +#ifdef DEBUG +#import +#endif + +@interface GameLogViewController () +#ifdef DEBUG + +#endif + +@end + +@implementation GameLogViewController + +#pragma mark - View life cycle + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.title = @"Last game log"; + + UIBarButtonItem *closeButton = [[UIBarButtonItem alloc] initWithTitle:@"Close" style:UIBarButtonItemStylePlain target:self action:@selector(dismissAction)]; + self.navigationItem.rightBarButtonItem = closeButton; + [closeButton release]; + +#ifdef DEBUG + if ([self allowSendLogByEmail]) + { + UIBarButtonItem *sendButton = [[UIBarButtonItem alloc] initWithTitle:@"Send" style:UIBarButtonItemStylePlain target:self action:@selector(sendLogByEmailAction)]; + self.navigationItem.leftBarButtonItem = sendButton; + [sendButton release]; + } +#endif + + NSString *debugStr = nil; + if ([[NSFileManager defaultManager] fileExistsAtPath:DEBUG_FILE()]) + debugStr = [[NSString alloc] initWithContentsOfFile:DEBUG_FILE() encoding:NSUTF8StringEncoding error:nil]; + else + debugStr = [[NSString alloc] initWithString:@"Here be log"]; + + UITextView *logView = [[UITextView alloc] initWithFrame:self.view.frame]; + [logView setAutoresizingMask:(UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth)]; + logView.text = debugStr; + [debugStr release]; + logView.editable = NO; + + [self.view addSubview:logView]; + [logView release]; +} + +#pragma mark - Parameters + +#ifdef DEBUG +- (BOOL)allowSendLogByEmail +{ + return ([MFMailComposeViewController canSendMail] && [[NSFileManager defaultManager] fileExistsAtPath:DEBUG_FILE()]); +} +#endif + +#pragma mark - Actions + +#ifdef DEBUG +- (void)sendLogByEmailAction +{ + MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init]; + picker.mailComposeDelegate = self; + [picker setSubject:@"Log file of iHedgewars game"]; + + // Attach a log file to the email + NSData *logData = [NSData dataWithContentsOfFile:DEBUG_FILE()]; + [picker addAttachmentData:logData mimeType:@"text/plain" fileName:@"game0.log"]; + + // Fill out the email body text + NSString *emailBody = @"Add here description of a problem/log"; + [picker setMessageBody:emailBody isHTML:NO]; + + [self presentViewController:picker animated:YES completion:nil]; + [picker release]; +} +#endif + +- (void)dismissAction +{ + [self dismissViewControllerAnimated:YES completion:nil]; +} + +#pragma mark - MailCompose delegate + +#ifdef DEBUG +- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error +{ + // Notifies users about errors associated with the interface + switch (result) + { + case MFMailComposeResultCancelled: + NSLog(@"MailComposeResult: canceled"); + break; + case MFMailComposeResultSaved: + NSLog(@"MailComposeResult: saved"); + break; + case MFMailComposeResultSent: + NSLog(@"MailComposeResult: sent"); + break; + case MFMailComposeResultFailed: + NSLog(@"MailComposeResult: failed"); + break; + default: + NSLog(@"MailComposeResult: not sent"); + break; + } + + [self dismissViewControllerAnimated:YES completion:nil]; +} +#endif + +#pragma mark - Memory warning + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +@end diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/GeneralSettingsViewController.h --- a/project_files/HedgewarsMobile/Classes/GeneralSettingsViewController.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/GeneralSettingsViewController.h Tue Nov 10 20:43:13 2015 +0100 @@ -13,14 +13,14 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ #import - +#import "TableViewControllerWithDoneButton.h" -@interface GeneralSettingsViewController : UITableViewController { +@interface GeneralSettingsViewController : TableViewControllerWithDoneButton { } diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/GeneralSettingsViewController.m --- a/project_files/HedgewarsMobile/Classes/GeneralSettingsViewController.m Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/GeneralSettingsViewController.m Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ @@ -30,7 +30,7 @@ #pragma mark - #pragma mark View Lifecycle -(void) viewDidLoad { - self.navigationItem.title = @"Edit game options"; + self.navigationItem.title = NSLocalizedString(@"Edit game options", nil); [super viewDidLoad]; } @@ -179,7 +179,7 @@ switchContent = (UISwitch *)cell.accessoryView; if (row == 0) { - cell.textLabel.text = NSLocalizedString(@"Sound Effects", @"from the settings table"); + cell.textLabel.text = NSLocalizedString(@"Sound", @"from the settings table"); switchContent.on = [[settings objectForKey:@"sound"] boolValue]; switchContent.tag = 10; } else { diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/GravesViewController.h --- a/project_files/HedgewarsMobile/Classes/GravesViewController.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/GravesViewController.h Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/GravesViewController.m --- a/project_files/HedgewarsMobile/Classes/GravesViewController.m Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/GravesViewController.m Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ @@ -88,8 +88,8 @@ #pragma mark - #pragma mark Table view delegate -(void) tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - int newRow = [indexPath row]; - int oldRow = (lastIndexPath != nil) ? [lastIndexPath row] : -1; + NSInteger newRow = [indexPath row]; + NSInteger oldRow = (lastIndexPath != nil) ? [lastIndexPath row] : -1; if (newRow != oldRow) { [teamDictionary setObject:[[graveArray objectAtIndex:newRow] stringByDeletingPathExtension] forKey:@"grave"]; diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/HWUtils.h --- a/project_files/HedgewarsMobile/Classes/HWUtils.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/HWUtils.h Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ @@ -41,6 +41,7 @@ +(NSInteger) randomPort; +(void) freePort:(NSInteger) port; +(BOOL) isNetworkReachable; ++(NSString *) languageID; //+(UIView *)mainSDLViewInstance; @end diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/HWUtils.m --- a/project_files/HedgewarsMobile/Classes/HWUtils.m Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/HWUtils.m Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ @@ -103,23 +103,22 @@ +(NSInteger) randomPort { // set a new feed only at initialization time and forbid connecting to the server port if (activePorts == nil) { - srandom(time(NULL)); activePorts = [[NSMutableArray arrayWithObject:[NSNumber numberWithInt:NETGAME_DEFAULT_PORT]] retain]; } // pick a random number from the free ports list NSInteger res = 0; do { - res = (random() % 64511) + 1024; - } while ([activePorts containsObject:[NSNumber numberWithInt:res]]); + res = (arc4random_uniform(64511)) + 1024; + } while ([activePorts containsObject:[NSNumber numberWithInteger:res]]); // add this number to the forbdding list - [activePorts addObject:[NSNumber numberWithInt:res]]; + [activePorts addObject:[NSNumber numberWithInteger:res]]; return res; } +(void) freePort:(NSInteger) port { - [activePorts removeObject:[NSNumber numberWithInt:port]]; + [activePorts removeObject:[NSNumber numberWithInteger:port]]; } +(BOOL) isNetworkReachable { @@ -156,6 +155,12 @@ return ((isReachable && !needsConnection) || nonWiFi) ? testResult : NO; } ++ (NSString *)languageID +{ + NSString *language = [[NSLocale preferredLanguages] firstObject]; + return [[language componentsSeparatedByString:@"-"] firstObject]; +} + /* +(UIView *)mainSDLViewInstance { SDL_Window *window = HW_getSDLWindow(); diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/HedgewarsAppDelegate.h --- a/project_files/HedgewarsMobile/Classes/HedgewarsAppDelegate.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/HedgewarsAppDelegate.h Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/HedgewarsAppDelegate.m --- a/project_files/HedgewarsMobile/Classes/HedgewarsAppDelegate.m Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/HedgewarsAppDelegate.m Tue Nov 10 20:43:13 2015 +0100 @@ -13,13 +13,13 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ #import "HedgewarsAppDelegate.h" #import "MainMenuViewController.h" - +#import "Appirater.h" @implementation SDLUIKitDelegate (customDelegate) @@ -50,7 +50,18 @@ } // override the direct execution of SDL_main to allow us to implement our own frontend --(void) postFinishLaunch { +-(void) postFinishLaunch +{ + // Setup Appirater + [Appirater setAppId:@"391234866"]; + [Appirater setDaysUntilPrompt:3]; + [Appirater setUsesUntilPrompt:5]; + [Appirater setSignificantEventsUntilPrompt:-1]; + [Appirater setTimeBeforeReminding:1]; + //[Appirater setDebug:YES]; + + [self performSelector:@selector(hideLaunchScreen) withObject:nil afterDelay:0.0]; + [[UIApplication sharedApplication] setStatusBarHidden:YES]; self.uiwindow = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; @@ -58,7 +69,7 @@ NSString *controllerName = (IS_IPAD() ? @"MainMenuViewController-iPad" : @"MainMenuViewController-iPhone"); self.mainViewController = [[MainMenuViewController alloc] initWithNibName:controllerName bundle:nil]; - [self.uiwindow addSubview:self.mainViewController.view]; + self.uiwindow.rootViewController = self.mainViewController; [self.mainViewController release]; [self.uiwindow makeKeyAndVisible]; diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/HelpPageLobbyViewController-iPad.xib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/HelpPageLobbyViewController-iPad.xib Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,320 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/HelpPageLobbyViewController-iPhone.xib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/HelpPageLobbyViewController-iPhone.xib Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/HelpPageLobbyViewController.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/HelpPageLobbyViewController.h Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,31 @@ +/* + * Hedgewars-iOS, a Hedgewars port for iOS devices + * Copyright (c) 2009-2012 Vittorio Giovara + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + +#import + + +@interface HelpPageLobbyViewController : UIViewController { + UIScrollView *scrollView; +} + +@property (nonatomic, retain) IBOutlet UIScrollView *scrollView; + +-(IBAction) dismiss; + +@end diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/HelpPageLobbyViewController.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/HelpPageLobbyViewController.m Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,65 @@ +/* + * Hedgewars-iOS, a Hedgewars port for iOS devices + * Copyright (c) 2009-2012 Vittorio Giovara + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + +#import "HelpPageLobbyViewController.h" + + +@implementation HelpPageLobbyViewController +@synthesize scrollView; + +-(BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation) interfaceOrientation { + return rotationManager(interfaceOrientation); +} + +-(void) didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; + self.scrollView = nil; +} + +// on iPhone the XIBs contain UIScrollView +-(void) viewDidLoad { + if (IS_IPAD() == NO){ + scrollView.contentSize = CGSizeMake(self.view.frame.size.width, 650); + scrollView.maximumZoomScale = 4.0; + scrollView.minimumZoomScale = 0.75; + scrollView.clipsToBounds = YES; + scrollView.delegate = self; + } + [super viewDidLoad]; +} + +-(void) viewDidUnload { + [super viewDidUnload]; + self.scrollView = nil; +} + +-(void) dealloc { + releaseAndNil(scrollView); + [super dealloc]; +} + +-(IBAction) dismiss { + [UIView animateWithDuration:0.5 animations:^{ + self.view.alpha = 0; + } completion:^(BOOL finished){ + [self.view performSelector:@selector(removeFromSuperview) withObject:nil afterDelay:0]; + }]; +} + +@end diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/HogHatViewController.h --- a/project_files/HedgewarsMobile/Classes/HogHatViewController.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/HogHatViewController.h Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ @@ -26,13 +26,11 @@ NSArray *hatArray; UIImage *normalHogSprite; - NSIndexPath *lastIndexPath; } @property (nonatomic,retain) NSDictionary *teamDictionary; @property (nonatomic) NSInteger selectedHog; @property (nonatomic,retain) NSArray *hatArray; @property (nonatomic,retain) UIImage *normalHogSprite; -@property (nonatomic,retain) NSIndexPath *lastIndexPath; @end diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/HogHatViewController.m --- a/project_files/HedgewarsMobile/Classes/HogHatViewController.m Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/HogHatViewController.m Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ @@ -21,7 +21,7 @@ @implementation HogHatViewController -@synthesize teamDictionary, hatArray, normalHogSprite, lastIndexPath, selectedHog; +@synthesize teamDictionary, hatArray, normalHogSprite, selectedHog; -(BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation) interfaceOrientation { @@ -77,8 +77,7 @@ if (cell == nil) cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; - NSDictionary *hog = [[self.teamDictionary objectForKey:@"hedgehogs"] objectAtIndex:selectedHog]; - NSString *hat = [hatArray objectAtIndex:[indexPath row]]; + NSString *hat = [self.hatArray objectAtIndex:[indexPath row]]; cell.textLabel.text = [hat stringByDeletingPathExtension]; NSString *hatFile = [[NSString alloc] initWithFormat:@"%@/%@", HATS_DIRECTORY(), hat]; @@ -87,9 +86,9 @@ cell.imageView.image = [self.normalHogSprite mergeWith:hatSprite atPoint:CGPointMake(0, 5)]; [hatSprite release]; - if ([hat isEqualToString:[hog objectForKey:@"hat"]]) { + NSDictionary *hog = (self.selectedHog != -1) ? [[self.teamDictionary objectForKey:@"hedgehogs"] objectAtIndex:self.selectedHog] : nil; + if ([[hat stringByDeletingPathExtension] isEqualToString:[hog objectForKey:@"hat"]]) { cell.accessoryType = UITableViewCellAccessoryCheckmark; - self.lastIndexPath = indexPath; } else { cell.accessoryType = UITableViewCellAccessoryNone; } @@ -100,45 +99,53 @@ #pragma mark - #pragma mark Table view delegate --(void) tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - int newRow = [indexPath row]; - int oldRow = (lastIndexPath != nil) ? [lastIndexPath row] : -1; - - if (newRow != oldRow) { - // if the two selected rows differ update data on the hog dictionary and reload table content - // TODO: maybe this section could be cleaned up - NSDictionary *oldHog = [[teamDictionary objectForKey:@"hedgehogs"] objectAtIndex:selectedHog]; +-(void) tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath +{ + NSInteger selectedRow = [indexPath row]; + NSString *newHat = [[self.hatArray objectAtIndex:selectedRow] stringByDeletingPathExtension]; + + // update data on the hogs dictionary + if (self.selectedHog != -1) + { + // update only selected hog with new hat + [self updateTeamDictionaryWithNewHat:newHat forStartHogIndex:self.selectedHog toEndHogIndex:self.selectedHog]; + } + else + { + // update all hogs with new hat + NSInteger startIndex = 0; + NSInteger endIndex = [[self.teamDictionary objectForKey:@"hedgehogs"] count] - 1; + [self updateTeamDictionaryWithNewHat:newHat forStartHogIndex:startIndex toEndHogIndex:endIndex]; + } - NSMutableDictionary *newHog = [[NSMutableDictionary alloc] initWithDictionary: oldHog]; - [newHog setObject:[[hatArray objectAtIndex:newRow] stringByDeletingPathExtension] forKey:@"hat"]; - [[teamDictionary objectForKey:@"hedgehogs"] replaceObjectAtIndex:selectedHog withObject:newHog]; - [newHog release]; - - // tell our boss to write this new stuff on disk - [[NSNotificationCenter defaultCenter] postNotificationName:@"setWriteNeedTeams" object:nil]; - - UITableViewCell *newCell = [aTableView cellForRowAtIndexPath:indexPath]; - newCell.accessoryType = UITableViewCellAccessoryCheckmark; - UITableViewCell *oldCell = [aTableView cellForRowAtIndexPath:lastIndexPath]; - oldCell.accessoryType = UITableViewCellAccessoryNone; - self.lastIndexPath = indexPath; - [aTableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionNone]; - } - [aTableView deselectRowAtIndexPath:indexPath animated:YES]; + // tell our boss to write this new stuff on disk + [[NSNotificationCenter defaultCenter] postNotificationName:@"setWriteNeedTeams" object:nil]; + [self.navigationController popViewControllerAnimated:YES]; } +- (void)updateTeamDictionaryWithNewHat:(NSString *)newHat forStartHogIndex:(NSInteger)startIndex toEndHogIndex:(NSInteger)endIndex +{ + NSMutableArray *hogsArray = [self.teamDictionary objectForKey:@"hedgehogs"]; + + for (NSInteger i=startIndex; i <= endIndex; i++) + { + NSDictionary *oldHog = [hogsArray objectAtIndex:i]; + NSMutableDictionary *newHog = [[NSMutableDictionary alloc] initWithDictionary:oldHog]; + [newHog setObject:newHat forKey:@"hat"]; + [hogsArray replaceObjectAtIndex:i withObject:newHog]; + [newHog release]; + } +} #pragma mark - #pragma mark Memory management -(void) didReceiveMemoryWarning { - self.lastIndexPath = nil; MSG_MEMCLEAN(); [super didReceiveMemoryWarning]; } -(void) viewDidUnload { - self.lastIndexPath = nil; self.normalHogSprite = nil; self.teamDictionary = nil; self.hatArray = nil; @@ -150,7 +157,6 @@ releaseAndNil(hatArray); releaseAndNil(teamDictionary); releaseAndNil(normalHogSprite); - releaseAndNil(lastIndexPath); [super dealloc]; } diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/HoldTableViewCell.h --- a/project_files/HedgewarsMobile/Classes/HoldTableViewCell.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/HoldTableViewCell.h Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/HoldTableViewCell.m --- a/project_files/HedgewarsMobile/Classes/HoldTableViewCell.m Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/HoldTableViewCell.m Tue Nov 10 20:43:13 2015 +0100 @@ -13,12 +13,12 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ #import "HoldTableViewCell.h" - +#import "UITableViewCell+FindTable.h" @implementation HoldTableViewCell @synthesize delegate; @@ -57,7 +57,13 @@ -(void) holdAction { if (self.delegate != nil && [self.delegate respondsToSelector:@selector(holdAction:onTable:)]) - [self.delegate holdAction:self.textLabel.text onTable:(UITableView *)self.superview]; + { + UITableView *tableView = [self findTable]; + if (tableView) + { + [self.delegate holdAction:self.textLabel.text onTable:tableView]; + } + } } -(void) dealloc { diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/LabelWithIBLocalization.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/LabelWithIBLocalization.h Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,23 @@ +/* + * Hedgewars-iOS, a Hedgewars port for iOS devices + * Copyright (c) 2015 Anton Malmygin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#import + +@interface LabelWithIBLocalization : UILabel + +@end diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/LabelWithIBLocalization.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/LabelWithIBLocalization.m Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,41 @@ +/* + * Hedgewars-iOS, a Hedgewars port for iOS devices + * Copyright (c) 2015 Anton Malmygin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#import "LabelWithIBLocalization.h" + +@interface LabelWithIBLocalization () +@property (nonatomic) BOOL isAlreadyLocalized; +@end + +@implementation LabelWithIBLocalization + +- (void)layoutSubviews +{ + [super layoutSubviews]; + + if (!self.isAlreadyLocalized) + { + // Text which set in Interface Builder used here as a key for localization + self.text = NSLocalizedString(self.text, nil); + + [self setNeedsLayout]; + self.isAlreadyLocalized = YES; + } +} + +@end diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/LevelViewController.h --- a/project_files/HedgewarsMobile/Classes/LevelViewController.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/LevelViewController.h Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/LevelViewController.m --- a/project_files/HedgewarsMobile/Classes/LevelViewController.m Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/LevelViewController.m Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 0211-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ @@ -31,7 +31,6 @@ #pragma mark View lifecycle -(void) viewDidLoad { [super viewDidLoad]; - srandom(time(NULL)); NSArray *array = [[NSArray alloc] initWithObjects: NSLocalizedString(@"Brutal",@""), @@ -59,10 +58,6 @@ [self.tableView setContentOffset:CGPointMake(0,0) animated:NO]; } --(void) viewWillDisappear:(BOOL)animated { - // stuff like checking that at least 1 field was selected -} - #pragma mark - #pragma mark Table view data source -(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView { @@ -133,7 +128,7 @@ if (theSwitch.on) { numberOfSections = 2; [self.tableView insertSections:sections withRowAnimation:UITableViewRowAnimationFade]; - level = 1 + (random() % ([levelArray count] - 1)); + level = 1 + arc4random_uniform((int)[levelArray count] - 1); } else { numberOfSections = 1; [self.tableView deleteSections:sections withRowAnimation:UITableViewRowAnimationFade]; @@ -141,9 +136,9 @@ } [sections release]; - DLog(@"New level is %d",level); + DLog(@"New level is %ld", (long)level); for (NSMutableDictionary *hog in hogs) - [hog setObject:[NSNumber numberWithInt:level] forKey:@"level"]; + [hog setObject:[NSNumber numberWithInteger:level] forKey:@"level"]; [self.tableView reloadData]; [[NSNotificationCenter defaultCenter] postNotificationName:@"setWriteNeedTeams" object:nil]; @@ -153,8 +148,8 @@ #pragma mark - #pragma mark Table view delegate -(void) tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - int newRow = [indexPath row]; - int oldRow = (self.lastIndexPath != nil) ? [self.lastIndexPath row] : -1; + NSInteger newRow = [indexPath row]; + NSInteger oldRow = (self.lastIndexPath != nil) ? [self.lastIndexPath row] : -1; if ([indexPath section] != 0) { if (newRow != oldRow) { @@ -162,8 +157,8 @@ NSInteger level = newRow + 1; for (NSMutableDictionary *hog in hogs) - [hog setObject:[NSNumber numberWithInt:level] forKey:@"level"]; - DLog(@"New level is %d",level); + [hog setObject:[NSNumber numberWithInteger:level] forKey:@"level"]; + DLog(@"New level is %ld", (long)level); // tell our boss to write this new stuff on disk [[NSNotificationCenter defaultCenter] postNotificationName:@"setWriteNeedTeams" object:nil]; diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/MGSplitViewController/MGSplitCornersView.h --- a/project_files/HedgewarsMobile/Classes/MGSplitViewController/MGSplitCornersView.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/MGSplitViewController/MGSplitCornersView.h Tue Nov 10 20:43:13 2015 +0100 @@ -9,23 +9,23 @@ #import typedef enum _MGCornersPosition { - MGCornersPositionLeadingVertical = 0, // top of screen for a left/right split. - MGCornersPositionTrailingVertical = 1, // bottom of screen for a left/right split. - MGCornersPositionLeadingHorizontal = 2, // left of screen for a top/bottom split. - MGCornersPositionTrailingHorizontal = 3 // right of screen for a top/bottom split. + MGCornersPositionLeadingVertical = 0, // top of screen for a left/right split. + MGCornersPositionTrailingVertical = 1, // bottom of screen for a left/right split. + MGCornersPositionLeadingHorizontal = 2, // left of screen for a top/bottom split. + MGCornersPositionTrailingHorizontal = 3 // right of screen for a top/bottom split. } MGCornersPosition; @class MGSplitViewController; @interface MGSplitCornersView : UIView { - float cornerRadius; - MGSplitViewController *splitViewController; - MGCornersPosition cornersPosition; - UIColor *cornerBackgroundColor; + float cornerRadius; + MGSplitViewController *__unsafe_unretained splitViewController; + MGCornersPosition cornersPosition; + UIColor *cornerBackgroundColor; } @property (nonatomic, assign) float cornerRadius; -@property (nonatomic, assign) MGSplitViewController *splitViewController; // weak ref. +@property (nonatomic, unsafe_unretained) MGSplitViewController *splitViewController; // weak ref. @property (nonatomic, assign) MGCornersPosition cornersPosition; // don't change this manually; let the splitViewController manage it. -@property (nonatomic, retain) UIColor *cornerBackgroundColor; +@property (nonatomic, strong) UIColor *cornerBackgroundColor; @end diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/MGSplitViewController/MGSplitCornersView.m --- a/project_files/HedgewarsMobile/Classes/MGSplitViewController/MGSplitCornersView.m Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/MGSplitViewController/MGSplitCornersView.m Tue Nov 10 20:43:13 2015 +0100 @@ -7,7 +7,7 @@ // #import "MGSplitCornersView.h" -#import "CGPointUtils.h" + @implementation MGSplitCornersView @@ -19,23 +19,32 @@ - (id)initWithFrame:(CGRect)frame { if ((self = [super initWithFrame:frame])) { - self.contentMode = UIViewContentModeRedraw; - self.userInteractionEnabled = NO; - self.opaque = NO; - self.backgroundColor = [UIColor clearColor]; - cornerRadius = 0.0; // actual value is set by the splitViewController. - cornersPosition = MGCornersPositionLeadingVertical; + self.contentMode = UIViewContentModeRedraw; + self.userInteractionEnabled = NO; + self.opaque = NO; + self.backgroundColor = [UIColor clearColor]; + cornerRadius = 0.0; // actual value is set by the splitViewController. + cornersPosition = MGCornersPositionLeadingVertical; } - + return self; } - (void)dealloc { - self.cornerBackgroundColor = nil; + self.cornerBackgroundColor = nil; +} + - [super dealloc]; +#pragma mark - +#pragma mark Geometry helpers + + +static double deg2Rad(double degrees) +{ + // Converts degrees to radians. + return degrees * (M_PI / 180.0); } @@ -45,131 +54,127 @@ - (void)drawRect:(CGRect)rect { - // Draw two appropriate corners, with cornerBackgroundColor behind them. - if (cornerRadius > 0) { - if (NO) { // just for debugging. - [[UIColor redColor] set]; - UIRectFill(self.bounds); - } - - float maxX = CGRectGetMaxX(self.bounds); - float maxY = CGRectGetMaxY(self.bounds); - UIBezierPath *path = [UIBezierPath bezierPath]; - CGPoint pt = CGPointZero; - switch (cornersPosition) { - case MGCornersPositionLeadingVertical: // top of screen for a left/right split - [path moveToPoint:pt]; - pt.y += cornerRadius; - [path appendPath:[UIBezierPath bezierPathWithArcCenter:pt radius:cornerRadius startAngle:degreesToRadians(90) endAngle:0 clockwise:YES]]; - pt.x += cornerRadius; - pt.y -= cornerRadius; - [path addLineToPoint:pt]; - [path addLineToPoint:CGPointZero]; - [path closePath]; - - pt.x = maxX - cornerRadius; - pt.y = 0; - [path moveToPoint:pt]; - pt.y = maxY; - [path addLineToPoint:pt]; - pt.x += cornerRadius; - [path appendPath:[UIBezierPath bezierPathWithArcCenter:pt radius:cornerRadius startAngle:degreesToRadians(180) endAngle:degreesToRadians(90) clockwise:YES]]; - pt.y -= cornerRadius; - [path addLineToPoint:pt]; - pt.x -= cornerRadius; - [path addLineToPoint:pt]; - [path closePath]; - - break; - - case MGCornersPositionTrailingVertical: // bottom of screen for a left/right split - pt.y = maxY; - [path moveToPoint:pt]; - pt.y -= cornerRadius; - [path appendPath:[UIBezierPath bezierPathWithArcCenter:pt radius:cornerRadius startAngle:degreesToRadians(270) endAngle:degreesToRadians(360) clockwise:NO]]; - pt.x += cornerRadius; - pt.y += cornerRadius; - [path addLineToPoint:pt]; - pt.x -= cornerRadius; - [path addLineToPoint:pt]; - [path closePath]; - - pt.x = maxX - cornerRadius; - pt.y = maxY; - [path moveToPoint:pt]; - pt.y -= cornerRadius; - [path addLineToPoint:pt]; - pt.x += cornerRadius; - [path appendPath:[UIBezierPath bezierPathWithArcCenter:pt radius:cornerRadius startAngle:degreesToRadians(180) endAngle:degreesToRadians(270) clockwise:NO]]; - pt.y += cornerRadius; - [path addLineToPoint:pt]; - pt.x -= cornerRadius; - [path addLineToPoint:pt]; - [path closePath]; - - break; - - case MGCornersPositionLeadingHorizontal: // left of screen for a top/bottom split - pt.x = 0; - pt.y = cornerRadius; - [path moveToPoint:pt]; - pt.y -= cornerRadius; - [path addLineToPoint:pt]; - pt.x += cornerRadius; - [path appendPath:[UIBezierPath bezierPathWithArcCenter:pt radius:cornerRadius startAngle:degreesToRadians(180) endAngle:degreesToRadians(270) clockwise:NO]]; - pt.y += cornerRadius; - [path addLineToPoint:pt]; - pt.x -= cornerRadius; - [path addLineToPoint:pt]; - [path closePath]; - - pt.x = 0; - pt.y = maxY - cornerRadius; - [path moveToPoint:pt]; - pt.y = maxY; - [path addLineToPoint:pt]; - pt.x += cornerRadius; - [path appendPath:[UIBezierPath bezierPathWithArcCenter:pt radius:cornerRadius startAngle:degreesToRadians(180) endAngle:degreesToRadians(90) clockwise:YES]]; - pt.y -= cornerRadius; - [path addLineToPoint:pt]; - pt.x -= cornerRadius; - [path addLineToPoint:pt]; - [path closePath]; - - break; - - case MGCornersPositionTrailingHorizontal: // right of screen for a top/bottom split - pt.y = cornerRadius; - [path moveToPoint:pt]; - pt.y -= cornerRadius; - [path appendPath:[UIBezierPath bezierPathWithArcCenter:pt radius:cornerRadius startAngle:degreesToRadians(270) endAngle:degreesToRadians(360) clockwise:NO]]; - pt.x += cornerRadius; - pt.y += cornerRadius; - [path addLineToPoint:pt]; - pt.x -= cornerRadius; - [path addLineToPoint:pt]; - [path closePath]; - - pt.y = maxY - cornerRadius; - [path moveToPoint:pt]; - pt.y += cornerRadius; - [path appendPath:[UIBezierPath bezierPathWithArcCenter:pt radius:cornerRadius startAngle:degreesToRadians(90) endAngle:0 clockwise:YES]]; - pt.x += cornerRadius; - pt.y -= cornerRadius; - [path addLineToPoint:pt]; - pt.x -= cornerRadius; - [path addLineToPoint:pt]; - [path closePath]; - - break; - - default: - break; - } - - [self.cornerBackgroundColor set]; - [path fill]; - } + // Draw two appropriate corners, with cornerBackgroundColor behind them. + if (cornerRadius > 0) { + + float maxX = CGRectGetMaxX(self.bounds); + float maxY = CGRectGetMaxY(self.bounds); + UIBezierPath *path = [UIBezierPath bezierPath]; + CGPoint pt = CGPointZero; + switch (cornersPosition) { + case MGCornersPositionLeadingVertical: // top of screen for a left/right split + [path moveToPoint:pt]; + pt.y += cornerRadius; + [path appendPath:[UIBezierPath bezierPathWithArcCenter:pt radius:cornerRadius startAngle:(float)deg2Rad(90) endAngle:0 clockwise:YES]]; + pt.x += cornerRadius; + pt.y -= cornerRadius; + [path addLineToPoint:pt]; + [path addLineToPoint:CGPointZero]; + [path closePath]; + + pt.x = maxX - cornerRadius; + pt.y = 0; + [path moveToPoint:pt]; + pt.y = maxY; + [path addLineToPoint:pt]; + pt.x += cornerRadius; + [path appendPath:[UIBezierPath bezierPathWithArcCenter:pt radius:cornerRadius startAngle:(float)deg2Rad(180) endAngle:(float)deg2Rad(90) clockwise:YES]]; + pt.y -= cornerRadius; + [path addLineToPoint:pt]; + pt.x -= cornerRadius; + [path addLineToPoint:pt]; + [path closePath]; + + break; + + case MGCornersPositionTrailingVertical: // bottom of screen for a left/right split + pt.y = maxY; + [path moveToPoint:pt]; + pt.y -= cornerRadius; + [path appendPath:[UIBezierPath bezierPathWithArcCenter:pt radius:cornerRadius startAngle:(float)deg2Rad(270) endAngle:(float)deg2Rad(360) clockwise:NO]]; + pt.x += cornerRadius; + pt.y += cornerRadius; + [path addLineToPoint:pt]; + pt.x -= cornerRadius; + [path addLineToPoint:pt]; + [path closePath]; + + pt.x = maxX - cornerRadius; + pt.y = maxY; + [path moveToPoint:pt]; + pt.y -= cornerRadius; + [path addLineToPoint:pt]; + pt.x += cornerRadius; + [path appendPath:[UIBezierPath bezierPathWithArcCenter:pt radius:cornerRadius startAngle:(float)deg2Rad(180) endAngle:(float)deg2Rad(270) clockwise:NO]]; + pt.y += cornerRadius; + [path addLineToPoint:pt]; + pt.x -= cornerRadius; + [path addLineToPoint:pt]; + [path closePath]; + + break; + + case MGCornersPositionLeadingHorizontal: // left of screen for a top/bottom split + pt.x = 0; + pt.y = cornerRadius; + [path moveToPoint:pt]; + pt.y -= cornerRadius; + [path addLineToPoint:pt]; + pt.x += cornerRadius; + [path appendPath:[UIBezierPath bezierPathWithArcCenter:pt radius:cornerRadius startAngle:(float)deg2Rad(180) endAngle:(float)deg2Rad(270) clockwise:NO]]; + pt.y += cornerRadius; + [path addLineToPoint:pt]; + pt.x -= cornerRadius; + [path addLineToPoint:pt]; + [path closePath]; + + pt.x = 0; + pt.y = maxY - cornerRadius; + [path moveToPoint:pt]; + pt.y = maxY; + [path addLineToPoint:pt]; + pt.x += cornerRadius; + [path appendPath:[UIBezierPath bezierPathWithArcCenter:pt radius:cornerRadius startAngle:(float)deg2Rad(180) endAngle:(float)deg2Rad(90) clockwise:YES]]; + pt.y -= cornerRadius; + [path addLineToPoint:pt]; + pt.x -= cornerRadius; + [path addLineToPoint:pt]; + [path closePath]; + + break; + + case MGCornersPositionTrailingHorizontal: // right of screen for a top/bottom split + pt.y = cornerRadius; + [path moveToPoint:pt]; + pt.y -= cornerRadius; + [path appendPath:[UIBezierPath bezierPathWithArcCenter:pt radius:cornerRadius startAngle:(float)deg2Rad(270) endAngle:(float)deg2Rad(360) clockwise:NO]]; + pt.x += cornerRadius; + pt.y += cornerRadius; + [path addLineToPoint:pt]; + pt.x -= cornerRadius; + [path addLineToPoint:pt]; + [path closePath]; + + pt.y = maxY - cornerRadius; + [path moveToPoint:pt]; + pt.y += cornerRadius; + [path appendPath:[UIBezierPath bezierPathWithArcCenter:pt radius:cornerRadius startAngle:(float)deg2Rad(90) endAngle:0 clockwise:YES]]; + pt.x += cornerRadius; + pt.y -= cornerRadius; + [path addLineToPoint:pt]; + pt.x -= cornerRadius; + [path addLineToPoint:pt]; + [path closePath]; + + break; + + default: + break; + } + + [self.cornerBackgroundColor set]; + [path fill]; + } } @@ -179,38 +184,37 @@ - (void)setCornerRadius:(float)newRadius { - if (newRadius != cornerRadius) { - cornerRadius = newRadius; - [self setNeedsDisplay]; - } + if (newRadius != cornerRadius) { + cornerRadius = newRadius; + [self setNeedsDisplay]; + } } - (void)setSplitViewController:(MGSplitViewController *)theController { - if (theController != splitViewController) { - splitViewController = theController; - [self setNeedsDisplay]; - } + if (theController != splitViewController) { + splitViewController = theController; + [self setNeedsDisplay]; + } } - (void)setCornersPosition:(MGCornersPosition)posn { - if (cornersPosition != posn) { - cornersPosition = posn; - [self setNeedsDisplay]; - } + if (cornersPosition != posn) { + cornersPosition = posn; + [self setNeedsDisplay]; + } } - (void)setCornerBackgroundColor:(UIColor *)color { - if (color != cornerBackgroundColor) { - [cornerBackgroundColor release]; - cornerBackgroundColor = [color retain]; - [self setNeedsDisplay]; - } + if (color != cornerBackgroundColor) { + cornerBackgroundColor = color; + [self setNeedsDisplay]; + } } diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/MGSplitViewController/MGSplitDividerView.h --- a/project_files/HedgewarsMobile/Classes/MGSplitViewController/MGSplitDividerView.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/MGSplitViewController/MGSplitDividerView.h Tue Nov 10 20:43:13 2015 +0100 @@ -10,11 +10,11 @@ @class MGSplitViewController; @interface MGSplitDividerView : UIView { - MGSplitViewController *splitViewController; - BOOL allowsDragging; + MGSplitViewController *__unsafe_unretained splitViewController; + BOOL allowsDragging; } -@property (nonatomic, assign) MGSplitViewController *splitViewController; // weak ref. +@property (nonatomic, unsafe_unretained) MGSplitViewController *splitViewController; // weak ref. @property (nonatomic, assign) BOOL allowsDragging; - (void)drawGripThumbInRect:(CGRect)rect; diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/MGSplitViewController/MGSplitDividerView.m --- a/project_files/HedgewarsMobile/Classes/MGSplitViewController/MGSplitDividerView.m Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/MGSplitViewController/MGSplitDividerView.m Tue Nov 10 20:43:13 2015 +0100 @@ -19,19 +19,18 @@ - (id)initWithFrame:(CGRect)frame { - if ((self = [super initWithFrame:frame])) { - self.userInteractionEnabled = NO; - self.allowsDragging = NO; - self.contentMode = UIViewContentModeRedraw; - } - return self; + if ((self = [super initWithFrame:frame])) { + self.userInteractionEnabled = NO; + self.allowsDragging = NO; + self.contentMode = UIViewContentModeRedraw; + } + return self; } - (void)dealloc { - self.splitViewController = nil; - [super dealloc]; + self.splitViewController = nil; } @@ -41,139 +40,139 @@ - (void)drawRect:(CGRect)rect { - if (splitViewController.dividerStyle == MGSplitViewDividerStyleThin) { - [super drawRect:rect]; - - } else if (splitViewController.dividerStyle == MGSplitViewDividerStylePaneSplitter) { - // Draw gradient background. - CGRect bounds = self.bounds; - CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB(); - CGFloat locations[2] = {0, 1}; - CGFloat components[8] = { 0.988, 0.988, 0.988, 1.0, // light - 0.875, 0.875, 0.875, 1.0 };// dark - CGGradientRef gradient = CGGradientCreateWithColorComponents (rgb, components, locations, 2); - CGContextRef context = UIGraphicsGetCurrentContext(); - CGPoint start, end; - if (splitViewController.vertical) { - // Light left to dark right. - start = CGPointMake(CGRectGetMinX(bounds), CGRectGetMidY(bounds)); - end = CGPointMake(CGRectGetMaxX(bounds), CGRectGetMidY(bounds)); - } else { - // Light top to dark bottom. - start = CGPointMake(CGRectGetMidX(bounds), CGRectGetMinY(bounds)); - end = CGPointMake(CGRectGetMidX(bounds), CGRectGetMaxY(bounds)); - } - CGContextDrawLinearGradient(context, gradient, start, end, 0); - CGColorSpaceRelease(rgb); - CGGradientRelease(gradient); - - // Draw borders. - float borderThickness = 1.0; - [[UIColor colorWithWhite:0.7 alpha:1.0] set]; - CGRect borderRect = bounds; - if (splitViewController.vertical) { - borderRect.size.width = borderThickness; - UIRectFill(borderRect); - borderRect.origin.x = CGRectGetMaxX(bounds) - borderThickness; - UIRectFill(borderRect); - - } else { - borderRect.size.height = borderThickness; - UIRectFill(borderRect); - borderRect.origin.y = CGRectGetMaxY(bounds) - borderThickness; - UIRectFill(borderRect); - } - - // Draw grip. - [self drawGripThumbInRect:bounds]; - } + if (splitViewController.dividerStyle == MGSplitViewDividerStyleThin) { + [super drawRect:rect]; + + } else if (splitViewController.dividerStyle == MGSplitViewDividerStylePaneSplitter) { + // Draw gradient background. + CGRect bounds = self.bounds; + CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB(); + CGFloat locations[2] = {0, 1}; + CGFloat components[8] = { 0.988f, 0.988f, 0.988f, 1.0, // light + 0.875, 0.875, 0.875, 1.0 };// dark + CGGradientRef gradient = CGGradientCreateWithColorComponents (rgb, components, locations, 2); + CGContextRef context = UIGraphicsGetCurrentContext(); + CGPoint start, end; + if (splitViewController.vertical) { + // Light left to dark right. + start = CGPointMake(CGRectGetMinX(bounds), CGRectGetMidY(bounds)); + end = CGPointMake(CGRectGetMaxX(bounds), CGRectGetMidY(bounds)); + } else { + // Light top to dark bottom. + start = CGPointMake(CGRectGetMidX(bounds), CGRectGetMinY(bounds)); + end = CGPointMake(CGRectGetMidX(bounds), CGRectGetMaxY(bounds)); + } + CGContextDrawLinearGradient(context, gradient, start, end, 0); + CGColorSpaceRelease(rgb); + CGGradientRelease(gradient); + + // Draw borders. + float borderThickness = 1.0; + [[UIColor colorWithWhite:0.7f alpha:1.0] set]; + CGRect borderRect = bounds; + if (splitViewController.vertical) { + borderRect.size.width = borderThickness; + UIRectFill(borderRect); + borderRect.origin.x = CGRectGetMaxX(bounds) - borderThickness; + UIRectFill(borderRect); + + } else { + borderRect.size.height = borderThickness; + UIRectFill(borderRect); + borderRect.origin.y = CGRectGetMaxY(bounds) - borderThickness; + UIRectFill(borderRect); + } + + // Draw grip. + [self drawGripThumbInRect:bounds]; + } } - (void)drawGripThumbInRect:(CGRect)rect { - float width = 9.0; - float height; - if (splitViewController.vertical) { - height = 30.0; - } else { - height = width; - width = 30.0; - } - - // Draw grip in centred in rect. - CGRect gripRect = CGRectMake(0, 0, width, height); - gripRect.origin.x = ((rect.size.width - gripRect.size.width) / 2.0); - gripRect.origin.y = ((rect.size.height - gripRect.size.height) / 2.0); - - float stripThickness = 1.0; - UIColor *stripColor = [UIColor colorWithWhite:0.35 alpha:1.0]; - UIColor *lightColor = [UIColor colorWithWhite:1.0 alpha:1.0]; - float space = 3.0; - if (splitViewController.vertical) { - gripRect.size.width = stripThickness; - [stripColor set]; - UIRectFill(gripRect); - - gripRect.origin.x += stripThickness; - gripRect.origin.y += 1; - [lightColor set]; - UIRectFill(gripRect); - gripRect.origin.x -= stripThickness; - gripRect.origin.y -= 1; - - gripRect.origin.x += space + stripThickness; - [stripColor set]; - UIRectFill(gripRect); - - gripRect.origin.x += stripThickness; - gripRect.origin.y += 1; - [lightColor set]; - UIRectFill(gripRect); - gripRect.origin.x -= stripThickness; - gripRect.origin.y -= 1; - - gripRect.origin.x += space + stripThickness; - [stripColor set]; - UIRectFill(gripRect); - - gripRect.origin.x += stripThickness; - gripRect.origin.y += 1; - [lightColor set]; - UIRectFill(gripRect); - - } else { - gripRect.size.height = stripThickness; - [stripColor set]; - UIRectFill(gripRect); - - gripRect.origin.y += stripThickness; - gripRect.origin.x -= 1; - [lightColor set]; - UIRectFill(gripRect); - gripRect.origin.y -= stripThickness; - gripRect.origin.x += 1; - - gripRect.origin.y += space + stripThickness; - [stripColor set]; - UIRectFill(gripRect); - - gripRect.origin.y += stripThickness; - gripRect.origin.x -= 1; - [lightColor set]; - UIRectFill(gripRect); - gripRect.origin.y -= stripThickness; - gripRect.origin.x += 1; - - gripRect.origin.y += space + stripThickness; - [stripColor set]; - UIRectFill(gripRect); - - gripRect.origin.y += stripThickness; - gripRect.origin.x -= 1; - [lightColor set]; - UIRectFill(gripRect); - } + float width = 9.0; + float height; + if (splitViewController.vertical) { + height = 30.0; + } else { + height = width; + width = 30.0; + } + + // Draw grip in centred in rect. + CGRect gripRect = CGRectMake(0, 0, width, height); + gripRect.origin.x = ((rect.size.width - gripRect.size.width) / 2.f); + gripRect.origin.y = ((rect.size.height - gripRect.size.height) / 2.f); + + float stripThickness = 1.0; + UIColor *stripColor = [UIColor colorWithWhite:0.35f alpha:1.0]; + UIColor *lightColor = [UIColor colorWithWhite:1.0 alpha:1.0]; + float space = 3.0; + if (splitViewController.vertical) { + gripRect.size.width = stripThickness; + [stripColor set]; + UIRectFill(gripRect); + + gripRect.origin.x += stripThickness; + gripRect.origin.y += 1; + [lightColor set]; + UIRectFill(gripRect); + gripRect.origin.x -= stripThickness; + gripRect.origin.y -= 1; + + gripRect.origin.x += space + stripThickness; + [stripColor set]; + UIRectFill(gripRect); + + gripRect.origin.x += stripThickness; + gripRect.origin.y += 1; + [lightColor set]; + UIRectFill(gripRect); + gripRect.origin.x -= stripThickness; + gripRect.origin.y -= 1; + + gripRect.origin.x += space + stripThickness; + [stripColor set]; + UIRectFill(gripRect); + + gripRect.origin.x += stripThickness; + gripRect.origin.y += 1; + [lightColor set]; + UIRectFill(gripRect); + + } else { + gripRect.size.height = stripThickness; + [stripColor set]; + UIRectFill(gripRect); + + gripRect.origin.y += stripThickness; + gripRect.origin.x -= 1; + [lightColor set]; + UIRectFill(gripRect); + gripRect.origin.y -= stripThickness; + gripRect.origin.x += 1; + + gripRect.origin.y += space + stripThickness; + [stripColor set]; + UIRectFill(gripRect); + + gripRect.origin.y += stripThickness; + gripRect.origin.x -= 1; + [lightColor set]; + UIRectFill(gripRect); + gripRect.origin.y -= stripThickness; + gripRect.origin.x += 1; + + gripRect.origin.y += space + stripThickness; + [stripColor set]; + UIRectFill(gripRect); + + gripRect.origin.y += stripThickness; + gripRect.origin.x -= 1; + [lightColor set]; + UIRectFill(gripRect); + } } @@ -183,16 +182,16 @@ - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { - UITouch *touch = [touches anyObject]; - if (touch) { - CGPoint lastPt = [touch previousLocationInView:self]; - CGPoint pt = [touch locationInView:self]; - float offset = (splitViewController.vertical) ? pt.x - lastPt.x : pt.y - lastPt.y; - if (!splitViewController.masterBeforeDetail) { - offset = -offset; - } - splitViewController.splitPosition = splitViewController.splitPosition + offset; - } + UITouch *touch = [touches anyObject]; + if (touch) { + CGPoint lastPt = [touch previousLocationInView:self]; + CGPoint pt = [touch locationInView:self]; + float offset = (splitViewController.vertical) ? pt.x - lastPt.x : pt.y - lastPt.y; + if (!splitViewController.masterBeforeDetail) { + offset = -offset; + } + splitViewController.splitPosition = splitViewController.splitPosition + offset; + } } @@ -202,10 +201,10 @@ - (void)setAllowsDragging:(BOOL)flag { - if (flag != allowsDragging) { - allowsDragging = flag; - self.userInteractionEnabled = allowsDragging; - } + if (flag != allowsDragging) { + allowsDragging = flag; + self.userInteractionEnabled = allowsDragging; + } } diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/MGSplitViewController/MGSplitViewController.h --- a/project_files/HedgewarsMobile/Classes/MGSplitViewController/MGSplitViewController.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/MGSplitViewController/MGSplitViewController.h Tue Nov 10 20:43:13 2015 +0100 @@ -9,31 +9,32 @@ #import typedef enum _MGSplitViewDividerStyle { - // These names have been chosen to be conceptually similar to those of NSSplitView on Mac OS X. - MGSplitViewDividerStyleThin = 0, // Thin divider, like UISplitViewController (default). - MGSplitViewDividerStylePaneSplitter = 1 // Thick divider, drawn with a grey gradient and a grab-strip. + // These names have been chosen to be conceptually similar to those of NSSplitView on Mac OS X. + MGSplitViewDividerStyleThin = 0, // Thin divider, like UISplitViewController (default). + MGSplitViewDividerStylePaneSplitter = 1 // Thick divider, drawn with a grey gradient and a grab-strip. } MGSplitViewDividerStyle; @class MGSplitDividerView; @protocol MGSplitViewControllerDelegate; @interface MGSplitViewController : UIViewController { - BOOL _showsMasterInPortrait; - BOOL _showsMasterInLandscape; - float _splitWidth; - id _delegate; - BOOL _vertical; - BOOL _masterBeforeDetail; - NSMutableArray *_viewControllers; - UIBarButtonItem *_barButtonItem; // To be compliant with wacky UISplitViewController behaviour. + BOOL _showsMasterInPortrait; + BOOL _showsMasterInLandscape; + float _splitWidth; + id _delegate; + BOOL _vertical; + BOOL _masterBeforeDetail; + NSMutableArray *_viewControllers; + UIBarButtonItem *_barButtonItem; // To be compliant with wacky UISplitViewController behaviour. UIPopoverController *_hiddenPopoverController; // Popover used to hold the master view if it's not always visible. - MGSplitDividerView *_dividerView; // View that draws the divider between the master and detail views. - NSArray *_cornerViews; // Views to draw the inner rounded corners between master and detail views. - float _splitPosition; - BOOL _reconfigurePopup; - MGSplitViewDividerStyle _dividerStyle; // Meta-setting which configures several aspects of appearance and behaviour. + MGSplitDividerView *_dividerView; // View that draws the divider between the master and detail views. + NSArray *_cornerViews; // Views to draw the inner rounded corners between master and detail views. + float _splitPosition; + BOOL _reconfigurePopup; + MGSplitViewDividerStyle _dividerStyle; // Meta-setting which configures several aspects of appearance and behaviour. + BOOL togglesMasterPopover; } -@property (nonatomic, assign) IBOutlet id delegate; +@property (nonatomic, unsafe_unretained) IBOutlet id delegate; @property (nonatomic, assign) BOOL showsMasterInPortrait; // applies to both portrait orientations (default NO) @property (nonatomic, assign) BOOL showsMasterInLandscape; // applies to both landscape orientations (default YES) @property (nonatomic, assign, getter=isVertical) BOOL vertical; // if NO, split is horizontal, i.e. master above detail (default YES) @@ -43,31 +44,34 @@ @property (nonatomic, assign) BOOL allowsDraggingDivider; // whether to let the user drag the divider to alter the split position (default NO). @property (nonatomic, copy) NSArray *viewControllers; // array of UIViewControllers; master is at index 0, detail is at index 1. -@property (nonatomic, retain) IBOutlet UIViewController *masterViewController; // convenience. -@property (nonatomic, retain) IBOutlet UIViewController *detailViewController; // convenience. -@property (nonatomic, retain) MGSplitDividerView *dividerView; // the view which draws the divider/split between master and detail. +@property (nonatomic, strong) IBOutlet UIViewController *masterViewController; // convenience. +@property (nonatomic, strong) IBOutlet UIViewController *detailViewController; // convenience. +@property (nonatomic, strong) MGSplitDividerView *dividerView; // the view which draws the divider/split between master and detail. @property (nonatomic, assign) MGSplitViewDividerStyle dividerStyle; // style (and behaviour) of the divider between master and detail. @property (nonatomic, readonly, getter=isLandscape) BOOL landscape; // returns YES if this view controller is in either of the two Landscape orientations, else NO. +@property (nonatomic, readwrite) BOOL togglesMasterPopover; // default is NO. + // Actions - (IBAction)toggleSplitOrientation:(id)sender; // toggles split axis between vertical (left/right; default) and horizontal (top/bottom). - (IBAction)toggleMasterBeforeDetail:(id)sender; // toggles position of master view relative to detail view. - (IBAction)toggleMasterView:(id)sender; // toggles display of the master view in the current orientation. - (IBAction)showMasterPopover:(id)sender; // shows the master view in a popover spawned from the provided barButtonItem, if it's currently hidden. +- (IBAction)hideMasterPopover:(id)sender; // hides the master view in a popover spawned from the provided barButtonItem, if it's currently shown. - (void)notePopoverDismissed; // should rarely be needed, because you should not change the popover's delegate. If you must, then call this when it's dismissed. // Conveniences for you, because I care. - (BOOL)isShowingMaster; - (void)setSplitPosition:(float)posn animated:(BOOL)animate; // Allows for animation of splitPosition changes. The property's regular setter is not animated. -/* Note: splitPosition is the width (in a left/right split, or height in a top/bottom split) of the master view. - It is relative to the appropriate side of the splitView, which can be any of the four sides depending on the values in isMasterBeforeDetail and isVertical: - isVertical = YES, isMasterBeforeDetail = YES: splitPosition is relative to the LEFT edge. (Default) - isVertical = YES, isMasterBeforeDetail = NO: splitPosition is relative to the RIGHT edge. - isVertical = NO, isMasterBeforeDetail = YES: splitPosition is relative to the TOP edge. - isVertical = NO, isMasterBeforeDetail = NO: splitPosition is relative to the BOTTOM edge. +/* Note: splitPosition is the width (in a left/right split, or height in a top/bottom split) of the master view. + It is relative to the appropriate side of the splitView, which can be any of the four sides depending on the values in isMasterBeforeDetail and isVertical: + isVertical = YES, isMasterBeforeDetail = YES: splitPosition is relative to the LEFT edge. (Default) + isVertical = YES, isMasterBeforeDetail = NO: splitPosition is relative to the RIGHT edge. + isVertical = NO, isMasterBeforeDetail = YES: splitPosition is relative to the TOP edge. + isVertical = NO, isMasterBeforeDetail = NO: splitPosition is relative to the BOTTOM edge. - This implementation was chosen so you don't need to recalculate equivalent splitPositions if the user toggles masterBeforeDetail themselves. + This implementation was chosen so you don't need to recalculate equivalent splitPositions if the user toggles masterBeforeDetail themselves. */ - (void)setDividerStyle:(MGSplitViewDividerStyle)newStyle animated:(BOOL)animate; // Allows for animation of dividerStyle changes. The property's regular setter is not animated. - (NSArray *)cornerViews; @@ -76,8 +80,8 @@ The first view is the "leading" corners (top edge of screen for left/right split, left edge of screen for top/bottom split). The second view is the "trailing" corners (bottom edge of screen for left/right split, right edge of screen for top/bottom split). Do NOT modify them, except to: - 1. Change their .cornerBackgroundColor - 2. Change their .cornerRadius + 1. Change their .cornerBackgroundColor + 2. Change their .cornerRadius */ @end @@ -88,21 +92,26 @@ @optional // Called when a button should be added to a toolbar for a hidden view controller. -- (void)splitViewController:(MGSplitViewController*)svc - willHideViewController:(UIViewController *)aViewController - withBarButtonItem:(UIBarButtonItem*)barButtonItem - forPopoverController: (UIPopoverController*)pc; +- (void)splitViewController:(MGSplitViewController*)svc + willHideViewController:(UIViewController *)aViewController + withBarButtonItem:(UIBarButtonItem*)barButtonItem + forPopoverController: (UIPopoverController*)pc; // Called when the master view is shown again in the split view, invalidating the button and popover controller. -- (void)splitViewController:(MGSplitViewController*)svc - willShowViewController:(UIViewController *)aViewController +- (void)splitViewController:(MGSplitViewController*)svc + willShowViewController:(UIViewController *)aViewController invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem; // Called when the master view is shown in a popover, so the delegate can take action like hiding other popovers. -- (void)splitViewController:(MGSplitViewController*)svc - popoverController:(UIPopoverController*)pc +- (void)splitViewController:(MGSplitViewController*)svc + popoverController:(UIPopoverController*)pc willPresentViewController:(UIViewController *)aViewController; +// Called when a popover containing the master view is going to be hidden so the delegate can take action like showing other popovers. This only happens if togglesMasterPopover is set to YES. +- (void)splitViewController:(MGSplitViewController*)svc + popoverController:(UIPopoverController*)pc + willDismissViewController:(UIViewController *)aViewController; + // Called when the split orientation will change (from vertical to horizontal, or vice versa). - (void)splitViewController:(MGSplitViewController*)svc willChangeSplitOrientationToVertical:(BOOL)isVertical; diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/MGSplitViewController/MGSplitViewController.m --- a/project_files/HedgewarsMobile/Classes/MGSplitViewController/MGSplitViewController.m Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/MGSplitViewController/MGSplitViewController.m Tue Nov 10 20:43:13 2015 +0100 @@ -10,19 +10,18 @@ #import "MGSplitDividerView.h" #import "MGSplitCornersView.h" -#define MG_DEFAULT_SPLIT_POSITION 320.0 // default width of master view in UISplitViewController. -#define MG_DEFAULT_SPLIT_WIDTH 1.0 // default width of split-gutter in UISplitViewController. -#define MG_DEFAULT_CORNER_RADIUS 5.0 // default corner-radius of overlapping split-inner corners on the master and detail views. -#define MG_DEFAULT_CORNER_COLOR [UIColor blackColor] // default color of intruding inner corners (and divider background). +#define MG_DEFAULT_SPLIT_POSITION 320.0 // default width of master view in UISplitViewController. +#define MG_DEFAULT_SPLIT_WIDTH 1.0 // default width of split-gutter in UISplitViewController. +#define MG_DEFAULT_CORNER_RADIUS 5.0 // default corner-radius of overlapping split-inner corners on the master and detail views. +#define MG_DEFAULT_CORNER_COLOR [UIColor blackColor] // default color of intruding inner corners (and divider background). -#define MG_PANESPLITTER_CORNER_RADIUS 0.0 // corner-radius of split-inner corners for MGSplitViewDividerStylePaneSplitter style. -#define MG_PANESPLITTER_SPLIT_WIDTH 25.0 // width of split-gutter for MGSplitViewDividerStylePaneSplitter style. +#define MG_PANESPLITTER_CORNER_RADIUS 0.0 // corner-radius of split-inner corners for MGSplitViewDividerStylePaneSplitter style. +#define MG_PANESPLITTER_SPLIT_WIDTH 25.0 // width of split-gutter for MGSplitViewDividerStylePaneSplitter style. -#define MG_MIN_VIEW_WIDTH 200.0 // minimum width a view is allowed to become as a result of changing the splitPosition. +#define MG_MIN_VIEW_WIDTH 200.0 // minimum width a view is allowed to become as a result of changing the splitPosition. -#define MG_ANIMATION_CHANGE_SPLIT_ORIENTATION @"ChangeSplitOrientation" // Animation ID for internal use. -#define MG_ANIMATION_CHANGE_SUBVIEWS_ORDER @"ChangeSubviewsOrder" // Animation ID for internal use. - +#define MG_ANIMATION_CHANGE_SPLIT_ORIENTATION @"ChangeSplitOrientation" // Animation ID for internal use. +#define MG_ANIMATION_CHANGE_SUBVIEWS_ORDER @"ChangeSubviewsOrder" // Animation ID for internal use. @interface MGSplitViewController (MGPrivateMethods) @@ -48,50 +47,50 @@ - (NSString *)nameOfInterfaceOrientation:(UIInterfaceOrientation)theOrientation { - NSString *orientationName = nil; - switch (theOrientation) { - case UIInterfaceOrientationPortrait: - orientationName = @"Portrait"; // Home button at bottom - break; - case UIInterfaceOrientationPortraitUpsideDown: - orientationName = @"Portrait (Upside Down)"; // Home button at top - break; - case UIInterfaceOrientationLandscapeLeft: - orientationName = @"Landscape (Left)"; // Home button on left - break; - case UIInterfaceOrientationLandscapeRight: - orientationName = @"Landscape (Right)"; // Home button on right - break; - default: - break; - } - - return orientationName; + NSString *orientationName = nil; + switch (theOrientation) { + case UIInterfaceOrientationPortrait: + orientationName = @"Portrait"; // Home button at bottom + break; + case UIInterfaceOrientationPortraitUpsideDown: + orientationName = @"Portrait (Upside Down)"; // Home button at top + break; + case UIInterfaceOrientationLandscapeLeft: + orientationName = @"Landscape (Left)"; // Home button on left + break; + case UIInterfaceOrientationLandscapeRight: + orientationName = @"Landscape (Right)"; // Home button on right + break; + default: + break; + } + + return orientationName; } - (BOOL)isLandscape { - return UIInterfaceOrientationIsLandscape(self.interfaceOrientation); + return UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]); } - (BOOL)shouldShowMasterForInterfaceOrientation:(UIInterfaceOrientation)theOrientation { - // Returns YES if master view should be shown directly embedded in the splitview, instead of hidden in a popover. - return ((UIInterfaceOrientationIsLandscape(theOrientation)) ? _showsMasterInLandscape : _showsMasterInPortrait); + // Returns YES if master view should be shown directly embedded in the splitview, instead of hidden in a popover. + return ((UIInterfaceOrientationIsLandscape(theOrientation)) ? _showsMasterInLandscape : _showsMasterInPortrait); } - (BOOL)shouldShowMaster { - return [self shouldShowMasterForInterfaceOrientation:self.interfaceOrientation]; + return [self shouldShowMasterForInterfaceOrientation:[[UIApplication sharedApplication] statusBarOrientation]]; } - (BOOL)isShowingMaster { - return [self shouldShowMaster] && self.masterViewController && self.masterViewController.view && ([self.masterViewController.view superview] == self.view); + return [self shouldShowMaster] && self.masterViewController && self.masterViewController.view && ([self.masterViewController.view superview] == self.view); } @@ -101,61 +100,58 @@ - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { - if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) { - [self setup]; - } - - return self; + if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) { + [self setup]; + } + + return self; } - (id)initWithCoder:(NSCoder *)aDecoder { - if ((self = [super initWithCoder:aDecoder])) { - [self setup]; - } - - return self; + if ((self = [super initWithCoder:aDecoder])) { + [self setup]; + } + + return self; } - (void)setup { - // Configure default behaviour. - _viewControllers = [[NSMutableArray alloc] initWithObjects:[NSNull null], [NSNull null], nil]; - _splitWidth = MG_DEFAULT_SPLIT_WIDTH; - _showsMasterInPortrait = NO; - _showsMasterInLandscape = YES; - _reconfigurePopup = NO; - _vertical = YES; - _masterBeforeDetail = YES; - _splitPosition = MG_DEFAULT_SPLIT_POSITION; - CGRect divRect = self.view.bounds; - if ([self isVertical]) { - divRect.origin.y = _splitPosition; - divRect.size.height = _splitWidth; - } else { - divRect.origin.x = _splitPosition; - divRect.size.width = _splitWidth; - } - _dividerView = [[MGSplitDividerView alloc] initWithFrame:divRect]; - _dividerView.splitViewController = self; - _dividerView.backgroundColor = MG_DEFAULT_CORNER_COLOR; - _dividerStyle = MGSplitViewDividerStyleThin; + // Configure default behaviour. + _viewControllers = [[NSMutableArray alloc] initWithObjects:[NSNull null], [NSNull null], nil]; + _splitWidth = MG_DEFAULT_SPLIT_WIDTH; + _showsMasterInPortrait = NO; + _showsMasterInLandscape = YES; + _reconfigurePopup = NO; + _vertical = YES; + _masterBeforeDetail = YES; + _splitPosition = MG_DEFAULT_SPLIT_POSITION; + CGRect divRect = self.view.bounds; + if ([self isVertical]) { + divRect.origin.y = _splitPosition; + divRect.size.height = _splitWidth; + } else { + divRect.origin.x = _splitPosition; + divRect.size.width = _splitWidth; + } + _dividerView = [[MGSplitDividerView alloc] initWithFrame:divRect]; + _dividerView.splitViewController = self; + _dividerView.backgroundColor = MG_DEFAULT_CORNER_COLOR; + _dividerStyle = MGSplitViewDividerStyleThin; + + // fix for iOS 6 layout + self.view.autoresizesSubviews = NO; } - (void)dealloc { - _delegate = nil; - [self.view.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)]; - [_viewControllers release]; - [_barButtonItem release]; - [_hiddenPopoverController release]; - [_dividerView release]; - [_cornerViews release]; - - [super dealloc]; + _delegate = nil; + _viewControllers = nil; + [self.view.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)]; } @@ -165,377 +161,370 @@ - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { + if (self.detailViewController) + { + return [self.detailViewController shouldAutorotateToInterfaceOrientation:interfaceOrientation]; + } + return YES; } - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { - [self.masterViewController willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration]; - [self.detailViewController willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration]; + [self.masterViewController willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration]; + [self.detailViewController willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration]; } - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation { - [self.masterViewController didRotateFromInterfaceOrientation:fromInterfaceOrientation]; - [self.detailViewController didRotateFromInterfaceOrientation:fromInterfaceOrientation]; + [self.masterViewController didRotateFromInterfaceOrientation:fromInterfaceOrientation]; + [self.detailViewController didRotateFromInterfaceOrientation:fromInterfaceOrientation]; } -- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation - duration:(NSTimeInterval)duration +- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation + duration:(NSTimeInterval)duration { - [self.masterViewController willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration]; - [self.detailViewController willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration]; - - // Hide popover. - if (_hiddenPopoverController && _hiddenPopoverController.popoverVisible) { - [_hiddenPopoverController dismissPopoverAnimated:NO]; - } - - // Re-tile views. - _reconfigurePopup = YES; - [self layoutSubviewsForInterfaceOrientation:toInterfaceOrientation withAnimation:YES]; -} - - -- (void)willAnimateFirstHalfOfRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration -{ - [self.masterViewController willAnimateFirstHalfOfRotationToInterfaceOrientation:toInterfaceOrientation duration:duration]; - [self.detailViewController willAnimateFirstHalfOfRotationToInterfaceOrientation:toInterfaceOrientation duration:duration]; -} - - -- (void)didAnimateFirstHalfOfRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation -{ - [self.masterViewController didAnimateFirstHalfOfRotationToInterfaceOrientation:toInterfaceOrientation]; - [self.detailViewController didAnimateFirstHalfOfRotationToInterfaceOrientation:toInterfaceOrientation]; -} - - -- (void)willAnimateSecondHalfOfRotationFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation duration:(NSTimeInterval)duration -{ - [self.masterViewController willAnimateSecondHalfOfRotationFromInterfaceOrientation:fromInterfaceOrientation duration:duration]; - [self.detailViewController willAnimateSecondHalfOfRotationFromInterfaceOrientation:fromInterfaceOrientation duration:duration]; + [self.masterViewController willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration]; + [self.detailViewController willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration]; + + // Hide popover. + if (_hiddenPopoverController && _hiddenPopoverController.popoverVisible) { + [_hiddenPopoverController dismissPopoverAnimated:NO]; + } + + // Re-tile views. + _reconfigurePopup = YES; + [self layoutSubviewsForInterfaceOrientation:toInterfaceOrientation withAnimation:YES]; } - (CGSize)splitViewSizeForOrientation:(UIInterfaceOrientation)theOrientation { - UIScreen *screen = [UIScreen mainScreen]; - CGRect fullScreenRect = screen.bounds; // always implicitly in Portrait orientation. - CGRect appFrame = screen.applicationFrame; - - // Find status bar height by checking which dimension of the applicationFrame is narrower than screen bounds. - // Little bit ugly looking, but it'll still work even if they change the status bar height in future. - float statusBarHeight = MAX((fullScreenRect.size.width - appFrame.size.width), (fullScreenRect.size.height - appFrame.size.height)); - - // Initially assume portrait orientation. - float width = fullScreenRect.size.width; - float height = fullScreenRect.size.height; - - // Correct for orientation. - if (UIInterfaceOrientationIsLandscape(theOrientation)) { - width = height; - height = fullScreenRect.size.width; + UIScreen *screen = [UIScreen mainScreen]; + CGRect fullScreenRect = screen.bounds; // always implicitly in Portrait orientation. + CGRect appFrame = screen.applicationFrame; + + // Find status bar height by checking which dimension of the applicationFrame is narrower than screen bounds. + // Little bit ugly looking, but it'll still work even if they change the status bar height in future. + float statusBarHeight = MAX((fullScreenRect.size.width - appFrame.size.width), (fullScreenRect.size.height - appFrame.size.height)); + + // In iOS 7 the status bar is transparent, so don't adjust for it. + if (NSFoundationVersionNumber >= NSFoundationVersionNumber_iOS_7_0) { + statusBarHeight = 0; } - - // Account for status bar, which always subtracts from the height (since it's always at the top of the screen). - height -= statusBarHeight; - - return CGSizeMake(width, height); + + float navigationBarHeight = 0; + if ((self.navigationController)&&(!self.navigationController.navigationBarHidden)) { + navigationBarHeight = self.navigationController.navigationBar.frame.size.height; + } + + // Initially assume portrait orientation. + float width = fullScreenRect.size.width; + float height = fullScreenRect.size.height; + + // Correct for orientation (only for iOS7.1 and earlier, since iOS8 it will do it automatically). + if (NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_7_1 && UIInterfaceOrientationIsLandscape(theOrientation)) { + width = height; + height = fullScreenRect.size.width; + } + + // Account for status bar, which always subtracts from the height (since it's always at the top of the screen). + height -= statusBarHeight; + height -= navigationBarHeight; + + return CGSizeMake(width, height); } - (void)layoutSubviewsForInterfaceOrientation:(UIInterfaceOrientation)theOrientation withAnimation:(BOOL)animate { - if (_reconfigurePopup) { - [self reconfigureForMasterInPopover:![self shouldShowMasterForInterfaceOrientation:theOrientation]]; - } - - // Layout the master, detail and divider views appropriately, adding/removing subviews as needed. - // First obtain relevant geometry. - CGSize fullSize = [self splitViewSizeForOrientation:theOrientation]; - float width = fullSize.width; - float height = fullSize.height; - - if (NO) { // Just for debugging. - NSLog(@"Target orientation is %@, dimensions will be %.0f x %.0f", - [self nameOfInterfaceOrientation:theOrientation], width, height); - } - - // Layout the master, divider and detail views. - CGRect newFrame = CGRectMake(0, 0, width, height); - UIViewController *controller; - UIView *theView; - BOOL shouldShowMaster = [self shouldShowMasterForInterfaceOrientation:theOrientation]; - BOOL masterFirst = [self isMasterBeforeDetail]; - if ([self isVertical]) { - // Master on left, detail on right (or vice versa). - CGRect masterRect, dividerRect, detailRect; - if (masterFirst) { - if (!shouldShowMaster) { - // Move off-screen. - newFrame.origin.x -= (_splitPosition + _splitWidth); - } - - newFrame.size.width = _splitPosition; - masterRect = newFrame; - - newFrame.origin.x += newFrame.size.width; - newFrame.size.width = _splitWidth; - dividerRect = newFrame; - - newFrame.origin.x += newFrame.size.width; - newFrame.size.width = width - newFrame.origin.x; - detailRect = newFrame; - - } else { - if (!shouldShowMaster) { - // Move off-screen. - newFrame.size.width += (_splitPosition + _splitWidth); - } - - newFrame.size.width -= (_splitPosition + _splitWidth); - detailRect = newFrame; - - newFrame.origin.x += newFrame.size.width; - newFrame.size.width = _splitWidth; - dividerRect = newFrame; - - newFrame.origin.x += newFrame.size.width; - newFrame.size.width = _splitPosition; - masterRect = newFrame; - } - - // Position master. - controller = self.masterViewController; - if (controller && [controller isKindOfClass:[UIViewController class]]) { - theView = controller.view; - if (theView) { - theView.frame = masterRect; - if (!theView.superview) { - [controller viewWillAppear:NO]; - [self.view addSubview:theView]; - [controller viewDidAppear:NO]; - } - } - } - - // Position divider. - theView = _dividerView; - theView.frame = dividerRect; - if (!theView.superview) { - [self.view addSubview:theView]; - } - - // Position detail. - controller = self.detailViewController; - if (controller && [controller isKindOfClass:[UIViewController class]]) { - theView = controller.view; - if (theView) { - theView.frame = detailRect; - if (!theView.superview) { - [self.view insertSubview:theView aboveSubview:self.masterViewController.view]; - } else { - [self.view bringSubviewToFront:theView]; - } - } - } - - } else { - // Master above, detail below (or vice versa). - CGRect masterRect, dividerRect, detailRect; - if (masterFirst) { - if (!shouldShowMaster) { - // Move off-screen. - newFrame.origin.y -= (_splitPosition + _splitWidth); - } - - newFrame.size.height = _splitPosition; - masterRect = newFrame; - - newFrame.origin.y += newFrame.size.height; - newFrame.size.height = _splitWidth; - dividerRect = newFrame; - - newFrame.origin.y += newFrame.size.height; - newFrame.size.height = height - newFrame.origin.y; - detailRect = newFrame; - - } else { - if (!shouldShowMaster) { - // Move off-screen. - newFrame.size.height += (_splitPosition + _splitWidth); - } - - newFrame.size.height -= (_splitPosition + _splitWidth); - detailRect = newFrame; - - newFrame.origin.y += newFrame.size.height; - newFrame.size.height = _splitWidth; - dividerRect = newFrame; - - newFrame.origin.y += newFrame.size.height; - newFrame.size.height = _splitPosition; - masterRect = newFrame; - } - - // Position master. - controller = self.masterViewController; - if (controller && [controller isKindOfClass:[UIViewController class]]) { - theView = controller.view; - if (theView) { - theView.frame = masterRect; - if (!theView.superview) { - [controller viewWillAppear:NO]; - [self.view addSubview:theView]; - [controller viewDidAppear:NO]; - } - } - } - - // Position divider. - theView = _dividerView; - theView.frame = dividerRect; - if (!theView.superview) { - [self.view addSubview:theView]; - } - - // Position detail. - controller = self.detailViewController; - if (controller && [controller isKindOfClass:[UIViewController class]]) { - theView = controller.view; - if (theView) { - theView.frame = detailRect; - if (!theView.superview) { - [self.view insertSubview:theView aboveSubview:self.masterViewController.view]; - } else { - [self.view bringSubviewToFront:theView]; - } - } - } - } - - // Create corner views if necessary. - MGSplitCornersView *leadingCorners; // top/left of screen in vertical/horizontal split. - MGSplitCornersView *trailingCorners; // bottom/right of screen in vertical/horizontal split. - if (!_cornerViews) { - CGRect cornerRect = CGRectMake(0, 0, 10, 10); // arbitrary, will be resized below. - leadingCorners = [[MGSplitCornersView alloc] initWithFrame:cornerRect]; - leadingCorners.splitViewController = self; - leadingCorners.cornerBackgroundColor = MG_DEFAULT_CORNER_COLOR; - leadingCorners.cornerRadius = MG_DEFAULT_CORNER_RADIUS; - trailingCorners = [[MGSplitCornersView alloc] initWithFrame:cornerRect]; - trailingCorners.splitViewController = self; - trailingCorners.cornerBackgroundColor = MG_DEFAULT_CORNER_COLOR; - trailingCorners.cornerRadius = MG_DEFAULT_CORNER_RADIUS; - _cornerViews = [[NSArray alloc] initWithObjects:leadingCorners, trailingCorners, nil]; - [leadingCorners release]; - [trailingCorners release]; - - } else if ([_cornerViews count] == 2) { - leadingCorners = [_cornerViews objectAtIndex:0]; - trailingCorners = [_cornerViews objectAtIndex:1]; - } - - // Configure and layout the corner-views. - leadingCorners.cornersPosition = (_vertical) ? MGCornersPositionLeadingVertical : MGCornersPositionLeadingHorizontal; - trailingCorners.cornersPosition = (_vertical) ? MGCornersPositionTrailingVertical : MGCornersPositionTrailingHorizontal; - leadingCorners.autoresizingMask = (_vertical) ? UIViewAutoresizingFlexibleBottomMargin : UIViewAutoresizingFlexibleRightMargin; - trailingCorners.autoresizingMask = (_vertical) ? UIViewAutoresizingFlexibleTopMargin : UIViewAutoresizingFlexibleLeftMargin; - - float x, y, cornersWidth, cornersHeight; - CGRect leadingRect, trailingRect; - float radius = leadingCorners.cornerRadius; - if (_vertical) { // left/right split - cornersWidth = (radius * 2.0) + _splitWidth; - cornersHeight = radius; - x = ((shouldShowMaster) ? ((masterFirst) ? _splitPosition : width - (_splitPosition + _splitWidth)) : (0 - _splitWidth)) - radius; - y = 0; - leadingRect = CGRectMake(x, y, cornersWidth, cornersHeight); // top corners - trailingRect = CGRectMake(x, (height - cornersHeight), cornersWidth, cornersHeight); // bottom corners - - } else { // top/bottom split - x = 0; - y = ((shouldShowMaster) ? ((masterFirst) ? _splitPosition : height - (_splitPosition + _splitWidth)) : (0 - _splitWidth)) - radius; - cornersWidth = radius; - cornersHeight = (radius * 2.0) + _splitWidth; - leadingRect = CGRectMake(x, y, cornersWidth, cornersHeight); // left corners - trailingRect = CGRectMake((width - cornersWidth), y, cornersWidth, cornersHeight); // right corners - } - - leadingCorners.frame = leadingRect; - trailingCorners.frame = trailingRect; - - // Ensure corners are visible and frontmost. - if (!leadingCorners.superview) { - [self.view insertSubview:leadingCorners aboveSubview:self.detailViewController.view]; - [self.view insertSubview:trailingCorners aboveSubview:self.detailViewController.view]; - } else { - [self.view bringSubviewToFront:leadingCorners]; - [self.view bringSubviewToFront:trailingCorners]; - } + if (_reconfigurePopup) { + [self reconfigureForMasterInPopover:![self shouldShowMasterForInterfaceOrientation:theOrientation]]; + } + + // Layout the master, detail and divider views appropriately, adding/removing subviews as needed. + // First obtain relevant geometry. + CGSize fullSize = [self splitViewSizeForOrientation:theOrientation]; + float width = fullSize.width; + float height = fullSize.height; + + if (NO) { // Just for debugging. + NSLog(@"Target orientation is %@, dimensions will be %.0f x %.0f", + [self nameOfInterfaceOrientation:theOrientation], width, height); + } + + // Layout the master, divider and detail views. + CGRect newFrame = CGRectMake(0, 0, width, height); + UIViewController *controller; + UIView *theView; + BOOL shouldShowMaster = [self shouldShowMasterForInterfaceOrientation:theOrientation]; + BOOL masterFirst = [self isMasterBeforeDetail]; + if ([self isVertical]) { + // Master on left, detail on right (or vice versa). + CGRect masterRect, dividerRect, detailRect; + if (masterFirst) { + if (!shouldShowMaster) { + // Move off-screen. + newFrame.origin.x -= (_splitPosition + _splitWidth); + } + + newFrame.size.width = _splitPosition; + masterRect = newFrame; + + newFrame.origin.x += newFrame.size.width; + newFrame.size.width = _splitWidth; + dividerRect = newFrame; + + newFrame.origin.x += newFrame.size.width; + newFrame.size.width = width - newFrame.origin.x; + detailRect = newFrame; + + } else { + if (!shouldShowMaster) { + // Move off-screen. + newFrame.size.width += (_splitPosition + _splitWidth); + } + + newFrame.size.width -= (_splitPosition + _splitWidth); + detailRect = newFrame; + + newFrame.origin.x += newFrame.size.width; + newFrame.size.width = _splitWidth; + dividerRect = newFrame; + + newFrame.origin.x += newFrame.size.width; + newFrame.size.width = _splitPosition; + masterRect = newFrame; + } + + // Position master. + controller = self.masterViewController; + if (controller && [controller isKindOfClass:[UIViewController class]]) { + theView = controller.view; + if (theView) { + theView.frame = masterRect; + if (!theView.superview) { + [controller viewWillAppear:NO]; + [self.view addSubview:theView]; + [controller viewDidAppear:NO]; + } + } + } + + // Position divider. + theView = _dividerView; + theView.frame = dividerRect; + if (!theView.superview) { + [self.view addSubview:theView]; + } + + // Position detail. + controller = self.detailViewController; + if (controller && [controller isKindOfClass:[UIViewController class]]) { + theView = controller.view; + if (theView) { + theView.frame = detailRect; + if (!theView.superview) { + [self.view insertSubview:theView aboveSubview:self.masterViewController.view]; + } else { + [self.view bringSubviewToFront:theView]; + } + } + } + + } else { + // Master above, detail below (or vice versa). + CGRect masterRect, dividerRect, detailRect; + if (masterFirst) { + if (!shouldShowMaster) { + // Move off-screen. + newFrame.origin.y -= (_splitPosition + _splitWidth); + } + + newFrame.size.height = _splitPosition; + masterRect = newFrame; + + newFrame.origin.y += newFrame.size.height; + newFrame.size.height = _splitWidth; + dividerRect = newFrame; + + newFrame.origin.y += newFrame.size.height; + newFrame.size.height = height - newFrame.origin.y; + detailRect = newFrame; + + } else { + if (!shouldShowMaster) { + // Move off-screen. + newFrame.size.height += (_splitPosition + _splitWidth); + } + + newFrame.size.height -= (_splitPosition + _splitWidth); + detailRect = newFrame; + + newFrame.origin.y += newFrame.size.height; + newFrame.size.height = _splitWidth; + dividerRect = newFrame; + + newFrame.origin.y += newFrame.size.height; + newFrame.size.height = _splitPosition; + masterRect = newFrame; + } + + // Position master. + controller = self.masterViewController; + if (controller && [controller isKindOfClass:[UIViewController class]]) { + theView = controller.view; + if (theView) { + theView.frame = masterRect; + if (!theView.superview) { + [controller viewWillAppear:NO]; + [self.view addSubview:theView]; + [controller viewDidAppear:NO]; + } + } + } + + // Position divider. + theView = _dividerView; + theView.frame = dividerRect; + if (!theView.superview) { + [self.view addSubview:theView]; + } + + // Position detail. + controller = self.detailViewController; + if (controller && [controller isKindOfClass:[UIViewController class]]) { + theView = controller.view; + if (theView) { + theView.frame = detailRect; + if (!theView.superview) { + [self.view insertSubview:theView aboveSubview:self.masterViewController.view]; + } else { + [self.view bringSubviewToFront:theView]; + } + } + } + } + + // Create corner views if necessary. + MGSplitCornersView *leadingCorners = nil; // top/left of screen in vertical/horizontal split. + MGSplitCornersView *trailingCorners = nil; // bottom/right of screen in vertical/horizontal split. + if (!_cornerViews) { + CGRect cornerRect = CGRectMake(0, 0, 10, 10); // arbitrary, will be resized below. + leadingCorners = [[MGSplitCornersView alloc] initWithFrame:cornerRect]; + leadingCorners.splitViewController = self; + leadingCorners.cornerBackgroundColor = MG_DEFAULT_CORNER_COLOR; + leadingCorners.cornerRadius = NSFoundationVersionNumber >= NSFoundationVersionNumber_iOS_7_0 ? 0 : MG_DEFAULT_CORNER_RADIUS; + trailingCorners = [[MGSplitCornersView alloc] initWithFrame:cornerRect]; + trailingCorners.splitViewController = self; + trailingCorners.cornerBackgroundColor = MG_DEFAULT_CORNER_COLOR; + trailingCorners.cornerRadius = NSFoundationVersionNumber >= NSFoundationVersionNumber_iOS_7_0 ? 0 : MG_DEFAULT_CORNER_RADIUS; + _cornerViews = [[NSArray alloc] initWithObjects:leadingCorners, trailingCorners, nil]; + + } else if ([_cornerViews count] == 2) { + leadingCorners = [_cornerViews objectAtIndex:0]; + trailingCorners = [_cornerViews objectAtIndex:1]; + } + + // Configure and layout the corner-views. + leadingCorners.cornersPosition = (_vertical) ? MGCornersPositionLeadingVertical : MGCornersPositionLeadingHorizontal; + trailingCorners.cornersPosition = (_vertical) ? MGCornersPositionTrailingVertical : MGCornersPositionTrailingHorizontal; + leadingCorners.autoresizingMask = (_vertical) ? UIViewAutoresizingFlexibleBottomMargin : UIViewAutoresizingFlexibleRightMargin; + trailingCorners.autoresizingMask = (_vertical) ? UIViewAutoresizingFlexibleTopMargin : UIViewAutoresizingFlexibleLeftMargin; + + float x, y, cornersWidth, cornersHeight; + CGRect leadingRect, trailingRect; + float radius = leadingCorners.cornerRadius; + if (_vertical) { // left/right split + cornersWidth = (radius * 2.f) + _splitWidth; + cornersHeight = radius; + x = ((shouldShowMaster) ? ((masterFirst) ? _splitPosition : width - (_splitPosition + _splitWidth)) : (0 - _splitWidth)) - radius; + y = 0; + leadingRect = CGRectMake(x, y, cornersWidth, cornersHeight); // top corners + trailingRect = CGRectMake(x, (height - cornersHeight), cornersWidth, cornersHeight); // bottom corners + + } else { // top/bottom split + x = 0; + y = ((shouldShowMaster) ? ((masterFirst) ? _splitPosition : height - (_splitPosition + _splitWidth)) : (0 - _splitWidth)) - radius; + cornersWidth = radius; + cornersHeight = (radius * 2.f) + _splitWidth; + leadingRect = CGRectMake(x, y, cornersWidth, cornersHeight); // left corners + trailingRect = CGRectMake((width - cornersWidth), y, cornersWidth, cornersHeight); // right corners + } + + leadingCorners.frame = leadingRect; + trailingCorners.frame = trailingRect; + + // Ensure corners are visible and frontmost. + if (!leadingCorners.superview) { + [self.view insertSubview:leadingCorners aboveSubview:self.detailViewController.view]; + [self.view insertSubview:trailingCorners aboveSubview:self.detailViewController.view]; + } else { + [self.view bringSubviewToFront:leadingCorners]; + [self.view bringSubviewToFront:trailingCorners]; + } } - (void)layoutSubviewsWithAnimation:(BOOL)animate { - [self layoutSubviewsForInterfaceOrientation:self.interfaceOrientation withAnimation:animate]; + [self layoutSubviewsForInterfaceOrientation:self.interfaceOrientation withAnimation:animate]; } - (void)layoutSubviews { - [self layoutSubviewsForInterfaceOrientation:self.interfaceOrientation withAnimation:YES]; + [self layoutSubviewsForInterfaceOrientation:self.interfaceOrientation withAnimation:YES]; } - (void)viewWillAppear:(BOOL)animated { - [super viewWillAppear:animated]; - - if ([self isShowingMaster]) { - [self.masterViewController viewWillAppear:animated]; - } - [self.detailViewController viewWillAppear:animated]; - - _reconfigurePopup = YES; - [self layoutSubviews]; + [super viewWillAppear:animated]; + + if ([self isShowingMaster]) { + [self.masterViewController viewWillAppear:animated]; + } + [self.detailViewController viewWillAppear:animated]; + + _reconfigurePopup = YES; } - (void)viewDidAppear:(BOOL)animated { - [super viewDidAppear:animated]; - - if ([self isShowingMaster]) { - [self.masterViewController viewDidAppear:animated]; - } - [self.detailViewController viewDidAppear:animated]; + [super viewDidAppear:animated]; + + if ([self isShowingMaster]) { + [self.masterViewController viewDidAppear:animated]; + } + [self.detailViewController viewDidAppear:animated]; + [self layoutSubviews]; } - (void)viewWillDisappear:(BOOL)animated { - [super viewWillDisappear:animated]; - - if ([self isShowingMaster]) { - [self.masterViewController viewWillDisappear:animated]; - } - [self.detailViewController viewWillDisappear:animated]; + [super viewWillDisappear:animated]; + + if ([self isShowingMaster]) { + [self.masterViewController viewWillDisappear:animated]; + } + [self.detailViewController viewWillDisappear:animated]; } - (void)viewDidDisappear:(BOOL)animated { - [super viewDidDisappear:animated]; - - if ([self isShowingMaster]) { - [self.masterViewController viewDidDisappear:animated]; - } - [self.detailViewController viewDidDisappear:animated]; + [super viewDidDisappear:animated]; + + if ([self isShowingMaster]) { + [self.masterViewController viewDidDisappear:animated]; + } + [self.detailViewController viewDidDisappear:animated]; } @@ -545,73 +534,73 @@ - (void)reconfigureForMasterInPopover:(BOOL)inPopover { - _reconfigurePopup = NO; - - if ((inPopover && _hiddenPopoverController) || (!inPopover && !_hiddenPopoverController) || !self.masterViewController) { - // Nothing to do. - return; - } - - if (inPopover && !_hiddenPopoverController && !_barButtonItem) { - // Create and configure popover for our masterViewController. - [_hiddenPopoverController release]; - _hiddenPopoverController = nil; - [self.masterViewController viewWillDisappear:NO]; - _hiddenPopoverController = [[UIPopoverController alloc] initWithContentViewController:self.masterViewController]; - [self.masterViewController viewDidDisappear:NO]; - - // Create and configure _barButtonItem. - _barButtonItem = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Master", nil) - style:UIBarButtonItemStyleBordered - target:self - action:@selector(showMasterPopover:)]; - - // Inform delegate of this state of affairs. - if (_delegate && [_delegate respondsToSelector:@selector(splitViewController:willHideViewController:withBarButtonItem:forPopoverController:)]) { - [(NSObject *)_delegate splitViewController:self - willHideViewController:self.masterViewController - withBarButtonItem:_barButtonItem - forPopoverController:_hiddenPopoverController]; + _reconfigurePopup = NO; + + if ((inPopover && _hiddenPopoverController) || (!inPopover && !_hiddenPopoverController) || !self.masterViewController) { + // Nothing to do. + return; + } + + if (inPopover && !_hiddenPopoverController && !_barButtonItem) { + // Create and configure popover for our masterViewController. + _hiddenPopoverController = nil; + [self.masterViewController viewWillDisappear:NO]; + _hiddenPopoverController = [[UIPopoverController alloc] initWithContentViewController:self.masterViewController]; + [self.masterViewController viewDidDisappear:NO]; + + // Create and configure _barButtonItem. + _barButtonItem = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Master", nil) + style:UIBarButtonItemStyleBordered + target:self + action:(self.togglesMasterPopover ? @selector(toggleMasterPopover:) : @selector(showMasterPopover:))]; + + // Inform delegate of this state of affairs. + if (_delegate && [_delegate respondsToSelector:@selector(splitViewController:willHideViewController:withBarButtonItem:forPopoverController:)]) { + [(NSObject *)_delegate splitViewController:self + willHideViewController:self.masterViewController + withBarButtonItem:_barButtonItem + forPopoverController:_hiddenPopoverController]; + } + + } else if (!inPopover && _hiddenPopoverController && _barButtonItem) { + // I know this looks strange, but it fixes a bizarre issue with UIPopoverController leaving masterViewController's views in disarray. + // It does also break stuff on iOS8, so we disable it. + if (NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_7_1) { + [_hiddenPopoverController presentPopoverFromRect:CGRectZero inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:NO]; } - } else if (!inPopover && _hiddenPopoverController && _barButtonItem) { - // I know this looks strange, but it fixes a bizarre issue with UIPopoverController leaving masterViewController's views in disarray. - [_hiddenPopoverController presentPopoverFromRect:CGRectZero inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:NO]; - - // Remove master from popover and destroy popover, if it exists. - [_hiddenPopoverController dismissPopoverAnimated:NO]; - [_hiddenPopoverController release]; - _hiddenPopoverController = nil; - - // Inform delegate that the _barButtonItem will become invalid. - if (_delegate && [_delegate respondsToSelector:@selector(splitViewController:willShowViewController:invalidatingBarButtonItem:)]) { - [(NSObject *)_delegate splitViewController:self - willShowViewController:self.masterViewController - invalidatingBarButtonItem:_barButtonItem]; - } - - // Destroy _barButtonItem. - [_barButtonItem release]; - _barButtonItem = nil; - - // Move master view. - UIView *masterView = self.masterViewController.view; - if (masterView && masterView.superview != self.view) { - [masterView removeFromSuperview]; - } - } + // Remove master from popover and destroy popover, if it exists. + [_hiddenPopoverController dismissPopoverAnimated:NO]; + _hiddenPopoverController = nil; + + // Inform delegate that the _barButtonItem will become invalid. + if (_delegate && [_delegate respondsToSelector:@selector(splitViewController:willShowViewController:invalidatingBarButtonItem:)]) { + [(NSObject *)_delegate splitViewController:self + willShowViewController:self.masterViewController + invalidatingBarButtonItem:_barButtonItem]; + } + + // Destroy _barButtonItem. + _barButtonItem = nil; + + // Move master view. + UIView *masterView = self.masterViewController.view; + if (masterView && masterView.superview != self.view) { + [masterView removeFromSuperview]; + } + } } - (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController { - [self reconfigureForMasterInPopover:NO]; + [self reconfigureForMasterInPopover:NO]; } - (void)notePopoverDismissed { - [self popoverControllerDidDismissPopover:_hiddenPopoverController]; + [self popoverControllerDidDismissPopover:_hiddenPopoverController]; } @@ -621,14 +610,14 @@ - (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context { - if (([animationID isEqualToString:MG_ANIMATION_CHANGE_SPLIT_ORIENTATION] || - [animationID isEqualToString:MG_ANIMATION_CHANGE_SUBVIEWS_ORDER]) - && _cornerViews) { - for (UIView *corner in _cornerViews) { - corner.hidden = NO; - } - _dividerView.hidden = NO; - } + if (([animationID isEqualToString:MG_ANIMATION_CHANGE_SPLIT_ORIENTATION] || + [animationID isEqualToString:MG_ANIMATION_CHANGE_SUBVIEWS_ORDER]) + && _cornerViews) { + for (UIView *corner in _cornerViews) { + corner.hidden = NO; + } + _dividerView.hidden = NO; + } } @@ -638,83 +627,131 @@ - (IBAction)toggleSplitOrientation:(id)sender { - BOOL showingMaster = [self isShowingMaster]; - if (showingMaster) { - if (_cornerViews) { - for (UIView *corner in _cornerViews) { - corner.hidden = YES; - } - _dividerView.hidden = YES; - } - [UIView beginAnimations:MG_ANIMATION_CHANGE_SPLIT_ORIENTATION context:nil]; - [UIView setAnimationDelegate:self]; - [UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)]; - } - self.vertical = (!self.vertical); - if (showingMaster) { - [UIView commitAnimations]; - } + BOOL showingMaster = [self isShowingMaster]; + if (showingMaster) { + if (_cornerViews) { + for (UIView *corner in _cornerViews) { + corner.hidden = YES; + } + _dividerView.hidden = YES; + } + [UIView beginAnimations:MG_ANIMATION_CHANGE_SPLIT_ORIENTATION context:nil]; + [UIView setAnimationDelegate:self]; + [UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)]; + } + self.vertical = (!self.vertical); + if (showingMaster) { + [UIView commitAnimations]; + } } - (IBAction)toggleMasterBeforeDetail:(id)sender { - BOOL showingMaster = [self isShowingMaster]; - if (showingMaster) { - if (_cornerViews) { - for (UIView *corner in _cornerViews) { - corner.hidden = YES; - } - _dividerView.hidden = YES; - } - [UIView beginAnimations:MG_ANIMATION_CHANGE_SUBVIEWS_ORDER context:nil]; - [UIView setAnimationDelegate:self]; - [UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)]; - } - self.masterBeforeDetail = (!self.masterBeforeDetail); - if (showingMaster) { - [UIView commitAnimations]; - } + BOOL showingMaster = [self isShowingMaster]; + if (showingMaster) { + if (_cornerViews) { + for (UIView *corner in _cornerViews) { + corner.hidden = YES; + } + _dividerView.hidden = YES; + } + [UIView beginAnimations:MG_ANIMATION_CHANGE_SUBVIEWS_ORDER context:nil]; + [UIView setAnimationDelegate:self]; + [UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)]; + } + self.masterBeforeDetail = (!self.masterBeforeDetail); + if (showingMaster) { + [UIView commitAnimations]; + } } - (IBAction)toggleMasterView:(id)sender { - if (_hiddenPopoverController && _hiddenPopoverController.popoverVisible) { - [_hiddenPopoverController dismissPopoverAnimated:NO]; - } - - if (![self isShowingMaster]) { - // We're about to show the master view. Ensure it's in place off-screen to be animated in. - _reconfigurePopup = YES; - [self reconfigureForMasterInPopover:NO]; - [self layoutSubviews]; - } - - // This action functions on the current primary orientation; it is independent of the other primary orientation. - [UIView beginAnimations:@"toggleMaster" context:nil]; - if (self.isLandscape) { - self.showsMasterInLandscape = !_showsMasterInLandscape; - } else { - self.showsMasterInPortrait = !_showsMasterInPortrait; - } - [UIView commitAnimations]; + if (_hiddenPopoverController && _hiddenPopoverController.popoverVisible) { + [_hiddenPopoverController dismissPopoverAnimated:NO]; + } + + if (![self isShowingMaster]) { + // We're about to show the master view. Ensure it's in place off-screen to be animated in. + _reconfigurePopup = YES; + [self reconfigureForMasterInPopover:NO]; + [self layoutSubviews]; + } + + // This action functions on the current primary orientation; it is independent of the other primary orientation. + [UIView beginAnimations:@"toggleMaster" context:nil]; + if (self.isLandscape) { + self.showsMasterInLandscape = !_showsMasterInLandscape; + } else { + self.showsMasterInPortrait = !_showsMasterInPortrait; + } + [UIView commitAnimations]; } -- (IBAction)showMasterPopover:(id) sender +- (void) setTogglesMasterPopover:(BOOL)flag { + + togglesMasterPopover = flag; + + if (!_barButtonItem) + return; + + _barButtonItem.action = flag ? @selector(toggleMasterPopover:) : @selector(showMasterPopover:); + +} + +- (IBAction)toggleMasterPopover:(id)sender { - if (_hiddenPopoverController && !(_hiddenPopoverController.popoverVisible)) { - // Inform delegate. - if (_delegate && [_delegate respondsToSelector:@selector(splitViewController:popoverController:willPresentViewController:)]) { - [(NSObject *)_delegate splitViewController:self - popoverController:_hiddenPopoverController - willPresentViewController:self.masterViewController]; - } + + if (!_hiddenPopoverController) + return; + + if (_hiddenPopoverController.popoverVisible) { + + [self hideMasterPopover:sender]; + + } else { + + [self showMasterPopover:sender]; + + } + +} + - // Show popover. - [_hiddenPopoverController presentPopoverFromBarButtonItem:_barButtonItem permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES]; - } +- (IBAction)showMasterPopover:(id)sender +{ + if (_hiddenPopoverController && !(_hiddenPopoverController.popoverVisible)) { + // Inform delegate. + if (_delegate && [_delegate respondsToSelector:@selector(splitViewController:popoverController:willPresentViewController:)]) { + [(NSObject *)_delegate splitViewController:self + popoverController:_hiddenPopoverController + willPresentViewController:self.masterViewController]; + } + + // Show popover. + [_hiddenPopoverController presentPopoverFromBarButtonItem:(sender ? sender : _barButtonItem) permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES]; + } +} + + +- (IBAction)hideMasterPopover:(id)sender +{ + + if(_hiddenPopoverController && _hiddenPopoverController.popoverVisible) { + + if (_delegate && [_delegate respondsToSelector:@selector(splitViewController:popoverController:willDismissViewController:)]) { + + [(NSObject *)_delegate splitViewController:self popoverController:_hiddenPopoverController willDismissViewController:self.masterViewController]; + + } + + [_hiddenPopoverController dismissPopoverAnimated:YES]; + + } + } @@ -724,395 +761,393 @@ - (id)delegate { - return _delegate; + return _delegate; } - (void)setDelegate:(id )newDelegate { - if (newDelegate != _delegate && - (!newDelegate || [(NSObject *)newDelegate conformsToProtocol:@protocol(MGSplitViewControllerDelegate)])) { - _delegate = newDelegate; - } + if (newDelegate != _delegate && + (!newDelegate || [(NSObject *)newDelegate conformsToProtocol:@protocol(MGSplitViewControllerDelegate)])) { + _delegate = newDelegate; + } } - (BOOL)showsMasterInPortrait { - return _showsMasterInPortrait; + return _showsMasterInPortrait; } - (void)setShowsMasterInPortrait:(BOOL)flag { - if (flag != _showsMasterInPortrait) { - _showsMasterInPortrait = flag; - - if (![self isLandscape]) { // i.e. if this will cause a visual change. - if (_hiddenPopoverController && _hiddenPopoverController.popoverVisible) { - [_hiddenPopoverController dismissPopoverAnimated:NO]; - } - - // Rearrange views. - _reconfigurePopup = YES; - [self layoutSubviews]; - } - } + if (flag != _showsMasterInPortrait) { + _showsMasterInPortrait = flag; + + if (![self isLandscape]) { // i.e. if this will cause a visual change. + if (_hiddenPopoverController && _hiddenPopoverController.popoverVisible) { + [_hiddenPopoverController dismissPopoverAnimated:NO]; + } + + // Rearrange views. + _reconfigurePopup = YES; + [self layoutSubviews]; + } + } } - (BOOL)showsMasterInLandscape { - return _showsMasterInLandscape; + return _showsMasterInLandscape; } - (void)setShowsMasterInLandscape:(BOOL)flag { - if (flag != _showsMasterInLandscape) { - _showsMasterInLandscape = flag; - - if ([self isLandscape]) { // i.e. if this will cause a visual change. - if (_hiddenPopoverController && _hiddenPopoverController.popoverVisible) { - [_hiddenPopoverController dismissPopoverAnimated:NO]; - } - - // Rearrange views. - _reconfigurePopup = YES; - [self layoutSubviews]; - } - } + if (flag != _showsMasterInLandscape) { + _showsMasterInLandscape = flag; + + if ([self isLandscape]) { // i.e. if this will cause a visual change. + if (_hiddenPopoverController && _hiddenPopoverController.popoverVisible) { + [_hiddenPopoverController dismissPopoverAnimated:NO]; + } + + // Rearrange views. + _reconfigurePopup = YES; + [self layoutSubviews]; + } + } } - (BOOL)isVertical { - return _vertical; + return _vertical; } - (void)setVertical:(BOOL)flag { - if (flag != _vertical) { - if (_hiddenPopoverController && _hiddenPopoverController.popoverVisible) { - [_hiddenPopoverController dismissPopoverAnimated:NO]; - } - - _vertical = flag; - - // Inform delegate. - if (_delegate && [_delegate respondsToSelector:@selector(splitViewController:willChangeSplitOrientationToVertical:)]) { - [_delegate splitViewController:self willChangeSplitOrientationToVertical:_vertical]; - } - - [self layoutSubviews]; - } + if (flag != _vertical) { + if (_hiddenPopoverController && _hiddenPopoverController.popoverVisible) { + [_hiddenPopoverController dismissPopoverAnimated:NO]; + } + + _vertical = flag; + + // Inform delegate. + if (_delegate && [_delegate respondsToSelector:@selector(splitViewController:willChangeSplitOrientationToVertical:)]) { + [_delegate splitViewController:self willChangeSplitOrientationToVertical:_vertical]; + } + + [self layoutSubviews]; + } } - (BOOL)isMasterBeforeDetail { - return _masterBeforeDetail; + return _masterBeforeDetail; } - (void)setMasterBeforeDetail:(BOOL)flag { - if (flag != _masterBeforeDetail) { - if (_hiddenPopoverController && _hiddenPopoverController.popoverVisible) { - [_hiddenPopoverController dismissPopoverAnimated:NO]; - } - - _masterBeforeDetail = flag; - - if ([self isShowingMaster]) { - [self layoutSubviews]; - } - } + if (flag != _masterBeforeDetail) { + if (_hiddenPopoverController && _hiddenPopoverController.popoverVisible) { + [_hiddenPopoverController dismissPopoverAnimated:NO]; + } + + _masterBeforeDetail = flag; + + if ([self isShowingMaster]) { + [self layoutSubviews]; + } + } } - (float)splitPosition { - return _splitPosition; + return _splitPosition; } - (void)setSplitPosition:(float)posn { - // Check to see if delegate wishes to constrain the position. - float newPosn = posn; - BOOL constrained = NO; - CGSize fullSize = [self splitViewSizeForOrientation:self.interfaceOrientation]; - if (_delegate && [_delegate respondsToSelector:@selector(splitViewController:constrainSplitPosition:splitViewSize:)]) { - newPosn = [_delegate splitViewController:self constrainSplitPosition:newPosn splitViewSize:fullSize]; - constrained = YES; // implicitly trust delegate's response. - - } else { - // Apply default constraints if delegate doesn't wish to participate. - float minPos = MG_MIN_VIEW_WIDTH; - float maxPos = ((_vertical) ? fullSize.width : fullSize.height) - (MG_MIN_VIEW_WIDTH + _splitWidth); - constrained = (newPosn != _splitPosition && newPosn >= minPos && newPosn <= maxPos); - } - - if (constrained) { - if (_hiddenPopoverController && _hiddenPopoverController.popoverVisible) { - [_hiddenPopoverController dismissPopoverAnimated:NO]; - } - - _splitPosition = newPosn; - - // Inform delegate. - if (_delegate && [_delegate respondsToSelector:@selector(splitViewController:willMoveSplitToPosition:)]) { - [_delegate splitViewController:self willMoveSplitToPosition:_splitPosition]; - } - - if ([self isShowingMaster]) { - [self layoutSubviews]; - } - } + // Check to see if delegate wishes to constrain the position. + float newPosn = posn; + BOOL constrained = NO; + CGSize fullSize = [self splitViewSizeForOrientation:self.interfaceOrientation]; + if (_delegate && [_delegate respondsToSelector:@selector(splitViewController:constrainSplitPosition:splitViewSize:)]) { + newPosn = [_delegate splitViewController:self constrainSplitPosition:newPosn splitViewSize:fullSize]; + constrained = YES; // implicitly trust delegate's response. + + } else { + // Apply default constraints if delegate doesn't wish to participate. + float minPos = MG_MIN_VIEW_WIDTH; + float maxPos = (float) (((_vertical) ? fullSize.width : fullSize.height) - (MG_MIN_VIEW_WIDTH + _splitWidth)); + constrained = (newPosn != _splitPosition && newPosn >= minPos && newPosn <= maxPos); + } + + if (constrained) { + if (_hiddenPopoverController && _hiddenPopoverController.popoverVisible) { + [_hiddenPopoverController dismissPopoverAnimated:NO]; + } + + _splitPosition = newPosn; + + // Inform delegate. + if (_delegate && [_delegate respondsToSelector:@selector(splitViewController:willMoveSplitToPosition:)]) { + [_delegate splitViewController:self willMoveSplitToPosition:_splitPosition]; + } + + if ([self isShowingMaster]) { + [self layoutSubviews]; + } + } } - (void)setSplitPosition:(float)posn animated:(BOOL)animate { - BOOL shouldAnimate = (animate && [self isShowingMaster]); - if (shouldAnimate) { - [UIView beginAnimations:@"SplitPosition" context:nil]; - } - [self setSplitPosition:posn]; - if (shouldAnimate) { - [UIView commitAnimations]; - } + BOOL shouldAnimate = (animate && [self isShowingMaster]); + if (shouldAnimate) { + [UIView beginAnimations:@"SplitPosition" context:nil]; + } + [self setSplitPosition:posn]; + if (shouldAnimate) { + [UIView commitAnimations]; + } } - (float)splitWidth { - return _splitWidth; + return _splitWidth; } - (void)setSplitWidth:(float)width { - if (width != _splitWidth && width >= 0) { - _splitWidth = width; - if ([self isShowingMaster]) { - [self layoutSubviews]; - } - } + if (width != _splitWidth && width >= 0) { + _splitWidth = width; + if ([self isShowingMaster]) { + [self layoutSubviews]; + } + } } - (NSArray *)viewControllers { - return [[_viewControllers copy] autorelease]; + return [_viewControllers copy]; } - (void)setViewControllers:(NSArray *)controllers { - if (controllers != _viewControllers) { - for (UIViewController *controller in _viewControllers) { - if ([controller isKindOfClass:[UIViewController class]]) { - [controller.view removeFromSuperview]; - } - } - [_viewControllers release]; - _viewControllers = [[NSMutableArray alloc] initWithCapacity:2]; - if (controllers && [controllers count] >= 2) { - self.masterViewController = [controllers objectAtIndex:0]; - self.detailViewController = [controllers objectAtIndex:1]; - } else { - NSLog(@"Error: %@ requires 2 view-controllers. (%@)", NSStringFromClass([self class]), NSStringFromSelector(_cmd)); - } - - [self layoutSubviews]; - } + if (controllers != _viewControllers) { + for (UIViewController *controller in _viewControllers) { + if ([controller isKindOfClass:[UIViewController class]]) { + [controller.view removeFromSuperview]; + } + } + _viewControllers = [[NSMutableArray alloc] initWithCapacity:2]; + if (controllers && [controllers count] >= 2) { + self.masterViewController = [controllers objectAtIndex:0]; + self.detailViewController = [controllers objectAtIndex:1]; + } else { + NSLog(@"Error: %@ requires 2 view-controllers. (%@)", NSStringFromClass([self class]), NSStringFromSelector(_cmd)); + } + + [self layoutSubviews]; + } } - (UIViewController *)masterViewController { - if (_viewControllers && [_viewControllers count] > 0) { - NSObject *controller = [_viewControllers objectAtIndex:0]; - if ([controller isKindOfClass:[UIViewController class]]) { - return [[controller retain] autorelease]; - } - } - - return nil; + if (_viewControllers && [_viewControllers count] > 0) { + UIViewController *controller = (UIViewController *)[_viewControllers objectAtIndex:0]; + if ([controller isKindOfClass:[UIViewController class]]) { + return controller; + } + } + + return nil; } - (void)setMasterViewController:(UIViewController *)master { - if (!_viewControllers) { - _viewControllers = [[NSMutableArray alloc] initWithCapacity:2]; - } - - NSObject *newMaster = master; - if (!newMaster) { - newMaster = [NSNull null]; - } - - BOOL changed = YES; - if ([_viewControllers count] > 0) { - if ([_viewControllers objectAtIndex:0] == newMaster) { - changed = NO; - } else { - [_viewControllers replaceObjectAtIndex:0 withObject:newMaster]; - } - - } else { - [_viewControllers addObject:newMaster]; - } - - if (changed) { - [self layoutSubviews]; - } + if (!_viewControllers) { + _viewControllers = [[NSMutableArray alloc] initWithCapacity:2]; + } + + NSObject *newMaster = master; + if (!newMaster) { + newMaster = [NSNull null]; + } + + BOOL changed = YES; + if ([_viewControllers count] > 0) { + if ([_viewControllers objectAtIndex:0] == newMaster) { + changed = NO; + } else { + [_viewControllers replaceObjectAtIndex:0 withObject:newMaster]; + } + + } else { + [_viewControllers addObject:newMaster]; + } + + if (changed) { + [self layoutSubviews]; + } } - (UIViewController *)detailViewController { - if (_viewControllers && [_viewControllers count] > 1) { - NSObject *controller = [_viewControllers objectAtIndex:1]; - if ([controller isKindOfClass:[UIViewController class]]) { - return [[controller retain] autorelease]; - } - } - - return nil; + if (_viewControllers && [_viewControllers count] > 1) { + UIViewController *controller = (UIViewController *)[_viewControllers objectAtIndex:1]; + if ([controller isKindOfClass:[UIViewController class]]) { + return controller; + } + } + + return nil; } - (void)setDetailViewController:(UIViewController *)detail { - if (!_viewControllers) { - _viewControllers = [[NSMutableArray alloc] initWithCapacity:2]; - [_viewControllers addObject:[NSNull null]]; - } - - BOOL changed = YES; - if ([_viewControllers count] > 1) { - if ([_viewControllers objectAtIndex:1] == detail) { - changed = NO; - } else { - [_viewControllers replaceObjectAtIndex:1 withObject:detail]; - } - - } else { - [_viewControllers addObject:detail]; - } - - if (changed) { - [self layoutSubviews]; - } + if (!_viewControllers) { + _viewControllers = [[NSMutableArray alloc] initWithCapacity:2]; + [_viewControllers addObject:[NSNull null]]; + } + + BOOL changed = YES; + if ([_viewControllers count] > 1) { + if ([_viewControllers objectAtIndex:1] == detail) { + changed = NO; + } else { + [_viewControllers replaceObjectAtIndex:1 withObject:detail]; + } + + } else { + [_viewControllers addObject:detail]; + } + + if (changed) { + [self layoutSubviews]; + } } - (MGSplitDividerView *)dividerView { - return [[_dividerView retain] autorelease]; + return _dividerView; } - (void)setDividerView:(MGSplitDividerView *)divider { - if (divider != _dividerView) { - [_dividerView removeFromSuperview]; - [_dividerView release]; - _dividerView = [divider retain]; - _dividerView.splitViewController = self; - _dividerView.backgroundColor = MG_DEFAULT_CORNER_COLOR; - if ([self isShowingMaster]) { - [self layoutSubviews]; - } - } + if (divider != _dividerView) { + [_dividerView removeFromSuperview]; + _dividerView = divider; + _dividerView.splitViewController = self; + _dividerView.backgroundColor = MG_DEFAULT_CORNER_COLOR; + if ([self isShowingMaster]) { + [self layoutSubviews]; + } + } } - (BOOL)allowsDraggingDivider { - if (_dividerView) { - return _dividerView.allowsDragging; - } - - return NO; + if (_dividerView) { + return _dividerView.allowsDragging; + } + + return NO; } - (void)setAllowsDraggingDivider:(BOOL)flag { - if (self.allowsDraggingDivider != flag && _dividerView) { - _dividerView.allowsDragging = flag; - } + if (self.allowsDraggingDivider != flag && _dividerView) { + _dividerView.allowsDragging = flag; + } } - (MGSplitViewDividerStyle)dividerStyle { - return _dividerStyle; + return _dividerStyle; } - (void)setDividerStyle:(MGSplitViewDividerStyle)newStyle { - if (_hiddenPopoverController && _hiddenPopoverController.popoverVisible) { - [_hiddenPopoverController dismissPopoverAnimated:NO]; - } - - // We don't check to see if newStyle equals _dividerStyle, because it's a meta-setting. - // Aspects could have been changed since it was set. - _dividerStyle = newStyle; - - // Reconfigure general appearance and behaviour. - float cornerRadius; - if (_dividerStyle == MGSplitViewDividerStyleThin) { - cornerRadius = MG_DEFAULT_CORNER_RADIUS; - _splitWidth = MG_DEFAULT_SPLIT_WIDTH; - self.allowsDraggingDivider = NO; - - } else if (_dividerStyle == MGSplitViewDividerStylePaneSplitter) { - cornerRadius = MG_PANESPLITTER_CORNER_RADIUS; - _splitWidth = MG_PANESPLITTER_SPLIT_WIDTH; - self.allowsDraggingDivider = YES; - } - - // Update divider and corners. - [_dividerView setNeedsDisplay]; - if (_cornerViews) { - for (MGSplitCornersView *corner in _cornerViews) { - corner.cornerRadius = cornerRadius; - } - } - - // Layout all views. - [self layoutSubviews]; + if (_hiddenPopoverController && _hiddenPopoverController.popoverVisible) { + [_hiddenPopoverController dismissPopoverAnimated:NO]; + } + + // We don't check to see if newStyle equals _dividerStyle, because it's a meta-setting. + // Aspects could have been changed since it was set. + _dividerStyle = newStyle; + + // Reconfigure general appearance and behaviour. + float cornerRadius = 0.0f; + if (_dividerStyle == MGSplitViewDividerStyleThin) { + cornerRadius = NSFoundationVersionNumber >= NSFoundationVersionNumber_iOS_7_0 ? 0 : MG_DEFAULT_CORNER_RADIUS; + _splitWidth = MG_DEFAULT_SPLIT_WIDTH; + self.allowsDraggingDivider = NO; + + } else if (_dividerStyle == MGSplitViewDividerStylePaneSplitter) { + cornerRadius = MG_PANESPLITTER_CORNER_RADIUS; + _splitWidth = MG_PANESPLITTER_SPLIT_WIDTH; + self.allowsDraggingDivider = YES; + } + + // Update divider and corners. + [_dividerView setNeedsDisplay]; + if (_cornerViews) { + for (MGSplitCornersView *corner in _cornerViews) { + corner.cornerRadius = cornerRadius; + } + } + + // Layout all views. + [self layoutSubviews]; } - (void)setDividerStyle:(MGSplitViewDividerStyle)newStyle animated:(BOOL)animate { - BOOL shouldAnimate = (animate && [self isShowingMaster]); - if (shouldAnimate) { - [UIView beginAnimations:@"DividerStyle" context:nil]; - } - [self setDividerStyle:newStyle]; - if (shouldAnimate) { - [UIView commitAnimations]; - } + BOOL shouldAnimate = (animate && [self isShowingMaster]); + if (shouldAnimate) { + [UIView beginAnimations:@"DividerStyle" context:nil]; + } + [self setDividerStyle:newStyle]; + if (shouldAnimate) { + [UIView commitAnimations]; + } } - (NSArray *)cornerViews { - if (_cornerViews) { - return [[_cornerViews retain] autorelease]; - } - - return nil; + if (_cornerViews) { + return _cornerViews; + } + + return nil; } @@ -1120,14 +1155,15 @@ @synthesize showsMasterInLandscape; @synthesize vertical; @synthesize delegate; -@synthesize viewControllers; +@synthesize viewControllers = _viewControllers; @synthesize masterViewController; @synthesize detailViewController; -@synthesize dividerView; +@synthesize dividerView = _dividerView; @synthesize splitPosition; @synthesize splitWidth; @synthesize allowsDraggingDivider; @synthesize dividerStyle; +@synthesize togglesMasterPopover; @end diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/MXAudioPlayerFadeOperation.m --- a/project_files/HedgewarsMobile/Classes/MXAudioPlayerFadeOperation.m Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/MXAudioPlayerFadeOperation.m Tue Nov 10 20:43:13 2015 +0100 @@ -79,7 +79,8 @@ } - (void)main { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + @autoreleasepool { + [NSThread sleepForTimeInterval:_delay]; if ([self.audioPlayer isKindOfClass:[AVAudioPlayer class]]) { [self beginFadeOperation]; @@ -88,7 +89,7 @@ ALog(@"AudioPlayerFadeOperation began with invalid AVAudioPlayer"); } - [pool release]; + } } - (void)beginFadeOperation { diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/MainMenuViewController-iPad.xib --- a/project_files/HedgewarsMobile/Classes/MainMenuViewController-iPad.xib Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/MainMenuViewController-iPad.xib Tue Nov 10 20:43:13 2015 +0100 @@ -1,719 +1,135 @@ - - - - 1056 - 10K549 - 823 - 1038.36 - 461.00 - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - 132 - - - YES - - - - YES - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - YES - - YES - - - YES - - - - YES - - IBFilesOwner - IBIPadFramework - - - IBFirstResponder - IBIPadFramework - - - - 294 - - YES - - - 274 - {1024, 768} - - NO - IBIPadFramework - - NSImage - background.png - - - - - 301 - {{383, 389}, {271, 244}} - - NO - IBIPadFramework - 0 - 0 - - Helvetica-Bold - 15 - 16 - - 215 - 0.0 - 0.0 - 0.0 - - 3 - MQA - - - 2 - MC45OTYwNzg0OTEyIDAuODAwMDAwMDcxNSAwLjAzOTIxNTY4NzY2AA - - - 3 - MC41AA - - - NSImage - localplayButton~ipad.png - - - - - 289 - {{986, 19}, {18, 19}} - - NO - YES - 0.31690141558647156 - 3 - IBIPadFramework - 0 - 0 - - 3 - YES - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - - 265 - {{940, 686}, {64, 64}} - - NO - 2 - IBIPadFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - NSImage - settingsButton.png - - - - - 268 - {{20, 686}, {64, 64}} - - NO - 4 - IBIPadFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - NSImage - savesButton.png - - - - - 301 - {{242, 43}, {540, 300}} - - NO - IBIPadFramework - - NSImage - title~ipad.png - - - - - 269 - {{565, 686}, {89, 37}} - - NO - 5 - IBIPadFramework - 0 - 0 - - 1 - Missions - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - - 269 - {{383, 686}, {89, 37}} - - NO - 6 - IBIPadFramework - 0 - 0 - - 1 - Simple - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - {1024, 768} - - - 1 - MCAwIDAAA - - - 3 - - IBIPadFramework - - - - - YES - - - view - - - - 3 - - - - switchViews: - - - 7 - - 47 - - - - switchViews: - - - 7 - - 48 - - - - switchViews: - - - 7 - - 54 - - - - switchViews: - - - 7 - - 89 - - - - switchViews: - - - 7 - - 92 - - - - switchViews: - - - 7 - - 94 - - - - - YES - - 0 - - - - - - 1 - - - YES - - - - - - - - - - - - - -1 - - - File's Owner - - - -2 - - - - - 39 - - - local - - - 45 - - - - - 52 - - - - - 37 - - - - - 88 - - - - - 90 - - - - - 91 - - - - - 93 - - - - - - - YES - - YES - -1.CustomClassName - -2.CustomClassName - 1.IBEditorWindowLastContentRect - 1.IBPluginDependency - 37.IBPluginDependency - 39.IBPluginDependency - 45.IBPluginDependency - 45.IBViewBoundsToFrameTransform - 52.IBPluginDependency - 52.IBViewBoundsToFrameTransform - 88.IBPluginDependency - 88.IBViewBoundsToFrameTransform - 90.IBPluginDependency - 90.IBViewBoundsToFrameTransform - 91.IBPluginDependency - 91.IBViewBoundsToFrameTransform - 93.IBPluginDependency - 93.IBViewBoundsToFrameTransform - - - YES - MainMenuViewController - UIResponder - {{89, 260}, {1024, 768}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABERsAAw6cAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABEaQAAxDsAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABBoAAAxDsAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDbQAAw6qAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABD6gAAxDRAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDuYAAxDRAAA - - - - - YES - - - YES - - - - - YES - - - YES - - - - 94 - - - - YES - - MainMenuViewController - UIViewController - - switchViews: - id - - - switchViews: - - switchViews: - id - - - - IBProjectSource - Classes/MainMenuViewController.h - - - - UIButton - - IBProjectSource - Classes/ExtraCategories.h - - - - - YES - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSError.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSFileManager.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueCoding.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueObserving.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyedArchiver.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSObject.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSRunLoop.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSThread.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURL.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURLConnection.h - - - - NSObject - - IBFrameworkSource - QuartzCore.framework/Headers/CAAnimation.h - - - - NSObject - - IBFrameworkSource - QuartzCore.framework/Headers/CALayer.h - - - - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UIAccessibility.h - - - - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UINibLoading.h - - - - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UIResponder.h - - - - UIButton - UIControl - - IBFrameworkSource - UIKit.framework/Headers/UIButton.h - - - - UIControl - UIView - - IBFrameworkSource - UIKit.framework/Headers/UIControl.h - - - - UIImageView - UIView - - IBFrameworkSource - UIKit.framework/Headers/UIImageView.h - - - - UIResponder - NSObject - - - - UISearchBar - UIView - - IBFrameworkSource - UIKit.framework/Headers/UISearchBar.h - - - - UISearchDisplayController - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UISearchDisplayController.h - - - - UIView - - IBFrameworkSource - UIKit.framework/Headers/UIPrintFormatter.h - - - - UIView - - IBFrameworkSource - UIKit.framework/Headers/UITextField.h - - - - UIView - UIResponder - - IBFrameworkSource - UIKit.framework/Headers/UIView.h - - - - UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UINavigationController.h - - - - UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UIPopoverController.h - - - - UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UISplitViewController.h - - - - UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UITabBarController.h - - - - UIViewController - UIResponder - - IBFrameworkSource - UIKit.framework/Headers/UIViewController.h - - - - - 0 - IBIPadFramework - - com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS - - - - com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 - - - YES - ../Hedgewars.xcodeproj - 3 - - YES - - YES - background.png - localplayButton~ipad.png - savesButton.png - settingsButton.png - title~ipad.png - - - YES - {1024, 768} - {263, 244} - {64, 64} - {64, 64} - {540, 300} - - - 132 - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/MainMenuViewController-iPhone.xib --- a/project_files/HedgewarsMobile/Classes/MainMenuViewController-iPhone.xib Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/MainMenuViewController-iPhone.xib Tue Nov 10 20:43:13 2015 +0100 @@ -1,734 +1,137 @@ - - - - 1056 - 10K549 - 823 - 1038.36 - 461.00 - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - 132 - - - YES - - - - YES - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - YES - - YES - - - YES - - - - YES - - IBFilesOwner - IBCocoaTouchFramework - - - IBFirstResponder - IBCocoaTouchFramework - - - - 293 - - YES - - - 274 - {480, 320} - - - 3 - MCAwAA - - 4 - NO - IBCocoaTouchFramework - - NSImage - background~iphone.png - - - - - 293 - {{105, 20}, {270, 150}} - - NO - NO - 4 - NO - IBCocoaTouchFramework - - NSImage - title~iphone.png - - - - - 289 - {{190, 200}, {100, 100}} - - - 1 - MCAwIDAgMAA - - NO - NO - IBCocoaTouchFramework - 0 - 0 - - Helvetica-Bold - 15 - 16 - - - 3 - MQA - - - 1 - MC4xOTYwNzg0MyAwLjMwOTgwMzkzIDAuNTIxNTY4NjYAA - - - 3 - MC41AA - - - NSImage - localplayButton~iphone.png - - - - - 269 - {{396, 236}, {64, 64}} - - NO - NO - 2 - IBCocoaTouchFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MyAwLjMwOTgwMzkzIDAuNTIxNTY4NjYAA - - - - NSImage - settingsButton.png - - - - - 269 - {{20, 236}, {64, 64}} - - NO - NO - 4 - IBCocoaTouchFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MyAwLjMwOTgwMzkzIDAuNTIxNTY4NjYAA - - - - NSImage - savesButton.png - - - - - 292 - {{20, 19}, {18, 19}} - - NO - 0.5 - 3 - IBCocoaTouchFramework - 0 - 0 - - 3 - YES - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - - 292 - {{439, 13}, {29, 31}} - - NO - 5 - IBCocoaTouchFramework - 0 - 0 - - 2 - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - - 292 - {{439, 68}, {29, 31}} - - NO - 6 - IBCocoaTouchFramework - 0 - 0 - - 2 - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - {480, 320} - - - 1 - MCAwIDAAA - - - 3 - - IBCocoaTouchFramework - - - - - YES - - - view - - - - 3 - - - - switchViews: - - - 7 - - 30 - - - - switchViews: - - - 7 - - 40 - - - - switchViews: - - - 7 - - 42 - - - - switchViews: - - - 7 - - 44 - - - - switchViews: - - - 7 - - 47 - - - - switchViews: - - - 7 - - 49 - - - - - YES - - 0 - - - - - - 1 - - - YES - - - - - - - - - - - - - -1 - - - File's Owner - - - -2 - - - - - 23 - - - - - 22 - - - - - 41 - - - - - 43 - - - - - 24 - - - - - 28 - - - - - 46 - - - - - 48 - - - - - - - YES - - YES - -1.CustomClassName - -2.CustomClassName - 1.IBEditorWindowLastContentRect - 1.IBPluginDependency - 22.IBPluginDependency - 22.IBViewBoundsToFrameTransform - 23.IBPluginDependency - 23.IBViewBoundsToFrameTransform - 24.IBPluginDependency - 24.IBViewBoundsToFrameTransform - 28.IBPluginDependency - 28.IBViewBoundsToFrameTransform - 41.IBPluginDependency - 41.IBViewBoundsToFrameTransform - 43.IBPluginDependency - 43.IBViewBoundsToFrameTransform - 46.IBPluginDependency - 46.IBViewBoundsToFrameTransform - 48.IBPluginDependency - 48.IBViewBoundsToFrameTransform - - - YES - MainMenuViewController - UIResponder - {{517, 519}, {480, 320}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAAAAAAAAw5UAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABCygAAwzcAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDPgAAw5UAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDxgAAw5iAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABBcAAAwhAAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABBoAAAw5iAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUPbgABBUAAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABD3gAAwjwAAA - - - - - YES - - - YES - - - - - YES - - - YES - - - - 49 - - - - YES - - MainMenuViewController - UIViewController - - switchViews: - id - - - switchViews: - - switchViews: - id - - - - IBProjectSource - Classes/MainMenuViewController.h - - - - UIButton - - IBProjectSource - Classes/ExtraCategories.h - - - - - YES - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSError.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSFileManager.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueCoding.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueObserving.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyedArchiver.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSObject.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSRunLoop.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSThread.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURL.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURLConnection.h - - - - NSObject - - IBFrameworkSource - QuartzCore.framework/Headers/CAAnimation.h - - - - NSObject - - IBFrameworkSource - QuartzCore.framework/Headers/CALayer.h - - - - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UIAccessibility.h - - - - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UINibLoading.h - - - - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UIResponder.h - - - - UIButton - UIControl - - IBFrameworkSource - UIKit.framework/Headers/UIButton.h - - - - UIControl - UIView - - IBFrameworkSource - UIKit.framework/Headers/UIControl.h - - - - UIImageView - UIView - - IBFrameworkSource - UIKit.framework/Headers/UIImageView.h - - - - UIResponder - NSObject - - - - UISearchBar - UIView - - IBFrameworkSource - UIKit.framework/Headers/UISearchBar.h - - - - UISearchDisplayController - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UISearchDisplayController.h - - - - UIView - - IBFrameworkSource - UIKit.framework/Headers/UIPrintFormatter.h - - - - UIView - - IBFrameworkSource - UIKit.framework/Headers/UITextField.h - - - - UIView - UIResponder - - IBFrameworkSource - UIKit.framework/Headers/UIView.h - - - - UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UINavigationController.h - - - - UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UIPopoverController.h - - - - UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UISplitViewController.h - - - - UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UITabBarController.h - - - - UIViewController - UIResponder - - IBFrameworkSource - UIKit.framework/Headers/UIViewController.h - - - - - 0 - IBCocoaTouchFramework - - com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS - - - - com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 - - - YES - ../Hedgewars.xcodeproj - 3 - - YES - - YES - background~iphone.png - localplayButton~iphone.png - savesButton.png - settingsButton.png - title~iphone.png - - - YES - {480, 320} - {100, 100} - {64, 64} - {64, 64} - {270, 150} - - - 132 - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/MainMenuViewController.h --- a/project_files/HedgewarsMobile/Classes/MainMenuViewController.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/MainMenuViewController.h Tue Nov 10 20:43:13 2015 +0100 @@ -13,35 +13,13 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ #import - -@class GameConfigViewController; -@class SettingsContainerViewController; -@class AboutViewController; -@class SavedGamesViewController; -@class RestoreViewController; -@class MissionTrainingViewController; - -@interface MainMenuViewController : UIViewController { - GameConfigViewController *gameConfigViewController; - SettingsContainerViewController *settingsViewController; - AboutViewController *aboutViewController; - SavedGamesViewController *savedGamesViewController; - RestoreViewController *restoreViewController; - MissionTrainingViewController *missionsViewController; -} - -@property (nonatomic,retain) GameConfigViewController *gameConfigViewController; -@property (nonatomic,retain) SettingsContainerViewController *settingsViewController; -@property (nonatomic,retain) AboutViewController *aboutViewController; -@property (nonatomic,retain) SavedGamesViewController *savedGamesViewController; -@property (nonatomic,retain) RestoreViewController *restoreViewController; -@property (nonatomic,retain) MissionTrainingViewController *missionsViewController; +@interface MainMenuViewController : UIViewController -(IBAction) switchViews:(id)sender; diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/MainMenuViewController.m --- a/project_files/HedgewarsMobile/Classes/MainMenuViewController.m Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/MainMenuViewController.m Tue Nov 10 20:43:13 2015 +0100 @@ -13,14 +13,15 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ #import "MainMenuViewController.h" #import #import "GameConfigViewController.h" -#import "SettingsContainerViewController.h" +#import "MGSplitViewController.h" +#import "SettingsBaseViewController.h" #import "AboutViewController.h" #import "SavedGamesViewController.h" #import "RestoreViewController.h" @@ -29,10 +30,23 @@ #import "ServerProtocolNetwork.h" #import "GameInterfaceBridge.h" +#import "SettingsBaseViewController.h" +#import "GeneralSettingsViewController.h" +#import "TeamSettingsViewController.h" +#import "WeaponSettingsViewController.h" +#import "SchemeSettingsViewController.h" +#import "SupportViewController.h" + +#ifdef DEBUG +#import "GameLogViewController.h" +#endif + +@interface MainMenuViewController () +@property (retain, nonatomic) IBOutlet UIButton *simpleGameButton; +@property (retain, nonatomic) IBOutlet UIButton *missionsButton; +@end @implementation MainMenuViewController -@synthesize gameConfigViewController, settingsViewController, aboutViewController, savedGamesViewController, - restoreViewController, missionsViewController; -(BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation) interfaceOrientation { return rotationManager(interfaceOrientation); @@ -42,7 +56,13 @@ -(void) viewDidLoad { self.view.frame = [[UIScreen mainScreen] safeBounds]; [super viewDidLoad]; - + + [self.simpleGameButton setTitle:NSLocalizedString(@"Simple", nil) forState:UIControlStateNormal]; + [self.missionsButton setTitle:NSLocalizedString(@"Missions", nil) forState:UIControlStateNormal]; + + [self.simpleGameButton applyDarkBlueQuickStyle]; + [self.missionsButton applyDarkBlueQuickStyle]; + // get the app's version NSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleVersionKey]; @@ -62,19 +82,19 @@ // prompt for restoring any previous game NSString *saveString = [userDefaults objectForKey:@"savedGamePath"]; - if (saveString != nil && [saveString isEqualToString:@""] == NO && [[userDefaults objectForKey:@"saveIsValid"] boolValue]) { - if (self.restoreViewController == nil) { - NSString *xibName = [@"RestoreViewController-" stringByAppendingString:(IS_IPAD() ? @"iPad" : @"iPhone")]; - RestoreViewController *restored = [[RestoreViewController alloc] initWithNibName:xibName bundle:nil]; - if ([restored respondsToSelector:@selector(setModalPresentationStyle:)]) - restored.modalPresentationStyle = UIModalPresentationFormSheet; - self.restoreViewController = restored; - [restored release]; - } - [self performSelector:@selector(presentModalViewController:animated:) withObject:self.restoreViewController afterDelay:0.25]; - } else { + if (saveString != nil && [saveString isEqualToString:@""] == NO && [[userDefaults objectForKey:@"saveIsValid"] boolValue]) + { + NSString *xibName = [@"RestoreViewController-" stringByAppendingString:(IS_IPAD() ? @"iPad" : @"iPhone")]; + RestoreViewController *restored = [[RestoreViewController alloc] initWithNibName:xibName bundle:nil]; + if ([restored respondsToSelector:@selector(setModalPresentationStyle:)]) + restored.modalPresentationStyle = UIModalPresentationFormSheet; + + [self performSelector:@selector(presentViewController:) withObject:restored afterDelay:0.25]; + } + else + { // let's not prompt for rating when app crashed >_> - [Appirater appLaunched]; + [Appirater appLaunched:YES]; } /* @@ -82,6 +102,12 @@ */ } +- (void) presentViewController:(UIViewController *)vc +{ + [self presentViewController:vc animated:NO completion:nil]; + [vc release]; +} + -(void) viewWillAppear:(BOOL)animated { [[AudioManagerController mainManager] playBackgroundMusic]; [super viewWillAppear:animated]; @@ -92,99 +118,134 @@ UIButton *button = (UIButton *)sender; UIAlertView *alert; NSString *xib = nil; - NSString *debugStr = nil; [[AudioManagerController mainManager] playClickSound]; switch (button.tag) { case 0: - if (nil == self.gameConfigViewController) { - xib = IS_IPAD() ? @"GameConfigViewController-iPad" : @"GameConfigViewController-iPhone"; + xib = IS_IPAD() ? @"GameConfigViewController-iPad" : @"GameConfigViewController-iPhone"; - GameConfigViewController *gcvc = [[GameConfigViewController alloc] initWithNibName:xib bundle:nil]; - gcvc.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal; - self.gameConfigViewController = gcvc; - [gcvc release]; - } - [self presentModalViewController:self.gameConfigViewController animated:YES]; + GameConfigViewController *gcvc = [[GameConfigViewController alloc] initWithNibName:xib bundle:nil]; + gcvc.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal; + + [self presentViewController:gcvc animated:YES completion:nil]; + [gcvc release]; break; case 2: - if (nil == self.settingsViewController) { - SettingsContainerViewController *svrc = [[SettingsContainerViewController alloc] initWithNibName:nil bundle:nil]; - svrc.modalTransitionStyle = UIModalTransitionStyleCoverVertical; - self.settingsViewController = svrc; - [svrc release]; + if (IS_IPAD()) + { + // the contents on the right of the splitview, setting targetController to nil to avoid creating the table + SettingsBaseViewController *rightController = [[SettingsBaseViewController alloc] init]; + rightController.targetController = nil; + UINavigationController *rightNavController = [[UINavigationController alloc] initWithRootViewController:rightController]; + [rightController release]; + + // the contens on the left of the splitview, setting targetController that will receive push/pop actions + SettingsBaseViewController *leftController = [[SettingsBaseViewController alloc] init]; + leftController.targetController = rightNavController.topViewController; + UINavigationController *leftNavController = [[UINavigationController alloc] initWithRootViewController:leftController]; + [leftController release]; + + MGSplitViewController *splitViewRootController = [[MGSplitViewController alloc] init]; + splitViewRootController.delegate = nil; + splitViewRootController.showsMasterInPortrait = YES; + splitViewRootController.viewControllers = [NSArray arrayWithObjects:leftNavController, rightNavController, nil]; + [leftNavController release]; + [rightNavController release]; + + [self presentViewController:splitViewRootController animated:YES completion:nil]; + [splitViewRootController release]; } - [self presentModalViewController:self.settingsViewController animated:YES]; + else + { + NSMutableArray *tabBarNavigationControllers = [[NSMutableArray alloc] initWithCapacity:5]; + + UIViewController *generalSettingsViewController = [[GeneralSettingsViewController alloc] initWithStyle:UITableViewStyleGrouped]; + generalSettingsViewController.tabBarItem = [self tabBarItemWithTitle:NSLocalizedString(@"General",@"") imageName:@"flower" selectedImageName:@"flower_filled"]; + UINavigationController *generalNavController = [[UINavigationController alloc] initWithRootViewController:generalSettingsViewController]; + [generalSettingsViewController release]; + [tabBarNavigationControllers addObject:generalNavController]; + [generalNavController release]; + + UIViewController *teamSettingsViewController = [[TeamSettingsViewController alloc] initWithStyle:UITableViewStyleGrouped]; + teamSettingsViewController.tabBarItem = [self tabBarItemWithTitle:NSLocalizedString(@"Teams",@"") imageName:@"teams" selectedImageName:@"teams_filled"]; + UINavigationController *teamNavController = [[UINavigationController alloc] initWithRootViewController:teamSettingsViewController]; + [teamSettingsViewController release]; + [tabBarNavigationControllers addObject:teamNavController]; + [teamNavController release]; + + UIViewController *weaponSettingsViewController = [[WeaponSettingsViewController alloc] initWithStyle:UITableViewStyleGrouped]; + weaponSettingsViewController.tabBarItem = [self tabBarItemWithTitle:NSLocalizedString(@"Weapons",@"") imageName:@"bullet" selectedImageName:@"bullet_filled"]; + UINavigationController *weaponNavController = [[UINavigationController alloc] initWithRootViewController:weaponSettingsViewController]; + [weaponSettingsViewController release]; + [tabBarNavigationControllers addObject:weaponNavController]; + [weaponNavController release]; + + UIViewController *schemeSettingsViewController = [[SchemeSettingsViewController alloc] initWithStyle:UITableViewStyleGrouped]; + schemeSettingsViewController.tabBarItem = [self tabBarItemWithTitle:NSLocalizedString(@"Schemes",@"") imageName:@"target" selectedImageName:@"target_filled"]; + UINavigationController *schemeNavController = [[UINavigationController alloc] initWithRootViewController:schemeSettingsViewController]; + [schemeSettingsViewController release]; + [tabBarNavigationControllers addObject:schemeNavController]; + [schemeNavController release]; + + UIViewController *supportViewController = [[SupportViewController alloc] initWithStyle:UITableViewStyleGrouped]; + supportViewController.tabBarItem = [self tabBarItemWithTitle:NSLocalizedString(@"Support",@"") imageName:@"heart" selectedImageName:@"heart_filled"]; + UINavigationController *supportNavController = [[UINavigationController alloc] initWithRootViewController:supportViewController]; + [supportViewController release]; + [tabBarNavigationControllers addObject:supportNavController]; + [supportNavController release]; + + UITabBarController *settingsTabController = [[UITabBarController alloc] init]; + settingsTabController.viewControllers = tabBarNavigationControllers; + [tabBarNavigationControllers release]; + + [self presentViewController:settingsTabController animated:YES completion:nil]; + [settingsTabController release]; + } break; case 3: #ifdef DEBUG - if ([[NSFileManager defaultManager] fileExistsAtPath:DEBUG_FILE()]) - debugStr = [[NSString alloc] initWithContentsOfFile:DEBUG_FILE()]; - else - debugStr = [[NSString alloc] initWithString:@"Here be log"]; - UITextView *scroll = [[UITextView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.height, self.view.frame.size.width)]; - scroll.text = debugStr; - [debugStr release]; - scroll.editable = NO; - scroll.alpha = 0; - - UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom]; - [btn addTarget:scroll action:@selector(removeFromSuperview) forControlEvents:UIControlEventTouchUpInside]; - [btn addTarget:btn action:@selector(removeFromSuperview) forControlEvents:UIControlEventTouchUpInside]; - btn.frame = CGRectMake(self.view.frame.size.height-58, -6, 64, 64); - btn.backgroundColor = [UIColor blackColor]; - btn.titleLabel.textColor = [UIColor whiteColor]; - btn.titleLabel.textAlignment = UITextAlignmentCenter; - btn.titleLabel.font = [UIFont boldSystemFontOfSize:[UIFont systemFontSize]]; - [btn setTitle:@"Close" forState:UIControlStateNormal]; - btn.alpha = 0; - [btn.layer setCornerRadius:10.0f]; - [btn.layer setMasksToBounds:YES]; - - [self.view addSubview:scroll]; - [self.view addSubview:btn]; - - [UIView beginAnimations:@"fadein" context:NULL]; - [UIView setAnimationDuration:0.25f]; - btn.alpha = 1; - scroll.alpha = 1; - [UIView commitAnimations]; - [scroll release]; + { + GameLogViewController *gameLogVC = [[GameLogViewController alloc] init]; + UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:gameLogVC]; + [gameLogVC release]; + + [self presentViewController:navController animated:YES completion:nil]; + [navController release]; + } #else - debugStr = debugStr; // prevent compiler warning - if (nil == self.aboutViewController) { + { AboutViewController *about = [[AboutViewController alloc] initWithNibName:@"AboutViewController" bundle:nil]; about.modalTransitionStyle = UIModalTransitionStyleCoverVertical; if ([about respondsToSelector:@selector(setModalPresentationStyle:)]) about.modalPresentationStyle = UIModalPresentationFormSheet; - self.aboutViewController = about; + + [self presentViewController:about animated:YES completion:nil]; [about release]; } - [self presentModalViewController:self.aboutViewController animated:YES]; #endif break; case 4: - if (nil == self.savedGamesViewController) { + { SavedGamesViewController *savedgames = [[SavedGamesViewController alloc] initWithNibName:@"SavedGamesViewController" bundle:nil]; savedgames.modalTransitionStyle = UIModalTransitionStyleCoverVertical; if ([savedgames respondsToSelector:@selector(setModalPresentationStyle:)]) savedgames.modalPresentationStyle = UIModalPresentationPageSheet; - self.savedGamesViewController = savedgames; + + [self presentViewController:savedgames animated:YES completion:nil]; [savedgames release]; } - [self presentModalViewController:self.savedGamesViewController animated:YES]; break; case 5: - if (nil == self.missionsViewController) { + { xib = IS_IPAD() ? @"MissionTrainingViewController-iPad" : @"MissionTrainingViewController-iPhone"; MissionTrainingViewController *missions = [[MissionTrainingViewController alloc] initWithNibName:xib bundle:nil]; missions.modalTransitionStyle = IS_IPAD() ? UIModalTransitionStyleCoverVertical : UIModalTransitionStyleCrossDissolve; if ([missions respondsToSelector:@selector(setModalPresentationStyle:)]) missions.modalPresentationStyle = UIModalPresentationPageSheet; - self.missionsViewController = missions; + + [self presentViewController:missions animated:YES completion:nil]; [missions release]; } - [self presentModalViewController:self.missionsViewController animated:YES]; break; case 6: [GameInterfaceBridge registerCallingController:self]; @@ -202,42 +263,29 @@ } } +- (UITabBarItem *)tabBarItemWithTitle: (NSString *)title + imageName: (NSString *)imageName + selectedImageName: (NSString *)selectedImageName +{ + return [[[UITabBarItem alloc] initWithTitle:title + image:[UIImage imageNamed:imageName] + selectedImage:[UIImage imageNamed:selectedImageName]] autorelease]; +} + #pragma mark - -(void) viewDidUnload { - self.gameConfigViewController = nil; - self.settingsViewController = nil; - self.aboutViewController = nil; - self.savedGamesViewController = nil; - self.restoreViewController = nil; - self.missionsViewController = nil; MSG_DIDUNLOAD(); [super viewDidUnload]; } -(void) didReceiveMemoryWarning { - if (self.settingsViewController.view.superview == nil) - self.settingsViewController = nil; - if (self.gameConfigViewController.view.superview == nil) - self.gameConfigViewController = nil; - if (self.aboutViewController.view.superview == nil) - self.aboutViewController = nil; - if (self.savedGamesViewController.view.superview == nil) - self.savedGamesViewController = nil; - if (self.restoreViewController.view.superview == nil) - self.restoreViewController = nil; - if (self.missionsViewController.view.superview == nil) - self.missionsViewController = nil; MSG_MEMCLEAN(); [super didReceiveMemoryWarning]; } -(void) dealloc { - releaseAndNil(settingsViewController); - releaseAndNil(gameConfigViewController); - releaseAndNil(aboutViewController); - releaseAndNil(savedGamesViewController); - releaseAndNil(restoreViewController); - releaseAndNil(missionsViewController); + [_simpleGameButton release]; + [_missionsButton release]; [super dealloc]; } diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/MapConfigViewController-iPhone.xib --- a/project_files/HedgewarsMobile/Classes/MapConfigViewController-iPhone.xib Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/MapConfigViewController-iPhone.xib Tue Nov 10 20:43:13 2015 +0100 @@ -1,34 +1,30 @@ - + - 1056 - 10K549 - 823 - 1038.36 - 461.00 + 1792 + 14E46 + 7706 + 1348.17 + 758.70 com.apple.InterfaceBuilder.IBCocoaTouchPlugin - 132 - - - YES - - - - YES - com.apple.InterfaceBuilder.IBCocoaTouchPlugin + 7703 - - YES - - YES - - - YES - - - - YES + + IBProxyObject + IBUIButton + IBUIImageView + IBUILabel + IBUISegmentedControl + IBUISlider + IBUITableView + IBUIView + + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + IBFilesOwner IBCocoaTouchFramework @@ -40,18 +36,19 @@ 274 - - YES + - 292 + 274 {480, 276} + + 2 NO IBCocoaTouchFramework NSImage - background~iphone.png + background.png @@ -59,46 +56,42 @@ 292 {{9, 14}, {270, 30}} + NO IBCocoaTouchFramework 2 4 1 - - YES + Random Map Maze Mission - - - YES + + - - - YES + + - - - YES + + {0, 0} {0, 0} {0, 0} {0, 0} - - - YES + + - + 3 MC42NjY2NjY2NjY3AA @@ -109,17 +102,13 @@ 292 {{71, 196}, {145, 44}} + NO YES 7 NO IBCocoaTouchFramework Loading... - - Helvetica-Bold - 17 - 16 - 2 MC45NDExNzY1MzM3IDAuODE1Njg2MzQ1MSAwAA @@ -128,39 +117,59 @@ 1 10 1 + + Helvetica-Bold + Helvetica + 2 + 17 + + + Helvetica-Bold + 17 + 16 + + YES 292 {{16, 58}, {256, 128}} + NO IBCocoaTouchFramework 0 0 - - Helvetica-Bold - 15 - 16 + + 1 + MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA 3 MQA - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - 3 MC41AA + + Helvetica-Bold + Helvetica + 2 + 15 + + + Helvetica-Bold + 15 + 16 + 274 {{284, 0}, {196, 276}} + 3 MCAwAA @@ -183,6 +192,7 @@ 292 {{52, 239}, {184, 23}} + NO IBCocoaTouchFramework 0 @@ -190,20 +200,26 @@ 0.05000000074505806 0.05000000074505806 - + {480, 276} + + YES + 3 3 + + IBUISimulatedFreeformSizeMetricsSentinel + Freeform + IBCocoaTouchFramework - + - - YES + view @@ -229,6 +245,39 @@ 16 + + segmentedControl + + + + 21 + + + + tableView + + + + 32 + + + + slider + + + + 38 + + + + segmentedControlChanged: + + + 13 + + 22 + + sliderChanged: @@ -248,47 +297,6 @@ - segmentedControl - - - - 21 - - - - segmentedControlChanged: - - - 13 - - 22 - - - - dataSource - - - - 26 - - - - delegate - - - - 27 - - - - tableView - - - - 32 - - - delegate @@ -306,34 +314,40 @@ - slider - - + dataSource + + - 38 + 26 - + + + delegate + + + + 27 + + - - YES + 0 - + 1 - - YES + - + @@ -360,9 +374,7 @@ 25 - - YES - + Table View (Themes) @@ -381,343 +393,141 @@ - + - - YES - - YES - -1.CustomClassName - -2.CustomClassName - 1.IBEditorWindowLastContentRect - 1.IBPluginDependency - 11.IBPluginDependency - 11.IBViewBoundsToFrameTransform - 25.IBPluginDependency - 25.IBViewBoundsToFrameTransform - 35.IBPluginDependency - 35.IBViewBoundsToFrameTransform - 7.IBPluginDependency - 7.IBViewBoundsToFrameTransform - 8.CustomClassName - 8.IBPluginDependency - 8.IBViewBoundsToFrameTransform - 9.CustomClassName - 9.IBPluginDependency - 9.IBViewBoundsToFrameTransform - - - YES - MapConfigViewController - UIResponder - {{790, 298}, {480, 320}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUKOAABDRAAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDjgAAw4kAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAAAAAAAAw4kAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABBUAAAwigAAA - - MNEValueTrackingSlider - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABCWAAAw4IAAA - - MapPreviewButtonView - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABBgAAAwzgAAA - - - - - YES - - - YES - - + + MapConfigViewController + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + UIResponder + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + MNEValueTrackingSlider + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + MapPreviewButtonView + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + - - YES - - - YES - - + 38 - - YES + MNEValueTrackingSlider UISlider IBProjectSource - Classes/MNEValueTrackingSlider.h + ../Classes/MNEValueTrackingSlider.h MapConfigViewController UIViewController - - YES - - YES - mapButtonPressed: - segmentedControlChanged: - sliderChanged: - sliderEndedChanging: - - - YES - id - id - id - id + + id + id + id + id + + + + mapButtonPressed: + id - - - YES - - YES - mapButtonPressed: - segmentedControlChanged: - sliderChanged: - sliderEndedChanging: + + segmentedControlChanged: + id - - YES - - mapButtonPressed: - id - - - segmentedControlChanged: - id - - - sliderChanged: - id - - - sliderEndedChanging: - id - + + sliderChanged: + id + + + sliderEndedChanging: + id - - - YES - - YES - maxLabel - previewButton - segmentedControl - slider - tableView - - - YES - UILabel - MapPreviewButtonView - UISegmentedControl - MNEValueTrackingSlider - UITableView + + + UILabel + MapPreviewButtonView + UISegmentedControl + MNEValueTrackingSlider + UITableView + + + + maxLabel + UILabel - - - YES - - YES - maxLabel - previewButton - segmentedControl - slider - tableView + + previewButton + MapPreviewButtonView + + + segmentedControl + UISegmentedControl - - YES - - maxLabel - UILabel - - - previewButton - MapPreviewButtonView - - - segmentedControl - UISegmentedControl - - - slider - MNEValueTrackingSlider - - - tableView - UITableView - + + slider + MNEValueTrackingSlider - + + tableView + UITableView + + IBProjectSource - Classes/MapConfigViewController.h + ../Classes/MapConfigViewController.h + + + + MapConfigViewController + + id + id + id + id + + + + mapButtonPressed: + id + + + segmentedControlChanged: + id + + + sliderChanged: + id + + + sliderEndedChanging: + id + + + + IBProjectSource + ../Classes/MapConfigViewController.m MapPreviewButtonView UIButton - - delegate - id - - - delegate - - delegate - id - - IBProjectSource - Classes/MapPreviewButtonView.h - - - - UIButton - - IBProjectSource - Classes/ExtraCategories.h - - - - UILabel - - - - UITableView - - - - - YES - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSError.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSFileManager.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueCoding.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueObserving.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyedArchiver.h + ../Classes/MapPreviewButtonView.h - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSObject.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSRunLoop.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSThread.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURL.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURLConnection.h - - - - NSObject - - IBFrameworkSource - QuartzCore.framework/Headers/CAAnimation.h - - - - NSObject - - IBFrameworkSource - QuartzCore.framework/Headers/CALayer.h - - - - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UIAccessibility.h - - - - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UINibLoading.h - - - - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UIResponder.h - - + + UIButton UIControl @@ -735,6 +545,14 @@ + UIGestureRecognizer + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UIGestureRecognizer.h + + + UIImageView UIView @@ -753,7 +571,10 @@ UIResponder NSObject - + + IBFrameworkSource + UIKit.framework/Headers/UIResponder.h + UIScrollView @@ -805,20 +626,6 @@ UIView - - IBFrameworkSource - UIKit.framework/Headers/UIPrintFormatter.h - - - - UIView - - IBFrameworkSource - UIKit.framework/Headers/UITextField.h - - - - UIView UIResponder IBFrameworkSource @@ -827,59 +634,26 @@ UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UINavigationController.h - - - - UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UIPopoverController.h - - - - UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UISplitViewController.h - - - - UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UITabBarController.h - - - - UIViewController UIResponder IBFrameworkSource UIKit.framework/Headers/UIViewController.h - + 0 IBCocoaTouchFramework - - com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS - - + NO com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 - + YES - ../Hedgewars.xcodeproj 3 - background~iphone.png + background.png {480, 320} - 132 diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/MapConfigViewController.h --- a/project_files/HedgewarsMobile/Classes/MapConfigViewController.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/MapConfigViewController.h Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/MapConfigViewController.m --- a/project_files/HedgewarsMobile/Classes/MapConfigViewController.m Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/MapConfigViewController.m Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ @@ -62,7 +62,7 @@ [seed release]; // perform as if user clicked on an entry - NSIndexPath *theIndex = [NSIndexPath indexPathForRow:(random()%[source count]) inSection:0]; + NSIndexPath *theIndex = [NSIndexPath indexPathForRow:arc4random_uniform((int)[source count]) inSection:0]; [self tableView:self.tableView didSelectRowAtIndexPath:theIndex]; if (IS_NOT_POWERFUL([HWUtils modelType]) == NO) [self.tableView scrollToRowAtIndexPath:theIndex atScrollPosition:UITableViewScrollPositionMiddle animated:YES]; @@ -179,8 +179,8 @@ #pragma mark - #pragma mark Table view delegate -(void) tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - int newRow = [indexPath row]; - int oldRow = (lastIndexPath != nil) ? [lastIndexPath row] : -1; + NSInteger newRow = [indexPath row]; + NSInteger oldRow = (lastIndexPath != nil) ? [lastIndexPath row] : -1; if (newRow != oldRow) { NSArray *source = [self.dataSourceArray objectAtIndex:scIndex]; @@ -352,6 +352,15 @@ oldPage = newPage; } +- (void)localizeSegmentedControl +{ + for (NSUInteger i = 0; i < self.segmentedControl.numberOfSegments; i++) + { + NSString *oldTitle = [self.segmentedControl titleForSegmentAtIndex:i]; + [self.segmentedControl setTitle:NSLocalizedString(oldTitle, nil) forSegmentAtIndex:i]; + } +} + #pragma mark - #pragma mark view management -(NSArray *) dataSourceArray { @@ -403,8 +412,9 @@ -(void) viewDidLoad { [super viewDidLoad]; - srandom(time(NULL)); - + + [self localizeSegmentedControl]; + // initialize some "default" values self.slider.value = 0.05f; self.slider.enabled = NO; diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/MapPreviewButtonView.h --- a/project_files/HedgewarsMobile/Classes/MapPreviewButtonView.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/MapPreviewButtonView.h Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/MapPreviewButtonView.m --- a/project_files/HedgewarsMobile/Classes/MapPreviewButtonView.m Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/MapPreviewButtonView.m Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ @@ -24,6 +24,10 @@ #define INDICATOR_TAG 7654 +@interface MapPreviewButtonView () +@property (nonatomic) NSInteger port; +@end + @implementation MapPreviewButtonView @synthesize delegate; @@ -54,7 +58,7 @@ #pragma mark - #pragma mark preview -(int) sendToEngine:(NSString *)string { - unsigned char length = [string length]; + unsigned char length = [string lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; SDLNet_TCP_Send(csd, &length, 1); return SDLNet_TCP_Send(csd, [string UTF8String], length); @@ -64,7 +68,7 @@ IPaddress ip; BOOL serverQuit = NO; uint8_t packedMap[128*32]; - int port = [HWUtils randomPort]; + self.port = [HWUtils randomPort]; if (SDLNet_Init() < 0) { DLog(@"SDLNet_Init: %s", SDLNet_GetError()); @@ -72,23 +76,45 @@ } // Resolving the host using NULL make network interface to listen - if (SDLNet_ResolveHost(&ip, NULL, port) < 0) { + if (SDLNet_ResolveHost(&ip, NULL, self.port) < 0) { DLog(@"SDLNet_ResolveHost: %s\n", SDLNet_GetError()); serverQuit = YES; } // Open a connection with the IP provided (listen on the host's port) if (!(sd = SDLNet_TCP_Open(&ip))) { - DLog(@"SDLNet_TCP_Open: %s %\n", SDLNet_GetError(), port); + DLog(@"SDLNet_TCP_Open: %s %ld\n", SDLNet_GetError(), (long)self.port); serverQuit = YES; } - // launch the preview here so that we're sure the tcp channel is open - pthread_t thread_id; - pthread_create(&thread_id, NULL, (void *(*)(void *))GenLandPreview, (void *)port); - pthread_detach(thread_id); - - DLog(@"Waiting for a client on port %d", port); + // launch the preview in background here so that we're sure the tcp channel is open + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{ + NSString *ipcString = [[NSString alloc] initWithFormat:@"%ld", (long)self.port]; + NSString *documentsDirectory = DOCUMENTS_FOLDER(); + + NSMutableArray *gameParameters = [[NSMutableArray alloc] initWithObjects: + @"--internal", + @"--port", ipcString, + @"--user-prefix", documentsDirectory, + @"--landpreview", + nil]; + [ipcString release]; + + int argc = [gameParameters count]; + const char **argv = (const char **)malloc(sizeof(const char*)*argc); + for (int i = 0; i < argc; i++) + argv[i] = strdup([[gameParameters objectAtIndex:i] UTF8String]); + [gameParameters release]; + + RunEngine(argc, argv); + + // cleanup + for (int i = 0; i < argc; i++) + free((void *)argv[i]); + free(argv); + }); + + DLog(@"Waiting for a client on port %ld", (long)self.port); while (!serverQuit) { /* This check the sd if there is a pending connection. * If there is one, accept that, and open a new socket for communicating */ @@ -111,7 +137,7 @@ serverQuit = YES; } } - [HWUtils freePort:port]; + [HWUtils freePort:self.port]; SDLNet_TCP_Close(sd); SDLNet_Quit(); @@ -129,13 +155,14 @@ } -(void) drawingThread { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + @autoreleasepool { + uint8_t unpackedMap[128*32*8]; [self engineProtocol:unpackedMap]; // http://developer.apple.com/mac/library/qa/qa2001/qa1037.html CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceGray(); - CGContextRef bitmapImage = CGBitmapContextCreate(unpackedMap, 256, 128, 8, 256, colorspace, kCGImageAlphaNone); + CGContextRef bitmapImage = CGBitmapContextCreate(unpackedMap, 256, 128, 8, 256, colorspace, (CGBitmapInfo)kCGImageAlphaNone); CGColorSpaceRelease(colorspace); CGImageRef previewCGImage = CGBitmapContextCreateImage(bitmapImage); @@ -149,7 +176,7 @@ waitUntilDone:NO]; [previewImage release]; [self performSelectorOnMainThread:@selector(setLabelText:) - withObject:[NSString stringWithFormat:@"%d", maxHogs] + withObject:[NSString stringWithFormat:@"%ld", (long)maxHogs] waitUntilDone:NO]; [self performSelectorOnMainThread:@selector(turnOnWidgets) withObject:nil @@ -157,8 +184,8 @@ [self performSelectorOnMainThread:@selector(removeIndicator) withObject:nil waitUntilDone:NO]; - - [pool release]; + + } } -(void) updatePreviewWithSeed:(NSString *)seed { diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/MissionTrainingViewController-iPhone.xib --- a/project_files/HedgewarsMobile/Classes/MissionTrainingViewController-iPhone.xib Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/MissionTrainingViewController-iPhone.xib Tue Nov 10 20:43:13 2015 +0100 @@ -1,34 +1,27 @@ - + - 1056 - 10K549 - 823 - 1038.36 - 461.00 + 1792 + 14E46 + 7706 + 1348.17 + 758.70 com.apple.InterfaceBuilder.IBCocoaTouchPlugin - 132 - - - YES - - - - YES - com.apple.InterfaceBuilder.IBCocoaTouchPlugin + 7703 - - YES - - YES - - - YES - - - - YES + + IBProxyObject + IBUIButton + IBUIImageView + IBUITableView + IBUIView + + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + IBFilesOwner IBCocoaTouchFramework @@ -40,18 +33,19 @@ 274 - - YES + - 292 + 274 {480, 320} + + 2 NO IBCocoaTouchFramework NSImage - smallerBackground~iphone.png + smallerBackground.png @@ -59,6 +53,7 @@ 274 {{180, 0}, {300, 320}} + 3 MQA @@ -80,6 +75,7 @@ 292 {{11, 19}, {157, 130}} + YES NO IBCocoaTouchFramework @@ -89,20 +85,16 @@ 292 {{57, 245}, {64, 64}} + NO IBCocoaTouchFramework 0 0 - - Helvetica-Bold - 15 - 16 - - 1 MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA + 3 MC41AA @@ -111,32 +103,46 @@ NSImage backButton.png + + Helvetica-Bold + Helvetica + 2 + 15 + + + Helvetica-Bold + 15 + 16 + 292 {{18, 164}, {142, 64}} + NO 1 IBCocoaTouchFramework 0 0 - - 1 MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA + NSImage startGameButton.png + + - + {480, 320} + 3 MQA @@ -145,14 +151,18 @@ + 3 3 + + IBUISimulatedFreeformSizeMetricsSentinel + Freeform + IBCocoaTouchFramework - + - - YES + view @@ -163,6 +173,22 @@ + previewImage + + + + 13 + + + + tableView + + + + 14 + + + dataSource @@ -178,22 +204,6 @@ 12 - - previewImage - - - - 13 - - - - tableView - - - - 14 - - buttonPressed: @@ -211,27 +221,25 @@ 20 - + - - YES + 0 - + 1 - - YES + - + @@ -248,9 +256,7 @@ 9 - - YES - + @@ -273,72 +279,28 @@ - + - - YES - - YES - -1.CustomClassName - -2.CustomClassName - 1.IBEditorWindowLastContentRect - 1.IBPluginDependency - 10.IBPluginDependency - 10.IBViewBoundsToFrameTransform - 17.IBPluginDependency - 17.IBViewBoundsToFrameTransform - 18.IBPluginDependency - 18.IBViewBoundsToFrameTransform - 23.IBPluginDependency - 9.IBPluginDependency - 9.IBViewBoundsToFrameTransform - - - YES - MissionTrainingViewController - UIResponder - {{492, 751}, {480, 320}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABAoAAAwwYAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABChAAAw5eAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABB2AAAw2cAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDUAAAw5UAAA - - - - - YES - - - YES - - + + MissionTrainingViewController + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + UIResponder + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + - - YES - - - YES - - + 23 - - YES + MissionTrainingViewController UIViewController @@ -353,173 +315,50 @@ id - - YES - - YES - descriptionLabel - previewImage - tableView + + UILabel + UIImageView + UITableView + + + + descriptionLabel + UILabel - - YES - UILabel - UIImageView - UITableView + + previewImage + UIImageView + + tableView + UITableView + + + + IBProjectSource + ../Classes/MissionTrainingViewController.h - - YES - - YES - descriptionLabel - previewImage - tableView - - - YES - - descriptionLabel - UILabel - - - previewImage - UIImageView - - - tableView - UITableView - + + + MissionTrainingViewController + + buttonPressed: + id + + + buttonPressed: + + buttonPressed: + id IBProjectSource - Classes/MissionTrainingViewController.h - - - - UIButton - - IBProjectSource - Classes/ExtraCategories.h - - - - UILabel - - - - UITableView - - - - - YES - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSError.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSFileManager.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueCoding.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueObserving.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyedArchiver.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSObject.h + ../Classes/MissionTrainingViewController.m - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSRunLoop.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSThread.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURL.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURLConnection.h - - - - NSObject - - IBFrameworkSource - QuartzCore.framework/Headers/CAAnimation.h - - - - NSObject - - IBFrameworkSource - QuartzCore.framework/Headers/CALayer.h - - - - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UIAccessibility.h - - - - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UINibLoading.h - - - - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UIResponder.h - - + + UIButton UIControl @@ -537,6 +376,14 @@ + UIGestureRecognizer + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UIGestureRecognizer.h + + + UIImageView UIView @@ -555,7 +402,10 @@ UIResponder NSObject - + + IBFrameworkSource + UIKit.framework/Headers/UIResponder.h + UIScrollView @@ -591,20 +441,6 @@ UIView - - IBFrameworkSource - UIKit.framework/Headers/UIPrintFormatter.h - - - - UIView - - IBFrameworkSource - UIKit.framework/Headers/UITextField.h - - - - UIView UIResponder IBFrameworkSource @@ -613,70 +449,27 @@ UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UINavigationController.h - - - - UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UIPopoverController.h - - - - UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UISplitViewController.h - - - - UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UITabBarController.h - - - - UIViewController UIResponder IBFrameworkSource UIKit.framework/Headers/UIViewController.h - + 0 IBCocoaTouchFramework - - com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS - - + NO com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 - + YES - ../Hedgewars.xcodeproj 3 - - YES - - YES - backButton.png - smallerBackground~iphone.png - startGameButton.png - - - YES - {64, 64} - {480, 320} - {142, 64} - - - 132 + + {64, 64} + {480, 320} + {142, 64} + diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/MissionTrainingViewController.h --- a/project_files/HedgewarsMobile/Classes/MissionTrainingViewController.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/MissionTrainingViewController.h Tue Nov 10 20:43:13 2015 +0100 @@ -13,25 +13,19 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ #import -@interface MissionTrainingViewController : UIViewController { - NSArray *listOfMissions; - NSArray *listOfDescriptions; - NSString *missionName; - UIImageView *previewImage; - UITableView *tableView; - UILabel *descriptionLabel; -} +@interface MissionTrainingViewController : UIViewController -@property (nonatomic, retain) NSArray *listOfMissions; -@property (nonatomic, retain) NSArray *listOfDescriptions; +@property (nonatomic, retain) NSArray *listOfMissionIDs; +@property (nonatomic, retain) NSDictionary *dictOfMissions; @property (nonatomic, retain) NSString *missionName; + @property (nonatomic, retain) IBOutlet UIImageView *previewImage; @property (nonatomic, retain) IBOutlet UITableView *tableView; @property (nonatomic, retain) IBOutlet UILabel *descriptionLabel; diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/MissionTrainingViewController.m --- a/project_files/HedgewarsMobile/Classes/MissionTrainingViewController.m Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/MissionTrainingViewController.m Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ @@ -23,7 +23,6 @@ @implementation MissionTrainingViewController -@synthesize listOfMissions, listOfDescriptions, previewImage, tableView, descriptionLabel, missionName; -(BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation) interfaceOrientation { return rotationManager(interfaceOrientation); @@ -31,7 +30,10 @@ #pragma mark - #pragma mark View management --(void) viewDidLoad { +-(void) viewDidLoad +{ + [super viewDidLoad]; + self.previewImage.layer.borderColor = [[UIColor darkYellowColor] CGColor]; self.previewImage.layer.borderWidth = 3.8f; self.previewImage.layer.cornerRadius = 14; @@ -50,12 +52,11 @@ self.tableView.separatorColor = [UIColor whiteColor]; self.descriptionLabel.textColor = [UIColor lightYellowColor]; - [super viewDidLoad]; } -(void) viewWillAppear:(BOOL)animated { - NSIndexPath *indexPath = [NSIndexPath indexPathForRow:random()%[self.listOfMissions count] inSection:0]; - [self.tableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionNone]; + NSIndexPath *indexPath = [NSIndexPath indexPathForRow:arc4random_uniform((int)[self.listOfMissionIDs count]) inSection:0]; + [self.tableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionMiddle]; [self tableView:self.tableView didSelectRowAtIndexPath:indexPath]; [super viewWillAppear:animated]; } @@ -65,43 +66,136 @@ if (button.tag == 0) { [[AudioManagerController mainManager] playBackSound]; - [[self parentViewController] dismissModalViewControllerAnimated:YES]; + [self.presentingViewController dismissViewControllerAnimated:YES completion:nil]; } else { [GameInterfaceBridge registerCallingController:self]; [GameInterfaceBridge startMissionGame:self.missionName]; } } -#pragma mark - -#pragma mark override setters/getters for better memory handling --(NSArray *)listOfMissions { - if (listOfMissions == nil) - self.listOfMissions = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:TRAININGS_DIRECTORY() error:NULL]; - return listOfMissions; +#pragma mark - Missions dictionaries methods + +- (NSDictionary *)newLocalizedMissionsDictionary +{ + NSString *languageID = [HWUtils languageID]; + + NSString *missionsDescLocation = [[NSString alloc] initWithFormat:@"%@/missions_en.txt",LOCALE_DIRECTORY()]; + NSString *localizedMissionsDescLocation = [[NSString alloc] initWithFormat:@"%@/missions_%@.txt", LOCALE_DIRECTORY(), languageID]; + + if (![languageID isEqualToString:@"en"] && [[NSFileManager defaultManager] fileExistsAtPath:localizedMissionsDescLocation]) + { + NSDictionary *missionsDict = [self newMissionsDictionaryFromMissionsFile:missionsDescLocation]; + NSDictionary *localizedMissionsDict = [self newMissionsDictionaryFromMissionsFile:localizedMissionsDescLocation]; + + [missionsDescLocation release]; + [localizedMissionsDescLocation release]; + + NSMutableDictionary *tempMissionsDict = [[NSMutableDictionary alloc] init]; + + for (NSString *key in [missionsDict allKeys]) + { + if ([localizedMissionsDict objectForKey:key]) + { + [tempMissionsDict setObject:[localizedMissionsDict objectForKey:key] forKey:key]; + } + else + { + [tempMissionsDict setObject:[missionsDict objectForKey:key] forKey:key]; + } + } + + [missionsDict release]; + [localizedMissionsDict release]; + + return tempMissionsDict; + } + else + { + NSDictionary *missionsDict = [self newMissionsDictionaryFromMissionsFile:missionsDescLocation]; + + [missionsDescLocation release]; + [localizedMissionsDescLocation release]; + + return missionsDict; + } } --(NSArray *)listOfDescriptions { - if (listOfDescriptions == nil) { - NSString *descLocation = [[NSString alloc] initWithFormat:@"%@/missions_en.txt",LOCALE_DIRECTORY()]; - NSString *descComplete = [[NSString alloc] initWithContentsOfFile:descLocation encoding:NSUTF8StringEncoding error:NULL]; - [descLocation release]; - NSArray *descArray = [descComplete componentsSeparatedByString:@"\n"]; - NSMutableArray *filteredArray = [[NSMutableArray alloc] initWithCapacity:[descArray count]/3]; - [descComplete release]; - // sanity check to avoid having missions and descriptions conflicts - for (NSUInteger i = 0; i < [self.listOfMissions count]; i++) { - NSString *desc = [[self.listOfMissions objectAtIndex:i] stringByDeletingPathExtension]; - for (NSString *str in descArray) - if ([str hasPrefix:desc] && [str hasSuffix:@"\""]) { - NSArray *descriptionText = [str componentsSeparatedByString:@"\""]; - [filteredArray insertObject:[descriptionText objectAtIndex:1] atIndex:i]; - break; - } +- (NSDictionary *)newMissionsDictionaryFromMissionsFile:(NSString *)filePath +{ + NSMutableDictionary *missionsDict = [[NSMutableDictionary alloc] init]; + + NSString *missionsFileContents = [[NSString alloc] initWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:NULL]; + NSArray *missionsLines = [missionsFileContents componentsSeparatedByString:@"\n"]; + [missionsFileContents release]; + + for (NSString *line in missionsLines) + { + if ([line length] > 0) + { + NSUInteger firstDotLocation = [line rangeOfString:@"."].location; + + NSString *missionID = [line substringToIndex:firstDotLocation]; + + NSString *missionFullPath = [NSString stringWithFormat:@"%@%@.lua", TRAININGS_DIRECTORY(), missionID]; + if (![[NSFileManager defaultManager] fileExistsAtPath:missionFullPath]) + { + continue; + } + + NSString *nameOrDesc = [line substringFromIndex:firstDotLocation+1]; + + NSString *missionParsedName = ([nameOrDesc hasPrefix:@"name="]) ? [nameOrDesc stringByReplacingOccurrencesOfString:@"name=" withString:@""] : nil; + NSString *missionParsedDesc = ([nameOrDesc hasPrefix:@"desc="]) ? [nameOrDesc stringByReplacingOccurrencesOfString:@"desc=" withString:@""] : nil; + + if (![missionsDict objectForKey:missionID]) + { + NSMutableDictionary *missionDict = [[NSMutableDictionary alloc] init]; + [missionsDict setObject:missionDict forKey:missionID]; + [missionDict release]; + } + + NSMutableDictionary *missionDict = [missionsDict objectForKey:missionID]; + + if (missionParsedName) + { + [missionDict setObject:missionParsedName forKey:@"name"]; + } + + if (missionParsedDesc) + { + missionParsedDesc = [missionParsedDesc stringByReplacingOccurrencesOfString:@"\"" withString:@""]; + [missionDict setObject:missionParsedDesc forKey:@"desc"]; + } + + [missionsDict setObject:missionDict forKey:missionID]; } - self.listOfDescriptions = filteredArray; - [filteredArray release]; } - return listOfDescriptions; + + return missionsDict; +} + +#pragma mark - +#pragma mark override setters/getters for better memory handling + +-(NSArray *)listOfMissionIDs +{ + if (!_listOfMissionIDs) + { + NSArray *sortedKeys = [[self.dictOfMissions allKeys] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)]; + _listOfMissionIDs = [[NSArray alloc] initWithArray:sortedKeys]; + } + + return _listOfMissionIDs; +} + +- (NSDictionary *)dictOfMissions +{ + if (!_dictOfMissions) + { + _dictOfMissions = [self newLocalizedMissionsDictionary]; + } + + return _dictOfMissions; } #pragma mark - @@ -111,7 +205,7 @@ } -(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - return [self.listOfMissions count]; + return [self.listOfMissionIDs count]; } -(CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { @@ -126,21 +220,28 @@ if (cell == nil) cell = [[[UITableViewCell alloc] initWithStyle:(IS_IPAD()) ? UITableViewCellStyleDefault : UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease]; - - cell.textLabel.text = [[[self.listOfMissions objectAtIndex:row] stringByDeletingPathExtension] - stringByReplacingOccurrencesOfString:@"_" withString:@" "]; + + NSString *missionID = [self.listOfMissionIDs objectAtIndex:row]; + cell.textLabel.text = self.dictOfMissions[missionID][@"name"]; + cell.textLabel.textColor = [UIColor lightYellowColor]; //cell.textLabel.font = [UIFont fontWithName:@"Bradley Hand Bold" size:[UIFont labelFontSize]]; cell.textLabel.textAlignment = (IS_IPAD()) ? UITextAlignmentCenter : UITextAlignmentLeft; cell.textLabel.backgroundColor = [UIColor clearColor]; cell.textLabel.adjustsFontSizeToFitWidth = YES; - cell.detailTextLabel.text = (IS_IPAD()) ? nil : [self.listOfDescriptions objectAtIndex:row]; + cell.detailTextLabel.text = (IS_IPAD()) ? nil : self.dictOfMissions[missionID][@"desc"]; cell.detailTextLabel.textColor = [UIColor whiteColor]; cell.detailTextLabel.backgroundColor = [UIColor clearColor]; cell.detailTextLabel.adjustsFontSizeToFitWidth = YES; cell.detailTextLabel.numberOfLines = ([cell.detailTextLabel.text length] % 40); cell.detailTextLabel.baselineAdjustment = UIBaselineAdjustmentAlignCenters; + UIView *bgColorView = [[UIView alloc] init]; + bgColorView.backgroundColor = [UIColor colorWithRed:(85.0/255.0) green:(15.0/255.0) blue:(106.0/255.0) alpha:1.0]; + bgColorView.layer.masksToBounds = YES; + cell.selectedBackgroundView = bgColorView; + [bgColorView release]; + cell.backgroundColor = [UIColor blackColorTransparent]; return cell; } @@ -150,7 +251,7 @@ -(void) tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { NSInteger row = [indexPath row]; - self.missionName = [[self.listOfMissions objectAtIndex:row] stringByDeletingPathExtension]; + self.missionName = [self.listOfMissionIDs objectAtIndex:row]; NSString *size = IS_IPAD() ? @"@2x" : @""; NSString *filePath = [[NSString alloc] initWithFormat:@"%@/Missions/Training/%@%@.png",GRAPHICS_DIRECTORY(),self.missionName,size]; UIImage *img = [[UIImage alloc] initWithContentsOfFile:filePath]; @@ -158,24 +259,27 @@ [self.previewImage setImage:img]; [img release]; - self.descriptionLabel.text = [self.listOfDescriptions objectAtIndex:row]; + self.descriptionLabel.text = self.dictOfMissions[self.missionName][@"desc"]; } #pragma mark - #pragma mark Memory management --(void) didReceiveMemoryWarning { + +-(void) didReceiveMemoryWarning +{ self.previewImage = nil; self.missionName = nil; - self.listOfMissions = nil; - self.listOfDescriptions = nil; + self.listOfMissionIDs = nil; + self.dictOfMissions = nil; // if you nil this one it won't get updated anymore //self.previewImage = nil; [super didReceiveMemoryWarning]; } --(void) viewDidUnload { - self.listOfMissions = nil; - self.listOfDescriptions = nil; +-(void) viewDidUnload +{ + self.listOfMissionIDs = nil; + self.dictOfMissions = nil; self.previewImage = nil; self.tableView = nil; self.descriptionLabel = nil; @@ -185,13 +289,14 @@ } --(void) dealloc { - releaseAndNil(listOfMissions); - releaseAndNil(listOfDescriptions); - releaseAndNil(previewImage); - releaseAndNil(tableView); - releaseAndNil(descriptionLabel); - releaseAndNil(missionName); +-(void) dealloc +{ + releaseAndNil(_listOfMissionIDs); + releaseAndNil(_dictOfMissions); + releaseAndNil(_previewImage); + releaseAndNil(_tableView); + releaseAndNil(_descriptionLabel); + releaseAndNil(_missionName); [super dealloc]; } diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/ObjcExports.h --- a/project_files/HedgewarsMobile/Classes/ObjcExports.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/ObjcExports.h Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/ObjcExports.m --- a/project_files/HedgewarsMobile/Classes/ObjcExports.m Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/ObjcExports.m Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/PascalImports.h --- a/project_files/HedgewarsMobile/Classes/PascalImports.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/PascalImports.h Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ @@ -28,9 +28,8 @@ * that you want to use in your non-Pascal code */ - void Game(const int argc, const char *argv[]); - void GenLandPreview(void); - void LoadLocaleWrapper(const char *filename); + void RunEngine(const int argc, const char *argv[]); + void LoadLocaleWrapper(const char *filepath, const char *filename); void HW_versionInfo(int *protoNum, char **versionStr); void *HW_getSDLWindow(void); diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/RestoreViewController-iPad.xib --- a/project_files/HedgewarsMobile/Classes/RestoreViewController-iPad.xib Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/RestoreViewController-iPad.xib Tue Nov 10 20:43:13 2015 +0100 @@ -1,654 +1,92 @@ - - - - 1056 - 10K549 - 823 - 1038.36 - 461.00 - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - 132 - - - YES - - - - YES - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - YES - - YES - - - YES - - - - YES - - IBFilesOwner - IBIPadFramework - - - IBFirstResponder - IBIPadFramework - - - - 274 - - YES - - - 319 - {540, 640} - - NO - IBIPadFramework - - NSImage - smallerBackground~ipad.png - - - - - 302 - {{84, 517}, {151, 37}} - - NO - IBIPadFramework - 0 - 0 - - Helvetica-Bold - 15 - 16 - - 1 - Dismiss - - 3 - MQA - - - 1 - MCAwIDAuNTAxOTYwODE0AA - - - 3 - MC41AA - - - - - 299 - {{308, 517}, {151, 37}} - - NO - 1 - IBIPadFramework - 0 - 0 - - 1 - Restore - - - - - - - 295 - {{216, 35}, {108, 29}} - - NO - YES - 7 - NO - IBIPadFramework - Hmm... - - Helvetica-Bold - 24 - 16 - - - 2 - MSAwLjc4MDM5MjIyOTYgMAA - - - 1 - 10 - 1 - - - - 282 - {{80, 375}, {380, 96}} - - NO - YES - 7 - NO - IBIPadFramework - Would you like to restore it? - - Helvetica - 18 - 16 - - - 1 - MC45MDE5NjA3OTAyIDAuOTAxOTYwNzkwMiAwLjkwMTk2MDc5MDIAA - - - 1 - 10 - 4 - 1 - - - - 306 - {{80, 87}, {380, 96}} - - NO - YES - 7 - NO - IBIPadFramework - It appears you didn't complete your last game! - - - 1 - MC45MDE5NjA3OTAyIDAuOTAxOTYwNzkwMiAwLjkwMTk2MDc5MDIAA - - - 1 - 10 - 4 - 1 - - - - 301 - {{150, 191}, {240, 160}} - - NO - IBIPadFramework - - NSImage - denied.png - - - - {540, 640} - - - 4 - - 3 - - IBIPadFramework - - - - - YES - - - view - - - - 3 - - - - buttonReleased: - - - 7 - - 21 - - - - buttonReleased: - - - 7 - - 22 - - - - - YES - - 0 - - - - - - 1 - - - YES - - - - - - - - - - - - -1 - - - File's Owner - - - -2 - - - - - 15 - - - - - 16 - - - - - 18 - - - - - 19 - - - - - 20 - - - - - 23 - - - - - 24 - - - - - - - YES - - YES - -1.CustomClassName - -2.CustomClassName - 1.IBEditorWindowLastContentRect - 1.IBPluginDependency - 15.IBPluginDependency - 15.IBViewBoundsToFrameTransform - 16.IBPluginDependency - 16.IBViewBoundsToFrameTransform - 18.IBPluginDependency - 18.IBViewBoundsToFrameTransform - 19.IBPluginDependency - 19.IBViewBoundsToFrameTransform - 20.IBPluginDependency - 20.IBViewBoundsToFrameTransform - 23.IBPluginDependency - 23.IBViewBoundsToFrameTransform - 24.IBPluginDependency - 24.IBViewBoundsToFrameTransform - - - YES - RestoreViewController - UIResponder - {{650, 289}, {540, 640}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDlIAAw2gAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABEAkAAw2gAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDXAAAw3UAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUKgAABDmYAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDFgAAw8cAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABCoAAAw9uAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - - - YES - - - YES - - - - - YES - - - YES - - - - 24 - - - - YES - - RestoreViewController - UIViewController - - buttonReleased: - id - - - buttonReleased: - - buttonReleased: - id - - - - IBProjectSource - Classes/RestoreViewController.h - - - - UILabel - - IBProjectSource - Classes/ExtraCategories.h - - - - - YES - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSError.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSFileManager.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueCoding.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueObserving.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyedArchiver.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSObject.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSRunLoop.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSThread.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURL.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURLConnection.h - - - - NSObject - - IBFrameworkSource - QuartzCore.framework/Headers/CAAnimation.h - - - - NSObject - - IBFrameworkSource - QuartzCore.framework/Headers/CALayer.h - - - - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UIAccessibility.h - - - - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UINibLoading.h - - - - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UIResponder.h - - - - UIButton - UIControl - - IBFrameworkSource - UIKit.framework/Headers/UIButton.h - - - - UIControl - UIView - - IBFrameworkSource - UIKit.framework/Headers/UIControl.h - - - - UIImageView - UIView - - IBFrameworkSource - UIKit.framework/Headers/UIImageView.h - - - - UILabel - UIView - - IBFrameworkSource - UIKit.framework/Headers/UILabel.h - - - - UIResponder - NSObject - - - - UISearchBar - UIView - - IBFrameworkSource - UIKit.framework/Headers/UISearchBar.h - - - - UISearchDisplayController - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UISearchDisplayController.h - - - - UIView - - IBFrameworkSource - UIKit.framework/Headers/UIPrintFormatter.h - - - - UIView - - IBFrameworkSource - UIKit.framework/Headers/UITextField.h - - - - UIView - UIResponder - - IBFrameworkSource - UIKit.framework/Headers/UIView.h - - - - UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UINavigationController.h - - - - UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UIPopoverController.h - - - - UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UISplitViewController.h - - - - UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UITabBarController.h - - - - UIViewController - UIResponder - - IBFrameworkSource - UIKit.framework/Headers/UIViewController.h - - - - - 0 - IBIPadFramework - - com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS - - - - com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 - - - YES - ../Hedgewars.xcodeproj - 3 - - YES - - YES - denied.png - smallerBackground~ipad.png - - - YES - {240, 160} - {540, 640} - - - 132 - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/RestoreViewController-iPhone.xib --- a/project_files/HedgewarsMobile/Classes/RestoreViewController-iPhone.xib Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/RestoreViewController-iPhone.xib Tue Nov 10 20:43:13 2015 +0100 @@ -1,620 +1,93 @@ - - - - 1056 - 10K549 - 823 - 1038.36 - 461.00 - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - 132 - - - YES - - - - YES - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - YES - - YES - - - YES - - - - YES - - IBFilesOwner - IBCocoaTouchFramework - - - IBFirstResponder - IBCocoaTouchFramework - - - - 274 - - YES - - - 319 - {480, 320} - - NO - IBCocoaTouchFramework - - NSImage - smallerBackground~iphone.png - - - - - 300 - {{20, 20}, {240, 160}} - - NO - IBCocoaTouchFramework - - NSImage - denied.png - - - - - 315 - {{310, 32}, {108, 29}} - - NO - YES - 7 - NO - IBCocoaTouchFramework - Hmm... - - Helvetica-Bold - 24 - 16 - - - 2 - MSAwLjgyNzQ1MTA1MDMgMAA - - - 3 - MQA - - 1 - 10 - 1 - - - - 307 - {{268, 74}, {192, 96}} - - NO - YES - 7 - NO - IBCocoaTouchFramework - It appears you didn't complete your last game! Would you like to restore it? - - Helvetica - 18 - 16 - - - 1 - MC45MDE5NjA3OTAyIDAuOTAxOTYwNzkwMiAwLjkwMTk2MDc5MDIAA - - - 1 - 10 - 4 - 1 - - - - 302 - {{53, 229}, {151, 37}} - - NO - IBCocoaTouchFramework - 0 - 0 - - Helvetica-Bold - 15 - 16 - - 1 - Dismiss - - - 1 - MCAwIDAuNTAxOTYwODE0AA - - - 3 - MC41AA - - - - - 299 - {{277, 229}, {151, 37}} - - NO - 1 - IBCocoaTouchFramework - 0 - 0 - - 1 - Restore - - - - - - {480, 320} - - - 4 - - 3 - - IBCocoaTouchFramework - - - - - YES - - - view - - - - 3 - - - - buttonReleased: - - - 7 - - 11 - - - - buttonReleased: - - - 7 - - 12 - - - - - YES - - 0 - - - - - - 1 - - - YES - - - - - - - - - - - -1 - - - File's Owner - - - -2 - - - - - 5 - - - - - 6 - - - - - 7 - - - - - 8 - - - - - 10 - - - - - 15 - - - - - - - YES - - YES - -1.CustomClassName - -2.CustomClassName - 1.IBEditorWindowLastContentRect - 1.IBPluginDependency - 10.IBPluginDependency - 10.IBViewBoundsToFrameTransform - 15.IBPluginDependency - 15.IBViewBoundsToFrameTransform - 5.IBPluginDependency - 5.IBViewBoundsToFrameTransform - 6.IBPluginDependency - 6.IBViewBoundsToFrameTransform - 7.IBPluginDependency - 7.IBViewBoundsToFrameTransform - 8.IBPluginDependency - 8.IBViewBoundsToFrameTransform - - - YES - RestoreViewController - UIResponder - {{206, 423}, {480, 320}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUOKgABDZQAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUGgAABBoAAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUObAABCAAAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUOGAABClAAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUJUAABDZQAAA - - - - - YES - - - YES - - - - - YES - - - YES - - - - 15 - - - - YES - - RestoreViewController - UIViewController - - buttonReleased: - id - - - buttonReleased: - - buttonReleased: - id - - - - IBProjectSource - Classes/RestoreViewController.h - - - - UILabel - - IBProjectSource - Classes/ExtraCategories.h - - - - - YES - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSError.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSFileManager.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueCoding.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueObserving.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyedArchiver.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSObject.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSRunLoop.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSThread.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURL.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURLConnection.h - - - - NSObject - - IBFrameworkSource - QuartzCore.framework/Headers/CAAnimation.h - - - - NSObject - - IBFrameworkSource - QuartzCore.framework/Headers/CALayer.h - - - - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UIAccessibility.h - - - - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UINibLoading.h - - - - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UIResponder.h - - - - UIButton - UIControl - - IBFrameworkSource - UIKit.framework/Headers/UIButton.h - - - - UIControl - UIView - - IBFrameworkSource - UIKit.framework/Headers/UIControl.h - - - - UIImageView - UIView - - IBFrameworkSource - UIKit.framework/Headers/UIImageView.h - - - - UILabel - UIView - - IBFrameworkSource - UIKit.framework/Headers/UILabel.h - - - - UIResponder - NSObject - - - - UISearchBar - UIView - - IBFrameworkSource - UIKit.framework/Headers/UISearchBar.h - - - - UISearchDisplayController - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UISearchDisplayController.h - - - - UIView - - IBFrameworkSource - UIKit.framework/Headers/UIPrintFormatter.h - - - - UIView - - IBFrameworkSource - UIKit.framework/Headers/UITextField.h - - - - UIView - UIResponder - - IBFrameworkSource - UIKit.framework/Headers/UIView.h - - - - UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UINavigationController.h - - - - UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UIPopoverController.h - - - - UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UISplitViewController.h - - - - UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UITabBarController.h - - - - UIViewController - UIResponder - - IBFrameworkSource - UIKit.framework/Headers/UIViewController.h - - - - - 0 - IBCocoaTouchFramework - - com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS - - - - com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 - - - YES - ../Hedgewars.xcodeproj - 3 - - YES - - YES - denied.png - smallerBackground~iphone.png - - - YES - {240, 160} - {480, 320} - - - 132 - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/RestoreViewController.h --- a/project_files/HedgewarsMobile/Classes/RestoreViewController.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/RestoreViewController.h Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/RestoreViewController.m --- a/project_files/HedgewarsMobile/Classes/RestoreViewController.m Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/RestoreViewController.m Tue Nov 10 20:43:13 2015 +0100 @@ -13,13 +13,18 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ #import "RestoreViewController.h" #import "GameInterfaceBridge.h" +@interface RestoreViewController () +@property (retain, nonatomic) IBOutlet UIButton *restoreButton; +@property (retain, nonatomic) IBOutlet UIButton *dismissButton; +@end + @implementation RestoreViewController -(BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { @@ -32,18 +37,31 @@ if (theButton.tag != 0) { [[AudioManagerController mainManager] playClickSound]; - [GameInterfaceBridge registerCallingController:self.parentViewController]; - [GameInterfaceBridge startSaveGame:[[NSUserDefaults standardUserDefaults] objectForKey:@"savedGamePath"]]; + [GameInterfaceBridge registerCallingController:self.presentingViewController]; + + // Since iOS 8, the file system layout of app containers has changed. + // So, we must rely now on saved game filename, not full path. + NSString *oldSavedGamePath = [[NSUserDefaults standardUserDefaults] objectForKey:@"savedGamePath"]; + NSString *savedGameFile = [oldSavedGamePath lastPathComponent]; + NSString *newSavedGamePath = [NSString stringWithFormat:@"%@%@", SAVES_DIRECTORY(), savedGameFile]; + + [GameInterfaceBridge startSaveGame:newSavedGamePath]; } else { [[AudioManagerController mainManager] playBackSound]; [defaults setObject:@"" forKey:@"savedGamePath"]; [defaults synchronize]; } - [self.parentViewController dismissModalViewControllerAnimated:YES]; + [self.presentingViewController dismissViewControllerAnimated:YES completion:nil]; } -(void) viewDidLoad { [super viewDidLoad]; + + [self.restoreButton setTitle:NSLocalizedString(@"Restore", nil) forState:UIControlStateNormal]; + [self.dismissButton setTitle:NSLocalizedString(@"Dismiss", nil) forState:UIControlStateNormal]; + + [self.restoreButton applyDarkBlueQuickStyle]; + [self.dismissButton applyDarkBlueQuickStyle]; } -(void) didReceiveMemoryWarning { @@ -55,6 +73,8 @@ } -(void) dealloc { + [_restoreButton release]; + [_dismissButton release]; [super dealloc]; } diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/SavedGamesViewController.h --- a/project_files/HedgewarsMobile/Classes/SavedGamesViewController.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/SavedGamesViewController.h Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ @@ -24,12 +24,10 @@ EditableCellViewDelegate, UIActionSheetDelegate> { UITableView *tableView; NSMutableArray *listOfSavegames; - NSInteger numberOfItems; } @property (nonatomic,retain) IBOutlet UITableView *tableView; @property (nonatomic,retain) NSMutableArray *listOfSavegames; -@property (assign) NSInteger numberOfItems; -(IBAction) buttonPressed:(id) sender; diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/SavedGamesViewController.m --- a/project_files/HedgewarsMobile/Classes/SavedGamesViewController.m Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/SavedGamesViewController.m Tue Nov 10 20:43:13 2015 +0100 @@ -13,16 +13,19 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ #import "SavedGamesViewController.h" #import "GameInterfaceBridge.h" +@interface SavedGamesViewController () +@property (retain, nonatomic) IBOutlet UIBarButtonItem *clearAllButton; +@end @implementation SavedGamesViewController -@synthesize tableView, listOfSavegames, numberOfItems; +@synthesize tableView, listOfSavegames; -(BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation) interfaceOrientation { return rotationManager(interfaceOrientation); @@ -33,12 +36,14 @@ NSMutableArray *array = [[NSMutableArray alloc] initWithArray:contentsOfDir copyItems:YES]; self.listOfSavegames = array; [array release]; - self.numberOfItems = [self.listOfSavegames count]; [self.tableView reloadData]; } --(void) viewDidLoad { +-(void) viewDidLoad +{ + [super viewDidLoad]; + [self.tableView setBackgroundColorForAnyTable:[UIColor clearColor]]; NSString *imgName = (IS_IPAD()) ? @"mediumBackground~ipad.png" : @"smallerBackground~iphone.png"; @@ -49,10 +54,11 @@ background.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; [self.view insertSubview:background atIndex:0]; [background release]; - + + [self.clearAllButton setTitle:NSLocalizedString(@"Clear All", nil)]; + if (self.listOfSavegames == nil) [self updateTable]; - [super viewDidLoad]; } -(void) viewWillAppear:(BOOL)animated { @@ -68,7 +74,7 @@ if (button.tag == 0) { [[AudioManagerController mainManager] playBackSound]; [self.tableView setEditing:NO animated:YES]; - [[self parentViewController] dismissModalViewControllerAnimated:YES]; + [[self presentingViewController] dismissViewControllerAnimated:YES completion:nil]; } else { NSString *titleStr, *cancelStr, *confirmStr; titleStr = NSLocalizedString(@"Are you reeeeeally sure?", @""); @@ -96,13 +102,12 @@ [[NSFileManager defaultManager] createDirectoryAtPath:SAVES_DIRECTORY() withIntermediateDirectories:NO attributes:nil error:NULL]; // update the table and the cached list - NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:self.numberOfItems]; - for (int i = 0; i < self.numberOfItems; i++) + NSMutableArray *array = [[NSMutableArray alloc] init]; + for (int i = 0; i < [self.listOfSavegames count]; i++) [array addObject:[NSIndexPath indexPathForRow:i inSection:0]]; - self.numberOfItems = 0; + [self.listOfSavegames removeAllObjects]; + [self.tableView deleteRowsAtIndexPaths:array withRowAnimation:UITableViewRowAnimationTop]; - [self.listOfSavegames removeAllObjects]; - [array release]; } } @@ -114,20 +119,19 @@ } -(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - return self.numberOfItems; + return [self.listOfSavegames count]; } -(UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Cell"; - if (self.listOfSavegames == nil) - [self updateTable]; EditableCellView *editableCell = (EditableCellView *)[aTableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (editableCell == nil) { editableCell = [[[EditableCellView alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; - editableCell.delegate = self; + editableCell.delegate = nil; + editableCell.textField.userInteractionEnabled = NO; } - editableCell.respectEditing = YES; + editableCell.tag = [indexPath row]; editableCell.textField.text = [[self.listOfSavegames objectAtIndex:[indexPath row]] stringByDeletingPathExtension]; editableCell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; @@ -158,13 +162,29 @@ -(void) tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { [(EditableCellView *)[self.tableView cellForRowAtIndexPath:indexPath] save:nil]; - self.numberOfItems--; - [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationLeft]; + [self fixTagsForStartTag:[indexPath row]]; NSString *saveName = [self.listOfSavegames objectAtIndex:[indexPath row]]; NSString *filePath = [NSString stringWithFormat:@"%@/%@",SAVES_DIRECTORY(),saveName]; [[NSFileManager defaultManager] removeItemAtPath:filePath error:nil]; [self.listOfSavegames removeObject:saveName]; + + [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationLeft]; +} + +#pragma mark - Fix cells' tags + +- (void)fixTagsForStartTag:(NSInteger)tag +{ + for (UITableViewCell *cell in self.tableView.visibleCells) + { + NSInteger oldTag = cell.tag; + + if (oldTag > tag) + { + cell.tag--; + } + } } #pragma mark - @@ -187,7 +207,6 @@ [[NSFileManager defaultManager] copyItemAtPath:currentFilePath toPath:newFilePath error:nil]; [newFilePath release]; - self.numberOfItems++; [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone]; [GameInterfaceBridge registerCallingController:self]; @@ -229,6 +248,7 @@ -(void) dealloc { releaseAndNil(tableView); releaseAndNil(listOfSavegames); + releaseAndNil(_clearAllButton); [super dealloc]; } diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/SavedGamesViewController.xib --- a/project_files/HedgewarsMobile/Classes/SavedGamesViewController.xib Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/SavedGamesViewController.xib Tue Nov 10 20:43:13 2015 +0100 @@ -1,553 +1,56 @@ - - - - 1056 - 10K549 - 823 - 1038.36 - 461.00 - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - 132 - - - YES - - - - YES - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - YES - - YES - - - YES - - - - YES - - IBFilesOwner - IBIPadFramework - - - IBFirstResponder - IBIPadFramework - - - - 292 - - YES - - - 290 - {768, 44} - - NO - 458912 - IBIPadFramework - - YES - - IBIPadFramework - 1 - - 0 - - - IBIPadFramework - - 5 - - - 1 - Clear All - IBIPadFramework - 1 - - - - - - - 274 - {{0, 44}, {768, 724}} - - - 3 - MCAwAA - - YES - IBIPadFramework - YES - 1 - 2 - 0 - YES - 44 - 10 - 10 - - - {768, 768} - - - 3 - MQA - - NO - - 3 - - IBIPadFramework - - - - - YES - - - view - - - - 3 - - - - buttonPressed: - - - - 6 - - - - dataSource - - - - 8 - - - - delegate - - - - 9 - - - - tableView - - - - 10 - - - - buttonPressed: - - - - 17 - - - - - YES - - 0 - - - - - - -1 - - - File's Owner - - - -2 - - - - - 2 - - - YES - - - - - - - 4 - - - YES - - - - - - - - 5 - - - - - 7 - - - - - 13 - - - - - 15 - - - - - - - YES - - YES - -1.CustomClassName - -2.CustomClassName - 13.IBPluginDependency - 15.IBPluginDependency - 2.IBEditorWindowLastContentRect - 2.IBPluginDependency - 4.IBPluginDependency - 5.IBPluginDependency - 7.IBPluginDependency - - - YES - SavedGamesViewController - UIResponder - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - {{467, 276}, {768, 768}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - - YES - - - YES - - - - - YES - - - YES - - - - 17 - - - - YES - - SavedGamesViewController - UIViewController - - buttonPressed: - id - - - buttonPressed: - - buttonPressed: - id - - - - tableView - UITableView - - - tableView - - tableView - UITableView - - - - IBProjectSource - Classes/SavedGamesViewController.h - - - - UITableView - - IBProjectSource - Classes/ExtraCategories.h - - - - - YES - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSError.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSFileManager.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueCoding.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueObserving.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyedArchiver.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSObject.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSRunLoop.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSThread.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURL.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURLConnection.h - - - - NSObject - - IBFrameworkSource - QuartzCore.framework/Headers/CAAnimation.h - - - - NSObject - - IBFrameworkSource - QuartzCore.framework/Headers/CALayer.h - - - - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UIAccessibility.h - - - - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UINibLoading.h - - - - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UIResponder.h - - - - UIBarButtonItem - UIBarItem - - IBFrameworkSource - UIKit.framework/Headers/UIBarButtonItem.h - - - - UIBarItem - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UIBarItem.h - - - - UIResponder - NSObject - - - - UIScrollView - UIView - - IBFrameworkSource - UIKit.framework/Headers/UIScrollView.h - - - - UISearchBar - UIView - - IBFrameworkSource - UIKit.framework/Headers/UISearchBar.h - - - - UISearchDisplayController - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UISearchDisplayController.h - - - - UITableView - UIScrollView - - IBFrameworkSource - UIKit.framework/Headers/UITableView.h - - - - UIToolbar - UIView - - IBFrameworkSource - UIKit.framework/Headers/UIToolbar.h - - - - UIView - - IBFrameworkSource - UIKit.framework/Headers/UIPrintFormatter.h - - - - UIView - - IBFrameworkSource - UIKit.framework/Headers/UITextField.h - - - - UIView - UIResponder - - IBFrameworkSource - UIKit.framework/Headers/UIView.h - - - - UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UINavigationController.h - - - - UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UIPopoverController.h - - - - UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UISplitViewController.h - - - - UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UITabBarController.h - - - - UIViewController - UIResponder - - IBFrameworkSource - UIKit.framework/Headers/UIViewController.h - - - - - 0 - IBIPadFramework - - com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS - - - - com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 - - - YES - ../Hedgewars.xcodeproj - 3 - 132 - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/SchemeSettingsViewController.h --- a/project_files/HedgewarsMobile/Classes/SchemeSettingsViewController.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/SchemeSettingsViewController.h Tue Nov 10 20:43:13 2015 +0100 @@ -13,18 +13,15 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ #import - - -@class SingleSchemeViewController; +#import "TableViewControllerWithDoneButton.h" -@interface SchemeSettingsViewController : UITableViewController { +@interface SchemeSettingsViewController : TableViewControllerWithDoneButton { NSMutableArray *listOfSchemes; - SingleSchemeViewController *childController; } @property (nonatomic, retain) NSMutableArray *listOfSchemes; diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/SchemeSettingsViewController.m --- a/project_files/HedgewarsMobile/Classes/SchemeSettingsViewController.m Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/SchemeSettingsViewController.m Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ @@ -40,7 +40,7 @@ self.navigationItem.rightBarButtonItem = editButton; [editButton release]; - self.navigationItem.title = @"List of schemes"; + self.navigationItem.title = NSLocalizedString(@"List of schemes", nil); } -(void) viewWillAppear:(BOOL) animated { @@ -131,43 +131,43 @@ #pragma mark - #pragma mark Table view delegate --(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - if (childController == nil) { - childController = [[SingleSchemeViewController alloc] initWithStyle:UITableViewStyleGrouped]; - } - +-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath +{ + SingleSchemeViewController *singleSchemeViewController = [[SingleSchemeViewController alloc] initWithStyle:UITableViewStyleGrouped]; + NSInteger row = [indexPath row]; NSString *selectedSchemeFile = [self.listOfSchemes objectAtIndex:row]; // this must be set so childController can load the correct plist - childController.schemeName = [selectedSchemeFile stringByDeletingPathExtension]; - [childController.tableView setContentOffset:CGPointMake(0,0) animated:NO]; + singleSchemeViewController.schemeName = [selectedSchemeFile stringByDeletingPathExtension]; + [singleSchemeViewController.tableView setContentOffset:CGPointMake(0,0) animated:NO]; - [self.navigationController pushViewController:childController animated:YES]; + [self.navigationController pushViewController:singleSchemeViewController animated:YES]; + [singleSchemeViewController release]; + [tableView deselectRowAtIndexPath:indexPath animated:YES]; } #pragma mark - #pragma mark Memory management --(void)didReceiveMemoryWarning { +-(void)didReceiveMemoryWarning +{ [super didReceiveMemoryWarning]; - if (childController.view.superview == nil ) - childController = nil; MSG_MEMCLEAN(); } --(void) viewDidUnload { +-(void) viewDidUnload +{ self.listOfSchemes = nil; - childController = nil; MSG_DIDUNLOAD(); [super viewDidUnload]; } --(void) dealloc { +-(void) dealloc +{ releaseAndNil(listOfSchemes); - releaseAndNil(childController); [super dealloc]; } diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/SchemeWeaponConfigViewController.h --- a/project_files/HedgewarsMobile/Classes/SchemeWeaponConfigViewController.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/SchemeWeaponConfigViewController.h Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/SchemeWeaponConfigViewController.m --- a/project_files/HedgewarsMobile/Classes/SchemeWeaponConfigViewController.m Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/SchemeWeaponConfigViewController.m Tue Nov 10 20:43:13 2015 +0100 @@ -13,13 +13,14 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ #import "SchemeWeaponConfigViewController.h" #import +#define DISABLED_GAME_STYLES @[@"Frenzy.lua", @"Gravity.lua", @"HedgeEditor.lua", @"Continental_supplies.lua", @"Space_Invasion.lua", @"Tumbler.lua"] #define LABEL_TAG 57423 #define TABLE_TAG 45657 @@ -48,7 +49,7 @@ -(NSString *)selectedScript { if (selectedScript == nil) - self.selectedScript = @"Normal.plist"; + self.selectedScript = @""; return selectedScript; } @@ -73,7 +74,7 @@ -(NSArray *)listOfScripts { if (listOfScripts == nil) self.listOfScripts = [[[NSFileManager defaultManager] contentsOfDirectoryAtPath:SCRIPTS_DIRECTORY() error:NULL] - filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"SELF ENDSWITH '.lua'"]]; + filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"SELF ENDSWITH '.lua' AND NOT (SELF IN %@)", DISABLED_GAME_STYLES]]; return listOfScripts; } @@ -125,6 +126,8 @@ } else { UIImage *backgroundImage = [[UIImage alloc] initWithContentsOfFile:@"background~iphone.png"]; UIImageView *background = [[UIImageView alloc] initWithImage:backgroundImage]; + background.contentMode = UIViewContentModeScaleAspectFill; + background.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; [backgroundImage release]; [self.view addSubview:background]; [background release]; @@ -164,7 +167,7 @@ else if (self.topControl.selectedSegmentIndex == 1) return [self.listOfWeapons count]; else - return [self.listOfScripts count]; + return [self.listOfScripts count] + 1; // +1 for fake 'Normal' } // Customize the appearance of table view cells. @@ -203,14 +206,31 @@ self.lastIndexPath_we = indexPath; } } else { - 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; - [checkbox release]; - self.lastIndexPath_lu = indexPath; + if (row == 0) + { + cell.textLabel.text = @"Normal"; + + if ([self.selectedScript isEqualToString:@""]) + { + UIImageView *checkbox = [[UIImageView alloc] initWithImage:[UIImage imageWithContentsOfFile:@"checkbox.png"]]; + cell.accessoryView = checkbox; + [checkbox release]; + self.lastIndexPath_lu = indexPath; + } + } + else + { + row--; + + 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; + [checkbox release]; + self.lastIndexPath_lu = indexPath; + } } } @@ -276,8 +296,8 @@ else lastIndexPath = self.lastIndexPath_lu; - int newRow = [indexPath row]; - int oldRow = (lastIndexPath != nil) ? [lastIndexPath row] : -1; + NSInteger newRow = [indexPath row]; + NSInteger oldRow = (lastIndexPath != nil) ? [lastIndexPath row] : -1; if (newRow != oldRow) { //TODO: this code works only for a single section table @@ -297,7 +317,7 @@ if ([[settings objectForKey:@"sync_ws"] boolValue]) { for (NSString *str in self.listOfWeapons) { if ([str isEqualToString:self.selectedScheme]) { - int row = [self.listOfSchemes indexOfObject:str]; + NSInteger row = [self.listOfSchemes indexOfObject:str]; self.selectedWeapon = str; self.lastIndexPath_we = [NSIndexPath indexPathForRow:row inSection:1]; break; @@ -309,32 +329,63 @@ self.selectedWeapon = [self.listOfWeapons objectAtIndex:newRow]; } else { self.lastIndexPath_lu = indexPath; - self.selectedScript = [self.listOfScripts objectAtIndex:newRow]; - - // some styles disable or force the choice of a particular scheme/weaponset - NSString *path = [[NSString alloc] initWithFormat:@"%@/%@.cfg",SCRIPTS_DIRECTORY(),[self.selectedScript stringByDeletingPathExtension]]; - NSString *configFile = [[NSString alloc] initWithContentsOfFile:path]; - [path release]; - 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"]) { + + if (newRow == 0) + { + self.selectedScript = nil; + self.scriptCommand = nil; + self.selectedScheme = @"Default.plist"; - [self.topControl setEnabled:NO forSegmentAtIndex:0]; - } else { - self.selectedScheme = [NSString stringWithFormat:@"%@.plist",scheme]; [self.topControl setEnabled:YES forSegmentAtIndex:0]; + + self.selectedWeapon = @"Default.plist"; + [self.topControl setEnabled:YES forSegmentAtIndex:1]; } - - NSString *weapon = [scriptOptions objectAtIndex:1]; - if ([weapon isEqualToString:@"locked"]) { - self.selectedWeapon = @"Default.plist"; - [self.topControl setEnabled:NO forSegmentAtIndex:1]; - } else { - self.selectedWeapon = [NSString stringWithFormat:@"%@.plist",weapon]; - [self.topControl setEnabled:YES forSegmentAtIndex:1]; + else + { + newRow--; + + self.selectedScript = [self.listOfScripts objectAtIndex:newRow]; + + // some styles disable or force the choice of a particular scheme/weaponset + NSString *path = [[NSString alloc] initWithFormat:@"%@/%@.cfg",SCRIPTS_DIRECTORY(),[self.selectedScript stringByDeletingPathExtension]]; + NSString *configFile = [[NSString alloc] initWithContentsOfFile:path]; + [path release]; + 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 + { + if (scheme && ![scheme isEqualToString:@"*"]) + { + NSString *correctScheme = [scheme stringByReplacingOccurrencesOfString:@"_" withString:@" "]; + self.selectedScheme = [NSString stringWithFormat:@"%@.plist", correctScheme]; + } + [self.topControl setEnabled:YES forSegmentAtIndex:0]; + } + + NSString *weapon = [scriptOptions objectAtIndex:1]; + if ([weapon isEqualToString:@"locked"]) + { + self.selectedWeapon = @"Default.plist"; + [self.topControl setEnabled:NO forSegmentAtIndex:1]; + } + else + { + if (weapon && ![weapon isEqualToString:@"*"]) + { + NSString *correctWeapon = [weapon stringByReplacingOccurrencesOfString:@"_" withString:@" "]; + self.selectedWeapon = [NSString stringWithFormat:@"%@.plist", correctWeapon]; + } + [self.topControl setEnabled:YES forSegmentAtIndex:1]; + } } } @@ -382,16 +433,6 @@ #pragma mark - #pragma mark Memory management -(void) didReceiveMemoryWarning { - if ([HWUtils isGameLaunched]) { - self.lastIndexPath_sc = nil; - self.lastIndexPath_we = nil; - self.lastIndexPath_lu = nil; - self.selectedScheme = nil; - self.selectedWeapon = nil; - self.selectedScript = nil; - self.scriptCommand = nil; - self.topControl = nil; - } self.listOfSchemes = nil; self.listOfWeapons = nil; self.listOfScripts = nil; @@ -400,7 +441,6 @@ } -(void) viewDidUnload { - [[NSNotificationCenter defaultCenter] removeObserver:self]; self.listOfSchemes = nil; self.listOfWeapons = nil; self.listOfScripts = nil; @@ -416,7 +456,9 @@ [super viewDidUnload]; } --(void) dealloc { +-(void) dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self]; releaseAndNil(listOfSchemes); releaseAndNil(listOfWeapons); releaseAndNil(listOfScripts); diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/ServerProtocolNetwork.h --- a/project_files/HedgewarsMobile/Classes/ServerProtocolNetwork.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/ServerProtocolNetwork.h Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/ServerProtocolNetwork.m --- a/project_files/HedgewarsMobile/Classes/ServerProtocolNetwork.m Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/ServerProtocolNetwork.m Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ @@ -69,20 +69,21 @@ #pragma mark Communication layer -(int) sendToServer:(NSString *)command { NSString *message = [[NSString alloc] initWithFormat:@"%@\n\n",command]; - int result = SDLNet_TCP_Send(self.ssd, [message UTF8String], [message length]); + int result = SDLNet_TCP_Send(self.ssd, [message UTF8String], [message lengthOfBytesUsingEncoding:NSUTF8StringEncoding]); [message release]; return result; } -(int) sendToServer:(NSString *)command withArgument:(NSString *)argument { NSString *message = [[NSString alloc] initWithFormat:@"%@\n%@\n\n",command,argument]; - int result = SDLNet_TCP_Send(self.ssd, [message UTF8String], [message length]); + int result = SDLNet_TCP_Send(self.ssd, [message UTF8String], [message lengthOfBytesUsingEncoding:NSUTF8StringEncoding]); [message release]; return result; } -(void) serverProtocol { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + @autoreleasepool { + IPaddress ip; BOOL clientQuit = NO; char *buffer = (char *)malloc(sizeof(char)*BUFFER_SIZE); @@ -206,7 +207,7 @@ SDLNet_TCP_Close(self.ssd); SDLNet_Quit(); - [pool release]; + } } @end diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/SettingsBaseViewController.h --- a/project_files/HedgewarsMobile/Classes/SettingsBaseViewController.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/SettingsBaseViewController.h Tue Nov 10 20:43:13 2015 +0100 @@ -13,35 +13,22 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ #import - -@class GeneralSettingsViewController; -@class TeamSettingsViewController; -@class WeaponSettingsViewController; -@class SchemeSettingsViewController; -@class SupportViewController; - @interface SettingsBaseViewController : UIViewController { UIViewController *targetController; NSArray *controllerNames; NSIndexPath *lastIndexPath; UITabBarController *tabController; - GeneralSettingsViewController *generalSettingsViewController; - TeamSettingsViewController *teamSettingsViewController; - WeaponSettingsViewController *weaponSettingsViewController; - SchemeSettingsViewController *schemeSettingsViewController; - SupportViewController *supportViewController; } @property (nonatomic, retain) UIViewController *targetController; @property (nonatomic, retain) NSArray *controllerNames; @property (nonatomic, retain) NSIndexPath *lastIndexPath; -@property (nonatomic, retain) UITabBarController *tabController; -(void) dismissSplitView; diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/SettingsBaseViewController.m --- a/project_files/HedgewarsMobile/Classes/SettingsBaseViewController.m Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/SettingsBaseViewController.m Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ @@ -26,7 +26,7 @@ @implementation SettingsBaseViewController -@synthesize tabController, targetController, controllerNames, lastIndexPath; +@synthesize targetController, controllerNames, lastIndexPath; -(BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation) interfaceOrientation { return rotationManager(interfaceOrientation); @@ -45,105 +45,40 @@ self.controllerNames = array; [array release]; - UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone - target:self - action:@selector(dismissSplitView)]; - if (IS_IPAD()) { + if (IS_IPAD()) + { // this class gets loaded twice, we tell the difference by looking at targetController - if (self.targetController != nil) { + if (self.targetController != nil) + { UITableView *tableView = [[UITableView alloc] initWithFrame:self.view.frame style:UITableViewStylePlain]; + tableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; tableView.delegate = self; tableView.dataSource = self; [tableView reloadData]; [self.view addSubview:tableView]; [self tableView:tableView didSelectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; [tableView release]; - self.navigationItem.leftBarButtonItem = doneButton; - } - } else { - // this class just loads all controllers and set up tabbar and navigation controllers - NSMutableArray *tabBarNavigationControllers = [[NSMutableArray alloc] initWithCapacity:5]; - UINavigationController *navController = nil; - - if (nil == generalSettingsViewController) { - generalSettingsViewController = [[GeneralSettingsViewController alloc] initWithStyle:UITableViewStyleGrouped]; - generalSettingsViewController.tabBarItem.title = [self.controllerNames objectAtIndex:0]; - generalSettingsViewController.tabBarItem.image = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"%@/TargetBee.png",GRAPHICS_DIRECTORY()]]; - navController = [[UINavigationController alloc] initWithRootViewController:generalSettingsViewController]; - generalSettingsViewController.navigationItem.backBarButtonItem = doneButton; - generalSettingsViewController.navigationItem.leftBarButtonItem = doneButton; - [generalSettingsViewController release]; - [tabBarNavigationControllers addObject:navController]; - releaseAndNil(navController); - } - if (nil == teamSettingsViewController) { - teamSettingsViewController = [[TeamSettingsViewController alloc] initWithStyle:UITableViewStyleGrouped]; - teamSettingsViewController.tabBarItem.title = [self.controllerNames objectAtIndex:1]; - teamSettingsViewController.tabBarItem.image = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"%@/Egg.png",GRAPHICS_DIRECTORY()]]; - navController = [[UINavigationController alloc] initWithRootViewController:teamSettingsViewController]; - teamSettingsViewController.navigationItem.backBarButtonItem = doneButton; - teamSettingsViewController.navigationItem.leftBarButtonItem = doneButton; - [tabBarNavigationControllers addObject:navController]; - releaseAndNil(navController); + self.navigationItem.leftBarButtonItem = [self doneButton]; } - if (nil == weaponSettingsViewController) { - weaponSettingsViewController = [[WeaponSettingsViewController alloc] initWithStyle:UITableViewStyleGrouped]; - weaponSettingsViewController.tabBarItem.title = [self.controllerNames objectAtIndex:2]; - weaponSettingsViewController.tabBarItem.image = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"%@/cheese.png",GRAPHICS_DIRECTORY()]]; - navController = [[UINavigationController alloc] initWithRootViewController:weaponSettingsViewController]; - weaponSettingsViewController.navigationItem.backBarButtonItem = doneButton; - weaponSettingsViewController.navigationItem.leftBarButtonItem = doneButton; - [tabBarNavigationControllers addObject:navController]; - releaseAndNil(navController); - } - if (nil == schemeSettingsViewController) { - schemeSettingsViewController = [[SchemeSettingsViewController alloc] initWithStyle:UITableViewStyleGrouped]; - schemeSettingsViewController.tabBarItem.title = [self.controllerNames objectAtIndex:3]; - schemeSettingsViewController.tabBarItem.image = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"%@/Targetp.png",GRAPHICS_DIRECTORY()]]; - navController = [[UINavigationController alloc] initWithRootViewController:schemeSettingsViewController]; - schemeSettingsViewController.navigationItem.backBarButtonItem = doneButton; - schemeSettingsViewController.navigationItem.leftBarButtonItem = doneButton; - [tabBarNavigationControllers addObject:navController]; - releaseAndNil(navController); - } - if (nil == supportViewController) { - supportViewController = [[SupportViewController alloc] initWithStyle:UITableViewStyleGrouped]; - supportViewController.tabBarItem.title = [self.controllerNames objectAtIndex:4]; - supportViewController.tabBarItem.image = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"%@/Seduction.png",GRAPHICS_DIRECTORY()]]; - navController = [[UINavigationController alloc] initWithRootViewController:supportViewController]; - supportViewController.navigationItem.backBarButtonItem = doneButton; - supportViewController.navigationItem.leftBarButtonItem = doneButton; - [tabBarNavigationControllers addObject:navController]; - releaseAndNil(navController); - } + } + else + { + //iPhone part moved to MainMenuViewController + } - self.tabController = [[UITabBarController alloc] init]; - self.tabController.viewControllers = tabBarNavigationControllers; - self.tabController.delegate = self; - - [self.view addSubview:self.tabController.view]; - } - [doneButton release]; [super viewDidLoad]; } --(void) tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController { - [viewController viewWillAppear:NO]; +- (UIBarButtonItem *)doneButton +{ + return [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone + target:self + action:@selector(dismissSplitView)] autorelease]; } -(void) dismissSplitView { [[AudioManagerController mainManager] playBackSound]; - [[[HedgewarsAppDelegate sharedAppDelegate] mainViewController] dismissModalViewControllerAnimated:YES]; -} - --(void) willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { - if (IS_IPAD() == NO) - return; - - if (self.targetController != nil) { - CGRect screenRect = [[UIScreen mainScreen] safeBounds]; - self.view.frame = CGRectMake(0, 0, 320, screenRect.size.height); - } + [[[HedgewarsAppDelegate sharedAppDelegate] mainViewController] dismissViewControllerAnimated:YES completion:nil]; } #pragma mark - @@ -197,40 +132,33 @@ #pragma mark - #pragma mark Table view delegate --(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - int newRow = [indexPath row]; - int oldRow = (lastIndexPath != nil) ? [lastIndexPath row] : -1; +-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath +{ + NSInteger newRow = [indexPath row]; + NSInteger oldRow = (lastIndexPath != nil) ? [lastIndexPath row] : -1; UIViewController *nextController = nil; - if (newRow != oldRow) { + if (newRow != oldRow) + { [tableView deselectRowAtIndexPath:lastIndexPath animated:YES]; [targetController.navigationController popToRootViewControllerAnimated:NO]; - switch (newRow) { + switch (newRow) + { case 0: - if (nil == generalSettingsViewController) - generalSettingsViewController = [[GeneralSettingsViewController alloc] initWithStyle:UITableViewStyleGrouped]; - nextController = generalSettingsViewController; + nextController = [[GeneralSettingsViewController alloc] initWithStyle:UITableViewStyleGrouped];; break; case 1: - if (nil == teamSettingsViewController) - teamSettingsViewController = [[TeamSettingsViewController alloc] initWithStyle:UITableViewStyleGrouped]; - nextController = teamSettingsViewController; + nextController = [[TeamSettingsViewController alloc] initWithStyle:UITableViewStyleGrouped]; break; case 2: - if (nil == weaponSettingsViewController) - weaponSettingsViewController = [[WeaponSettingsViewController alloc] initWithStyle:UITableViewStyleGrouped]; - nextController = weaponSettingsViewController; + nextController = [[WeaponSettingsViewController alloc] initWithStyle:UITableViewStyleGrouped]; break; case 3: - if (nil == schemeSettingsViewController) - schemeSettingsViewController = [[SchemeSettingsViewController alloc] initWithStyle:UITableViewStyleGrouped]; - nextController = schemeSettingsViewController; + nextController = [[SchemeSettingsViewController alloc] initWithStyle:UITableViewStyleGrouped]; break; case 4: - if (nil == supportViewController) - supportViewController = [[SupportViewController alloc] initWithStyle:UITableViewStyleGrouped]; - nextController = supportViewController; + nextController = [[SupportViewController alloc] initWithStyle:UITableViewStyleGrouped]; break; } @@ -240,6 +168,8 @@ nextController.navigationItem.hidesBackButton = YES; [nextController viewWillAppear:NO]; [targetController.navigationController pushViewController:nextController animated:NO]; + [nextController release]; + [[AudioManagerController mainManager] playClickSound]; } } @@ -247,62 +177,28 @@ #pragma mark - #pragma mark Memory management --(void) didReceiveMemoryWarning { - if (generalSettingsViewController.view.superview == nil) - generalSettingsViewController = nil; - if (teamSettingsViewController.view.superview == nil) - teamSettingsViewController = nil; - if (weaponSettingsViewController.view.superview == nil) - weaponSettingsViewController = nil; - if (schemeSettingsViewController.view.superview == nil) - schemeSettingsViewController = nil; - if (supportViewController.view.superview == nil) - supportViewController = nil; - if (tabController.view.superview == nil) - tabController = nil; +-(void) didReceiveMemoryWarning +{ MSG_MEMCLEAN(); [super didReceiveMemoryWarning]; } --(void) viewDidUnload { +-(void) viewDidUnload +{ self.controllerNames = nil; self.lastIndexPath = nil; self.targetController = nil; - self.tabController = nil; - generalSettingsViewController = nil; - teamSettingsViewController = nil; - weaponSettingsViewController = nil; - schemeSettingsViewController = nil; - supportViewController = nil; MSG_DIDUNLOAD(); [super viewDidUnload]; } --(void) dealloc { +-(void) dealloc +{ releaseAndNil(targetController); releaseAndNil(controllerNames); releaseAndNil(lastIndexPath); - releaseAndNil(tabController); - releaseAndNil(generalSettingsViewController); - releaseAndNil(teamSettingsViewController); - releaseAndNil(weaponSettingsViewController); - releaseAndNil(schemeSettingsViewController); - releaseAndNil(supportViewController); [super dealloc]; } - --(void) viewWillDisappear:(BOOL)animated { - // this will send -viewWillDisappear: only the active view - [self.tabController viewWillDisappear:animated]; - // let's send that to every page, even though only GeneralSettingsViewController needs it - [generalSettingsViewController viewWillDisappear:animated]; - [teamSettingsViewController viewWillDisappear:animated]; - [weaponSettingsViewController viewWillDisappear:animated]; - [schemeSettingsViewController viewWillDisappear:animated]; - [supportViewController viewWillDisappear:animated]; - [super viewWillDisappear:animated]; -} - @end diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/SettingsContainerViewController.h --- a/project_files/HedgewarsMobile/Classes/SettingsContainerViewController.h Tue Nov 10 18:16:35 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -/* - * Hedgewars-iOS, a Hedgewars port for iOS devices - * Copyright (c) 2009-2012 Vittorio Giovara - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - - -#import - - -@class SettingsBaseViewController; -@class MGSplitViewController; - -@interface SettingsContainerViewController : UIViewController { - SettingsBaseViewController *baseController; - MGSplitViewController *splitViewRootController; -} - -@property (nonatomic,retain) SettingsBaseViewController *baseController; -@property (nonatomic,retain) MGSplitViewController *splitViewRootController; - -@end diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/SettingsContainerViewController.m --- a/project_files/HedgewarsMobile/Classes/SettingsContainerViewController.m Tue Nov 10 18:16:35 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,142 +0,0 @@ -/* - * Hedgewars-iOS, a Hedgewars port for iOS devices - * Copyright (c) 2009-2012 Vittorio Giovara - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - - -#import "SettingsContainerViewController.h" -#import "SettingsBaseViewController.h" -#import "MGSplitViewController.h" - - -@implementation SettingsContainerViewController -@synthesize baseController, splitViewRootController; - --(BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { - return rotationManager(interfaceOrientation); -} - --(void) viewDidLoad { - CGRect screenRect = [[UIScreen mainScreen] safeBounds]; - self.view.frame = screenRect; - - if (IS_IPAD()) { - // the contents on the right of the splitview, setting targetController to nil to avoid creating the table - SettingsBaseViewController *rightController = [[SettingsBaseViewController alloc] init]; - rightController.targetController = nil; - UINavigationController *rightNavController = [[UINavigationController alloc] initWithRootViewController:rightController]; - [rightController release]; - - // the contens on the left of the splitview, setting targetController that will receive push/pop actions - SettingsBaseViewController *leftController = [[SettingsBaseViewController alloc] init]; - leftController.targetController = rightNavController.topViewController; - UINavigationController *leftNavController = [[UINavigationController alloc] initWithRootViewController:leftController]; - [leftController release]; - - self.splitViewRootController = [[MGSplitViewController alloc] init]; - self.splitViewRootController.delegate = nil; - self.splitViewRootController.view.frame = screenRect; - self.splitViewRootController.viewControllers = [NSArray arrayWithObjects: leftNavController, rightNavController, nil]; - self.splitViewRootController.showsMasterInPortrait = YES; - [leftNavController release]; - [rightNavController release]; - - // add view to main controller - [self.view addSubview:self.splitViewRootController.view]; - } else { - if (nil == self.baseController) { - SettingsBaseViewController *sbvc = [[SettingsBaseViewController alloc] init]; - self.baseController = sbvc; - [sbvc release]; - } - self.baseController.targetController = nil; - self.baseController.view.frame = screenRect; - - [self.view addSubview:self.baseController.view]; - } - - [super viewDidLoad]; -} - -#pragma mark - -#pragma mark Memory management --(void) didReceiveMemoryWarning { - if (self.baseController.view.superview == nil) - self.baseController = nil; - if (self.splitViewRootController.view.superview == nil) - self.splitViewRootController = nil; - MSG_MEMCLEAN(); - [super didReceiveMemoryWarning]; -} - --(void) viewDidUnload { - self.baseController = nil; - self.splitViewRootController = nil; - MSG_DIDUNLOAD(); - [super viewDidUnload]; -} - --(void) dealloc { - releaseAndNil(baseController); - releaseAndNil(splitViewRootController); - [super dealloc]; -} - - -#pragma mark - -#pragma mark view event management propagation -// every time we add a uiviewcontroller programmatically we need to take care of propgating such messages -// see http://davidebenini.it/2009/01/03/viewwillappear-not-being-called-inside-a-uinavigationcontroller/ --(void) viewWillAppear:(BOOL)animated { - [self.splitViewRootController.detailViewController viewWillAppear:animated]; - [self.baseController viewWillAppear:animated]; - [super viewWillAppear:animated]; -} - --(void) viewWillDisappear:(BOOL)animated { - [self.splitViewRootController.detailViewController viewWillDisappear:animated]; - [self.baseController viewWillDisappear:animated]; - [super viewWillDisappear:animated]; -} - --(void) viewDidAppear:(BOOL)animated { - [self.splitViewRootController.detailViewController viewDidAppear:animated]; - [self.baseController viewDidAppear:animated]; - [super viewDidAppear:animated]; -} - --(void) viewDidDisappear:(BOOL)animated { - [self.splitViewRootController.detailViewController viewDidDisappear:animated]; - [self.baseController viewDidDisappear:animated]; - [super viewDidDisappear:animated]; -} - --(void) willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { - [self.splitViewRootController willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration]; - [self.baseController willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration]; -} - --(void) willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { - [self.splitViewRootController willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration]; - [self.baseController willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration]; -} - --(void) didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation { - [self.splitViewRootController didRotateFromInterfaceOrientation:fromInterfaceOrientation]; - [self.baseController didRotateFromInterfaceOrientation:fromInterfaceOrientation]; -} - -@end diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/SingleSchemeViewController.h --- a/project_files/HedgewarsMobile/Classes/SingleSchemeViewController.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/SingleSchemeViewController.h Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/SingleSchemeViewController.m --- a/project_files/HedgewarsMobile/Classes/SingleSchemeViewController.m Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/SingleSchemeViewController.m Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ @@ -25,18 +25,6 @@ #define SLIDER_TAG 54321 #define SWITCH_TAG 67890 -#define checkValueString(detailString,labelSting,sliderRef); \ - if ([labelSting isEqualToString:@"Turn Time"] && (NSInteger) sliderRef.value == 100) \ - detailString = @"∞"; \ - else if ([labelSting isEqualToString:@"Water Rise Amount"] && (NSInteger) sliderRef.value == 100) \ - detailString = NSLocalizedString(@"Nvr",@"Short for 'Never'"); \ - else if ([labelSting isEqualToString:@"Crate Drop Turns"] && (NSInteger) sliderRef.value == 0) \ - detailString = NSLocalizedString(@"Nvr",@"Short for 'Never'"); \ - else if ([labelSting isEqualToString:@"Mines Time"] && (NSInteger) sliderRef.value == -1) \ - detailString = NSLocalizedString(@"Rnd",@"Short for 'Random'"); \ - else \ - detailString = [NSString stringWithFormat:@"%d",(NSInteger) sliderRef.value]; - @implementation SingleSchemeViewController @synthesize schemeName, schemeDictionary, basicSettingList, gameModifierArray; @@ -190,7 +178,8 @@ [img release]; UILabel *cellLabel = (UILabel *)[cell.contentView viewWithTag:LABEL_TAG]; - cellLabel.text = [[self.basicSettingList objectAtIndex:row] objectForKey:@"title"]; + NSString *basicSettingTitleKey = [[self.basicSettingList objectAtIndex:row] objectForKey:@"title"]; + cellLabel.text = NSLocalizedStringFromTable(basicSettingTitleKey, @"Scheme", nil); cellLabel.adjustsFontSizeToFitWidth = YES; // can't use the viewWithTag method because row is dynamic @@ -220,8 +209,7 @@ } cellSlider.frame = CGRectMake(hOffset, vOffset, sliderLength, 23); - NSString *prestring = nil; - checkValueString(prestring,cellLabel.text,cellSlider); + NSString *prestring = [self localizedValueStringForKey:basicSettingTitleKey andSlider:cellSlider]; // forced to use this weird format otherwise the label disappears when size of the text is bigger than the original while ([prestring length] <= 4) @@ -251,8 +239,10 @@ [image release]; cell.imageView.layer.cornerRadius = 6.0f; cell.imageView.layer.masksToBounds = YES; - cell.textLabel.text = [[self.gameModifierArray objectAtIndex:row] objectForKey:@"title"]; - cell.detailTextLabel.text = [[self.gameModifierArray objectAtIndex:row] objectForKey:@"description"]; + NSString *gameModTitleKey = [[self.gameModifierArray objectAtIndex:row] objectForKey:@"title"]; + cell.textLabel.text = NSLocalizedStringFromTable(gameModTitleKey, @"Scheme", nil); + NSString *gameModDescKey = [[self.gameModifierArray objectAtIndex:row] objectForKey:@"description"]; + cell.detailTextLabel.text = NSLocalizedStringFromTable(gameModDescKey, @"Scheme", nil); cell.detailTextLabel.adjustsFontSizeToFitWidth = YES; cell.detailTextLabel.minimumFontSize = 6; @@ -277,14 +267,14 @@ UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath]; // grab the associated labels UILabel *detailLabel = (UILabel *)cell.detailTextLabel; - UILabel *cellLabel = (UILabel *)[cell.contentView viewWithTag:LABEL_TAG]; // modify it - checkValueString(detailLabel.text,cellLabel.text,theSlider); + NSString *basicSettingTitleKey = [[self.basicSettingList objectAtIndex:[indexPath row]] objectForKey:@"title"]; + detailLabel.text = [self localizedValueStringForKey:basicSettingTitleKey andSlider:theSlider]; // save changes in the main array NSMutableArray *array = [self.schemeDictionary objectForKey:@"basic"]; - [array replaceObjectAtIndex:theSlider.tag-SLIDER_TAG withObject:[NSNumber numberWithInt:(NSInteger) theSlider.value]]; + [array replaceObjectAtIndex:theSlider.tag-SLIDER_TAG withObject:[NSNumber numberWithInteger:theSlider.value]]; } #pragma mark - @@ -345,6 +335,42 @@ return 56; } +#pragma mark - Helper methods + +- (NSString *)localizedValueStringForKey:(NSString *)keyString andSlider:(UISlider *)slider +{ + NSInteger sliderValue = (NSInteger)slider.value; + + if ([keyString isEqualToString:@"Turn Time"] && sliderValue == 100) + return @"∞"; + else if ([keyString isEqualToString:@"Water Rise Amount"] && sliderValue == 100) + return NSLocalizedString(@"Nvr", @"Short for 'Never'"); + else if ([keyString isEqualToString:@"Crate Drop Turns"] && sliderValue == 0) + return NSLocalizedString(@"Nvr", @"Short for 'Never'"); + else if ([keyString isEqualToString:@"Mines Time"] && sliderValue == -1) + return NSLocalizedString(@"Rnd", @"Short for 'Random'"); + else if ([keyString isEqualToString:@"World Edge"]) + switch (sliderValue) + { + case 0: + return NSLocalizedString(@"None", nil); + + case 1: + return NSLocalizedString(@"Wrap", nil); + + case 2: + return NSLocalizedString(@"Bounce", nil); + + case 3: + return NSLocalizedString(@"Sea", nil); + + default: + return @""; + } + else + return [NSString stringWithFormat:@"%ld", (long)sliderValue]; +} + #pragma mark - #pragma mark Memory management -(void) didReceiveMemoryWarning { diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/SingleTeamViewController.h --- a/project_files/HedgewarsMobile/Classes/SingleTeamViewController.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/SingleTeamViewController.h Tue Nov 10 20:43:13 2015 +0100 @@ -13,20 +13,12 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ #import - -@class HogHatViewController; -@class GravesViewController; -@class VoicesViewController; -@class FortsViewController; -@class FlagsViewController; -@class LevelViewController; - @interface SingleTeamViewController : UITableViewController { NSMutableDictionary *teamDictionary; @@ -36,13 +28,6 @@ NSArray *secondaryItems; NSArray *moreSecondaryItems; BOOL isWriteNeeded; - - HogHatViewController *hogHatViewController; - GravesViewController *gravesViewController; - VoicesViewController *voicesViewController; - FortsViewController *fortsViewController; - FlagsViewController *flagsViewController; - LevelViewController *levelViewController; } @property (nonatomic,retain) NSMutableDictionary *teamDictionary; diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/SingleTeamViewController.m --- a/project_files/HedgewarsMobile/Classes/SingleTeamViewController.m Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/SingleTeamViewController.m Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ @@ -146,7 +146,7 @@ rows = 1; break; case 1: // team members - rows = HW_getMaxNumberOfHogs(); + rows = HW_getMaxNumberOfHogs() + 1; // one for 'Select one hat for all hogs' cell break; case 2: // team details rows = [self.secondaryItems count]; @@ -180,6 +180,7 @@ static NSString *CellIdentifier0 = @"Cell0"; static NSString *CellIdentifier1 = @"Cell1"; static NSString *CellIdentifier2 = @"Cell2"; + static NSString *CellIdentifierDefault = @"CellDefault"; NSArray *hogArray; UITableViewCell *cell = nil; @@ -204,13 +205,28 @@ cell = editableCell; break; case 1: + if ([indexPath row] == HW_getMaxNumberOfHogs()) + { + cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifierDefault]; + if (cell == nil) + { + cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault + reuseIdentifier:CellIdentifierDefault] autorelease]; + cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; + } + + cell.textLabel.text = NSLocalizedString(@"Select one hat for all hogs", nil); + + break; + } + editableCell = (EditableCellView *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier1]; if (editableCell == nil) { editableCell = [[[EditableCellView alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier1] autorelease]; editableCell.delegate = self; - editableCell.tag = [indexPath row]; } + editableCell.tag = [indexPath row]; hogArray = [self.teamDictionary objectForKey:@"hedgehogs"]; @@ -290,120 +306,118 @@ NSInteger row = [indexPath row]; NSInteger section = [indexPath section]; - if (2 == section) { - switch (row) { + if (2 == section) + { + switch (row) + { case 0: // grave - if (nil == gravesViewController) - gravesViewController = [[GravesViewController alloc] initWithStyle:UITableViewStyleGrouped]; + { + GravesViewController *gravesViewController = [[GravesViewController alloc] initWithStyle:UITableViewStyleGrouped]; [gravesViewController setTeamDictionary:teamDictionary]; [self.navigationController pushViewController:gravesViewController animated:YES]; + [gravesViewController release]; break; + } case 1: // voice - if (nil == voicesViewController) - voicesViewController = [[VoicesViewController alloc] initWithStyle:UITableViewStyleGrouped]; + { + VoicesViewController *voicesViewController = [[VoicesViewController alloc] initWithStyle:UITableViewStyleGrouped]; [voicesViewController setTeamDictionary:teamDictionary]; [self.navigationController pushViewController:voicesViewController animated:YES]; + [voicesViewController release]; break; + } case 2: // fort - if (nil == fortsViewController) - fortsViewController = [[FortsViewController alloc] initWithStyle:UITableViewStyleGrouped]; + { + FortsViewController *fortsViewController = [[FortsViewController alloc] initWithStyle:UITableViewStyleGrouped]; [fortsViewController setTeamDictionary:teamDictionary]; [self.navigationController pushViewController:fortsViewController animated:YES]; + [fortsViewController release]; break; + } case 3: // flag - if (nil == flagsViewController) - flagsViewController = [[FlagsViewController alloc] initWithStyle:UITableViewStyleGrouped]; + { + FlagsViewController *flagsViewController = [[FlagsViewController alloc] initWithStyle:UITableViewStyleGrouped]; [flagsViewController setTeamDictionary:teamDictionary]; [self.navigationController pushViewController:flagsViewController animated:YES]; + [flagsViewController release]; break; + } case 4: // level - if (nil == levelViewController) - levelViewController = [[LevelViewController alloc] initWithStyle:UITableViewStyleGrouped]; + { + LevelViewController *levelViewController = [[LevelViewController alloc] initWithStyle:UITableViewStyleGrouped]; [levelViewController setTeamDictionary:teamDictionary]; [self.navigationController pushViewController:levelViewController animated:YES]; + [levelViewController release]; break; + } default: DLog(@"Nope"); break; } } else { - EditableCellView *cell = (EditableCellView *)[aTableView cellForRowAtIndexPath:indexPath]; - [cell replyKeyboard]; - [aTableView deselectRowAtIndexPath:indexPath animated:NO]; + if (section == 1 && row == HW_getMaxNumberOfHogs()) { + // 'Select one hat for all hogs' selected + [self showHogHatViewControllerForHogIndex:-1]; + } else { + EditableCellView *cell = (EditableCellView *)[aTableView cellForRowAtIndexPath:indexPath]; + [cell replyKeyboard]; + [aTableView deselectRowAtIndexPath:indexPath animated:NO]; + } } } // action to perform when you want to change a hog hat -(void) tableView:(UITableView *)aTableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath { - if (nil == hogHatViewController) - hogHatViewController = [[HogHatViewController alloc] initWithStyle:UITableViewStyleGrouped]; - - // cache the dictionary file of the team, so that other controllers can modify it - hogHatViewController.teamDictionary = self.teamDictionary; - hogHatViewController.selectedHog = [indexPath row]; - // if we are editing the field undo any change before proceeding EditableCellView *cell = (EditableCellView *)[aTableView cellForRowAtIndexPath:indexPath]; [cell cancel:nil]; - - [self.navigationController pushViewController:hogHatViewController animated:YES]; + + [self showHogHatViewControllerForHogIndex:[indexPath row]]; } +- (void)showHogHatViewControllerForHogIndex:(NSInteger)hogIndex +{ + HogHatViewController *hogHatViewController = [[HogHatViewController alloc] initWithStyle:UITableViewStyleGrouped]; + + // cache the dictionary file of the team, so that other controllers can modify it + hogHatViewController.teamDictionary = self.teamDictionary; + hogHatViewController.selectedHog = hogIndex; + + [self.navigationController pushViewController:hogHatViewController animated:YES]; + [hogHatViewController release]; +} #pragma mark - #pragma mark Memory management -(void) didReceiveMemoryWarning { [super didReceiveMemoryWarning]; - if (hogHatViewController.view.superview == nil) - hogHatViewController = nil; - if (gravesViewController.view.superview == nil) - gravesViewController = nil; - if (voicesViewController.view.superview == nil) - voicesViewController = nil; - if (fortsViewController.view.superview == nil) - fortsViewController = nil; - if (flagsViewController.view.superview == nil) - flagsViewController = nil; - if (levelViewController.view.superview == nil) - levelViewController = nil; MSG_MEMCLEAN(); } -(void) viewDidUnload { - [[NSNotificationCenter defaultCenter] removeObserver:self]; self.teamDictionary = nil; self.teamName = nil; self.normalHogSprite = nil; self.secondaryItems = nil; self.moreSecondaryItems = nil; - hogHatViewController = nil; - gravesViewController = nil; - voicesViewController = nil; - flagsViewController = nil; - fortsViewController = nil; - levelViewController = nil; MSG_DIDUNLOAD(); [super viewDidUnload]; } --(void) dealloc { +-(void) dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self]; releaseAndNil(teamDictionary); releaseAndNil(teamName); releaseAndNil(normalHogSprite); releaseAndNil(secondaryItems); releaseAndNil(moreSecondaryItems); - releaseAndNil(hogHatViewController); - releaseAndNil(gravesViewController); - releaseAndNil(fortsViewController); - releaseAndNil(voicesViewController); - releaseAndNil(flagsViewController); - releaseAndNil(levelViewController); [super dealloc]; } diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/SingleWeaponViewController.h --- a/project_files/HedgewarsMobile/Classes/SingleWeaponViewController.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/SingleWeaponViewController.h Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/SingleWeaponViewController.m --- a/project_files/HedgewarsMobile/Classes/SingleWeaponViewController.m Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/SingleWeaponViewController.m Tue Nov 10 20:43:13 2015 +0100 @@ -13,12 +13,16 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ #import "SingleWeaponViewController.h" +@interface SingleWeaponViewController () +@property (nonatomic, retain) NSString *trPath; +@property (nonatomic, retain) NSString *trFileName; +@end @implementation SingleWeaponViewController @synthesize weaponName, description, ammoStoreImage; @@ -32,9 +36,10 @@ -(void) viewDidLoad { [super viewDidLoad]; - NSString *trFilePath = [NSString stringWithFormat:@"%@/%@.txt",LOCALE_DIRECTORY(),[[NSLocale preferredLanguages] objectAtIndex:0]]; + self.trPath = [NSString stringWithFormat:@"%@", LOCALE_DIRECTORY()]; + self.trFileName = [NSString stringWithFormat:@"%@.txt", [HWUtils languageID]]; // fill the data structure that we are going to read - LoadLocaleWrapper([trFilePath UTF8String]); + LoadLocaleWrapper([self.trPath UTF8String], [self.trFileName UTF8String]); quantity = (char *)malloc(sizeof(char)*(HW_getNumberOfWeapons()+1)); probability = (char *)malloc(sizeof(char)*(HW_getNumberOfWeapons()+1)); @@ -261,6 +266,9 @@ -(void) dealloc { + releaseAndNil(_trPath); + releaseAndNil(_trFileName); + releaseAndNil(weaponName); releaseAndNil(description); releaseAndNil(ammoStoreImage); diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/SquareButtonView.h --- a/project_files/HedgewarsMobile/Classes/SquareButtonView.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/SquareButtonView.h Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/SquareButtonView.m --- a/project_files/HedgewarsMobile/Classes/SquareButtonView.m Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/SquareButtonView.m Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ @@ -61,7 +61,7 @@ -(void) selectColor:(NSUInteger) color { if (color != self.selectedColor) { self.selectedColor = color; - self.colorIndex = [self.colorArray indexOfObject:[NSNumber numberWithUnsignedInt:color]]; + self.colorIndex = [self.colorArray indexOfObject:[NSNumber numberWithUnsignedInteger:color]]; self.backgroundColor = [UIColor colorWithRed:((color & 0x00FF0000) >> 16)/255.0f green:((color & 0x0000FF00) >> 8)/255.0f diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/StatsPageViewController.h --- a/project_files/HedgewarsMobile/Classes/StatsPageViewController.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/StatsPageViewController.h Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/StatsPageViewController.m --- a/project_files/HedgewarsMobile/Classes/StatsPageViewController.m Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/StatsPageViewController.m Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ @@ -29,6 +29,7 @@ -(void) viewDidLoad { UITableView *aTableView = [[UITableView alloc] initWithFrame:self.view.frame style:UITableViewStyleGrouped]; + aTableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; [aTableView setBackgroundColorForAnyTable:[UIColor clearColor]]; NSString *imgName = (IS_IPAD()) ? @"mediumBackground~ipad.png" : @"smallerBackground~iphone.png"; @@ -44,13 +45,29 @@ aTableView.separatorStyle = UITableViewCellSeparatorStyleNone; aTableView.delegate = self; aTableView.dataSource = self; - + + aTableView.rowHeight = 44; + [self.view addSubview:aTableView]; [aTableView release]; [super viewDidLoad]; } +#pragma mark - Helpers + +- (NSString *)teamNameFromInfo: (NSArray *)info +{ + NSString *teamName = [NSString stringWithString:[info objectAtIndex:2]]; + + for (int i=3; i < [info count]; i++) + { + teamName = [teamName stringByAppendingFormat:@" %@", [info objectAtIndex:i]]; + } + + return teamName; +} + #pragma mark - #pragma mark Table view data source -(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView { @@ -90,7 +107,7 @@ green:((color >> 8) & 0xFF)/255.0f blue:(color & 0xFF)/255.0f alpha:1.0f]; - cell.textLabel.text = [NSString stringWithFormat:@"%d. %@ (%@ kills)", row+1, [info objectAtIndex:2], [info objectAtIndex:1]]; + cell.textLabel.text = [NSString stringWithFormat:@"%d. %@ (%@ %@)", row+1, [self teamNameFromInfo:info], [info objectAtIndex:1], NSLocalizedString(@"kills", nil)]; imgName = [NSString stringWithFormat:@"StatsMedal%d",row+1]; } else if (section == 2) { // general info imgName = @"iconDamage"; @@ -116,7 +133,7 @@ } -(CGFloat) tableView:(UITableView *)aTableView heightForHeaderInSection:(NSInteger)section { - return 160; + return (section == 0) ? 160 : 40; } -(UIView *)tableView:(UITableView *)aTableView viewForHeaderInSection:(NSInteger)section { @@ -162,7 +179,7 @@ #pragma mark button delegate -(void) dismissView { [[AudioManagerController mainManager] playClickSound]; - [self dismissModalViewControllerAnimated:YES]; + [self dismissViewControllerAnimated:YES completion:nil]; } #pragma mark - diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/SupportViewController.h --- a/project_files/HedgewarsMobile/Classes/SupportViewController.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/SupportViewController.h Tue Nov 10 20:43:13 2015 +0100 @@ -13,14 +13,14 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ #import - +#import "TableViewControllerWithDoneButton.h" -@interface SupportViewController : UITableViewController { +@interface SupportViewController : TableViewControllerWithDoneButton { NSArray *waysToSupport; } diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/SupportViewController.m --- a/project_files/HedgewarsMobile/Classes/SupportViewController.m Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/SupportViewController.m Tue Nov 10 20:43:13 2015 +0100 @@ -13,12 +13,12 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ #import "SupportViewController.h" - +#import "Appirater.h" @implementation SupportViewController @synthesize waysToSupport; @@ -95,6 +95,7 @@ DLog(@"No way"); break; } + cell.accessoryView = nil; } NSString *imgString = [[NSString alloc] initWithFormat:@"%@/%@.png",[[NSBundle mainBundle] resourcePath],imgName]; @@ -113,12 +114,17 @@ #pragma mark - #pragma mark Table view delegate --(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - NSString *urlString = nil; +-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath +{ if ([indexPath section] == 0) - urlString = @"http://itunes.apple.com/us/app/hedgewars/id391234866?affC=QQABAAAAHgAFasEiWjVwUGZOc3k1VGctQkRJazlacXhUclpBTVpiU2xteVdfUQ%3D%3D#&mt=8"; + { + [Appirater rateApp]; + } else - switch ([indexPath row]) { + { + NSString *urlString = nil; + switch ([indexPath row]) + { case 0: urlString = @"http://www.facebook.com/Hedgewars"; break; @@ -135,7 +141,8 @@ DLog(@"No way"); break; } - [[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlString]]; + [[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlString]]; + } } -(UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger) section { @@ -154,7 +161,7 @@ UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.tableView.frame.size.width, 20)]; label.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin; label.textAlignment = UITextAlignmentCenter; - label.text = @" ♥ THANK YOU ♥ "; + label.text = NSLocalizedString(@" ♥ THANK YOU ♥ ", nil); label.backgroundColor = [UIColor clearColor]; label.center = CGPointMake(self.tableView.frame.size.width/2, 250); [footer addSubview:label]; @@ -167,7 +174,7 @@ -(CGFloat) tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section { // image height + label height - return 265; + return (section == 1) ? 265 : 20; } #pragma mark - diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/TableViewControllerWithDoneButton.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/TableViewControllerWithDoneButton.h Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,23 @@ +/* + * Hedgewars-iOS, a Hedgewars port for iOS devices + * Copyright (c) 2015 Anton Malmygin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#import + +@interface TableViewControllerWithDoneButton : UITableViewController + +@end diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/TableViewControllerWithDoneButton.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/TableViewControllerWithDoneButton.m Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,52 @@ +/* + * Hedgewars-iOS, a Hedgewars port for iOS devices + * Copyright (c) 2015 Anton Malmygin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#import "TableViewControllerWithDoneButton.h" + +@interface TableViewControllerWithDoneButton () + +@end + +@implementation TableViewControllerWithDoneButton + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + if (!IS_IPAD()) + { + UIBarButtonItem *doneButton = [self doneButton]; + self.navigationItem.backBarButtonItem = doneButton; + self.navigationItem.leftBarButtonItem = doneButton; + } +} + +- (UIBarButtonItem *)doneButton +{ + return [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone + target:self + action:@selector(dismissView)] autorelease]; +} + +- (void)dismissView +{ + [[AudioManagerController mainManager] playBackSound]; + [[[HedgewarsAppDelegate sharedAppDelegate] mainViewController] dismissViewControllerAnimated:YES completion:nil]; +} + +@end diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/TeamConfigViewController.h --- a/project_files/HedgewarsMobile/Classes/TeamConfigViewController.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/TeamConfigViewController.h Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/TeamConfigViewController.m --- a/project_files/HedgewarsMobile/Classes/TeamConfigViewController.m Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/TeamConfigViewController.m Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ @@ -45,6 +45,8 @@ } else { UIImage *backgroundImage = [[UIImage alloc] initWithContentsOfFile:@"background~iphone.png"]; UIImageView *background = [[UIImageView alloc] initWithImage:backgroundImage]; + background.contentMode = UIViewContentModeScaleAspectFill; + background.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; [backgroundImage release]; [self.view addSubview:background]; [background release]; @@ -245,7 +247,7 @@ SquareButtonView *squareButton = (SquareButtonView *)cell.accessoryView; NSInteger increaseNumber = [[selectedRow objectForKey:@"number"] intValue] + 1; - NSNumber *newNumber = [NSNumber numberWithInt:[self filterNumberOfHogs:increaseNumber]]; + NSNumber *newNumber = [NSNumber numberWithInteger:[self filterNumberOfHogs:increaseNumber]]; [squareButton setTitle:[newNumber stringValue] forState:UIControlStateNormal]; [selectedRow setObject:newNumber forKey:@"number"]; diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/TeamSettingsViewController.h --- a/project_files/HedgewarsMobile/Classes/TeamSettingsViewController.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/TeamSettingsViewController.h Tue Nov 10 20:43:13 2015 +0100 @@ -13,18 +13,15 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ #import - - -@class SingleTeamViewController; +#import "TableViewControllerWithDoneButton.h" -@interface TeamSettingsViewController : UITableViewController { +@interface TeamSettingsViewController : TableViewControllerWithDoneButton { NSMutableArray *listOfTeams; - SingleTeamViewController *childController; } @property (nonatomic, retain) NSMutableArray *listOfTeams; diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/TeamSettingsViewController.m --- a/project_files/HedgewarsMobile/Classes/TeamSettingsViewController.m Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/TeamSettingsViewController.m Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ @@ -41,7 +41,7 @@ self.navigationItem.rightBarButtonItem = editButton; [editButton release]; - self.navigationItem.title = @"List of teams"; + self.navigationItem.title = NSLocalizedString(@"List of teams", nil); } // load the list of teams in the teams directory @@ -136,43 +136,43 @@ #pragma mark - #pragma mark Table view delegate --(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - if (childController == nil) { - childController = [[SingleTeamViewController alloc] initWithStyle:UITableViewStyleGrouped]; - } - +-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath +{ + SingleTeamViewController *singleTeamViewController = [[SingleTeamViewController alloc] initWithStyle:UITableViewStyleGrouped]; + NSInteger row = [indexPath row]; NSString *selectedTeamFile = [listOfTeams objectAtIndex:row]; // this must be set so childController can load the correct plist - childController.teamName = [selectedTeamFile stringByDeletingPathExtension]; - [childController.tableView setContentOffset:CGPointMake(0,0) animated:NO]; + singleTeamViewController.teamName = [selectedTeamFile stringByDeletingPathExtension]; + [singleTeamViewController.tableView setContentOffset:CGPointMake(0,0) animated:NO]; - [self.navigationController pushViewController:childController animated:YES]; + [self.navigationController pushViewController:singleTeamViewController animated:YES]; + [singleTeamViewController release]; + [tableView deselectRowAtIndexPath:indexPath animated:YES]; } #pragma mark - #pragma mark Memory management --(void) didReceiveMemoryWarning { +-(void) didReceiveMemoryWarning +{ // Releases the view if it doesn't have a superview. [super didReceiveMemoryWarning]; // Relinquish ownership any cached data, images, etc that aren't in use. - if (childController.view.superview == nil ) - childController = nil; } --(void) viewDidUnload { +-(void) viewDidUnload +{ self.listOfTeams = nil; - childController = nil; MSG_DIDUNLOAD(); [super viewDidUnload]; } --(void) dealloc { +-(void) dealloc +{ releaseAndNil(listOfTeams); - releaseAndNil(childController); [super dealloc]; } diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/UIImageExtra.h --- a/project_files/HedgewarsMobile/Classes/UIImageExtra.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/UIImageExtra.h Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/UIImageExtra.m --- a/project_files/HedgewarsMobile/Classes/UIImageExtra.m Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/UIImageExtra.m Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/UITableViewCell+FindTable.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/UITableViewCell+FindTable.h Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,25 @@ +/* + * Hedgewars-iOS, a Hedgewars port for iOS devices + * Copyright (c) 2015 Anton Malmygin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#import + +@interface UITableViewCell (FindTable) + +- (UITableView *)findTable; + +@end diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/UITableViewCell+FindTable.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/UITableViewCell+FindTable.m Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,39 @@ +/* + * Hedgewars-iOS, a Hedgewars port for iOS devices + * Copyright (c) 2015 Anton Malmygin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#import "UITableViewCell+FindTable.h" + +@implementation UITableViewCell (FindTable) + +- (UITableView *)findTable +{ + UIView *tableView = self.superview; + while (![tableView isKindOfClass:[UITableView class]] || (tableView == nil)) + { + tableView = tableView.superview; + + if ([tableView isEqual:self.window]) + { + tableView = nil; + } + } + + return (UITableView *)tableView; +} + +@end diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/VoicesViewController.h --- a/project_files/HedgewarsMobile/Classes/VoicesViewController.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/VoicesViewController.h Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/VoicesViewController.m --- a/project_files/HedgewarsMobile/Classes/VoicesViewController.m Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/VoicesViewController.m Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ @@ -32,7 +32,6 @@ #pragma mark View lifecycle -(void) viewDidLoad { [super viewDidLoad]; - srandom(time(NULL)); voiceBeingPlayed = NULL; @@ -104,8 +103,8 @@ #pragma mark - #pragma mark Table view delegate -(void) tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - int newRow = [indexPath row]; - int oldRow = (lastIndexPath != nil) ? [lastIndexPath row] : -1; + NSInteger newRow = [indexPath row]; + NSInteger oldRow = (lastIndexPath != nil) ? [lastIndexPath row] : -1; if (newRow != oldRow) { [teamDictionary setObject:[voiceArray objectAtIndex:newRow] forKey:@"voicepack"]; @@ -129,7 +128,7 @@ NSString *voiceDir = [[NSString alloc] initWithFormat:@"%@/%@/",VOICES_DIRECTORY(),[voiceArray objectAtIndex:newRow]]; NSArray *array = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:voiceDir error:NULL]; - int index = random() % [array count]; + int index = arc4random_uniform((int)[array count]); voiceBeingPlayed = Mix_LoadWAV([[voiceDir stringByAppendingString:[array objectAtIndex:index]] UTF8String]); [voiceDir release]; diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/WeaponCellView.h --- a/project_files/HedgewarsMobile/Classes/WeaponCellView.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/WeaponCellView.h Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/WeaponCellView.m --- a/project_files/HedgewarsMobile/Classes/WeaponCellView.m Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/WeaponCellView.m Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ @@ -200,10 +200,10 @@ crateLab.text = ((int)crateSli.value == 9) ? @"∞" : [NSString stringWithFormat:@"%d",(int)crateSli.value]; [delegate updateValues:[NSArray arrayWithObjects: - [NSNumber numberWithInt:(int)initialSli.value], - [NSNumber numberWithInt:(int)probabilitySli.value], - [NSNumber numberWithInt:(int)delaySli.value], - [NSNumber numberWithInt:(int)crateSli.value], nil] + [NSNumber numberWithInteger:initialSli.value], + [NSNumber numberWithInteger:probabilitySli.value], + [NSNumber numberWithInteger:delaySli.value], + [NSNumber numberWithInteger:crateSli.value], nil] atIndex:self.tag]; } else DLog(@"error - delegate = nil!"); diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/WeaponSettingsViewController.h --- a/project_files/HedgewarsMobile/Classes/WeaponSettingsViewController.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/WeaponSettingsViewController.h Tue Nov 10 20:43:13 2015 +0100 @@ -13,18 +13,15 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ #import - - -@class SingleWeaponViewController; +#import "TableViewControllerWithDoneButton.h" -@interface WeaponSettingsViewController : UITableViewController { +@interface WeaponSettingsViewController : TableViewControllerWithDoneButton { NSMutableArray *listOfWeapons; - SingleWeaponViewController *childController; } @property (nonatomic, retain) NSMutableArray *listOfWeapons; diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Classes/WeaponSettingsViewController.m --- a/project_files/HedgewarsMobile/Classes/WeaponSettingsViewController.m Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Classes/WeaponSettingsViewController.m Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ @@ -40,7 +40,7 @@ self.navigationItem.rightBarButtonItem = editButton; [editButton release]; - self.navigationItem.title = @"List of weapons"; + self.navigationItem.title = NSLocalizedString(@"List of weapons", nil); } -(void) viewWillAppear:(BOOL) animated { @@ -131,42 +131,42 @@ #pragma mark - #pragma mark Table view delegate --(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - if (childController == nil) { - childController = [[SingleWeaponViewController alloc] initWithStyle:UITableViewStyleGrouped]; - } +-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath +{ + SingleWeaponViewController *singleWeaponViewController = [[SingleWeaponViewController alloc] initWithStyle:UITableViewStyleGrouped]; NSInteger row = [indexPath row]; NSString *selectedWeaponFile = [self.listOfWeapons objectAtIndex:row]; // this must be set so childController can load the correct plist - childController.weaponName = [selectedWeaponFile stringByDeletingPathExtension]; - [childController.tableView setContentOffset:CGPointMake(0,0) animated:NO]; + singleWeaponViewController.weaponName = [selectedWeaponFile stringByDeletingPathExtension]; + [singleWeaponViewController.tableView setContentOffset:CGPointMake(0,0) animated:NO]; - [self.navigationController pushViewController:childController animated:YES]; + [self.navigationController pushViewController:singleWeaponViewController animated:YES]; + [singleWeaponViewController release]; + [tableView deselectRowAtIndexPath:indexPath animated:YES]; } #pragma mark - #pragma mark Memory management --(void)didReceiveMemoryWarning { +-(void)didReceiveMemoryWarning +{ [super didReceiveMemoryWarning]; - if (childController.view.superview == nil ) - childController = nil; } --(void) viewDidUnload { +-(void) viewDidUnload +{ self.listOfWeapons = nil; - childController = nil; MSG_DIDUNLOAD(); [super viewDidUnload]; } --(void) dealloc { +-(void) dealloc +{ releaseAndNil(listOfWeapons); - releaseAndNil(childController); [super dealloc]; } diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Default-568h@2x.png Binary file project_files/HedgewarsMobile/Default-568h@2x.png has changed diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Hedgewars.xcodeproj/project.pbxproj --- a/project_files/HedgewarsMobile/Hedgewars.xcodeproj/project.pbxproj Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Hedgewars.xcodeproj/project.pbxproj Tue Nov 10 20:43:13 2015 +0100 @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 45; + objectVersion = 46; objects = { /* Begin PBXAggregateTarget section */ @@ -74,9 +74,9 @@ 615AD9EB1207654E00F2FF04 /* helpButton.png in Resources */ = {isa = PBXBuildFile; fileRef = 615AD9EA1207654E00F2FF04 /* helpButton.png */; }; 615BE3D4155C5DDF003CA34D /* uInputHandler.pas in Sources */ = {isa = PBXBuildFile; fileRef = 615BE3D3155C5DDF003CA34D /* uInputHandler.pas */; }; 615E755A14E41E8C00FBA131 /* MXAudioPlayerFadeOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 615E755914E41E8C00FBA131 /* MXAudioPlayerFadeOperation.m */; }; - 615E76BC14E4421200FBA131 /* MGSplitCornersView.m in Sources */ = {isa = PBXBuildFile; fileRef = 615E76B714E4421200FBA131 /* MGSplitCornersView.m */; }; - 615E76BD14E4421200FBA131 /* MGSplitDividerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 615E76B914E4421200FBA131 /* MGSplitDividerView.m */; }; - 615E76BE14E4421200FBA131 /* MGSplitViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 615E76BB14E4421200FBA131 /* MGSplitViewController.m */; }; + 615E76BC14E4421200FBA131 /* MGSplitCornersView.m in Sources */ = {isa = PBXBuildFile; fileRef = 615E76B714E4421200FBA131 /* MGSplitCornersView.m */; settings = {COMPILER_FLAGS = "-fobjc-arc"; }; }; + 615E76BD14E4421200FBA131 /* MGSplitDividerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 615E76B914E4421200FBA131 /* MGSplitDividerView.m */; settings = {COMPILER_FLAGS = "-fobjc-arc"; }; }; + 615E76BE14E4421200FBA131 /* MGSplitViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 615E76BB14E4421200FBA131 /* MGSplitViewController.m */; settings = {COMPILER_FLAGS = "-fobjc-arc"; }; }; 615FEAE212A2A6640098EE92 /* localplayButton~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = 615FEADF12A2A6640098EE92 /* localplayButton~ipad.png */; }; 615FEAE312A2A6640098EE92 /* localplayButton~iphone.png in Resources */ = {isa = PBXBuildFile; fileRef = 615FEAE012A2A6640098EE92 /* localplayButton~iphone.png */; }; 616065A8159A71FD00CFAEF4 /* hwclassic.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 616065A7159A71FD00CFAEF4 /* hwclassic.mp3 */; }; @@ -96,7 +96,6 @@ 6165921B11CA9BA200D6E256 /* SchemeWeaponConfigViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 616591FD11CA9BA200D6E256 /* SchemeWeaponConfigViewController.m */; }; 6165921C11CA9BA200D6E256 /* SingleSchemeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 616591FF11CA9BA200D6E256 /* SingleSchemeViewController.m */; }; 6165921D11CA9BA200D6E256 /* SingleTeamViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6165920111CA9BA200D6E256 /* SingleTeamViewController.m */; }; - 6165921E11CA9BA200D6E256 /* SettingsContainerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6165920311CA9BA200D6E256 /* SettingsContainerViewController.m */; }; 6165921F11CA9BA200D6E256 /* TeamConfigViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6165920511CA9BA200D6E256 /* TeamConfigViewController.m */; }; 6165922011CA9BA200D6E256 /* TeamSettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6165920711CA9BA200D6E256 /* TeamSettingsViewController.m */; }; 6165922111CA9BA200D6E256 /* VoicesViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6165920911CA9BA200D6E256 /* VoicesViewController.m */; }; @@ -208,7 +207,6 @@ 61A670C112747DB900B06CE7 /* MainMenuViewController-iPhone.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6165924C11CA9CB400D6E256 /* MainMenuViewController-iPhone.xib */; }; 61A670C212747DBD00B06CE7 /* MapConfigViewController-iPhone.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6165924E11CA9CB400D6E256 /* MapConfigViewController-iPhone.xib */; }; 61A976B3136F668500DD9878 /* uCursor.pas in Sources */ = {isa = PBXBuildFile; fileRef = 61A976B2136F668500DD9878 /* uCursor.pas */; }; - 61AC067412B2E32D000B52A2 /* Appirater.m in Sources */ = {isa = PBXBuildFile; fileRef = 61AC067312B2E32D000B52A2 /* Appirater.m */; }; 61B37A1F17837C78009F283D /* ArgParsers.pas in Sources */ = {isa = PBXBuildFile; fileRef = 61B37A1D17837C78009F283D /* ArgParsers.pas */; }; 61B37A2017837C78009F283D /* uVisualGearsList.pas in Sources */ = {isa = PBXBuildFile; fileRef = 61B37A1E17837C78009F283D /* uVisualGearsList.pas */; }; 61B37A80178381DB009F283D /* uGearsHandlersMess.pas in Sources */ = {isa = PBXBuildFile; fileRef = 61B37A7F178381DB009F283D /* uGearsHandlersMess.pas */; }; @@ -244,6 +242,51 @@ 61F9040B11DF59370068B24D /* background.png in Resources */ = {isa = PBXBuildFile; fileRef = 61F9040A11DF59370068B24D /* background.png */; }; 61F904D711DF7DA30068B24D /* WeaponCellView.m in Sources */ = {isa = PBXBuildFile; fileRef = 61F904D611DF7DA30068B24D /* WeaponCellView.m */; }; 922F64900F10F53100DC6EC0 /* libfpc.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 928301170F10CAFC00CC5A3C /* libfpc.a */; }; + F60D04771BD137B5003ACB00 /* bullet_filled.png in Resources */ = {isa = PBXBuildFile; fileRef = F60D04631BD137B5003ACB00 /* bullet_filled.png */; }; + F60D04781BD137B5003ACB00 /* bullet_filled@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F60D04641BD137B5003ACB00 /* bullet_filled@2x.png */; }; + F60D04791BD137B5003ACB00 /* bullet.png in Resources */ = {isa = PBXBuildFile; fileRef = F60D04651BD137B5003ACB00 /* bullet.png */; }; + F60D047A1BD137B5003ACB00 /* bullet@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F60D04661BD137B5003ACB00 /* bullet@2x.png */; }; + F60D047B1BD137B5003ACB00 /* flower_filled.png in Resources */ = {isa = PBXBuildFile; fileRef = F60D04671BD137B5003ACB00 /* flower_filled.png */; }; + F60D047C1BD137B5003ACB00 /* flower_filled@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F60D04681BD137B5003ACB00 /* flower_filled@2x.png */; }; + F60D047D1BD137B5003ACB00 /* flower.png in Resources */ = {isa = PBXBuildFile; fileRef = F60D04691BD137B5003ACB00 /* flower.png */; }; + F60D047E1BD137B5003ACB00 /* flower@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F60D046A1BD137B5003ACB00 /* flower@2x.png */; }; + F60D047F1BD137B5003ACB00 /* heart_filled.png in Resources */ = {isa = PBXBuildFile; fileRef = F60D046B1BD137B5003ACB00 /* heart_filled.png */; }; + F60D04801BD137B5003ACB00 /* heart_filled@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F60D046C1BD137B5003ACB00 /* heart_filled@2x.png */; }; + F60D04811BD137B5003ACB00 /* heart.png in Resources */ = {isa = PBXBuildFile; fileRef = F60D046D1BD137B5003ACB00 /* heart.png */; }; + F60D04821BD137B5003ACB00 /* heart@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F60D046E1BD137B5003ACB00 /* heart@2x.png */; }; + F60D04831BD137B5003ACB00 /* target_filled.png in Resources */ = {isa = PBXBuildFile; fileRef = F60D046F1BD137B5003ACB00 /* target_filled.png */; }; + F60D04841BD137B5003ACB00 /* target_filled@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F60D04701BD137B5003ACB00 /* target_filled@2x.png */; }; + F60D04851BD137B5003ACB00 /* target.png in Resources */ = {isa = PBXBuildFile; fileRef = F60D04711BD137B5003ACB00 /* target.png */; }; + F60D04861BD137B5003ACB00 /* target@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F60D04721BD137B5003ACB00 /* target@2x.png */; }; + F60D04871BD137B5003ACB00 /* teams_filled.png in Resources */ = {isa = PBXBuildFile; fileRef = F60D04731BD137B5003ACB00 /* teams_filled.png */; }; + F60D04881BD137B5003ACB00 /* teams_filled@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F60D04741BD137B5003ACB00 /* teams_filled@2x.png */; }; + F60D04891BD137B5003ACB00 /* teams.png in Resources */ = {isa = PBXBuildFile; fileRef = F60D04751BD137B5003ACB00 /* teams.png */; }; + F60D048A1BD137B5003ACB00 /* teams@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F60D04761BD137B5003ACB00 /* teams@2x.png */; }; + F6448CE31BD2E00500C31C8C /* TableViewControllerWithDoneButton.m in Sources */ = {isa = PBXBuildFile; fileRef = F6448CE21BD2E00500C31C8C /* TableViewControllerWithDoneButton.m */; }; + F65724FD1B7E784700A86262 /* helpabove.png in Resources */ = {isa = PBXBuildFile; fileRef = F65724F81B7E784700A86262 /* helpabove.png */; }; + F65724FE1B7E784700A86262 /* helpbottom.png in Resources */ = {isa = PBXBuildFile; fileRef = F65724F91B7E784700A86262 /* helpbottom.png */; }; + F65724FF1B7E784700A86262 /* helpleft.png in Resources */ = {isa = PBXBuildFile; fileRef = F65724FA1B7E784700A86262 /* helpleft.png */; }; + F65725001B7E784700A86262 /* helpplain.png in Resources */ = {isa = PBXBuildFile; fileRef = F65724FB1B7E784700A86262 /* helpplain.png */; }; + F65725011B7E784700A86262 /* helpright.png in Resources */ = {isa = PBXBuildFile; fileRef = F65724FC1B7E784700A86262 /* helpright.png */; }; + F65E1DBF1B9B95A400A78ADF /* Icon-60@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F65E1DBC1B9B95A400A78ADF /* Icon-60@2x.png */; }; + F65E1DC01B9B95A400A78ADF /* Icon-76.png in Resources */ = {isa = PBXBuildFile; fileRef = F65E1DBD1B9B95A400A78ADF /* Icon-76.png */; }; + F65E1DC11B9B95A400A78ADF /* Icon-76@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F65E1DBE1B9B95A400A78ADF /* Icon-76@2x.png */; }; + F6756D801BD8550500B6AB6B /* LabelWithIBLocalization.m in Sources */ = {isa = PBXBuildFile; fileRef = F6756D7F1BD8550500B6AB6B /* LabelWithIBLocalization.m */; }; + F67FC8121BEC06E700A9DC75 /* Appirater.m in Sources */ = {isa = PBXBuildFile; fileRef = F67FC8101BEC06E700A9DC75 /* Appirater.m */; settings = {COMPILER_FLAGS = "-fobjc-arc"; }; }; + F67FC8141BEC072B00A9DC75 /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F67FC8131BEC072B00A9DC75 /* StoreKit.framework */; }; + F67FC8161BEC17AC00A9DC75 /* Appirater.bundle in Resources */ = {isa = PBXBuildFile; fileRef = F67FC8151BEC17AC00A9DC75 /* Appirater.bundle */; }; + F6BA38461BA7A834005D16EA /* GameLogViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F6BA38451BA7A834005D16EA /* GameLogViewController.m */; }; + F6D7E09F1B76884E004F3BCF /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F6D7E09E1B76884E004F3BCF /* Default-568h@2x.png */; }; + F6D7E0C21B768F19004F3BCF /* uLandGenPerlin.pas in Sources */ = {isa = PBXBuildFile; fileRef = F6D7E0BF1B768F19004F3BCF /* uLandGenPerlin.pas */; }; + F6D7E0C31B768F19004F3BCF /* uLandGenTemplateBased.pas in Sources */ = {isa = PBXBuildFile; fileRef = F6D7E0C01B768F19004F3BCF /* uLandGenTemplateBased.pas */; }; + F6D7E0C41B768F19004F3BCF /* uLandUtils.pas in Sources */ = {isa = PBXBuildFile; fileRef = F6D7E0C11B768F19004F3BCF /* uLandUtils.pas */; }; + F6D7E0C61B769819004F3BCF /* CoreMotion.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F6D7E0C51B769819004F3BCF /* CoreMotion.framework */; }; + F6D7E0C81B7698BF004F3BCF /* libstdc++.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = F6D7E0C71B7698BE004F3BCF /* libstdc++.dylib */; }; + F6F07BDE1B7E72D40010E48F /* HelpPageLobbyViewController-iPad.xib in Resources */ = {isa = PBXBuildFile; fileRef = F6F07BDA1B7E72D40010E48F /* HelpPageLobbyViewController-iPad.xib */; }; + F6F07BDF1B7E72D40010E48F /* HelpPageLobbyViewController-iPhone.xib in Resources */ = {isa = PBXBuildFile; fileRef = F6F07BDB1B7E72D40010E48F /* HelpPageLobbyViewController-iPhone.xib */; }; + F6F07BE01B7E72D40010E48F /* HelpPageLobbyViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F6F07BDD1B7E72D40010E48F /* HelpPageLobbyViewController.m */; }; + F6F7DA8F1BE18F5700432EA7 /* UITableViewCell+FindTable.m in Sources */ = {isa = PBXBuildFile; fileRef = F6F7DA8E1BE18F5700432EA7 /* UITableViewCell+FindTable.m */; }; + F6FF25A21BB8AEE300124053 /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F6FF25A11BB8AEE300124053 /* GameController.framework */; }; /* End PBXBuildFile section */ /* Begin PBXBuildRule section */ @@ -416,9 +459,6 @@ 61177BA7148A658900686905 /* German */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = German; path = Locale/German.lproj/Localizable.strings; sourceTree = ""; }; 61177BA9148A660C00686905 /* German */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = German; path = Locale/German.lproj/Scheme.strings; sourceTree = ""; }; 61177BAA148A661600686905 /* German */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = German; path = Locale/German.lproj/About.strings; sourceTree = ""; }; - 61177BAC148A671600686905 /* Turkish */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Turkish; path = Locale/Turkish.lproj/About.strings; sourceTree = ""; }; - 61177BAD148A672000686905 /* Turkish */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Turkish; path = Locale/Turkish.lproj/Localizable.strings; sourceTree = ""; }; - 61177BAE148A672C00686905 /* Turkish */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Turkish; path = Locale/Turkish.lproj/Scheme.strings; sourceTree = ""; }; 61177BE4148B881C00686905 /* Danish */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Danish; path = Locale/Danish.lproj/About.strings; sourceTree = ""; }; 61177BF0148B882500686905 /* Danish */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Danish; path = Locale/Danish.lproj/Localizable.strings; sourceTree = ""; }; 61177BF1148B882F00686905 /* Danish */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Danish; path = Locale/Danish.lproj/Scheme.strings; sourceTree = ""; }; @@ -493,8 +533,6 @@ 616591FF11CA9BA200D6E256 /* SingleSchemeViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SingleSchemeViewController.m; sourceTree = ""; }; 6165920011CA9BA200D6E256 /* SingleTeamViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SingleTeamViewController.h; sourceTree = ""; }; 6165920111CA9BA200D6E256 /* SingleTeamViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SingleTeamViewController.m; sourceTree = ""; }; - 6165920211CA9BA200D6E256 /* SettingsContainerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingsContainerViewController.h; sourceTree = ""; }; - 6165920311CA9BA200D6E256 /* SettingsContainerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SettingsContainerViewController.m; sourceTree = ""; }; 6165920411CA9BA200D6E256 /* TeamConfigViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TeamConfigViewController.h; sourceTree = ""; }; 6165920511CA9BA200D6E256 /* TeamConfigViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TeamConfigViewController.m; sourceTree = ""; }; 6165920611CA9BA200D6E256 /* TeamSettingsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TeamSettingsViewController.h; sourceTree = ""; }; @@ -638,8 +676,6 @@ 61A4A39312A5CCC2004D81E6 /* uVariables.pas */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; name = uVariables.pas; path = ../../hedgewars/uVariables.pas; sourceTree = SOURCE_ROOT; }; 61A4A3A112A5CD56004D81E6 /* uCaptions.pas */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; name = uCaptions.pas; path = ../../hedgewars/uCaptions.pas; sourceTree = SOURCE_ROOT; }; 61A976B2136F668500DD9878 /* uCursor.pas */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; name = uCursor.pas; path = ../../hedgewars/uCursor.pas; sourceTree = SOURCE_ROOT; }; - 61AC067212B2E32D000B52A2 /* Appirater.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Appirater.h; path = Classes/Appirater.h; sourceTree = ""; }; - 61AC067312B2E32D000B52A2 /* Appirater.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Appirater.m; path = Classes/Appirater.m; sourceTree = ""; }; 61B37A1D17837C78009F283D /* ArgParsers.pas */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; name = ArgParsers.pas; path = ../../hedgewars/ArgParsers.pas; sourceTree = SOURCE_ROOT; }; 61B37A1E17837C78009F283D /* uVisualGearsList.pas */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; name = uVisualGearsList.pas; path = ../../hedgewars/uVisualGearsList.pas; sourceTree = SOURCE_ROOT; }; 61B37A7F178381DB009F283D /* uGearsHandlersMess.pas */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; name = uGearsHandlersMess.pas; path = ../../hedgewars/uGearsHandlersMess.pas; sourceTree = SOURCE_ROOT; }; @@ -695,6 +731,64 @@ 61F904D611DF7DA30068B24D /* WeaponCellView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = WeaponCellView.m; path = Classes/WeaponCellView.m; sourceTree = ""; }; 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 928301170F10CAFC00CC5A3C /* libfpc.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libfpc.a; sourceTree = BUILT_PRODUCTS_DIR; }; + F60D04631BD137B5003ACB00 /* bullet_filled.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = bullet_filled.png; path = Resources/Icons/bullet_filled.png; sourceTree = ""; }; + F60D04641BD137B5003ACB00 /* bullet_filled@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "bullet_filled@2x.png"; path = "Resources/Icons/bullet_filled@2x.png"; sourceTree = ""; }; + F60D04651BD137B5003ACB00 /* bullet.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = bullet.png; path = Resources/Icons/bullet.png; sourceTree = ""; }; + F60D04661BD137B5003ACB00 /* bullet@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "bullet@2x.png"; path = "Resources/Icons/bullet@2x.png"; sourceTree = ""; }; + F60D04671BD137B5003ACB00 /* flower_filled.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = flower_filled.png; path = Resources/Icons/flower_filled.png; sourceTree = ""; }; + F60D04681BD137B5003ACB00 /* flower_filled@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "flower_filled@2x.png"; path = "Resources/Icons/flower_filled@2x.png"; sourceTree = ""; }; + F60D04691BD137B5003ACB00 /* flower.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = flower.png; path = Resources/Icons/flower.png; sourceTree = ""; }; + F60D046A1BD137B5003ACB00 /* flower@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "flower@2x.png"; path = "Resources/Icons/flower@2x.png"; sourceTree = ""; }; + F60D046B1BD137B5003ACB00 /* heart_filled.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = heart_filled.png; path = Resources/Icons/heart_filled.png; sourceTree = ""; }; + F60D046C1BD137B5003ACB00 /* heart_filled@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "heart_filled@2x.png"; path = "Resources/Icons/heart_filled@2x.png"; sourceTree = ""; }; + F60D046D1BD137B5003ACB00 /* heart.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = heart.png; path = Resources/Icons/heart.png; sourceTree = ""; }; + F60D046E1BD137B5003ACB00 /* heart@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "heart@2x.png"; path = "Resources/Icons/heart@2x.png"; sourceTree = ""; }; + F60D046F1BD137B5003ACB00 /* target_filled.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = target_filled.png; path = Resources/Icons/target_filled.png; sourceTree = ""; }; + F60D04701BD137B5003ACB00 /* target_filled@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "target_filled@2x.png"; path = "Resources/Icons/target_filled@2x.png"; sourceTree = ""; }; + F60D04711BD137B5003ACB00 /* target.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = target.png; path = Resources/Icons/target.png; sourceTree = ""; }; + F60D04721BD137B5003ACB00 /* target@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "target@2x.png"; path = "Resources/Icons/target@2x.png"; sourceTree = ""; }; + F60D04731BD137B5003ACB00 /* teams_filled.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = teams_filled.png; path = Resources/Icons/teams_filled.png; sourceTree = ""; }; + F60D04741BD137B5003ACB00 /* teams_filled@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "teams_filled@2x.png"; path = "Resources/Icons/teams_filled@2x.png"; sourceTree = ""; }; + F60D04751BD137B5003ACB00 /* teams.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = teams.png; path = Resources/Icons/teams.png; sourceTree = ""; }; + F60D04761BD137B5003ACB00 /* teams@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "teams@2x.png"; path = "Resources/Icons/teams@2x.png"; sourceTree = ""; }; + F6448CE11BD2E00500C31C8C /* TableViewControllerWithDoneButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TableViewControllerWithDoneButton.h; sourceTree = ""; }; + F6448CE21BD2E00500C31C8C /* TableViewControllerWithDoneButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TableViewControllerWithDoneButton.m; sourceTree = ""; }; + F65724F81B7E784700A86262 /* helpabove.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = helpabove.png; sourceTree = ""; }; + F65724F91B7E784700A86262 /* helpbottom.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = helpbottom.png; sourceTree = ""; }; + F65724FA1B7E784700A86262 /* helpleft.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = helpleft.png; sourceTree = ""; }; + F65724FB1B7E784700A86262 /* helpplain.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = helpplain.png; sourceTree = ""; }; + F65724FC1B7E784700A86262 /* helpright.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = helpright.png; sourceTree = ""; }; + F65725291B7EB9CC00A86262 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = Locale/ru.lproj/About.strings; sourceTree = ""; }; + F657252A1B7EB9CC00A86262 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = Locale/ru.lproj/Localizable.strings; sourceTree = ""; }; + F657252B1B7EB9CC00A86262 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = Locale/ru.lproj/Scheme.strings; sourceTree = ""; }; + F65E1DBC1B9B95A400A78ADF /* Icon-60@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Icon-60@2x.png"; path = "Resources/Icons/Icon-60@2x.png"; sourceTree = ""; }; + F65E1DBD1B9B95A400A78ADF /* Icon-76.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Icon-76.png"; path = "Resources/Icons/Icon-76.png"; sourceTree = ""; }; + F65E1DBE1B9B95A400A78ADF /* Icon-76@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Icon-76@2x.png"; path = "Resources/Icons/Icon-76@2x.png"; sourceTree = ""; }; + F6756D7E1BD8550500B6AB6B /* LabelWithIBLocalization.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LabelWithIBLocalization.h; sourceTree = ""; }; + F6756D7F1BD8550500B6AB6B /* LabelWithIBLocalization.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LabelWithIBLocalization.m; sourceTree = ""; }; + F67FC80F1BEC06E700A9DC75 /* Appirater.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Appirater.h; sourceTree = ""; }; + F67FC8101BEC06E700A9DC75 /* Appirater.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Appirater.m; sourceTree = ""; }; + F67FC8111BEC06E700A9DC75 /* AppiraterDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppiraterDelegate.h; sourceTree = ""; }; + F67FC8131BEC072B00A9DC75 /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = System/Library/Frameworks/StoreKit.framework; sourceTree = SDKROOT; }; + F67FC8151BEC17AC00A9DC75 /* Appirater.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Appirater.bundle; sourceTree = ""; }; + F67FC81F1BEC280D00A9DC75 /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = Locale/tr.lproj/About.strings; sourceTree = ""; }; + F67FC8201BEC280D00A9DC75 /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = Locale/tr.lproj/Localizable.strings; sourceTree = ""; }; + F67FC8211BEC280D00A9DC75 /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = Locale/tr.lproj/Scheme.strings; sourceTree = ""; }; + F6BA38441BA7A834005D16EA /* GameLogViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GameLogViewController.h; sourceTree = ""; }; + F6BA38451BA7A834005D16EA /* GameLogViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GameLogViewController.m; sourceTree = ""; }; + F6D7E09E1B76884E004F3BCF /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; + F6D7E0BF1B768F19004F3BCF /* uLandGenPerlin.pas */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; name = uLandGenPerlin.pas; path = ../../hedgewars/uLandGenPerlin.pas; sourceTree = ""; }; + F6D7E0C01B768F19004F3BCF /* uLandGenTemplateBased.pas */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; name = uLandGenTemplateBased.pas; path = ../../hedgewars/uLandGenTemplateBased.pas; sourceTree = ""; }; + F6D7E0C11B768F19004F3BCF /* uLandUtils.pas */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; name = uLandUtils.pas; path = ../../hedgewars/uLandUtils.pas; sourceTree = ""; }; + F6D7E0C51B769819004F3BCF /* CoreMotion.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMotion.framework; path = System/Library/Frameworks/CoreMotion.framework; sourceTree = SDKROOT; }; + F6D7E0C71B7698BE004F3BCF /* libstdc++.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libstdc++.dylib"; path = "usr/lib/libstdc++.dylib"; sourceTree = SDKROOT; }; + F6F07BDA1B7E72D40010E48F /* HelpPageLobbyViewController-iPad.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = "HelpPageLobbyViewController-iPad.xib"; sourceTree = ""; }; + F6F07BDB1B7E72D40010E48F /* HelpPageLobbyViewController-iPhone.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = "HelpPageLobbyViewController-iPhone.xib"; sourceTree = ""; }; + F6F07BDC1B7E72D40010E48F /* HelpPageLobbyViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HelpPageLobbyViewController.h; sourceTree = ""; }; + F6F07BDD1B7E72D40010E48F /* HelpPageLobbyViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HelpPageLobbyViewController.m; sourceTree = ""; }; + F6F7DA8D1BE18F5700432EA7 /* UITableViewCell+FindTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UITableViewCell+FindTable.h"; path = "Classes/UITableViewCell+FindTable.h"; sourceTree = ""; }; + F6F7DA8E1BE18F5700432EA7 /* UITableViewCell+FindTable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "UITableViewCell+FindTable.m"; path = "Classes/UITableViewCell+FindTable.m"; sourceTree = ""; }; + F6FF25A11BB8AEE300124053 /* GameController.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameController.framework; path = System/Library/Frameworks/GameController.framework; sourceTree = SDKROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -702,6 +796,10 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + F67FC8141BEC072B00A9DC75 /* StoreKit.framework in Frameworks */, + F6FF25A21BB8AEE300124053 /* GameController.framework in Frameworks */, + F6D7E0C81B7698BF004F3BCF /* libstdc++.dylib in Frameworks */, + F6D7E0C61B769819004F3BCF /* CoreMotion.framework in Frameworks */, 617D791E16D933060091D4D6 /* libPhysfs.a in Frameworks */, 617D795716D9345F0091D4D6 /* libPhyslayer.a in Frameworks */, 922F64900F10F53100DC6EC0 /* libfpc.a in Frameworks */, @@ -779,8 +877,7 @@ 61F8535314578999002CA294 /* Helpers */, 61641FE21437CD8F006E049C /* Headers */, 61DE91561258B76800B80214 /* Custom UIs */, - 61AC067212B2E32D000B52A2 /* Appirater.h */, - 61AC067312B2E32D000B52A2 /* Appirater.m */, + F67FC80E1BEC06E700A9DC75 /* Appirater */, 61006F93128DE31F00EBA7F7 /* CreationChamber.h */, 61006F94128DE31F00EBA7F7 /* CreationChamber.m */, 6165929C11CA9E2F00D6E256 /* HedgewarsAppDelegate.h */, @@ -794,6 +891,7 @@ 29B97317FDCFA39411CA2CEA /* Resources */ = { isa = PBXGroup; children = ( + F6D7E09E1B76884E004F3BCF /* Default-568h@2x.png */, 6129B9F611EFB04D0017E305 /* denied.png */, 6167C88B14294738003DD50F /* denied@2x.png */, 6199E86C12464A8E00DADF8C /* surprise.png */, @@ -814,6 +912,8 @@ 29B97323FDCFA39411CA2CEA /* Frameworks */ = { isa = PBXGroup; children = ( + F67FC8131BEC072B00A9DC75 /* StoreKit.framework */, + F6FF25A11BB8AEE300124053 /* GameController.framework */, 617D78D816D932310091D4D6 /* Physfs.xcodeproj */, 617D794316D933B00091D4D6 /* Physlayer.xcodeproj */, 6195993F1364C82B00B429B6 /* Lua.xcodeproj */, @@ -822,6 +922,7 @@ 61A19C1E14D20F51004B1E6D /* SDL_mixer.xcodeproj */, 61A19BF414D20D83004B1E6D /* SDL_net.xcodeproj */, 61A19BC114D20CDA004B1E6D /* SDL_ttf.xcodeproj */, + F6D7E0C71B7698BE004F3BCF /* libstdc++.dylib */, 61798934114AB25F00BA94A9 /* AudioToolbox.framework */, 612CABAA1391CE68005E9596 /* AVFoundation.framework */, 61A117FE1168322700359010 /* CoreGraphics.framework */, @@ -833,6 +934,7 @@ 61272338117DF778005B90CF /* MobileCoreServices.framework */, 6199E81512463EA800DADF8C /* CFNetwork.framework */, 6199E81912463EC400DADF8C /* SystemConfiguration.framework */, + F6D7E0C51B769819004F3BCF /* CoreMotion.framework */, ); name = Frameworks; sourceTree = ""; @@ -853,6 +955,8 @@ 61F2E7CB1205EDE0005734F7 /* AboutViewController.h */, 61F2E7CC1205EDE0005734F7 /* AboutViewController.m */, 61F2E7CD1205EDE0005734F7 /* AboutViewController.xib */, + F6BA38441BA7A834005D16EA /* GameLogViewController.h */, + F6BA38451BA7A834005D16EA /* GameLogViewController.m */, 6167A6731391514600AA6D07 /* RestoreViewController.h */, 6167A6741391514600AA6D07 /* RestoreViewController.m */, 6167A6751391514600AA6D07 /* RestoreViewController-iPhone.xib */, @@ -898,8 +1002,6 @@ 6163EE4C11CC2478001C0453 /* Settings Page */ = { isa = PBXGroup; children = ( - 6165920211CA9BA200D6E256 /* SettingsContainerViewController.h */, - 6165920311CA9BA200D6E256 /* SettingsContainerViewController.m */, 616591F411CA9BA200D6E256 /* SettingsBaseViewController.h */, 616591F511CA9BA200D6E256 /* SettingsBaseViewController.m */, 6163EE4E11CC248D001C0453 /* First Level */, @@ -924,6 +1026,12 @@ 616591F311CA9BA200D6E256 /* MapConfigViewController.m */, 6165924D11CA9CB400D6E256 /* MapConfigViewController-iPad.xib */, 6165924E11CA9CB400D6E256 /* MapConfigViewController-iPhone.xib */, + F6F07BDC1B7E72D40010E48F /* HelpPageLobbyViewController.h */, + F6F07BDD1B7E72D40010E48F /* HelpPageLobbyViewController.m */, + F6F07BDA1B7E72D40010E48F /* HelpPageLobbyViewController-iPad.xib */, + F6F07BDB1B7E72D40010E48F /* HelpPageLobbyViewController-iPhone.xib */, + F6756D7E1BD8550500B6AB6B /* LabelWithIBLocalization.h */, + F6756D7F1BD8550500B6AB6B /* LabelWithIBLocalization.m */, ); name = "Game Configuration"; sourceTree = ""; @@ -931,6 +1039,8 @@ 6163EE4E11CC248D001C0453 /* First Level */ = { isa = PBXGroup; children = ( + F6448CE11BD2E00500C31C8C /* TableViewControllerWithDoneButton.h */, + F6448CE21BD2E00500C31C8C /* TableViewControllerWithDoneButton.m */, 616591E811CA9BA200D6E256 /* GeneralSettingsViewController.h */, 616591E911CA9BA200D6E256 /* GeneralSettingsViewController.m */, 6165920611CA9BA200D6E256 /* TeamSettingsViewController.h */, @@ -1069,6 +1179,8 @@ 619C5BA0124FA59000D041AE /* MapPreviewButtonView.h */, 619C5BA1124FA59000D041AE /* MapPreviewButtonView.m */, 61F544C512AF1748007FD913 /* HoldTableViewCell.h */, + F6F7DA8D1BE18F5700432EA7 /* UITableViewCell+FindTable.h */, + F6F7DA8E1BE18F5700432EA7 /* UITableViewCell+FindTable.m */, 61F544C612AF1748007FD913 /* HoldTableViewCell.m */, 6165922A11CA9BD500D6E256 /* SquareButtonView.h */, 6165922B11CA9BD500D6E256 /* SquareButtonView.m */, @@ -1083,6 +1195,7 @@ 61F7A42811E2905C0040BA66 /* Icons */ = { isa = PBXGroup; children = ( + F60D04611BD1378F003ACB00 /* Tabbar */, 61F2E7EB12060E31005734F7 /* checkbox.png */, 615FEAD912A2A4C10098EE92 /* checkbox@2x.png */, 61D3D2A41290E03A003CE7C3 /* irc.png */, @@ -1120,6 +1233,9 @@ 61F7A43411E290650040BA66 /* Icon-Small@2x.png */, 61F7A43511E290650040BA66 /* Icon.png */, 61F7A43611E290650040BA66 /* Icon@2x.png */, + F65E1DBC1B9B95A400A78ADF /* Icon-60@2x.png */, + F65E1DBD1B9B95A400A78ADF /* Icon-76.png */, + F65E1DBE1B9B95A400A78ADF /* Icon-76@2x.png */, 61F7A43711E290650040BA66 /* iTunesArtwork.png */, ); name = Icons; @@ -1172,6 +1288,7 @@ 6172FEEC1298D25D00D73365 /* smallerBackground@2x~iphone.png */, 6172FEEE1298D25D00D73365 /* smallerBackground~iphone.png */, 6172FEED1298D25D00D73365 /* smallerBackground~ipad.png */, + F65724F71B7E784700A86262 /* Help Bubbles */, ); name = Frontend; sourceTree = ""; @@ -1229,10 +1346,13 @@ 617987FC114AA34C00BA94A9 /* uGears.pas */, 617987FD114AA34C00BA94A9 /* uIO.pas */, 617987FF114AA34C00BA94A9 /* uLand.pas */, + F6D7E0BF1B768F19004F3BCF /* uLandGenPerlin.pas */, + F6D7E0C01B768F19004F3BCF /* uLandGenTemplateBased.pas */, 61798800114AA34C00BA94A9 /* uLandGraphics.pas */, 61798801114AA34C00BA94A9 /* uLandObjects.pas */, 61798802114AA34C00BA94A9 /* uLandTemplates.pas */, 61798803114AA34C00BA94A9 /* uLandTexture.pas */, + F6D7E0C11B768F19004F3BCF /* uLandUtils.pas */, 61798804114AA34C00BA94A9 /* uLocale.pas */, 61798805114AA34C00BA94A9 /* uMisc.pas */, 61798806114AA34C00BA94A9 /* uRandom.pas */, @@ -1247,6 +1367,58 @@ name = "Pascal Sources"; sourceTree = ""; }; + F60D04611BD1378F003ACB00 /* Tabbar */ = { + isa = PBXGroup; + children = ( + F60D04631BD137B5003ACB00 /* bullet_filled.png */, + F60D04641BD137B5003ACB00 /* bullet_filled@2x.png */, + F60D04651BD137B5003ACB00 /* bullet.png */, + F60D04661BD137B5003ACB00 /* bullet@2x.png */, + F60D04671BD137B5003ACB00 /* flower_filled.png */, + F60D04681BD137B5003ACB00 /* flower_filled@2x.png */, + F60D04691BD137B5003ACB00 /* flower.png */, + F60D046A1BD137B5003ACB00 /* flower@2x.png */, + F60D046B1BD137B5003ACB00 /* heart_filled.png */, + F60D046C1BD137B5003ACB00 /* heart_filled@2x.png */, + F60D046D1BD137B5003ACB00 /* heart.png */, + F60D046E1BD137B5003ACB00 /* heart@2x.png */, + F60D046F1BD137B5003ACB00 /* target_filled.png */, + F60D04701BD137B5003ACB00 /* target_filled@2x.png */, + F60D04711BD137B5003ACB00 /* target.png */, + F60D04721BD137B5003ACB00 /* target@2x.png */, + F60D04731BD137B5003ACB00 /* teams_filled.png */, + F60D04741BD137B5003ACB00 /* teams_filled@2x.png */, + F60D04751BD137B5003ACB00 /* teams.png */, + F60D04761BD137B5003ACB00 /* teams@2x.png */, + ); + name = Tabbar; + sourceTree = ""; + }; + F65724F71B7E784700A86262 /* Help Bubbles */ = { + isa = PBXGroup; + children = ( + F65724F81B7E784700A86262 /* helpabove.png */, + F65724F91B7E784700A86262 /* helpbottom.png */, + F65724FA1B7E784700A86262 /* helpleft.png */, + F65724FB1B7E784700A86262 /* helpplain.png */, + F65724FC1B7E784700A86262 /* helpright.png */, + ); + name = "Help Bubbles"; + path = "Resources/Frontend/Help Bubbles"; + sourceTree = ""; + }; + F67FC80E1BEC06E700A9DC75 /* Appirater */ = { + isa = PBXGroup; + children = ( + F67FC80F1BEC06E700A9DC75 /* Appirater.h */, + F67FC8101BEC06E700A9DC75 /* Appirater.m */, + F67FC8111BEC06E700A9DC75 /* AppiraterDelegate.h */, + F67FC8151BEC17AC00A9DC75 /* Appirater.bundle */, + ); + name = Appirater; + path = Classes/Appirater; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -1301,9 +1473,10 @@ isa = PBXProject; attributes = { BuildIndependentTargetsInParallel = YES; + LastUpgradeCheck = 0710; }; buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "Hedgewars" */; - compatibilityVersion = "Xcode 3.1"; + compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 1; knownRegions = ( @@ -1319,6 +1492,8 @@ Bulgarian, Portuguese, Romanian, + ru, + tr, ); mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; projectDirPath = ""; @@ -1434,27 +1609,42 @@ 611E12FF117BBBDA0044B62F /* Entitlements-Development.plist in Resources */, 6165925311CA9CB400D6E256 /* MainMenuViewController-iPad.xib in Resources */, 6165925511CA9CB400D6E256 /* MapConfigViewController-iPad.xib in Resources */, + F60D04791BD137B5003ACB00 /* bullet.png in Resources */, 61F9040911DF58B00068B24D /* settingsButton.png in Resources */, 61F9040B11DF59370068B24D /* background.png in Resources */, 61EBA62A11DFF2BC0048B68A /* title~iphone.png in Resources */, 61F7A43811E290650040BA66 /* Icon-72.png in Resources */, + F60D04781BD137B5003ACB00 /* bullet_filled@2x.png in Resources */, 61F7A43911E290650040BA66 /* Icon-Small-50.png in Resources */, + F60D04871BD137B5003ACB00 /* teams_filled.png in Resources */, 61F7A43A11E290650040BA66 /* Icon-Small.png in Resources */, 61F7A43C11E290650040BA66 /* Icon.png in Resources */, + F65724FE1B7E784700A86262 /* helpbottom.png in Resources */, 61F7A43E11E290650040BA66 /* iTunesArtwork.png in Resources */, + F60D04811BD137B5003ACB00 /* heart.png in Resources */, + F65E1DC11B9B95A400A78ADF /* Icon-76@2x.png in Resources */, 6129B9F711EFB04D0017E305 /* denied.png in Resources */, 61F2E7CF1205EDE0005734F7 /* AboutViewController.xib in Resources */, + F60D047C1BD137B5003ACB00 /* flower_filled@2x.png in Resources */, 61F2E7EC12060E31005734F7 /* checkbox.png in Resources */, + F60D04821BD137B5003ACB00 /* heart@2x.png in Resources */, 615AD96212073B4D00F2FF04 /* startGameButton.png in Resources */, + F60D048A1BD137B5003ACB00 /* teams@2x.png in Resources */, + F6D7E09F1B76884E004F3BCF /* Default-568h@2x.png in Resources */, + F60D047E1BD137B5003ACB00 /* flower@2x.png in Resources */, + F60D04841BD137B5003ACB00 /* target_filled@2x.png in Resources */, 615AD9E9120764CA00F2FF04 /* backButton.png in Resources */, 615AD9EB1207654E00F2FF04 /* helpButton.png in Resources */, + F60D04891BD137B5003ACB00 /* teams.png in Resources */, 611EE974122A9C4100DF6938 /* clickSound.caf in Resources */, 611EE9DA122AA10A00DF6938 /* selSound.caf in Resources */, 6199E86D12464A8E00DADF8C /* surprise.png in Resources */, 611D9BFC12497E9800008271 /* SavedGamesViewController.xib in Resources */, 6147DAD31253DCDE0010357E /* savesButton.png in Resources */, 610D5FB21270E2660033333A /* Icon-Small@2x.png in Resources */, + F6F07BDF1B7E72D40010E48F /* HelpPageLobbyViewController-iPhone.xib in Resources */, 610D5FB31270E26C0033333A /* Icon@2x.png in Resources */, + F65E1DC01B9B95A400A78ADF /* Icon-76.png in Resources */, 61A670C012747D9B00B06CE7 /* Default.png in Resources */, 61A670C112747DB900B06CE7 /* MainMenuViewController-iPhone.xib in Resources */, 61A670C212747DBD00B06CE7 /* MapConfigViewController-iPhone.xib in Resources */, @@ -1464,15 +1654,24 @@ 61D3D2A51290E03A003CE7C3 /* irc.png in Resources */, 6172FED91298CF9800D73365 /* background~iphone.png in Resources */, 6172FEEF1298D25D00D73365 /* mediumBackground~ipad.png in Resources */, + F65E1DBF1B9B95A400A78ADF /* Icon-60@2x.png in Resources */, 6172FEF11298D25D00D73365 /* smallerBackground~ipad.png in Resources */, + F60D047A1BD137B5003ACB00 /* bullet@2x.png in Resources */, + F60D04861BD137B5003ACB00 /* target@2x.png in Resources */, 6172FEF21298D25D00D73365 /* smallerBackground~iphone.png in Resources */, 61889985129995B500D55FD6 /* title~ipad.png in Resources */, + F60D047D1BD137B5003ACB00 /* flower.png in Resources */, + F60D04801BD137B5003ACB00 /* heart_filled@2x.png in Resources */, 615FEAE212A2A6640098EE92 /* localplayButton~ipad.png in Resources */, 615FEAE312A2A6640098EE92 /* localplayButton~iphone.png in Resources */, + F65725001B7E784700A86262 /* helpplain.png in Resources */, 61188BF712A6FE5A0026C5DA /* backButton@2x.png in Resources */, 61188BF812A6FE5C0026C5DA /* background@2x~iphone.png in Resources */, 61188BF912A6FE5D0026C5DA /* checkbox@2x.png in Resources */, 61188BFB12A6FE610026C5DA /* Default-ipad-Landscape.png in Resources */, + F60D047B1BD137B5003ACB00 /* flower_filled.png in Resources */, + F60D04771BD137B5003ACB00 /* bullet_filled.png in Resources */, + F60D04881BD137B5003ACB00 /* teams_filled@2x.png in Resources */, 61188BFC12A6FE630026C5DA /* Default@2x.png in Resources */, 61188BFD12A6FE730026C5DA /* fb@2x.png in Resources */, 61188BFE12A6FE7C0026C5DA /* irc@2x.png in Resources */, @@ -1481,10 +1680,15 @@ 61188C0412A6FE880026C5DA /* savesButton@2x.png in Resources */, 61188C0512A6FE8F0026C5DA /* Data in Resources */, 61188C0612A6FE950026C5DA /* smallerBackground@2x~iphone.png in Resources */, + F67FC8161BEC17AC00A9DC75 /* Appirater.bundle in Resources */, + F65724FD1B7E784700A86262 /* helpabove.png in Resources */, + F6F07BDE1B7E72D40010E48F /* HelpPageLobbyViewController-iPad.xib in Resources */, 61188C0712A6FE960026C5DA /* settingsButton@2x.png in Resources */, 61188C0812A6FE9A0026C5DA /* title@2x~iphone.png in Resources */, + F65724FF1B7E784700A86262 /* helpleft.png in Resources */, 61188C0912A6FE9C0026C5DA /* tw@2x.png in Resources */, 6174F7C812CD62E300205D6F /* smallerTitle.png in Resources */, + F65725011B7E784700A86262 /* helpright.png in Resources */, 6174F7C912CD62E300205D6F /* smallerTitle@2x.png in Resources */, 6167A6771391514600AA6D07 /* RestoreViewController-iPhone.xib in Resources */, 6167A72D13919E6800AA6D07 /* RestoreViewController-iPad.xib in Resources */, @@ -1496,12 +1700,15 @@ 6167C8F81429502C003DD50F /* robotBadge@2x.png in Resources */, 6167C8F91429502C003DD50F /* star.png in Resources */, 6167C8FA1429502C003DD50F /* star@2x.png in Resources */, + F60D047F1BD137B5003ACB00 /* heart_filled.png in Resources */, + F60D04831BD137B5003ACB00 /* target_filled.png in Resources */, 6167CA37142A6ED7003DD50F /* bot0.png in Resources */, 6167CA38142A6ED7003DD50F /* bot0@2x.png in Resources */, 6167CA39142A6ED7003DD50F /* bot1.png in Resources */, 6167CA3A142A6ED7003DD50F /* bot1@2x.png in Resources */, 6167CA3B142A6ED7003DD50F /* bot2.png in Resources */, 6167CA3C142A6ED7003DD50F /* bot2@2x.png in Resources */, + F60D04851BD137B5003ACB00 /* target.png in Resources */, 6167CA3D142A6ED7003DD50F /* bot3.png in Resources */, 6167CA3E142A6ED7003DD50F /* bot3@2x.png in Resources */, 6167CA3F142A6ED7003DD50F /* bot4.png in Resources */, @@ -1553,7 +1760,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "SOURCE_DIR=${PROJECT_DIR}/../../\n\n#copy new stuff over old stuff\nrm -rf ${PROJECT_DIR}/Data\n\necho \"Copying Data...\"\ncp -R ${SOURCE_DIR}/share/hedgewars/Data ${PROJECT_DIR}/Data\n\n#copy some other files\necho \"Fetching additional graphics...\"\nmkdir -p ${PROJECT_DIR}/Data/Graphics/Icons\ncp ${SOURCE_DIR}/QTfrontend/res/{btn*,icon*,StatsMedal*,ammopic*}.png ${PROJECT_DIR}/Data/Graphics/Icons/\ncp -R ${SOURCE_DIR}/project_files/Android-build/SDL-android-project/assets/Data/Graphics/Buttons ${PROJECT_DIR}/Data/Graphics/\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 ${SOURCE_DIR}/project_files/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\""; + shellScript = "SOURCE_DIR=${PROJECT_DIR}/../../\n\n#copy new stuff over old stuff\nrm -rf ${PROJECT_DIR}/Data\n\necho \"Copying Data...\"\ncp -R ${SOURCE_DIR}/share/hedgewars/Data ${PROJECT_DIR}/Data\n\n#copy some other files\necho \"Fetching additional graphics...\"\nmkdir -p ${PROJECT_DIR}/Data/Graphics/Icons\ncp ${SOURCE_DIR}/QTfrontend/res/{btn*,icon*,StatsMedal*,ammopic*}.png ${PROJECT_DIR}/Data/Graphics/Icons/\ncp -R ${SOURCE_DIR}/project_files/Android-build/SDL-android-project/assets/Data/Graphics/Buttons ${PROJECT_DIR}/Data/Graphics/\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 all CMake generated files\nfind ${PROJECT_DIR}/Data -name CMakeFiles -type d -exec rm -r {} +\nfind ${PROJECT_DIR}/Data -name Makefile -delete\nfind ${PROJECT_DIR}/Data -name *.cmake -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/{FlightJoust,ClimbHome}\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#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,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\""; }; 61806B78170B83EA00C601BC /* config.inc */ = { isa = PBXShellScriptBuildPhase; @@ -1568,7 +1775,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "HG=/usr/local/bin/hg\nSOURCE_DIR=${PROJECT_DIR}/../../\n\n#create config.inc\necho \"Updating config file...\"\nPRON=`grep HEDGEWARS_PROTO_VER ${SOURCE_DIR}/CMakeLists.txt | grep -o -E [0-9]+`\nMAJN=`grep CPACK_PACKAGE_VERSION_MAJOR ${SOURCE_DIR}/CMakeLists.txt | grep -o -E \"[0-9]+\"`\nMINN=`grep CPACK_PACKAGE_VERSION_MINOR ${SOURCE_DIR}/CMakeLists.txt | grep -o -E \"[0-9]+\"`\nPATN=`grep CPACK_PACKAGE_VERSION_PATCH ${SOURCE_DIR}/CMakeLists.txt | grep -o -E \"[0-9]+\"`\nREVN=`$HG id -n ${SOURCE_DIR}`\nHASH=`$HG id -i ${SOURCE_DIR}`\n\necho \"{Do not change this file, use the project target to regenerate}\" > ${PROJECT_DIR}/config.inc\necho \"const cNetProtoVersion = $PRON;\" >> ${PROJECT_DIR}/config.inc\necho \"const cVersionString = '$MAJN.$MINN.$PATN';\" >> ${PROJECT_DIR}/config.inc\necho \"const cRevisionString = '$REVN';\" >> ${PROJECT_DIR}/config.inc\necho \"const cHashString = '$HASH';\" >> ${PROJECT_DIR}/config.inc\n"; + shellScript = "HG=/usr/local/bin/hg\nSOURCE_DIR=${PROJECT_DIR}/../../\n\n#create config.inc\necho \"Updating config file...\"\nPRON=`grep HEDGEWARS_PROTO_VER ${SOURCE_DIR}/CMakeLists.txt | grep -o -E [0-9]+`\nMAJN=`grep CPACK_PACKAGE_VERSION_MAJOR ${SOURCE_DIR}/CMakeLists.txt | grep -o -E \"[0-9]+\"`\nMINN=`grep CPACK_PACKAGE_VERSION_MINOR ${SOURCE_DIR}/CMakeLists.txt | grep -o -E \"[0-9]+\"`\nPATN=`grep CPACK_PACKAGE_VERSION_PATCH ${SOURCE_DIR}/CMakeLists.txt | grep -o -E \"[0-9]+\"`\nREVN=`$HG id -n ${SOURCE_DIR}`\nHASH=`$HG id -i ${SOURCE_DIR}`\n\necho \"{Do not change this file, use the project target to regenerate}\" > ${PROJECT_DIR}/config.inc\necho \"const cNetProtoVersion = $PRON;\" >> ${PROJECT_DIR}/config.inc\necho \"const cVersionString = '$MAJN.$MINN.$PATN';\" >> ${PROJECT_DIR}/config.inc\necho \"const cRevisionString = '$REVN';\" >> ${PROJECT_DIR}/config.inc\necho \"const cHashString = '$HASH';\" >> ${PROJECT_DIR}/config.inc\necho \"const cDefaultPathPrefix = '';\" >> ${PROJECT_DIR}/config.inc\n"; }; 9283011B0F10CB2D00CC5A3C /* Build libfpc.a */ = { isa = PBXShellScriptBuildPhase; @@ -1584,7 +1791,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "# Build libfpc.a\n# 9 July 2006 (Jonas Maebe)\n# * original version\n# 15 September 2006 (Erling Johansen)\n# * simplified\n# 26 April 2007 (Jonas Maebe)\n# * added support for ppc64/x86_64 (future proofing)\n# 4 August 2007 (Jonas Maebe)\n# * call ranlib after ar so the toc of the library is up-to-date\n# 3 January 2009 (Jonas Maebe)\n# * support for ARM\n# 24 October 2009 (Jonas Maebe)\n# * don't hardcode version 2.3.1 anymore under certain circumstances\n# * use the FPC_RTL_UNITS_BASE setting\n# 13 December 2009 (Jonas Maebe)\n# * use new FPC_COMPILER_BINARY_DIR setting to make it easier to change the used FPC version\n\nrm -f \"$TARGET_TEMP_DIR\"/*.a\nnarch=\n\ntemparchs=`echo $ARCHS|sed -e 's/arm[^\\w]*/arm\\\n/'|sort -u`\nfor arch in $temparchs\ndo\n\ttargetos=darwin;\n\tcase $arch in\n\t\tppc) fpc_arch=ppc; fpc_rtl=powerpc ;;\n\t\ti386) fpc_arch=386; fpc_rtl=i386; targetos=iphonesim ;;\n\t\tppc64) fpc_arch=ppc64; fpc_rtl=powerpc64 ;;\n\t\tx86_64) fpc_arch=x64; fpc_rtl=x86_64 ;;\n\t\tarm*) fpc_arch=arm; fpc_rtl=arm ;;\n\t\t*) continue\n\tesac\n\tif test -e \"${FPC_COMPILER_BINARY_DIR}\"/ppc${fpc_arch}\n\tthen\n\t\tupath=\"$FPC_RTL_UNITS_BASE\"/`\"${FPC_COMPILER_BINARY_DIR}\"/ppc${fpc_arch} -iV`/units/${fpc_rtl}-${targetos}\n\t\tar -q \"$TARGET_TEMP_DIR\"/libfpc${narch}.a `ls \"$upath\"/*/*.o | grep -v 'darwin/fv/'`\n\t\tranlib \"$TARGET_TEMP_DIR\"/libfpc${narch}.a\n\t\tnarch=${narch}x\n\telse\n\t\techo error: can\\'t build libfpc.a for $arch \\(${FPC_COMPILER_BINARY_DIR}/ppc${fpc_arch} not found, derived from FPC_COMPILER_BINARY_DIR project setting\\)\n\tfi\ndone\n\nif test ${#narch} -gt 1\nthen\n\tlipo -create \"$TARGET_TEMP_DIR\"/libfpc*.a -output \"$TARGET_BUILD_DIR\"/libfpc.a\n\trm -f \"$TARGET_TEMP_DIR\"/*.a\nelse\n\tmv \"$TARGET_TEMP_DIR\"/libfpc.a \"$TARGET_BUILD_DIR\"\nfi\n"; + shellScript = "# Build libfpc.a\n# 9 July 2006 (Jonas Maebe)\n# * original version\n# 15 September 2006 (Erling Johansen)\n# * simplified\n# 26 April 2007 (Jonas Maebe)\n# * added support for ppc64/x86_64 (future proofing)\n# 4 August 2007 (Jonas Maebe)\n# * call ranlib after ar so the toc of the library is up-to-date\n# 3 January 2009 (Jonas Maebe)\n# * support for ARM\n# 24 October 2009 (Jonas Maebe)\n# * don't hardcode version 2.3.1 anymore under certain circumstances\n# * use the FPC_RTL_UNITS_BASE setting\n# 13 December 2009 (Jonas Maebe)\n# * use new FPC_COMPILER_BINARY_DIR setting to make it easier to change the used FPC version\n\nrm -f \"$TARGET_TEMP_DIR\"/*.a\nnarch=\n\n#temparchs=`echo $ARCHS|sed -e 's/arm[^\\w]*/arm\\\n#/'|sort -u`\ntemparchs=`echo $ARCHS|sort -u`\necho $temparchs\nfor arch in $temparchs\ndo\n\ttargetos=darwin;\n\tcase $arch in\n arm64) fpc_arch=rossa64; fpc_rtl=aarch64 ;;\n armv7) fpc_arch=rossarm; fpc_rtl=arm ;;\n x86_64) fpc_arch=x64; fpc_rtl=x86_64; targetos=iphonesim ;;\n# ppc) fpc_arch=ppc; fpc_rtl=powerpc ;;\n#\t\ti386) fpc_arch=386; fpc_rtl=i386; targetos=iphonesim ;;\n#\t\tppc64) fpc_arch=ppc64; fpc_rtl=powerpc64 ;;\n#\t\tx86_64) fpc_arch=x64; fpc_rtl=x86_64 ;;\n#\t\tarm*) fpc_arch=arm; fpc_rtl=arm ;;\n\t\t*) continue\n\tesac\n\tif test -e \"${FPC_COMPILER_BINARY_DIR}\"/ppc${fpc_arch}\n\tthen\n\t\tupath=\"$FPC_RTL_UNITS_BASE\"/`\"${FPC_COMPILER_BINARY_DIR}\"/ppc${fpc_arch} -iV`/units/${fpc_rtl}-${targetos}\n\t\tar -q \"$TARGET_TEMP_DIR\"/libfpc${narch}.a `ls \"$upath\"/*/*.o | grep -v 'darwin/fv/'`\n\t\tranlib \"$TARGET_TEMP_DIR\"/libfpc${narch}.a\n\t\tnarch=${narch}x\n\telse\n\t\techo error: can\\'t build libfpc.a for $arch \\(${FPC_COMPILER_BINARY_DIR}/ppc${fpc_arch} not found, derived from FPC_COMPILER_BINARY_DIR project setting\\)\n\tfi\ndone\n \nif test ${#narch} -gt 1\nthen\n\tlipo -create \"$TARGET_TEMP_DIR\"/libfpc*.a -output \"$TARGET_BUILD_DIR\"/libfpc.a\n\trm -f \"$TARGET_TEMP_DIR\"/*.a\nelse\n\tmv \"$TARGET_TEMP_DIR\"/libfpc.a \"$TARGET_BUILD_DIR\"\nfi\n"; }; 928301560F10E04C00CC5A3C /* Compile Pascal Sources */ = { isa = PBXShellScriptBuildPhase; @@ -1599,7 +1806,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "# Compile Pascal Sources\n# 15sep06,ejo written.\n# 26 April 2007 - Jonas Maebe\n# * support for ppc64 and x86_64\n# * don't run when cleaning (in case running scripts when cleaning is ever fixed by Apple)\n# * split the options in FPC_COMMON_FLAGS (common to all configurations) and FPC_CFG_SPECIFIC_FLAGS (per configuration)\n# 4 January 2009 - Jonas Maebe\n# * support for ARM\n# 24 October 2009 - Jonas Maebe\n# * don't hardcode 2.3.1 in some cases anymore\n# 13 December 2009 (Jonas Maebe)\n# * use new FPC_COMPILER_BINARY_DIR setting to make it easier to change the used FPC version\n\nif [ x\"$ACTION\" != \"xbuild\" ]; then\n # in case running scripts during cleaning gets fixed\n exit 0\nfi\n\nif test ! -e \"$FPC_MAIN_FILE\"\nthen\n\techo error: FPC_MAIN_FILE not found \\($FPC_MAIN_FILE\\)\n\texit 2\nfi\n\nfor variant in $BUILD_VARIANTS\ndo\n\tfor arch in $ARCHS\n\tdo\n\t\ttargetos=darwin;\n\t\tcase $arch in\n\t\t\tppc) fpc_arch=ppc; fpc_rtl=powerpc ;;\n\t\t\ti386) fpc_arch=386; fpc_rtl=i386; targetos=iphonesim ;;\n\t\t\tppc64) fpc_arch=ppc64; fpc_rtl=powerpc64 ;;\n\t\t\tx86_64) fpc_arch=x64; fpc_rtl=x86_64 ;;\n\t\t\tarm*) fpc_arch=arm; fpc_rtl=arm ;;\n\t\t\t*) continue\n\t\tesac\n\n\t\tapp_target_temp_dir=$CONFIGURATION_TEMP_DIR/`basename \"$PROJECT_TEMP_DIR\"`\n\t\tout_dir=$app_target_temp_dir/`basename \"$DERIVED_SOURCES_DIR\"`-$variant/$arch\n\t\tfpccompiler=\"${FPC_COMPILER_BINARY_DIR}/ppc${fpc_arch}\"\n\t\tif test -e \"$fpccompiler\"\n\t\tthen\n\t\t\tfpcversion=`\"$fpccompiler\" -iV`\n\t\t\tmainunitdir=\"$FPC_RTL_UNITS_BASE/$fpcversion/units/${fpc_rtl}-${targetos}/\"\n\t\t\tmkdir -p \"$out_dir\"\n\t\t\tcd \"$out_dir\"\n\t\t\techo \"Compiling to $out_dir\"\n\t\t\trm -f compilefailed\n\t\n\t\t\t# delete any ppu files for which the \".s\" file was somehow deleted (Xcode does that sometimes in case of errors),\n\t\t\t# so that FPC will recompile the unit\n\t\t\tfor file in *.ppu\n\t\t\tdo\n\t\t\t\tasmname=`basename \"$file\" ppu`s\n\t\t\t\tif [ ! -f \"$asmname\" ]; then\n\t\t\t\t\t# can fail in case there are no .ppu files, since then it will try to erase the file with name '*.ppu'\n\t\t\t\t\t# -> use -f so it won't give an error message\n\t\t\t\t\trm -f \"$file\"\n\t\t\t\tfi\n\t\t\tdone\n\n\t\t\techo $fpccompiler -n -l -viwn -a -s -vbr -FE. $FPC_COMMON_OPTIONS $FPC_SPECIFIC_OPTIONS '\\' >ppccmd.sh\n\t\t\techo -Fi\\\"`dirname \"$FPC_MAIN_FILE\"`\\\" '\\' >>ppccmd.sh\n\t\t\techo -Fu\"$mainunitdir/*\" -Fu\"$mainunitdir/rtl\" '\\' >>ppccmd.sh\n\t\t\t# allow FPC_UNIT_PATHS to override default search directory\n\t\t\techo $FPC_UNIT_PATHS '\\' >>ppccmd.sh\n\t\t\techo \\\"$FPC_MAIN_FILE\\\" >>ppccmd.sh\n\t\t\t# cat ppccmd.sh\n\n\t\t\t/bin/sh ppccmd.sh\n\t\t\tif [ $? != 0 ]; then\n\t\t\t\ttouch \"$out_dir\"/compilefailed\n\t\t\t\texit 1\n\t\t\tfi\n\t\telse\n\t\t\ttouch \"$out_dir\"/compilefailed\n\t\t\techo $FPC_MAIN_FILE:1: error: 1: can\\'t compile for $arch \\(ppc${fpc_arch} not found\\)\n\t\t\texit 2\n\t\tfi\n\tdone\ndone\n"; + shellScript = "# Compile Pascal Sources\n# 15sep06,ejo written.\n# 26 April 2007 - Jonas Maebe\n# * support for ppc64 and x86_64\n# * don't run when cleaning (in case running scripts when cleaning is ever fixed by Apple) (removed)\n# * split the options in FPC_COMMON_FLAGS (common to all configurations) and FPC_CFG_SPECIFIC_FLAGS (per configuration)\n# 4 January 2009 - Jonas Maebe\n# * support for ARM\n# 24 October 2009 - Jonas Maebe\n# * don't hardcode 2.3.1 in some cases anymore\n# 13 December 2009 (Jonas Maebe)\n# * use new FPC_COMPILER_BINARY_DIR setting to make it easier to change the used FPC version\n\nif test ! -e \"$FPC_MAIN_FILE\"\nthen\n\techo error: FPC_MAIN_FILE not found \\($FPC_MAIN_FILE\\)\n\texit 2\nfi\n\nfor variant in $BUILD_VARIANTS\ndo\n\tfor arch in $ARCHS\n\tdo\n\t\ttargetos=darwin;\n\t\tcase $arch in\n arm64) fpc_arch=rossa64; fpc_rtl=aarch64 ;;\n armv7) fpc_arch=rossarm; fpc_rtl=arm ;;\n x86_64) fpc_arch=x64; fpc_rtl=x86_64; targetos=iphonesim ;;\n#\t\t\tppc) fpc_arch=ppc; fpc_rtl=powerpc ;;\n#\t\t\ti386) fpc_arch=386; fpc_rtl=i386; targetos=iphonesim ;;\n#\t\t\tppc64) fpc_arch=ppc64; fpc_rtl=powerpc64 ;;\n#\t\t\tx86_64) fpc_arch=x64; fpc_rtl=x86_64 ;;\n#\t\t\tarm*) fpc_arch=arm; fpc_rtl=arm ;;\n\t\t\t*) continue\n\t\tesac\n\n\t\tapp_target_temp_dir=$CONFIGURATION_TEMP_DIR/`basename \"$PROJECT_TEMP_DIR\"`\n\t\tout_dir=$app_target_temp_dir/`basename \"$DERIVED_SOURCES_DIR\"`-$variant/$arch\n\t\tfpccompiler=\"${FPC_COMPILER_BINARY_DIR}/ppc${fpc_arch}\"\n\t\tif test -e \"$fpccompiler\"\n\t\tthen\n\t\t\tfpcversion=`\"$fpccompiler\" -iV`\n\t\t\tmainunitdir=\"$FPC_RTL_UNITS_BASE/$fpcversion/units/${fpc_rtl}-${targetos}/\"\n\t\t\tmkdir -p \"$out_dir\"\n\t\t\tcd \"$out_dir\"\n\t\t\techo \"Compiling to $out_dir\"\n\t\t\trm -f compilefailed\n\t\n\t\t\t# delete any ppu files for which the \".s\" file was somehow deleted (Xcode does that sometimes in case of errors),\n\t\t\t# so that FPC will recompile the unit\n\t\t\tfor file in *.ppu\n\t\t\tdo\n\t\t\t\tasmname=`basename \"$file\" ppu`s\n\t\t\t\tif [ ! -f \"$asmname\" ]; then\n\t\t\t\t\t# can fail in case there are no .ppu files, since then it will try to erase the file with name '*.ppu'\n\t\t\t\t\t# -> use -f so it won't give an error message\n\t\t\t\t\trm -f \"$file\"\n\t\t\t\tfi\n\t\t\tdone\n\n\t\t\techo $fpccompiler -n -l -viwn -a -s -vbr -FE. $FPC_COMMON_OPTIONS $FPC_SPECIFIC_OPTIONS '\\' >ppccmd.sh\n\t\t\techo -Fi\\\"`dirname \"$FPC_MAIN_FILE\"`\\\" '\\' >>ppccmd.sh\n\t\t\techo -Fu\"$mainunitdir/*\" -Fu\"$mainunitdir/rtl\" '\\' >>ppccmd.sh\n\t\t\t# allow FPC_UNIT_PATHS to override default search directory\n\t\t\techo $FPC_UNIT_PATHS '\\' >>ppccmd.sh\n\t\t\techo \\\"$FPC_MAIN_FILE\\\" >>ppccmd.sh\n\t\t\t# cat ppccmd.sh\n\n\t\t\t/bin/sh ppccmd.sh\n\t\t\tif [ $? != 0 ]; then\n\t\t\t\ttouch \"$out_dir\"/compilefailed\n\t\t\t\texit 1\n\t\t\tfi\n\t\telse\n\t\t\ttouch \"$out_dir\"/compilefailed\n\t\t\techo $FPC_MAIN_FILE:1: error: 1: can\\'t compile for $arch \\(ppc${fpc_arch} not found\\)\n\t\t\texit 2\n\t\tfi\n\tdone\ndone\n"; }; /* End PBXShellScriptBuildPhase section */ @@ -1615,6 +1822,7 @@ 61798820114AA34C00BA94A9 /* uAIActions.pas in Sources */, 61798821114AA34C00BA94A9 /* uAIAmmoTests.pas in Sources */, 61798822114AA34C00BA94A9 /* uAIMisc.pas in Sources */, + F6BA38461BA7A834005D16EA /* GameLogViewController.m in Sources */, 61798823114AA34C00BA94A9 /* uAmmos.pas in Sources */, 61798824114AA34C00BA94A9 /* uChat.pas in Sources */, 61798825114AA34C00BA94A9 /* uCollisions.pas in Sources */, @@ -1627,7 +1835,9 @@ 6179882D114AA34C00BA94A9 /* uLand.pas in Sources */, 6179882E114AA34C00BA94A9 /* uLandGraphics.pas in Sources */, 6179882F114AA34C00BA94A9 /* uLandObjects.pas in Sources */, + F6756D801BD8550500B6AB6B /* LabelWithIBLocalization.m in Sources */, 61798830114AA34C00BA94A9 /* uLandTemplates.pas in Sources */, + F6D7E0C31B768F19004F3BCF /* uLandGenTemplateBased.pas in Sources */, 61798831114AA34C00BA94A9 /* uLandTexture.pas in Sources */, 61798832114AA34C00BA94A9 /* uLocale.pas in Sources */, 61798833114AA34C00BA94A9 /* uMisc.pas in Sources */, @@ -1654,7 +1864,6 @@ 6165921B11CA9BA200D6E256 /* SchemeWeaponConfigViewController.m in Sources */, 6165921C11CA9BA200D6E256 /* SingleSchemeViewController.m in Sources */, 6165921D11CA9BA200D6E256 /* SingleTeamViewController.m in Sources */, - 6165921E11CA9BA200D6E256 /* SettingsContainerViewController.m in Sources */, 6165921F11CA9BA200D6E256 /* TeamConfigViewController.m in Sources */, 6165922011CA9BA200D6E256 /* TeamSettingsViewController.m in Sources */, 6165922111CA9BA200D6E256 /* VoicesViewController.m in Sources */, @@ -1677,10 +1886,12 @@ 61006F95128DE31F00EBA7F7 /* CreationChamber.m in Sources */, 61A4A39412A5CCC2004D81E6 /* uCommandHandlers.pas in Sources */, 61A4A39512A5CCC2004D81E6 /* uCommands.pas in Sources */, + F6448CE31BD2E00500C31C8C /* TableViewControllerWithDoneButton.m in Sources */, 61A4A39612A5CCC2004D81E6 /* uDebug.pas in Sources */, 61A4A39712A5CCC2004D81E6 /* uGearsRender.pas in Sources */, 61A4A39812A5CCC2004D81E6 /* uRender.pas in Sources */, 61A4A39912A5CCC2004D81E6 /* uRenderUtils.pas in Sources */, + F6F7DA8F1BE18F5700432EA7 /* UITableViewCell+FindTable.m in Sources */, 61A4A39A12A5CCC2004D81E6 /* uSinTable.pas in Sources */, 61A4A39B12A5CCC2004D81E6 /* uTextures.pas in Sources */, 61A4A39C12A5CCC2004D81E6 /* uTypes.pas in Sources */, @@ -1689,11 +1900,12 @@ 61A4A3A212A5CD56004D81E6 /* uCaptions.pas in Sources */, 61E5D68D12AB006F00566F29 /* uLandPainted.pas in Sources */, 61F544C712AF1748007FD913 /* HoldTableViewCell.m in Sources */, - 61AC067412B2E32D000B52A2 /* Appirater.m in Sources */, 61E2E12E12BAAEE30051B659 /* ServerProtocolNetwork.m in Sources */, 61B7A33812CC21080086B604 /* StatsPageViewController.m in Sources */, + F6D7E0C41B768F19004F3BCF /* uLandUtils.pas in Sources */, 61EDB5B0135B3F97009B29A6 /* GameInterfaceBridge.m in Sources */, 61A976B3136F668500DD9878 /* uCursor.pas in Sources */, + F67FC8121BEC06E700A9DC75 /* Appirater.m in Sources */, 6167A6761391514600AA6D07 /* RestoreViewController.m in Sources */, 61C28D3F142D380400DA16C2 /* AudioManagerController.m in Sources */, 611D7A50142FDCD3006E0798 /* uTouch.pas in Sources */, @@ -1709,11 +1921,13 @@ 615E76BC14E4421200FBA131 /* MGSplitCornersView.m in Sources */, 615E76BD14E4421200FBA131 /* MGSplitDividerView.m in Sources */, 615E76BE14E4421200FBA131 /* MGSplitViewController.m in Sources */, + F6F07BE01B7E72D40010E48F /* HelpPageLobbyViewController.m in Sources */, 615BE3D4155C5DDF003CA34D /* uInputHandler.pas in Sources */, 619349C8160BAF3E00A08518 /* uAILandMarks.pas in Sources */, 619349C9160BAF3E00A08518 /* uGearsHandlers.pas in Sources */, 619349CA160BAF3E00A08518 /* uGearsHandlersRope.pas in Sources */, 610FB7C81661390E002FB2A7 /* uPhysFSLayer.pas in Sources */, + F6D7E0C21B768F19004F3BCF /* uLandGenPerlin.pas in Sources */, 61B37A1F17837C78009F283D /* ArgParsers.pas in Sources */, 61B37A2017837C78009F283D /* uVisualGearsList.pas in Sources */, 61B37A80178381DB009F283D /* uGearsHandlersMess.pas in Sources */, @@ -1780,13 +1994,14 @@ 6115652D147F4C52006729A9 /* French */, 61156530147F4D10006729A9 /* Polish */, 61177BAA148A661600686905 /* German */, - 61177BAC148A671600686905 /* Turkish */, 61177BE4148B881C00686905 /* Danish */, 617BC22D1490210E00E1C294 /* Italian */, 619BCEC41495615700C1C409 /* Bulgarian */, 61D08D8714AEA9670007C078 /* Japanese */, 61C6783F14B3DD020087425A /* Portuguese */, 6154A53114C37E4A00F6EEF6 /* Romanian */, + F65725291B7EB9CC00A86262 /* ru */, + F67FC81F1BEC280D00A9DC75 /* tr */, ); name = About.strings; sourceTree = ""; @@ -1799,13 +2014,14 @@ 6115652C147F4C4C006729A9 /* French */, 61156531147F4D17006729A9 /* Polish */, 61177BA7148A658900686905 /* German */, - 61177BAD148A672000686905 /* Turkish */, 61177BF0148B882500686905 /* Danish */, 617BC2391490211500E1C294 /* Italian */, 619BCED01495615F00C1C409 /* Bulgarian */, 61D08D8814AEA9700007C078 /* Japanese */, 61C6784B14B3DD0B0087425A /* Portuguese */, 6154A53E14C37E5400F6EEF6 /* Romanian */, + F657252A1B7EB9CC00A86262 /* ru */, + F67FC8201BEC280D00A9DC75 /* tr */, ); name = Localizable.strings; sourceTree = ""; @@ -1818,13 +2034,14 @@ 6115652B147F4C45006729A9 /* French */, 61156532147F4D1E006729A9 /* Polish */, 61177BA9148A660C00686905 /* German */, - 61177BAE148A672C00686905 /* Turkish */, 61177BF1148B882F00686905 /* Danish */, 617BC23A1490211F00E1C294 /* Italian */, 619BCED11495616700C1C409 /* Bulgarian */, 61D08D8914AEA9780007C078 /* Japanese */, 61C6784C14B3DD140087425A /* Portuguese */, 6154A54014C37EB100F6EEF6 /* Romanian */, + F657252B1B7EB9CC00A86262 /* ru */, + F67FC8211BEC280D00A9DC75 /* tr */, ); name = Scheme.strings; sourceTree = ""; @@ -1835,24 +2052,32 @@ 1D6058940D05DD3E006BFB54 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; GCC_DYNAMIC_NO_PIC = NO; GCC_GENERATE_TEST_COVERAGE_FILES = YES; GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = YES; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = Hedgewars_Prefix.pch; INFOPLIST_FILE = Info.plist; + PRODUCT_BUNDLE_IDENTIFIER = org.hedgewars.mobile; PRODUCT_NAME = Hedgewars; + PROVISIONING_PROFILE = ""; }; name = Debug; }; 1D6058950D05DD3E006BFB54 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = YES; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = Hedgewars_Prefix.pch; INFOPLIST_FILE = Info.plist; + PRODUCT_BUNDLE_IDENTIFIER = org.hedgewars.mobile; PRODUCT_NAME = Hedgewars; + PROVISIONING_PROFILE = ""; }; name = Release; }; @@ -1861,23 +2086,32 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; APPLY_RULES_IN_COPY_FILES = YES; - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "iPhone Distribution"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_BITCODE = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; FPC_COMMON_OPTIONS = "-l- -dIPHONEOS -Cs2000000 -B -vwi -Sgix -Fi${PROJECT_DIR}"; - FPC_COMPILER_BINARY_DIR = /usr/local/lib/fpc/2.7.1; + FPC_COMPILER_BINARY_DIR = /usr/local/lib/fpc/3.1.1; FPC_MAIN_FILE = "$(PROJECT_DIR)/../../hedgewars/hwLibrary.pas"; FPC_RTL_UNITS_BASE = /usr/local/lib/fpc; - FPC_SPECIFIC_OPTIONS = "-Ci- -Cr- -Co- -Os -Xs -Cfvfpv3 -dNOCONSOLE"; + FPC_SPECIFIC_OPTIONS = "-Ci- -Cr- -Co- -O2 -Xs -dNOCONSOLE"; FPC_UNITS_PATH = "-Fu\"$(PROJECT_DIR)\""; GCC_C_LANGUAGE_STANDARD = c99; GCC_DEBUGGING_SYMBOLS = default; GCC_DYNAMIC_NO_PIC = NO; GCC_FAST_MATH = YES; + GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = s; GCC_PREPROCESSOR_DEFINITIONS = ""; GCC_STRICT_ALIASING = YES; - GCC_THUMB_SUPPORT = NO; GCC_VERSION = com.apple.compilers.llvm.clang.1_0; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; @@ -1892,6 +2126,7 @@ GCC_WARN_SHADOW = YES; GCC_WARN_STRICT_SELECTOR_MATCH = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNKNOWN_PRAGMAS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_LABEL = YES; @@ -1902,21 +2137,18 @@ "\"$(SRCROOT)/../../../Library/SDL_net/\"", "\"$(SRCROOT)/../../../Library/SDL_mixer/\"", ); - IPHONEOS_DEPLOYMENT_TARGET = 3.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; LLVM_LTO = NO; ONLY_ACTIVE_ARCH = NO; OTHER_CODE_SIGN_FLAGS = ""; - OTHER_LDFLAGS = ( - "-lz", - "-Wl,-no_order_inits", - ); + OTHER_LDFLAGS = "-lz"; PREBINDING = NO; PROVISIONING_PROFILE = ""; "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; - VALID_ARCHS = "armv7 armv6"; + VALID_ARCHS = "armv7 x86_64 arm64"; WARNING_CFLAGS = ( "-Wall", "-Wbad-function-cast", @@ -1929,11 +2161,15 @@ 61022D7D12305A2800B08935 /* Distro AppStore */ = { isa = XCBuildConfiguration; buildSettings = { + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = YES; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = Hedgewars_Prefix.pch; INFOPLIST_FILE = Info.plist; + PRODUCT_BUNDLE_IDENTIFIER = org.hedgewars.mobile; PRODUCT_NAME = Hedgewars; + PROVISIONING_PROFILE = ""; }; name = "Distro AppStore"; }; @@ -1945,6 +2181,7 @@ GCC_ENABLE_FIX_AND_CONTINUE = NO; PREBINDING = NO; PRODUCT_NAME = fpc; + SKIP_INSTALL = YES; ZERO_LINK = NO; }; name = "Distro AppStore"; @@ -1965,24 +2202,33 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; APPLY_RULES_IN_COPY_FILES = YES; - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_ENTITLEMENTS = "Entitlements-Distribution.plist"; CODE_SIGN_IDENTITY = "iPhone Distribution"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_BITCODE = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; FPC_COMMON_OPTIONS = "-l- -dIPHONEOS -Cs2000000 -B -vwi -Sgix -Fi${PROJECT_DIR}"; - FPC_COMPILER_BINARY_DIR = /usr/local/lib/fpc/2.7.1; + FPC_COMPILER_BINARY_DIR = /usr/local/lib/fpc/3.1.1; FPC_MAIN_FILE = "$(PROJECT_DIR)/../../hedgewars/hwLibrary.pas"; FPC_RTL_UNITS_BASE = /usr/local/lib/fpc; - FPC_SPECIFIC_OPTIONS = "-dDEBUGFILE -O- -g -gl -gw2 -gt -ghttt -Xs- -Cfvfpv3"; + FPC_SPECIFIC_OPTIONS = "-dDEBUGFILE -O- -g -gl -gw2 -gt -ghttt -Xs-"; FPC_UNITS_PATH = "-Fu\"$(PROJECT_DIR)\""; GCC_C_LANGUAGE_STANDARD = c99; GCC_DEBUGGING_SYMBOLS = full; - GCC_DYNAMIC_NO_PIC = YES; + GCC_DYNAMIC_NO_PIC = NO; GCC_FAST_MATH = YES; + GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = DEBUG; GCC_STRICT_ALIASING = YES; - GCC_THUMB_SUPPORT = NO; GCC_VERSION = com.apple.compilers.llvm.clang.1_0; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; @@ -1997,6 +2243,7 @@ GCC_WARN_SHADOW = YES; GCC_WARN_STRICT_SELECTOR_MATCH = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNKNOWN_PRAGMAS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_LABEL = YES; @@ -2007,11 +2254,12 @@ "\"$(SRCROOT)/../../../Library/SDL_net/\"", "\"$(SRCROOT)/../../../Library/SDL_mixer/\"", ); - IPHONEOS_DEPLOYMENT_TARGET = 3.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; ONLY_ACTIVE_ARCH = NO; OTHER_LDFLAGS = ( "-lz", - "-Wl,-no_order_inits", + "-framework", + MessageUI, ); PREBINDING = NO; PROVISIONING_PROFILE = ""; @@ -2019,7 +2267,7 @@ SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; - VALID_ARCHS = "armv7 armv6"; + VALID_ARCHS = "armv7 x86_64 arm64"; WARNING_CFLAGS = ( "-Wall", "-Wbad-function-cast", @@ -2032,11 +2280,15 @@ 6137064C117B1CB3004EE44A /* Distro Adhoc */ = { isa = XCBuildConfiguration; buildSettings = { + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = YES; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = Hedgewars_Prefix.pch; INFOPLIST_FILE = Info.plist; + PRODUCT_BUNDLE_IDENTIFIER = org.hedgewars.mobile; PRODUCT_NAME = Hedgewars; + PROVISIONING_PROFILE = ""; }; name = "Distro Adhoc"; }; @@ -2048,6 +2300,7 @@ GCC_ENABLE_FIX_AND_CONTINUE = NO; PREBINDING = NO; PRODUCT_NAME = fpc; + SKIP_INSTALL = YES; ZERO_LINK = NO; }; name = "Distro Adhoc"; @@ -2092,6 +2345,7 @@ GCC_OPTIMIZATION_LEVEL = 0; PREBINDING = NO; PRODUCT_NAME = fpc; + SKIP_INSTALL = YES; }; name = Debug; }; @@ -2103,6 +2357,7 @@ GCC_ENABLE_FIX_AND_CONTINUE = NO; PREBINDING = NO; PRODUCT_NAME = fpc; + SKIP_INSTALL = YES; ZERO_LINK = NO; }; name = Release; @@ -2112,12 +2367,21 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; APPLY_RULES_IN_COPY_FILES = YES; - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_BITCODE = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; FPC_COMMON_OPTIONS = "-l- -dIPHONEOS -Cs2000000 -B -vwi -Sgix -Fi${PROJECT_DIR}"; - FPC_COMPILER_BINARY_DIR = /usr/local/lib/fpc/2.6.0; + FPC_COMPILER_BINARY_DIR = /usr/local/lib/fpc/3.1.1; FPC_MAIN_FILE = "$(PROJECT_DIR)/../../hedgewars/hwLibrary.pas"; FPC_RTL_UNITS_BASE = /usr/local/lib/fpc; FPC_SPECIFIC_OPTIONS = "-Tiphonesim -dDEBUGFILE -O- -g -gl -gw2 -gt -ghttt -Xs-"; @@ -2126,10 +2390,10 @@ GCC_DEBUGGING_SYMBOLS = full; GCC_DYNAMIC_NO_PIC = NO; GCC_FAST_MATH = YES; + GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = DEBUG; GCC_STRICT_ALIASING = YES; - GCC_THUMB_SUPPORT = NO; GCC_VERSION = com.apple.compilers.llvm.clang.1_0; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; @@ -2144,6 +2408,7 @@ GCC_WARN_SHADOW = YES; GCC_WARN_STRICT_SELECTOR_MATCH = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNKNOWN_PRAGMAS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_LABEL = YES; @@ -2154,11 +2419,12 @@ "\"$(SRCROOT)/../../../Library/SDL_net/\"", "\"$(SRCROOT)/../../../Library/SDL_mixer/\"", ); - IPHONEOS_DEPLOYMENT_TARGET = 3.0; - ONLY_ACTIVE_ARCH = NO; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + ONLY_ACTIVE_ARCH = YES; OTHER_LDFLAGS = ( "-lz", - "-Wl,-no_order_inits", + "-framework", + MessageUI, ); PREBINDING = NO; PROVISIONING_PROFILE = ""; @@ -2166,7 +2432,7 @@ SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = NO; - VALID_ARCHS = "armv7 armv6"; + VALID_ARCHS = "armv7 x86_64 arm64"; WARNING_CFLAGS = ( "-Wall", "-Wbad-function-cast", @@ -2181,24 +2447,33 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; APPLY_RULES_IN_COPY_FILES = YES; - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_ENTITLEMENTS = "Entitlements-Development.plist"; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_BITCODE = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; FPC_COMMON_OPTIONS = "-l- -dIPHONEOS -Cs2000000 -B -vwi -Sgix -Fi${PROJECT_DIR}"; - FPC_COMPILER_BINARY_DIR = /usr/local/lib/fpc/2.6.0; + FPC_COMPILER_BINARY_DIR = /usr/local/lib/fpc/3.1.1; FPC_MAIN_FILE = "$(PROJECT_DIR)/../../hedgewars/hwLibrary.pas"; FPC_RTL_UNITS_BASE = /usr/local/lib/fpc; - FPC_SPECIFIC_OPTIONS = "-Ci- -Cr- -Co- -Os -Xs -Cfvfpv3 -dDEBUGFILE"; + FPC_SPECIFIC_OPTIONS = "-Ci- -Cr- -Co- -O2 -Xs -dDEBUGFILE"; FPC_UNITS_PATH = "-Fu\"$(PROJECT_DIR)\""; GCC_C_LANGUAGE_STANDARD = c99; GCC_DEBUGGING_SYMBOLS = default; - GCC_DYNAMIC_NO_PIC = YES; + GCC_DYNAMIC_NO_PIC = NO; GCC_FAST_MATH = YES; + GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = s; GCC_PREPROCESSOR_DEFINITIONS = DEBUG; GCC_STRICT_ALIASING = YES; - GCC_THUMB_SUPPORT = NO; GCC_VERSION = com.apple.compilers.llvm.clang.1_0; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; @@ -2213,6 +2488,7 @@ GCC_WARN_SHADOW = YES; GCC_WARN_STRICT_SELECTOR_MATCH = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNKNOWN_PRAGMAS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_LABEL = YES; @@ -2223,12 +2499,13 @@ "\"$(SRCROOT)/../../../Library/SDL_net/\"", "\"$(SRCROOT)/../../../Library/SDL_mixer/\"", ); - IPHONEOS_DEPLOYMENT_TARGET = 3.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; LLVM_LTO = NO; ONLY_ACTIVE_ARCH = NO; OTHER_LDFLAGS = ( "-lz", - "-Wl,-no_order_inits", + "-framework", + MessageUI, ); PREBINDING = NO; PROVISIONING_PROFILE = ""; @@ -2236,7 +2513,7 @@ SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = NO; - VALID_ARCHS = "armv7 armv6"; + VALID_ARCHS = "armv7 x86_64 arm64"; WARNING_CFLAGS = ( "-Wall", "-Wbad-function-cast", diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Hedgewars.xcodeproj/project.xcworkspace/contents.xcworkspacedata --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Hedgewars.xcodeproj/project.xcworkspace/contents.xcworkspacedata Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,7 @@ + + + + + diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Hedgewars_Prefix.pch --- a/project_files/HedgewarsMobile/Hedgewars_Prefix.pch Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Hedgewars_Prefix.pch Tue Nov 10 20:43:13 2015 +0100 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Info.plist --- a/project_files/HedgewarsMobile/Info.plist Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Info.plist Tue Nov 10 20:43:13 2015 +0100 @@ -16,34 +16,34 @@ Icon-Small.png Icon-Small-50.png Icon-Small@2x.png + Icon-60@2x.png + Icon-76.png + Icon-76@2x.png CFBundleIdentifier - org.hedgewars.mobile + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName ${PRODUCT_NAME} CFBundlePackageType APPL + CFBundleShortVersionString + 2.0 CFBundleSignature ???? CFBundleVersion ${HEDGEWARS_REVISION} - CFBundleShortVersionString - 1.3.2 LSRequiresIPhoneOS + UILaunchImageFile~ipad + Default-ipad UIPrerenderedIcon + UIRequiresFullScreen + UIStatusBarHidden - UILaunchImageFile~ipad - Default-ipad - UISupportedInterfaceOrientations~iphone - - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - UISupportedInterfaceOrientations~ipad UIInterfaceOrientationPortrait @@ -51,5 +51,10 @@ UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight + UISupportedInterfaceOrientations~iphone + + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Locale/English.lproj/About.strings Binary file project_files/HedgewarsMobile/Locale/English.lproj/About.strings has changed diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Locale/English.lproj/Localizable.strings Binary file project_files/HedgewarsMobile/Locale/English.lproj/Localizable.strings has changed diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Locale/English.lproj/Scheme.strings Binary file project_files/HedgewarsMobile/Locale/English.lproj/Scheme.strings has changed diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Locale/Japanese.lproj/About.strings --- a/project_files/HedgewarsMobile/Locale/Japanese.lproj/About.strings Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Locale/Japanese.lproj/About.strings Tue Nov 10 20:43:13 2015 +0100 @@ -1,44 +1,44 @@ -/* code credit */ -"Engine, frontend, net server" = "エンジン、フロントエンド、ネットサーバー"; -"Many desktop frontend improvements" = "多くのデスクトップフロントエンドの改善"; -"Many engine and desktop frontend improvements" = "多くのエンジンとデスクトップフロントエンドの改善"; -"Drillrocket, Ballgun, RC Plane weapons" = "ドリルロケット、ボールガン、ラジコン武器"; -"Mine number and time game settings" = "地雷番号とタイムゲーム設定"; -"Desktop frontend improvements" = "デスクトップフロントエンドの改善"; -"Desktop frontend improvements" = "デスクトップフロントエンドの改善"; -"Mac OS X and iPhone version" = "Mac OS X と iPhone バージョン"; -"Many engine and desktop frontend improvements" = "多くのエンジンとデスクトップフロントエンドの改善"; -"Gamepad and Lua integration" = "ゲームパッドとLuaの統合化"; -"Many engine improvements and graphics" = "多くのエンジン改善とグラフィック"; -"Maze maps" = "迷路地図"; -"Engine and desktop frontend improvements" = "エンジンとデスクトップフロントエンドの改善"; -"Lua game modes and missions" = "Lua ゲームモードとミッション"; -"Desktop frontend improvements" = "デスクトップフロントエンドの改善"; -"Android port" = "アンドロイドポート"; - -/* art credit */ -"Main graphics" = "メイングラフィック"; -"Some hats" = "帽子"; -"Hedgehogs voice" = "ハリネズミの声"; - -/* translation credit */ -"Brazilian Portuguese" = "ポルトガル語(ブラジル)"; -"Bulgarian" = "ブルガリア語"; -"Czech" = "チェコ語"; -"Chinese" = "中国語"; -"English" = "英語"; -"Finnish" = "フィンランド語"; -"French" = "フランス語"; -"German" = "ドイツ語"; -"Greek" = "ギリシャ語"; -"Italian" = "イタリア語"; -"Japanese" = "日本語"; -"Korean" = "韓国語"; -"Lithuanian" = "リトアニア語"; -"Polish" = "ポーランド語"; -"Portuguese" = "ポルトガル語"; -"Russian" = "ロシア語"; -"Slovak" = "スロバキア語"; -"Spanish" = "スペイン語"; -"Swedish" = "スウェーデン語"; -"Ukrainian" = "ウクライナ語"; +/* code credit */ +"Engine, frontend, net server" = "エンジン、フロントエンド、ネットサーバー"; +"Many desktop frontend improvements" = "多くのデスクトップフロントエンドの改善"; +"Many engine and desktop frontend improvements" = "多くのエンジンとデスクトップフロントエンドの改善"; +"Drillrocket, Ballgun, RC Plane weapons" = "ドリルロケット、ボールガン、ラジコン武器"; +"Mine number and time game settings" = "地雷番号とタイムゲーム設定"; +"Desktop frontend improvements" = "デスクトップフロントエンドの改善"; +"Desktop frontend improvements" = "デスクトップフロントエンドの改善"; +"Mac OS X and iPhone version" = "Mac OS X と iPhone バージョン"; +"Many engine and desktop frontend improvements" = "多くのエンジンとデスクトップフロントエンドの改善"; +"Gamepad and Lua integration" = "ゲームパッドとLuaの統合化"; +"Many engine improvements and graphics" = "多くのエンジン改善とグラフィック"; +"Maze maps" = "迷路地図"; +"Engine and desktop frontend improvements" = "エンジンとデスクトップフロントエンドの改善"; +"Lua game modes and missions" = "Lua ゲームモードとミッション"; +"Desktop frontend improvements" = "デスクトップフロントエンドの改善"; +"Android port" = "アンドロイドポート"; + +/* art credit */ +"Main graphics" = "メイングラフィック"; +"Some hats" = "帽子"; +"Hedgehogs voice" = "ハリネズミの声"; + +/* translation credit */ +"Brazilian Portuguese" = "ポルトガル語(ブラジル)"; +"Bulgarian" = "ブルガリア語"; +"Czech" = "チェコ語"; +"Chinese" = "中国語"; +"English" = "英語"; +"Finnish" = "フィンランド語"; +"French" = "フランス語"; +"German" = "ドイツ語"; +"Greek" = "ギリシャ語"; +"Italian" = "イタリア語"; +"Japanese" = "日本語"; +"Korean" = "韓国語"; +"Lithuanian" = "リトアニア語"; +"Polish" = "ポーランド語"; +"Portuguese" = "ポルトガル語"; +"Russian" = "ロシア語"; +"Slovak" = "スロバキア語"; +"Spanish" = "スペイン語"; +"Swedish" = "スウェーデン語"; +"Ukrainian" = "ウクライナ語"; diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Locale/Japanese.lproj/Localizable.strings --- a/project_files/HedgewarsMobile/Locale/Japanese.lproj/Localizable.strings Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Locale/Japanese.lproj/Localizable.strings Tue Nov 10 20:43:13 2015 +0100 @@ -1,380 +1,380 @@ -/* No comment provided by engineer. */ -"A monitor has been disconnected while playing and this has ended the match! You need to restart the game if you wish to use the second display again." = "モニターの接続が切断され、マッチを終了してしまいました!二番目のディスプレーをまた使用したい場合はゲームをリスタートしなければいけません。"; - -/* from the scheme panel - from the team panel */ -"Add" = "追加"; - -/* No comment provided by engineer. */ -"Aggressive" = "積極的"; - -/* No comment provided by engineer. */ -"All" = "全て"; - -/* from the settings table */ -"Alternate Damage" = "代わりのダメージ"; - -/* No comment provided by engineer. */ -"Are you reeeeeally sure?" = "本当にいいですか?"; - -/* from the settings table */ -"Audio Preferences" = "オーディオ設定"; - -/* No comment provided by engineer. */ -"Available Teams" = "利用可能なチーム"; - -/* No comment provided by engineer. */ -"Average" = "平均"; - -/* No comment provided by engineer. */ -"Backup" = "バックアップ"; - -/* No comment provided by engineer. */ -"Before playing the preview needs to be generated" = "プレーする前にプレビューを生成する必要があります"; - -/* No comment provided by engineer. */ -"Before returning the preview needs to be generated" = "戻る前にプレビューを生成する必要があります"; - -/* No comment provided by engineer. */ -"Brutal" = "残忍"; - -/* No comment provided by engineer. */ -"Bully" = "いじめっ子"; - -/* No comment provided by engineer. */ -"Cancel" = "キャンセル"; - -/* No comment provided by engineer. */ -"Cavern" = "洞窟"; - -/* No comment provided by engineer. */ -"Change hedgehogs' hat" = "ハリネズミの帽子を変える"; - -/* No comment provided by engineer. */ -"Chat with the devs in IRC" = "IRC でデベロッパ達とチャットする"; - -/* No comment provided by engineer. */ -"Choose a charismatic symbol for your team" = "チームのためのカリスマ的なシンボルを選択する"; - -/* No comment provided by engineer. */ -"Choose hedgehog graves" = "ハリネズミの墓を選択する"; - -/* No comment provided by engineer. */ -"Choose team fort" = "チームの砦を選択する"; - -/* from the settings table */ -"Choosing a Scheme will select its associated Weapon" = "スキームを選択すると関連した武器を選択します。"; - -/* No comment provided by engineer. */ -"Classic Ammo Menu" = "クラシックな弾薬メニュー"; - -/* No comment provided by engineer. */ -"Community" = "コミュニティー"; - -/* from the settings table */ -"Damage popups will notify you on every single hit" = "ダメージポップアップはすべてのヒットを通知してくれます。"; - -/* from the scheme panel - from the team panel */ -"Done" = "終了"; - -/* from the scheme panel - from the team panel */ -"Edit" = "編集"; - -/* No comment provided by engineer. */ -"Edit scheme preferences" = "スキーム設定を編集"; - -/* No comment provided by engineer. */ -"Edit team settings" = "チーム設定を編集"; - -/* No comment provided by engineer. */ -"Edit weapons preferences" = "武器設定を編集"; - -/* No comment provided by engineer. */ -"End Game" = "ゲームを終了する"; - -/* No comment provided by engineer. */ -"Flag" = "フラグ"; - -/* No comment provided by engineer. */ -"Follow us on Twitter" = "ツイッターでフォローする"; - -/* No comment provided by engineer. */ -"Fort" = "砦"; - -/* No comment provided by engineer. */ -"Game Modifiers" = "ゲームの変更"; - -/* No comment provided by engineer. */ -"Game Settings" = "ゲームの設定"; - -/* No comment provided by engineer. */ -"General" = "一般"; - -/* No comment provided by engineer. */ -"Grave" = "墓"; - -/* No comment provided by engineer. */ -"Hedgewars supports multi-monitor configurations, but the screen has to be connected before launching the game." = "Hedgewarsはマルチモニター設定をサポートしていますが、スクリーンはゲームをスタートする前に接続されていなければいけません。"; - -/* No comment provided by engineer. */ -"Hogs controlled by AI" = "AIにコントロールされたハリネズミ"; - -/* No comment provided by engineer. */ -"Hold your finger on a weapon to see what it does.\nTap anywhere to dismiss." = "武器の上でホールドして何をするか見る。\nほかの部分をタップして閉じる。"; - -/* No comment provided by engineer. */ -"Hold your finger on a weapon to see what it does.\nYou can move this window anywhere on the screen." = "武器の上でホールドして何をするか見る。\nこのウィンドウはスクリーンのどこにでも動かすことができます。"; - -/* ammo selection */ -"Initial quantity " = "初期量"; - -/* from the settings table */ -"Insert your password" = "パスワードを入力"; - -/* from the settings table */ -"Insert your username (if you have one)" = "ユーザーネームを入力 (持っていた場合)"; - -/* No comment provided by engineer. */ -"Join us on Facebook" = "Facebookで参加する"; - -/* No comment provided by engineer. */ -"Large" = "大きな"; - -/* No comment provided by engineer. */ -"Large Floating Islands" = "大きな浮き島"; - -/* No comment provided by engineer. */ -"Large Tunnels" = "大きなトンネル"; - -/* No comment provided by engineer. */ -"Leave a positive review on iTunes!" = "iTunesでポジティブなレビューを残す!"; - -/* No comment provided by engineer. */ -"Level" = "レベル"; - -/* No comment provided by engineer. */ -"Loading..." = "ロード中..."; - -/* from the settings table */ -"Main Configuration" = "メイン設定"; - -/* No comment provided by engineer. */ -"Mark the death of your fallen warriors" = "あなたの倒れた戦士の死をマーク"; - -/* No comment provided by engineer. */ -"Max Hogs:" = "ハリネズミの最大数:"; - -/* No comment provided by engineer. */ -"Medium" = "中くらい"; - -/* No comment provided by engineer. */ -"Medium Floating Islands" = "中くらいの浮き島"; - -/* No comment provided by engineer. */ -"Medium Tunnels" = "中くらいのトンネル"; - -/* No comment provided by engineer. */ -"Missing detail" = "詳細が抜けています"; - -/* No comment provided by engineer. */ -"Missions don't need further configuration" = "ミッションはこれ以上の設定を必要としません"; - -/* from the settings table */ -"Music" = "音楽"; - -/* No comment provided by engineer. */ -"Names and Hats" = "ネームと帽子"; - -/* from the settings table */ -"Nickname" = "ニックネーム"; - -/* No comment provided by engineer. */ -"No filter" = "フィルターなし"; - -/* No comment provided by engineer. */ -"No thanks" = "遠慮します"; - -/* ammo selection */ -"Number of turns before you can use this weapon " = "この武器を使えるようになるまでのターン数"; - -/* Short for 'Never' */ -"Nvr" = "絶対にない"; - -/* No comment provided by engineer. */ -"Of course!" = "もちろん!"; - -/* No comment provided by engineer. */ -"Ok, got it" = "Ok, わかった"; - -/* No comment provided by engineer. */ -"Opt for controlling the team or let the AI lead" = "チームをコントロールするかAIをリードさせる"; - -/* from the settings table */ -"Other Settings" = "ほかの設定"; - -/* from the settings table */ -"Password" = "パスワード"; - -/* No comment provided by engineer. */ -"Pick a slang your hogs will speak" = "あなたのハリネズミが話すスラングを選択"; - -/* No comment provided by engineer. */ -"Playing Teams" = "プレー中のチーム"; - -/* ammo selection */ -"Presence probability in crates " = "クレートの中の存在確率"; - -/* No comment provided by engineer. */ -"Press to resume playing or swipe to delete the save file." = "押してプレーを再開するか、スワイプしてセーブファイルを削除。"; - -/* No comment provided by engineer. */ -"Preview not available" = "プレビューが利用できません"; - -/* ammo selection */ -"Quantity that you will find in a crate " = "クレーとの中で見つかる量"; - -/* No comment provided by engineer. */ -"Remind me later" = "後で連絡"; - -/* Short for 'Random' */ -"Rnd" = "ランダム"; - -/* No comment provided by engineer. */ -"Save" = "保存"; - -/* No comment provided by engineer. */ -"Scheme" = "スキーム"; - -/* No comment provided by engineer. */ -"Scheme mismatch" = "スキームミスマッチ"; - -/* No comment provided by engineer. */ -"Scheme Name" = "スキーム名"; - -/* No comment provided by engineer. */ -"Schemes" = "スキーム"; - -/* No comment provided by engineer. */ -"Select at least two teams to play a game" = "ゲームをプレーするには最低二チーム選択してください。"; - -/* No comment provided by engineer. */ -"Select one Scheme and one Weapon for this game" = "このゲームのためにスキームと武器を一つずつ選択してください。"; - -/* No comment provided by engineer. */ -"Select the team invincible fortress (only valid for fort games)" = "無敵砦のチームを選択する (砦ゲームのみ有効)"; - -/* from the settings table */ -"Select which style of ammo menu you prefer" = "弾薬メニューのスタイルを選択してください"; - -/* No comment provided by engineer. */ -"Set difficulty level" = "難易度レベルをセットする"; - -/* No comment provided by engineer. */ -"Set hedgehog voices" = "ハリネズミの声をセットする"; - -/* No comment provided by engineer. */ -"Set team flag" = "チームフラグをセットする"; - -/* on the overlay */ -"Set!" = "セット!"; - -/* No comment provided by engineer. */ -"Show Help" = "ヘルプを表示する"; - -/* No comment provided by engineer. */ -"Small" = "小さい"; - -/* No comment provided by engineer. */ -"Small Floating Islands" = "小さな浮き島"; - -/* No comment provided by engineer. */ -"Small Tunnels" = "小さなトンネル"; - -/* from the settings table */ -"Sound" = "サウンド"; - -/* No comment provided by engineer. */ -"Style" = "スタイル"; - -/* No comment provided by engineer. */ -"Support" = "サポート"; - -/* No comment provided by engineer. */ -"Sync Schemes and Weapons" = "スキームと武器を同期する"; - -/* No comment provided by engineer. */ -"Tag" = "タグ"; - -/* No comment provided by engineer. */ -"Tap to add hogs or change color, touch and hold to remove a team." = "ハリネズミを追加するか色を変更するにはタップ、チームを取り除くにはタッチしてホールドしてください。"; - -/* No comment provided by engineer. */ -"Team Name" = "チーム名"; - -/* No comment provided by engineer. */ -"Team Preferences" = "チーム設定"; - -/* No comment provided by engineer. */ -"Teams" = "チーム"; - -/* No comment provided by engineer. */ -"The map is too small for that many hogs" = "このマップはこれだけのハリネズミには小さすぎます。"; - -/* No comment provided by engineer. */ -"The robot badge indicates an AI-controlled team." = "ロボットバッジはAIがコントロールするチームを指します。"; - -/* No comment provided by engineer. */ -"The scheme you selected allows only for two teams" = "選択したスキームは二チーム用です。"; - -/* No comment provided by engineer. */ -"This weapon is locked" = "この武器はロックされています"; - -/* No comment provided by engineer. */ -"Too few teams playing" = "プレーしているチームが少なすぎます"; - -/* No comment provided by engineer. */ -"Too many hogs" = "ハリネズミが多すぎます"; - -/* No comment provided by engineer. */ -"Too many teams" = "チームが多すぎます"; - -/* No comment provided by engineer. */ -"Visit our website" = "ウェブサイトを見る"; - -/* No comment provided by engineer. */ -"Voice" = "音量"; - -/* No comment provided by engineer. */ -"Wacky" = "奇抜"; - -/* No comment provided by engineer. */ -"Wait for the Preview" = "プレビューを待つ"; - -/* No comment provided by engineer. */ -"Weaky" = "弱い者"; - -/* No comment provided by engineer. */ -"Weapon" = "武器"; - -/* No comment provided by engineer. */ -"Weapon Ammuntions" = "武器弾薬"; - -/* No comment provided by engineer. */ -"Weapons" = "武器"; - -/* No comment provided by engineer. */ -"Weaponset Name" = "武器セット名"; - -/* No comment provided by engineer. */ -"Well, maybe not..." = "まあ、そうでないかもしれません..."; - -/* No comment provided by engineer. */ -"Worldwide" = "ワールドワイド"; - -/* No comment provided by engineer. */ -"You can add a description if you wish" = "お望みなら説明を追加することができます。"; - -/* No comment provided by engineer. */ +/* No comment provided by engineer. */ +"A monitor has been disconnected while playing and this has ended the match! You need to restart the game if you wish to use the second display again." = "モニターの接続が切断され、マッチを終了してしまいました!二番目のディスプレーをまた使用したい場合はゲームをリスタートしなければいけません。"; + +/* from the scheme panel + from the team panel */ +"Add" = "追加"; + +/* No comment provided by engineer. */ +"Aggressive" = "積極的"; + +/* No comment provided by engineer. */ +"All" = "全て"; + +/* from the settings table */ +"Alternate Damage" = "代わりのダメージ"; + +/* No comment provided by engineer. */ +"Are you reeeeeally sure?" = "本当にいいですか?"; + +/* from the settings table */ +"Audio Preferences" = "オーディオ設定"; + +/* No comment provided by engineer. */ +"Available Teams" = "利用可能なチーム"; + +/* No comment provided by engineer. */ +"Average" = "平均"; + +/* No comment provided by engineer. */ +"Backup" = "バックアップ"; + +/* No comment provided by engineer. */ +"Before playing the preview needs to be generated" = "プレーする前にプレビューを生成する必要があります"; + +/* No comment provided by engineer. */ +"Before returning the preview needs to be generated" = "戻る前にプレビューを生成する必要があります"; + +/* No comment provided by engineer. */ +"Brutal" = "残忍"; + +/* No comment provided by engineer. */ +"Bully" = "いじめっ子"; + +/* No comment provided by engineer. */ +"Cancel" = "キャンセル"; + +/* No comment provided by engineer. */ +"Cavern" = "洞窟"; + +/* No comment provided by engineer. */ +"Change hedgehogs' hat" = "ハリネズミの帽子を変える"; + +/* No comment provided by engineer. */ +"Chat with the devs in IRC" = "IRC でデベロッパ達とチャットする"; + +/* No comment provided by engineer. */ +"Choose a charismatic symbol for your team" = "チームのためのカリスマ的なシンボルを選択する"; + +/* No comment provided by engineer. */ +"Choose hedgehog graves" = "ハリネズミの墓を選択する"; + +/* No comment provided by engineer. */ +"Choose team fort" = "チームの砦を選択する"; + +/* from the settings table */ +"Choosing a Scheme will select its associated Weapon" = "スキームを選択すると関連した武器を選択します。"; + +/* No comment provided by engineer. */ +"Classic Ammo Menu" = "クラシックな弾薬メニュー"; + +/* No comment provided by engineer. */ +"Community" = "コミュニティー"; + +/* from the settings table */ +"Damage popups will notify you on every single hit" = "ダメージポップアップはすべてのヒットを通知してくれます。"; + +/* from the scheme panel + from the team panel */ +"Done" = "終了"; + +/* from the scheme panel + from the team panel */ +"Edit" = "編集"; + +/* No comment provided by engineer. */ +"Edit scheme preferences" = "スキーム設定を編集"; + +/* No comment provided by engineer. */ +"Edit team settings" = "チーム設定を編集"; + +/* No comment provided by engineer. */ +"Edit weapons preferences" = "武器設定を編集"; + +/* No comment provided by engineer. */ +"End Game" = "ゲームを終了する"; + +/* No comment provided by engineer. */ +"Flag" = "フラグ"; + +/* No comment provided by engineer. */ +"Follow us on Twitter" = "ツイッターでフォローする"; + +/* No comment provided by engineer. */ +"Fort" = "砦"; + +/* No comment provided by engineer. */ +"Game Modifiers" = "ゲームの変更"; + +/* No comment provided by engineer. */ +"Game Settings" = "ゲームの設定"; + +/* No comment provided by engineer. */ +"General" = "一般"; + +/* No comment provided by engineer. */ +"Grave" = "墓"; + +/* No comment provided by engineer. */ +"Hedgewars supports multi-monitor configurations, but the screen has to be connected before launching the game." = "Hedgewarsはマルチモニター設定をサポートしていますが、スクリーンはゲームをスタートする前に接続されていなければいけません。"; + +/* No comment provided by engineer. */ +"Hogs controlled by AI" = "AIにコントロールされたハリネズミ"; + +/* No comment provided by engineer. */ +"Hold your finger on a weapon to see what it does.\nTap anywhere to dismiss." = "武器の上でホールドして何をするか見る。\nほかの部分をタップして閉じる。"; + +/* No comment provided by engineer. */ +"Hold your finger on a weapon to see what it does.\nYou can move this window anywhere on the screen." = "武器の上でホールドして何をするか見る。\nこのウィンドウはスクリーンのどこにでも動かすことができます。"; + +/* ammo selection */ +"Initial quantity " = "初期量"; + +/* from the settings table */ +"Insert your password" = "パスワードを入力"; + +/* from the settings table */ +"Insert your username (if you have one)" = "ユーザーネームを入力 (持っていた場合)"; + +/* No comment provided by engineer. */ +"Join us on Facebook" = "Facebookで参加する"; + +/* No comment provided by engineer. */ +"Large" = "大きな"; + +/* No comment provided by engineer. */ +"Large Floating Islands" = "大きな浮き島"; + +/* No comment provided by engineer. */ +"Large Tunnels" = "大きなトンネル"; + +/* No comment provided by engineer. */ +"Leave a positive review on iTunes!" = "iTunesでポジティブなレビューを残す!"; + +/* No comment provided by engineer. */ +"Level" = "レベル"; + +/* No comment provided by engineer. */ +"Loading..." = "ロード中..."; + +/* from the settings table */ +"Main Configuration" = "メイン設定"; + +/* No comment provided by engineer. */ +"Mark the death of your fallen warriors" = "あなたの倒れた戦士の死をマーク"; + +/* No comment provided by engineer. */ +"Max Hogs:" = "ハリネズミの最大数:"; + +/* No comment provided by engineer. */ +"Medium" = "中くらい"; + +/* No comment provided by engineer. */ +"Medium Floating Islands" = "中くらいの浮き島"; + +/* No comment provided by engineer. */ +"Medium Tunnels" = "中くらいのトンネル"; + +/* No comment provided by engineer. */ +"Missing detail" = "詳細が抜けています"; + +/* No comment provided by engineer. */ +"Missions don't need further configuration" = "ミッションはこれ以上の設定を必要としません"; + +/* from the settings table */ +"Music" = "音楽"; + +/* No comment provided by engineer. */ +"Names and Hats" = "ネームと帽子"; + +/* from the settings table */ +"Nickname" = "ニックネーム"; + +/* No comment provided by engineer. */ +"No filter" = "フィルターなし"; + +/* No comment provided by engineer. */ +"No thanks" = "遠慮します"; + +/* ammo selection */ +"Number of turns before you can use this weapon " = "この武器を使えるようになるまでのターン数"; + +/* Short for 'Never' */ +"Nvr" = "絶対にない"; + +/* No comment provided by engineer. */ +"Of course!" = "もちろん!"; + +/* No comment provided by engineer. */ +"Ok, got it" = "Ok, わかった"; + +/* No comment provided by engineer. */ +"Opt for controlling the team or let the AI lead" = "チームをコントロールするかAIをリードさせる"; + +/* from the settings table */ +"Other Settings" = "ほかの設定"; + +/* from the settings table */ +"Password" = "パスワード"; + +/* No comment provided by engineer. */ +"Pick a slang your hogs will speak" = "あなたのハリネズミが話すスラングを選択"; + +/* No comment provided by engineer. */ +"Playing Teams" = "プレー中のチーム"; + +/* ammo selection */ +"Presence probability in crates " = "クレートの中の存在確率"; + +/* No comment provided by engineer. */ +"Press to resume playing or swipe to delete the save file." = "押してプレーを再開するか、スワイプしてセーブファイルを削除。"; + +/* No comment provided by engineer. */ +"Preview not available" = "プレビューが利用できません"; + +/* ammo selection */ +"Quantity that you will find in a crate " = "クレーとの中で見つかる量"; + +/* No comment provided by engineer. */ +"Remind me later" = "後で連絡"; + +/* Short for 'Random' */ +"Rnd" = "ランダム"; + +/* No comment provided by engineer. */ +"Save" = "保存"; + +/* No comment provided by engineer. */ +"Scheme" = "スキーム"; + +/* No comment provided by engineer. */ +"Scheme mismatch" = "スキームミスマッチ"; + +/* No comment provided by engineer. */ +"Scheme Name" = "スキーム名"; + +/* No comment provided by engineer. */ +"Schemes" = "スキーム"; + +/* No comment provided by engineer. */ +"Select at least two teams to play a game" = "ゲームをプレーするには最低二チーム選択してください。"; + +/* No comment provided by engineer. */ +"Select one Scheme and one Weapon for this game" = "このゲームのためにスキームと武器を一つずつ選択してください。"; + +/* No comment provided by engineer. */ +"Select the team invincible fortress (only valid for fort games)" = "無敵砦のチームを選択する (砦ゲームのみ有効)"; + +/* from the settings table */ +"Select which style of ammo menu you prefer" = "弾薬メニューのスタイルを選択してください"; + +/* No comment provided by engineer. */ +"Set difficulty level" = "難易度レベルをセットする"; + +/* No comment provided by engineer. */ +"Set hedgehog voices" = "ハリネズミの声をセットする"; + +/* No comment provided by engineer. */ +"Set team flag" = "チームフラグをセットする"; + +/* on the overlay */ +"Set!" = "セット!"; + +/* No comment provided by engineer. */ +"Show Help" = "ヘルプを表示する"; + +/* No comment provided by engineer. */ +"Small" = "小さい"; + +/* No comment provided by engineer. */ +"Small Floating Islands" = "小さな浮き島"; + +/* No comment provided by engineer. */ +"Small Tunnels" = "小さなトンネル"; + +/* from the settings table */ +"Sound" = "サウンド"; + +/* No comment provided by engineer. */ +"Style" = "スタイル"; + +/* No comment provided by engineer. */ +"Support" = "サポート"; + +/* No comment provided by engineer. */ +"Sync Schemes and Weapons" = "スキームと武器を同期する"; + +/* No comment provided by engineer. */ +"Tag" = "タグ"; + +/* No comment provided by engineer. */ +"Tap to add hogs or change color, touch and hold to remove a team." = "ハリネズミを追加するか色を変更するにはタップ、チームを取り除くにはタッチしてホールドしてください。"; + +/* No comment provided by engineer. */ +"Team Name" = "チーム名"; + +/* No comment provided by engineer. */ +"Team Preferences" = "チーム設定"; + +/* No comment provided by engineer. */ +"Teams" = "チーム"; + +/* No comment provided by engineer. */ +"The map is too small for that many hogs" = "このマップはこれだけのハリネズミには小さすぎます。"; + +/* No comment provided by engineer. */ +"The robot badge indicates an AI-controlled team." = "ロボットバッジはAIがコントロールするチームを指します。"; + +/* No comment provided by engineer. */ +"The scheme you selected allows only for two teams" = "選択したスキームは二チーム用です。"; + +/* No comment provided by engineer. */ +"This weapon is locked" = "この武器はロックされています"; + +/* No comment provided by engineer. */ +"Too few teams playing" = "プレーしているチームが少なすぎます"; + +/* No comment provided by engineer. */ +"Too many hogs" = "ハリネズミが多すぎます"; + +/* No comment provided by engineer. */ +"Too many teams" = "チームが多すぎます"; + +/* No comment provided by engineer. */ +"Visit our website" = "ウェブサイトを見る"; + +/* No comment provided by engineer. */ +"Voice" = "音量"; + +/* No comment provided by engineer. */ +"Wacky" = "奇抜"; + +/* No comment provided by engineer. */ +"Wait for the Preview" = "プレビューを待つ"; + +/* No comment provided by engineer. */ +"Weaky" = "弱い者"; + +/* No comment provided by engineer. */ +"Weapon" = "武器"; + +/* No comment provided by engineer. */ +"Weapon Ammuntions" = "武器弾薬"; + +/* No comment provided by engineer. */ +"Weapons" = "武器"; + +/* No comment provided by engineer. */ +"Weaponset Name" = "武器セット名"; + +/* No comment provided by engineer. */ +"Well, maybe not..." = "まあ、そうでないかもしれません..."; + +/* No comment provided by engineer. */ +"Worldwide" = "ワールドワイド"; + +/* No comment provided by engineer. */ +"You can add a description if you wish" = "お望みなら説明を追加することができます。"; + +/* No comment provided by engineer. */ "You exceeded the maximum number of tems allowed in a game" = "ゲームで許可されているチームの最大数を超しました。"; \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Locale/Japanese.lproj/Scheme.strings --- a/project_files/HedgewarsMobile/Locale/Japanese.lproj/Scheme.strings Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Locale/Japanese.lproj/Scheme.strings Tue Nov 10 20:43:13 2015 +0100 @@ -1,194 +1,194 @@ -/* game mod description */ -"Land can not be destroyed" = "土地は破壊することができません"; - -/* game mod title */ -"Solid Land" = "固形の土地"; - -/* game mod description */ -"Add an indestructable border around the terrain" = "地形の周りに破壊できないボーダーを追加する"; - -/* game mod title */ -"Add Border" = "ボーダーを追加する"; - -/* game mod description */ -"Teams will start on opposite sides of the terrain" = "チームは地形の反対側からスタート思案す"; - -/* game mod title */ -"Divide Team (max 2 teams)" = "チームを分ける (最大二チーム)"; - -/* game mod description */ -"Lower gravity" = "低い重力"; - -/* game mod title */ -"Low Gravity" = "低重力"; - -/* game mod description */ -"Assisted aiming with laser sight" = "レーザーサイトで狙いの補助"; - -/* game mod title */ -"Laser Sight" = "レーザーサイト"; - -/* game mod description */ -"All hogs have a personal forcefield" = "全てのハリネズミは自分の力場を持っています"; - -/* game mod title */ -"Invulnerable" = "無敵"; - -/* game mod description */ -"All (living) hedgehogs are fully restored at the end of turn" = "全ての (生きている) ハリネズミの体力はターン終了時に完全に復元されます"; - -/* game mod title */ -"Reset Health" = "体力をリセット"; - -/* game mod description */ -"Gain 80% of the damage you do back in health" = "ダメージの80% を体力としてもらう"; - -/* game mod title */ -"Vampirism Mode" = "吸血モード"; - -/* game mod description */ -"Share your opponents pain, share their damage" = "相手の痛みを共有し、 ダメージを共有する"; - -/* game mod title */ -"Karma Mode" = "カルマモード"; - -/* game mod description */ -"Your hogs are unable to move, test your aim" = "あなたのハリネズミは動けない, 狙いを試せ"; - -/* game mod title */ -"Artillery Mode" = "砲兵モード"; - -/* game mod description */ -"Defend your fort and destroy the opponents" = "砦を守って相手を潰せ"; - -/* game mod title */ -"Fort Mode" = "砦モード"; - -/* game mod description */ -"Order of play is random instead of in room order" = "プレー順はルーム順ではなくランダムです"; - -/* game mod title */ -"Random Order" = "ランダムオーダー"; - -/* game mod description */ -"Play with a King; when he dies, your side loses" = "キングとプレーする; キングが死ぬと、あなたの負けです"; - -/* game mod title */ -"King Mode" = "キングモード"; - -/* game mod description */ -"Take turns placing your hedgehogs pre-game" = "ゲームの前にターンを取ってハリネズミを置く"; - -/* game mod title */ -"Place Hedgehogs" = "ハリネズミを置く"; - -/* game mod description */ -"Ammo is shared between all clan teams" = "弾薬は全ての一族チームの間で共有されます"; - -/* game mod title */ -"Clan Shares Ammo" = "一族は弾薬を共有します"; - -/* game mod description */ -"Disable girders when generating random maps" = "ランダムマップを作成するときはガードを無効にする"; - -/* game mod title */ -"Disable Girders" = "ガードを無効にする"; - -/* game mod description */ -"Disable land objects when generating maps" = "マップ作成中は土地のオブジェクトを無効にする"; - -/* game mod title */ -"Disable Land Objects" = "土地のオブジェクトを無効にする"; - -/* game mod description */ -"AI-controlled hogs respawn on death" = "AIがコントロールするハリネズミは死ぬと再出現します"; - -/* game mod title */ -"AI Survival Mode" = "AI サバイバルモード"; - -/* game mod description */ -"Attacking does not end your turn" = "攻撃してもターンは終了しません"; - -/* game mod title */ -"Unlimited Attacks" = "無限攻撃"; - -/* game mod description */ -"Weapons are reset to starting values each turn" = "武器は毎ターン初期値にリセットされます"; - -/* game mod title */ -"Reset Weapons" = "武器をリセット"; - -/* game mod description */ -"Each hedgehog has its own ammo" = "各ハリネズミが自分の弾薬を持っています"; - -/* game mod title */ -"Per Hedgehog Ammo" = "ハリネズミあたりの弾薬"; - -/* game mod description */ -"You will not have to worry about wind any more" = "風のことは気にせずに良くなります"; - -/* game mod title */ -"Disable Wind" = "風を無効にする"; - -/* game mod description */ -"Wind will affect almost everything" = "風はほとんどのものに影響します"; - -/* game mod title */ -"More Wind" = "より強い風"; - -/* game mod description */ -"Clan teams take turns sharing their time" = "一族のチームはタイムを共有してターンを取ります"; - -/* game mod title */ -"Tag Team" = "タッグチーム"; - -/* game mod description */ -"Add an indestructible border along the bottom" = "破壊できないボーダーを下に追加する"; - -/* game mod title */ -"Bottom Border" = "ボトムボーダー"; - - -/* flag description */ -"Initial Health" = "初期体力"; - -/* flag description */ -"Damage Modifier" = "ダメージ変更"; - -/* flag description */ -"Turn Time" = "ターンタイム"; -/* flag description */ -"Sudden Death Timeout" = "サデン・デス タイムアウト"; - -/* flag description */ -"Water Rise Amount" = "水位上昇量"; - -/* flag description */ -"Health Decrease" = "体力の減少"; - -/* flag description */ -"Rope Length (%)" = "ロープの長さ (%)"; - -/* flag description */ -"Crate Drop Turns" = "クレートドロップターン"; - -/* flag description */ -"Health Kit Probability (%)" = "体力キットの確率 (%)"; - -/* flag description */ -"Health Amount in Kit" = "キットの体力量"; - -/* flag description */ -"Mines Time" = "地雷タイム"; - -/* flag description */ -"Mines Number" = "地雷ナンバー"; - -/* flag description */ -"Dud Mines Probability (%)" = "不発地雷の確率(%)"; - -/* flag description */ -"Explosives" = "爆発物"; - -/* flag description */ +/* game mod description */ +"Land can not be destroyed" = "土地は破壊することができません"; + +/* game mod title */ +"Solid Land" = "固形の土地"; + +/* game mod description */ +"Add an indestructable border around the terrain" = "地形の周りに破壊できないボーダーを追加する"; + +/* game mod title */ +"Add Border" = "ボーダーを追加する"; + +/* game mod description */ +"Teams will start on opposite sides of the terrain" = "チームは地形の反対側からスタート思案す"; + +/* game mod title */ +"Divide Team (max 2 teams)" = "チームを分ける (最大二チーム)"; + +/* game mod description */ +"Lower gravity" = "低い重力"; + +/* game mod title */ +"Low Gravity" = "低重力"; + +/* game mod description */ +"Assisted aiming with laser sight" = "レーザーサイトで狙いの補助"; + +/* game mod title */ +"Laser Sight" = "レーザーサイト"; + +/* game mod description */ +"All hogs have a personal forcefield" = "全てのハリネズミは自分の力場を持っています"; + +/* game mod title */ +"Invulnerable" = "無敵"; + +/* game mod description */ +"All (living) hedgehogs are fully restored at the end of turn" = "全ての (生きている) ハリネズミの体力はターン終了時に完全に復元されます"; + +/* game mod title */ +"Reset Health" = "体力をリセット"; + +/* game mod description */ +"Gain 80% of the damage you do back in health" = "ダメージの80% を体力としてもらう"; + +/* game mod title */ +"Vampirism Mode" = "吸血モード"; + +/* game mod description */ +"Share your opponents pain, share their damage" = "相手の痛みを共有し、 ダメージを共有する"; + +/* game mod title */ +"Karma Mode" = "カルマモード"; + +/* game mod description */ +"Your hogs are unable to move, test your aim" = "あなたのハリネズミは動けない, 狙いを試せ"; + +/* game mod title */ +"Artillery Mode" = "砲兵モード"; + +/* game mod description */ +"Defend your fort and destroy the opponents" = "砦を守って相手を潰せ"; + +/* game mod title */ +"Fort Mode" = "砦モード"; + +/* game mod description */ +"Order of play is random instead of in room order" = "プレー順はルーム順ではなくランダムです"; + +/* game mod title */ +"Random Order" = "ランダムオーダー"; + +/* game mod description */ +"Play with a King; when he dies, your side loses" = "キングとプレーする; キングが死ぬと、あなたの負けです"; + +/* game mod title */ +"King Mode" = "キングモード"; + +/* game mod description */ +"Take turns placing your hedgehogs pre-game" = "ゲームの前にターンを取ってハリネズミを置く"; + +/* game mod title */ +"Place Hedgehogs" = "ハリネズミを置く"; + +/* game mod description */ +"Ammo is shared between all clan teams" = "弾薬は全ての一族チームの間で共有されます"; + +/* game mod title */ +"Clan Shares Ammo" = "一族は弾薬を共有します"; + +/* game mod description */ +"Disable girders when generating random maps" = "ランダムマップを作成するときはガードを無効にする"; + +/* game mod title */ +"Disable Girders" = "ガードを無効にする"; + +/* game mod description */ +"Disable land objects when generating maps" = "マップ作成中は土地のオブジェクトを無効にする"; + +/* game mod title */ +"Disable Land Objects" = "土地のオブジェクトを無効にする"; + +/* game mod description */ +"AI-controlled hogs respawn on death" = "AIがコントロールするハリネズミは死ぬと再出現します"; + +/* game mod title */ +"AI Survival Mode" = "AI サバイバルモード"; + +/* game mod description */ +"Attacking does not end your turn" = "攻撃してもターンは終了しません"; + +/* game mod title */ +"Unlimited Attacks" = "無限攻撃"; + +/* game mod description */ +"Weapons are reset to starting values each turn" = "武器は毎ターン初期値にリセットされます"; + +/* game mod title */ +"Reset Weapons" = "武器をリセット"; + +/* game mod description */ +"Each hedgehog has its own ammo" = "各ハリネズミが自分の弾薬を持っています"; + +/* game mod title */ +"Per Hedgehog Ammo" = "ハリネズミあたりの弾薬"; + +/* game mod description */ +"You will not have to worry about wind any more" = "風のことは気にせずに良くなります"; + +/* game mod title */ +"Disable Wind" = "風を無効にする"; + +/* game mod description */ +"Wind will affect almost everything" = "風はほとんどのものに影響します"; + +/* game mod title */ +"More Wind" = "より強い風"; + +/* game mod description */ +"Clan teams take turns sharing their time" = "一族のチームはタイムを共有してターンを取ります"; + +/* game mod title */ +"Tag Team" = "タッグチーム"; + +/* game mod description */ +"Add an indestructible border along the bottom" = "破壊できないボーダーを下に追加する"; + +/* game mod title */ +"Bottom Border" = "ボトムボーダー"; + + +/* flag description */ +"Initial Health" = "初期体力"; + +/* flag description */ +"Damage Modifier" = "ダメージ変更"; + +/* flag description */ +"Turn Time" = "ターンタイム"; +/* flag description */ +"Sudden Death Timeout" = "サデン・デス タイムアウト"; + +/* flag description */ +"Water Rise Amount" = "水位上昇量"; + +/* flag description */ +"Health Decrease" = "体力の減少"; + +/* flag description */ +"Rope Length (%)" = "ロープの長さ (%)"; + +/* flag description */ +"Crate Drop Turns" = "クレートドロップターン"; + +/* flag description */ +"Health Kit Probability (%)" = "体力キットの確率 (%)"; + +/* flag description */ +"Health Amount in Kit" = "キットの体力量"; + +/* flag description */ +"Mines Time" = "地雷タイム"; + +/* flag description */ +"Mines Number" = "地雷ナンバー"; + +/* flag description */ +"Dud Mines Probability (%)" = "不発地雷の確率(%)"; + +/* flag description */ +"Explosives" = "爆発物"; + +/* flag description */ "Get Away Time (%)" = "脱出タイム (%)"; \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Locale/Turkish.lproj/About.strings Binary file project_files/HedgewarsMobile/Locale/Turkish.lproj/About.strings has changed diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Locale/Turkish.lproj/Localizable.strings Binary file project_files/HedgewarsMobile/Locale/Turkish.lproj/Localizable.strings has changed diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Locale/Turkish.lproj/Scheme.strings Binary file project_files/HedgewarsMobile/Locale/Turkish.lproj/Scheme.strings has changed diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Locale/hw-desc_ja.txt --- a/project_files/HedgewarsMobile/Locale/hw-desc_ja.txt Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Locale/hw-desc_ja.txt Tue Nov 10 20:43:13 2015 +0100 @@ -1,28 +1,28 @@ - -Hedgewars, ブラストだ! - -Hedgewars が Mac アップストアに登場! Mac で Hedgewars を検索して無料コピーを今すぐダウンロードしよう! - -iOS ポートはいくつかの限定フィーチャーがあります。例えば: -* iPad VGA アウト: 外部ディスプレイを接続してフル解像度でプレー -* Retina ディスrプレイサポート: ゲームの全てを高い解像度でプレー; -* マルチタスキング: いつでもゲームをポーズ; -* ゲームリストア: あなたは何が何でもマッチを完成させることができます。 - -説明: -これはあなたが遊ぶ一番面白くて依存症のあるゲームです - いつでも、どこでも楽しめる陽気な楽しみ。 Hedgewars はターン制ストラテジーゲームですが、本当の楽しみはあの厄介なハリネズミがすばらしい武器を使って起こす破壊を見ることです - 悪い態度の小さな厄介者! - -言い換えれば、 Hedgewars はターン製ストラテジー、砲兵、アクションとコメディゲームで、地獄から宇宙まで 悪ふざけをするピンクのハリネズミが特色です。 - -司令官としてのあなたの役目はハリネズミ兵のチームを編成し、敵に戦争を持ってゆくことです。 - -プレイヤーはそれぞれ複数のハリネズミをコントロールします。ゲーム中は、ハリネズミの一つを使って交代します。利用可能な武器や道具を使って敵のハリネズミを攻撃して殺し、勝利を取ります。 -Hedgehogs は地形をさまざまな方法で動き回ります。普段は歩いたりジャンプしたりしますが、"ロープ"や"パラシュート"などの特定の道具を使って本来なら届かないエリアに移動することができます。ターンはプレイヤーが動いたいり考えたりする時間をとり過ぎないようにタイムリミットがかかっています。ゲーム中はさまざまな道具や武器が使えます:手榴弾、クラスター爆弾、UFO、ショットガン、デザートイーグル、ファイアーパンチ、野球バット、ダイナマイト、地雷、ロープ、ニューマチックピックやパラシュートです。ほとんどの武器は、使用時に、地形を変える爆発を起こします。地形は水の上に浮かんでいる島か、下に水がある洞窟です。ハリネズミは水の中に入るか(島から落ちるか、穴を通って)、アリーナの横から落とされるか、爆発などで体力がゼロに減ると(プレーヤーやCPUのターンのダメージは全ての動きが止まった後表示されます)死んでしまいます。 - -* 六人までの陽気と壊滅的なターン制コンバット -* AIも追加可能なローカルとネットワーク上のマルチプレーヤー -* ランダムで作成された無限のマップと二十以上の環境の中で戦おう -* 48(上昇中)の圧倒的な武器を使おう!ピアノストライクと爆発的なロボットケーキも含みます。 -* 二十種類以上のゲーム修飾法で戦いのほとんどの部分を微調整して自分のやり方でプレーしよう -* 120以上のコスチューム、30以上の墓、12以上の砦、100以上のフラグやユニークなボイスパックでチームをカスタマイズ + +Hedgewars, ブラストだ! + +Hedgewars が Mac アップストアに登場! Mac で Hedgewars を検索して無料コピーを今すぐダウンロードしよう! + +iOS ポートはいくつかの限定フィーチャーがあります。例えば: +* iPad VGA アウト: 外部ディスプレイを接続してフル解像度でプレー +* Retina ディスrプレイサポート: ゲームの全てを高い解像度でプレー; +* マルチタスキング: いつでもゲームをポーズ; +* ゲームリストア: あなたは何が何でもマッチを完成させることができます。 + +説明: +これはあなたが遊ぶ一番面白くて依存症のあるゲームです - いつでも、どこでも楽しめる陽気な楽しみ。 Hedgewars はターン制ストラテジーゲームですが、本当の楽しみはあの厄介なハリネズミがすばらしい武器を使って起こす破壊を見ることです - 悪い態度の小さな厄介者! + +言い換えれば、 Hedgewars はターン製ストラテジー、砲兵、アクションとコメディゲームで、地獄から宇宙まで 悪ふざけをするピンクのハリネズミが特色です。 + +司令官としてのあなたの役目はハリネズミ兵のチームを編成し、敵に戦争を持ってゆくことです。 + +プレイヤーはそれぞれ複数のハリネズミをコントロールします。ゲーム中は、ハリネズミの一つを使って交代します。利用可能な武器や道具を使って敵のハリネズミを攻撃して殺し、勝利を取ります。 +Hedgehogs は地形をさまざまな方法で動き回ります。普段は歩いたりジャンプしたりしますが、"ロープ"や"パラシュート"などの特定の道具を使って本来なら届かないエリアに移動することができます。ターンはプレイヤーが動いたいり考えたりする時間をとり過ぎないようにタイムリミットがかかっています。ゲーム中はさまざまな道具や武器が使えます:手榴弾、クラスター爆弾、UFO、ショットガン、デザートイーグル、ファイアーパンチ、野球バット、ダイナマイト、地雷、ロープ、ニューマチックピックやパラシュートです。ほとんどの武器は、使用時に、地形を変える爆発を起こします。地形は水の上に浮かんでいる島か、下に水がある洞窟です。ハリネズミは水の中に入るか(島から落ちるか、穴を通って)、アリーナの横から落とされるか、爆発などで体力がゼロに減ると(プレーヤーやCPUのターンのダメージは全ての動きが止まった後表示されます)死んでしまいます。 + +* 六人までの陽気と壊滅的なターン制コンバット +* AIも追加可能なローカルとネットワーク上のマルチプレーヤー +* ランダムで作成された無限のマップと二十以上の環境の中で戦おう +* 48(上昇中)の圧倒的な武器を使おう!ピアノストライクと爆発的なロボットケーキも含みます。 +* 二十種類以上のゲーム修飾法で戦いのほとんどの部分を微調整して自分のやり方でプレーしよう +* 120以上のコスチューム、30以上の墓、12以上の砦、100以上のフラグやユニークなボイスパックでチームをカスタマイズ * 64体までの広大な戦い \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Locale/hw-desc_tr.txt Binary file project_files/HedgewarsMobile/Locale/hw-desc_tr.txt has changed diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Locale/ru.lproj/About.strings Binary file project_files/HedgewarsMobile/Locale/ru.lproj/About.strings has changed diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Locale/ru.lproj/Localizable.strings Binary file project_files/HedgewarsMobile/Locale/ru.lproj/Localizable.strings has changed diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Locale/ru.lproj/Scheme.strings Binary file project_files/HedgewarsMobile/Locale/ru.lproj/Scheme.strings has changed diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Locale/tr.lproj/About.strings Binary file project_files/HedgewarsMobile/Locale/tr.lproj/About.strings has changed diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Locale/tr.lproj/Localizable.strings Binary file project_files/HedgewarsMobile/Locale/tr.lproj/Localizable.strings has changed diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Locale/tr.lproj/Scheme.strings Binary file project_files/HedgewarsMobile/Locale/tr.lproj/Scheme.strings has changed diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Resources/Frontend/Help Bubbles/helpabove.png Binary file project_files/HedgewarsMobile/Resources/Frontend/Help Bubbles/helpabove.png has changed diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Resources/Frontend/Help Bubbles/helpbottom.png Binary file project_files/HedgewarsMobile/Resources/Frontend/Help Bubbles/helpbottom.png has changed diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Resources/Frontend/Help Bubbles/helpleft.png Binary file project_files/HedgewarsMobile/Resources/Frontend/Help Bubbles/helpleft.png has changed diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Resources/Frontend/Help Bubbles/helpplain.png Binary file project_files/HedgewarsMobile/Resources/Frontend/Help Bubbles/helpplain.png has changed diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Resources/Frontend/Help Bubbles/helpright.png Binary file project_files/HedgewarsMobile/Resources/Frontend/Help Bubbles/helpright.png has changed diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Resources/Icons/Icon-60@2x.png Binary file project_files/HedgewarsMobile/Resources/Icons/Icon-60@2x.png has changed diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Resources/Icons/Icon-76.png Binary file project_files/HedgewarsMobile/Resources/Icons/Icon-76.png has changed diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Resources/Icons/Icon-76@2x.png Binary file project_files/HedgewarsMobile/Resources/Icons/Icon-76@2x.png has changed diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Resources/Icons/bullet.png Binary file project_files/HedgewarsMobile/Resources/Icons/bullet.png has changed diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Resources/Icons/bullet@2x.png Binary file project_files/HedgewarsMobile/Resources/Icons/bullet@2x.png has changed diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Resources/Icons/bullet_filled.png Binary file project_files/HedgewarsMobile/Resources/Icons/bullet_filled.png has changed diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Resources/Icons/bullet_filled@2x.png Binary file project_files/HedgewarsMobile/Resources/Icons/bullet_filled@2x.png has changed diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Resources/Icons/flower.png Binary file project_files/HedgewarsMobile/Resources/Icons/flower.png has changed diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Resources/Icons/flower@2x.png Binary file project_files/HedgewarsMobile/Resources/Icons/flower@2x.png has changed diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Resources/Icons/flower_filled.png Binary file project_files/HedgewarsMobile/Resources/Icons/flower_filled.png has changed diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Resources/Icons/flower_filled@2x.png Binary file project_files/HedgewarsMobile/Resources/Icons/flower_filled@2x.png has changed diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Resources/Icons/heart.png Binary file project_files/HedgewarsMobile/Resources/Icons/heart.png has changed diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Resources/Icons/heart@2x.png Binary file project_files/HedgewarsMobile/Resources/Icons/heart@2x.png has changed diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Resources/Icons/heart_filled.png Binary file project_files/HedgewarsMobile/Resources/Icons/heart_filled.png has changed diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Resources/Icons/heart_filled@2x.png Binary file project_files/HedgewarsMobile/Resources/Icons/heart_filled@2x.png has changed diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Resources/Icons/target.png Binary file project_files/HedgewarsMobile/Resources/Icons/target.png has changed diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Resources/Icons/target@2x.png Binary file project_files/HedgewarsMobile/Resources/Icons/target@2x.png has changed diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Resources/Icons/target_filled.png Binary file project_files/HedgewarsMobile/Resources/Icons/target_filled.png has changed diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Resources/Icons/target_filled@2x.png Binary file project_files/HedgewarsMobile/Resources/Icons/target_filled@2x.png has changed diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Resources/Icons/teams.png Binary file project_files/HedgewarsMobile/Resources/Icons/teams.png has changed diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Resources/Icons/teams@2x.png Binary file project_files/HedgewarsMobile/Resources/Icons/teams@2x.png has changed diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Resources/Icons/teams_filled.png Binary file project_files/HedgewarsMobile/Resources/Icons/teams_filled.png has changed diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Resources/Icons/teams_filled@2x.png Binary file project_files/HedgewarsMobile/Resources/Icons/teams_filled@2x.png has changed diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Resources/basicFlags.plist --- a/project_files/HedgewarsMobile/Resources/basicFlags.plist Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Resources/basicFlags.plist Tue Nov 10 20:43:13 2015 +0100 @@ -266,5 +266,41 @@ title Get Away Time (%) + + checkOverMax + + times1000 + + command + e$airmines + default + 0 + image + Mine + max + 80 + min + 0 + title + Air Mines + + + checkOverMax + + times1000 + + command + e$worldedge + default + 0 + image + Earth + max + 3 + min + 0 + title + World Edge + diff -r 31570b766315 -r ed5a6478e710 project_files/HedgewarsMobile/Resources/credits.plist --- a/project_files/HedgewarsMobile/Resources/credits.plist Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/HedgewarsMobile/Resources/credits.plist Tue Nov 10 20:43:13 2015 +0100 @@ -3,9 +3,9 @@ - Andrey "UnC0Rr" Korotaev + Andrey "unC0Rr" Korotaev Igor "Displacer" Ulyanov - Derek "Nemo" Pomery + Derek "nemo" Pomery Martin "Affect" Boze David "Krawek" Cuadrado Martin "Ttsmj" Minarik @@ -13,12 +13,20 @@ Vittorio "Koda" Giovara Mario "Smaxx" Liebisch Carlos "Palewolf" Vives - Richard "Sheepluva" Korlyi + Richard "sheepluva" Karolyi Henning "Prg" Kühn Henrik "Henek" Rostedt - John "Mikade" Lambert + John "mikade" Lambert Mayur "Zorg" Pawashe Richard "Xeli" Deurwaarder + Simeon Maxein + Meng Xiangyun + Stepan Podoskin + Szabolcs Orbàn + Drew Gottlieb + Ondrej Skopek + Julia Struchenko + Anton "antonc27" Malmygin John "Fizzy" Dum @@ -26,7 +34,8 @@ Stanko Tadić Julien Koesten Joshua O'Sullivan - Nils Luck + Nils Lück + Guillaume Englert Trey Perry @@ -42,16 +51,16 @@ Jie Luo Andrey Korotaev Nina Kuisma - Antoine Turmel - Peter Hüwe, Mario Liebisch, Richard Karolyi + Antoine Turmel, Clement Woitrain, Matisumi + Peter Hüwe, Mario Liebisch, Richard Karolyi, Wuzzy Talos Kriti - Luca Bonora, Marco Bresciani - Adam Etienne + Luca Bonora, Marco Bresciani, Gianfranco Costamagna + Adam Etienne, Marco Bresciani Anthony Bellew Lukas Urbonas Maciej Mroziński, Wojciech Latkowski, Piotr Mitana, Maciej Górny Fábio Canário - Andrey Korotaev + Andrey Korotaev, Vitaly Novichkov, Anton Malmygin Jose Riha Carlos Vives Niklas Grahn, Henrik Rostedt @@ -80,6 +89,14 @@ Lua game modes and missions Desktop frontend improvements Android port + Android netplay, portability abstraction + WebGL port, some pas2c and GLES2 work + Video recording + Campaign support, first campaign + Keybinds, feedback, maps and hats interfaces + Login dialogs, frontend improvements + Icegun weapon + Current developer of iPhone/iPad versions Main graphics @@ -88,6 +105,7 @@ + Some hats diff -r 31570b766315 -r ed5a6478e710 project_files/cmdlineClient/cmdlineClient.c --- a/project_files/cmdlineClient/cmdlineClient.c Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/cmdlineClient/cmdlineClient.c Tue Nov 10 20:43:13 2015 +0100 @@ -1,475 +1,475 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#define ENGINE_DIR ".\\" -#define CONFIG_DIR "..\\share\\hedgewars" -#define DATA_DIR CONFIG_DIR"\\Data" - -static flib_netconn *netconn; -static flib_gameconn *gameconn; -static flib_mapconn *mapconn; -static char nickname[128]; -static flib_metascheme *metacfg; -static bool netConnected = false; - -// Callback function that will be called when the map is rendered -static void handleMapGenerated(void *context, const uint8_t *bitmap, int numHedgehogs) { - printf("Drawing map for %i brave little hogs...", numHedgehogs); - - // Draw the map as ASCII art - for(int y=0; y>3] & (1<<(7-(pixelnum&7))); - printf(pixel ? "#" : " "); - } - printf("\n"); - } - - flib_mapconn_destroy(mapconn); - mapconn = NULL; -} - -static void onGameDisconnect(void *context, int reason) { - flib_log_i("Connection closed. Reason: %i", reason); - flib_gameconn_destroy(gameconn); - gameconn = NULL; - if(netconn) { - flib_netconn_send_roundfinished(netconn, reason==GAME_END_FINISHED); - } -} - -// Callback function that will be called on error -static void handleMapFailure(void *context, const char *errormessage) { - flib_log_e("Map rendering failed: %s", errormessage); - flib_mapconn_destroy(mapconn); - mapconn = NULL; -} - -static void startEngineMap(int port) { - char cmdbuffer[255]; - char argbuffer[255]; - snprintf(cmdbuffer, 255, "%shwengine.exe", ENGINE_DIR); - snprintf(argbuffer, 255, "%s %i landpreview", CONFIG_DIR, port); - ShellExecute(NULL, NULL, cmdbuffer, argbuffer, NULL, SW_HIDE); -} - -static void startEngineGame(int port) { - char cmdbuffer[255]; - char argbuffer[255]; - char base64PlayerName[255]; - base64_encode(nickname, strlen(nickname), base64PlayerName, sizeof(base64PlayerName)); - snprintf(cmdbuffer, 255, "%shwengine.exe", ENGINE_DIR); - snprintf(argbuffer, 255, "%s 1024 768 32 %i 0 0 0 10 10 %s 0 0 %s 0 0 en.txt", CONFIG_DIR, port, DATA_DIR, base64PlayerName); - ShellExecute(NULL, NULL, cmdbuffer, argbuffer, NULL, SW_HIDE); -} - -void handleNetDisconnect(void *context, int reason, const char *message) { - printf("Disconnected: %s", message); - flib_netconn_destroy(netconn); - netconn = NULL; -} - -/*void printRoomList() { - const flib_roomlist *roomlist = flib_netconn_get_roomlist(netconn); - if(roomlist) { - if(roomlist->roomCount>0) { - for(int i=0; iroomCount; i++) { - if(i>0) { - printf(", "); - } - flib_room *room = roomlist->rooms[i]; - printf("%s", room->name); - } - } else { - puts("Unfortunately, there are no rooms at the moment."); - } - } else { - puts("Sorry, due to an error the room list is not available."); - } - puts("\n"); -}*/ - -void printTeamList() { - flib_gamesetup *setup = flib_netconn_create_gamesetup(netconn); - if(setup) { - puts("The following teams are in this room:"); - for(int i=0; iteamlist->teamCount; i++) { - if(i>0) { - printf(", "); - } - printf("%s", setup->teamlist->teams[i]->name); - } - puts("\n"); - } else { - puts("Sorry, due to an error the team list is not available."); - } - flib_gamesetup_destroy(setup); -} - -void handleNetConnected(void *context) { - printf("You enter the lobby of a strange house inhabited by hedgehogs. Looking around, you see hallways branching off to these rooms:\n"); - //printRoomList(); - printf("\n\nNow, you can chat by just entering text, or join a room with /join ."); - printf(" You can also /quit or let me /describe . Once in a room, you can /add and set yourself /ready. You can also /list the available rooms (in the lobby) or the teams (in a room).\n"); - netConnected = true; -} - -void handleChat(void *context, const char *nick, const char *msg) { - if(gameconn) { - flib_gameconn_send_chatmsg(gameconn, nick, msg); - } - printf("%s: %s\n", nick, msg); -} - -void handleEnterRoom(void *context, bool isChief) { - puts("You have entered the room."); -} - -void handleRoomJoin(void *context, const char *nick) { - if(strcmp(nick, nickname)) { - printf("%s is here.\n", nick); - } -} - -void handleRoomLeave(void *context, const char *nick, const char *partmsg) { - if(strcmp(nick, nickname)) { - printf("%s leaves.\n", nick); - } -} - -void handleReady(void *context, const char *nick, bool ready) { - if(strcmp(nick, nickname)) { - if(ready) { - printf("%s is ready to go.\n", nick); - } else { - printf("%s is not ready.\n", nick); - } - } else { - if(ready) { - printf("You are ready to go.\n"); - } else { - printf("You are not ready.\n"); - } - } -} - -void handleEmFromNet(void *context, const uint8_t *em, size_t size) { - if(gameconn) { - flib_gameconn_send_enginemsg(gameconn, em, size); - } -} - -void handleEmFromEngine(void *context, const uint8_t *em, size_t size) { - if(netconn) { - flib_netconn_send_engineMessage(netconn, em, size); - } -} - -void handleChatFromGame(void *context, const char *message, bool teamchat) { - if(netconn) { - if(teamchat) { - flib_netconn_send_teamchat(netconn, message); - } else { - flib_netconn_send_chat(netconn, message); - } - } -} - -void handleRunGame(void *context) { - flib_gamesetup *gamesetup = flib_netconn_create_gamesetup(netconn); - if(gameconn) { - flib_log_e("Request to start game, but a game is already running."); - } else if(gamesetup) { - gameconn = flib_gameconn_create(nickname, gamesetup, true); - flib_gameconn_onEngineMessage(gameconn, handleEmFromEngine, NULL); - flib_gameconn_onDisconnect(gameconn, onGameDisconnect, NULL); - flib_gameconn_onChat(gameconn, handleChatFromGame, NULL); - startEngineGame(flib_gameconn_getport(gameconn)); - } - flib_gamesetup_destroy(gamesetup); -} - -void handleNickTaken(void *context, const char *nick) { - printf("The nickname %s is already in use, please choose a different one:\n", nick); - flib_gets(nickname, sizeof(nickname)); - flib_netconn_send_nick(netconn, nickname); -} - -void handlePwRequest(void *context, const char *nick) { - printf("A password is required to log in as %s, please enter (warning: shown in cleartext):\n", nick); - char password[256]; - flib_gets(password, sizeof(password)); - flib_netconn_send_password(netconn, password); -} - -void handleMessage(void *context, int type, const char *msg) { - if(gameconn) { - flib_gameconn_send_textmsg(gameconn, 1, msg); - } - printf("*** %s\n", msg); -} - -void handleTeamAccepted(void *context, const char *teamname) { - printf("The team %s has been accepted.\n", teamname); -} - -void handleMapChanged(void *context, const flib_map *map, int changetype) { - if(map->mapgen != MAPGEN_NAMED && changetype != NETCONN_MAPCHANGE_THEME) { - if(mapconn) { - flib_mapconn_destroy(mapconn); - mapconn = NULL; - } - mapconn = flib_mapconn_create(map); - if(mapconn) { - flib_mapconn_onSuccess(mapconn, handleMapGenerated, NULL); - flib_mapconn_onFailure(mapconn, handleMapFailure, NULL); - startEngineMap(flib_mapconn_getport(mapconn)); - } - } else if(map->mapgen == MAPGEN_NAMED) { - printf("The map %s has been selected.\n", map->name); - } -} - -void handleLeaveRoom(void *context, int reason, const char *msg) { - if(reason == NETCONN_ROOMLEAVE_ABANDONED) { - printf("The chief has abandoned the room."); - } else if(reason == NETCONN_ROOMLEAVE_KICKED) { - printf("You have been kicked from the room."); - } - if(msg) { - printf(" (%s)", msg); - } - puts(" You are back in the lobby."); -} - -void handleSchemeChanged(void *context, const flib_scheme *scheme) { - printf("Game scheme: %s.\n", scheme->name); -} - -void handleWeaponsetChanged(void *context, const flib_weaponset *weaponset) { - printf("Weaponset: %s.\n", weaponset->name); -} - -void handleHogcountChanged(void *context, const char *team, int count) { - printf("Team %s will send %i hogs into the fight.\n", team, count); -} - -void handleRoomAdd(void *context, const flib_room *room) { - printf("%s created a new room called %s.\n", room->owner, room->name); -} - -void handleRoomDelete(void *context, const char *roomName) { - printf("The room %s has collapsed.\n", roomName); -} - -void handleScriptChanged(void *context, const char *script) { - printf("Game Type: %s\n", script); -} - -void handleTeamAdd(void *context, const flib_team *team) { - printf("%s puts the team %s to the planning board.\n", team->ownerName, team->name); -} - -void handleTeamDelete(void *context, const char *teamName) { - printf("The team %s decided not to fight this battle after all.\n", teamName); -} - -void handleTeamColorChanged(void *context, const char *name, int colorIndex) { - static const char* colorNames[] = {"red", "blue", "teal", "purple", "pink", "green", "orange", "brown", "yellow"}; - const char *colorName = "strange"; - if(colorIndex>=0 && colorIndex < 9) { - colorName = colorNames[colorIndex]; - } - printf("The team %s will wear %s uniforms today.\n", name, colorName); -} - -void tick() { - if(gameconn) { - flib_gameconn_tick(gameconn); - } - if(netconn) { - flib_netconn_tick(netconn); - } - if(mapconn) { - flib_mapconn_tick(mapconn); - } -} - -static HANDLE hStdin; - -static int init() { - hStdin = GetStdHandle(STD_INPUT_HANDLE); - if(hStdin == INVALID_HANDLE_VALUE) { - flib_log_e("Unable to get stdin handle"); - return 1; - } - if(!flib_init(0)) { - flib_log_setLevel(FLIB_LOGLEVEL_WARNING); - freopen( "CON", "w", stdout ); - freopen( "CON", "w", stderr ); - metacfg = flib_metascheme_from_ini("metasettings.ini"); - if(!metacfg) { - flib_quit(); - return -1; - } else { - return 0; - } - } - return -1; -} - -int main(int argc, char *argv[]) { - if(init()) { - return -1; - } - - puts("Please enter a nickname:"); - flib_gets(nickname, sizeof(nickname)); - - netconn = flib_netconn_create(nickname, metacfg, DATA_DIR"\\", "140.247.62.101", 46631); - if(!netconn) { - flib_quit(); - return -1; - } - - flib_netconn_onConnected(netconn, handleNetConnected, NULL); - flib_netconn_onDisconnected(netconn, handleNetDisconnect, NULL); - flib_netconn_onChat(netconn, handleChat, NULL); - flib_netconn_onEnterRoom(netconn, handleEnterRoom, NULL); - flib_netconn_onRunGame(netconn, handleRunGame, NULL); - flib_netconn_onEngineMessage(netconn, handleEmFromNet, NULL); - flib_netconn_onRoomJoin(netconn, handleRoomJoin, NULL); - flib_netconn_onRoomLeave(netconn, handleRoomLeave, NULL); - flib_netconn_onReadyState(netconn, handleReady, NULL); - flib_netconn_onNickTaken(netconn, handleNickTaken, NULL); - flib_netconn_onPasswordRequest(netconn, handlePwRequest, NULL); - flib_netconn_onMessage(netconn, handleMessage, NULL); - flib_netconn_onTeamAccepted(netconn, handleTeamAccepted, NULL); - flib_netconn_onMapChanged(netconn, handleMapChanged, NULL); - flib_netconn_onLeaveRoom(netconn, handleLeaveRoom, NULL); - flib_netconn_onCfgScheme(netconn, handleSchemeChanged, NULL); - flib_netconn_onWeaponsetChanged(netconn, handleWeaponsetChanged, NULL); - flib_netconn_onHogCountChanged(netconn, handleHogcountChanged, NULL); - flib_netconn_onRoomAdd(netconn, handleRoomAdd, NULL); - flib_netconn_onRoomDelete(netconn, handleRoomDelete, NULL); - flib_netconn_onScriptChanged(netconn, handleScriptChanged, NULL); - flib_netconn_onTeamAdd(netconn, handleTeamAdd, NULL); - flib_netconn_onTeamDelete(netconn, handleTeamDelete, NULL); - flib_netconn_onTeamColorChanged(netconn, handleTeamColorChanged, NULL); - - INPUT_RECORD inputRecord; - DWORD eventCount = 0; - - while(netconn || gameconn) { - tick(); - if(netconn && netConnected) { - while(PeekConsoleInput(hStdin, &inputRecord, 1, &eventCount) && eventCount>0) { - if(inputRecord.EventType != KEY_EVENT) { - ReadConsoleInput(hStdin, &inputRecord, 1, &eventCount); - } else { - printf("%s: ", nickname); - char input[256]; - if(!flib_gets(input, sizeof(input))) { - if(!memcmp("/quit", input, strlen("/quit"))) { - flib_netconn_send_quit(netconn, "Player quit."); - } else if(!memcmp("/describe ", input, strlen("/describe "))) { - const char *roomname = input+strlen("/describe "); - /*const flib_roomlist *roomlist = flib_netconn_get_roomlist(netconn); - flib_room *room = flib_roomlist_find(roomlist, roomname); - if(!room) { - puts("Unknown room."); - } else { - char *text = flib_asprintf( - "%s is a room created by %s, where %i players (%i teams) are %s on %s%s, using the %s scheme and %s weaponset.", - room->name, - room->owner, - room->playerCount, - room->teamCount, - room->inProgress ? "fighting" : "preparing to fight", - room->map[0]=='+' ? "" : "the map ", - !strcmp("+rnd+", room->map) ? "a random map" : - !strcmp("+maze+", room->map) ? "a random maze" : - !strcmp("+drawn+", room->map) ? "a hand-drawn map" : - room->map, - room->scheme, - room->weapons); - if(text) { - puts(text); - } - free(text); - }*/ - } else if(!memcmp("/join ", input, strlen("/join "))) { - const char *roomname = input+strlen("/join "); - flib_netconn_send_joinRoom(netconn, roomname); - } else if(!memcmp("/ready", input, strlen("/ready"))) { - flib_netconn_send_toggleReady(netconn); - } else if(!memcmp("/loglevel ", input, strlen("/loglevel "))) { - int loglevel = atoi(input+strlen("/loglevel ")); - flib_log_setLevel(loglevel); - } else if(!memcmp("/list", input, strlen("/list"))) { - if(flib_netconn_is_in_room_context(netconn)) { - printTeamList(); - } else { - puts("From this big and expansive lobby, hallways branch off to these rooms:"); - //printRoomList(); - } - } else if(!memcmp("/addteam ", input, strlen("/addteam "))) { - const char *teamname = input+strlen("/addteam "); - if(!flib_contains_dir_separator(teamname)) { - char *teamfilename = flib_asprintf("%s.hwt", teamname); - if(teamfilename) { - flib_team *team = flib_team_from_ini(teamfilename); - if(team) { - flib_netconn_send_addTeam(netconn, team); - } else { - printf("Teamfile %s not found.\n", teamfilename); - } - flib_team_destroy(team); - } - free(teamfilename); - } - } else if(strlen(input)>0) { - flib_netconn_send_chat(netconn, input); - } - } - } - } - } - fflush(stdout); - Sleep(10); - } - - - flib_metascheme_release(metacfg); - return 0; -} +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#define ENGINE_DIR ".\\" +#define CONFIG_DIR "..\\share\\hedgewars" +#define DATA_DIR CONFIG_DIR"\\Data" + +static flib_netconn *netconn; +static flib_gameconn *gameconn; +static flib_mapconn *mapconn; +static char nickname[128]; +static flib_metascheme *metacfg; +static bool netConnected = false; + +// Callback function that will be called when the map is rendered +static void handleMapGenerated(void *context, const uint8_t *bitmap, int numHedgehogs) { + printf("Drawing map for %i brave little hogs...", numHedgehogs); + + // Draw the map as ASCII art + for(int y=0; y>3] & (1<<(7-(pixelnum&7))); + printf(pixel ? "#" : " "); + } + printf("\n"); + } + + flib_mapconn_destroy(mapconn); + mapconn = NULL; +} + +static void onGameDisconnect(void *context, int reason) { + flib_log_i("Connection closed. Reason: %i", reason); + flib_gameconn_destroy(gameconn); + gameconn = NULL; + if(netconn) { + flib_netconn_send_roundfinished(netconn, reason==GAME_END_FINISHED); + } +} + +// Callback function that will be called on error +static void handleMapFailure(void *context, const char *errormessage) { + flib_log_e("Map rendering failed: %s", errormessage); + flib_mapconn_destroy(mapconn); + mapconn = NULL; +} + +static void startEngineMap(int port) { + char cmdbuffer[255]; + char argbuffer[255]; + snprintf(cmdbuffer, 255, "%shwengine.exe", ENGINE_DIR); + snprintf(argbuffer, 255, "%s %i landpreview", CONFIG_DIR, port); + ShellExecute(NULL, NULL, cmdbuffer, argbuffer, NULL, SW_HIDE); +} + +static void startEngineGame(int port) { + char cmdbuffer[255]; + char argbuffer[255]; + char base64PlayerName[255]; + base64_encode(nickname, strlen(nickname), base64PlayerName, sizeof(base64PlayerName)); + snprintf(cmdbuffer, 255, "%shwengine.exe", ENGINE_DIR); + snprintf(argbuffer, 255, "%s 1024 768 32 %i 0 0 0 10 10 %s 0 0 %s 0 0 en.txt", CONFIG_DIR, port, DATA_DIR, base64PlayerName); + ShellExecute(NULL, NULL, cmdbuffer, argbuffer, NULL, SW_HIDE); +} + +void handleNetDisconnect(void *context, int reason, const char *message) { + printf("Disconnected: %s", message); + flib_netconn_destroy(netconn); + netconn = NULL; +} + +/*void printRoomList() { + const flib_roomlist *roomlist = flib_netconn_get_roomlist(netconn); + if(roomlist) { + if(roomlist->roomCount>0) { + for(int i=0; iroomCount; i++) { + if(i>0) { + printf(", "); + } + flib_room *room = roomlist->rooms[i]; + printf("%s", room->name); + } + } else { + puts("Unfortunately, there are no rooms at the moment."); + } + } else { + puts("Sorry, due to an error the room list is not available."); + } + puts("\n"); +}*/ + +void printTeamList() { + flib_gamesetup *setup = flib_netconn_create_gamesetup(netconn); + if(setup) { + puts("The following teams are in this room:"); + for(int i=0; iteamlist->teamCount; i++) { + if(i>0) { + printf(", "); + } + printf("%s", setup->teamlist->teams[i]->name); + } + puts("\n"); + } else { + puts("Sorry, due to an error the team list is not available."); + } + flib_gamesetup_destroy(setup); +} + +void handleNetConnected(void *context) { + printf("You enter the lobby of a strange house inhabited by hedgehogs. Looking around, you see hallways branching off to these rooms:\n"); + //printRoomList(); + printf("\n\nNow, you can chat by just entering text, or join a room with /join ."); + printf(" You can also /quit or let me /describe . Once in a room, you can /add and set yourself /ready. You can also /list the available rooms (in the lobby) or the teams (in a room).\n"); + netConnected = true; +} + +void handleChat(void *context, const char *nick, const char *msg) { + if(gameconn) { + flib_gameconn_send_chatmsg(gameconn, nick, msg); + } + printf("%s: %s\n", nick, msg); +} + +void handleEnterRoom(void *context, bool isChief) { + puts("You have entered the room."); +} + +void handleRoomJoin(void *context, const char *nick) { + if(strcmp(nick, nickname)) { + printf("%s is here.\n", nick); + } +} + +void handleRoomLeave(void *context, const char *nick, const char *partmsg) { + if(strcmp(nick, nickname)) { + printf("%s leaves.\n", nick); + } +} + +void handleReady(void *context, const char *nick, bool ready) { + if(strcmp(nick, nickname)) { + if(ready) { + printf("%s is ready to go.\n", nick); + } else { + printf("%s is not ready.\n", nick); + } + } else { + if(ready) { + printf("You are ready to go.\n"); + } else { + printf("You are not ready.\n"); + } + } +} + +void handleEmFromNet(void *context, const uint8_t *em, size_t size) { + if(gameconn) { + flib_gameconn_send_enginemsg(gameconn, em, size); + } +} + +void handleEmFromEngine(void *context, const uint8_t *em, size_t size) { + if(netconn) { + flib_netconn_send_engineMessage(netconn, em, size); + } +} + +void handleChatFromGame(void *context, const char *message, bool teamchat) { + if(netconn) { + if(teamchat) { + flib_netconn_send_teamchat(netconn, message); + } else { + flib_netconn_send_chat(netconn, message); + } + } +} + +void handleRunGame(void *context) { + flib_gamesetup *gamesetup = flib_netconn_create_gamesetup(netconn); + if(gameconn) { + flib_log_e("Request to start game, but a game is already running."); + } else if(gamesetup) { + gameconn = flib_gameconn_create(nickname, gamesetup, true); + flib_gameconn_onEngineMessage(gameconn, handleEmFromEngine, NULL); + flib_gameconn_onDisconnect(gameconn, onGameDisconnect, NULL); + flib_gameconn_onChat(gameconn, handleChatFromGame, NULL); + startEngineGame(flib_gameconn_getport(gameconn)); + } + flib_gamesetup_destroy(gamesetup); +} + +void handleNickTaken(void *context, const char *nick) { + printf("The nickname %s is already in use, please choose a different one:\n", nick); + flib_gets(nickname, sizeof(nickname)); + flib_netconn_send_nick(netconn, nickname); +} + +void handlePwRequest(void *context, const char *nick) { + printf("A password is required to log in as %s, please enter (warning: shown in cleartext):\n", nick); + char password[256]; + flib_gets(password, sizeof(password)); + flib_netconn_send_password(netconn, password); +} + +void handleMessage(void *context, int type, const char *msg) { + if(gameconn) { + flib_gameconn_send_textmsg(gameconn, 1, msg); + } + printf("*** %s\n", msg); +} + +void handleTeamAccepted(void *context, const char *teamname) { + printf("The team %s has been accepted.\n", teamname); +} + +void handleMapChanged(void *context, const flib_map *map, int changetype) { + if(map->mapgen != MAPGEN_NAMED && changetype != NETCONN_MAPCHANGE_THEME) { + if(mapconn) { + flib_mapconn_destroy(mapconn); + mapconn = NULL; + } + mapconn = flib_mapconn_create(map); + if(mapconn) { + flib_mapconn_onSuccess(mapconn, handleMapGenerated, NULL); + flib_mapconn_onFailure(mapconn, handleMapFailure, NULL); + startEngineMap(flib_mapconn_getport(mapconn)); + } + } else if(map->mapgen == MAPGEN_NAMED) { + printf("The map %s has been selected.\n", map->name); + } +} + +void handleLeaveRoom(void *context, int reason, const char *msg) { + if(reason == NETCONN_ROOMLEAVE_ABANDONED) { + printf("The chief has abandoned the room."); + } else if(reason == NETCONN_ROOMLEAVE_KICKED) { + printf("You have been kicked from the room."); + } + if(msg) { + printf(" (%s)", msg); + } + puts(" You are back in the lobby."); +} + +void handleSchemeChanged(void *context, const flib_scheme *scheme) { + printf("Game scheme: %s.\n", scheme->name); +} + +void handleWeaponsetChanged(void *context, const flib_weaponset *weaponset) { + printf("Weaponset: %s.\n", weaponset->name); +} + +void handleHogcountChanged(void *context, const char *team, int count) { + printf("Team %s will send %i hogs into the fight.\n", team, count); +} + +void handleRoomAdd(void *context, const flib_room *room) { + printf("%s created a new room called %s.\n", room->owner, room->name); +} + +void handleRoomDelete(void *context, const char *roomName) { + printf("The room %s has collapsed.\n", roomName); +} + +void handleScriptChanged(void *context, const char *script) { + printf("Game Type: %s\n", script); +} + +void handleTeamAdd(void *context, const flib_team *team) { + printf("%s puts the team %s to the planning board.\n", team->ownerName, team->name); +} + +void handleTeamDelete(void *context, const char *teamName) { + printf("The team %s decided not to fight this battle after all.\n", teamName); +} + +void handleTeamColorChanged(void *context, const char *name, int colorIndex) { + static const char* colorNames[] = {"red", "blue", "teal", "purple", "pink", "green", "orange", "brown", "yellow"}; + const char *colorName = "strange"; + if(colorIndex>=0 && colorIndex < 9) { + colorName = colorNames[colorIndex]; + } + printf("The team %s will wear %s uniforms today.\n", name, colorName); +} + +void tick() { + if(gameconn) { + flib_gameconn_tick(gameconn); + } + if(netconn) { + flib_netconn_tick(netconn); + } + if(mapconn) { + flib_mapconn_tick(mapconn); + } +} + +static HANDLE hStdin; + +static int init() { + hStdin = GetStdHandle(STD_INPUT_HANDLE); + if(hStdin == INVALID_HANDLE_VALUE) { + flib_log_e("Unable to get stdin handle"); + return 1; + } + if(!flib_init(0)) { + flib_log_setLevel(FLIB_LOGLEVEL_WARNING); + freopen( "CON", "w", stdout ); + freopen( "CON", "w", stderr ); + metacfg = flib_metascheme_from_ini("metasettings.ini"); + if(!metacfg) { + flib_quit(); + return -1; + } else { + return 0; + } + } + return -1; +} + +int main(int argc, char *argv[]) { + if(init()) { + return -1; + } + + puts("Please enter a nickname:"); + flib_gets(nickname, sizeof(nickname)); + + netconn = flib_netconn_create(nickname, metacfg, DATA_DIR"\\", "140.247.62.101", 46631); + if(!netconn) { + flib_quit(); + return -1; + } + + flib_netconn_onConnected(netconn, handleNetConnected, NULL); + flib_netconn_onDisconnected(netconn, handleNetDisconnect, NULL); + flib_netconn_onChat(netconn, handleChat, NULL); + flib_netconn_onEnterRoom(netconn, handleEnterRoom, NULL); + flib_netconn_onRunGame(netconn, handleRunGame, NULL); + flib_netconn_onEngineMessage(netconn, handleEmFromNet, NULL); + flib_netconn_onRoomJoin(netconn, handleRoomJoin, NULL); + flib_netconn_onRoomLeave(netconn, handleRoomLeave, NULL); + flib_netconn_onReadyState(netconn, handleReady, NULL); + flib_netconn_onNickTaken(netconn, handleNickTaken, NULL); + flib_netconn_onPasswordRequest(netconn, handlePwRequest, NULL); + flib_netconn_onMessage(netconn, handleMessage, NULL); + flib_netconn_onTeamAccepted(netconn, handleTeamAccepted, NULL); + flib_netconn_onMapChanged(netconn, handleMapChanged, NULL); + flib_netconn_onLeaveRoom(netconn, handleLeaveRoom, NULL); + flib_netconn_onCfgScheme(netconn, handleSchemeChanged, NULL); + flib_netconn_onWeaponsetChanged(netconn, handleWeaponsetChanged, NULL); + flib_netconn_onHogCountChanged(netconn, handleHogcountChanged, NULL); + flib_netconn_onRoomAdd(netconn, handleRoomAdd, NULL); + flib_netconn_onRoomDelete(netconn, handleRoomDelete, NULL); + flib_netconn_onScriptChanged(netconn, handleScriptChanged, NULL); + flib_netconn_onTeamAdd(netconn, handleTeamAdd, NULL); + flib_netconn_onTeamDelete(netconn, handleTeamDelete, NULL); + flib_netconn_onTeamColorChanged(netconn, handleTeamColorChanged, NULL); + + INPUT_RECORD inputRecord; + DWORD eventCount = 0; + + while(netconn || gameconn) { + tick(); + if(netconn && netConnected) { + while(PeekConsoleInput(hStdin, &inputRecord, 1, &eventCount) && eventCount>0) { + if(inputRecord.EventType != KEY_EVENT) { + ReadConsoleInput(hStdin, &inputRecord, 1, &eventCount); + } else { + printf("%s: ", nickname); + char input[256]; + if(!flib_gets(input, sizeof(input))) { + if(!memcmp("/quit", input, strlen("/quit"))) { + flib_netconn_send_quit(netconn, "Player quit."); + } else if(!memcmp("/describe ", input, strlen("/describe "))) { + const char *roomname = input+strlen("/describe "); + /*const flib_roomlist *roomlist = flib_netconn_get_roomlist(netconn); + flib_room *room = flib_roomlist_find(roomlist, roomname); + if(!room) { + puts("Unknown room."); + } else { + char *text = flib_asprintf( + "%s is a room created by %s, where %i players (%i teams) are %s on %s%s, using the %s scheme and %s weaponset.", + room->name, + room->owner, + room->playerCount, + room->teamCount, + room->inProgress ? "fighting" : "preparing to fight", + room->map[0]=='+' ? "" : "the map ", + !strcmp("+rnd+", room->map) ? "a random map" : + !strcmp("+maze+", room->map) ? "a random maze" : + !strcmp("+drawn+", room->map) ? "a hand-drawn map" : + room->map, + room->scheme, + room->weapons); + if(text) { + puts(text); + } + free(text); + }*/ + } else if(!memcmp("/join ", input, strlen("/join "))) { + const char *roomname = input+strlen("/join "); + flib_netconn_send_joinRoom(netconn, roomname); + } else if(!memcmp("/ready", input, strlen("/ready"))) { + flib_netconn_send_toggleReady(netconn); + } else if(!memcmp("/loglevel ", input, strlen("/loglevel "))) { + int loglevel = atoi(input+strlen("/loglevel ")); + flib_log_setLevel(loglevel); + } else if(!memcmp("/list", input, strlen("/list"))) { + if(flib_netconn_is_in_room_context(netconn)) { + printTeamList(); + } else { + puts("From this big and expansive lobby, hallways branch off to these rooms:"); + //printRoomList(); + } + } else if(!memcmp("/addteam ", input, strlen("/addteam "))) { + const char *teamname = input+strlen("/addteam "); + if(!flib_contains_dir_separator(teamname)) { + char *teamfilename = flib_asprintf("%s.hwt", teamname); + if(teamfilename) { + flib_team *team = flib_team_from_ini(teamfilename); + if(team) { + flib_netconn_send_addTeam(netconn, team); + } else { + printf("Teamfile %s not found.\n", teamfilename); + } + flib_team_destroy(team); + } + free(teamfilename); + } + } else if(strlen(input)>0) { + flib_netconn_send_chat(netconn, input); + } + } + } + } + } + fflush(stdout); + Sleep(10); + } + + + flib_metascheme_release(metacfg); + return 0; +} diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/Android.mk --- a/project_files/frontlib/Android.mk Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/Android.mk Tue Nov 10 20:43:13 2015 +0100 @@ -4,17 +4,17 @@ LOCAL_MODULE := frontlib -LOCAL_CFLAGS := -I$(LOCAL_PATH)/../Android-build/SDL-android-project/jni/SDL_net -std=c99 -I$(LOCAL_PATH)/../Android-build/SDL-android-project/jni/SDL/include +LOCAL_CFLAGS := -I$(LOCAL_PATH)/../Android-build/SDL-android-project/jni/SDL_net -std=c99 -I$(LOCAL_PATH)/../Android-build/SDL-android-project/jni/SDL/include LOCAL_SRC_FILES := base64/base64.c iniparser/iniparser.c \ - iniparser/dictionary.c ipc/gameconn.c ipc/ipcbase.c \ - ipc/ipcprotocol.c ipc/mapconn.c md5/md5.c model/scheme.c \ - model/gamesetup.c model/map.c model/mapcfg.c model/room.c \ - model/schemelist.c model/team.c model/teamlist.c model/weapon.c \ - net/netbase.c net/netconn_callbacks.c net/netconn_send.c \ - net/netconn.c net/netprotocol.c util/buffer.c util/inihelper.c \ - util/logging.c util/util.c frontlib.c hwconsts.c socket.c \ - extra/jnacontrol.c + iniparser/dictionary.c ipc/gameconn.c ipc/ipcbase.c \ + ipc/ipcprotocol.c ipc/mapconn.c md5/md5.c model/scheme.c \ + model/gamesetup.c model/map.c model/mapcfg.c model/room.c \ + model/schemelist.c model/team.c model/teamlist.c model/weapon.c \ + net/netbase.c net/netconn_callbacks.c net/netconn_send.c \ + net/netconn.c net/netprotocol.c util/buffer.c util/inihelper.c \ + util/logging.c util/util.c frontlib.c hwconsts.c socket.c \ + extra/jnacontrol.c LOCAL_SHARED_LIBRARIES += SDL SDL_net LOCAL_LDLIBS += -lz diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/extra/jnacontrol.c --- a/project_files/frontlib/extra/jnacontrol.c Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/extra/jnacontrol.c Tue Nov 10 20:43:13 2015 +0100 @@ -1,240 +1,240 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/* - * This file is not directly part of the frontlib and is not required to build it. - * However, it is recommended to include it in compilation when building for Android. The purpose of this file - * is to ensure consistency between the function signatures of the JNA Java bindings of the Android port and the - * frontlib functions. - * - * This file, in essence, consists only of function declarations. They are duplicates of function declarations - * from the frontlib headers that are referenced from JNA bindings. If the signature of one of these functions - * changes in the frontlib, it will no longer match the signature in this file, and the compiler will show an error. - * If that happens, you need to update the JNA bindings in Hedgeroid to match the new function signature, and then - * update this file. - * - * The reason for all this is that JNA does not actually know the function signatures of the functions it binds, - * it derives them from Java method declarations. If those do not match the actual function signatures, you will - * only notice when you suddenly get strange (and possibly hard to track down) problems at runtime. This file is - * an attempt to detect these problems at compile time instead. Notice that it will NOT detect changes to structs - * or constants though, which also require updates to the JNA bindings. - */ - -/* - * Before we include the frontlib headers, we define away the const keyword. This is necessary because there is no - * distinction between const and non-const types on the JNA side, and we don't want the compiler to complain because - * of bad constness. - * - * This is so evil, but it works... - */ -#define const - -#include "../frontlib.h" - -/* - * Now we map the Java types to the corresponding C types... - */ -typedef flib_netconn *NetconnPtr; -typedef flib_gameconn *GameconnPtr; -typedef flib_mapconn *MapconnPtr; -typedef flib_metascheme *MetaschemePtr; -typedef flib_room **RoomArrayPtr; -typedef flib_weaponset *WeaponsetPtr; -typedef flib_weaponsetlist *WeaponsetListPtr; -typedef flib_map *MapRecipePtr; -typedef flib_scheme *SchemePtr; -typedef flib_schemelist *SchemelistPtr; - -typedef flib_room *RoomPtr; -typedef flib_team *TeamPtr; -typedef flib_gamesetup *GameSetupPtr; -typedef bool boolean; -typedef size_t NativeSizeT; -typedef void *Pointer; -typedef uint8_t *ByteArrayPtr; -typedef char *String; - -/* - * Mapping callback types - */ -typedef void (*VoidCallback)(Pointer context); -typedef void (*StrCallback)(Pointer context, String arg1); -typedef void (*IntCallback)(Pointer context, int arg1); -typedef void (*IntStrCallback)(Pointer context, int arg1, String arg2); -typedef void (*StrIntCallback)(Pointer context, String arg1, int arg2); -typedef void (*StrStrCallback)(Pointer context, String arg1, String arg2); -typedef void (*StrStrBoolCallback)(Pointer context, String arg1, String arg2, boolean arg3); -typedef void (*RoomCallback)(Pointer context, RoomPtr arg1); -typedef void (*RoomListCallback)(Pointer context, RoomArrayPtr arg1, int arg2); -typedef void (*StrRoomCallback)(Pointer context, String arg1, RoomPtr arg2); -typedef void (*BoolCallback)(Pointer context, boolean arg1); -typedef void (*StrBoolCallback)(Pointer context, String arg1, boolean arg2); -typedef void (*TeamCallback)(Pointer context, TeamPtr arg1); -typedef void (*BytesCallback)(Pointer context, const uint8_t *buffer, NativeSizeT size); -typedef void (*BytesBoolCallback)(Pointer context, const uint8_t *buffer, NativeSizeT size, boolean arg3); -typedef void (*SchemeCallback)(Pointer context, SchemePtr arg1); -typedef void (*MapIntCallback)(Pointer context, MapRecipePtr arg1, int arg2); -typedef void (*WeaponsetCallback)(Pointer context, WeaponsetPtr arg1); -typedef void (*MapimageCallback)(Pointer context, const uint8_t *mapimage, int hogs); -typedef void (*LogCallback)(int arg1, String arg2); - -/* - * Below here are the copypasted method declarations from the JNA bindings - */ - - // frontlib.h - int flib_init(); - void flib_quit(); - - // hwconsts.h - int flib_get_teamcolor_count(); - int flib_get_hedgehogs_per_team(); - int flib_get_weapons_count(); - MetaschemePtr flib_get_metascheme(); - - // net/netconn.h - NetconnPtr flib_netconn_create(String playerName, String dataDirPath, String host, int port); - void flib_netconn_destroy(NetconnPtr conn); - - void flib_netconn_tick(NetconnPtr conn); - boolean flib_netconn_is_chief(NetconnPtr conn); - String flib_netconn_get_playername(NetconnPtr conn); - GameSetupPtr flib_netconn_create_gamesetup(NetconnPtr conn); - int flib_netconn_send_quit(NetconnPtr conn, String quitmsg); - int flib_netconn_send_chat(NetconnPtr conn, String chat); - int flib_netconn_send_teamchat(NetconnPtr conn, String msg); - int flib_netconn_send_password(NetconnPtr conn, String passwd); - int flib_netconn_send_nick(NetconnPtr conn, String nick); - int flib_netconn_send_request_roomlist(NetconnPtr conn); - int flib_netconn_send_joinRoom(NetconnPtr conn, String room); - int flib_netconn_send_createRoom(NetconnPtr conn, String room); - int flib_netconn_send_renameRoom(NetconnPtr conn, String roomName); - int flib_netconn_send_leaveRoom(NetconnPtr conn, String msg); - int flib_netconn_send_toggleReady(NetconnPtr conn); - int flib_netconn_send_addTeam(NetconnPtr conn, TeamPtr team); - int flib_netconn_send_removeTeam(NetconnPtr conn, String teamname); - int flib_netconn_send_engineMessage(NetconnPtr conn, ByteArrayPtr message, NativeSizeT size); - int flib_netconn_send_teamHogCount(NetconnPtr conn, String teamname, int hogcount); - int flib_netconn_send_teamColor(NetconnPtr conn, String teamname, int colorIndex); - int flib_netconn_send_weaponset(NetconnPtr conn, WeaponsetPtr weaponset); - int flib_netconn_send_map(NetconnPtr conn, MapRecipePtr map); - int flib_netconn_send_mapName(NetconnPtr conn, String mapName); - int flib_netconn_send_mapGen(NetconnPtr conn, int mapGen); - int flib_netconn_send_mapTemplate(NetconnPtr conn, int templateFilter); - int flib_netconn_send_mapMazeSize(NetconnPtr conn, int mazeSize); - int flib_netconn_send_mapSeed(NetconnPtr conn, String seed); - int flib_netconn_send_mapTheme(NetconnPtr conn, String theme); - int flib_netconn_send_mapDrawdata(NetconnPtr conn, ByteArrayPtr drawData, NativeSizeT size); - int flib_netconn_send_script(NetconnPtr conn, String scriptName); - int flib_netconn_send_scheme(NetconnPtr conn, SchemePtr scheme); - int flib_netconn_send_roundfinished(NetconnPtr conn, boolean withoutError); - int flib_netconn_send_ban(NetconnPtr conn, String playerName); - int flib_netconn_send_kick(NetconnPtr conn, String playerName); - int flib_netconn_send_playerInfo(NetconnPtr conn, String playerName); - int flib_netconn_send_playerFollow(NetconnPtr conn, String playerName); - int flib_netconn_send_startGame(NetconnPtr conn); - int flib_netconn_send_toggleRestrictJoins(NetconnPtr conn); - int flib_netconn_send_toggleRestrictTeams(NetconnPtr conn); - int flib_netconn_send_clearAccountsCache(NetconnPtr conn); - int flib_netconn_send_setServerVar(NetconnPtr conn, String name, String value); - int flib_netconn_send_getServerVars(NetconnPtr conn); - - void flib_netconn_onMessage(NetconnPtr conn, IntStrCallback callback, Pointer context); - void flib_netconn_onClientFlags(NetconnPtr conn, StrStrBoolCallback callback, Pointer context); - void flib_netconn_onChat(NetconnPtr conn, StrStrCallback callback, Pointer context); - void flib_netconn_onConnected(NetconnPtr conn, VoidCallback callback, Pointer context); - void flib_netconn_onDisconnected(NetconnPtr conn, IntStrCallback callback, Pointer context); - void flib_netconn_onRoomlist(NetconnPtr conn, RoomListCallback callback, Pointer context); - void flib_netconn_onRoomAdd(NetconnPtr conn, RoomCallback callback, Pointer context); - void flib_netconn_onRoomDelete(NetconnPtr conn, StrCallback callback, Pointer context); - void flib_netconn_onRoomUpdate(NetconnPtr conn, StrRoomCallback callback, Pointer context); - void flib_netconn_onLobbyJoin(NetconnPtr conn, StrCallback callback, Pointer context); - void flib_netconn_onLobbyLeave(NetconnPtr conn, StrStrCallback callback, Pointer context); - void flib_netconn_onNickTaken(NetconnPtr conn, StrCallback callback, Pointer context); - void flib_netconn_onPasswordRequest(NetconnPtr conn, StrCallback callback, Pointer context); - void flib_netconn_onEnterRoom(NetconnPtr conn, BoolCallback callback, Pointer context); - void flib_netconn_onLeaveRoom(NetconnPtr conn, IntStrCallback callback, Pointer context); - void flib_netconn_onTeamAdd(NetconnPtr conn, TeamCallback callback, Pointer context); - void flib_netconn_onTeamDelete(NetconnPtr conn, StrCallback callback, Pointer context); - void flib_netconn_onRoomJoin(NetconnPtr conn, StrCallback callback, Pointer context); - void flib_netconn_onRoomLeave(NetconnPtr conn, StrStrCallback callback, Pointer context); - void flib_netconn_onRunGame(NetconnPtr conn, VoidCallback callback, Pointer context); - void flib_netconn_onTeamAccepted(NetconnPtr conn, StrCallback callback, Pointer context); - void flib_netconn_onHogCountChanged(NetconnPtr conn, StrIntCallback callback, Pointer context); - void flib_netconn_onTeamColorChanged(NetconnPtr conn, StrIntCallback callback, Pointer context); - void flib_netconn_onEngineMessage(NetconnPtr conn, BytesCallback callback, Pointer context); - void flib_netconn_onSchemeChanged(NetconnPtr conn, SchemeCallback callback, Pointer context); - void flib_netconn_onMapChanged(NetconnPtr conn, MapIntCallback callback, Pointer context); - void flib_netconn_onScriptChanged(NetconnPtr conn, StrCallback callback, Pointer context); - void flib_netconn_onWeaponsetChanged(NetconnPtr conn, WeaponsetCallback callback, Pointer context); - void flib_netconn_onServerVar(NetconnPtr conn, StrStrCallback callback, Pointer context); - - // ipc/gameconn.h - - GameconnPtr flib_gameconn_create(String playerName, GameSetupPtr setup, boolean netgame); - GameconnPtr flib_gameconn_create_playdemo(ByteArrayPtr demo, NativeSizeT size); - GameconnPtr flib_gameconn_create_loadgame(String playerName, ByteArrayPtr save, NativeSizeT size); - GameconnPtr flib_gameconn_create_campaign(String playerName, String seed, String script); - - void flib_gameconn_destroy(GameconnPtr conn); - int flib_gameconn_getport(GameconnPtr conn); - void flib_gameconn_tick(GameconnPtr conn); - - int flib_gameconn_send_enginemsg(GameconnPtr conn, ByteArrayPtr data, NativeSizeT len); - int flib_gameconn_send_textmsg(GameconnPtr conn, int msgtype, String msg); - int flib_gameconn_send_chatmsg(GameconnPtr conn, String playername, String msg); - int flib_gameconn_send_quit(GameconnPtr conn); - int flib_gameconn_send_cmd(GameconnPtr conn, String cmdString); - - void flib_gameconn_onConnect(GameconnPtr conn, VoidCallback callback, Pointer context); - void flib_gameconn_onDisconnect(GameconnPtr conn, IntCallback callback, Pointer context); - void flib_gameconn_onErrorMessage(GameconnPtr conn, StrCallback callback, Pointer context); - void flib_gameconn_onChat(GameconnPtr conn, StrBoolCallback callback, Pointer context); - void flib_gameconn_onGameRecorded(GameconnPtr conn, BytesBoolCallback callback, Pointer context); - void flib_gameconn_onEngineMessage(GameconnPtr conn, BytesCallback callback, Pointer context); - - // ipc/mapconn.h - MapconnPtr flib_mapconn_create(MapRecipePtr mapdesc); - void flib_mapconn_destroy(MapconnPtr conn); - int flib_mapconn_getport(MapconnPtr conn); - void flib_mapconn_onSuccess(MapconnPtr conn, MapimageCallback callback, Pointer context); - void flib_mapconn_onFailure(MapconnPtr conn, StrCallback callback, Pointer context); - void flib_mapconn_tick(MapconnPtr conn); - - // model/schemelist.h - SchemelistPtr flib_schemelist_from_ini(String filename); - int flib_schemelist_to_ini(String filename, SchemelistPtr list); - void flib_schemelist_destroy(SchemelistPtr list); - - // model/team.h - TeamPtr flib_team_from_ini(String filename); - int flib_team_to_ini(String filename, TeamPtr team); - void flib_team_destroy(TeamPtr team); - - // model/weapon.h - WeaponsetListPtr flib_weaponsetlist_from_ini(String filename); - int flib_weaponsetlist_to_ini(String filename, WeaponsetListPtr weaponsets); - void flib_weaponsetlist_destroy(WeaponsetListPtr list); - - // model/gamesetup.h - void flib_gamesetup_destroy(GameSetupPtr gamesetup); - - // util/logging.h - void flib_log_setLevel(int level); - void flib_log_setCallback(LogCallback callback); +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* + * This file is not directly part of the frontlib and is not required to build it. + * However, it is recommended to include it in compilation when building for Android. The purpose of this file + * is to ensure consistency between the function signatures of the JNA Java bindings of the Android port and the + * frontlib functions. + * + * This file, in essence, consists only of function declarations. They are duplicates of function declarations + * from the frontlib headers that are referenced from JNA bindings. If the signature of one of these functions + * changes in the frontlib, it will no longer match the signature in this file, and the compiler will show an error. + * If that happens, you need to update the JNA bindings in Hedgeroid to match the new function signature, and then + * update this file. + * + * The reason for all this is that JNA does not actually know the function signatures of the functions it binds, + * it derives them from Java method declarations. If those do not match the actual function signatures, you will + * only notice when you suddenly get strange (and possibly hard to track down) problems at runtime. This file is + * an attempt to detect these problems at compile time instead. Notice that it will NOT detect changes to structs + * or constants though, which also require updates to the JNA bindings. + */ + +/* + * Before we include the frontlib headers, we define away the const keyword. This is necessary because there is no + * distinction between const and non-const types on the JNA side, and we don't want the compiler to complain because + * of bad constness. + * + * This is so evil, but it works... + */ +#define const + +#include "../frontlib.h" + +/* + * Now we map the Java types to the corresponding C types... + */ +typedef flib_netconn *NetconnPtr; +typedef flib_gameconn *GameconnPtr; +typedef flib_mapconn *MapconnPtr; +typedef flib_metascheme *MetaschemePtr; +typedef flib_room **RoomArrayPtr; +typedef flib_weaponset *WeaponsetPtr; +typedef flib_weaponsetlist *WeaponsetListPtr; +typedef flib_map *MapRecipePtr; +typedef flib_scheme *SchemePtr; +typedef flib_schemelist *SchemelistPtr; + +typedef flib_room *RoomPtr; +typedef flib_team *TeamPtr; +typedef flib_gamesetup *GameSetupPtr; +typedef bool boolean; +typedef size_t NativeSizeT; +typedef void *Pointer; +typedef uint8_t *ByteArrayPtr; +typedef char *String; + +/* + * Mapping callback types + */ +typedef void (*VoidCallback)(Pointer context); +typedef void (*StrCallback)(Pointer context, String arg1); +typedef void (*IntCallback)(Pointer context, int arg1); +typedef void (*IntStrCallback)(Pointer context, int arg1, String arg2); +typedef void (*StrIntCallback)(Pointer context, String arg1, int arg2); +typedef void (*StrStrCallback)(Pointer context, String arg1, String arg2); +typedef void (*StrStrBoolCallback)(Pointer context, String arg1, String arg2, boolean arg3); +typedef void (*RoomCallback)(Pointer context, RoomPtr arg1); +typedef void (*RoomListCallback)(Pointer context, RoomArrayPtr arg1, int arg2); +typedef void (*StrRoomCallback)(Pointer context, String arg1, RoomPtr arg2); +typedef void (*BoolCallback)(Pointer context, boolean arg1); +typedef void (*StrBoolCallback)(Pointer context, String arg1, boolean arg2); +typedef void (*TeamCallback)(Pointer context, TeamPtr arg1); +typedef void (*BytesCallback)(Pointer context, const uint8_t *buffer, NativeSizeT size); +typedef void (*BytesBoolCallback)(Pointer context, const uint8_t *buffer, NativeSizeT size, boolean arg3); +typedef void (*SchemeCallback)(Pointer context, SchemePtr arg1); +typedef void (*MapIntCallback)(Pointer context, MapRecipePtr arg1, int arg2); +typedef void (*WeaponsetCallback)(Pointer context, WeaponsetPtr arg1); +typedef void (*MapimageCallback)(Pointer context, const uint8_t *mapimage, int hogs); +typedef void (*LogCallback)(int arg1, String arg2); + +/* + * Below here are the copypasted method declarations from the JNA bindings + */ + + // frontlib.h + int flib_init(); + void flib_quit(); + + // hwconsts.h + int flib_get_teamcolor_count(); + int flib_get_hedgehogs_per_team(); + int flib_get_weapons_count(); + MetaschemePtr flib_get_metascheme(); + + // net/netconn.h + NetconnPtr flib_netconn_create(String playerName, String dataDirPath, String host, int port); + void flib_netconn_destroy(NetconnPtr conn); + + void flib_netconn_tick(NetconnPtr conn); + boolean flib_netconn_is_chief(NetconnPtr conn); + String flib_netconn_get_playername(NetconnPtr conn); + GameSetupPtr flib_netconn_create_gamesetup(NetconnPtr conn); + int flib_netconn_send_quit(NetconnPtr conn, String quitmsg); + int flib_netconn_send_chat(NetconnPtr conn, String chat); + int flib_netconn_send_teamchat(NetconnPtr conn, String msg); + int flib_netconn_send_password(NetconnPtr conn, String passwd); + int flib_netconn_send_nick(NetconnPtr conn, String nick); + int flib_netconn_send_request_roomlist(NetconnPtr conn); + int flib_netconn_send_joinRoom(NetconnPtr conn, String room); + int flib_netconn_send_createRoom(NetconnPtr conn, String room); + int flib_netconn_send_renameRoom(NetconnPtr conn, String roomName); + int flib_netconn_send_leaveRoom(NetconnPtr conn, String msg); + int flib_netconn_send_toggleReady(NetconnPtr conn); + int flib_netconn_send_addTeam(NetconnPtr conn, TeamPtr team); + int flib_netconn_send_removeTeam(NetconnPtr conn, String teamname); + int flib_netconn_send_engineMessage(NetconnPtr conn, ByteArrayPtr message, NativeSizeT size); + int flib_netconn_send_teamHogCount(NetconnPtr conn, String teamname, int hogcount); + int flib_netconn_send_teamColor(NetconnPtr conn, String teamname, int colorIndex); + int flib_netconn_send_weaponset(NetconnPtr conn, WeaponsetPtr weaponset); + int flib_netconn_send_map(NetconnPtr conn, MapRecipePtr map); + int flib_netconn_send_mapName(NetconnPtr conn, String mapName); + int flib_netconn_send_mapGen(NetconnPtr conn, int mapGen); + int flib_netconn_send_mapTemplate(NetconnPtr conn, int templateFilter); + int flib_netconn_send_mapMazeSize(NetconnPtr conn, int mazeSize); + int flib_netconn_send_mapSeed(NetconnPtr conn, String seed); + int flib_netconn_send_mapTheme(NetconnPtr conn, String theme); + int flib_netconn_send_mapDrawdata(NetconnPtr conn, ByteArrayPtr drawData, NativeSizeT size); + int flib_netconn_send_script(NetconnPtr conn, String scriptName); + int flib_netconn_send_scheme(NetconnPtr conn, SchemePtr scheme); + int flib_netconn_send_roundfinished(NetconnPtr conn, boolean withoutError); + int flib_netconn_send_ban(NetconnPtr conn, String playerName); + int flib_netconn_send_kick(NetconnPtr conn, String playerName); + int flib_netconn_send_playerInfo(NetconnPtr conn, String playerName); + int flib_netconn_send_playerFollow(NetconnPtr conn, String playerName); + int flib_netconn_send_startGame(NetconnPtr conn); + int flib_netconn_send_toggleRestrictJoins(NetconnPtr conn); + int flib_netconn_send_toggleRestrictTeams(NetconnPtr conn); + int flib_netconn_send_clearAccountsCache(NetconnPtr conn); + int flib_netconn_send_setServerVar(NetconnPtr conn, String name, String value); + int flib_netconn_send_getServerVars(NetconnPtr conn); + + void flib_netconn_onMessage(NetconnPtr conn, IntStrCallback callback, Pointer context); + void flib_netconn_onClientFlags(NetconnPtr conn, StrStrBoolCallback callback, Pointer context); + void flib_netconn_onChat(NetconnPtr conn, StrStrCallback callback, Pointer context); + void flib_netconn_onConnected(NetconnPtr conn, VoidCallback callback, Pointer context); + void flib_netconn_onDisconnected(NetconnPtr conn, IntStrCallback callback, Pointer context); + void flib_netconn_onRoomlist(NetconnPtr conn, RoomListCallback callback, Pointer context); + void flib_netconn_onRoomAdd(NetconnPtr conn, RoomCallback callback, Pointer context); + void flib_netconn_onRoomDelete(NetconnPtr conn, StrCallback callback, Pointer context); + void flib_netconn_onRoomUpdate(NetconnPtr conn, StrRoomCallback callback, Pointer context); + void flib_netconn_onLobbyJoin(NetconnPtr conn, StrCallback callback, Pointer context); + void flib_netconn_onLobbyLeave(NetconnPtr conn, StrStrCallback callback, Pointer context); + void flib_netconn_onNickTaken(NetconnPtr conn, StrCallback callback, Pointer context); + void flib_netconn_onPasswordRequest(NetconnPtr conn, StrCallback callback, Pointer context); + void flib_netconn_onEnterRoom(NetconnPtr conn, BoolCallback callback, Pointer context); + void flib_netconn_onLeaveRoom(NetconnPtr conn, IntStrCallback callback, Pointer context); + void flib_netconn_onTeamAdd(NetconnPtr conn, TeamCallback callback, Pointer context); + void flib_netconn_onTeamDelete(NetconnPtr conn, StrCallback callback, Pointer context); + void flib_netconn_onRoomJoin(NetconnPtr conn, StrCallback callback, Pointer context); + void flib_netconn_onRoomLeave(NetconnPtr conn, StrStrCallback callback, Pointer context); + void flib_netconn_onRunGame(NetconnPtr conn, VoidCallback callback, Pointer context); + void flib_netconn_onTeamAccepted(NetconnPtr conn, StrCallback callback, Pointer context); + void flib_netconn_onHogCountChanged(NetconnPtr conn, StrIntCallback callback, Pointer context); + void flib_netconn_onTeamColorChanged(NetconnPtr conn, StrIntCallback callback, Pointer context); + void flib_netconn_onEngineMessage(NetconnPtr conn, BytesCallback callback, Pointer context); + void flib_netconn_onSchemeChanged(NetconnPtr conn, SchemeCallback callback, Pointer context); + void flib_netconn_onMapChanged(NetconnPtr conn, MapIntCallback callback, Pointer context); + void flib_netconn_onScriptChanged(NetconnPtr conn, StrCallback callback, Pointer context); + void flib_netconn_onWeaponsetChanged(NetconnPtr conn, WeaponsetCallback callback, Pointer context); + void flib_netconn_onServerVar(NetconnPtr conn, StrStrCallback callback, Pointer context); + + // ipc/gameconn.h + + GameconnPtr flib_gameconn_create(String playerName, GameSetupPtr setup, boolean netgame); + GameconnPtr flib_gameconn_create_playdemo(ByteArrayPtr demo, NativeSizeT size); + GameconnPtr flib_gameconn_create_loadgame(String playerName, ByteArrayPtr save, NativeSizeT size); + GameconnPtr flib_gameconn_create_campaign(String playerName, String seed, String script); + + void flib_gameconn_destroy(GameconnPtr conn); + int flib_gameconn_getport(GameconnPtr conn); + void flib_gameconn_tick(GameconnPtr conn); + + int flib_gameconn_send_enginemsg(GameconnPtr conn, ByteArrayPtr data, NativeSizeT len); + int flib_gameconn_send_textmsg(GameconnPtr conn, int msgtype, String msg); + int flib_gameconn_send_chatmsg(GameconnPtr conn, String playername, String msg); + int flib_gameconn_send_quit(GameconnPtr conn); + int flib_gameconn_send_cmd(GameconnPtr conn, String cmdString); + + void flib_gameconn_onConnect(GameconnPtr conn, VoidCallback callback, Pointer context); + void flib_gameconn_onDisconnect(GameconnPtr conn, IntCallback callback, Pointer context); + void flib_gameconn_onErrorMessage(GameconnPtr conn, StrCallback callback, Pointer context); + void flib_gameconn_onChat(GameconnPtr conn, StrBoolCallback callback, Pointer context); + void flib_gameconn_onGameRecorded(GameconnPtr conn, BytesBoolCallback callback, Pointer context); + void flib_gameconn_onEngineMessage(GameconnPtr conn, BytesCallback callback, Pointer context); + + // ipc/mapconn.h + MapconnPtr flib_mapconn_create(MapRecipePtr mapdesc); + void flib_mapconn_destroy(MapconnPtr conn); + int flib_mapconn_getport(MapconnPtr conn); + void flib_mapconn_onSuccess(MapconnPtr conn, MapimageCallback callback, Pointer context); + void flib_mapconn_onFailure(MapconnPtr conn, StrCallback callback, Pointer context); + void flib_mapconn_tick(MapconnPtr conn); + + // model/schemelist.h + SchemelistPtr flib_schemelist_from_ini(String filename); + int flib_schemelist_to_ini(String filename, SchemelistPtr list); + void flib_schemelist_destroy(SchemelistPtr list); + + // model/team.h + TeamPtr flib_team_from_ini(String filename); + int flib_team_to_ini(String filename, TeamPtr team); + void flib_team_destroy(TeamPtr team); + + // model/weapon.h + WeaponsetListPtr flib_weaponsetlist_from_ini(String filename); + int flib_weaponsetlist_to_ini(String filename, WeaponsetListPtr weaponsets); + void flib_weaponsetlist_destroy(WeaponsetListPtr list); + + // model/gamesetup.h + void flib_gamesetup_destroy(GameSetupPtr gamesetup); + + // util/logging.h + void flib_log_setLevel(int level); + void flib_log_setCallback(LogCallback callback); diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/frontlib.c --- a/project_files/frontlib/frontlib.c Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/frontlib.c Tue Nov 10 20:43:13 2015 +0100 @@ -1,37 +1,37 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "frontlib.h" -#include "util/logging.h" -#include - -int flib_init() { - flib_log_d("Initializing frontlib"); - if(SDLNet_Init()==-1) { - flib_log_e("Error in SDLNet_Init: %s", SDLNet_GetError()); - return -1; - } - - return 0; -} - -void flib_quit() { - flib_log_d("Shutting down frontlib"); - SDLNet_Quit(); -} +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "frontlib.h" +#include "util/logging.h" +#include + +int flib_init() { + flib_log_d("Initializing frontlib"); + if(SDLNet_Init()==-1) { + flib_log_e("Error in SDLNet_Init: %s", SDLNet_GetError()); + return -1; + } + + return 0; +} + +void flib_quit() { + flib_log_d("Shutting down frontlib"); + SDLNet_Quit(); +} diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/frontlib.h --- a/project_files/frontlib/frontlib.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/frontlib.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,48 +1,48 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/* - * Public header file for the hedgewars frontent networking library. - * - * This is the only header you should need to include from frontend code. - */ - -#ifndef FRONTLIB_H_ -#define FRONTLIB_H_ - -#include "ipc/gameconn.h" -#include "ipc/mapconn.h" -#include "net/netconn.h" -#include "util/logging.h" -#include "model/schemelist.h" - -/** - * Call this function before anything else in this library. - * Returns 0 on success, -1 on error. - */ -int flib_init(); - -/** - * Free resources associated with the library. Call this function once - * the library is no longer needed. You can re-initialize the library by calling - * flib_init again. - */ -void flib_quit(); - -#endif /* FRONTLIB_H_ */ +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* + * Public header file for the hedgewars frontent networking library. + * + * This is the only header you should need to include from frontend code. + */ + +#ifndef FRONTLIB_H_ +#define FRONTLIB_H_ + +#include "ipc/gameconn.h" +#include "ipc/mapconn.h" +#include "net/netconn.h" +#include "util/logging.h" +#include "model/schemelist.h" + +/** + * Call this function before anything else in this library. + * Returns 0 on success, -1 on error. + */ +int flib_init(); + +/** + * Free resources associated with the library. Call this function once + * the library is no longer needed. You can re-initialize the library by calling + * flib_init again. + */ +void flib_quit(); + +#endif /* FRONTLIB_H_ */ diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/hwconsts.c --- a/project_files/frontlib/hwconsts.c Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/hwconsts.c Tue Nov 10 20:43:13 2015 +0100 @@ -1,100 +1,100 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "hwconsts.h" - -const uint32_t flib_teamcolors[] = HW_TEAMCOLOR_ARRAY; -const size_t flib_teamcolor_count = sizeof(flib_teamcolors)/sizeof(uint32_t)-1; - -static const flib_metascheme_setting metaSchemeSettings[] = { - { .name = "damagefactor", .times1000 = false, .engineCommand = "e$damagepct", .maxMeansInfinity = false, .min = 10, .max = 300, .def = 100 }, - { .name = "turntime", .times1000 = true, .engineCommand = "e$turntime", .maxMeansInfinity = true, .min = 1, .max = 9999, .def = 45 }, - { .name = "health", .times1000 = false, .engineCommand = NULL, .maxMeansInfinity = false, .min = 50, .max = 200, .def = 100 }, - { .name = "suddendeath", .times1000 = false, .engineCommand = "e$sd_turns", .maxMeansInfinity = true, .min = 0, .max = 50, .def = 15 }, - { .name = "caseprobability", .times1000 = false, .engineCommand = "e$casefreq", .maxMeansInfinity = false, .min = 0, .max = 9, .def = 5 }, - { .name = "minestime", .times1000 = true, .engineCommand = "e$minestime", .maxMeansInfinity = false, .min = -1, .max = 5, .def = 3 }, - { .name = "minesnum", .times1000 = false, .engineCommand = "e$minesnum", .maxMeansInfinity = false, .min = 0, .max = 80, .def = 4 }, - { .name = "minedudpct", .times1000 = false, .engineCommand = "e$minedudpct", .maxMeansInfinity = false, .min = 0, .max = 100, .def = 0 }, - { .name = "explosives", .times1000 = false, .engineCommand = "e$explosives", .maxMeansInfinity = false, .min = 0, .max = 40, .def = 2 }, - { .name = "healthprobability", .times1000 = false, .engineCommand = "e$healthprob", .maxMeansInfinity = false, .min = 0, .max = 100, .def = 35 }, - { .name = "healthcaseamount", .times1000 = false, .engineCommand = "e$hcaseamount", .maxMeansInfinity = false, .min = 0, .max = 200, .def = 25 }, - { .name = "waterrise", .times1000 = false, .engineCommand = "e$waterrise", .maxMeansInfinity = false, .min = 0, .max = 100, .def = 47 }, - { .name = "healthdecrease", .times1000 = false, .engineCommand = "e$healthdec", .maxMeansInfinity = false, .min = 0, .max = 100, .def = 5 }, - { .name = "ropepct", .times1000 = false, .engineCommand = "e$ropepct", .maxMeansInfinity = false, .min = 25, .max = 999, .def = 100 }, - { .name = "getawaytime", .times1000 = false, .engineCommand = "e$getawaytime", .maxMeansInfinity = false, .min = 0, .max = 999, .def = 100 } -}; - -static const flib_metascheme_mod metaSchemeMods[] = { - { .name = "fortsmode", .bitmaskIndex = 12 }, - { .name = "divteams", .bitmaskIndex = 4 }, - { .name = "solidland", .bitmaskIndex = 2 }, - { .name = "border", .bitmaskIndex = 3 }, - { .name = "lowgrav", .bitmaskIndex = 5 }, - { .name = "laser", .bitmaskIndex = 6 }, - { .name = "invulnerability", .bitmaskIndex = 7 }, - { .name = "resethealth", .bitmaskIndex = 8 }, - { .name = "vampiric", .bitmaskIndex = 9 }, - { .name = "karma", .bitmaskIndex = 10 }, - { .name = "artillery", .bitmaskIndex = 11 }, - { .name = "randomorder", .bitmaskIndex = 13 }, - { .name = "king", .bitmaskIndex = 14 }, - { .name = "placehog", .bitmaskIndex = 15 }, - { .name = "sharedammo", .bitmaskIndex = 16 }, - { .name = "disablegirders", .bitmaskIndex = 17 }, - { .name = "disablelandobjects", .bitmaskIndex = 18 }, - { .name = "aisurvival", .bitmaskIndex = 19 }, - { .name = "infattack", .bitmaskIndex = 20 }, - { .name = "resetweps", .bitmaskIndex = 21 }, - { .name = "perhogammo", .bitmaskIndex = 22 }, - { .name = "disablewind", .bitmaskIndex = 23 }, - { .name = "morewind", .bitmaskIndex = 24 }, - { .name = "tagteam", .bitmaskIndex = 25 }, - { .name = "bottomborder", .bitmaskIndex = 26 } -}; - -const flib_metascheme flib_meta = { - .settingCount = sizeof(metaSchemeSettings)/sizeof(flib_metascheme_setting), - .modCount = sizeof(metaSchemeMods)/sizeof(flib_metascheme_mod), - .settings = metaSchemeSettings, - .mods = metaSchemeMods -}; - -uint32_t flib_get_teamcolor(int colorIndex) { - if(colorIndex>=0 && colorIndex < flib_teamcolor_count) { - return flib_teamcolors[colorIndex]; - } else { - return 0; - } -} - -int flib_get_teamcolor_count() { - return flib_teamcolor_count; -} - -int flib_get_hedgehogs_per_team() { - return HEDGEHOGS_PER_TEAM; -} - -int flib_get_weapons_count() { - return WEAPONS_COUNT; -} - -const flib_metascheme *flib_get_metascheme() { - return &flib_meta; -} +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "hwconsts.h" + +const uint32_t flib_teamcolors[] = HW_TEAMCOLOR_ARRAY; +const size_t flib_teamcolor_count = sizeof(flib_teamcolors)/sizeof(uint32_t)-1; + +static const flib_metascheme_setting metaSchemeSettings[] = { + { .name = "damagefactor", .times1000 = false, .engineCommand = "e$damagepct", .maxMeansInfinity = false, .min = 10, .max = 300, .def = 100 }, + { .name = "turntime", .times1000 = true, .engineCommand = "e$turntime", .maxMeansInfinity = true, .min = 1, .max = 9999, .def = 45 }, + { .name = "health", .times1000 = false, .engineCommand = NULL, .maxMeansInfinity = false, .min = 50, .max = 200, .def = 100 }, + { .name = "suddendeath", .times1000 = false, .engineCommand = "e$sd_turns", .maxMeansInfinity = true, .min = 0, .max = 50, .def = 15 }, + { .name = "caseprobability", .times1000 = false, .engineCommand = "e$casefreq", .maxMeansInfinity = false, .min = 0, .max = 9, .def = 5 }, + { .name = "minestime", .times1000 = true, .engineCommand = "e$minestime", .maxMeansInfinity = false, .min = -1, .max = 5, .def = 3 }, + { .name = "minesnum", .times1000 = false, .engineCommand = "e$minesnum", .maxMeansInfinity = false, .min = 0, .max = 80, .def = 4 }, + { .name = "minedudpct", .times1000 = false, .engineCommand = "e$minedudpct", .maxMeansInfinity = false, .min = 0, .max = 100, .def = 0 }, + { .name = "explosives", .times1000 = false, .engineCommand = "e$explosives", .maxMeansInfinity = false, .min = 0, .max = 40, .def = 2 }, + { .name = "healthprobability", .times1000 = false, .engineCommand = "e$healthprob", .maxMeansInfinity = false, .min = 0, .max = 100, .def = 35 }, + { .name = "healthcaseamount", .times1000 = false, .engineCommand = "e$hcaseamount", .maxMeansInfinity = false, .min = 0, .max = 200, .def = 25 }, + { .name = "waterrise", .times1000 = false, .engineCommand = "e$waterrise", .maxMeansInfinity = false, .min = 0, .max = 100, .def = 47 }, + { .name = "healthdecrease", .times1000 = false, .engineCommand = "e$healthdec", .maxMeansInfinity = false, .min = 0, .max = 100, .def = 5 }, + { .name = "ropepct", .times1000 = false, .engineCommand = "e$ropepct", .maxMeansInfinity = false, .min = 25, .max = 999, .def = 100 }, + { .name = "getawaytime", .times1000 = false, .engineCommand = "e$getawaytime", .maxMeansInfinity = false, .min = 0, .max = 999, .def = 100 } +}; + +static const flib_metascheme_mod metaSchemeMods[] = { + { .name = "fortsmode", .bitmaskIndex = 12 }, + { .name = "divteams", .bitmaskIndex = 4 }, + { .name = "solidland", .bitmaskIndex = 2 }, + { .name = "border", .bitmaskIndex = 3 }, + { .name = "lowgrav", .bitmaskIndex = 5 }, + { .name = "laser", .bitmaskIndex = 6 }, + { .name = "invulnerability", .bitmaskIndex = 7 }, + { .name = "resethealth", .bitmaskIndex = 8 }, + { .name = "vampiric", .bitmaskIndex = 9 }, + { .name = "karma", .bitmaskIndex = 10 }, + { .name = "artillery", .bitmaskIndex = 11 }, + { .name = "randomorder", .bitmaskIndex = 13 }, + { .name = "king", .bitmaskIndex = 14 }, + { .name = "placehog", .bitmaskIndex = 15 }, + { .name = "sharedammo", .bitmaskIndex = 16 }, + { .name = "disablegirders", .bitmaskIndex = 17 }, + { .name = "disablelandobjects", .bitmaskIndex = 18 }, + { .name = "aisurvival", .bitmaskIndex = 19 }, + { .name = "infattack", .bitmaskIndex = 20 }, + { .name = "resetweps", .bitmaskIndex = 21 }, + { .name = "perhogammo", .bitmaskIndex = 22 }, + { .name = "disablewind", .bitmaskIndex = 23 }, + { .name = "morewind", .bitmaskIndex = 24 }, + { .name = "tagteam", .bitmaskIndex = 25 }, + { .name = "bottomborder", .bitmaskIndex = 26 } +}; + +const flib_metascheme flib_meta = { + .settingCount = sizeof(metaSchemeSettings)/sizeof(flib_metascheme_setting), + .modCount = sizeof(metaSchemeMods)/sizeof(flib_metascheme_mod), + .settings = metaSchemeSettings, + .mods = metaSchemeMods +}; + +uint32_t flib_get_teamcolor(int colorIndex) { + if(colorIndex>=0 && colorIndex < flib_teamcolor_count) { + return flib_teamcolors[colorIndex]; + } else { + return 0; + } +} + +int flib_get_teamcolor_count() { + return flib_teamcolor_count; +} + +int flib_get_hedgehogs_per_team() { + return HEDGEHOGS_PER_TEAM; +} + +int flib_get_weapons_count() { + return WEAPONS_COUNT; +} + +const flib_metascheme *flib_get_metascheme() { + return &flib_meta; +} diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/hwconsts.h --- a/project_files/frontlib/hwconsts.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/hwconsts.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,118 +1,118 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev - * Copyright (c) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -/** - * This file contains important constants which might need to be changed to adapt to - * changes in the engine or protocols. - * - * It also contains getter functions for some constants (in particular for constants - * that are important for the layout of data structures), so that client code can - * query the constants that the library was built with. - */ - -#ifndef HWCONSTS_H_ -#define HWCONSTS_H_ - -#include -#include -#include - -#define HEDGEHOGS_PER_TEAM 8 -#define DEFAULT_HEDGEHOG_COUNT 4 -#define DEFAULT_COLOR_INDEX 0 - -#define NETGAME_DEFAULT_PORT 46631 -#define PROTOCOL_VERSION 42 -#define MIN_SERVER_VERSION 1 - -//! Used for sending scripts to the engine -#define MULTIPLAYER_SCRIPT_PATH "Scripts/Multiplayer/" - -#define WEAPONS_COUNT 56 - -// TODO allow frontend to override these? -/*! A merge of mikade/bugq colours w/ a bit of channel feedback */ -#define HW_TEAMCOLOR_ARRAY { UINT32_C(0xffff0204), /*! red */ \ - UINT32_C(0xff4980c1), /*! blue */ \ - UINT32_C(0xff1de6ba), /*! teal */ \ - UINT32_C(0xffb541ef), /*! purple */ \ - UINT32_C(0xffe55bb0), /*! pink */ \ - UINT32_C(0xff20bf00), /*! green */ \ - UINT32_C(0xfffe8b0e), /*! orange */ \ - UINT32_C(0xff5f3605), /*! brown */ \ - UINT32_C(0xffffff01), /*! yellow */ \ - /*! add new colors here */ \ - 0 } /*! Keep this 0 at the end */ - -extern const size_t flib_teamcolor_count; -extern const uint32_t flib_teamcolors[]; - -/** - * Returns the team color (ARGB) corresponding to the color index (0 if index out of bounds) - */ -uint32_t flib_get_teamcolor(int colorIndex); - -/** - * Returns the number of team colors (i.e. the length of the flib_teamcolors array) - */ -int flib_get_teamcolor_count(); - -/** - * Returns the HEDGEHOGS_PER_TEAM constant - */ -int flib_get_hedgehogs_per_team(); - -/** - * Returns the WEAPONS_COUNT constant - */ -int flib_get_weapons_count(); - -/*! - * These structs define the meaning of values in the flib_scheme struct, i.e. their correspondence to - * ini settings, engine commands and positions in the network protocol (the last is encoded in the - * order of settings/mods). - */ -typedef struct { - const char *name; //!< A name identifying this setting (used as key in the schemes file) - const char *engineCommand; //!< The command needed to send the setting to the engine. May be null if the setting is not sent to the engine (for the "health" setting) - const bool maxMeansInfinity; //!< If true, send a very high number to the engine if the setting is equal to its maximum - const bool times1000; //!< If true (for time-based settings), multiply the setting by 1000 before sending it to the engine. - const int min; //!< The smallest allowed value - const int max; //!< The highest allowed value - const int def; //!< The default value -} flib_metascheme_setting; - -typedef struct { - const char *name; //!< A name identifying this mod (used as key in the schemes file) - const int bitmaskIndex; //!< Mods are sent to the engine in a single integer, this field describes which bit of that integer is used - //! for this particular mod. -} flib_metascheme_mod; - -typedef struct { - const int settingCount; - const int modCount; - const flib_metascheme_setting *settings; - const flib_metascheme_mod *mods; -} flib_metascheme; - -extern const flib_metascheme flib_meta; - -const flib_metascheme *flib_get_metascheme(); - -#endif +/* + * Hedgewars, a free turn based strategy game + * Copyright (c) 2004-2015 Andrey Korotaev + * Copyright (c) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * This file contains important constants which might need to be changed to adapt to + * changes in the engine or protocols. + * + * It also contains getter functions for some constants (in particular for constants + * that are important for the layout of data structures), so that client code can + * query the constants that the library was built with. + */ + +#ifndef HWCONSTS_H_ +#define HWCONSTS_H_ + +#include +#include +#include + +#define HEDGEHOGS_PER_TEAM 8 +#define DEFAULT_HEDGEHOG_COUNT 4 +#define DEFAULT_COLOR_INDEX 0 + +#define NETGAME_DEFAULT_PORT 46631 +#define PROTOCOL_VERSION 42 +#define MIN_SERVER_VERSION 1 + +//! Used for sending scripts to the engine +#define MULTIPLAYER_SCRIPT_PATH "Scripts/Multiplayer/" + +#define WEAPONS_COUNT 56 + +// TODO allow frontend to override these? +/*! A merge of mikade/bugq colours w/ a bit of channel feedback */ +#define HW_TEAMCOLOR_ARRAY { UINT32_C(0xffff0204), /*! red */ \ + UINT32_C(0xff4980c1), /*! blue */ \ + UINT32_C(0xff1de6ba), /*! teal */ \ + UINT32_C(0xffb541ef), /*! purple */ \ + UINT32_C(0xffe55bb0), /*! pink */ \ + UINT32_C(0xff20bf00), /*! green */ \ + UINT32_C(0xfffe8b0e), /*! orange */ \ + UINT32_C(0xff5f3605), /*! brown */ \ + UINT32_C(0xffffff01), /*! yellow */ \ + /*! add new colors here */ \ + 0 } /*! Keep this 0 at the end */ + +extern const size_t flib_teamcolor_count; +extern const uint32_t flib_teamcolors[]; + +/** + * Returns the team color (ARGB) corresponding to the color index (0 if index out of bounds) + */ +uint32_t flib_get_teamcolor(int colorIndex); + +/** + * Returns the number of team colors (i.e. the length of the flib_teamcolors array) + */ +int flib_get_teamcolor_count(); + +/** + * Returns the HEDGEHOGS_PER_TEAM constant + */ +int flib_get_hedgehogs_per_team(); + +/** + * Returns the WEAPONS_COUNT constant + */ +int flib_get_weapons_count(); + +/*! + * These structs define the meaning of values in the flib_scheme struct, i.e. their correspondence to + * ini settings, engine commands and positions in the network protocol (the last is encoded in the + * order of settings/mods). + */ +typedef struct { + const char *name; //!< A name identifying this setting (used as key in the schemes file) + const char *engineCommand; //!< The command needed to send the setting to the engine. May be null if the setting is not sent to the engine (for the "health" setting) + const bool maxMeansInfinity; //!< If true, send a very high number to the engine if the setting is equal to its maximum + const bool times1000; //!< If true (for time-based settings), multiply the setting by 1000 before sending it to the engine. + const int min; //!< The smallest allowed value + const int max; //!< The highest allowed value + const int def; //!< The default value +} flib_metascheme_setting; + +typedef struct { + const char *name; //!< A name identifying this mod (used as key in the schemes file) + const int bitmaskIndex; //!< Mods are sent to the engine in a single integer, this field describes which bit of that integer is used + //! for this particular mod. +} flib_metascheme_mod; + +typedef struct { + const int settingCount; + const int modCount; + const flib_metascheme_setting *settings; + const flib_metascheme_mod *mods; +} flib_metascheme; + +extern const flib_metascheme flib_meta; + +const flib_metascheme *flib_get_metascheme(); + +#endif diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/iniparser/LICENSE --- a/project_files/frontlib/iniparser/LICENSE Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/iniparser/LICENSE Tue Nov 10 20:43:13 2015 +0100 @@ -1,23 +1,23 @@ -Copyright (c) 2000-2012 by Nicolas Devillard. -MIT License - -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +Copyright (c) 2000-2012 by Nicolas Devillard. +MIT License + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/iniparser/VERSION --- a/project_files/frontlib/iniparser/VERSION Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/iniparser/VERSION Tue Nov 10 20:43:13 2015 +0100 @@ -1,2 +1,2 @@ -This is version 3.1 of the iniparser library developed by N. Devillard. +This is version 3.1 of the iniparser library developed by N. Devillard. See http://ndevilla.free.fr/iniparser/ for details and new versions. \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/iniparser/dictionary.c --- a/project_files/frontlib/iniparser/dictionary.c Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/iniparser/dictionary.c Tue Nov 10 20:43:13 2015 +0100 @@ -38,7 +38,7 @@ static void * mem_double(void * ptr, int size) { void * newptr ; - + newptr = calloc(2*size, 1); if (newptr==NULL) { return NULL ; @@ -224,7 +224,7 @@ unsigned hash ; if (d==NULL || key==NULL) return -1 ; - + /* Compute hash for this key */ hash = dictionary_hash(key) ; /* Find if value is already in dictionary */ @@ -367,7 +367,7 @@ /* Allocate dictionary */ printf("allocating...\n"); d = dictionary_new(0); - + /* Set values in dictionary */ printf("setting %d values...\n", NVALS); for (i=0 ; isize ; j++) { if (d->key[j]==NULL) continue ; - if (!strncmp(d->key[j], keym, seclen+1)) + if (!strncmp(d->key[j], keym, seclen+1)) nkeys++; } @@ -310,7 +310,7 @@ This function queries a dictionary and finds all keys in a given section. Each pointer in the returned char pointer-to-pointer is pointing to a string allocated in the dictionary; do not free or modify them. - + This function returns NULL in case of error. */ /*--------------------------------------------------------------------------*/ @@ -334,7 +334,7 @@ seclen = (int)strlen(s); sprintf(keym, "%s:", s); - + i = 0; for (j=0 ; jsize ; j++) { @@ -557,7 +557,7 @@ char * section, char * key, char * value) -{ +{ line_status sta ; char line[ASCIILINESZ+1]; int len ; @@ -571,7 +571,7 @@ sta = LINE_EMPTY ; } else if (line[0]=='#' || line[0]==';') { /* Comment line */ - sta = LINE_COMMENT ; + sta = LINE_COMMENT ; } else if (line[0]=='[' && line[len-1]==']') { /* Section name */ sscanf(line, "[%[^]]", section); diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/ipc/gameconn.c --- a/project_files/frontlib/ipc/gameconn.c Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/ipc/gameconn.c Tue Nov 10 20:43:13 2015 +0100 @@ -1,452 +1,452 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "gameconn.h" -#include "ipcbase.h" -#include "ipcprotocol.h" -#include "../util/logging.h" -#include "../util/util.h" -#include "../hwconsts.h" -#include -#include -#include - -typedef enum { - AWAIT_CONNECTION, - CONNECTED, - FINISHED -} gameconn_state; - -struct _flib_gameconn { - flib_ipcbase *ipcBase; - flib_vector *configBuffer; - flib_vector *demoBuffer; - char *playerName; - - gameconn_state state; - bool netgame; - int disconnectReason; - - void (*onConnectCb)(void* context); - void *onConnectCtx; - - void (*onDisconnectCb)(void* context, int reason); - void *onDisconnectCtx; - - void (*onErrorMessageCb)(void* context, const char *msg); - void *onErrorMessageCtx; - - void (*onChatCb)(void* context, const char *msg, bool teamchat); - void *onChatCtx; - - void (*onGameRecordedCb)(void *context, const uint8_t *record, size_t size, bool isSavegame); - void *onGameRecordedCtx; - - void (*onEngineMessageCb)(void *context, const uint8_t *em, size_t size); - void *onEngineMessageCtx; - - bool running; - bool destroyRequested; -}; - -static void defaultCallback_onErrorMessage(void* context, const char *msg) { - flib_log_w("Error from engine (no callback set): %s", msg); -} - -static void clearCallbacks(flib_gameconn *conn) { - flib_gameconn_onConnect(conn, NULL, NULL); - flib_gameconn_onDisconnect(conn, NULL, NULL); - flib_gameconn_onErrorMessage(conn, NULL, NULL); - flib_gameconn_onChat(conn, NULL, NULL); - flib_gameconn_onGameRecorded(conn, NULL, NULL); - flib_gameconn_onEngineMessage(conn, NULL, NULL); -} - -static flib_gameconn *flib_gameconn_create_partial(bool record, const char *playerName, bool netGame) { - flib_gameconn *result = NULL; - flib_gameconn *tempConn = flib_calloc(1, sizeof(flib_gameconn)); - if(tempConn) { - tempConn->ipcBase = flib_ipcbase_create(); - tempConn->configBuffer = flib_vector_create(); - tempConn->playerName = flib_strdupnull(playerName); - if(tempConn->ipcBase && tempConn->configBuffer && tempConn->playerName) { - if(record) { - tempConn->demoBuffer = flib_vector_create(); - } - tempConn->state = AWAIT_CONNECTION; - tempConn->netgame = netGame; - tempConn->disconnectReason = GAME_END_ERROR; - clearCallbacks(tempConn); - result = tempConn; - tempConn = NULL; - } - } - flib_gameconn_destroy(tempConn); - return result; -} - -flib_gameconn *flib_gameconn_create(const char *playerName, const flib_gamesetup *setup, bool netgame) { - if(log_badargs_if2(playerName==NULL, setup==NULL)) { - return NULL; - } - flib_gameconn *result = NULL; - flib_gameconn *tempConn = flib_gameconn_create_partial(true, playerName, netgame); - if(tempConn) { - if(flib_ipc_append_fullconfig(tempConn->configBuffer, setup, netgame)) { - flib_log_e("Error generating full game configuration for the engine."); - } else { - result = tempConn; - tempConn = NULL; - } - } - flib_gameconn_destroy(tempConn); - return result; -} - -flib_gameconn *flib_gameconn_create_playdemo(const uint8_t *demoFileContent, size_t size) { - if(log_badargs_if(demoFileContent==NULL && size>0)) { - return NULL; - } - flib_gameconn *result = NULL; - flib_gameconn *tempConn = flib_gameconn_create_partial(false, "Player", false); - if(tempConn) { - if(!flib_vector_append(tempConn->configBuffer, demoFileContent, size)) { - result = tempConn; - tempConn = NULL; - } - } - flib_gameconn_destroy(tempConn); - return result; -} - -flib_gameconn *flib_gameconn_create_loadgame(const char *playerName, const uint8_t *saveFileContent, size_t size) { - if(log_badargs_if(saveFileContent==NULL && size>0)) { - return NULL; - } - flib_gameconn *result = NULL; - flib_gameconn *tempConn = flib_gameconn_create_partial(true, playerName, false); - if(tempConn) { - if(!flib_vector_append(tempConn->configBuffer, saveFileContent, size)) { - result = tempConn; - tempConn = NULL; - } - } - flib_gameconn_destroy(tempConn); - return result; -} - -flib_gameconn *flib_gameconn_create_campaign(const char *playerName, const char *seed, const char *script) { - if(log_badargs_if3(playerName==NULL, seed==NULL, script==NULL)) { - return NULL; - } - flib_gameconn *result = NULL; - flib_gameconn *tempConn = flib_gameconn_create_partial(true, playerName, false); - if(tempConn) { - if(!flib_ipc_append_message(tempConn->configBuffer, "TL") - && !flib_ipc_append_seed(tempConn->configBuffer, seed) - && !flib_ipc_append_script(tempConn->configBuffer, script) - && !flib_ipc_append_message(tempConn->configBuffer, "!")) { - result = tempConn; - tempConn = NULL; - } - } - flib_gameconn_destroy(tempConn); - return result; -} - -void flib_gameconn_destroy(flib_gameconn *conn) { - if(conn) { - if(conn->running) { - /* - * The function was called from a callback, so the tick function is still running - * and we delay the actual destruction. We ensure no further callbacks will be - * sent to prevent surprises. - */ - clearCallbacks(conn); - conn->destroyRequested = true; - } else { - flib_ipcbase_destroy(conn->ipcBase); - flib_vector_destroy(conn->configBuffer); - flib_vector_destroy(conn->demoBuffer); - free(conn->playerName); - free(conn); - } - } -} - -int flib_gameconn_getport(flib_gameconn *conn) { - if(log_badargs_if(conn==NULL)) { - return 0; - } - return flib_ipcbase_port(conn->ipcBase); -} - -static void demo_append(flib_gameconn *conn, const void *data, size_t len) { - if(conn->demoBuffer) { - if(flib_vector_append(conn->demoBuffer, data, len)) { - flib_log_e("Error recording demo: Out of memory."); - flib_vector_destroy(conn->demoBuffer); - conn->demoBuffer = NULL; - } - } -} - -static int format_chatmessage(uint8_t buffer[257], const char *playerName, const char *message) { - size_t msglen = strlen(message); - - // If the message starts with /me, it will be displayed differently. - bool meMessage = msglen >= 4 && !memcmp(message, "/me ", 4); - const char *template = meMessage ? "s\x02* %s %s " : "s\x01%s: %s "; - int size = snprintf((char*)buffer+1, 256, template, playerName, meMessage ? message+4 : message); - if(log_e_if(size<=0, "printf error")) { - return -1; - } else { - buffer[0] = size>255 ? 255 : size; - return 0; - } -} - -static void demo_append_chatmessage(flib_gameconn *conn, const char *message) { - // Chat messages are reformatted to make them look as if they were received, not sent. - uint8_t converted[257]; - if(!format_chatmessage(converted, conn->playerName, message)) { - demo_append(conn, converted, converted[0]+1); - } -} - -static void demo_replace_gamemode(flib_buffer buf, char gamemode) { - size_t msgStart = 0; - uint8_t *data = (uint8_t*)buf.data; - while(msgStart+2 < buf.size) { - if(!memcmp(data+msgStart, "\x02T", 2)) { - data[msgStart+2] = gamemode; - } - msgStart += (uint8_t)data[msgStart]+1; - } -} - -int flib_gameconn_send_enginemsg(flib_gameconn *conn, const uint8_t *data, size_t len) { - if(log_badargs_if2(conn==NULL, data==NULL && len>0)) { - return -1; - } - int result = flib_ipcbase_send_raw(conn->ipcBase, data, len); - if(!result) { - demo_append(conn, data, len); - } - return result; -} - -int flib_gameconn_send_textmsg(flib_gameconn *conn, int msgtype, const char *msg) { - if(log_badargs_if2(conn==NULL, msg==NULL)) { - return -1; - } - int result = -1; - uint8_t converted[257]; - int size = snprintf((char*)converted+1, 256, "s%c%s", (char)msgtype, msg); - if(size>0) { - converted[0] = size>255 ? 255 : size; - if(!flib_ipcbase_send_raw(conn->ipcBase, converted, converted[0]+1)) { - demo_append(conn, converted, converted[0]+1); - result = 0; - } - } - return result; -} - -int flib_gameconn_send_chatmsg(flib_gameconn *conn, const char *playername, const char *msg) { - if(log_badargs_if3(conn==NULL, playername==NULL, msg==NULL)) { - return -1; - } - uint8_t converted[257]; - if(!format_chatmessage(converted, playername, msg) - && !flib_ipcbase_send_raw(conn->ipcBase, converted, converted[0]+1)) { - demo_append(conn, converted, converted[0]+1); - return 0; - } - return -1; -} - -int flib_gameconn_send_quit(flib_gameconn *conn) { - return flib_gameconn_send_cmd(conn, "efinish"); -} - -int flib_gameconn_send_cmd(flib_gameconn *conn, const char *cmdString) { - if(log_badargs_if2(conn==NULL, cmdString==NULL)) { - return -1; - } - int result = -1; - uint8_t converted[256]; - size_t msglen = strlen(cmdString); - if(!log_e_if(msglen>255, "Message too long: %s", cmdString)) { - strcpy((char*)converted+1, cmdString); - converted[0] = msglen; - if(!flib_ipcbase_send_raw(conn->ipcBase, converted, msglen+1)) { - demo_append(conn, converted, msglen+1); - result = 0; - } - } - return result; -} - -/** - * This macro generates a callback setter function. It uses the name of the callback to - * automatically generate the function name and the fields to set, so a consistent naming - * convention needs to be enforced (not that that is a bad thing). If null is passed as - * callback to the generated function, the defaultCb will be set instead (with conn - * as the context). - */ -#define GENERATE_CB_SETTER(cbName, cbParameterTypes, defaultCb) \ - void flib_gameconn_##cbName(flib_gameconn *conn, void (*callback)cbParameterTypes, void *context) { \ - if(!log_badargs_if(conn==NULL)) { \ - conn->cbName##Cb = callback ? callback : &defaultCb; \ - conn->cbName##Ctx = callback ? context : conn; \ - } \ - } - -/** - * Generate a callback setter function like GENERATE_CB_SETTER, and automatically generate a - * no-op callback function as well that is used as default. - */ -#define GENERATE_CB_SETTER_AND_DEFAULT(cbName, cbParameterTypes) \ - static void _noop_callback_##cbName cbParameterTypes {} \ - GENERATE_CB_SETTER(cbName, cbParameterTypes, _noop_callback_##cbName) - -GENERATE_CB_SETTER_AND_DEFAULT(onConnect, (void *context)); -GENERATE_CB_SETTER_AND_DEFAULT(onDisconnect, (void* context, int reason)); -GENERATE_CB_SETTER(onErrorMessage, (void* context, const char *msg), defaultCallback_onErrorMessage); -GENERATE_CB_SETTER_AND_DEFAULT(onChat, (void* context, const char *msg, bool teamchat)); -GENERATE_CB_SETTER_AND_DEFAULT(onGameRecorded, (void *context, const uint8_t *record, size_t size, bool isSavegame)); -GENERATE_CB_SETTER_AND_DEFAULT(onEngineMessage, (void *context, const uint8_t *em, size_t size)); - -#undef GENERATE_CB_SETTER_AND_DEFAULT -#undef GENERATE_CB_SETTER - -static void flib_gameconn_wrappedtick(flib_gameconn *conn) { - if(conn->state == AWAIT_CONNECTION) { - flib_ipcbase_accept(conn->ipcBase); - switch(flib_ipcbase_state(conn->ipcBase)) { - case IPC_CONNECTED: - { - flib_constbuffer configBuffer = flib_vector_as_constbuffer(conn->configBuffer); - if(flib_ipcbase_send_raw(conn->ipcBase, configBuffer.data, configBuffer.size)) { - conn->state = FINISHED; - conn->onDisconnectCb(conn->onDisconnectCtx, GAME_END_ERROR); - return; - } else { - demo_append(conn, configBuffer.data, configBuffer.size); - conn->state = CONNECTED; - conn->onConnectCb(conn->onConnectCtx); - if(conn->destroyRequested) { - return; - } - } - } - break; - case IPC_NOT_CONNECTED: - conn->state = FINISHED; - conn->onDisconnectCb(conn->onDisconnectCtx, GAME_END_ERROR); - return; - default: - break; - } - } - - if(conn->state == CONNECTED) { - uint8_t msgbuffer[257]; - int len; - while(!conn->destroyRequested && (len = flib_ipcbase_recv_message(conn->ipcBase, msgbuffer))>=0) { - if(len<2) { - flib_log_w("Received short message from IPC (<2 bytes)"); - continue; - } - switch(msgbuffer[1]) { - case '?': // Ping - // The pong is already part of the config message - break; - case 'C': // Config query - // And we already send the config message on connecting. - break; - case 'E': // Error message - if(len>=3) { - msgbuffer[len-2] = 0; - conn->onErrorMessageCb(conn->onErrorMessageCtx, (char*)msgbuffer+2); - } - break; - case 'i': // Statistics - // TODO stats - break; - case 'Q': // Game interrupted - case 'H': // Game halted - case 'q': // game finished - { - int reason = msgbuffer[1]=='Q' ? GAME_END_INTERRUPTED : msgbuffer[1]=='H' ? GAME_END_HALTED : GAME_END_FINISHED; - conn->disconnectReason = reason; - bool savegame = (reason != GAME_END_FINISHED) && !conn->netgame; - if(conn->demoBuffer) { - flib_buffer demoBuffer = flib_vector_as_buffer(conn->demoBuffer); - demo_replace_gamemode(demoBuffer, savegame ? 'S' : 'D'); - conn->onGameRecordedCb(conn->onGameRecordedCtx, demoBuffer.data, demoBuffer.size, savegame); - if(conn->destroyRequested) { - return; - } - } - return; - } - case 's': // Chat message - if(len>=3) { - msgbuffer[len-2] = 0; - demo_append_chatmessage(conn, (char*)msgbuffer+2); - - conn->onChatCb(conn->onChatCtx, (char*)msgbuffer+2, false); - } - break; - case 'b': // Teamchat message - if(len>=3) { - msgbuffer[len-2] = 0; - conn->onChatCb(conn->onChatCtx, (char*)msgbuffer+2, true); - } - break; - default: // Engine message - demo_append(conn, msgbuffer, len); - - conn->onEngineMessageCb(conn->onEngineMessageCtx, msgbuffer, len); - break; - } - } - } - - if(flib_ipcbase_state(conn->ipcBase) == IPC_NOT_CONNECTED) { - conn->state = FINISHED; - conn->onDisconnectCb(conn->onDisconnectCtx, conn->disconnectReason); - } -} - -void flib_gameconn_tick(flib_gameconn *conn) { - if(!log_badargs_if(conn == NULL) - && !log_w_if(conn->running, "Call to flib_gameconn_tick from a callback") - && !log_w_if(conn->state == FINISHED, "We are already done.")) { - conn->running = true; - flib_gameconn_wrappedtick(conn); - conn->running = false; - - if(conn->destroyRequested) { - flib_gameconn_destroy(conn); - } - } -} +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "gameconn.h" +#include "ipcbase.h" +#include "ipcprotocol.h" +#include "../util/logging.h" +#include "../util/util.h" +#include "../hwconsts.h" +#include +#include +#include + +typedef enum { + AWAIT_CONNECTION, + CONNECTED, + FINISHED +} gameconn_state; + +struct _flib_gameconn { + flib_ipcbase *ipcBase; + flib_vector *configBuffer; + flib_vector *demoBuffer; + char *playerName; + + gameconn_state state; + bool netgame; + int disconnectReason; + + void (*onConnectCb)(void* context); + void *onConnectCtx; + + void (*onDisconnectCb)(void* context, int reason); + void *onDisconnectCtx; + + void (*onErrorMessageCb)(void* context, const char *msg); + void *onErrorMessageCtx; + + void (*onChatCb)(void* context, const char *msg, bool teamchat); + void *onChatCtx; + + void (*onGameRecordedCb)(void *context, const uint8_t *record, size_t size, bool isSavegame); + void *onGameRecordedCtx; + + void (*onEngineMessageCb)(void *context, const uint8_t *em, size_t size); + void *onEngineMessageCtx; + + bool running; + bool destroyRequested; +}; + +static void defaultCallback_onErrorMessage(void* context, const char *msg) { + flib_log_w("Error from engine (no callback set): %s", msg); +} + +static void clearCallbacks(flib_gameconn *conn) { + flib_gameconn_onConnect(conn, NULL, NULL); + flib_gameconn_onDisconnect(conn, NULL, NULL); + flib_gameconn_onErrorMessage(conn, NULL, NULL); + flib_gameconn_onChat(conn, NULL, NULL); + flib_gameconn_onGameRecorded(conn, NULL, NULL); + flib_gameconn_onEngineMessage(conn, NULL, NULL); +} + +static flib_gameconn *flib_gameconn_create_partial(bool record, const char *playerName, bool netGame) { + flib_gameconn *result = NULL; + flib_gameconn *tempConn = flib_calloc(1, sizeof(flib_gameconn)); + if(tempConn) { + tempConn->ipcBase = flib_ipcbase_create(); + tempConn->configBuffer = flib_vector_create(); + tempConn->playerName = flib_strdupnull(playerName); + if(tempConn->ipcBase && tempConn->configBuffer && tempConn->playerName) { + if(record) { + tempConn->demoBuffer = flib_vector_create(); + } + tempConn->state = AWAIT_CONNECTION; + tempConn->netgame = netGame; + tempConn->disconnectReason = GAME_END_ERROR; + clearCallbacks(tempConn); + result = tempConn; + tempConn = NULL; + } + } + flib_gameconn_destroy(tempConn); + return result; +} + +flib_gameconn *flib_gameconn_create(const char *playerName, const flib_gamesetup *setup, bool netgame) { + if(log_badargs_if2(playerName==NULL, setup==NULL)) { + return NULL; + } + flib_gameconn *result = NULL; + flib_gameconn *tempConn = flib_gameconn_create_partial(true, playerName, netgame); + if(tempConn) { + if(flib_ipc_append_fullconfig(tempConn->configBuffer, setup, netgame)) { + flib_log_e("Error generating full game configuration for the engine."); + } else { + result = tempConn; + tempConn = NULL; + } + } + flib_gameconn_destroy(tempConn); + return result; +} + +flib_gameconn *flib_gameconn_create_playdemo(const uint8_t *demoFileContent, size_t size) { + if(log_badargs_if(demoFileContent==NULL && size>0)) { + return NULL; + } + flib_gameconn *result = NULL; + flib_gameconn *tempConn = flib_gameconn_create_partial(false, "Player", false); + if(tempConn) { + if(!flib_vector_append(tempConn->configBuffer, demoFileContent, size)) { + result = tempConn; + tempConn = NULL; + } + } + flib_gameconn_destroy(tempConn); + return result; +} + +flib_gameconn *flib_gameconn_create_loadgame(const char *playerName, const uint8_t *saveFileContent, size_t size) { + if(log_badargs_if(saveFileContent==NULL && size>0)) { + return NULL; + } + flib_gameconn *result = NULL; + flib_gameconn *tempConn = flib_gameconn_create_partial(true, playerName, false); + if(tempConn) { + if(!flib_vector_append(tempConn->configBuffer, saveFileContent, size)) { + result = tempConn; + tempConn = NULL; + } + } + flib_gameconn_destroy(tempConn); + return result; +} + +flib_gameconn *flib_gameconn_create_campaign(const char *playerName, const char *seed, const char *script) { + if(log_badargs_if3(playerName==NULL, seed==NULL, script==NULL)) { + return NULL; + } + flib_gameconn *result = NULL; + flib_gameconn *tempConn = flib_gameconn_create_partial(true, playerName, false); + if(tempConn) { + if(!flib_ipc_append_message(tempConn->configBuffer, "TL") + && !flib_ipc_append_seed(tempConn->configBuffer, seed) + && !flib_ipc_append_script(tempConn->configBuffer, script) + && !flib_ipc_append_message(tempConn->configBuffer, "!")) { + result = tempConn; + tempConn = NULL; + } + } + flib_gameconn_destroy(tempConn); + return result; +} + +void flib_gameconn_destroy(flib_gameconn *conn) { + if(conn) { + if(conn->running) { + /* + * The function was called from a callback, so the tick function is still running + * and we delay the actual destruction. We ensure no further callbacks will be + * sent to prevent surprises. + */ + clearCallbacks(conn); + conn->destroyRequested = true; + } else { + flib_ipcbase_destroy(conn->ipcBase); + flib_vector_destroy(conn->configBuffer); + flib_vector_destroy(conn->demoBuffer); + free(conn->playerName); + free(conn); + } + } +} + +int flib_gameconn_getport(flib_gameconn *conn) { + if(log_badargs_if(conn==NULL)) { + return 0; + } + return flib_ipcbase_port(conn->ipcBase); +} + +static void demo_append(flib_gameconn *conn, const void *data, size_t len) { + if(conn->demoBuffer) { + if(flib_vector_append(conn->demoBuffer, data, len)) { + flib_log_e("Error recording demo: Out of memory."); + flib_vector_destroy(conn->demoBuffer); + conn->demoBuffer = NULL; + } + } +} + +static int format_chatmessage(uint8_t buffer[257], const char *playerName, const char *message) { + size_t msglen = strlen(message); + + // If the message starts with /me, it will be displayed differently. + bool meMessage = msglen >= 4 && !memcmp(message, "/me ", 4); + const char *template = meMessage ? "s\x02* %s %s " : "s\x01%s: %s "; + int size = snprintf((char*)buffer+1, 256, template, playerName, meMessage ? message+4 : message); + if(log_e_if(size<=0, "printf error")) { + return -1; + } else { + buffer[0] = size>255 ? 255 : size; + return 0; + } +} + +static void demo_append_chatmessage(flib_gameconn *conn, const char *message) { + // Chat messages are reformatted to make them look as if they were received, not sent. + uint8_t converted[257]; + if(!format_chatmessage(converted, conn->playerName, message)) { + demo_append(conn, converted, converted[0]+1); + } +} + +static void demo_replace_gamemode(flib_buffer buf, char gamemode) { + size_t msgStart = 0; + uint8_t *data = (uint8_t*)buf.data; + while(msgStart+2 < buf.size) { + if(!memcmp(data+msgStart, "\x02T", 2)) { + data[msgStart+2] = gamemode; + } + msgStart += (uint8_t)data[msgStart]+1; + } +} + +int flib_gameconn_send_enginemsg(flib_gameconn *conn, const uint8_t *data, size_t len) { + if(log_badargs_if2(conn==NULL, data==NULL && len>0)) { + return -1; + } + int result = flib_ipcbase_send_raw(conn->ipcBase, data, len); + if(!result) { + demo_append(conn, data, len); + } + return result; +} + +int flib_gameconn_send_textmsg(flib_gameconn *conn, int msgtype, const char *msg) { + if(log_badargs_if2(conn==NULL, msg==NULL)) { + return -1; + } + int result = -1; + uint8_t converted[257]; + int size = snprintf((char*)converted+1, 256, "s%c%s", (char)msgtype, msg); + if(size>0) { + converted[0] = size>255 ? 255 : size; + if(!flib_ipcbase_send_raw(conn->ipcBase, converted, converted[0]+1)) { + demo_append(conn, converted, converted[0]+1); + result = 0; + } + } + return result; +} + +int flib_gameconn_send_chatmsg(flib_gameconn *conn, const char *playername, const char *msg) { + if(log_badargs_if3(conn==NULL, playername==NULL, msg==NULL)) { + return -1; + } + uint8_t converted[257]; + if(!format_chatmessage(converted, playername, msg) + && !flib_ipcbase_send_raw(conn->ipcBase, converted, converted[0]+1)) { + demo_append(conn, converted, converted[0]+1); + return 0; + } + return -1; +} + +int flib_gameconn_send_quit(flib_gameconn *conn) { + return flib_gameconn_send_cmd(conn, "efinish"); +} + +int flib_gameconn_send_cmd(flib_gameconn *conn, const char *cmdString) { + if(log_badargs_if2(conn==NULL, cmdString==NULL)) { + return -1; + } + int result = -1; + uint8_t converted[256]; + size_t msglen = strlen(cmdString); + if(!log_e_if(msglen>255, "Message too long: %s", cmdString)) { + strcpy((char*)converted+1, cmdString); + converted[0] = msglen; + if(!flib_ipcbase_send_raw(conn->ipcBase, converted, msglen+1)) { + demo_append(conn, converted, msglen+1); + result = 0; + } + } + return result; +} + +/** + * This macro generates a callback setter function. It uses the name of the callback to + * automatically generate the function name and the fields to set, so a consistent naming + * convention needs to be enforced (not that that is a bad thing). If null is passed as + * callback to the generated function, the defaultCb will be set instead (with conn + * as the context). + */ +#define GENERATE_CB_SETTER(cbName, cbParameterTypes, defaultCb) \ + void flib_gameconn_##cbName(flib_gameconn *conn, void (*callback)cbParameterTypes, void *context) { \ + if(!log_badargs_if(conn==NULL)) { \ + conn->cbName##Cb = callback ? callback : &defaultCb; \ + conn->cbName##Ctx = callback ? context : conn; \ + } \ + } + +/** + * Generate a callback setter function like GENERATE_CB_SETTER, and automatically generate a + * no-op callback function as well that is used as default. + */ +#define GENERATE_CB_SETTER_AND_DEFAULT(cbName, cbParameterTypes) \ + static void _noop_callback_##cbName cbParameterTypes {} \ + GENERATE_CB_SETTER(cbName, cbParameterTypes, _noop_callback_##cbName) + +GENERATE_CB_SETTER_AND_DEFAULT(onConnect, (void *context)); +GENERATE_CB_SETTER_AND_DEFAULT(onDisconnect, (void* context, int reason)); +GENERATE_CB_SETTER(onErrorMessage, (void* context, const char *msg), defaultCallback_onErrorMessage); +GENERATE_CB_SETTER_AND_DEFAULT(onChat, (void* context, const char *msg, bool teamchat)); +GENERATE_CB_SETTER_AND_DEFAULT(onGameRecorded, (void *context, const uint8_t *record, size_t size, bool isSavegame)); +GENERATE_CB_SETTER_AND_DEFAULT(onEngineMessage, (void *context, const uint8_t *em, size_t size)); + +#undef GENERATE_CB_SETTER_AND_DEFAULT +#undef GENERATE_CB_SETTER + +static void flib_gameconn_wrappedtick(flib_gameconn *conn) { + if(conn->state == AWAIT_CONNECTION) { + flib_ipcbase_accept(conn->ipcBase); + switch(flib_ipcbase_state(conn->ipcBase)) { + case IPC_CONNECTED: + { + flib_constbuffer configBuffer = flib_vector_as_constbuffer(conn->configBuffer); + if(flib_ipcbase_send_raw(conn->ipcBase, configBuffer.data, configBuffer.size)) { + conn->state = FINISHED; + conn->onDisconnectCb(conn->onDisconnectCtx, GAME_END_ERROR); + return; + } else { + demo_append(conn, configBuffer.data, configBuffer.size); + conn->state = CONNECTED; + conn->onConnectCb(conn->onConnectCtx); + if(conn->destroyRequested) { + return; + } + } + } + break; + case IPC_NOT_CONNECTED: + conn->state = FINISHED; + conn->onDisconnectCb(conn->onDisconnectCtx, GAME_END_ERROR); + return; + default: + break; + } + } + + if(conn->state == CONNECTED) { + uint8_t msgbuffer[257]; + int len; + while(!conn->destroyRequested && (len = flib_ipcbase_recv_message(conn->ipcBase, msgbuffer))>=0) { + if(len<2) { + flib_log_w("Received short message from IPC (<2 bytes)"); + continue; + } + switch(msgbuffer[1]) { + case '?': // Ping + // The pong is already part of the config message + break; + case 'C': // Config query + // And we already send the config message on connecting. + break; + case 'E': // Error message + if(len>=3) { + msgbuffer[len-2] = 0; + conn->onErrorMessageCb(conn->onErrorMessageCtx, (char*)msgbuffer+2); + } + break; + case 'i': // Statistics + // TODO stats + break; + case 'Q': // Game interrupted + case 'H': // Game halted + case 'q': // game finished + { + int reason = msgbuffer[1]=='Q' ? GAME_END_INTERRUPTED : msgbuffer[1]=='H' ? GAME_END_HALTED : GAME_END_FINISHED; + conn->disconnectReason = reason; + bool savegame = (reason != GAME_END_FINISHED) && !conn->netgame; + if(conn->demoBuffer) { + flib_buffer demoBuffer = flib_vector_as_buffer(conn->demoBuffer); + demo_replace_gamemode(demoBuffer, savegame ? 'S' : 'D'); + conn->onGameRecordedCb(conn->onGameRecordedCtx, demoBuffer.data, demoBuffer.size, savegame); + if(conn->destroyRequested) { + return; + } + } + return; + } + case 's': // Chat message + if(len>=3) { + msgbuffer[len-2] = 0; + demo_append_chatmessage(conn, (char*)msgbuffer+2); + + conn->onChatCb(conn->onChatCtx, (char*)msgbuffer+2, false); + } + break; + case 'b': // Teamchat message + if(len>=3) { + msgbuffer[len-2] = 0; + conn->onChatCb(conn->onChatCtx, (char*)msgbuffer+2, true); + } + break; + default: // Engine message + demo_append(conn, msgbuffer, len); + + conn->onEngineMessageCb(conn->onEngineMessageCtx, msgbuffer, len); + break; + } + } + } + + if(flib_ipcbase_state(conn->ipcBase) == IPC_NOT_CONNECTED) { + conn->state = FINISHED; + conn->onDisconnectCb(conn->onDisconnectCtx, conn->disconnectReason); + } +} + +void flib_gameconn_tick(flib_gameconn *conn) { + if(!log_badargs_if(conn == NULL) + && !log_w_if(conn->running, "Call to flib_gameconn_tick from a callback") + && !log_w_if(conn->state == FINISHED, "We are already done.")) { + conn->running = true; + flib_gameconn_wrappedtick(conn); + conn->running = false; + + if(conn->destroyRequested) { + flib_gameconn_destroy(conn); + } + } +} diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/ipc/gameconn.h --- a/project_files/frontlib/ipc/gameconn.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/ipc/gameconn.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,179 +1,179 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * This file contains functions for starting and interacting with a game run by the engine. - * The general usage is to first create a gameconn object by calling one of the flib_gameconn_create - * functions. That will cause the frontlib to listen on a random port which can be queried using - * flib_gameconn_getport(). You should also register your callback functions right at the start - * to ensure you don't miss any callbacks. - * - * Next, start the engine (that part is up to you) with the appropriate command line arguments - * for starting a game. - * - * In order to allow the gameconn to run, you should regularly call flib_gameconn_tick(), which - * performs network I/O and calls your callbacks on interesting events. - * - * Once the engine connects, the gameconn will send it the required commands for starting the - * game you requested in your flib_gameconn_create call. - * - * When the game is finished (or the connection is lost), you will receive the onDisconnect - * message. This is the signal to destroy the gameconn and stop calling tick(). - */ - -#ifndef GAMECONN_H_ -#define GAMECONN_H_ - -#include "../model/gamesetup.h" - -#include -#include -#include - -/* - * Different reasons for a disconnect. Only GAME_END_FINISHED signals a correctly completed game. - */ -#define GAME_END_FINISHED 0 -#define GAME_END_INTERRUPTED 1 -#define GAME_END_HALTED 2 -#define GAME_END_ERROR 3 - -typedef struct _flib_gameconn flib_gameconn; - -/** - * Create a gameconn that will start a local or network game with the indicated configuration. - */ -flib_gameconn *flib_gameconn_create(const char *playerName, const flib_gamesetup *setup, bool netgame); - -/** - * Create a gameconn that will play back a demo. - */ -flib_gameconn *flib_gameconn_create_playdemo(const uint8_t *demoFileContent, size_t size); - -/** - * Create a gameconn that will continue from a saved game. - */ -flib_gameconn *flib_gameconn_create_loadgame(const char *playerName, const uint8_t *saveFileContent, size_t size); - -/** - * Create a gameconn that will start a campaign or training mission with the indicated script. - * seed is the random seed to use as entropy source (any string). - * script is the path and filename of a Campaign or Training script, relative to the Data directory - * (e.g. "Missions/Training/Basic_Training_-_Bazooka.lua") - */ -flib_gameconn *flib_gameconn_create_campaign(const char *playerName, const char *seed, const char *script); - -/** - * Release all resources of this gameconn, including the network connection, and free its memory. - * It is safe to call this function from a callback. - */ -void flib_gameconn_destroy(flib_gameconn *conn); - -/** - * Returns the port on which the gameconn is listening. Only fails if you - * pass NULL (not allowed), in that case 0 is returned. - */ -int flib_gameconn_getport(flib_gameconn *conn); - -/** - * Perform I/O operations and call callbacks if something interesting happens. - * Should be called regularly. - */ -void flib_gameconn_tick(flib_gameconn *conn); - -/** - * Send an engine message to the engine. Only needed in net games, where you receive engine - * messages from the server and have to pass them here. - */ -int flib_gameconn_send_enginemsg(flib_gameconn *conn, const uint8_t *data, size_t len); - -/** - * Send an info message to the engine that will be displayed in the game's chatlog. - * The msgtype determines the color of the message; in the QTFrontend, info messages and - * normal chat messages use 1, emote-messages (those starting with /me) use 2, and - * join/leave messages use 3. You should use flib_gameconn_send_chatmsg for chat messages - * though because it automatically formats /me messages. - * - * Generally only needed in net games. - */ -int flib_gameconn_send_textmsg(flib_gameconn *conn, int msgtype, const char *msg); - -/** - * Send a chat message to be displayed in the game's chatlog. Messages starting with /me are - * automatically formatted correctly. - * - * Generally only needed in net games. - */ -int flib_gameconn_send_chatmsg(flib_gameconn *conn, const char *playername, const char *msg); - -/** - * Request the engine to stop the game (efinish). - * You can use this to shut down a game early without directly killing the engine process. - */ -int flib_gameconn_send_quit(flib_gameconn *conn); - -/** - * Send an arbitrary command to the engine, e.g. "eforcequit" to shut down the engine - * quickly. Commands prefixed with "e" will be processed by the engine's ProcessCommand - * method (with the e removed, so e.g. efinish will be parsed as finish). - */ -int flib_gameconn_send_cmd(flib_gameconn *conn, const char *cmdString); - -/** - * Expected callback signature: void handleConnect(void *context) - * The engine has successfully connected. You don't have to react to this in any way. - */ -void flib_gameconn_onConnect(flib_gameconn *conn, void (*callback)(void* context), void* context); - -/** - * Expected callback signature: void handleDisconnect(void *context, int reason) - * The connection to the engine was closed, either because the game has ended normally, or - * because it was interrupted/halted, or because of an error. The reason is provided as one - * of the GAME_END_xxx constants. - * - * You should destroy the gameconn and - in a netgame - notify the server that the game has ended. - */ -void flib_gameconn_onDisconnect(flib_gameconn *conn, void (*callback)(void* context, int reason), void* context); - -/** - * Expected callback signature: void handleErrorMessage(void* context, const char *msg) - * The engine sent an error message, you should probably display it to the user or at least log it. - */ -void flib_gameconn_onErrorMessage(flib_gameconn *conn, void (*callback)(void* context, const char *msg), void* context); - -/** - * Expected callback signature: void handleChat(void* context, const char *msg, bool teamchat) - * The player entered a chat or teamchat message. In a netgame, you should send it on to the server. - */ -void flib_gameconn_onChat(flib_gameconn *conn, void (*callback)(void* context, const char *msg, bool teamchat), void* context); - -/** - * Expected callback signature: void handleGameRecorded(void *context, const uint8_t *record, size_t size, bool isSavegame) - * The game has stopped, and a demo or savegame is available. You can store it in a file and later pass it back - * to the engine to either watch a replay (if it's a demo) or to continue playing (if it's a savegame). - */ -void flib_gameconn_onGameRecorded(flib_gameconn *conn, void (*callback)(void *context, const uint8_t *record, size_t size, bool isSavegame), void* context); - -/** - * Expected callback signature: void handleEngineMessage(void *context, const uint8_t *em, size_t size) - * The engine has generated a message with player input. In a netgame, you should send it on to the server. - */ -void flib_gameconn_onEngineMessage(flib_gameconn *conn, void (*callback)(void *context, const uint8_t *em, size_t size), void* context); - -#endif +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * This file contains functions for starting and interacting with a game run by the engine. + * The general usage is to first create a gameconn object by calling one of the flib_gameconn_create + * functions. That will cause the frontlib to listen on a random port which can be queried using + * flib_gameconn_getport(). You should also register your callback functions right at the start + * to ensure you don't miss any callbacks. + * + * Next, start the engine (that part is up to you) with the appropriate command line arguments + * for starting a game. + * + * In order to allow the gameconn to run, you should regularly call flib_gameconn_tick(), which + * performs network I/O and calls your callbacks on interesting events. + * + * Once the engine connects, the gameconn will send it the required commands for starting the + * game you requested in your flib_gameconn_create call. + * + * When the game is finished (or the connection is lost), you will receive the onDisconnect + * message. This is the signal to destroy the gameconn and stop calling tick(). + */ + +#ifndef GAMECONN_H_ +#define GAMECONN_H_ + +#include "../model/gamesetup.h" + +#include +#include +#include + +/* + * Different reasons for a disconnect. Only GAME_END_FINISHED signals a correctly completed game. + */ +#define GAME_END_FINISHED 0 +#define GAME_END_INTERRUPTED 1 +#define GAME_END_HALTED 2 +#define GAME_END_ERROR 3 + +typedef struct _flib_gameconn flib_gameconn; + +/** + * Create a gameconn that will start a local or network game with the indicated configuration. + */ +flib_gameconn *flib_gameconn_create(const char *playerName, const flib_gamesetup *setup, bool netgame); + +/** + * Create a gameconn that will play back a demo. + */ +flib_gameconn *flib_gameconn_create_playdemo(const uint8_t *demoFileContent, size_t size); + +/** + * Create a gameconn that will continue from a saved game. + */ +flib_gameconn *flib_gameconn_create_loadgame(const char *playerName, const uint8_t *saveFileContent, size_t size); + +/** + * Create a gameconn that will start a campaign or training mission with the indicated script. + * seed is the random seed to use as entropy source (any string). + * script is the path and filename of a Campaign or Training script, relative to the Data directory + * (e.g. "Missions/Training/Basic_Training_-_Bazooka.lua") + */ +flib_gameconn *flib_gameconn_create_campaign(const char *playerName, const char *seed, const char *script); + +/** + * Release all resources of this gameconn, including the network connection, and free its memory. + * It is safe to call this function from a callback. + */ +void flib_gameconn_destroy(flib_gameconn *conn); + +/** + * Returns the port on which the gameconn is listening. Only fails if you + * pass NULL (not allowed), in that case 0 is returned. + */ +int flib_gameconn_getport(flib_gameconn *conn); + +/** + * Perform I/O operations and call callbacks if something interesting happens. + * Should be called regularly. + */ +void flib_gameconn_tick(flib_gameconn *conn); + +/** + * Send an engine message to the engine. Only needed in net games, where you receive engine + * messages from the server and have to pass them here. + */ +int flib_gameconn_send_enginemsg(flib_gameconn *conn, const uint8_t *data, size_t len); + +/** + * Send an info message to the engine that will be displayed in the game's chatlog. + * The msgtype determines the color of the message; in the QTFrontend, info messages and + * normal chat messages use 1, emote-messages (those starting with /me) use 2, and + * join/leave messages use 3. You should use flib_gameconn_send_chatmsg for chat messages + * though because it automatically formats /me messages. + * + * Generally only needed in net games. + */ +int flib_gameconn_send_textmsg(flib_gameconn *conn, int msgtype, const char *msg); + +/** + * Send a chat message to be displayed in the game's chatlog. Messages starting with /me are + * automatically formatted correctly. + * + * Generally only needed in net games. + */ +int flib_gameconn_send_chatmsg(flib_gameconn *conn, const char *playername, const char *msg); + +/** + * Request the engine to stop the game (efinish). + * You can use this to shut down a game early without directly killing the engine process. + */ +int flib_gameconn_send_quit(flib_gameconn *conn); + +/** + * Send an arbitrary command to the engine, e.g. "eforcequit" to shut down the engine + * quickly. Commands prefixed with "e" will be processed by the engine's ProcessCommand + * method (with the e removed, so e.g. efinish will be parsed as finish). + */ +int flib_gameconn_send_cmd(flib_gameconn *conn, const char *cmdString); + +/** + * Expected callback signature: void handleConnect(void *context) + * The engine has successfully connected. You don't have to react to this in any way. + */ +void flib_gameconn_onConnect(flib_gameconn *conn, void (*callback)(void* context), void* context); + +/** + * Expected callback signature: void handleDisconnect(void *context, int reason) + * The connection to the engine was closed, either because the game has ended normally, or + * because it was interrupted/halted, or because of an error. The reason is provided as one + * of the GAME_END_xxx constants. + * + * You should destroy the gameconn and - in a netgame - notify the server that the game has ended. + */ +void flib_gameconn_onDisconnect(flib_gameconn *conn, void (*callback)(void* context, int reason), void* context); + +/** + * Expected callback signature: void handleErrorMessage(void* context, const char *msg) + * The engine sent an error message, you should probably display it to the user or at least log it. + */ +void flib_gameconn_onErrorMessage(flib_gameconn *conn, void (*callback)(void* context, const char *msg), void* context); + +/** + * Expected callback signature: void handleChat(void* context, const char *msg, bool teamchat) + * The player entered a chat or teamchat message. In a netgame, you should send it on to the server. + */ +void flib_gameconn_onChat(flib_gameconn *conn, void (*callback)(void* context, const char *msg, bool teamchat), void* context); + +/** + * Expected callback signature: void handleGameRecorded(void *context, const uint8_t *record, size_t size, bool isSavegame) + * The game has stopped, and a demo or savegame is available. You can store it in a file and later pass it back + * to the engine to either watch a replay (if it's a demo) or to continue playing (if it's a savegame). + */ +void flib_gameconn_onGameRecorded(flib_gameconn *conn, void (*callback)(void *context, const uint8_t *record, size_t size, bool isSavegame), void* context); + +/** + * Expected callback signature: void handleEngineMessage(void *context, const uint8_t *em, size_t size) + * The engine has generated a message with player input. In a netgame, you should send it on to the server. + */ +void flib_gameconn_onEngineMessage(flib_gameconn *conn, void (*callback)(void *context, const uint8_t *em, size_t size), void* context); + +#endif diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/ipc/ipcbase.c --- a/project_files/frontlib/ipc/ipcbase.c Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/ipc/ipcbase.c Tue Nov 10 20:43:13 2015 +0100 @@ -1,216 +1,216 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "ipcbase.h" -#include "../util/logging.h" -#include "../util/util.h" -#include "../socket.h" - -#include -#include -#include -#include - -/* - * The receive buffer has to be able to hold any message that might be received. Normally - * the messages are at most 256 bytes, but the map preview contains 4097 bytes (4096 for a - * bitmap, 1 for the number of hogs which fit on the map). - * - * We don't need to worry about wasting a few kb though, and I like powers of two... - */ -struct _flib_ipcbase { - uint8_t readBuffer[8192]; - int readBufferSize; - - flib_acceptor *acceptor; - uint16_t port; - - flib_tcpsocket *sock; -}; - -flib_ipcbase *flib_ipcbase_create() { - flib_ipcbase *result = flib_calloc(1, sizeof(flib_ipcbase)); - flib_acceptor *acceptor = flib_acceptor_create(0); - - if(!result || !acceptor) { - free(result); - flib_acceptor_close(acceptor); - return NULL; - } - - result->acceptor = acceptor; - result->sock = NULL; - result->readBufferSize = 0; - result->port = flib_acceptor_listenport(acceptor); - - flib_log_i("Started listening for IPC connections on port %u", (unsigned)result->port); - return result; -} - -uint16_t flib_ipcbase_port(flib_ipcbase *ipc) { - if(log_badargs_if(ipc==NULL)) { - return 0; - } - return ipc->port; -} - -void flib_ipcbase_destroy(flib_ipcbase *ipc) { - if(ipc) { - flib_acceptor_close(ipc->acceptor); - flib_socket_close(ipc->sock); - if(ipc->sock) { - flib_log_d("IPC connection closed."); - } - free(ipc); - } -} - -IpcState flib_ipcbase_state(flib_ipcbase *ipc) { - if(log_badargs_if(ipc==NULL)) { - return IPC_NOT_CONNECTED; - } else if(ipc->sock) { - return IPC_CONNECTED; - } else if(ipc->acceptor) { - return IPC_LISTENING; - } else { - return IPC_NOT_CONNECTED; - } -} - -static void receiveToBuffer(flib_ipcbase *ipc) { - if(ipc->sock) { - int size = flib_socket_nbrecv(ipc->sock, ipc->readBuffer+ipc->readBufferSize, sizeof(ipc->readBuffer)-ipc->readBufferSize); - if(size>=0) { - ipc->readBufferSize += size; - } else { - flib_log_d("IPC connection lost."); - flib_socket_close(ipc->sock); - ipc->sock = NULL; - } - } -} - -static bool isMessageReady(flib_ipcbase *ipc) { - return ipc->readBufferSize >= ipc->readBuffer[0]+1; -} - -static void logSentMsg(const uint8_t *data, size_t len) { - if(flib_log_isActive(FLIB_LOGLEVEL_DEBUG)) { - size_t msgStart = 0; - while(msgStart < len) { - uint8_t msglen = data[msgStart]; - if(msgStart+msglen < len) { - flib_log_d("[IPC OUT][%03u]%*.*s",(unsigned)msglen, (unsigned)msglen, (unsigned)msglen, data+msgStart+1); - } else { - uint8_t msglen2 = len-msgStart-1; - flib_log_d("[IPC OUT][%03u/%03u]%*.*s",(unsigned)msglen2, (unsigned)msglen, (unsigned)msglen2, (unsigned)msglen2, data+msgStart+1); - } - msgStart += (uint8_t)data[msgStart]+1; - } - } -} - -static void logRecvMsg(const uint8_t *data) { - if(flib_log_isActive(FLIB_LOGLEVEL_DEBUG)) { - uint8_t msglen = data[0]; - flib_log_d("[IPC IN][%03u]%*.*s",(unsigned)msglen, (unsigned)msglen, (unsigned)msglen, data+1); - } -} - -static void popFromReadBuffer(flib_ipcbase *ipc, uint8_t *outbuf, size_t size) { - memcpy(outbuf, ipc->readBuffer, size); - memmove(ipc->readBuffer, ipc->readBuffer+size, ipc->readBufferSize-size); - ipc->readBufferSize -= size; -} - -int flib_ipcbase_recv_message(flib_ipcbase *ipc, void *data) { - if(log_badargs_if2(ipc==NULL, data==NULL)) { - return -1; - } - - if(!isMessageReady(ipc)) { - receiveToBuffer(ipc); - } - - if(isMessageReady(ipc)) { - int msgsize = ipc->readBuffer[0]+1; - popFromReadBuffer(ipc, data, msgsize); - logRecvMsg(data); - return msgsize; - } else if(!ipc->sock && ipc->readBufferSize>0) { - flib_log_w("Last message from engine data stream is incomplete (received %u of %u bytes)", (unsigned)ipc->readBufferSize, (unsigned)(ipc->readBuffer[0])+1); - ipc->readBufferSize = 0; - return -1; - } else { - return -1; - } -} - -int flib_ipcbase_recv_map(flib_ipcbase *ipc, void *data) { - if(log_badargs_if2(ipc==NULL, data==NULL)) { - return -1; - } - - receiveToBuffer(ipc); - - if(ipc->readBufferSize >= IPCBASE_MAPMSG_BYTES) { - popFromReadBuffer(ipc, data, IPCBASE_MAPMSG_BYTES); - return IPCBASE_MAPMSG_BYTES; - } else { - return -1; - } -} - -int flib_ipcbase_send_raw(flib_ipcbase *ipc, const void *data, size_t len) { - if(log_badargs_if2(ipc==NULL, data==NULL && len>0) - || log_w_if(!ipc->sock, "flib_ipcbase_send_raw: Not connected.")) { - return -1; - } - if(flib_socket_send(ipc->sock, data, len) == len) { - logSentMsg(data, len); - return 0; - } else { - flib_log_w("Failed or incomplete IPC write: engine connection lost."); - flib_socket_close(ipc->sock); - ipc->sock = NULL; - return -1; - } -} - -int flib_ipcbase_send_message(flib_ipcbase *ipc, void *data, size_t len) { - if(log_badargs_if3(ipc==NULL, data==NULL && len>0, len>255)) { - return -1; - } - - uint8_t sendbuf[256]; - sendbuf[0] = len; - memcpy(sendbuf+1, data, len); - return flib_ipcbase_send_raw(ipc, sendbuf, len+1); -} - -void flib_ipcbase_accept(flib_ipcbase *ipc) { - if(!log_badargs_if(ipc==NULL) && !ipc->sock && ipc->acceptor) { - ipc->sock = flib_socket_accept(ipc->acceptor, true); - if(ipc->sock) { - flib_log_d("IPC connection accepted."); - flib_acceptor_close(ipc->acceptor); - ipc->acceptor = NULL; - } - } -} +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "ipcbase.h" +#include "../util/logging.h" +#include "../util/util.h" +#include "../socket.h" + +#include +#include +#include +#include + +/* + * The receive buffer has to be able to hold any message that might be received. Normally + * the messages are at most 256 bytes, but the map preview contains 4097 bytes (4096 for a + * bitmap, 1 for the number of hogs which fit on the map). + * + * We don't need to worry about wasting a few kb though, and I like powers of two... + */ +struct _flib_ipcbase { + uint8_t readBuffer[8192]; + int readBufferSize; + + flib_acceptor *acceptor; + uint16_t port; + + flib_tcpsocket *sock; +}; + +flib_ipcbase *flib_ipcbase_create() { + flib_ipcbase *result = flib_calloc(1, sizeof(flib_ipcbase)); + flib_acceptor *acceptor = flib_acceptor_create(0); + + if(!result || !acceptor) { + free(result); + flib_acceptor_close(acceptor); + return NULL; + } + + result->acceptor = acceptor; + result->sock = NULL; + result->readBufferSize = 0; + result->port = flib_acceptor_listenport(acceptor); + + flib_log_i("Started listening for IPC connections on port %u", (unsigned)result->port); + return result; +} + +uint16_t flib_ipcbase_port(flib_ipcbase *ipc) { + if(log_badargs_if(ipc==NULL)) { + return 0; + } + return ipc->port; +} + +void flib_ipcbase_destroy(flib_ipcbase *ipc) { + if(ipc) { + flib_acceptor_close(ipc->acceptor); + flib_socket_close(ipc->sock); + if(ipc->sock) { + flib_log_d("IPC connection closed."); + } + free(ipc); + } +} + +IpcState flib_ipcbase_state(flib_ipcbase *ipc) { + if(log_badargs_if(ipc==NULL)) { + return IPC_NOT_CONNECTED; + } else if(ipc->sock) { + return IPC_CONNECTED; + } else if(ipc->acceptor) { + return IPC_LISTENING; + } else { + return IPC_NOT_CONNECTED; + } +} + +static void receiveToBuffer(flib_ipcbase *ipc) { + if(ipc->sock) { + int size = flib_socket_nbrecv(ipc->sock, ipc->readBuffer+ipc->readBufferSize, sizeof(ipc->readBuffer)-ipc->readBufferSize); + if(size>=0) { + ipc->readBufferSize += size; + } else { + flib_log_d("IPC connection lost."); + flib_socket_close(ipc->sock); + ipc->sock = NULL; + } + } +} + +static bool isMessageReady(flib_ipcbase *ipc) { + return ipc->readBufferSize >= ipc->readBuffer[0]+1; +} + +static void logSentMsg(const uint8_t *data, size_t len) { + if(flib_log_isActive(FLIB_LOGLEVEL_DEBUG)) { + size_t msgStart = 0; + while(msgStart < len) { + uint8_t msglen = data[msgStart]; + if(msgStart+msglen < len) { + flib_log_d("[IPC OUT][%03u]%*.*s",(unsigned)msglen, (unsigned)msglen, (unsigned)msglen, data+msgStart+1); + } else { + uint8_t msglen2 = len-msgStart-1; + flib_log_d("[IPC OUT][%03u/%03u]%*.*s",(unsigned)msglen2, (unsigned)msglen, (unsigned)msglen2, (unsigned)msglen2, data+msgStart+1); + } + msgStart += (uint8_t)data[msgStart]+1; + } + } +} + +static void logRecvMsg(const uint8_t *data) { + if(flib_log_isActive(FLIB_LOGLEVEL_DEBUG)) { + uint8_t msglen = data[0]; + flib_log_d("[IPC IN][%03u]%*.*s",(unsigned)msglen, (unsigned)msglen, (unsigned)msglen, data+1); + } +} + +static void popFromReadBuffer(flib_ipcbase *ipc, uint8_t *outbuf, size_t size) { + memcpy(outbuf, ipc->readBuffer, size); + memmove(ipc->readBuffer, ipc->readBuffer+size, ipc->readBufferSize-size); + ipc->readBufferSize -= size; +} + +int flib_ipcbase_recv_message(flib_ipcbase *ipc, void *data) { + if(log_badargs_if2(ipc==NULL, data==NULL)) { + return -1; + } + + if(!isMessageReady(ipc)) { + receiveToBuffer(ipc); + } + + if(isMessageReady(ipc)) { + int msgsize = ipc->readBuffer[0]+1; + popFromReadBuffer(ipc, data, msgsize); + logRecvMsg(data); + return msgsize; + } else if(!ipc->sock && ipc->readBufferSize>0) { + flib_log_w("Last message from engine data stream is incomplete (received %u of %u bytes)", (unsigned)ipc->readBufferSize, (unsigned)(ipc->readBuffer[0])+1); + ipc->readBufferSize = 0; + return -1; + } else { + return -1; + } +} + +int flib_ipcbase_recv_map(flib_ipcbase *ipc, void *data) { + if(log_badargs_if2(ipc==NULL, data==NULL)) { + return -1; + } + + receiveToBuffer(ipc); + + if(ipc->readBufferSize >= IPCBASE_MAPMSG_BYTES) { + popFromReadBuffer(ipc, data, IPCBASE_MAPMSG_BYTES); + return IPCBASE_MAPMSG_BYTES; + } else { + return -1; + } +} + +int flib_ipcbase_send_raw(flib_ipcbase *ipc, const void *data, size_t len) { + if(log_badargs_if2(ipc==NULL, data==NULL && len>0) + || log_w_if(!ipc->sock, "flib_ipcbase_send_raw: Not connected.")) { + return -1; + } + if(flib_socket_send(ipc->sock, data, len) == len) { + logSentMsg(data, len); + return 0; + } else { + flib_log_w("Failed or incomplete IPC write: engine connection lost."); + flib_socket_close(ipc->sock); + ipc->sock = NULL; + return -1; + } +} + +int flib_ipcbase_send_message(flib_ipcbase *ipc, void *data, size_t len) { + if(log_badargs_if3(ipc==NULL, data==NULL && len>0, len>255)) { + return -1; + } + + uint8_t sendbuf[256]; + sendbuf[0] = len; + memcpy(sendbuf+1, data, len); + return flib_ipcbase_send_raw(ipc, sendbuf, len+1); +} + +void flib_ipcbase_accept(flib_ipcbase *ipc) { + if(!log_badargs_if(ipc==NULL) && !ipc->sock && ipc->acceptor) { + ipc->sock = flib_socket_accept(ipc->acceptor, true); + if(ipc->sock) { + flib_log_d("IPC connection accepted."); + flib_acceptor_close(ipc->acceptor); + ipc->acceptor = NULL; + } + } +} diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/ipc/ipcbase.h --- a/project_files/frontlib/ipc/ipcbase.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/ipc/ipcbase.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,105 +1,105 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/* - * Low-level protocol support for the IPC connection to the engine. - */ -#ifndef IPCBASE_H_ -#define IPCBASE_H_ - -#include -#include -#include - -#define IPCBASE_MAPMSG_BYTES 4097 - -typedef enum {IPC_NOT_CONNECTED, IPC_LISTENING, IPC_CONNECTED} IpcState; - -typedef struct _flib_ipcbase flib_ipcbase; - -/** - * Start an engine connection by listening on a random port. The selected port can - * be queried with flib_ipcbase_port and has to be passed to the engine. - * - * Returns NULL on error. Destroy the created object with flib_ipcbase_destroy. - * - * We stop accepting new connections once a connection has been established, so you - * need to create a new ipcbase in order to start a new connection. - */ -flib_ipcbase *flib_ipcbase_create(); - -/** - * Return the listening port - */ -uint16_t flib_ipcbase_port(flib_ipcbase *ipc); - -/** - * Free resources and close sockets. NULL safe. - */ -void flib_ipcbase_destroy(flib_ipcbase *ipc); - -/** - * Determine the current connection state - */ -IpcState flib_ipcbase_state(flib_ipcbase *ipc); - -/** - * Receive a single message (up to 256 bytes) and copy it into the data buffer. - * Returns the length of the received message, a negative value if no message could - * be read. - * - * The first byte of a message is its content length, which is one less than the returned - * value. - * - * Note: When a connection is closed, you probably want to call this function until - * no further message is returned, to ensure you see all messages that were sent - * before the connection closed. - */ -int flib_ipcbase_recv_message(flib_ipcbase *ipc, void *data); - -/** - * Try to receive 4097 bytes. This is the size of the reply the engine sends - * when successfully queried for map data. The first 4096 bytes are a bit-packed - * twocolor image of the map (256x128), the last byte is the number of hogs that - * fit on the map. - */ -int flib_ipcbase_recv_map(flib_ipcbase *ipc, void *data); - -/** - * Blocking send bytes over the socket. No message framing will be added. - * Returns 0 on success. - */ -int flib_ipcbase_send_raw(flib_ipcbase *ipc, const void *data, size_t len); - -/** - * Write a single message (up to 255 bytes) to the engine. This call blocks until the - * message is completely written or the connection is closed or an error occurs. - * - * Calling this function in a state other than IPC_CONNECTED will fail immediately. - * Returns 0 on success. - */ -int flib_ipcbase_send_message(flib_ipcbase *ipc, void *data, size_t len); - -/** - * Try to accept a connection. Only has an effect in state IPC_LISTENING. - */ -void flib_ipcbase_accept(flib_ipcbase *ipc); - -#endif /* IPCBASE_H_ */ - +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* + * Low-level protocol support for the IPC connection to the engine. + */ +#ifndef IPCBASE_H_ +#define IPCBASE_H_ + +#include +#include +#include + +#define IPCBASE_MAPMSG_BYTES 4097 + +typedef enum {IPC_NOT_CONNECTED, IPC_LISTENING, IPC_CONNECTED} IpcState; + +typedef struct _flib_ipcbase flib_ipcbase; + +/** + * Start an engine connection by listening on a random port. The selected port can + * be queried with flib_ipcbase_port and has to be passed to the engine. + * + * Returns NULL on error. Destroy the created object with flib_ipcbase_destroy. + * + * We stop accepting new connections once a connection has been established, so you + * need to create a new ipcbase in order to start a new connection. + */ +flib_ipcbase *flib_ipcbase_create(); + +/** + * Return the listening port + */ +uint16_t flib_ipcbase_port(flib_ipcbase *ipc); + +/** + * Free resources and close sockets. NULL safe. + */ +void flib_ipcbase_destroy(flib_ipcbase *ipc); + +/** + * Determine the current connection state + */ +IpcState flib_ipcbase_state(flib_ipcbase *ipc); + +/** + * Receive a single message (up to 256 bytes) and copy it into the data buffer. + * Returns the length of the received message, a negative value if no message could + * be read. + * + * The first byte of a message is its content length, which is one less than the returned + * value. + * + * Note: When a connection is closed, you probably want to call this function until + * no further message is returned, to ensure you see all messages that were sent + * before the connection closed. + */ +int flib_ipcbase_recv_message(flib_ipcbase *ipc, void *data); + +/** + * Try to receive 4097 bytes. This is the size of the reply the engine sends + * when successfully queried for map data. The first 4096 bytes are a bit-packed + * twocolor image of the map (256x128), the last byte is the number of hogs that + * fit on the map. + */ +int flib_ipcbase_recv_map(flib_ipcbase *ipc, void *data); + +/** + * Blocking send bytes over the socket. No message framing will be added. + * Returns 0 on success. + */ +int flib_ipcbase_send_raw(flib_ipcbase *ipc, const void *data, size_t len); + +/** + * Write a single message (up to 255 bytes) to the engine. This call blocks until the + * message is completely written or the connection is closed or an error occurs. + * + * Calling this function in a state other than IPC_CONNECTED will fail immediately. + * Returns 0 on success. + */ +int flib_ipcbase_send_message(flib_ipcbase *ipc, void *data, size_t len); + +/** + * Try to accept a connection. Only has an effect in state IPC_LISTENING. + */ +void flib_ipcbase_accept(flib_ipcbase *ipc); + +#endif /* IPCBASE_H_ */ + diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/ipc/ipcprotocol.c --- a/project_files/frontlib/ipc/ipcprotocol.c Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/ipc/ipcprotocol.c Tue Nov 10 20:43:13 2015 +0100 @@ -1,316 +1,316 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "ipcprotocol.h" -#include "../util/util.h" -#include "../util/logging.h" -#include "../md5/md5.h" - -#include -#include -#include -#include -#include - -int flib_ipc_append_message(flib_vector *vec, const char *fmt, ...) { - int result = -1; - if(!log_badargs_if2(vec==NULL, fmt==NULL)) { - // 1 byte size prefix, 255 bytes max message length, 1 0-byte for vsnprintf - char msgbuffer[257]; - - // Format the message, leaving one byte at the start for the length - va_list argp; - va_start(argp, fmt); - int msgSize = vsnprintf(msgbuffer+1, 256, fmt, argp); - va_end(argp); - - if(!log_e_if(msgSize > 255, "Message too long (%u bytes)", (unsigned)msgSize) - && !log_e_if(msgSize < 0, "printf error")) { - // Add the length prefix - ((uint8_t*)msgbuffer)[0] = msgSize; - - // Append it to the vector - result = flib_vector_append(vec, msgbuffer, msgSize+1); - } - } - return result; -} - -int flib_ipc_append_mapconf(flib_vector *vec, const flib_map *map, bool mappreview) { - int result = -1; - flib_vector *tempvector = flib_vector_create(); - if(!log_badargs_if2(vec==NULL, map==NULL)) { - bool error = false; - - if(map->mapgen == MAPGEN_NAMED) { - error |= log_e_if(!map->name, "Missing map name") - || flib_ipc_append_message(tempvector, "emap %s", map->name); - } - if(!mappreview) { - error |= log_e_if(!map->theme, "Missing map theme") - || flib_ipc_append_message(tempvector, "etheme %s", map->theme); - } - error |= flib_ipc_append_seed(tempvector, map->seed); - error |= flib_ipc_append_message(tempvector, "e$template_filter %i", map->templateFilter); - error |= flib_ipc_append_message(tempvector, "e$mapgen %i", map->mapgen); - - if(map->mapgen == MAPGEN_MAZE) { - error |= flib_ipc_append_message(tempvector, "e$maze_size %i", map->mazeSize); - } - if(map->mapgen == MAPGEN_DRAWN) { - /* - * We have to split the drawn map data into several edraw messages here because - * it can be longer than the maximum message size. - */ - const char *edraw = "edraw "; - int edrawlen = strlen(edraw); - for(size_t offset=0; offsetdrawDataSize; offset+=200) { - size_t bytesRemaining = map->drawDataSize-offset; - int fragmentsize = bytesRemaining < 200 ? bytesRemaining : 200; - uint8_t messagesize = edrawlen + fragmentsize; - error |= flib_vector_append(tempvector, &messagesize, 1); - error |= flib_vector_append(tempvector, edraw, edrawlen); - error |= flib_vector_append(tempvector, map->drawData+offset, fragmentsize); - } - } - - if(!log_e_if(error, "Error generating map config")) { - // Message created, now we can copy everything. - flib_constbuffer constbuf = flib_vector_as_constbuffer(tempvector); - if(!flib_vector_append(vec, constbuf.data, constbuf.size)) { - result = 0; - } - } - } - flib_vector_destroy(tempvector); - return result; -} - -int flib_ipc_append_seed(flib_vector *vec, const char *seed) { - if(log_badargs_if2(vec==NULL, seed==NULL)) { - return -1; - } - return flib_ipc_append_message(vec, "eseed %s", seed); -} - -int flib_ipc_append_script(flib_vector *vec, const char *script) { - int result = -1; - if(!log_badargs_if2(vec==NULL, script==NULL)) { - result = flib_ipc_append_message(vec, "escript %s", script); - } - return result; -} - -int flib_ipc_append_style(flib_vector *vec, const char *style) { - int result = -1; - char *copy = flib_strdupnull(style); - if(!log_badargs_if(vec==NULL) && copy) { - if(!strcmp("Normal", copy)) { - // "Normal" means no gametype script - // TODO if an empty script called "Normal" is added to the scripts directory this can be removed - result = 0; - } else { - size_t len = strlen(copy); - for(size_t i=0; imods[i]) { - int bitmaskIndex = flib_meta.mods[i].bitmaskIndex; - result |= (UINT32_C(1) << bitmaskIndex); - } - } - return result; -} - -int flib_ipc_append_gamescheme(flib_vector *vec, const flib_scheme *scheme) { - int result = -1; - flib_vector *tempvector = flib_vector_create(); - if(!log_badargs_if2(vec==NULL, scheme==NULL) && tempvector) { - bool error = false; - error |= flib_ipc_append_message(tempvector, "e$gmflags %"PRIu32, buildModFlags(scheme)); - for(int i=0; isettings[i]; - if(flib_meta.settings[i].maxMeansInfinity) { - value = value>=flib_meta.settings[i].max ? 9999 : value; - } - if(flib_meta.settings[i].times1000) { - value *= 1000; - } - error |= flib_ipc_append_message(tempvector, "%s %i", flib_meta.settings[i].engineCommand, value); - } - } - - if(!error) { - // Message created, now we can copy everything. - flib_constbuffer constbuf = flib_vector_as_constbuffer(tempvector); - if(!flib_vector_append(vec, constbuf.data, constbuf.size)) { - result = 0; - } - } - } - flib_vector_destroy(tempvector); - return result; -} - -static int appendWeaponSet(flib_vector *vec, flib_weaponset *set) { - return flib_ipc_append_message(vec, "eammloadt %s", set->loadout) - || flib_ipc_append_message(vec, "eammprob %s", set->crateprob) - || flib_ipc_append_message(vec, "eammdelay %s", set->delay) - || flib_ipc_append_message(vec, "eammreinf %s", set->crateammo); -} - -static void calculateMd5Hex(const char *in, char out[33]) { - md5_state_t md5state; - uint8_t md5bytes[16]; - md5_init(&md5state); - md5_append(&md5state, (unsigned char*)in, strlen(in)); - md5_finish(&md5state, md5bytes); - for(int i=0;ihogs[0].weaponset) - || flib_ipc_append_message(tempvector, "eammstore"); - } - - char md5Hex[33]; - calculateMd5Hex(team->ownerName ? team->ownerName : "", md5Hex); - if(team->colorIndex<0 || team->colorIndex>=flib_teamcolor_count) { - flib_log_e("Color index out of bounds for team %s: %i", team->name, team->colorIndex); - error = true; - } else { - error |= flib_ipc_append_message(tempvector, "eaddteam %s %"PRIu32" %s", md5Hex, flib_teamcolors[team->colorIndex], team->name); - } - - if(team->remoteDriven) { - error |= flib_ipc_append_message(tempvector, "erdriven"); - } - - error |= flib_ipc_append_message(tempvector, "egrave %s", team->grave); - error |= flib_ipc_append_message(tempvector, "efort %s", team->fort); - error |= flib_ipc_append_message(tempvector, "evoicepack %s", team->voicepack); - error |= flib_ipc_append_message(tempvector, "eflag %s", team->flag); - - for(int i=0; ibindingCount; i++) { - error |= flib_ipc_append_message(tempvector, "ebind %s %s", team->bindings[i].binding, team->bindings[i].action); - } - - for(int i=0; ihogsInGame; i++) { - if(perHogAmmo && !noAmmoStore) { - error |= appendWeaponSet(tempvector, team->hogs[i].weaponset); - } - error |= flib_ipc_append_message(tempvector, "eaddhh %i %i %s", team->hogs[i].difficulty, team->hogs[i].initialHealth, team->hogs[i].name); - error |= flib_ipc_append_message(tempvector, "ehat %s", team->hogs[i].hat); - } - - if(!error) { - // Message created, now we can copy everything. - flib_constbuffer constbuf = flib_vector_as_constbuffer(tempvector); - if(!flib_vector_append(vec, constbuf.data, constbuf.size)) { - result = 0; - } - } - } - flib_vector_destroy(tempvector); - return result; -} - -int flib_ipc_append_fullconfig(flib_vector *vec, const flib_gamesetup *setup, bool netgame) { - int result = -1; - flib_vector *tempvector = flib_vector_create(); - if(!log_badargs_if2(vec==NULL, setup==NULL) && tempvector) { - bool error = false; - bool perHogAmmo = false; - bool sharedAmmo = false; - - error |= flib_ipc_append_message(vec, netgame ? "TN" : "TL"); - if(setup->map) { - error |= flib_ipc_append_mapconf(tempvector, setup->map, false); - } - if(setup->style) { - error |= flib_ipc_append_style(tempvector, setup->style); - } - if(setup->gamescheme) { - error |= flib_ipc_append_gamescheme(tempvector, setup->gamescheme); - sharedAmmo = flib_scheme_get_mod(setup->gamescheme, "sharedammo"); - // Shared ammo has priority over per-hog ammo - perHogAmmo = !sharedAmmo && flib_scheme_get_mod(setup->gamescheme, "perhogammo"); - } - if(setup->teamlist->teams && setup->teamlist->teamCount>0) { - int *clanColors = flib_calloc(setup->teamlist->teamCount, sizeof(int)); - if(!clanColors) { - error = true; - } else { - int clanCount = 0; - for(int i=0; !error && iteamlist->teamCount; i++) { - flib_team *team = setup->teamlist->teams[i]; - // Find the clan index of this team (clans are identified by color). - bool newClan = false; - int clan = 0; - while(clancolorIndex) { - clan++; - } - if(clan==clanCount) { - newClan = true; - clanCount++; - clanColors[clan] = team->colorIndex; - } - - // If shared ammo is active, only add an ammo store for the first team in each clan. - bool noAmmoStore = sharedAmmo&&!newClan; - error |= flib_ipc_append_addteam(tempvector, setup->teamlist->teams[i], perHogAmmo, noAmmoStore); - } - } - free(clanColors); - } - error |= flib_ipc_append_message(tempvector, "!"); - - if(!error) { - // Message created, now we can copy everything. - flib_constbuffer constbuf = flib_vector_as_constbuffer(tempvector); - if(!flib_vector_append(vec, constbuf.data, constbuf.size)) { - result = 0; - } - } - } - return result; -} +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "ipcprotocol.h" +#include "../util/util.h" +#include "../util/logging.h" +#include "../md5/md5.h" + +#include +#include +#include +#include +#include + +int flib_ipc_append_message(flib_vector *vec, const char *fmt, ...) { + int result = -1; + if(!log_badargs_if2(vec==NULL, fmt==NULL)) { + // 1 byte size prefix, 255 bytes max message length, 1 0-byte for vsnprintf + char msgbuffer[257]; + + // Format the message, leaving one byte at the start for the length + va_list argp; + va_start(argp, fmt); + int msgSize = vsnprintf(msgbuffer+1, 256, fmt, argp); + va_end(argp); + + if(!log_e_if(msgSize > 255, "Message too long (%u bytes)", (unsigned)msgSize) + && !log_e_if(msgSize < 0, "printf error")) { + // Add the length prefix + ((uint8_t*)msgbuffer)[0] = msgSize; + + // Append it to the vector + result = flib_vector_append(vec, msgbuffer, msgSize+1); + } + } + return result; +} + +int flib_ipc_append_mapconf(flib_vector *vec, const flib_map *map, bool mappreview) { + int result = -1; + flib_vector *tempvector = flib_vector_create(); + if(!log_badargs_if2(vec==NULL, map==NULL)) { + bool error = false; + + if(map->mapgen == MAPGEN_NAMED) { + error |= log_e_if(!map->name, "Missing map name") + || flib_ipc_append_message(tempvector, "emap %s", map->name); + } + if(!mappreview) { + error |= log_e_if(!map->theme, "Missing map theme") + || flib_ipc_append_message(tempvector, "etheme %s", map->theme); + } + error |= flib_ipc_append_seed(tempvector, map->seed); + error |= flib_ipc_append_message(tempvector, "e$template_filter %i", map->templateFilter); + error |= flib_ipc_append_message(tempvector, "e$mapgen %i", map->mapgen); + + if(map->mapgen == MAPGEN_MAZE) { + error |= flib_ipc_append_message(tempvector, "e$maze_size %i", map->mazeSize); + } + if(map->mapgen == MAPGEN_DRAWN) { + /* + * We have to split the drawn map data into several edraw messages here because + * it can be longer than the maximum message size. + */ + const char *edraw = "edraw "; + int edrawlen = strlen(edraw); + for(size_t offset=0; offsetdrawDataSize; offset+=200) { + size_t bytesRemaining = map->drawDataSize-offset; + int fragmentsize = bytesRemaining < 200 ? bytesRemaining : 200; + uint8_t messagesize = edrawlen + fragmentsize; + error |= flib_vector_append(tempvector, &messagesize, 1); + error |= flib_vector_append(tempvector, edraw, edrawlen); + error |= flib_vector_append(tempvector, map->drawData+offset, fragmentsize); + } + } + + if(!log_e_if(error, "Error generating map config")) { + // Message created, now we can copy everything. + flib_constbuffer constbuf = flib_vector_as_constbuffer(tempvector); + if(!flib_vector_append(vec, constbuf.data, constbuf.size)) { + result = 0; + } + } + } + flib_vector_destroy(tempvector); + return result; +} + +int flib_ipc_append_seed(flib_vector *vec, const char *seed) { + if(log_badargs_if2(vec==NULL, seed==NULL)) { + return -1; + } + return flib_ipc_append_message(vec, "eseed %s", seed); +} + +int flib_ipc_append_script(flib_vector *vec, const char *script) { + int result = -1; + if(!log_badargs_if2(vec==NULL, script==NULL)) { + result = flib_ipc_append_message(vec, "escript %s", script); + } + return result; +} + +int flib_ipc_append_style(flib_vector *vec, const char *style) { + int result = -1; + char *copy = flib_strdupnull(style); + if(!log_badargs_if(vec==NULL) && copy) { + if(!strcmp("Normal", copy)) { + // "Normal" means no gametype script + // TODO if an empty script called "Normal" is added to the scripts directory this can be removed + result = 0; + } else { + size_t len = strlen(copy); + for(size_t i=0; imods[i]) { + int bitmaskIndex = flib_meta.mods[i].bitmaskIndex; + result |= (UINT32_C(1) << bitmaskIndex); + } + } + return result; +} + +int flib_ipc_append_gamescheme(flib_vector *vec, const flib_scheme *scheme) { + int result = -1; + flib_vector *tempvector = flib_vector_create(); + if(!log_badargs_if2(vec==NULL, scheme==NULL) && tempvector) { + bool error = false; + error |= flib_ipc_append_message(tempvector, "e$gmflags %"PRIu32, buildModFlags(scheme)); + for(int i=0; isettings[i]; + if(flib_meta.settings[i].maxMeansInfinity) { + value = value>=flib_meta.settings[i].max ? 9999 : value; + } + if(flib_meta.settings[i].times1000) { + value *= 1000; + } + error |= flib_ipc_append_message(tempvector, "%s %i", flib_meta.settings[i].engineCommand, value); + } + } + + if(!error) { + // Message created, now we can copy everything. + flib_constbuffer constbuf = flib_vector_as_constbuffer(tempvector); + if(!flib_vector_append(vec, constbuf.data, constbuf.size)) { + result = 0; + } + } + } + flib_vector_destroy(tempvector); + return result; +} + +static int appendWeaponSet(flib_vector *vec, flib_weaponset *set) { + return flib_ipc_append_message(vec, "eammloadt %s", set->loadout) + || flib_ipc_append_message(vec, "eammprob %s", set->crateprob) + || flib_ipc_append_message(vec, "eammdelay %s", set->delay) + || flib_ipc_append_message(vec, "eammreinf %s", set->crateammo); +} + +static void calculateMd5Hex(const char *in, char out[33]) { + md5_state_t md5state; + uint8_t md5bytes[16]; + md5_init(&md5state); + md5_append(&md5state, (unsigned char*)in, strlen(in)); + md5_finish(&md5state, md5bytes); + for(int i=0;ihogs[0].weaponset) + || flib_ipc_append_message(tempvector, "eammstore"); + } + + char md5Hex[33]; + calculateMd5Hex(team->ownerName ? team->ownerName : "", md5Hex); + if(team->colorIndex<0 || team->colorIndex>=flib_teamcolor_count) { + flib_log_e("Color index out of bounds for team %s: %i", team->name, team->colorIndex); + error = true; + } else { + error |= flib_ipc_append_message(tempvector, "eaddteam %s %"PRIu32" %s", md5Hex, flib_teamcolors[team->colorIndex], team->name); + } + + if(team->remoteDriven) { + error |= flib_ipc_append_message(tempvector, "erdriven"); + } + + error |= flib_ipc_append_message(tempvector, "egrave %s", team->grave); + error |= flib_ipc_append_message(tempvector, "efort %s", team->fort); + error |= flib_ipc_append_message(tempvector, "evoicepack %s", team->voicepack); + error |= flib_ipc_append_message(tempvector, "eflag %s", team->flag); + + for(int i=0; ibindingCount; i++) { + error |= flib_ipc_append_message(tempvector, "ebind %s %s", team->bindings[i].binding, team->bindings[i].action); + } + + for(int i=0; ihogsInGame; i++) { + if(perHogAmmo && !noAmmoStore) { + error |= appendWeaponSet(tempvector, team->hogs[i].weaponset); + } + error |= flib_ipc_append_message(tempvector, "eaddhh %i %i %s", team->hogs[i].difficulty, team->hogs[i].initialHealth, team->hogs[i].name); + error |= flib_ipc_append_message(tempvector, "ehat %s", team->hogs[i].hat); + } + + if(!error) { + // Message created, now we can copy everything. + flib_constbuffer constbuf = flib_vector_as_constbuffer(tempvector); + if(!flib_vector_append(vec, constbuf.data, constbuf.size)) { + result = 0; + } + } + } + flib_vector_destroy(tempvector); + return result; +} + +int flib_ipc_append_fullconfig(flib_vector *vec, const flib_gamesetup *setup, bool netgame) { + int result = -1; + flib_vector *tempvector = flib_vector_create(); + if(!log_badargs_if2(vec==NULL, setup==NULL) && tempvector) { + bool error = false; + bool perHogAmmo = false; + bool sharedAmmo = false; + + error |= flib_ipc_append_message(vec, netgame ? "TN" : "TL"); + if(setup->map) { + error |= flib_ipc_append_mapconf(tempvector, setup->map, false); + } + if(setup->style) { + error |= flib_ipc_append_style(tempvector, setup->style); + } + if(setup->gamescheme) { + error |= flib_ipc_append_gamescheme(tempvector, setup->gamescheme); + sharedAmmo = flib_scheme_get_mod(setup->gamescheme, "sharedammo"); + // Shared ammo has priority over per-hog ammo + perHogAmmo = !sharedAmmo && flib_scheme_get_mod(setup->gamescheme, "perhogammo"); + } + if(setup->teamlist->teams && setup->teamlist->teamCount>0) { + int *clanColors = flib_calloc(setup->teamlist->teamCount, sizeof(int)); + if(!clanColors) { + error = true; + } else { + int clanCount = 0; + for(int i=0; !error && iteamlist->teamCount; i++) { + flib_team *team = setup->teamlist->teams[i]; + // Find the clan index of this team (clans are identified by color). + bool newClan = false; + int clan = 0; + while(clancolorIndex) { + clan++; + } + if(clan==clanCount) { + newClan = true; + clanCount++; + clanColors[clan] = team->colorIndex; + } + + // If shared ammo is active, only add an ammo store for the first team in each clan. + bool noAmmoStore = sharedAmmo&&!newClan; + error |= flib_ipc_append_addteam(tempvector, setup->teamlist->teams[i], perHogAmmo, noAmmoStore); + } + } + free(clanColors); + } + error |= flib_ipc_append_message(tempvector, "!"); + + if(!error) { + // Message created, now we can copy everything. + flib_constbuffer constbuf = flib_vector_as_constbuffer(tempvector); + if(!flib_vector_append(vec, constbuf.data, constbuf.size)) { + result = 0; + } + } + } + return result; +} diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/ipc/ipcprotocol.h --- a/project_files/frontlib/ipc/ipcprotocol.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/ipc/ipcprotocol.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,93 +1,93 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef IPCPROTOCOL_H_ -#define IPCPROTOCOL_H_ - -#include "../util/buffer.h" -#include "../model/map.h" -#include "../model/team.h" -#include "../model/scheme.h" -#include "../model/gamesetup.h" - -#include - -/** - * Create a message in the IPC protocol format and add it to - * the vector. Use a format string and extra parameters as with printf. - * - * Returns nonzero if something goes wrong. In that case the buffer - * contents are unaffected. - */ -int flib_ipc_append_message(flib_vector *vec, const char *fmt, ...); - -/** - * Append IPC messages to the buffer that configure the engine for - * this map. - * - * Unfortunately the engine needs a slightly different configuration - * for generating a map preview. - * - * Returns nonzero if something goes wrong. In that case the buffer - * contents are unaffected. - */ -int flib_ipc_append_mapconf(flib_vector *vec, const flib_map *map, bool mappreview); - -/** - * Append a seed message to the buffer. - * - * Returns nonzero if something goes wrong. In that case the buffer - * contents are unaffected. - */ -int flib_ipc_append_seed(flib_vector *vec, const char *seed); - -/** - * Append a script to the buffer (e.g. "Missions/Training/Basic_Training_-_Bazooka.lua") - * - * Returns nonzero if something goes wrong. In that case the buffer - * contents are unaffected. - */ -int flib_ipc_append_script(flib_vector *vec, const char *script); - -/** - * Append a game style to the buffer. (e.g. "Capture the Flag") - * - * Returns nonzero if something goes wrong. In that case the buffer - * contents are unaffected. - */ -int flib_ipc_append_style(flib_vector *vec, const char *style); - -/** - * Append the game scheme to the buffer. - * - * Returns nonzero if something goes wrong. In that case the buffer - * contents are unaffected. - */ -int flib_ipc_append_gamescheme(flib_vector *vec, const flib_scheme *scheme); - -/** - * Append the entire game config to the buffer (including the final "!" that marks the - * end of configuration data for the engine) - * - * Returns nonzero if something goes wrong. In that case the buffer - * contents are unaffected. - */ -int flib_ipc_append_fullconfig(flib_vector *vec, const flib_gamesetup *setup, bool netgame); - -#endif /* IPCPROTOCOL_H_ */ +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef IPCPROTOCOL_H_ +#define IPCPROTOCOL_H_ + +#include "../util/buffer.h" +#include "../model/map.h" +#include "../model/team.h" +#include "../model/scheme.h" +#include "../model/gamesetup.h" + +#include + +/** + * Create a message in the IPC protocol format and add it to + * the vector. Use a format string and extra parameters as with printf. + * + * Returns nonzero if something goes wrong. In that case the buffer + * contents are unaffected. + */ +int flib_ipc_append_message(flib_vector *vec, const char *fmt, ...); + +/** + * Append IPC messages to the buffer that configure the engine for + * this map. + * + * Unfortunately the engine needs a slightly different configuration + * for generating a map preview. + * + * Returns nonzero if something goes wrong. In that case the buffer + * contents are unaffected. + */ +int flib_ipc_append_mapconf(flib_vector *vec, const flib_map *map, bool mappreview); + +/** + * Append a seed message to the buffer. + * + * Returns nonzero if something goes wrong. In that case the buffer + * contents are unaffected. + */ +int flib_ipc_append_seed(flib_vector *vec, const char *seed); + +/** + * Append a script to the buffer (e.g. "Missions/Training/Basic_Training_-_Bazooka.lua") + * + * Returns nonzero if something goes wrong. In that case the buffer + * contents are unaffected. + */ +int flib_ipc_append_script(flib_vector *vec, const char *script); + +/** + * Append a game style to the buffer. (e.g. "Capture the Flag") + * + * Returns nonzero if something goes wrong. In that case the buffer + * contents are unaffected. + */ +int flib_ipc_append_style(flib_vector *vec, const char *style); + +/** + * Append the game scheme to the buffer. + * + * Returns nonzero if something goes wrong. In that case the buffer + * contents are unaffected. + */ +int flib_ipc_append_gamescheme(flib_vector *vec, const flib_scheme *scheme); + +/** + * Append the entire game config to the buffer (including the final "!" that marks the + * end of configuration data for the engine) + * + * Returns nonzero if something goes wrong. In that case the buffer + * contents are unaffected. + */ +int flib_ipc_append_fullconfig(flib_vector *vec, const flib_gamesetup *setup, bool netgame); + +#endif /* IPCPROTOCOL_H_ */ diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/ipc/mapconn.c --- a/project_files/frontlib/ipc/mapconn.c Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/ipc/mapconn.c Tue Nov 10 20:43:13 2015 +0100 @@ -1,196 +1,196 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "mapconn.h" -#include "ipcbase.h" -#include "ipcprotocol.h" - -#include "../util/logging.h" -#include "../util/buffer.h" -#include "../util/util.h" - -#include - -typedef enum { - AWAIT_CONNECTION, - AWAIT_REPLY, - AWAIT_CLOSE, - FINISHED -} mapconn_state; - -struct _flib_mapconn { - uint8_t mapBuffer[IPCBASE_MAPMSG_BYTES]; - flib_ipcbase *ipcBase; - flib_vector *configBuffer; - - mapconn_state progress; - - void (*onSuccessCb)(void*, const uint8_t*, int); - void *onSuccessCtx; - - void (*onFailureCb)(void*, const char*); - void *onFailureCtx; - - bool running; - bool destroyRequested; -}; - -static void noop_handleSuccess(void *context, const uint8_t *bitmap, int numHedgehogs) {} -static void noop_handleFailure(void *context, const char *errormessage) {} - -static void clearCallbacks(flib_mapconn *conn) { - conn->onSuccessCb = &noop_handleSuccess; - conn->onFailureCb = &noop_handleFailure; -} - -static flib_vector *createConfigBuffer(const flib_map *mapdesc) { - flib_vector *result = NULL; - flib_vector *tempbuffer = flib_vector_create(); - if(tempbuffer) { - bool error = false; - error |= flib_ipc_append_mapconf(tempbuffer, mapdesc, true); - error |= flib_ipc_append_message(tempbuffer, "!"); - if(!error) { - result = tempbuffer; - tempbuffer = NULL; - } - } - flib_vector_destroy(tempbuffer); - return result; -} - -flib_mapconn *flib_mapconn_create(const flib_map *mapdesc) { - if(log_badargs_if(mapdesc==NULL)) { - return NULL; - } - flib_mapconn *result = NULL; - flib_mapconn *tempConn = flib_calloc(1, sizeof(flib_mapconn)); - if(tempConn) { - tempConn->ipcBase = flib_ipcbase_create(); - tempConn->configBuffer = createConfigBuffer(mapdesc); - if(tempConn->ipcBase && tempConn->configBuffer) { - tempConn->progress = AWAIT_CONNECTION; - clearCallbacks(tempConn); - result = tempConn; - tempConn = NULL; - } - } - flib_mapconn_destroy(tempConn); - return result; -} - -void flib_mapconn_destroy(flib_mapconn *conn) { - if(conn) { - if(conn->running) { - /* - * The function was called from a callback, so the tick function is still running - * and we delay the actual destruction. We ensure no further callbacks will be - * sent to prevent surprises. - */ - clearCallbacks(conn); - conn->destroyRequested = true; - } else { - flib_ipcbase_destroy(conn->ipcBase); - flib_vector_destroy(conn->configBuffer); - free(conn); - } - } -} - -int flib_mapconn_getport(flib_mapconn *conn) { - if(log_badargs_if(conn==NULL)) { - return 0; - } - return flib_ipcbase_port(conn->ipcBase); -} - -void flib_mapconn_onSuccess(flib_mapconn *conn, void (*callback)(void* context, const uint8_t *bitmap, int numHedgehogs), void *context) { - if(!log_badargs_if(conn==NULL)) { - conn->onSuccessCb = callback ? callback : &noop_handleSuccess; - conn->onSuccessCtx = context; - } -} - -void flib_mapconn_onFailure(flib_mapconn *conn, void (*callback)(void* context, const char *errormessage), void *context) { - if(!log_badargs_if(conn==NULL)) { - conn->onFailureCb = callback ? callback : &noop_handleFailure; - conn->onFailureCtx = context; - } -} - -static void flib_mapconn_wrappedtick(flib_mapconn *conn) { - if(conn->progress == AWAIT_CONNECTION) { - flib_ipcbase_accept(conn->ipcBase); - switch(flib_ipcbase_state(conn->ipcBase)) { - case IPC_CONNECTED: - { - flib_constbuffer configBuffer = flib_vector_as_constbuffer(conn->configBuffer); - if(flib_ipcbase_send_raw(conn->ipcBase, configBuffer.data, configBuffer.size)) { - conn->progress = FINISHED; - conn->onFailureCb(conn->onFailureCtx, "Error sending map information to the engine."); - return; - } else { - conn->progress = AWAIT_REPLY; - } - } - break; - case IPC_NOT_CONNECTED: - conn->progress = FINISHED; - conn->onFailureCb(conn->onFailureCtx, "Engine connection closed unexpectedly."); - return; - default: - break; - } - } - - if(conn->progress == AWAIT_REPLY) { - if(flib_ipcbase_recv_map(conn->ipcBase, conn->mapBuffer) >= 0) { - conn->progress = AWAIT_CLOSE; - } else if(flib_ipcbase_state(conn->ipcBase) != IPC_CONNECTED) { - conn->progress = FINISHED; - conn->onFailureCb(conn->onSuccessCtx, "Engine connection closed unexpectedly."); - return; - } - } - - if(conn->progress == AWAIT_CLOSE) { - // Just do throwaway reads so we find out when the engine disconnects - uint8_t buf[256]; - flib_ipcbase_recv_message(conn->ipcBase, buf); - if(flib_ipcbase_state(conn->ipcBase) != IPC_CONNECTED) { - conn->progress = FINISHED; - conn->onSuccessCb(conn->onSuccessCtx, conn->mapBuffer, conn->mapBuffer[IPCBASE_MAPMSG_BYTES-1]); - return; - } - } -} - -void flib_mapconn_tick(flib_mapconn *conn) { - if(!log_badargs_if(conn==NULL) - && !log_w_if(conn->running, "Call to flib_mapconn_tick from a callback") - && !log_w_if(conn->progress == FINISHED, "We are already done.")) { - conn->running = true; - flib_mapconn_wrappedtick(conn); - conn->running = false; - - if(conn->destroyRequested) { - flib_mapconn_destroy(conn); - } - } -} +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mapconn.h" +#include "ipcbase.h" +#include "ipcprotocol.h" + +#include "../util/logging.h" +#include "../util/buffer.h" +#include "../util/util.h" + +#include + +typedef enum { + AWAIT_CONNECTION, + AWAIT_REPLY, + AWAIT_CLOSE, + FINISHED +} mapconn_state; + +struct _flib_mapconn { + uint8_t mapBuffer[IPCBASE_MAPMSG_BYTES]; + flib_ipcbase *ipcBase; + flib_vector *configBuffer; + + mapconn_state progress; + + void (*onSuccessCb)(void*, const uint8_t*, int); + void *onSuccessCtx; + + void (*onFailureCb)(void*, const char*); + void *onFailureCtx; + + bool running; + bool destroyRequested; +}; + +static void noop_handleSuccess(void *context, const uint8_t *bitmap, int numHedgehogs) {} +static void noop_handleFailure(void *context, const char *errormessage) {} + +static void clearCallbacks(flib_mapconn *conn) { + conn->onSuccessCb = &noop_handleSuccess; + conn->onFailureCb = &noop_handleFailure; +} + +static flib_vector *createConfigBuffer(const flib_map *mapdesc) { + flib_vector *result = NULL; + flib_vector *tempbuffer = flib_vector_create(); + if(tempbuffer) { + bool error = false; + error |= flib_ipc_append_mapconf(tempbuffer, mapdesc, true); + error |= flib_ipc_append_message(tempbuffer, "!"); + if(!error) { + result = tempbuffer; + tempbuffer = NULL; + } + } + flib_vector_destroy(tempbuffer); + return result; +} + +flib_mapconn *flib_mapconn_create(const flib_map *mapdesc) { + if(log_badargs_if(mapdesc==NULL)) { + return NULL; + } + flib_mapconn *result = NULL; + flib_mapconn *tempConn = flib_calloc(1, sizeof(flib_mapconn)); + if(tempConn) { + tempConn->ipcBase = flib_ipcbase_create(); + tempConn->configBuffer = createConfigBuffer(mapdesc); + if(tempConn->ipcBase && tempConn->configBuffer) { + tempConn->progress = AWAIT_CONNECTION; + clearCallbacks(tempConn); + result = tempConn; + tempConn = NULL; + } + } + flib_mapconn_destroy(tempConn); + return result; +} + +void flib_mapconn_destroy(flib_mapconn *conn) { + if(conn) { + if(conn->running) { + /* + * The function was called from a callback, so the tick function is still running + * and we delay the actual destruction. We ensure no further callbacks will be + * sent to prevent surprises. + */ + clearCallbacks(conn); + conn->destroyRequested = true; + } else { + flib_ipcbase_destroy(conn->ipcBase); + flib_vector_destroy(conn->configBuffer); + free(conn); + } + } +} + +int flib_mapconn_getport(flib_mapconn *conn) { + if(log_badargs_if(conn==NULL)) { + return 0; + } + return flib_ipcbase_port(conn->ipcBase); +} + +void flib_mapconn_onSuccess(flib_mapconn *conn, void (*callback)(void* context, const uint8_t *bitmap, int numHedgehogs), void *context) { + if(!log_badargs_if(conn==NULL)) { + conn->onSuccessCb = callback ? callback : &noop_handleSuccess; + conn->onSuccessCtx = context; + } +} + +void flib_mapconn_onFailure(flib_mapconn *conn, void (*callback)(void* context, const char *errormessage), void *context) { + if(!log_badargs_if(conn==NULL)) { + conn->onFailureCb = callback ? callback : &noop_handleFailure; + conn->onFailureCtx = context; + } +} + +static void flib_mapconn_wrappedtick(flib_mapconn *conn) { + if(conn->progress == AWAIT_CONNECTION) { + flib_ipcbase_accept(conn->ipcBase); + switch(flib_ipcbase_state(conn->ipcBase)) { + case IPC_CONNECTED: + { + flib_constbuffer configBuffer = flib_vector_as_constbuffer(conn->configBuffer); + if(flib_ipcbase_send_raw(conn->ipcBase, configBuffer.data, configBuffer.size)) { + conn->progress = FINISHED; + conn->onFailureCb(conn->onFailureCtx, "Error sending map information to the engine."); + return; + } else { + conn->progress = AWAIT_REPLY; + } + } + break; + case IPC_NOT_CONNECTED: + conn->progress = FINISHED; + conn->onFailureCb(conn->onFailureCtx, "Engine connection closed unexpectedly."); + return; + default: + break; + } + } + + if(conn->progress == AWAIT_REPLY) { + if(flib_ipcbase_recv_map(conn->ipcBase, conn->mapBuffer) >= 0) { + conn->progress = AWAIT_CLOSE; + } else if(flib_ipcbase_state(conn->ipcBase) != IPC_CONNECTED) { + conn->progress = FINISHED; + conn->onFailureCb(conn->onSuccessCtx, "Engine connection closed unexpectedly."); + return; + } + } + + if(conn->progress == AWAIT_CLOSE) { + // Just do throwaway reads so we find out when the engine disconnects + uint8_t buf[256]; + flib_ipcbase_recv_message(conn->ipcBase, buf); + if(flib_ipcbase_state(conn->ipcBase) != IPC_CONNECTED) { + conn->progress = FINISHED; + conn->onSuccessCb(conn->onSuccessCtx, conn->mapBuffer, conn->mapBuffer[IPCBASE_MAPMSG_BYTES-1]); + return; + } + } +} + +void flib_mapconn_tick(flib_mapconn *conn) { + if(!log_badargs_if(conn==NULL) + && !log_w_if(conn->running, "Call to flib_mapconn_tick from a callback") + && !log_w_if(conn->progress == FINISHED, "We are already done.")) { + conn->running = true; + flib_mapconn_wrappedtick(conn); + conn->running = false; + + if(conn->destroyRequested) { + flib_mapconn_destroy(conn); + } + } +} diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/ipc/mapconn.h --- a/project_files/frontlib/ipc/mapconn.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/ipc/mapconn.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,116 +1,116 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * Functions for querying a map preview from the engine, which includes both a two-color image - * and the number of hogs this map is suitable for. - * - * The general usage is to first create a mapconn object by calling flib_mapconn_create. - * That will cause the frontlib to listen on a random port which can be queried using - * flib_mapconn_getport(). You should also register your callback functions right at the start - * to ensure you don't miss any callbacks. - * - * Next, start the engine (that part is up to you) with the appropriate command line arguments - * for a map preview request. - * - * In order to allow the mapconn to run, you should regularly call flib_mapconn_tick(), which - * performs network I/O and calls your callbacks if the map has been generated or an error - * has occurred. Once either the onSuccess or onFailure callback is called, you should destroy - * the mapconn and stop calling tick(). - */ - -#ifndef IPC_MAPCONN_H_ -#define IPC_MAPCONN_H_ - -#include "../model/map.h" - -#include - -#define MAPIMAGE_WIDTH 256 -#define MAPIMAGE_HEIGHT 128 -#define MAPIMAGE_BYTES (MAPIMAGE_WIDTH/8*MAPIMAGE_HEIGHT) - -typedef struct _flib_mapconn flib_mapconn; - -/** - * Start a new map rendering connection (mapconn). This means a listening socket - * will be started on a random unused port, waiting for a connection from the - * engine process. Once this connection is established, the required information - * will be sent to the engine, and the reply is read. - * - * The map must be a regular, maze or drawn map - for a preview of a named map, - * use the preview images in the map's directory, and for the hog count read the - * map information (e.g. using flib_mapcfg_read). - * - * No NULL parameters allowed, returns NULL on failure. - * Use flib_mapconn_destroy to free the returned object. - */ -flib_mapconn *flib_mapconn_create(const flib_map *mapdesc); - -/** - * Destroy the mapconn object. Passing NULL is allowed and does nothing. - * flib_mapconn_destroy may be called from inside a callback function. - */ -void flib_mapconn_destroy(flib_mapconn *conn); - -/** - * Returns the port on which the mapconn is listening. Only fails if you - * pass NULL (not allowed), in that case 0 is returned. - */ -int flib_mapconn_getport(flib_mapconn *conn); - -/** - * Set a callback which will receive the rendered map if the rendering succeeds. - * - * Expected callback signature: - * void handleSuccess(void *context, const uint8_t *bitmap, int numHedgehogs) - * - * The context passed to the callback is the same pointer you provided when - * registering the callback. bitmap is a pointer to a buffer of size MAPIMAGE_BYTES - * containing a bit-packed image of size MAPIMAGE_WIDTH * MAPIMAGE_HEIGHT. - * numHedgehogs is the number of hogs that fit on this map. - * - * The bitmap pointer passed to the callback belongs to the caller, - * so it should not be stored elsewhere. Note that it remains valid - * inside the callback method even if flib_mapconn_destroy is called. - */ -void flib_mapconn_onSuccess(flib_mapconn *conn, void (*callback)(void* context, const uint8_t *bitmap, int numHedgehogs), void *context); - -/** - * Set a callback which will receive an error message if rendering fails. - * - * Expected callback signature: - * void handleFailure(void *context, const char *errormessage) - * - * The context passed to the callback is the same pointer you provided when - * registering the callback. - * - * The error message passed to the callback belongs to the caller, - * so it should not be stored elsewhere. Note that it remains valid - * inside the callback method even if flib_mapconn_destroy is called. - */ -void flib_mapconn_onFailure(flib_mapconn *conn, void (*callback)(void* context, const char *errormessage), void *context); - -/** - * Perform I/O operations and call callbacks if something interesting happens. - * Should be called regularly. - */ -void flib_mapconn_tick(flib_mapconn *conn); - -#endif +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * Functions for querying a map preview from the engine, which includes both a two-color image + * and the number of hogs this map is suitable for. + * + * The general usage is to first create a mapconn object by calling flib_mapconn_create. + * That will cause the frontlib to listen on a random port which can be queried using + * flib_mapconn_getport(). You should also register your callback functions right at the start + * to ensure you don't miss any callbacks. + * + * Next, start the engine (that part is up to you) with the appropriate command line arguments + * for a map preview request. + * + * In order to allow the mapconn to run, you should regularly call flib_mapconn_tick(), which + * performs network I/O and calls your callbacks if the map has been generated or an error + * has occurred. Once either the onSuccess or onFailure callback is called, you should destroy + * the mapconn and stop calling tick(). + */ + +#ifndef IPC_MAPCONN_H_ +#define IPC_MAPCONN_H_ + +#include "../model/map.h" + +#include + +#define MAPIMAGE_WIDTH 256 +#define MAPIMAGE_HEIGHT 128 +#define MAPIMAGE_BYTES (MAPIMAGE_WIDTH/8*MAPIMAGE_HEIGHT) + +typedef struct _flib_mapconn flib_mapconn; + +/** + * Start a new map rendering connection (mapconn). This means a listening socket + * will be started on a random unused port, waiting for a connection from the + * engine process. Once this connection is established, the required information + * will be sent to the engine, and the reply is read. + * + * The map must be a regular, maze or drawn map - for a preview of a named map, + * use the preview images in the map's directory, and for the hog count read the + * map information (e.g. using flib_mapcfg_read). + * + * No NULL parameters allowed, returns NULL on failure. + * Use flib_mapconn_destroy to free the returned object. + */ +flib_mapconn *flib_mapconn_create(const flib_map *mapdesc); + +/** + * Destroy the mapconn object. Passing NULL is allowed and does nothing. + * flib_mapconn_destroy may be called from inside a callback function. + */ +void flib_mapconn_destroy(flib_mapconn *conn); + +/** + * Returns the port on which the mapconn is listening. Only fails if you + * pass NULL (not allowed), in that case 0 is returned. + */ +int flib_mapconn_getport(flib_mapconn *conn); + +/** + * Set a callback which will receive the rendered map if the rendering succeeds. + * + * Expected callback signature: + * void handleSuccess(void *context, const uint8_t *bitmap, int numHedgehogs) + * + * The context passed to the callback is the same pointer you provided when + * registering the callback. bitmap is a pointer to a buffer of size MAPIMAGE_BYTES + * containing a bit-packed image of size MAPIMAGE_WIDTH * MAPIMAGE_HEIGHT. + * numHedgehogs is the number of hogs that fit on this map. + * + * The bitmap pointer passed to the callback belongs to the caller, + * so it should not be stored elsewhere. Note that it remains valid + * inside the callback method even if flib_mapconn_destroy is called. + */ +void flib_mapconn_onSuccess(flib_mapconn *conn, void (*callback)(void* context, const uint8_t *bitmap, int numHedgehogs), void *context); + +/** + * Set a callback which will receive an error message if rendering fails. + * + * Expected callback signature: + * void handleFailure(void *context, const char *errormessage) + * + * The context passed to the callback is the same pointer you provided when + * registering the callback. + * + * The error message passed to the callback belongs to the caller, + * so it should not be stored elsewhere. Note that it remains valid + * inside the callback method even if flib_mapconn_destroy is called. + */ +void flib_mapconn_onFailure(flib_mapconn *conn, void (*callback)(void* context, const char *errormessage), void *context); + +/** + * Perform I/O operations and call callbacks if something interesting happens. + * Should be called regularly. + */ +void flib_mapconn_tick(flib_mapconn *conn); + +#endif diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/md5/md5.c --- a/project_files/frontlib/md5/md5.c Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/md5/md5.c Tue Nov 10 20:43:13 2015 +0100 @@ -27,7 +27,7 @@ This code implements the MD5 Algorithm defined in RFC 1321, whose text is available at - http://www.ietf.org/rfc/rfc1321.txt + http://www.ietf.org/rfc/rfc1321.txt The code is derived from the text of the RFC, including the test suite (section A.5) but excluding the rest of Appendix A. It does not include any code or documentation that is identified in the RFC as being @@ -38,14 +38,14 @@ that follows (in reverse chronological order): 2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order - either statically or dynamically; added missing #include - in library. + either statically or dynamically; added missing #include + in library. 2002-03-11 lpd Corrected argument list for main(), and added int return - type, in test program and T value program. + type, in test program and T value program. 2002-02-21 lpd Added missing #include in test program. 2000-07-03 lpd Patched to eliminate warnings about "constant is - unsigned in ANSI C, signed in traditional"; made test program - self-checking. + unsigned in ANSI C, signed in traditional"; made test program + self-checking. 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). 1999-05-03 lpd Original version. @@ -54,7 +54,7 @@ #include "md5.h" #include -#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */ +#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */ #ifdef ARCH_IS_BIG_ENDIAN # define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1) #else @@ -132,8 +132,8 @@ md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) { md5_word_t - a = pms->abcd[0], b = pms->abcd[1], - c = pms->abcd[2], d = pms->abcd[3]; + a = pms->abcd[0], b = pms->abcd[1], + c = pms->abcd[2], d = pms->abcd[3]; md5_word_t t; #if BYTE_ORDER > 0 /* Define storage only for big-endian CPUs. */ @@ -146,51 +146,51 @@ { #if BYTE_ORDER == 0 - /* - * Determine dynamically whether this is a big-endian or - * little-endian machine, since we can use a more efficient - * algorithm on the latter. - */ - static const int w = 1; + /* + * Determine dynamically whether this is a big-endian or + * little-endian machine, since we can use a more efficient + * algorithm on the latter. + */ + static const int w = 1; - if (*((const md5_byte_t *)&w)) /* dynamic little-endian */ + if (*((const md5_byte_t *)&w)) /* dynamic little-endian */ #endif -#if BYTE_ORDER <= 0 /* little-endian */ - { - /* - * On little-endian machines, we can process properly aligned - * data without copying it. - */ - if (!((data - (const md5_byte_t *)0) & 3)) { - /* data are properly aligned */ - X = (const md5_word_t *)data; - } else { - /* not aligned */ - memcpy(xbuf, data, 64); - X = xbuf; - } - } +#if BYTE_ORDER <= 0 /* little-endian */ + { + /* + * On little-endian machines, we can process properly aligned + * data without copying it. + */ + if (!((data - (const md5_byte_t *)0) & 3)) { + /* data are properly aligned */ + X = (const md5_word_t *)data; + } else { + /* not aligned */ + memcpy(xbuf, data, 64); + X = xbuf; + } + } #endif #if BYTE_ORDER == 0 - else /* dynamic big-endian */ + else /* dynamic big-endian */ #endif -#if BYTE_ORDER >= 0 /* big-endian */ - { - /* - * On big-endian machines, we must arrange the bytes in the - * right order. - */ - const md5_byte_t *xp = data; - int i; +#if BYTE_ORDER >= 0 /* big-endian */ + { + /* + * On big-endian machines, we must arrange the bytes in the + * right order. + */ + const md5_byte_t *xp = data; + int i; # if BYTE_ORDER == 0 - X = xbuf; /* (dynamic only) */ + X = xbuf; /* (dynamic only) */ # else -# define xbuf X /* (static only) */ +# define xbuf X /* (static only) */ # endif - for (i = 0; i < 16; ++i, xp += 4) - xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); - } + for (i = 0; i < 16; ++i, xp += 4) + xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); + } #endif } @@ -328,54 +328,54 @@ md5_word_t nbits = (md5_word_t)(nbytes << 3); if (nbytes <= 0) - return; + return; /* Update the message length. */ pms->count[1] += nbytes >> 29; pms->count[0] += nbits; if (pms->count[0] < nbits) - pms->count[1]++; + pms->count[1]++; /* Process an initial partial block. */ if (offset) { - int copy = (offset + nbytes > 64 ? 64 - offset : nbytes); + int copy = (offset + nbytes > 64 ? 64 - offset : nbytes); - memcpy(pms->buf + offset, p, copy); - if (offset + copy < 64) - return; - p += copy; - left -= copy; - md5_process(pms, pms->buf); + memcpy(pms->buf + offset, p, copy); + if (offset + copy < 64) + return; + p += copy; + left -= copy; + md5_process(pms, pms->buf); } /* Process full blocks. */ for (; left >= 64; p += 64, left -= 64) - md5_process(pms, p); + md5_process(pms, p); /* Process a final partial block. */ if (left) - memcpy(pms->buf, p, left); + memcpy(pms->buf, p, left); } void md5_finish(md5_state_t *pms, md5_byte_t digest[16]) { static const md5_byte_t pad[64] = { - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; md5_byte_t data[8]; int i; /* Save the length before padding. */ for (i = 0; i < 8; ++i) - data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3)); + data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3)); /* Pad to 56 bytes mod 64. */ md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); /* Append the length. */ md5_append(pms, data, 8); for (i = 0; i < 16; ++i) - digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); + digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); } diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/md5/md5.h --- a/project_files/frontlib/md5/md5.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/md5/md5.h Tue Nov 10 20:43:13 2015 +0100 @@ -27,7 +27,7 @@ This code implements the MD5 Algorithm defined in RFC 1321, whose text is available at - http://www.ietf.org/rfc/rfc1321.txt + http://www.ietf.org/rfc/rfc1321.txt The code is derived from the text of the RFC, including the test suite (section A.5) but excluding the rest of Appendix A. It does not include any code or documentation that is identified in the RFC as being @@ -38,12 +38,12 @@ that follows (in reverse chronological order): 2002-04-13 lpd Removed support for non-ANSI compilers; removed - references to Ghostscript; clarified derivation from RFC 1321; - now handles byte order either statically or dynamically. + references to Ghostscript; clarified derivation from RFC 1321; + now handles byte order either statically or dynamically. 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); - added conditionalization for C++ compilation from Martin - Purschke . + added conditionalization for C++ compilation from Martin + Purschke . 1999-05-03 lpd Original version. */ @@ -65,13 +65,13 @@ /*! Define the state of the MD5 Algorithm. */ typedef struct md5_state_s { - md5_word_t count[2]; /*! message length in bits, lsw first */ - md5_word_t abcd[4]; /*! digest buffer */ - md5_byte_t buf[64]; /*! accumulate block */ + md5_word_t count[2]; /*! message length in bits, lsw first */ + md5_word_t abcd[4]; /*! digest buffer */ + md5_byte_t buf[64]; /*! accumulate block */ } md5_state_t; #ifdef __cplusplus -extern "C" +extern "C" { #endif diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/model/gamesetup.c --- a/project_files/frontlib/model/gamesetup.c Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/model/gamesetup.c Tue Nov 10 20:43:13 2015 +0100 @@ -1,55 +1,55 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "gamesetup.h" -#include "../util/util.h" - -#include - -void flib_gamesetup_destroy(flib_gamesetup *gamesetup) { - if(gamesetup) { - free(gamesetup->style); - flib_scheme_destroy(gamesetup->gamescheme); - flib_map_destroy(gamesetup->map); - flib_teamlist_destroy(gamesetup->teamlist); - free(gamesetup); - } -} - -flib_gamesetup *flib_gamesetup_copy(const flib_gamesetup *setup) { - if(!setup) { - return NULL; - } - - flib_gamesetup *result = flib_calloc(1, sizeof(flib_gamesetup)); - if(result) { - result->style = flib_strdupnull(setup->style); - result->gamescheme = flib_scheme_copy(setup->gamescheme); - result->map = flib_map_copy(setup->map); - result->teamlist = flib_teamlist_copy(setup->teamlist); - if((setup->style && !result->style) - || (setup->gamescheme && !result->gamescheme) - || (setup->map && !result->map) - || (setup->teamlist && !result->teamlist)) { - flib_gamesetup_destroy(result); - result = NULL; - } - } - return result; -} +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "gamesetup.h" +#include "../util/util.h" + +#include + +void flib_gamesetup_destroy(flib_gamesetup *gamesetup) { + if(gamesetup) { + free(gamesetup->style); + flib_scheme_destroy(gamesetup->gamescheme); + flib_map_destroy(gamesetup->map); + flib_teamlist_destroy(gamesetup->teamlist); + free(gamesetup); + } +} + +flib_gamesetup *flib_gamesetup_copy(const flib_gamesetup *setup) { + if(!setup) { + return NULL; + } + + flib_gamesetup *result = flib_calloc(1, sizeof(flib_gamesetup)); + if(result) { + result->style = flib_strdupnull(setup->style); + result->gamescheme = flib_scheme_copy(setup->gamescheme); + result->map = flib_map_copy(setup->map); + result->teamlist = flib_teamlist_copy(setup->teamlist); + if((setup->style && !result->style) + || (setup->gamescheme && !result->gamescheme) + || (setup->map && !result->map) + || (setup->teamlist && !result->teamlist)) { + flib_gamesetup_destroy(result); + result = NULL; + } + } + return result; +} diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/model/gamesetup.h --- a/project_files/frontlib/model/gamesetup.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/model/gamesetup.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,47 +1,47 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * A complete game configuration that contains all settings the engine needs to start a - * local or networked game. - */ - -#ifndef MODEL_GAMESETUP_H_ -#define MODEL_GAMESETUP_H_ - -#include "scheme.h" -#include "weapon.h" -#include "map.h" -#include "teamlist.h" - -typedef struct { - char *style; //!< e.g. "Capture the Flag" - flib_scheme *gamescheme; - flib_map *map; - flib_teamlist *teamlist; -} flib_gamesetup; - -void flib_gamesetup_destroy(flib_gamesetup *gamesetup); - -/** - * Deep-copy of the flib_gamesetup. - */ -flib_gamesetup *flib_gamesetup_copy(const flib_gamesetup *gamesetup); - -#endif +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * A complete game configuration that contains all settings the engine needs to start a + * local or networked game. + */ + +#ifndef MODEL_GAMESETUP_H_ +#define MODEL_GAMESETUP_H_ + +#include "scheme.h" +#include "weapon.h" +#include "map.h" +#include "teamlist.h" + +typedef struct { + char *style; //!< e.g. "Capture the Flag" + flib_scheme *gamescheme; + flib_map *map; + flib_teamlist *teamlist; +} flib_gamesetup; + +void flib_gamesetup_destroy(flib_gamesetup *gamesetup); + +/** + * Deep-copy of the flib_gamesetup. + */ +flib_gamesetup *flib_gamesetup_copy(const flib_gamesetup *gamesetup); + +#endif diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/model/map.c --- a/project_files/frontlib/model/map.c Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/model/map.c Tue Nov 10 20:43:13 2015 +0100 @@ -1,110 +1,110 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "map.h" - -#include "../util/inihelper.h" -#include "../util/util.h" -#include "../util/logging.h" - -#include - -flib_map *flib_map_create_regular(const char *seed, const char *theme, int templateFilter) { - if(log_badargs_if2(seed==NULL, theme==NULL)) { - return NULL; - } - flib_map newmap = {0}; - newmap.mapgen = MAPGEN_REGULAR; - newmap.name = "+rnd+"; - newmap.seed = (char*)seed; - newmap.theme = (char*)theme; - newmap.templateFilter = templateFilter; - return flib_map_copy(&newmap); -} - -flib_map *flib_map_create_maze(const char *seed, const char *theme, int mazeSize) { - if(log_badargs_if2(seed==NULL, theme==NULL)) { - return NULL; - } - flib_map newmap = {0}; - newmap.mapgen = MAPGEN_MAZE; - newmap.name = "+maze+"; - newmap.seed = (char*)seed; - newmap.theme = (char*)theme; - newmap.mazeSize = mazeSize; - return flib_map_copy(&newmap); -} - -flib_map *flib_map_create_named(const char *seed, const char *name) { - if(log_badargs_if2(seed==NULL, name==NULL)) { - return NULL; - } - flib_map newmap = {0}; - newmap.mapgen = MAPGEN_NAMED; - newmap.name = (char*)name; - newmap.seed = (char*)seed; - return flib_map_copy(&newmap); -} - -flib_map *flib_map_create_drawn(const char *seed, const char *theme, const uint8_t *drawData, size_t drawDataSize) { - if(log_badargs_if3(seed==NULL, theme==NULL, drawData==NULL)) { - return NULL; - } - flib_map newmap = {0}; - newmap.mapgen = MAPGEN_DRAWN; - newmap.name = "+drawn+"; - newmap.seed = (char*)seed; - newmap.theme = (char*)theme; - newmap.drawData = (uint8_t*) drawData; - newmap.drawDataSize = drawDataSize; - return flib_map_copy(&newmap); -} - -flib_map *flib_map_copy(const flib_map *map) { - flib_map *result = NULL; - if(map) { - flib_map *newmap = flib_calloc(1, sizeof(flib_map)); - if(newmap) { - newmap->mapgen = map->mapgen; - newmap->drawDataSize = map->drawDataSize; - newmap->drawData = flib_bufdupnull(map->drawData, map->drawDataSize); - newmap->mazeSize = map->mazeSize; - newmap->name = flib_strdupnull(map->name); - newmap->seed = flib_strdupnull(map->seed); - newmap->templateFilter = map->templateFilter; - newmap->theme = flib_strdupnull(map->theme); - if((newmap->drawData || !map->drawData) && (newmap->name || !map->name) && (newmap->seed || !map->seed) && (newmap->theme || !map->theme)) { - result = newmap; - newmap = NULL; - } - } - flib_map_destroy(newmap); - } - return result; -} - -void flib_map_destroy(flib_map *map) { - if(map) { - free(map->seed); - free(map->drawData); - free(map->name); - free(map->theme); - free(map); - } -} +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "map.h" + +#include "../util/inihelper.h" +#include "../util/util.h" +#include "../util/logging.h" + +#include + +flib_map *flib_map_create_regular(const char *seed, const char *theme, int templateFilter) { + if(log_badargs_if2(seed==NULL, theme==NULL)) { + return NULL; + } + flib_map newmap = {0}; + newmap.mapgen = MAPGEN_REGULAR; + newmap.name = "+rnd+"; + newmap.seed = (char*)seed; + newmap.theme = (char*)theme; + newmap.templateFilter = templateFilter; + return flib_map_copy(&newmap); +} + +flib_map *flib_map_create_maze(const char *seed, const char *theme, int mazeSize) { + if(log_badargs_if2(seed==NULL, theme==NULL)) { + return NULL; + } + flib_map newmap = {0}; + newmap.mapgen = MAPGEN_MAZE; + newmap.name = "+maze+"; + newmap.seed = (char*)seed; + newmap.theme = (char*)theme; + newmap.mazeSize = mazeSize; + return flib_map_copy(&newmap); +} + +flib_map *flib_map_create_named(const char *seed, const char *name) { + if(log_badargs_if2(seed==NULL, name==NULL)) { + return NULL; + } + flib_map newmap = {0}; + newmap.mapgen = MAPGEN_NAMED; + newmap.name = (char*)name; + newmap.seed = (char*)seed; + return flib_map_copy(&newmap); +} + +flib_map *flib_map_create_drawn(const char *seed, const char *theme, const uint8_t *drawData, size_t drawDataSize) { + if(log_badargs_if3(seed==NULL, theme==NULL, drawData==NULL)) { + return NULL; + } + flib_map newmap = {0}; + newmap.mapgen = MAPGEN_DRAWN; + newmap.name = "+drawn+"; + newmap.seed = (char*)seed; + newmap.theme = (char*)theme; + newmap.drawData = (uint8_t*) drawData; + newmap.drawDataSize = drawDataSize; + return flib_map_copy(&newmap); +} + +flib_map *flib_map_copy(const flib_map *map) { + flib_map *result = NULL; + if(map) { + flib_map *newmap = flib_calloc(1, sizeof(flib_map)); + if(newmap) { + newmap->mapgen = map->mapgen; + newmap->drawDataSize = map->drawDataSize; + newmap->drawData = flib_bufdupnull(map->drawData, map->drawDataSize); + newmap->mazeSize = map->mazeSize; + newmap->name = flib_strdupnull(map->name); + newmap->seed = flib_strdupnull(map->seed); + newmap->templateFilter = map->templateFilter; + newmap->theme = flib_strdupnull(map->theme); + if((newmap->drawData || !map->drawData) && (newmap->name || !map->name) && (newmap->seed || !map->seed) && (newmap->theme || !map->theme)) { + result = newmap; + newmap = NULL; + } + } + flib_map_destroy(newmap); + } + return result; +} + +void flib_map_destroy(flib_map *map) { + if(map) { + free(map->seed); + free(map->drawData); + free(map->name); + free(map->theme); + free(map); + } +} diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/model/map.h --- a/project_files/frontlib/model/map.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/model/map.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,114 +1,114 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef MODEL_MAP_H_ -#define MODEL_MAP_H_ - -#include -#include -#include - -#define MAPGEN_REGULAR 0 -#define MAPGEN_MAZE 1 -#define MAPGEN_DRAWN 2 -#define MAPGEN_NAMED 3 - -#define TEMPLATEFILTER_ALL 0 -#define TEMPLATEFILTER_SMALL 1 -#define TEMPLATEFILTER_MEDIUM 2 -#define TEMPLATEFILTER_LARGE 3 -#define TEMPLATEFILTER_CAVERN 4 -#define TEMPLATEFILTER_WACKY 5 - -#define MAZE_SIZE_SMALL_TUNNELS 0 -#define MAZE_SIZE_MEDIUM_TUNNELS 1 -#define MAZE_SIZE_LARGE_TUNNELS 2 -#define MAZE_SIZE_SMALL_ISLANDS 3 -#define MAZE_SIZE_MEDIUM_ISLANDS 4 -#define MAZE_SIZE_LARGE_ISLANDS 5 - -/** - * Data structure for defining a map. This contains the whole recipe to - * exactly recreate a particular map. - * - * The required fields depend on the map generator, see the comments - * at the struct for details. - */ -typedef struct { - int mapgen; //!< Always one of the MAPGEN_ constants - char *name; //!< The name of the map for MAPGEN_NAMED (e.g. "Cogs"), otherwise one of "+rnd+", "+maze+" or "+drawn+". - char *seed; //!< Used for all maps. This is a random seed for all (non-AI) entropy in the round. Typically a random UUID, but can be any string. - char *theme; //!< Used for all maps. This is the name of a directory in Data/Themes (e.g. "Beach") - uint8_t *drawData; //!< Used for MAPGEN_DRAWN - size_t drawDataSize; //!< Used for MAPGEN_DRAWN - int templateFilter; //!< Used for MAPGEN_REGULAR. One of the TEMPLATEFILTER_xxx constants. - int mazeSize; //!< Used for MAPGEN_MAZE. One of the MAZE_SIZE_xxx constants. -} flib_map; - -/** - * Create a generated map. theme should be the name of a - * directory in "Themes" and templateFilter should be one of the - * TEMPLATEFILTER_* constants, but this is not checked before - * passing it to the engine. - * - * Use flib_map_destroy to free the returned object. - * No NULL parameters allowed, returns NULL on failure. - */ -flib_map *flib_map_create_regular(const char *seed, const char *theme, int templateFilter); - -/** - * Create a generated maze-type map. theme should be the name of a - * directory in "Themes" and mazeSize should be one of the - * MAZE_SIZE_* constants, but this is not checked before - * passing it to the engine. - * - * Use flib_map_destroy to free the returned object. - * No NULL parameters allowed, returns NULL on failure. - */ -flib_map *flib_map_create_maze(const char *seed, const char *theme, int mazeSize); - -/** - * Create a map from the Maps-Directory. name should be the name of a - * directory in "Maps", but this is not checked before - * passing it to the engine. If this is a mission, the corresponding - * script is used automatically. - * - * Use flib_map_destroy to free the returned object. - * No NULL parameters allowed, returns NULL on failure. - */ -flib_map *flib_map_create_named(const char *seed, const char *name); - -/** - * Create a hand-drawn map. Use flib_map_destroy to free the returned object. - * No NULL parameters allowed, returns NULL on failure. - */ -flib_map *flib_map_create_drawn(const char *seed, const char *theme, const uint8_t *drawData, size_t drawDataSize); - -/** - * Create a deep copy of the map. Returns NULL on failure or if NULL was passed. - */ -flib_map *flib_map_copy(const flib_map *map); - -/** - * Decrease the reference count of the object and free it if this was the last reference. - */ -void flib_map_destroy(flib_map *map); - - -#endif +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef MODEL_MAP_H_ +#define MODEL_MAP_H_ + +#include +#include +#include + +#define MAPGEN_REGULAR 0 +#define MAPGEN_MAZE 1 +#define MAPGEN_DRAWN 2 +#define MAPGEN_NAMED 3 + +#define TEMPLATEFILTER_ALL 0 +#define TEMPLATEFILTER_SMALL 1 +#define TEMPLATEFILTER_MEDIUM 2 +#define TEMPLATEFILTER_LARGE 3 +#define TEMPLATEFILTER_CAVERN 4 +#define TEMPLATEFILTER_WACKY 5 + +#define MAZE_SIZE_SMALL_TUNNELS 0 +#define MAZE_SIZE_MEDIUM_TUNNELS 1 +#define MAZE_SIZE_LARGE_TUNNELS 2 +#define MAZE_SIZE_SMALL_ISLANDS 3 +#define MAZE_SIZE_MEDIUM_ISLANDS 4 +#define MAZE_SIZE_LARGE_ISLANDS 5 + +/** + * Data structure for defining a map. This contains the whole recipe to + * exactly recreate a particular map. + * + * The required fields depend on the map generator, see the comments + * at the struct for details. + */ +typedef struct { + int mapgen; //!< Always one of the MAPGEN_ constants + char *name; //!< The name of the map for MAPGEN_NAMED (e.g. "Cogs"), otherwise one of "+rnd+", "+maze+" or "+drawn+". + char *seed; //!< Used for all maps. This is a random seed for all (non-AI) entropy in the round. Typically a random UUID, but can be any string. + char *theme; //!< Used for all maps. This is the name of a directory in Data/Themes (e.g. "Beach") + uint8_t *drawData; //!< Used for MAPGEN_DRAWN + size_t drawDataSize; //!< Used for MAPGEN_DRAWN + int templateFilter; //!< Used for MAPGEN_REGULAR. One of the TEMPLATEFILTER_xxx constants. + int mazeSize; //!< Used for MAPGEN_MAZE. One of the MAZE_SIZE_xxx constants. +} flib_map; + +/** + * Create a generated map. theme should be the name of a + * directory in "Themes" and templateFilter should be one of the + * TEMPLATEFILTER_* constants, but this is not checked before + * passing it to the engine. + * + * Use flib_map_destroy to free the returned object. + * No NULL parameters allowed, returns NULL on failure. + */ +flib_map *flib_map_create_regular(const char *seed, const char *theme, int templateFilter); + +/** + * Create a generated maze-type map. theme should be the name of a + * directory in "Themes" and mazeSize should be one of the + * MAZE_SIZE_* constants, but this is not checked before + * passing it to the engine. + * + * Use flib_map_destroy to free the returned object. + * No NULL parameters allowed, returns NULL on failure. + */ +flib_map *flib_map_create_maze(const char *seed, const char *theme, int mazeSize); + +/** + * Create a map from the Maps-Directory. name should be the name of a + * directory in "Maps", but this is not checked before + * passing it to the engine. If this is a mission, the corresponding + * script is used automatically. + * + * Use flib_map_destroy to free the returned object. + * No NULL parameters allowed, returns NULL on failure. + */ +flib_map *flib_map_create_named(const char *seed, const char *name); + +/** + * Create a hand-drawn map. Use flib_map_destroy to free the returned object. + * No NULL parameters allowed, returns NULL on failure. + */ +flib_map *flib_map_create_drawn(const char *seed, const char *theme, const uint8_t *drawData, size_t drawDataSize); + +/** + * Create a deep copy of the map. Returns NULL on failure or if NULL was passed. + */ +flib_map *flib_map_copy(const flib_map *map); + +/** + * Decrease the reference count of the object and free it if this was the last reference. + */ +void flib_map_destroy(flib_map *map); + + +#endif diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/model/mapcfg.c --- a/project_files/frontlib/model/mapcfg.c Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/model/mapcfg.c Tue Nov 10 20:43:13 2015 +0100 @@ -1,64 +1,64 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "mapcfg.h" - -#include "../util/util.h" -#include "../util/logging.h" - -#include -#include -#include -#include - -void removeNewline(char *str) { - for(;*str;str++) { - if(*str=='\n' || *str=='\r') { - *str = 0; - return; - } - } -} - -int flib_mapcfg_read(const char *dataDirPath, const char *mapname, flib_mapcfg *out) { - int result = -1; - if(!log_badargs_if4(dataDirPath==NULL, mapname==NULL, out==NULL, flib_contains_dir_separator(mapname))) { - char *path = flib_asprintf("%sMaps/%s/map.cfg", dataDirPath, mapname); - if(path) { - FILE *file = fopen(path, "rb"); - if(!log_e_if(!file, "Unable to open map config file %s", path)) { - if(!log_e_if(!fgets(out->theme, sizeof(out->theme), file), "Error reading theme from %s", path)) { - removeNewline(out->theme); - char buf[64]; - if(fgets(buf, sizeof(buf), file)) { - removeNewline(buf); - errno = 0; - out->hogLimit = strtol(buf, NULL, 10); - result = !log_e_if(errno, "Invalid hoglimit in %s: %i", path, buf); - } else { - result = 0; - } - } - fclose(file); - } - } - free(path); - } - return result; -} +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mapcfg.h" + +#include "../util/util.h" +#include "../util/logging.h" + +#include +#include +#include +#include + +void removeNewline(char *str) { + for(;*str;str++) { + if(*str=='\n' || *str=='\r') { + *str = 0; + return; + } + } +} + +int flib_mapcfg_read(const char *dataDirPath, const char *mapname, flib_mapcfg *out) { + int result = -1; + if(!log_badargs_if4(dataDirPath==NULL, mapname==NULL, out==NULL, flib_contains_dir_separator(mapname))) { + char *path = flib_asprintf("%sMaps/%s/map.cfg", dataDirPath, mapname); + if(path) { + FILE *file = fopen(path, "rb"); + if(!log_e_if(!file, "Unable to open map config file %s", path)) { + if(!log_e_if(!fgets(out->theme, sizeof(out->theme), file), "Error reading theme from %s", path)) { + removeNewline(out->theme); + char buf[64]; + if(fgets(buf, sizeof(buf), file)) { + removeNewline(buf); + errno = 0; + out->hogLimit = strtol(buf, NULL, 10); + result = !log_e_if(errno, "Invalid hoglimit in %s: %i", path, buf); + } else { + result = 0; + } + } + fclose(file); + } + } + free(path); + } + return result; +} diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/model/mapcfg.h --- a/project_files/frontlib/model/mapcfg.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/model/mapcfg.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,38 +1,38 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/*! - * Data structure and functions for accessing the map.cfg of named maps. - */ - -#ifndef MAPCFG_H_ -#define MAPCFG_H_ - -typedef struct { - char theme[256]; - int hogLimit; -} flib_mapcfg; - -/** - * Read the map configuration for the map with this name. - * The dataDirPath must end in a path separator. - */ -int flib_mapcfg_read(const char *dataDirPath, const char *mapname, flib_mapcfg *out); - -#endif /* MAPCFG_H_ */ +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/*! + * Data structure and functions for accessing the map.cfg of named maps. + */ + +#ifndef MAPCFG_H_ +#define MAPCFG_H_ + +typedef struct { + char theme[256]; + int hogLimit; +} flib_mapcfg; + +/** + * Read the map configuration for the map with this name. + * The dataDirPath must end in a path separator. + */ +int flib_mapcfg_read(const char *dataDirPath, const char *mapname, flib_mapcfg *out); + +#endif /* MAPCFG_H_ */ diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/model/room.c --- a/project_files/frontlib/model/room.c Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/model/room.c Tue Nov 10 20:43:13 2015 +0100 @@ -1,34 +1,34 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "room.h" -#include "../util/logging.h" - -#include - -void flib_room_destroy(flib_room *room) { - if(room) { - free(room->map); - free(room->name); - free(room->owner); - free(room->scheme); - free(room->weapons); - free(room); - } -} +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "room.h" +#include "../util/logging.h" + +#include + +void flib_room_destroy(flib_room *room) { + if(room) { + free(room->map); + free(room->name); + free(room->owner); + free(room->scheme); + free(room->weapons); + free(room); + } +} diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/model/room.h --- a/project_files/frontlib/model/room.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/model/room.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,42 +1,42 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * Models the room information for the lobby roomlist. - */ - -#ifndef ROOM_H_ -#define ROOM_H_ - -#include - -typedef struct { - bool inProgress; //!< true if the game is running - char *name; - int playerCount; - int teamCount; - char *owner; - char *map; //!< This is either a map name, or one of +rnd+, +maze+ or +drawn+. - char *scheme; - char *weapons; -} flib_room; - -void flib_room_destroy(); - -#endif +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * Models the room information for the lobby roomlist. + */ + +#ifndef ROOM_H_ +#define ROOM_H_ + +#include + +typedef struct { + bool inProgress; //!< true if the game is running + char *name; + int playerCount; + int teamCount; + char *owner; + char *map; //!< This is either a map name, or one of +rnd+, +maze+ or +drawn+. + char *scheme; + char *weapons; +} flib_room; + +void flib_room_destroy(); + +#endif diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/model/scheme.c --- a/project_files/frontlib/model/scheme.c Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/model/scheme.c Tue Nov 10 20:43:13 2015 +0100 @@ -1,95 +1,95 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "scheme.h" - -#include "../util/inihelper.h" -#include "../util/logging.h" -#include "../util/util.h" - -#include -#include -#include -#include - -flib_scheme *flib_scheme_create(const char *schemeName) { - flib_scheme *result = flib_calloc(1, sizeof(flib_scheme)); - if(log_badargs_if(schemeName==NULL) || result==NULL) { - return NULL; - } - - result->name = flib_strdupnull(schemeName); - result->mods = flib_calloc(flib_meta.modCount, sizeof(*result->mods)); - result->settings = flib_calloc(flib_meta.settingCount, sizeof(*result->settings)); - - if(!result->mods || !result->settings || !result->name) { - flib_scheme_destroy(result); - return NULL; - } - - for(int i=0; isettings[i] = flib_meta.settings[i].def; - } - return result; -} - -flib_scheme *flib_scheme_copy(const flib_scheme *scheme) { - flib_scheme *result = NULL; - if(scheme) { - result = flib_scheme_create(scheme->name); - if(result) { - memcpy(result->mods, scheme->mods, flib_meta.modCount * sizeof(*scheme->mods)); - memcpy(result->settings, scheme->settings, flib_meta.settingCount * sizeof(*scheme->settings)); - } - } - return result; -} - -void flib_scheme_destroy(flib_scheme* scheme) { - if(scheme) { - free(scheme->mods); - free(scheme->settings); - free(scheme->name); - free(scheme); - } -} - -bool flib_scheme_get_mod(const flib_scheme *scheme, const char *name) { - if(!log_badargs_if2(scheme==NULL, name==NULL)) { - for(int i=0; imods[i]; - } - } - flib_log_e("Unable to find game mod %s", name); - } - return false; -} - -int flib_scheme_get_setting(const flib_scheme *scheme, const char *name, int def) { - if(!log_badargs_if2(scheme==NULL, name==NULL)) { - for(int i=0; isettings[i]; - } - } - flib_log_e("Unable to find game setting %s", name); - } - return def; -} +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "scheme.h" + +#include "../util/inihelper.h" +#include "../util/logging.h" +#include "../util/util.h" + +#include +#include +#include +#include + +flib_scheme *flib_scheme_create(const char *schemeName) { + flib_scheme *result = flib_calloc(1, sizeof(flib_scheme)); + if(log_badargs_if(schemeName==NULL) || result==NULL) { + return NULL; + } + + result->name = flib_strdupnull(schemeName); + result->mods = flib_calloc(flib_meta.modCount, sizeof(*result->mods)); + result->settings = flib_calloc(flib_meta.settingCount, sizeof(*result->settings)); + + if(!result->mods || !result->settings || !result->name) { + flib_scheme_destroy(result); + return NULL; + } + + for(int i=0; isettings[i] = flib_meta.settings[i].def; + } + return result; +} + +flib_scheme *flib_scheme_copy(const flib_scheme *scheme) { + flib_scheme *result = NULL; + if(scheme) { + result = flib_scheme_create(scheme->name); + if(result) { + memcpy(result->mods, scheme->mods, flib_meta.modCount * sizeof(*scheme->mods)); + memcpy(result->settings, scheme->settings, flib_meta.settingCount * sizeof(*scheme->settings)); + } + } + return result; +} + +void flib_scheme_destroy(flib_scheme* scheme) { + if(scheme) { + free(scheme->mods); + free(scheme->settings); + free(scheme->name); + free(scheme); + } +} + +bool flib_scheme_get_mod(const flib_scheme *scheme, const char *name) { + if(!log_badargs_if2(scheme==NULL, name==NULL)) { + for(int i=0; imods[i]; + } + } + flib_log_e("Unable to find game mod %s", name); + } + return false; +} + +int flib_scheme_get_setting(const flib_scheme *scheme, const char *name, int def) { + if(!log_badargs_if2(scheme==NULL, name==NULL)) { + for(int i=0; isettings[i]; + } + } + flib_log_e("Unable to find game setting %s", name); + } + return def; +} diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/model/scheme.h --- a/project_files/frontlib/model/scheme.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/model/scheme.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,72 +1,72 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * Data structures for game scheme information. - * - * The scheme consists of settings (integers) and mods (booleans). These are not fixed, but - * described in a "metascheme", which describes how each setting and mod is sent to the - * engine, and in which order they appear in the network protocol. The metascheme is defined - * in hwconsts.h - */ - -#ifndef SCHEME_H_ -#define SCHEME_H_ - -#include -#include -#include "../hwconsts.h" - -/** - * The settings and mods arrays have the same number and order of elements - * as the corresponding arrays in the metascheme. - */ -typedef struct { - char *name; - int *settings; - bool *mods; -} flib_scheme; - -/** - * Create a new configuration with everything set to default or false - * Returns NULL on error. - */ -flib_scheme *flib_scheme_create(const char *schemeName); - -/** - * Create a copy of the scheme. Returns NULL on error or if NULL was passed. - */ -flib_scheme *flib_scheme_copy(const flib_scheme *scheme); - -/** - * Decrease the reference count of the object and free it if this was the last reference. - */ -void flib_scheme_destroy(flib_scheme* scheme); - -/** - * Retrieve a mod setting by its name. If the mod is not found, logs an error and returns false. - */ -bool flib_scheme_get_mod(const flib_scheme *scheme, const char *name); - -/** - * Retrieve a game setting by its name. If the setting is not found, logs an error and returns def. - */ -int flib_scheme_get_setting(const flib_scheme *scheme, const char *name, int def); - -#endif /* SCHEME_H_ */ +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * Data structures for game scheme information. + * + * The scheme consists of settings (integers) and mods (booleans). These are not fixed, but + * described in a "metascheme", which describes how each setting and mod is sent to the + * engine, and in which order they appear in the network protocol. The metascheme is defined + * in hwconsts.h + */ + +#ifndef SCHEME_H_ +#define SCHEME_H_ + +#include +#include +#include "../hwconsts.h" + +/** + * The settings and mods arrays have the same number and order of elements + * as the corresponding arrays in the metascheme. + */ +typedef struct { + char *name; + int *settings; + bool *mods; +} flib_scheme; + +/** + * Create a new configuration with everything set to default or false + * Returns NULL on error. + */ +flib_scheme *flib_scheme_create(const char *schemeName); + +/** + * Create a copy of the scheme. Returns NULL on error or if NULL was passed. + */ +flib_scheme *flib_scheme_copy(const flib_scheme *scheme); + +/** + * Decrease the reference count of the object and free it if this was the last reference. + */ +void flib_scheme_destroy(flib_scheme* scheme); + +/** + * Retrieve a mod setting by its name. If the mod is not found, logs an error and returns false. + */ +bool flib_scheme_get_mod(const flib_scheme *scheme, const char *name); + +/** + * Retrieve a game setting by its name. If the setting is not found, logs an error and returns def. + */ +int flib_scheme_get_setting(const flib_scheme *scheme, const char *name, int def); + +#endif /* SCHEME_H_ */ diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/model/schemelist.c --- a/project_files/frontlib/model/schemelist.c Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/model/schemelist.c Tue Nov 10 20:43:13 2015 +0100 @@ -1,216 +1,216 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "schemelist.h" - -#include "../util/inihelper.h" -#include "../util/logging.h" -#include "../util/util.h" -#include "../util/list.h" - -#include -#include -#include -#include - -static char *makePrefixedName(int schemeIndex, const char *settingName) { - return flib_asprintf("%i\\%s", schemeIndex, settingName); -} - -static int readSettingsFromIni(flib_ini *ini, flib_scheme *scheme, int index) { - bool error = false; - for(int i=0; isettings[i], key, flib_meta.settings[i].def)) { - flib_log_e("Error reading setting %s in schemes file.", key); - error = true; - } - free(key); - } - return error; -} - -static int readModsFromIni(flib_ini *ini, flib_scheme *scheme, int index) { - bool error = false; - for(int i=0; imods[i], key, false)) { - flib_log_e("Error reading mod %s in schemes file.", key); - error = true; - } - free(key); - } - return error; -} - -static flib_scheme *readSchemeFromIni(flib_ini *ini, int index) { - flib_scheme *result = NULL; - char *schemeNameKey = makePrefixedName(index+1, "name"); - if(schemeNameKey) { - char *schemeName = NULL; - if(!flib_ini_get_str_opt(ini, &schemeName, schemeNameKey, "Unnamed")) { - flib_scheme *tmpScheme = flib_scheme_create(schemeName); - if(tmpScheme) { - if(!readSettingsFromIni(ini, tmpScheme, index) && !readModsFromIni(ini, tmpScheme, index)) { - result = tmpScheme; - tmpScheme = NULL; - } - } - flib_scheme_destroy(tmpScheme); - } - free(schemeName); - } - free(schemeNameKey); - return result; -} - -static flib_schemelist *fromIniHandleError(flib_schemelist *result, flib_ini *ini) { - flib_ini_destroy(ini); - flib_schemelist_destroy(result); - return NULL; -} - -flib_schemelist *flib_schemelist_from_ini(const char *filename) { - if(log_badargs_if(filename==NULL)) { - return NULL; - } - - flib_schemelist *list = NULL; - flib_ini *ini = flib_ini_load(filename); - if(!ini || flib_ini_enter_section(ini, "schemes")) { - flib_log_e("Missing file or missing section \"schemes\" in file %s.", filename); - return fromIniHandleError(list, ini); - } - - list = flib_schemelist_create(); - if(!list) { - return fromIniHandleError(list, ini); - } - - int schemeCount = 0; - if(flib_ini_get_int(ini, &schemeCount, "size")) { - flib_log_e("Missing or malformed scheme count in config file %s.", filename); - return fromIniHandleError(list, ini); - } - - for(int i=0; iname); - free(key); - - for(int i=0; imods[i]); - free(key); - } - - for(int i=0; isettings[i]); - free(key); - } - return error; -} - -int flib_schemelist_to_ini(const char *filename, const flib_schemelist *schemes) { - int result = -1; - if(!log_badargs_if2(filename==NULL, schemes==NULL)) { - flib_ini *ini = flib_ini_create(NULL); - if(ini && !flib_ini_create_section(ini, "schemes")) { - bool error = false; - error |= flib_ini_set_int(ini, "size", schemes->schemeCount); - for(int i=0; ischemeCount && !error; i++) { - error |= writeSchemeToIni(schemes->schemes[i], ini, i); - } - - if(!error) { - result = flib_ini_save(ini, filename); - } - } - flib_ini_destroy(ini); - } - return result; -} - -flib_schemelist *flib_schemelist_create() { - return flib_calloc(1, sizeof(flib_schemelist)); -} - -void flib_schemelist_destroy(flib_schemelist *list) { - if(list) { - for(int i=0; ischemeCount; i++) { - flib_scheme_destroy(list->schemes[i]); - } - free(list->schemes); - free(list); - } -} - -flib_scheme *flib_schemelist_find(flib_schemelist *list, const char *name) { - if(!log_badargs_if2(list==NULL, name==NULL)) { - for(int i=0; ischemeCount; i++) { - if(!strcmp(name, list->schemes[i]->name)) { - return list->schemes[i]; - } - } - } - return NULL; -} - -GENERATE_STATIC_LIST_INSERT(insertScheme, flib_scheme*) -GENERATE_STATIC_LIST_DELETE(deleteScheme, flib_scheme*) - -int flib_schemelist_insert(flib_schemelist *list, flib_scheme *cfg, int pos) { - if(!log_badargs_if2(list==NULL, cfg==NULL) - && !insertScheme(&list->schemes, &list->schemeCount, cfg, pos)) { - return 0; - } - return -1; -} - -int flib_schemelist_delete(flib_schemelist *list, int pos) { - if(!log_badargs_if(list==NULL)) { - flib_scheme *elem = list->schemes[pos]; - if(!deleteScheme(&list->schemes, &list->schemeCount, pos)) { - flib_scheme_destroy(elem); - return 0; - } - } - return -1; -} +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "schemelist.h" + +#include "../util/inihelper.h" +#include "../util/logging.h" +#include "../util/util.h" +#include "../util/list.h" + +#include +#include +#include +#include + +static char *makePrefixedName(int schemeIndex, const char *settingName) { + return flib_asprintf("%i\\%s", schemeIndex, settingName); +} + +static int readSettingsFromIni(flib_ini *ini, flib_scheme *scheme, int index) { + bool error = false; + for(int i=0; isettings[i], key, flib_meta.settings[i].def)) { + flib_log_e("Error reading setting %s in schemes file.", key); + error = true; + } + free(key); + } + return error; +} + +static int readModsFromIni(flib_ini *ini, flib_scheme *scheme, int index) { + bool error = false; + for(int i=0; imods[i], key, false)) { + flib_log_e("Error reading mod %s in schemes file.", key); + error = true; + } + free(key); + } + return error; +} + +static flib_scheme *readSchemeFromIni(flib_ini *ini, int index) { + flib_scheme *result = NULL; + char *schemeNameKey = makePrefixedName(index+1, "name"); + if(schemeNameKey) { + char *schemeName = NULL; + if(!flib_ini_get_str_opt(ini, &schemeName, schemeNameKey, "Unnamed")) { + flib_scheme *tmpScheme = flib_scheme_create(schemeName); + if(tmpScheme) { + if(!readSettingsFromIni(ini, tmpScheme, index) && !readModsFromIni(ini, tmpScheme, index)) { + result = tmpScheme; + tmpScheme = NULL; + } + } + flib_scheme_destroy(tmpScheme); + } + free(schemeName); + } + free(schemeNameKey); + return result; +} + +static flib_schemelist *fromIniHandleError(flib_schemelist *result, flib_ini *ini) { + flib_ini_destroy(ini); + flib_schemelist_destroy(result); + return NULL; +} + +flib_schemelist *flib_schemelist_from_ini(const char *filename) { + if(log_badargs_if(filename==NULL)) { + return NULL; + } + + flib_schemelist *list = NULL; + flib_ini *ini = flib_ini_load(filename); + if(!ini || flib_ini_enter_section(ini, "schemes")) { + flib_log_e("Missing file or missing section \"schemes\" in file %s.", filename); + return fromIniHandleError(list, ini); + } + + list = flib_schemelist_create(); + if(!list) { + return fromIniHandleError(list, ini); + } + + int schemeCount = 0; + if(flib_ini_get_int(ini, &schemeCount, "size")) { + flib_log_e("Missing or malformed scheme count in config file %s.", filename); + return fromIniHandleError(list, ini); + } + + for(int i=0; iname); + free(key); + + for(int i=0; imods[i]); + free(key); + } + + for(int i=0; isettings[i]); + free(key); + } + return error; +} + +int flib_schemelist_to_ini(const char *filename, const flib_schemelist *schemes) { + int result = -1; + if(!log_badargs_if2(filename==NULL, schemes==NULL)) { + flib_ini *ini = flib_ini_create(NULL); + if(ini && !flib_ini_create_section(ini, "schemes")) { + bool error = false; + error |= flib_ini_set_int(ini, "size", schemes->schemeCount); + for(int i=0; ischemeCount && !error; i++) { + error |= writeSchemeToIni(schemes->schemes[i], ini, i); + } + + if(!error) { + result = flib_ini_save(ini, filename); + } + } + flib_ini_destroy(ini); + } + return result; +} + +flib_schemelist *flib_schemelist_create() { + return flib_calloc(1, sizeof(flib_schemelist)); +} + +void flib_schemelist_destroy(flib_schemelist *list) { + if(list) { + for(int i=0; ischemeCount; i++) { + flib_scheme_destroy(list->schemes[i]); + } + free(list->schemes); + free(list); + } +} + +flib_scheme *flib_schemelist_find(flib_schemelist *list, const char *name) { + if(!log_badargs_if2(list==NULL, name==NULL)) { + for(int i=0; ischemeCount; i++) { + if(!strcmp(name, list->schemes[i]->name)) { + return list->schemes[i]; + } + } + } + return NULL; +} + +GENERATE_STATIC_LIST_INSERT(insertScheme, flib_scheme*) +GENERATE_STATIC_LIST_DELETE(deleteScheme, flib_scheme*) + +int flib_schemelist_insert(flib_schemelist *list, flib_scheme *cfg, int pos) { + if(!log_badargs_if2(list==NULL, cfg==NULL) + && !insertScheme(&list->schemes, &list->schemeCount, cfg, pos)) { + return 0; + } + return -1; +} + +int flib_schemelist_delete(flib_schemelist *list, int pos) { + if(!log_badargs_if(list==NULL)) { + flib_scheme *elem = list->schemes[pos]; + if(!deleteScheme(&list->schemes, &list->schemeCount, pos)) { + flib_scheme_destroy(elem); + return 0; + } + } + return -1; +} diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/model/schemelist.h --- a/project_files/frontlib/model/schemelist.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/model/schemelist.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,79 +1,79 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * Functions for managing a list of schemes. - * This is in here because the scheme config file of the QtFrontend (which we are staying compatible with) contains - * all the schemes at once, so we need functions to work with a list like that. - */ - -#ifndef SCHEMELIST_H_ -#define SCHEMELIST_H_ - -#include "scheme.h" - -typedef struct { - int schemeCount; - flib_scheme **schemes; -} flib_schemelist; - -/** - * Load a list of configurations from the ini file. - * Returns NULL on error. - */ -flib_schemelist *flib_schemelist_from_ini(const char *filename); - -/** - * Store the list of configurations to an ini file. - * Returns NULL on error. - */ -int flib_schemelist_to_ini(const char *filename, const flib_schemelist *config); - -/** - * Create an empty scheme list. Returns NULL on error. - */ -flib_schemelist *flib_schemelist_create(); - -/** - * Insert a new scheme into the list at position pos, moving all higher schemes to make place. - * pos must be at least 0 (insert at the start) and at most list->schemeCount (insert at the end). - * Ownership of the scheme is transferred to the list. - * Returns 0 on success. - */ -int flib_schemelist_insert(flib_schemelist *list, flib_scheme *cfg, int pos); - -/** - * Delete a scheme from the list at position pos, moving down all higher schemes. - * The scheme is destroyed. - * Returns 0 on success. - */ -int flib_schemelist_delete(flib_schemelist *list, int pos); - -/** - * Find the scheme with a specific name - */ -flib_scheme *flib_schemelist_find(flib_schemelist *list, const char *name); - -/** - * Free this schemelist and all contained schemes - */ -void flib_schemelist_destroy(flib_schemelist *list); - - -#endif /* SCHEMELIST_H_ */ +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * Functions for managing a list of schemes. + * This is in here because the scheme config file of the QtFrontend (which we are staying compatible with) contains + * all the schemes at once, so we need functions to work with a list like that. + */ + +#ifndef SCHEMELIST_H_ +#define SCHEMELIST_H_ + +#include "scheme.h" + +typedef struct { + int schemeCount; + flib_scheme **schemes; +} flib_schemelist; + +/** + * Load a list of configurations from the ini file. + * Returns NULL on error. + */ +flib_schemelist *flib_schemelist_from_ini(const char *filename); + +/** + * Store the list of configurations to an ini file. + * Returns NULL on error. + */ +int flib_schemelist_to_ini(const char *filename, const flib_schemelist *config); + +/** + * Create an empty scheme list. Returns NULL on error. + */ +flib_schemelist *flib_schemelist_create(); + +/** + * Insert a new scheme into the list at position pos, moving all higher schemes to make place. + * pos must be at least 0 (insert at the start) and at most list->schemeCount (insert at the end). + * Ownership of the scheme is transferred to the list. + * Returns 0 on success. + */ +int flib_schemelist_insert(flib_schemelist *list, flib_scheme *cfg, int pos); + +/** + * Delete a scheme from the list at position pos, moving down all higher schemes. + * The scheme is destroyed. + * Returns 0 on success. + */ +int flib_schemelist_delete(flib_schemelist *list, int pos); + +/** + * Find the scheme with a specific name + */ +flib_scheme *flib_schemelist_find(flib_schemelist *list, const char *name); + +/** + * Free this schemelist and all contained schemes + */ +void flib_schemelist_destroy(flib_schemelist *list); + + +#endif /* SCHEMELIST_H_ */ diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/model/team.c --- a/project_files/frontlib/model/team.c Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/model/team.c Tue Nov 10 20:43:13 2015 +0100 @@ -1,323 +1,323 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "team.h" - -#include "../util/inihelper.h" -#include "../util/util.h" -#include "../util/logging.h" - -#include -#include - -static flib_team *from_ini_handleError(flib_team *result, flib_ini *settingfile) { - flib_ini_destroy(settingfile); - flib_team_destroy(result); - return NULL; -} - -flib_team *flib_team_from_ini(const char *filename) { - if(log_badargs_if(filename==NULL)) { - return NULL; - } - - flib_team *result = flib_calloc(1, sizeof(flib_team)); - flib_ini *ini = NULL; - - if(!result) { - return from_ini_handleError(result, ini); - } - - ini = flib_ini_load(filename); - if(!ini) { - flib_log_e("Error loading team file %s", filename); - return from_ini_handleError(result, ini); - } - - if(flib_ini_enter_section(ini, "team")) { - flib_log_e("Missing section \"Team\" in team file %s", filename); - return from_ini_handleError(result, ini); - } - bool error = false; - error |= flib_ini_get_str(ini, &result->name, "name"); - error |= flib_ini_get_str(ini, &result->grave, "grave"); - error |= flib_ini_get_str(ini, &result->fort, "fort"); - error |= flib_ini_get_str(ini, &result->voicepack, "voicepack"); - error |= flib_ini_get_str(ini, &result->flag, "flag"); - error |= flib_ini_get_int(ini, &result->rounds, "rounds"); - error |= flib_ini_get_int(ini, &result->wins, "wins"); - error |= flib_ini_get_int(ini, &result->campaignProgress, "campaignprogress"); - - int difficulty = 0; - error |= flib_ini_get_int(ini, &difficulty, "difficulty"); - - if(error) { - flib_log_e("Missing or malformed entry in section \"Team\" in file %s", filename); - return from_ini_handleError(result, ini); - } - - for(int i=0; ihogs[i]; - error |= flib_ini_get_str(ini, &hog->name, "name"); - error |= flib_ini_get_str(ini, &hog->hat, "hat"); - error |= flib_ini_get_int(ini, &hog->rounds, "rounds"); - error |= flib_ini_get_int(ini, &hog->kills, "kills"); - error |= flib_ini_get_int(ini, &hog->deaths, "deaths"); - error |= flib_ini_get_int(ini, &hog->suicides, "suicides"); - result->hogs[i].difficulty = difficulty; - result->hogs[i].initialHealth = TEAM_DEFAULT_HEALTH; - - if(error) { - flib_log_e("Missing or malformed entry in section \"%s\" in file %s", sectionName, filename); - return from_ini_handleError(result, ini); - } - } - - if(!flib_ini_enter_section(ini, "binds")) { - result->bindingCount = flib_ini_get_keycount(ini); - if(result->bindingCount<0) { - flib_log_e("Error reading bindings from file %s", filename); - result->bindingCount = 0; - } - result->bindings = flib_calloc(result->bindingCount, sizeof(flib_binding)); - if(!result->bindings) { - return from_ini_handleError(result, ini); - } - for(int i=0; ibindingCount; i++) { - char *keyname = flib_ini_get_keyname(ini, i); - if(!keyname) { - error = true; - } else { - result->bindings[i].action = flib_urldecode(keyname); - error |= !result->bindings[i].action; - error |= flib_ini_get_str(ini, &result->bindings[i].binding, keyname); - } - free(keyname); - } - } - - if(error) { - flib_log_e("Error reading team file %s", filename); - return from_ini_handleError(result, ini); - } - - flib_ini_destroy(ini); - return result; -} - -void flib_team_destroy(flib_team *team) { - if(team) { - for(int i=0; ihogs[i].name); - free(team->hogs[i].hat); - flib_weaponset_destroy(team->hogs[i].weaponset); - } - free(team->name); - free(team->grave); - free(team->fort); - free(team->voicepack); - free(team->flag); - if(team->bindings) { - for(int i=0; ibindingCount; i++) { - free(team->bindings[i].action); - free(team->bindings[i].binding); - } - } - free(team->bindings); - free(team->ownerName); - free(team); - } -} - -static int writeTeamSection(const flib_team *team, flib_ini *ini) { - if(flib_ini_create_section(ini, "team")) { - return -1; - } - bool error = false; - error |= flib_ini_set_str(ini, "name", team->name); - error |= flib_ini_set_str(ini, "grave", team->grave); - error |= flib_ini_set_str(ini, "fort", team->fort); - error |= flib_ini_set_str(ini, "voicepack", team->voicepack); - error |= flib_ini_set_str(ini, "flag", team->flag); - error |= flib_ini_set_int(ini, "rounds", team->rounds); - error |= flib_ini_set_int(ini, "wins", team->wins); - error |= flib_ini_set_int(ini, "campaignprogress", team->campaignProgress); - error |= flib_ini_set_int(ini, "difficulty", team->hogs[0].difficulty); - return error; -} - -static int writeHogSections(const flib_team *team, flib_ini *ini) { - for(int i=0; ihogs[i]; - char sectionName[32]; - if(snprintf(sectionName, sizeof(sectionName), "hedgehog%i", i) <= 0) { - return -1; - } - if(flib_ini_create_section(ini, sectionName)) { - return -1; - } - bool error = false; - error |= flib_ini_set_str(ini, "name", hog->name); - error |= flib_ini_set_str(ini, "hat", hog->hat); - error |= flib_ini_set_int(ini, "rounds", hog->rounds); - error |= flib_ini_set_int(ini, "kills", hog->kills); - error |= flib_ini_set_int(ini, "deaths", hog->deaths); - error |= flib_ini_set_int(ini, "suicides", hog->suicides); - if(error) { - return error; - } - } - return 0; -} - -static int writeBindingSection(const flib_team *team, flib_ini *ini) { - if(team->bindingCount == 0) { - return 0; - } - if(flib_ini_create_section(ini, "binds")) { - return -1; - } - for(int i=0; ibindingCount; i++) { - bool error = false; - char *action = flib_urlencode(team->bindings[i].action); - if(action) { - error |= flib_ini_set_str(ini, action, team->bindings[i].binding); - free(action); - } else { - error = true; - } - if(error) { - return error; - } - } - return 0; -} - -int flib_team_to_ini(const char *filename, const flib_team *team) { - int result = -1; - if(!log_badargs_if2(filename==NULL, team==NULL)) { - flib_ini *ini = flib_ini_create(filename); - bool error = false; - error |= writeTeamSection(team, ini); - error |= writeHogSections(team, ini); - error |= writeBindingSection(team, ini); - if(!error) { - result = flib_ini_save(ini, filename); - } - flib_ini_destroy(ini); - } - return result; -} - -int flib_team_set_weaponset(flib_team *team, const flib_weaponset *set) { - if(team) { - for(int i=0; ihogs[i].weaponset); - team->hogs[i].weaponset = flib_weaponset_copy(set); - if(set && !team->hogs[i].weaponset) { - return -1; - } - } - } - return 0; -} - -void flib_team_set_health(flib_team *team, int health) { - if(team) { - for(int i=0; ihogs[i].initialHealth = health; - } - } -} - -static char *strdupWithError(const char *in, bool *error) { - char *out = flib_strdupnull(in); - if(in && !out) { - *error = true; - } - return out; -} - -flib_team *flib_team_copy(const flib_team *team) { - flib_team *result = NULL; - if(team) { - flib_team *tmpTeam = flib_calloc(1, sizeof(flib_team)); - if(tmpTeam) { - bool error = false; - - for(int i=0; ihogs[i].name = strdupWithError(team->hogs[i].name, &error); - tmpTeam->hogs[i].hat = strdupWithError(team->hogs[i].hat, &error); - tmpTeam->hogs[i].rounds = team->hogs[i].rounds; - tmpTeam->hogs[i].kills = team->hogs[i].kills; - tmpTeam->hogs[i].deaths = team->hogs[i].deaths; - tmpTeam->hogs[i].suicides = team->hogs[i].suicides; - tmpTeam->hogs[i].difficulty = team->hogs[i].difficulty; - tmpTeam->hogs[i].initialHealth = team->hogs[i].initialHealth; - tmpTeam->hogs[i].weaponset = flib_weaponset_copy(team->hogs[i].weaponset); - if(team->hogs[i].weaponset && !tmpTeam->hogs[i].weaponset) { - error = true; - } - } - - tmpTeam->name = strdupWithError(team->name, &error); - tmpTeam->grave = strdupWithError(team->grave, &error); - tmpTeam->fort = strdupWithError(team->fort, &error); - tmpTeam->voicepack = strdupWithError(team->voicepack, &error); - tmpTeam->flag = strdupWithError(team->flag, &error); - tmpTeam->ownerName = strdupWithError(team->ownerName, &error); - - tmpTeam->bindingCount = team->bindingCount; - if(team->bindings) { - tmpTeam->bindings = flib_calloc(team->bindingCount, sizeof(flib_binding)); - if(tmpTeam->bindings) { - for(int i=0; ibindingCount; i++) { - tmpTeam->bindings[i].action = strdupWithError(team->bindings[i].action, &error); - tmpTeam->bindings[i].binding = strdupWithError(team->bindings[i].binding, &error); - } - } else { - error = true; - } - } - - tmpTeam->rounds = team->rounds; - tmpTeam->wins = team->wins; - tmpTeam->campaignProgress = team->campaignProgress; - - tmpTeam->colorIndex = team->colorIndex; - tmpTeam->hogsInGame = team->hogsInGame; - tmpTeam->remoteDriven = team->remoteDriven; - - if(!error) { - result = tmpTeam; - tmpTeam = 0; - } - } - flib_team_destroy(tmpTeam); - } - return result; -} +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "team.h" + +#include "../util/inihelper.h" +#include "../util/util.h" +#include "../util/logging.h" + +#include +#include + +static flib_team *from_ini_handleError(flib_team *result, flib_ini *settingfile) { + flib_ini_destroy(settingfile); + flib_team_destroy(result); + return NULL; +} + +flib_team *flib_team_from_ini(const char *filename) { + if(log_badargs_if(filename==NULL)) { + return NULL; + } + + flib_team *result = flib_calloc(1, sizeof(flib_team)); + flib_ini *ini = NULL; + + if(!result) { + return from_ini_handleError(result, ini); + } + + ini = flib_ini_load(filename); + if(!ini) { + flib_log_e("Error loading team file %s", filename); + return from_ini_handleError(result, ini); + } + + if(flib_ini_enter_section(ini, "team")) { + flib_log_e("Missing section \"Team\" in team file %s", filename); + return from_ini_handleError(result, ini); + } + bool error = false; + error |= flib_ini_get_str(ini, &result->name, "name"); + error |= flib_ini_get_str(ini, &result->grave, "grave"); + error |= flib_ini_get_str(ini, &result->fort, "fort"); + error |= flib_ini_get_str(ini, &result->voicepack, "voicepack"); + error |= flib_ini_get_str(ini, &result->flag, "flag"); + error |= flib_ini_get_int(ini, &result->rounds, "rounds"); + error |= flib_ini_get_int(ini, &result->wins, "wins"); + error |= flib_ini_get_int(ini, &result->campaignProgress, "campaignprogress"); + + int difficulty = 0; + error |= flib_ini_get_int(ini, &difficulty, "difficulty"); + + if(error) { + flib_log_e("Missing or malformed entry in section \"Team\" in file %s", filename); + return from_ini_handleError(result, ini); + } + + for(int i=0; ihogs[i]; + error |= flib_ini_get_str(ini, &hog->name, "name"); + error |= flib_ini_get_str(ini, &hog->hat, "hat"); + error |= flib_ini_get_int(ini, &hog->rounds, "rounds"); + error |= flib_ini_get_int(ini, &hog->kills, "kills"); + error |= flib_ini_get_int(ini, &hog->deaths, "deaths"); + error |= flib_ini_get_int(ini, &hog->suicides, "suicides"); + result->hogs[i].difficulty = difficulty; + result->hogs[i].initialHealth = TEAM_DEFAULT_HEALTH; + + if(error) { + flib_log_e("Missing or malformed entry in section \"%s\" in file %s", sectionName, filename); + return from_ini_handleError(result, ini); + } + } + + if(!flib_ini_enter_section(ini, "binds")) { + result->bindingCount = flib_ini_get_keycount(ini); + if(result->bindingCount<0) { + flib_log_e("Error reading bindings from file %s", filename); + result->bindingCount = 0; + } + result->bindings = flib_calloc(result->bindingCount, sizeof(flib_binding)); + if(!result->bindings) { + return from_ini_handleError(result, ini); + } + for(int i=0; ibindingCount; i++) { + char *keyname = flib_ini_get_keyname(ini, i); + if(!keyname) { + error = true; + } else { + result->bindings[i].action = flib_urldecode(keyname); + error |= !result->bindings[i].action; + error |= flib_ini_get_str(ini, &result->bindings[i].binding, keyname); + } + free(keyname); + } + } + + if(error) { + flib_log_e("Error reading team file %s", filename); + return from_ini_handleError(result, ini); + } + + flib_ini_destroy(ini); + return result; +} + +void flib_team_destroy(flib_team *team) { + if(team) { + for(int i=0; ihogs[i].name); + free(team->hogs[i].hat); + flib_weaponset_destroy(team->hogs[i].weaponset); + } + free(team->name); + free(team->grave); + free(team->fort); + free(team->voicepack); + free(team->flag); + if(team->bindings) { + for(int i=0; ibindingCount; i++) { + free(team->bindings[i].action); + free(team->bindings[i].binding); + } + } + free(team->bindings); + free(team->ownerName); + free(team); + } +} + +static int writeTeamSection(const flib_team *team, flib_ini *ini) { + if(flib_ini_create_section(ini, "team")) { + return -1; + } + bool error = false; + error |= flib_ini_set_str(ini, "name", team->name); + error |= flib_ini_set_str(ini, "grave", team->grave); + error |= flib_ini_set_str(ini, "fort", team->fort); + error |= flib_ini_set_str(ini, "voicepack", team->voicepack); + error |= flib_ini_set_str(ini, "flag", team->flag); + error |= flib_ini_set_int(ini, "rounds", team->rounds); + error |= flib_ini_set_int(ini, "wins", team->wins); + error |= flib_ini_set_int(ini, "campaignprogress", team->campaignProgress); + error |= flib_ini_set_int(ini, "difficulty", team->hogs[0].difficulty); + return error; +} + +static int writeHogSections(const flib_team *team, flib_ini *ini) { + for(int i=0; ihogs[i]; + char sectionName[32]; + if(snprintf(sectionName, sizeof(sectionName), "hedgehog%i", i) <= 0) { + return -1; + } + if(flib_ini_create_section(ini, sectionName)) { + return -1; + } + bool error = false; + error |= flib_ini_set_str(ini, "name", hog->name); + error |= flib_ini_set_str(ini, "hat", hog->hat); + error |= flib_ini_set_int(ini, "rounds", hog->rounds); + error |= flib_ini_set_int(ini, "kills", hog->kills); + error |= flib_ini_set_int(ini, "deaths", hog->deaths); + error |= flib_ini_set_int(ini, "suicides", hog->suicides); + if(error) { + return error; + } + } + return 0; +} + +static int writeBindingSection(const flib_team *team, flib_ini *ini) { + if(team->bindingCount == 0) { + return 0; + } + if(flib_ini_create_section(ini, "binds")) { + return -1; + } + for(int i=0; ibindingCount; i++) { + bool error = false; + char *action = flib_urlencode(team->bindings[i].action); + if(action) { + error |= flib_ini_set_str(ini, action, team->bindings[i].binding); + free(action); + } else { + error = true; + } + if(error) { + return error; + } + } + return 0; +} + +int flib_team_to_ini(const char *filename, const flib_team *team) { + int result = -1; + if(!log_badargs_if2(filename==NULL, team==NULL)) { + flib_ini *ini = flib_ini_create(filename); + bool error = false; + error |= writeTeamSection(team, ini); + error |= writeHogSections(team, ini); + error |= writeBindingSection(team, ini); + if(!error) { + result = flib_ini_save(ini, filename); + } + flib_ini_destroy(ini); + } + return result; +} + +int flib_team_set_weaponset(flib_team *team, const flib_weaponset *set) { + if(team) { + for(int i=0; ihogs[i].weaponset); + team->hogs[i].weaponset = flib_weaponset_copy(set); + if(set && !team->hogs[i].weaponset) { + return -1; + } + } + } + return 0; +} + +void flib_team_set_health(flib_team *team, int health) { + if(team) { + for(int i=0; ihogs[i].initialHealth = health; + } + } +} + +static char *strdupWithError(const char *in, bool *error) { + char *out = flib_strdupnull(in); + if(in && !out) { + *error = true; + } + return out; +} + +flib_team *flib_team_copy(const flib_team *team) { + flib_team *result = NULL; + if(team) { + flib_team *tmpTeam = flib_calloc(1, sizeof(flib_team)); + if(tmpTeam) { + bool error = false; + + for(int i=0; ihogs[i].name = strdupWithError(team->hogs[i].name, &error); + tmpTeam->hogs[i].hat = strdupWithError(team->hogs[i].hat, &error); + tmpTeam->hogs[i].rounds = team->hogs[i].rounds; + tmpTeam->hogs[i].kills = team->hogs[i].kills; + tmpTeam->hogs[i].deaths = team->hogs[i].deaths; + tmpTeam->hogs[i].suicides = team->hogs[i].suicides; + tmpTeam->hogs[i].difficulty = team->hogs[i].difficulty; + tmpTeam->hogs[i].initialHealth = team->hogs[i].initialHealth; + tmpTeam->hogs[i].weaponset = flib_weaponset_copy(team->hogs[i].weaponset); + if(team->hogs[i].weaponset && !tmpTeam->hogs[i].weaponset) { + error = true; + } + } + + tmpTeam->name = strdupWithError(team->name, &error); + tmpTeam->grave = strdupWithError(team->grave, &error); + tmpTeam->fort = strdupWithError(team->fort, &error); + tmpTeam->voicepack = strdupWithError(team->voicepack, &error); + tmpTeam->flag = strdupWithError(team->flag, &error); + tmpTeam->ownerName = strdupWithError(team->ownerName, &error); + + tmpTeam->bindingCount = team->bindingCount; + if(team->bindings) { + tmpTeam->bindings = flib_calloc(team->bindingCount, sizeof(flib_binding)); + if(tmpTeam->bindings) { + for(int i=0; ibindingCount; i++) { + tmpTeam->bindings[i].action = strdupWithError(team->bindings[i].action, &error); + tmpTeam->bindings[i].binding = strdupWithError(team->bindings[i].binding, &error); + } + } else { + error = true; + } + } + + tmpTeam->rounds = team->rounds; + tmpTeam->wins = team->wins; + tmpTeam->campaignProgress = team->campaignProgress; + + tmpTeam->colorIndex = team->colorIndex; + tmpTeam->hogsInGame = team->hogsInGame; + tmpTeam->remoteDriven = team->remoteDriven; + + if(!error) { + result = tmpTeam; + tmpTeam = 0; + } + } + flib_team_destroy(tmpTeam); + } + return result; +} diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/model/team.h --- a/project_files/frontlib/model/team.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/model/team.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,130 +1,130 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * This file defines a data structure for a hedgewars team. - * - * Teams are used in several different contexts in Hedgewars, and some of these require - * extra information about teams. For example, the weaponset is important - * to the engine, but not for ini reading/writing, and with the team statistics it is the - * other way around. To keep things simple, the data structure can hold all information - * used in any context. On the downside, that means we can't use static typing to ensure - * that team information is "complete" for a particular purpose. - */ -#ifndef TEAM_H_ -#define TEAM_H_ - - -#include "weapon.h" -#include "../hwconsts.h" - -#include -#include - -#define TEAM_DEFAULT_HEALTH 100 - -/** - * Struct representing a single keybinding. - */ -typedef struct { - char *action; - char *binding; -} flib_binding; - -typedef struct { - char *name; - char *hat; //!< e.g. hair_yellow; References a .png file in Data/Graphics/Hats - - //! Statistics. They are irrelevant for the engine or server, - //! but provided for ini reading/writing by the frontend. - int rounds; - int kills; - int deaths; - int suicides; - - int difficulty; //!< 0 = human, 1 = most difficult bot ... 5 = least difficult bot (somewhat counterintuitive) - - //! Transient setting used in game setup - int initialHealth; - flib_weaponset *weaponset; -} flib_hog; - -typedef struct { - flib_hog hogs[HEDGEHOGS_PER_TEAM]; - char *name; - char *grave; //!< e.g. "Bone"; References a .png file in Data/Graphics/Graves - char *fort; //!< e.g. "Castle"; References a series of files in Data/Forts - char *voicepack; //!< e.g. "Classic"; References a directory in Data/Sounds/voices - char *flag; //!< e.g. "hedgewars"; References a .png file in Data/Graphics/Flags - - flib_binding *bindings; - int bindingCount; - - //! Statistics. They are irrelevant for the engine or server, - //! but provided for ini reading/writing by the frontend. - int rounds; - int wins; - int campaignProgress; - - //! Transient settings used in game setup - int colorIndex; //!< Index into a color table - int hogsInGame; //!< The number of hogs that will actually play - bool remoteDriven; //!< true for non-local teams in a network game - char *ownerName; //!< Username of the owner of a team in a network game -} flib_team; - -/** - * Free all memory associated with the team - */ -void flib_team_destroy(flib_team *team); - -/** - * Loads a team, returns NULL on error. Destroy this team using flib_team_destroy. - * This will not fill in the fields marked as "transient" in the structs above. - */ -flib_team *flib_team_from_ini(const char *filename); - -/** - * Write the team to an ini file. Attempts to retain extra ini settings - * that were already present. Note that not all fields of a team struct - * are stored in the ini, some are only used intermittently to store - * information about a team in the context of a game. - * - * The flib_team can handle "difficulty" on a per-hog basis, but it - * is only written per-team in the team file. The difficulty of the - * first hog is used for the entire team when writing. - */ -int flib_team_to_ini(const char *filename, const flib_team *team); - -/** - * Set the same weaponset for every hog in the team - */ -int flib_team_set_weaponset(flib_team *team, const flib_weaponset *set); - -/** - * Set the same initial health for every hog. - */ -void flib_team_set_health(flib_team *team, int health); - -/** - * Create a deep copy of a team. Returns NULL on failure. - */ -flib_team *flib_team_copy(const flib_team *team); - -#endif /* TEAM_H_ */ +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * This file defines a data structure for a hedgewars team. + * + * Teams are used in several different contexts in Hedgewars, and some of these require + * extra information about teams. For example, the weaponset is important + * to the engine, but not for ini reading/writing, and with the team statistics it is the + * other way around. To keep things simple, the data structure can hold all information + * used in any context. On the downside, that means we can't use static typing to ensure + * that team information is "complete" for a particular purpose. + */ +#ifndef TEAM_H_ +#define TEAM_H_ + + +#include "weapon.h" +#include "../hwconsts.h" + +#include +#include + +#define TEAM_DEFAULT_HEALTH 100 + +/** + * Struct representing a single keybinding. + */ +typedef struct { + char *action; + char *binding; +} flib_binding; + +typedef struct { + char *name; + char *hat; //!< e.g. hair_yellow; References a .png file in Data/Graphics/Hats + + //! Statistics. They are irrelevant for the engine or server, + //! but provided for ini reading/writing by the frontend. + int rounds; + int kills; + int deaths; + int suicides; + + int difficulty; //!< 0 = human, 1 = most difficult bot ... 5 = least difficult bot (somewhat counterintuitive) + + //! Transient setting used in game setup + int initialHealth; + flib_weaponset *weaponset; +} flib_hog; + +typedef struct { + flib_hog hogs[HEDGEHOGS_PER_TEAM]; + char *name; + char *grave; //!< e.g. "Bone"; References a .png file in Data/Graphics/Graves + char *fort; //!< e.g. "Castle"; References a series of files in Data/Forts + char *voicepack; //!< e.g. "Classic"; References a directory in Data/Sounds/voices + char *flag; //!< e.g. "hedgewars"; References a .png file in Data/Graphics/Flags + + flib_binding *bindings; + int bindingCount; + + //! Statistics. They are irrelevant for the engine or server, + //! but provided for ini reading/writing by the frontend. + int rounds; + int wins; + int campaignProgress; + + //! Transient settings used in game setup + int colorIndex; //!< Index into a color table + int hogsInGame; //!< The number of hogs that will actually play + bool remoteDriven; //!< true for non-local teams in a network game + char *ownerName; //!< Username of the owner of a team in a network game +} flib_team; + +/** + * Free all memory associated with the team + */ +void flib_team_destroy(flib_team *team); + +/** + * Loads a team, returns NULL on error. Destroy this team using flib_team_destroy. + * This will not fill in the fields marked as "transient" in the structs above. + */ +flib_team *flib_team_from_ini(const char *filename); + +/** + * Write the team to an ini file. Attempts to retain extra ini settings + * that were already present. Note that not all fields of a team struct + * are stored in the ini, some are only used intermittently to store + * information about a team in the context of a game. + * + * The flib_team can handle "difficulty" on a per-hog basis, but it + * is only written per-team in the team file. The difficulty of the + * first hog is used for the entire team when writing. + */ +int flib_team_to_ini(const char *filename, const flib_team *team); + +/** + * Set the same weaponset for every hog in the team + */ +int flib_team_set_weaponset(flib_team *team, const flib_weaponset *set); + +/** + * Set the same initial health for every hog. + */ +void flib_team_set_health(flib_team *team, int health); + +/** + * Create a deep copy of a team. Returns NULL on failure. + */ +flib_team *flib_team_copy(const flib_team *team); + +#endif /* TEAM_H_ */ diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/model/teamlist.c --- a/project_files/frontlib/model/teamlist.c Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/model/teamlist.c Tue Nov 10 20:43:13 2015 +0100 @@ -1,120 +1,120 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "teamlist.h" - -#include "../util/util.h" -#include "../util/list.h" -#include "../util/logging.h" - -#include -#include - -flib_teamlist *flib_teamlist_create() { - return flib_calloc(1, sizeof(flib_teamlist)); -} - -void flib_teamlist_destroy(flib_teamlist *list) { - if(list) { - for(int i=0; iteamCount; i++) { - flib_team_destroy(list->teams[i]); - } - free(list->teams); - free(list); - } -} - -GENERATE_STATIC_LIST_INSERT(insertTeam, flib_team*) -GENERATE_STATIC_LIST_DELETE(deleteTeam, flib_team*) - -static int findTeam(const flib_teamlist *list, const char *name) { - for(int i=0; iteamCount; i++) { - if(!strcmp(name, list->teams[i]->name)) { - return i; - } - } - return -1; -} - -int flib_teamlist_insert(flib_teamlist *list, flib_team *team, int pos) { - if(!log_badargs_if2(list==NULL, team==NULL) - && !insertTeam(&list->teams, &list->teamCount, team, pos)) { - return 0; - } - return -1; -} - -int flib_teamlist_delete(flib_teamlist *list, const char *name) { - int result = -1; - if(!log_badargs_if2(list==NULL, name==NULL)) { - int itemid = findTeam(list, name); - if(itemid>=0) { - flib_team *team = list->teams[itemid]; - if(!deleteTeam(&list->teams, &list->teamCount, itemid)) { - flib_team_destroy(team); - result = 0; - } - } - } - return result; -} - -flib_team *flib_teamlist_find(const flib_teamlist *list, const char *name) { - flib_team *result = NULL; - if(!log_badargs_if2(list==NULL, name==NULL)) { - int itemid = findTeam(list, name); - if(itemid>=0) { - result = list->teams[itemid]; - } - } - return result; -} - -void flib_teamlist_clear(flib_teamlist *list) { - if(!log_badargs_if(list==NULL)) { - for(int i=0; iteamCount; i++) { - flib_team_destroy(list->teams[i]); - } - free(list->teams); - list->teams = NULL; - list->teamCount = 0; - } -} - -flib_teamlist *flib_teamlist_copy(flib_teamlist *list) { - if(!list) { - return NULL; - } - flib_teamlist *result = flib_teamlist_create(); - if(result) { - bool error = false; - for(int i=0; !error && iteamCount; i++) { - flib_team *teamcopy = flib_team_copy(list->teams[i]); - if(!teamcopy || flib_teamlist_insert(result, teamcopy, i)) { - flib_team_destroy(teamcopy); - error = true; - } - } - if(error) { - flib_teamlist_destroy(result); - result = NULL; - } - } - return result; -} +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "teamlist.h" + +#include "../util/util.h" +#include "../util/list.h" +#include "../util/logging.h" + +#include +#include + +flib_teamlist *flib_teamlist_create() { + return flib_calloc(1, sizeof(flib_teamlist)); +} + +void flib_teamlist_destroy(flib_teamlist *list) { + if(list) { + for(int i=0; iteamCount; i++) { + flib_team_destroy(list->teams[i]); + } + free(list->teams); + free(list); + } +} + +GENERATE_STATIC_LIST_INSERT(insertTeam, flib_team*) +GENERATE_STATIC_LIST_DELETE(deleteTeam, flib_team*) + +static int findTeam(const flib_teamlist *list, const char *name) { + for(int i=0; iteamCount; i++) { + if(!strcmp(name, list->teams[i]->name)) { + return i; + } + } + return -1; +} + +int flib_teamlist_insert(flib_teamlist *list, flib_team *team, int pos) { + if(!log_badargs_if2(list==NULL, team==NULL) + && !insertTeam(&list->teams, &list->teamCount, team, pos)) { + return 0; + } + return -1; +} + +int flib_teamlist_delete(flib_teamlist *list, const char *name) { + int result = -1; + if(!log_badargs_if2(list==NULL, name==NULL)) { + int itemid = findTeam(list, name); + if(itemid>=0) { + flib_team *team = list->teams[itemid]; + if(!deleteTeam(&list->teams, &list->teamCount, itemid)) { + flib_team_destroy(team); + result = 0; + } + } + } + return result; +} + +flib_team *flib_teamlist_find(const flib_teamlist *list, const char *name) { + flib_team *result = NULL; + if(!log_badargs_if2(list==NULL, name==NULL)) { + int itemid = findTeam(list, name); + if(itemid>=0) { + result = list->teams[itemid]; + } + } + return result; +} + +void flib_teamlist_clear(flib_teamlist *list) { + if(!log_badargs_if(list==NULL)) { + for(int i=0; iteamCount; i++) { + flib_team_destroy(list->teams[i]); + } + free(list->teams); + list->teams = NULL; + list->teamCount = 0; + } +} + +flib_teamlist *flib_teamlist_copy(flib_teamlist *list) { + if(!list) { + return NULL; + } + flib_teamlist *result = flib_teamlist_create(); + if(result) { + bool error = false; + for(int i=0; !error && iteamCount; i++) { + flib_team *teamcopy = flib_team_copy(list->teams[i]); + if(!teamcopy || flib_teamlist_insert(result, teamcopy, i)) { + flib_team_destroy(teamcopy); + error = true; + } + } + if(error) { + flib_teamlist_destroy(result); + result = NULL; + } + } + return result; +} diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/model/teamlist.h --- a/project_files/frontlib/model/teamlist.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/model/teamlist.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,61 +1,61 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef TEAMLIST_H_ -#define TEAMLIST_H_ - -#include "team.h" - -typedef struct { - int teamCount; - flib_team **teams; -} flib_teamlist; - -flib_teamlist *flib_teamlist_create(); - -void flib_teamlist_destroy(flib_teamlist *list); - -/** - * Insert a team into the list. The list takes ownership of the team. Returns 0 on success. - */ -int flib_teamlist_insert(flib_teamlist *list, flib_team *team, int pos); - -/** - * Delete the team with the name [name] from the list and destroys it. - * Returns 0 on success. - */ -int flib_teamlist_delete(flib_teamlist *list, const char *name); - -/** - * Returns the team with the name [name] from the list if it exists, NULL otherwise - */ -flib_team *flib_teamlist_find(const flib_teamlist *list, const char *name); - -/** - * Removes all items from the list and destroys them. - */ -void flib_teamlist_clear(flib_teamlist *list); - -/** - * Create a copy of the list and all the teams it contains. Weaponsets are not copied, but - * kept as references - */ -flib_teamlist *flib_teamlist_copy(flib_teamlist *list); - -#endif +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef TEAMLIST_H_ +#define TEAMLIST_H_ + +#include "team.h" + +typedef struct { + int teamCount; + flib_team **teams; +} flib_teamlist; + +flib_teamlist *flib_teamlist_create(); + +void flib_teamlist_destroy(flib_teamlist *list); + +/** + * Insert a team into the list. The list takes ownership of the team. Returns 0 on success. + */ +int flib_teamlist_insert(flib_teamlist *list, flib_team *team, int pos); + +/** + * Delete the team with the name [name] from the list and destroys it. + * Returns 0 on success. + */ +int flib_teamlist_delete(flib_teamlist *list, const char *name); + +/** + * Returns the team with the name [name] from the list if it exists, NULL otherwise + */ +flib_team *flib_teamlist_find(const flib_teamlist *list, const char *name); + +/** + * Removes all items from the list and destroys them. + */ +void flib_teamlist_clear(flib_teamlist *list); + +/** + * Create a copy of the list and all the teams it contains. Weaponsets are not copied, but + * kept as references + */ +flib_teamlist *flib_teamlist_copy(flib_teamlist *list); + +#endif diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/model/weapon.c --- a/project_files/frontlib/model/weapon.c Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/model/weapon.c Tue Nov 10 20:43:13 2015 +0100 @@ -1,234 +1,234 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "weapon.h" - -#include "../util/inihelper.h" -#include "../util/logging.h" -#include "../util/util.h" -#include "../util/list.h" - -#include -#include -#include - -static void setField(char field[WEAPONS_COUNT+1], const char *line, int lineLen, bool no9) { - if(lineLen>WEAPONS_COUNT) { - lineLen = WEAPONS_COUNT; - } - - char min = '0'; - char max = no9 ? '8' : '9'; - for(int i=0; i= min && line[i] <= max) { - field[i] = line[i]; - } else { - flib_log_w("Invalid character in weapon config string \"%.*s\", position %i", lineLen, line, i); - field[i] = '0'; - } - } - for(int i=lineLen; iname = flib_strdupnull(name); - if(newSet->name) { - setField(newSet->loadout, "", 0, false); - setField(newSet->crateprob, "", 0, false); - setField(newSet->crateammo, "", 0, false); - setField(newSet->delay, "", 0, false); - result = newSet; - newSet = NULL; - } - } - flib_weaponset_destroy(newSet); - } - return result; -} - -void flib_weaponset_destroy(flib_weaponset *cfg) { - if(cfg) { - free(cfg->name); - free(cfg); - } -} - -flib_weaponset *flib_weaponset_copy(const flib_weaponset *weaponset) { - if(!weaponset) { - return NULL; - } - - flib_weaponset *result = flib_weaponset_create(weaponset->name); - if(result) { - memcpy(result->loadout, weaponset->loadout, WEAPONS_COUNT+1); - memcpy(result->crateprob, weaponset->crateprob, WEAPONS_COUNT+1); - memcpy(result->delay, weaponset->delay, WEAPONS_COUNT+1); - memcpy(result->crateammo, weaponset->crateammo, WEAPONS_COUNT+1); - } - - return result; -} - -void flib_weaponsetlist_destroy(flib_weaponsetlist *list) { - if(list) { - for(int i=0; iweaponsetCount; i++) { - flib_weaponset_destroy(list->weaponsets[i]); - } - free(list->weaponsets); - free(list); - } -} - -flib_weaponset *flib_weaponset_from_ammostring(const char *name, const char *ammostring) { - flib_weaponset *result = NULL; - if(!log_badargs_if2(name==NULL, ammostring==NULL)) { - result = flib_weaponset_create(name); - if(result) { - int fieldlen = strlen(ammostring)/4; - setField(result->loadout, ammostring, fieldlen, false); - setField(result->crateprob, ammostring + fieldlen, fieldlen, true); - setField(result->delay, ammostring + 2*fieldlen, fieldlen, true); - setField(result->crateammo, ammostring + 3*fieldlen, fieldlen, true); - } - } - return result; -} - -static int fillWeaponsetFromIni(flib_weaponsetlist *list, flib_ini *ini, int index) { - int result = -1; - char *keyname = flib_ini_get_keyname(ini, index); - char *decodedKeyname = flib_urldecode(keyname); - char *ammostring = NULL; - if(decodedKeyname && !flib_ini_get_str(ini, &ammostring, keyname)) { - flib_weaponset *set = flib_weaponset_from_ammostring(decodedKeyname, ammostring); - if(set) { - result = flib_weaponsetlist_insert(list, set, list->weaponsetCount); - if(result) { - flib_weaponset_destroy(set); - } - } - } - free(ammostring); - free(decodedKeyname); - free(keyname); - return result; -} - -static int fillWeaponsetsFromIni(flib_weaponsetlist *list, flib_ini *ini) { - bool error = false; - int weaponsets = flib_ini_get_keycount(ini); - - for(int i=0; i='0' && c<='9') || (c>='a' && c <='z')); -} +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "weapon.h" + +#include "../util/inihelper.h" +#include "../util/logging.h" +#include "../util/util.h" +#include "../util/list.h" + +#include +#include +#include + +static void setField(char field[WEAPONS_COUNT+1], const char *line, int lineLen, bool no9) { + if(lineLen>WEAPONS_COUNT) { + lineLen = WEAPONS_COUNT; + } + + char min = '0'; + char max = no9 ? '8' : '9'; + for(int i=0; i= min && line[i] <= max) { + field[i] = line[i]; + } else { + flib_log_w("Invalid character in weapon config string \"%.*s\", position %i", lineLen, line, i); + field[i] = '0'; + } + } + for(int i=lineLen; iname = flib_strdupnull(name); + if(newSet->name) { + setField(newSet->loadout, "", 0, false); + setField(newSet->crateprob, "", 0, false); + setField(newSet->crateammo, "", 0, false); + setField(newSet->delay, "", 0, false); + result = newSet; + newSet = NULL; + } + } + flib_weaponset_destroy(newSet); + } + return result; +} + +void flib_weaponset_destroy(flib_weaponset *cfg) { + if(cfg) { + free(cfg->name); + free(cfg); + } +} + +flib_weaponset *flib_weaponset_copy(const flib_weaponset *weaponset) { + if(!weaponset) { + return NULL; + } + + flib_weaponset *result = flib_weaponset_create(weaponset->name); + if(result) { + memcpy(result->loadout, weaponset->loadout, WEAPONS_COUNT+1); + memcpy(result->crateprob, weaponset->crateprob, WEAPONS_COUNT+1); + memcpy(result->delay, weaponset->delay, WEAPONS_COUNT+1); + memcpy(result->crateammo, weaponset->crateammo, WEAPONS_COUNT+1); + } + + return result; +} + +void flib_weaponsetlist_destroy(flib_weaponsetlist *list) { + if(list) { + for(int i=0; iweaponsetCount; i++) { + flib_weaponset_destroy(list->weaponsets[i]); + } + free(list->weaponsets); + free(list); + } +} -static int writeWeaponsetToIni(flib_ini *ini, flib_weaponset *set) { - int result = -1; - char weaponstring[WEAPONS_COUNT*4+1]; - strcpy(weaponstring, set->loadout); - strcat(weaponstring, set->crateprob); - strcat(weaponstring, set->delay); - strcat(weaponstring, set->crateammo); - - char *escapedname = flib_urlencode_pred(set->name, needsEscape); - if(escapedname) { - result = flib_ini_set_str(ini, escapedname, weaponstring); - } - free(escapedname); - return result; -} - -int flib_weaponsetlist_to_ini(const char *filename, const flib_weaponsetlist *list) { - int result = -1; - if(!log_badargs_if2(filename==NULL, list==NULL)) { - flib_ini *ini = flib_ini_create(NULL); - if(ini && !flib_ini_create_section(ini, "General")) { - bool error = false; - for(int i=0; iweaponsetCount && !error; i++) { - error |= writeWeaponsetToIni(ini, list->weaponsets[i]); - } - - if(!error) { - result = flib_ini_save(ini, filename); - } - } - flib_ini_destroy(ini); - } - return result; -} - -flib_weaponsetlist *flib_weaponsetlist_create() { - return flib_calloc(1, sizeof(flib_weaponsetlist)); -} - -GENERATE_STATIC_LIST_INSERT(insertWeaponset, flib_weaponset*) -GENERATE_STATIC_LIST_DELETE(deleteWeaponset, flib_weaponset*) - -int flib_weaponsetlist_insert(flib_weaponsetlist *list, flib_weaponset *set, int pos) { - if(!log_badargs_if2(list==NULL, set==NULL) - && !insertWeaponset(&list->weaponsets, &list->weaponsetCount, set, pos)) { - return 0; - } - return -1; -} - -int flib_weaponsetlist_delete(flib_weaponsetlist *list, int pos) { - if(!log_badargs_if(list==NULL)) { - flib_weaponset *elem = list->weaponsets[pos]; - if(!deleteWeaponset(&list->weaponsets, &list->weaponsetCount, pos)) { - flib_weaponset_destroy(elem); - return 0; - } - } - return -1; -} +flib_weaponset *flib_weaponset_from_ammostring(const char *name, const char *ammostring) { + flib_weaponset *result = NULL; + if(!log_badargs_if2(name==NULL, ammostring==NULL)) { + result = flib_weaponset_create(name); + if(result) { + int fieldlen = strlen(ammostring)/4; + setField(result->loadout, ammostring, fieldlen, false); + setField(result->crateprob, ammostring + fieldlen, fieldlen, true); + setField(result->delay, ammostring + 2*fieldlen, fieldlen, true); + setField(result->crateammo, ammostring + 3*fieldlen, fieldlen, true); + } + } + return result; +} + +static int fillWeaponsetFromIni(flib_weaponsetlist *list, flib_ini *ini, int index) { + int result = -1; + char *keyname = flib_ini_get_keyname(ini, index); + char *decodedKeyname = flib_urldecode(keyname); + char *ammostring = NULL; + if(decodedKeyname && !flib_ini_get_str(ini, &ammostring, keyname)) { + flib_weaponset *set = flib_weaponset_from_ammostring(decodedKeyname, ammostring); + if(set) { + result = flib_weaponsetlist_insert(list, set, list->weaponsetCount); + if(result) { + flib_weaponset_destroy(set); + } + } + } + free(ammostring); + free(decodedKeyname); + free(keyname); + return result; +} + +static int fillWeaponsetsFromIni(flib_weaponsetlist *list, flib_ini *ini) { + bool error = false; + int weaponsets = flib_ini_get_keycount(ini); + + for(int i=0; i='0' && c<='9') || (c>='a' && c <='z')); +} + +static int writeWeaponsetToIni(flib_ini *ini, flib_weaponset *set) { + int result = -1; + char weaponstring[WEAPONS_COUNT*4+1]; + strcpy(weaponstring, set->loadout); + strcat(weaponstring, set->crateprob); + strcat(weaponstring, set->delay); + strcat(weaponstring, set->crateammo); + + char *escapedname = flib_urlencode_pred(set->name, needsEscape); + if(escapedname) { + result = flib_ini_set_str(ini, escapedname, weaponstring); + } + free(escapedname); + return result; +} + +int flib_weaponsetlist_to_ini(const char *filename, const flib_weaponsetlist *list) { + int result = -1; + if(!log_badargs_if2(filename==NULL, list==NULL)) { + flib_ini *ini = flib_ini_create(NULL); + if(ini && !flib_ini_create_section(ini, "General")) { + bool error = false; + for(int i=0; iweaponsetCount && !error; i++) { + error |= writeWeaponsetToIni(ini, list->weaponsets[i]); + } + + if(!error) { + result = flib_ini_save(ini, filename); + } + } + flib_ini_destroy(ini); + } + return result; +} + +flib_weaponsetlist *flib_weaponsetlist_create() { + return flib_calloc(1, sizeof(flib_weaponsetlist)); +} + +GENERATE_STATIC_LIST_INSERT(insertWeaponset, flib_weaponset*) +GENERATE_STATIC_LIST_DELETE(deleteWeaponset, flib_weaponset*) + +int flib_weaponsetlist_insert(flib_weaponsetlist *list, flib_weaponset *set, int pos) { + if(!log_badargs_if2(list==NULL, set==NULL) + && !insertWeaponset(&list->weaponsets, &list->weaponsetCount, set, pos)) { + return 0; + } + return -1; +} + +int flib_weaponsetlist_delete(flib_weaponsetlist *list, int pos) { + if(!log_badargs_if(list==NULL)) { + flib_weaponset *elem = list->weaponsets[pos]; + if(!deleteWeaponset(&list->weaponsets, &list->weaponsetCount, pos)) { + flib_weaponset_destroy(elem); + return 0; + } + } + return -1; +} diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/model/weapon.h --- a/project_files/frontlib/model/weapon.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/model/weapon.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,104 +1,104 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef MODEL_WEAPON_H_ -#define MODEL_WEAPON_H_ - -#include "../hwconsts.h" - -/** - * These values are all ASCII characters in the range '0'..'9' - * The fields are zero-terminated so they can easily be used as strings. - * - * For loadout, 9 means inifinite ammo. - * For the other setting, 9 is invalid. - */ -typedef struct { - char loadout[WEAPONS_COUNT+1]; - char crateprob[WEAPONS_COUNT+1]; - char crateammo[WEAPONS_COUNT+1]; - char delay[WEAPONS_COUNT+1]; - char *name; -} flib_weaponset; - -typedef struct { - int weaponsetCount; - flib_weaponset **weaponsets; -} flib_weaponsetlist; - -/** - * Returns a new weapon set, or NULL on error. - * name must not be NULL. - * - * The new weapon set is pre-filled with default - * settings (see hwconsts.h) - */ -flib_weaponset *flib_weaponset_create(const char *name); - -/** - * Free the memory used by this weaponset - */ -void flib_weaponset_destroy(flib_weaponset *weaponset); - -flib_weaponset *flib_weaponset_copy(const flib_weaponset *weaponset); - -/** - * Create a weaponset from an ammostring. This format is used both in the ini files - * and in the net protocol. - */ -flib_weaponset *flib_weaponset_from_ammostring(const char *name, const char *ammostring); - -/** - * Load a list of weaponsets from the ini file. - * Returns NULL on error. - */ -flib_weaponsetlist *flib_weaponsetlist_from_ini(const char *filename); - -/** - * Store the list of weaponsets to an ini file. - * Returns NULL on error. - */ -int flib_weaponsetlist_to_ini(const char *filename, const flib_weaponsetlist *weaponsets); - -/** - * Create an empty weaponset list. Returns NULL on error. - */ -flib_weaponsetlist *flib_weaponsetlist_create(); - -/** - * Release all memory associated with the weaponsetlist and release all contained weaponsets - */ -void flib_weaponsetlist_destroy(flib_weaponsetlist *list); - -/** - * Insert a new weaponset into the list at position pos, moving all higher weaponsets to make place. - * pos must be at least 0 (insert at the start) and at most list->weaponsetCount (insert at the end). - * Ownership of the weaponset is transferred to the list. - * Returns 0 on success. - */ -int flib_weaponsetlist_insert(flib_weaponsetlist *list, flib_weaponset *weaponset, int pos); - -/** - * Delete a weaponset from the list at position pos, moving down all higher weaponsets. - * The weaponset is destroyed. - * Returns 0 on success. - */ -int flib_weaponsetlist_delete(flib_weaponsetlist *list, int pos); - -#endif +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef MODEL_WEAPON_H_ +#define MODEL_WEAPON_H_ + +#include "../hwconsts.h" + +/** + * These values are all ASCII characters in the range '0'..'9' + * The fields are zero-terminated so they can easily be used as strings. + * + * For loadout, 9 means inifinite ammo. + * For the other setting, 9 is invalid. + */ +typedef struct { + char loadout[WEAPONS_COUNT+1]; + char crateprob[WEAPONS_COUNT+1]; + char crateammo[WEAPONS_COUNT+1]; + char delay[WEAPONS_COUNT+1]; + char *name; +} flib_weaponset; + +typedef struct { + int weaponsetCount; + flib_weaponset **weaponsets; +} flib_weaponsetlist; + +/** + * Returns a new weapon set, or NULL on error. + * name must not be NULL. + * + * The new weapon set is pre-filled with default + * settings (see hwconsts.h) + */ +flib_weaponset *flib_weaponset_create(const char *name); + +/** + * Free the memory used by this weaponset + */ +void flib_weaponset_destroy(flib_weaponset *weaponset); + +flib_weaponset *flib_weaponset_copy(const flib_weaponset *weaponset); + +/** + * Create a weaponset from an ammostring. This format is used both in the ini files + * and in the net protocol. + */ +flib_weaponset *flib_weaponset_from_ammostring(const char *name, const char *ammostring); + +/** + * Load a list of weaponsets from the ini file. + * Returns NULL on error. + */ +flib_weaponsetlist *flib_weaponsetlist_from_ini(const char *filename); + +/** + * Store the list of weaponsets to an ini file. + * Returns NULL on error. + */ +int flib_weaponsetlist_to_ini(const char *filename, const flib_weaponsetlist *weaponsets); + +/** + * Create an empty weaponset list. Returns NULL on error. + */ +flib_weaponsetlist *flib_weaponsetlist_create(); + +/** + * Release all memory associated with the weaponsetlist and release all contained weaponsets + */ +void flib_weaponsetlist_destroy(flib_weaponsetlist *list); + +/** + * Insert a new weaponset into the list at position pos, moving all higher weaponsets to make place. + * pos must be at least 0 (insert at the start) and at most list->weaponsetCount (insert at the end). + * Ownership of the weaponset is transferred to the list. + * Returns 0 on success. + */ +int flib_weaponsetlist_insert(flib_weaponsetlist *list, flib_weaponset *weaponset, int pos); + +/** + * Delete a weaponset from the list at position pos, moving down all higher weaponsets. + * The weaponset is destroyed. + * Returns 0 on success. + */ +int flib_weaponsetlist_delete(flib_weaponsetlist *list, int pos); + +#endif diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/net/netbase.c --- a/project_files/frontlib/net/netbase.c Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/net/netbase.c Tue Nov 10 20:43:13 2015 +0100 @@ -1,259 +1,259 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "netbase.h" -#include "../util/buffer.h" -#include "../util/logging.h" -#include "../util/util.h" -#include "../socket.h" - -#include -#include -#include -#include - -#define NET_READBUFFER_LIMIT (1024*1024) - -struct _flib_netbase { - flib_vector *readBuffer; - flib_tcpsocket *sock; -}; - -flib_netbase *flib_netbase_create(const char *server, uint16_t port) { - if(log_badargs_if2(server==NULL, port==0)) { - return NULL; - } - - flib_netbase *result = NULL; - flib_netbase *newNet = flib_calloc(1, sizeof(flib_netbase)); - - if(newNet) { - newNet->readBuffer = flib_vector_create(); - newNet->sock = flib_socket_connect(server, port); - if(newNet->readBuffer && newNet->sock) { - flib_log_i("Connected to server %s:%u", server, (unsigned)port); - result = newNet; - newNet = NULL; - } - } - flib_netbase_destroy(newNet); - - return result; -} - -void flib_netbase_destroy(flib_netbase *net) { - if(net) { - flib_socket_close(net->sock); - flib_vector_destroy(net->readBuffer); - free(net); - } -} - -bool flib_netbase_connected(flib_netbase *net) { - if(!log_badargs_if(net==NULL) && net->sock) { - return true; - } - return false; -} - -/** - * Parses and returns a message, and removes it from the vector. - */ -static flib_netmsg *parseMessage(flib_vector *vec) { - const uint8_t *partStart = flib_vector_data(vec); - const uint8_t *end = partStart+flib_vector_size(vec); - flib_netmsg *result = flib_netmsg_create(); - if(!result) { - return NULL; - } - - while(1) { - const uint8_t *partEnd = memchr(partStart, '\n', end-partStart); - if(!partEnd) { - // message incomplete - flib_netmsg_destroy(result); - return NULL; - } else if(partEnd-partStart == 0) { - // Zero-length part, message end marker. Remove the message from the vector. - uint8_t *vectorStart = flib_vector_data(vec); - size_t msgLen = partEnd+1-vectorStart; - memmove(vectorStart, partEnd+1, flib_vector_size(vec)-msgLen); - flib_vector_resize(vec, flib_vector_size(vec)-msgLen); - return result; - } else { - if(flib_netmsg_append_part(result, partStart, partEnd-partStart)) { - flib_netmsg_destroy(result); - return NULL; - } - partStart = partEnd+1; // Skip the '\n' - } - } - return NULL; // Never reached -} - -/** - * Receive some bytes and add them to the buffer. - * Returns the number of bytes received. - * Automatically closes the socket if an error occurs - * and sets sock=NULL. - */ -static int receiveToBuffer(flib_netbase *net) { - uint8_t buffer[256]; - if(!net->sock) { - return 0; - } else if(flib_vector_size(net->readBuffer) > NET_READBUFFER_LIMIT) { - flib_log_e("Net connection closed: Net message too big"); - flib_socket_close(net->sock); - net->sock = NULL; - return 0; - } else { - int size = flib_socket_nbrecv(net->sock, buffer, sizeof(buffer)); - if(size>=0 && !flib_vector_append(net->readBuffer, buffer, size)) { - return size; - } else { - flib_socket_close(net->sock); - net->sock = NULL; - return 0; - } - } -} - -flib_netmsg *flib_netbase_recv_message(flib_netbase *net) { - if(log_badargs_if(net==NULL)) { - return NULL; - } - - flib_netmsg *msg; - while(!(msg=parseMessage(net->readBuffer)) - && receiveToBuffer(net)) {} - - if(msg) { - return msg; - } else if(!net->sock && flib_vector_size(net->readBuffer)>0) { - // Connection is down and we didn't get a complete message, just flush the rest. - flib_vector_resize(net->readBuffer, 0); - } - return NULL; -} - -static void logSentMsg(const uint8_t *data, size_t len) { - if(flib_log_isActive(FLIB_LOGLEVEL_DEBUG)) { - flib_log_d("[NET OUT][%03u]%*.*s",(unsigned)len, (unsigned)len, (unsigned)len, data); - } -} - -int flib_netbase_send_raw(flib_netbase *net, const void *data, size_t len) { - if(log_badargs_if2(net==NULL, data==NULL && len>0)) { - return -1; - } - if(!net->sock) { - flib_log_w("flib_netbase_send_raw: Not connected."); - return -1; - } - - if(flib_socket_send(net->sock, data, len) == len) { - logSentMsg(data, len); - return 0; - } else { - flib_log_w("Failed or incomplete write: net connection lost."); - flib_socket_close(net->sock); - net->sock = NULL; - return -1; - } -} - -int flib_netbase_send_message(flib_netbase *net, const flib_netmsg *msg) { - if(log_badargs_if2(net==NULL, msg==NULL)) { - return -1; - } - - size_t totalSize = 0; - for(int i=0; ipartCount; i++) { - totalSize += strlen(msg->parts[i]) + 1; - } - totalSize++; // Last part ends in two '\n' instead of one - - uint8_t *buffer = flib_malloc(totalSize); - if(!buffer) { - return -1; - } - size_t pos = 0; - for(int i=0; ipartCount; i++) { - size_t partsize = strlen(msg->parts[i]); - memcpy(buffer+pos, msg->parts[i], partsize); - pos += partsize; - buffer[pos++] = '\n'; - } - buffer[pos++] = '\n'; - return flib_netbase_send_raw(net, buffer, pos); -} - -int flib_netbase_sendf(flib_netbase *net, const char *format, ...) { - int result = -1; - if(!log_badargs_if2(net==NULL, format==NULL)) { - va_list argp; - va_start(argp, format); - char *buffer = flib_vasprintf(format, argp); - if(buffer) { - result = flib_netbase_send_raw(net, buffer, strlen(buffer)); - } - free(buffer); - va_end(argp); - } - return result; -} - -flib_netmsg *flib_netmsg_create() { - flib_netmsg *result = flib_calloc(1, sizeof(flib_netmsg)); - if(result) { - result->partCount = 0; - result->parts = NULL; - return result; - } else { - return NULL; - } -} - -void flib_netmsg_destroy(flib_netmsg *msg) { - if(msg) { - for(int i=0; ipartCount; i++) { - free(msg->parts[i]); - } - free(msg->parts); - free(msg); - } -} - -int flib_netmsg_append_part(flib_netmsg *msg, const void *part, size_t partlen) { - int result = -1; - if(!log_badargs_if2(msg==NULL, part==NULL && partlen>0)) { - char **newParts = realloc(msg->parts, (msg->partCount+1)*sizeof(*msg->parts)); - if(newParts) { - msg->parts = newParts; - msg->parts[msg->partCount] = flib_malloc(partlen+1); - if(msg->parts[msg->partCount]) { - memcpy(msg->parts[msg->partCount], part, partlen); - msg->parts[msg->partCount][partlen] = 0; - msg->partCount++; - result = 0; - } - } - } - return result; -} +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "netbase.h" +#include "../util/buffer.h" +#include "../util/logging.h" +#include "../util/util.h" +#include "../socket.h" + +#include +#include +#include +#include + +#define NET_READBUFFER_LIMIT (1024*1024) + +struct _flib_netbase { + flib_vector *readBuffer; + flib_tcpsocket *sock; +}; + +flib_netbase *flib_netbase_create(const char *server, uint16_t port) { + if(log_badargs_if2(server==NULL, port==0)) { + return NULL; + } + + flib_netbase *result = NULL; + flib_netbase *newNet = flib_calloc(1, sizeof(flib_netbase)); + + if(newNet) { + newNet->readBuffer = flib_vector_create(); + newNet->sock = flib_socket_connect(server, port); + if(newNet->readBuffer && newNet->sock) { + flib_log_i("Connected to server %s:%u", server, (unsigned)port); + result = newNet; + newNet = NULL; + } + } + flib_netbase_destroy(newNet); + + return result; +} + +void flib_netbase_destroy(flib_netbase *net) { + if(net) { + flib_socket_close(net->sock); + flib_vector_destroy(net->readBuffer); + free(net); + } +} + +bool flib_netbase_connected(flib_netbase *net) { + if(!log_badargs_if(net==NULL) && net->sock) { + return true; + } + return false; +} + +/** + * Parses and returns a message, and removes it from the vector. + */ +static flib_netmsg *parseMessage(flib_vector *vec) { + const uint8_t *partStart = flib_vector_data(vec); + const uint8_t *end = partStart+flib_vector_size(vec); + flib_netmsg *result = flib_netmsg_create(); + if(!result) { + return NULL; + } + + while(1) { + const uint8_t *partEnd = memchr(partStart, '\n', end-partStart); + if(!partEnd) { + // message incomplete + flib_netmsg_destroy(result); + return NULL; + } else if(partEnd-partStart == 0) { + // Zero-length part, message end marker. Remove the message from the vector. + uint8_t *vectorStart = flib_vector_data(vec); + size_t msgLen = partEnd+1-vectorStart; + memmove(vectorStart, partEnd+1, flib_vector_size(vec)-msgLen); + flib_vector_resize(vec, flib_vector_size(vec)-msgLen); + return result; + } else { + if(flib_netmsg_append_part(result, partStart, partEnd-partStart)) { + flib_netmsg_destroy(result); + return NULL; + } + partStart = partEnd+1; // Skip the '\n' + } + } + return NULL; // Never reached +} + +/** + * Receive some bytes and add them to the buffer. + * Returns the number of bytes received. + * Automatically closes the socket if an error occurs + * and sets sock=NULL. + */ +static int receiveToBuffer(flib_netbase *net) { + uint8_t buffer[256]; + if(!net->sock) { + return 0; + } else if(flib_vector_size(net->readBuffer) > NET_READBUFFER_LIMIT) { + flib_log_e("Net connection closed: Net message too big"); + flib_socket_close(net->sock); + net->sock = NULL; + return 0; + } else { + int size = flib_socket_nbrecv(net->sock, buffer, sizeof(buffer)); + if(size>=0 && !flib_vector_append(net->readBuffer, buffer, size)) { + return size; + } else { + flib_socket_close(net->sock); + net->sock = NULL; + return 0; + } + } +} + +flib_netmsg *flib_netbase_recv_message(flib_netbase *net) { + if(log_badargs_if(net==NULL)) { + return NULL; + } + + flib_netmsg *msg; + while(!(msg=parseMessage(net->readBuffer)) + && receiveToBuffer(net)) {} + + if(msg) { + return msg; + } else if(!net->sock && flib_vector_size(net->readBuffer)>0) { + // Connection is down and we didn't get a complete message, just flush the rest. + flib_vector_resize(net->readBuffer, 0); + } + return NULL; +} + +static void logSentMsg(const uint8_t *data, size_t len) { + if(flib_log_isActive(FLIB_LOGLEVEL_DEBUG)) { + flib_log_d("[NET OUT][%03u]%*.*s",(unsigned)len, (unsigned)len, (unsigned)len, data); + } +} + +int flib_netbase_send_raw(flib_netbase *net, const void *data, size_t len) { + if(log_badargs_if2(net==NULL, data==NULL && len>0)) { + return -1; + } + if(!net->sock) { + flib_log_w("flib_netbase_send_raw: Not connected."); + return -1; + } + + if(flib_socket_send(net->sock, data, len) == len) { + logSentMsg(data, len); + return 0; + } else { + flib_log_w("Failed or incomplete write: net connection lost."); + flib_socket_close(net->sock); + net->sock = NULL; + return -1; + } +} + +int flib_netbase_send_message(flib_netbase *net, const flib_netmsg *msg) { + if(log_badargs_if2(net==NULL, msg==NULL)) { + return -1; + } + + size_t totalSize = 0; + for(int i=0; ipartCount; i++) { + totalSize += strlen(msg->parts[i]) + 1; + } + totalSize++; // Last part ends in two '\n' instead of one + + uint8_t *buffer = flib_malloc(totalSize); + if(!buffer) { + return -1; + } + size_t pos = 0; + for(int i=0; ipartCount; i++) { + size_t partsize = strlen(msg->parts[i]); + memcpy(buffer+pos, msg->parts[i], partsize); + pos += partsize; + buffer[pos++] = '\n'; + } + buffer[pos++] = '\n'; + return flib_netbase_send_raw(net, buffer, pos); +} + +int flib_netbase_sendf(flib_netbase *net, const char *format, ...) { + int result = -1; + if(!log_badargs_if2(net==NULL, format==NULL)) { + va_list argp; + va_start(argp, format); + char *buffer = flib_vasprintf(format, argp); + if(buffer) { + result = flib_netbase_send_raw(net, buffer, strlen(buffer)); + } + free(buffer); + va_end(argp); + } + return result; +} + +flib_netmsg *flib_netmsg_create() { + flib_netmsg *result = flib_calloc(1, sizeof(flib_netmsg)); + if(result) { + result->partCount = 0; + result->parts = NULL; + return result; + } else { + return NULL; + } +} + +void flib_netmsg_destroy(flib_netmsg *msg) { + if(msg) { + for(int i=0; ipartCount; i++) { + free(msg->parts[i]); + } + free(msg->parts); + free(msg); + } +} + +int flib_netmsg_append_part(flib_netmsg *msg, const void *part, size_t partlen) { + int result = -1; + if(!log_badargs_if2(msg==NULL, part==NULL && partlen>0)) { + char **newParts = realloc(msg->parts, (msg->partCount+1)*sizeof(*msg->parts)); + if(newParts) { + msg->parts = newParts; + msg->parts[msg->partCount] = flib_malloc(partlen+1); + if(msg->parts[msg->partCount]) { + memcpy(msg->parts[msg->partCount], part, partlen); + msg->parts[msg->partCount][partlen] = 0; + msg->partCount++; + result = 0; + } + } + } + return result; +} diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/net/netbase.h --- a/project_files/frontlib/net/netbase.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/net/netbase.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,91 +1,91 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/* - * Low-level protocol support for the network connection - */ - -#ifndef NETBASE_H_ -#define NETBASE_H_ - -#include -#include -#include - -struct _flib_netbase; -typedef struct _flib_netbase flib_netbase; - -typedef struct { - int partCount; - char **parts; -} flib_netmsg; - -/** - * Start a connection to the specified Hedgewars server. - * - * Returns NULL on error. Destroy the created object with flib_netconn_destroy. - */ -flib_netbase *flib_netbase_create(const char *server, uint16_t port); - -/** - * Free resources and close sockets. - */ -void flib_netbase_destroy(flib_netbase *net); - -/** - * Determine the current connection state. Starts out true, and turns to - * false when we are disconnected from the server. - */ -bool flib_netbase_connected(flib_netbase *net); - -/** - * Receive a new message and return it as a flib_netmsg. The netmsg has to be - * destroyed with flib_netmsg_destroy after use. - * Returns NULL if no message is available. - * - * Note: When a connection is closed, you probably want to call this function until - * no further message is returned, to ensure you see all messages that were sent - * before the connection closed. - */ -flib_netmsg *flib_netbase_recv_message(flib_netbase *net); - -int flib_netbase_send_raw(flib_netbase *net, const void *data, size_t len); - -/** - * Write a single message to the server. This call blocks until the - * message is completely written or the connection is closed or an error occurs. - * - * Returns a negative value on failure. - */ -int flib_netbase_send_message(flib_netbase *net, const flib_netmsg *msg); - -/** - * Send a message printf-style. - * - * flib_netbase_sendf(net, "%s\n\n", "TOGGLE_READY"); - * flib_netbase_sendf(net, "%s\n%s\n%i\n\n", "CFG", "MAPGEN", MAPGEN_MAZE); - */ -int flib_netbase_sendf(flib_netbase *net, const char *format, ...); - -flib_netmsg *flib_netmsg_create(); -void flib_netmsg_destroy(flib_netmsg *msg); -int flib_netmsg_append_part(flib_netmsg *msg, const void *param, size_t len); - -#endif /* NETBASE_H_ */ - +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* + * Low-level protocol support for the network connection + */ + +#ifndef NETBASE_H_ +#define NETBASE_H_ + +#include +#include +#include + +struct _flib_netbase; +typedef struct _flib_netbase flib_netbase; + +typedef struct { + int partCount; + char **parts; +} flib_netmsg; + +/** + * Start a connection to the specified Hedgewars server. + * + * Returns NULL on error. Destroy the created object with flib_netconn_destroy. + */ +flib_netbase *flib_netbase_create(const char *server, uint16_t port); + +/** + * Free resources and close sockets. + */ +void flib_netbase_destroy(flib_netbase *net); + +/** + * Determine the current connection state. Starts out true, and turns to + * false when we are disconnected from the server. + */ +bool flib_netbase_connected(flib_netbase *net); + +/** + * Receive a new message and return it as a flib_netmsg. The netmsg has to be + * destroyed with flib_netmsg_destroy after use. + * Returns NULL if no message is available. + * + * Note: When a connection is closed, you probably want to call this function until + * no further message is returned, to ensure you see all messages that were sent + * before the connection closed. + */ +flib_netmsg *flib_netbase_recv_message(flib_netbase *net); + +int flib_netbase_send_raw(flib_netbase *net, const void *data, size_t len); + +/** + * Write a single message to the server. This call blocks until the + * message is completely written or the connection is closed or an error occurs. + * + * Returns a negative value on failure. + */ +int flib_netbase_send_message(flib_netbase *net, const flib_netmsg *msg); + +/** + * Send a message printf-style. + * + * flib_netbase_sendf(net, "%s\n\n", "TOGGLE_READY"); + * flib_netbase_sendf(net, "%s\n%s\n%i\n\n", "CFG", "MAPGEN", MAPGEN_MAZE); + */ +int flib_netbase_sendf(flib_netbase *net, const char *format, ...); + +flib_netmsg *flib_netmsg_create(); +void flib_netmsg_destroy(flib_netmsg *msg); +int flib_netmsg_append_part(flib_netmsg *msg, const void *param, size_t len); + +#endif /* NETBASE_H_ */ + diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/net/netconn.c --- a/project_files/frontlib/net/netconn.c Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/net/netconn.c Tue Nov 10 20:43:13 2015 +0100 @@ -1,613 +1,613 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (c) 2006-2008 Igor Ulyanov - * Copyright (c) 2004-2013 Andrey Korotaev - * Copyright (c) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "netconn_internal.h" -#include "netprotocol.h" -#include "../util/logging.h" -#include "../util/util.h" -#include "../md5/md5.h" -#include "../base64/base64.h" -#include "../model/mapcfg.h" - -#include -#include -#include -#include - -flib_netconn *flib_netconn_create(const char *playerName, const char *dataDirPath, const char *host, int port) { - flib_netconn *result = NULL; - if(!log_badargs_if4(playerName==NULL, host==NULL, port<1, port>65535)) { - flib_netconn *newConn = flib_calloc(1, sizeof(flib_netconn)); - if(newConn) { - newConn->netBase = flib_netbase_create(host, port); - newConn->playerName = flib_strdupnull(playerName); - newConn->dataDirPath = flib_strdupnull(dataDirPath); - - newConn->netconnState = NETCONN_STATE_CONNECTING; - - newConn->isChief = false; - newConn->map = flib_map_create_named("", "NoSuchMap"); - newConn->pendingTeamlist.teamCount = 0; - newConn->pendingTeamlist.teams = NULL; - newConn->teamlist.teamCount = 0; - newConn->teamlist.teams = NULL; - newConn->scheme = NULL; - newConn->style = NULL; - newConn->weaponset = NULL; - - newConn->running = false; - newConn->destroyRequested = false; - netconn_clearCallbacks(newConn); - if(newConn->netBase && newConn->playerName && newConn->dataDirPath && newConn->map) { - result = newConn; - newConn = NULL; - } - } - flib_netconn_destroy(newConn); - } - return result; -} - -void flib_netconn_destroy(flib_netconn *conn) { - if(conn) { - if(conn->running) { - /* - * The function was called from a callback, so the tick function is still running - * and we delay the actual destruction. We ensure no further callbacks will be - * sent to prevent surprises. - */ - netconn_clearCallbacks(conn); - conn->destroyRequested = true; - } else { - flib_netbase_destroy(conn->netBase); - free(conn->playerName); - free(conn->dataDirPath); - - flib_map_destroy(conn->map); - flib_teamlist_clear(&conn->pendingTeamlist); - flib_teamlist_clear(&conn->teamlist); - flib_scheme_destroy(conn->scheme); - free(conn->style); - flib_weaponset_destroy(conn->weaponset); - - free(conn); - } - } -} - -bool flib_netconn_is_chief(flib_netconn *conn) { - if(!log_badargs_if(conn==NULL) && conn->netconnState==NETCONN_STATE_ROOM) { - return conn->isChief; - } - return false; -} - -const char *flib_netconn_get_playername(flib_netconn *conn) { - if(!log_badargs_if(conn==NULL)) { - return conn->playerName; - } - return NULL; -} - -void netconn_leaveRoom(flib_netconn *conn) { - conn->netconnState = NETCONN_STATE_LOBBY; - conn->isChief = false; - flib_map_destroy(conn->map); - conn->map = flib_map_create_named("", "NoSuchMap"); - flib_teamlist_clear(&conn->pendingTeamlist); - flib_teamlist_clear(&conn->teamlist); - flib_scheme_destroy(conn->scheme); - conn->scheme = NULL; - free(conn->style); - conn->style = NULL; - flib_weaponset_destroy(conn->weaponset); - conn->weaponset = NULL; -} - -void netconn_setMap(flib_netconn *conn, const flib_map *map) { - flib_map *copy = flib_map_copy(map); - if(copy) { - flib_map_destroy(conn->map); - conn->map = copy; - } -} - -void netconn_setWeaponset(flib_netconn *conn, const flib_weaponset *weaponset) { - flib_weaponset *copy = flib_weaponset_copy(weaponset); - if(copy) { - flib_weaponset_destroy(conn->weaponset); - conn->weaponset = copy; - } -} - -void netconn_setScript(flib_netconn *conn, const char *script) { - char *copy = flib_strdupnull(script); - if(copy) { - free(conn->style); - conn->style = copy; - } -} - -void netconn_setScheme(flib_netconn *conn, const flib_scheme *scheme) { - flib_scheme *copy = flib_scheme_copy(scheme); - if(copy) { - flib_scheme_destroy(conn->scheme); - conn->scheme = copy; - } -} - -flib_gamesetup *flib_netconn_create_gamesetup(flib_netconn *conn) { - flib_gamesetup *result = NULL; - if(!log_badargs_if(conn==NULL)) { - if(conn->teamlist.teamCount==0 || !conn->scheme || !conn->weaponset) { - flib_log_e("Incomplete room state"); - } else { - flib_gamesetup stackSetup = {0}; - stackSetup.gamescheme = conn->scheme; - stackSetup.map = conn->map; - stackSetup.style = conn->style; - stackSetup.teamlist = &conn->teamlist; - result = flib_gamesetup_copy(&stackSetup); - if(result) { - bool error = false; - for(int i=0; iteamlist->teamCount; i++) { - if(flib_team_set_weaponset(result->teamlist->teams[i], conn->weaponset)) { - error = true; - } - flib_team_set_health(result->teamlist->teams[i], flib_scheme_get_setting(conn->scheme, "health", 100)); - } - if(result->map->mapgen == MAPGEN_NAMED && result->map->name) { - flib_mapcfg mapcfg; - if(!flib_mapcfg_read(conn->dataDirPath, result->map->name, &mapcfg)) { - free(result->map->theme); - result->map->theme = flib_strdupnull(mapcfg.theme); - if(!result->map->theme) { - error = true; - } - } else { - flib_log_e("Unable to read map config for map %s", result->map->name); - } - } - if(error) { - flib_gamesetup_destroy(result); - result = NULL; - } - } - } - } - return result; -} - -static void flib_netconn_wrappedtick(flib_netconn *conn) { - flib_netmsg *netmsg; - flib_netbase *net = conn->netBase; - bool exit = false; - - while(!exit && !conn->destroyRequested && (netmsg=flib_netbase_recv_message(conn->netBase))) { - if(netmsg->partCount==0) { - flib_log_w("Empty server message"); - continue; - } - - if(flib_log_isActive(FLIB_LOGLEVEL_DEBUG)) { - char *buf = flib_join(netmsg->parts, netmsg->partCount, "|"); - if(buf) { - flib_log_d("[Net In]%s", buf); - } - free(buf); - } - - const char *cmd = netmsg->parts[0]; - - if (!strcmp(cmd, "NICK") && netmsg->partCount>=2) { - if(netmsg->partCount<2) { - flib_log_w("Net: Malformed NICK message"); - } else { - char *nick = flib_strdupnull(netmsg->parts[1]); - if(nick) { - free(conn->playerName); - conn->playerName = nick; - } else { - conn->netconnState = NETCONN_STATE_DISCONNECTED; - conn->onDisconnectedCb(conn->onDisconnectedCtx, NETCONN_DISCONNECT_INTERNAL_ERROR, "Out of memory"); - exit = true; - } - } - } else if (!strcmp(cmd, "PROTO")) { - // The server just echoes this back apparently - } else if (!strcmp(cmd, "ERROR")) { - if (netmsg->partCount >= 2) { - conn->onMessageCb(conn->onMessageCtx, NETCONN_MSG_TYPE_ERROR, netmsg->parts[1]); - } else { - conn->onMessageCb(conn->onMessageCtx, NETCONN_MSG_TYPE_ERROR, "Unknown Error"); - } - } else if(!strcmp(cmd, "WARNING")) { - if (netmsg->partCount >= 2) { - conn->onMessageCb(conn->onMessageCtx, NETCONN_MSG_TYPE_WARNING, netmsg->parts[1]); - } else { - conn->onMessageCb(conn->onMessageCtx, NETCONN_MSG_TYPE_WARNING, "Unknown Warning"); - } - } else if(!strcmp(cmd, "CONNECTED")) { - if(netmsg->partCount<3 || atol(netmsg->parts[2])netconnState = NETCONN_STATE_DISCONNECTED; - conn->onDisconnectedCb(conn->onDisconnectedCtx, NETCONN_DISCONNECT_SERVER_TOO_OLD, "Server too old"); - exit = true; - } else { - flib_netbase_sendf(net, "%s\n%s\n\n", "NICK", conn->playerName); - flib_netbase_sendf(net, "%s\n%i\n\n", "PROTO", (int)PROTOCOL_VERSION); - } - } else if(!strcmp(cmd, "PING")) { - if (netmsg->partCount > 1) { - flib_netbase_sendf(net, "%s\n%s\n\n", "PONG", netmsg->parts[1]); - } else { - flib_netbase_sendf(net, "%s\n\n", "PONG"); - } - } else if(!strcmp(cmd, "ROOMS")) { - if(netmsg->partCount % 8 != 1) { - flib_log_w("Net: Malformed ROOMS message"); - } else { - int roomCount = netmsg->partCount/8; - flib_room **rooms = flib_room_array_from_netmsg(netmsg->parts+1, roomCount); - if(rooms) { - conn->onRoomlistCb(conn->onRoomlistCtx, (const flib_room**)rooms, roomCount); - for(int i=0; ipartCount < 2) { - flib_log_w("Net: Empty SERVERMESSAGE message"); - } else { - conn->onMessageCb(conn->onMessageCtx, NETCONN_MSG_TYPE_SERVERMESSAGE, netmsg->parts[1]); - } - } else if (!strcmp(cmd, "CHAT")) { - if(netmsg->partCount < 3) { - flib_log_w("Net: Empty CHAT message"); - } else { - conn->onChatCb(conn->onChatCtx, netmsg->parts[1], netmsg->parts[2]); - } - } else if (!strcmp(cmd, "INFO")) { - if(netmsg->partCount < 5) { - flib_log_w("Net: Malformed INFO message"); - } else { - char *joined = flib_join(netmsg->parts+1, netmsg->partCount-1, "\n"); - if(joined) { - conn->onMessageCb(conn->onMessageCtx, NETCONN_MSG_TYPE_PLAYERINFO, joined); - } - free(joined); - } - } else if(!strcmp(cmd, "SERVER_VARS")) { - for(int offset=1; offset+2partCount; offset+=2) { - conn->onServerVarCb(conn->onServerVarCtx, netmsg->parts[offset], netmsg->parts[offset+1]); - } - } else if (!strcmp(cmd, "CLIENT_FLAGS")) { - if(netmsg->partCount < 3 || strlen(netmsg->parts[1]) < 2) { - flib_log_w("Net: Malformed CLIENT_FLAGS message"); - } else { - const char *flags = netmsg->parts[1]; - bool setFlag = flags[0] == '+'; - - for(int j = 2; j < netmsg->partCount; ++j) { - bool isSelf = !strcmp(conn->playerName, netmsg->parts[j]); - if(isSelf && strchr(flags, 'h')) { - conn->isChief = setFlag; - } - conn->onClientFlagsCb(conn->onClientFlagsCtx, netmsg->parts[j], flags+1, setFlag); - } - } - } else if (!strcmp(cmd, "ADD_TEAM")) { - if(netmsg->partCount != 24 || conn->netconnState!=NETCONN_STATE_ROOM) { - flib_log_w("Net: Bad ADD_TEAM message"); - } else { - flib_team *team = flib_team_from_netmsg(netmsg->parts+1); - if(!team || flib_teamlist_insert(&conn->teamlist, team, conn->teamlist.teamCount)) { - flib_team_destroy(team); - conn->netconnState = NETCONN_STATE_DISCONNECTED; - conn->onDisconnectedCb(conn->onDisconnectedCtx, NETCONN_DISCONNECT_INTERNAL_ERROR, "Internal error"); - exit = true; - } else { - conn->onTeamAddCb(conn->onTeamAddCtx, team); - } - } - } else if (!strcmp(cmd, "REMOVE_TEAM")) { - if(netmsg->partCount != 2 || conn->netconnState!=NETCONN_STATE_ROOM) { - flib_log_w("Net: Bad REMOVETEAM message"); - } else { - flib_teamlist_delete(&conn->teamlist, netmsg->parts[1]); - conn->onTeamDeleteCb(conn->onTeamDeleteCtx, netmsg->parts[1]); - } - } else if(!strcmp(cmd, "ROOMABANDONED")) { - netconn_leaveRoom(conn); - conn->onLeaveRoomCb(conn->onLeaveRoomCtx, NETCONN_ROOMLEAVE_ABANDONED, "Room destroyed"); - } else if(!strcmp(cmd, "KICKED")) { - netconn_leaveRoom(conn); - conn->onLeaveRoomCb(conn->onLeaveRoomCtx, NETCONN_ROOMLEAVE_KICKED, "You got kicked"); - } else if(!strcmp(cmd, "JOINED")) { - if(netmsg->partCount < 2) { - flib_log_w("Net: Bad JOINED message"); - } else { - for(int i = 1; i < netmsg->partCount; ++i) - { - bool isMe = !strcmp(conn->playerName, netmsg->parts[i]); - if (isMe) { - conn->netconnState = NETCONN_STATE_ROOM; - conn->onEnterRoomCb(conn->onEnterRoomCtx, conn->isChief); - } - - conn->onRoomJoinCb(conn->onRoomJoinCtx, netmsg->parts[i]); - } - } - } else if(!strcmp(cmd, "LOBBY:JOINED")) { - if(netmsg->partCount < 2) { - flib_log_w("Net: Bad JOINED message"); - } else { - for(int i = 1; i < netmsg->partCount; ++i) - { - bool isMe = !strcmp(conn->playerName, netmsg->parts[i]); - if (isMe && conn->netconnState == NETCONN_STATE_CONNECTING) { - conn->onConnectedCb(conn->onConnectedCtx); - conn->netconnState = NETCONN_STATE_LOBBY; - } - conn->onLobbyJoinCb(conn->onLobbyJoinCtx, netmsg->parts[i]); - } - } - } else if(!strcmp(cmd, "LEFT")) { - if(netmsg->partCount < 2) { - flib_log_w("Net: Bad LEFT message"); - } else { - conn->onRoomLeaveCb(conn->onRoomLeaveCtx, netmsg->parts[1], netmsg->partCount>2 ? netmsg->parts[2] : NULL); - } - } else if(!strcmp(cmd, "ROOM") && netmsg->partCount >= 2) { - const char *subcmd = netmsg->parts[1]; - if(!strcmp(subcmd, "ADD") && netmsg->partCount == 10) { - flib_room *room = flib_room_from_netmsg(netmsg->parts+2); - if(room) { - conn->onRoomAddCb(conn->onRoomAddCtx, room); - } - flib_room_destroy(room); - } else if(!strcmp(subcmd, "UPD") && netmsg->partCount == 11) { - flib_room *room = flib_room_from_netmsg(netmsg->parts+3); - if(room) { - conn->onRoomUpdateCb(conn->onRoomUpdateCtx, netmsg->parts[2], room); - } - flib_room_destroy(room); - } else if(!strcmp(subcmd, "DEL") && netmsg->partCount == 3) { - conn->onRoomDeleteCb(conn->onRoomDeleteCtx, netmsg->parts[2]); - } else { - flib_log_w("Net: Unknown or malformed ROOM subcommand: %s", subcmd); - } - } else if(!strcmp(cmd, "LOBBY:LEFT")) { - if(netmsg->partCount < 2) { - flib_log_w("Net: Bad LOBBY:LEFT message"); - } else { - conn->onLobbyLeaveCb(conn->onLobbyLeaveCtx, netmsg->parts[1], netmsg->partCount>2 ? netmsg->parts[2] : NULL); - } - } else if (!strcmp(cmd, "RUN_GAME")) { - conn->onRunGameCb(conn->onRunGameCtx); - } else if (!strcmp(cmd, "ASKPASSWORD")) { - conn->onPasswordRequestCb(conn->onPasswordRequestCtx, conn->playerName); - } else if (!strcmp(cmd, "NOTICE")) { - if(netmsg->partCount < 2) { - flib_log_w("Net: Bad NOTICE message"); - } else { - errno = 0; - long n = strtol(netmsg->parts[1], NULL, 10); - if(errno) { - flib_log_w("Net: Bad NOTICE message"); - } else if(n==0) { - conn->onNickTakenCb(conn->onNickTakenCtx, conn->playerName); - } else { - flib_log_w("Net: Unknown NOTICE message: %l", n); - } - } - } else if (!strcmp(cmd, "TEAM_ACCEPTED")) { - if (netmsg->partCount != 2 || conn->netconnState!=NETCONN_STATE_ROOM) { - flib_log_w("Net: Bad TEAM_ACCEPTED message"); - } else { - flib_team *team = flib_team_copy(flib_teamlist_find(&conn->pendingTeamlist, netmsg->parts[1])); - if(team) { - flib_teamlist_insert(&conn->teamlist, team, conn->teamlist.teamCount); - flib_teamlist_delete(&conn->pendingTeamlist, netmsg->parts[1]); - } else { - flib_log_e("Team accepted that was not requested: %s", netmsg->parts[1]); - } - conn->onTeamAcceptedCb(conn->onTeamAcceptedCtx, netmsg->parts[1]); - } - } else if (!strcmp(cmd, "CFG")) { - if(netmsg->partCount < 3 || conn->netconnState!=NETCONN_STATE_ROOM) { - flib_log_w("Net: Bad CFG message"); - } else { - const char *subcmd = netmsg->parts[1]; - if(!strcmp(subcmd, "SCHEME") && netmsg->partCount == flib_meta.modCount + flib_meta.settingCount + 3) { - flib_scheme *cfg = flib_scheme_from_netmsg(netmsg->parts+2); - if(cfg) { - flib_scheme_destroy(conn->scheme); - conn->scheme = cfg; - conn->onSchemeChangedCb(conn->onSchemeChangedCtx, cfg); - } else { - flib_log_e("Error processing CFG SCHEME message"); - } - } else if(!strcmp(subcmd, "FULLMAPCONFIG") && netmsg->partCount == 7) { - flib_map *map = flib_map_from_netmsg(netmsg->parts+2); - if(map) { - flib_map_destroy(conn->map); - conn->map = map; - conn->onMapChangedCb(conn->onMapChangedCtx, conn->map, NETCONN_MAPCHANGE_FULL); - } else { - flib_log_e("Error processing CFG FULLMAPCONFIG message"); - } - } else if(!strcmp(subcmd, "MAP") && netmsg->partCount == 3) { - char *mapname = flib_strdupnull(netmsg->parts[2]); - if(mapname) { - free(conn->map->name); - conn->map->name = mapname; - conn->onMapChangedCb(conn->onMapChangedCtx, conn->map, NETCONN_MAPCHANGE_MAP); - } else { - flib_log_e("Error processing CFG MAP message"); - } - } else if(!strcmp(subcmd, "THEME") && netmsg->partCount == 3) { - char *themename = flib_strdupnull(netmsg->parts[2]); - if(themename) { - free(conn->map->theme); - conn->map->theme = themename; - conn->onMapChangedCb(conn->onMapChangedCtx, conn->map, NETCONN_MAPCHANGE_THEME); - } else { - flib_log_e("Error processing CFG THEME message"); - } - } else if(!strcmp(subcmd, "SEED") && netmsg->partCount == 3) { - char *seed = flib_strdupnull(netmsg->parts[2]); - if(seed) { - free(conn->map->seed); - conn->map->seed = seed; - conn->onMapChangedCb(conn->onMapChangedCtx, conn->map, NETCONN_MAPCHANGE_SEED); - } else { - flib_log_e("Error processing CFG SEED message"); - } - } else if(!strcmp(subcmd, "TEMPLATE") && netmsg->partCount == 3) { - conn->map->templateFilter = atoi(netmsg->parts[2]); - conn->onMapChangedCb(conn->onMapChangedCtx, conn->map, NETCONN_MAPCHANGE_TEMPLATE); - } else if(!strcmp(subcmd, "MAPGEN") && netmsg->partCount == 3) { - conn->map->mapgen = atoi(netmsg->parts[2]); - conn->onMapChangedCb(conn->onMapChangedCtx, conn->map, NETCONN_MAPCHANGE_MAPGEN); - } else if(!strcmp(subcmd, "MAZE_SIZE") && netmsg->partCount == 3) { - conn->map->mazeSize = atoi(netmsg->parts[2]); - conn->onMapChangedCb(conn->onMapChangedCtx, conn->map, NETCONN_MAPCHANGE_MAZE_SIZE); - } else if(!strcmp(subcmd, "DRAWNMAP") && netmsg->partCount == 3) { - size_t drawnMapSize = 0; - uint8_t *drawnMapData = NULL; - if(!flib_drawnmapdata_from_netmsg(netmsg->parts[2], &drawnMapData, &drawnMapSize)) { - free(conn->map->drawData); - conn->map->drawData = drawnMapData; - conn->map->drawDataSize = drawnMapSize; - conn->onMapChangedCb(conn->onMapChangedCtx, conn->map, NETCONN_MAPCHANGE_DRAWNMAP); - } else { - flib_log_e("Error processing CFG DRAWNMAP message"); - } - } else if(!strcmp(subcmd, "SCRIPT") && netmsg->partCount == 3) { - netconn_setScript(conn, netmsg->parts[2]); - conn->onScriptChangedCb(conn->onScriptChangedCtx, netmsg->parts[2]); - } else if(!strcmp(subcmd, "AMMO") && netmsg->partCount == 4) { - flib_weaponset *weapons = flib_weaponset_from_ammostring(netmsg->parts[2], netmsg->parts[3]); - if(weapons) { - flib_weaponset_destroy(conn->weaponset); - conn->weaponset = weapons; - conn->onWeaponsetChangedCb(conn->onWeaponsetChangedCtx, weapons); - } else { - flib_log_e("Error processing CFG AMMO message"); - } - } else { - flib_log_w("Net: Unknown or malformed CFG subcommand: %s", subcmd); - } - } - } else if (!strcmp(cmd, "HH_NUM")) { - if (netmsg->partCount != 3 || conn->netconnState!=NETCONN_STATE_ROOM) { - flib_log_w("Net: Bad HH_NUM message"); - } else { - int hogs = atoi(netmsg->parts[2]); - if(hogs<=0 || hogs>HEDGEHOGS_PER_TEAM) { - flib_log_w("Net: Bad HH_NUM message: %s hogs", netmsg->parts[2]); - } else { - flib_team *team = flib_teamlist_find(&conn->teamlist, netmsg->parts[1]); - if(team) { - team->hogsInGame = hogs; - } else { - flib_log_e("HH_NUM message for unknown team %s", netmsg->parts[1]); - } - conn->onHogCountChangedCb(conn->onHogCountChangedCtx, netmsg->parts[1], hogs); - } - } - } else if (!strcmp(cmd, "TEAM_COLOR")) { - if (netmsg->partCount != 3 || conn->netconnState!=NETCONN_STATE_ROOM) { - flib_log_w("Net: Bad TEAM_COLOR message"); - } else { - long color; - if(sscanf(netmsg->parts[2], "%lu", &color) && color>=0 && colorteamlist, netmsg->parts[1]); - if(team) { - team->colorIndex = color; - } else { - flib_log_e("TEAM_COLOR message for unknown team %s", netmsg->parts[1]); - } - conn->onTeamColorChangedCb(conn->onTeamColorChangedCtx, netmsg->parts[1], color); - } else { - flib_log_w("Net: Bad TEAM_COLOR message: Color %s", netmsg->parts[2]); - } - } - } else if (!strcmp(cmd, "EM")) { - if(netmsg->partCount < 2) { - flib_log_w("Net: Bad EM message"); - } else { - for(int i = 1; i < netmsg->partCount; ++i) { - char *out = NULL; - size_t outlen; - bool ok = base64_decode_alloc(netmsg->parts[i], strlen(netmsg->parts[i]), &out, &outlen); - if(ok && outlen) { - conn->onEngineMessageCb(conn->onEngineMessageCtx, (uint8_t*)out, outlen); - } else { - flib_log_e("Net: Malformed engine message: %s", netmsg->parts[i]); - } - free(out); - } - } - } else if (!strcmp(cmd, "BYE")) { - if (netmsg->partCount < 2) { - flib_log_w("Net: Bad BYE message"); - } else { - conn->netconnState = NETCONN_STATE_DISCONNECTED; - if (!strcmp(netmsg->parts[1], "Authentication failed")) { - conn->onDisconnectedCb(conn->onDisconnectedCtx, NETCONN_DISCONNECT_AUTH_FAILED, netmsg->parts[1]); - } else { - conn->onDisconnectedCb(conn->onDisconnectedCtx, NETCONN_DISCONNECT_NORMAL, netmsg->parts[1]); - } - exit = true; - } - } else if (!strcmp(cmd, "ADMIN_ACCESS")) { - // deprecated - } else if (!strcmp(cmd, "ROOM_CONTROL_ACCESS")) { - // deprecated - } else { - flib_log_w("Unknown server command: %s", cmd); - } - flib_netmsg_destroy(netmsg); - } - - if(!exit && !conn->destroyRequested && !flib_netbase_connected(net)) { - conn->netconnState = NETCONN_STATE_DISCONNECTED; - conn->onDisconnectedCb(conn->onDisconnectedCtx, NETCONN_DISCONNECT_CONNLOST, "Connection lost"); - } -} - -void flib_netconn_tick(flib_netconn *conn) { - if(!log_badargs_if(conn==NULL) - && !log_w_if(conn->running, "Call to flib_netconn_tick from a callback") - && !log_w_if(conn->netconnState == NETCONN_STATE_DISCONNECTED, "We are already done.")) { - conn->running = true; - flib_netconn_wrappedtick(conn); - conn->running = false; - - if(conn->destroyRequested) { - flib_netconn_destroy(conn); - } - } -} +/* + * Hedgewars, a free turn based strategy game + * Copyright (c) 2006-2008 Igor Ulyanov + * Copyright (c) 2004-2015 Andrey Korotaev + * Copyright (c) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "netconn_internal.h" +#include "netprotocol.h" +#include "../util/logging.h" +#include "../util/util.h" +#include "../md5/md5.h" +#include "../base64/base64.h" +#include "../model/mapcfg.h" + +#include +#include +#include +#include + +flib_netconn *flib_netconn_create(const char *playerName, const char *dataDirPath, const char *host, int port) { + flib_netconn *result = NULL; + if(!log_badargs_if4(playerName==NULL, host==NULL, port<1, port>65535)) { + flib_netconn *newConn = flib_calloc(1, sizeof(flib_netconn)); + if(newConn) { + newConn->netBase = flib_netbase_create(host, port); + newConn->playerName = flib_strdupnull(playerName); + newConn->dataDirPath = flib_strdupnull(dataDirPath); + + newConn->netconnState = NETCONN_STATE_CONNECTING; + + newConn->isChief = false; + newConn->map = flib_map_create_named("", "NoSuchMap"); + newConn->pendingTeamlist.teamCount = 0; + newConn->pendingTeamlist.teams = NULL; + newConn->teamlist.teamCount = 0; + newConn->teamlist.teams = NULL; + newConn->scheme = NULL; + newConn->style = NULL; + newConn->weaponset = NULL; + + newConn->running = false; + newConn->destroyRequested = false; + netconn_clearCallbacks(newConn); + if(newConn->netBase && newConn->playerName && newConn->dataDirPath && newConn->map) { + result = newConn; + newConn = NULL; + } + } + flib_netconn_destroy(newConn); + } + return result; +} + +void flib_netconn_destroy(flib_netconn *conn) { + if(conn) { + if(conn->running) { + /* + * The function was called from a callback, so the tick function is still running + * and we delay the actual destruction. We ensure no further callbacks will be + * sent to prevent surprises. + */ + netconn_clearCallbacks(conn); + conn->destroyRequested = true; + } else { + flib_netbase_destroy(conn->netBase); + free(conn->playerName); + free(conn->dataDirPath); + + flib_map_destroy(conn->map); + flib_teamlist_clear(&conn->pendingTeamlist); + flib_teamlist_clear(&conn->teamlist); + flib_scheme_destroy(conn->scheme); + free(conn->style); + flib_weaponset_destroy(conn->weaponset); + + free(conn); + } + } +} + +bool flib_netconn_is_chief(flib_netconn *conn) { + if(!log_badargs_if(conn==NULL) && conn->netconnState==NETCONN_STATE_ROOM) { + return conn->isChief; + } + return false; +} + +const char *flib_netconn_get_playername(flib_netconn *conn) { + if(!log_badargs_if(conn==NULL)) { + return conn->playerName; + } + return NULL; +} + +void netconn_leaveRoom(flib_netconn *conn) { + conn->netconnState = NETCONN_STATE_LOBBY; + conn->isChief = false; + flib_map_destroy(conn->map); + conn->map = flib_map_create_named("", "NoSuchMap"); + flib_teamlist_clear(&conn->pendingTeamlist); + flib_teamlist_clear(&conn->teamlist); + flib_scheme_destroy(conn->scheme); + conn->scheme = NULL; + free(conn->style); + conn->style = NULL; + flib_weaponset_destroy(conn->weaponset); + conn->weaponset = NULL; +} + +void netconn_setMap(flib_netconn *conn, const flib_map *map) { + flib_map *copy = flib_map_copy(map); + if(copy) { + flib_map_destroy(conn->map); + conn->map = copy; + } +} + +void netconn_setWeaponset(flib_netconn *conn, const flib_weaponset *weaponset) { + flib_weaponset *copy = flib_weaponset_copy(weaponset); + if(copy) { + flib_weaponset_destroy(conn->weaponset); + conn->weaponset = copy; + } +} + +void netconn_setScript(flib_netconn *conn, const char *script) { + char *copy = flib_strdupnull(script); + if(copy) { + free(conn->style); + conn->style = copy; + } +} + +void netconn_setScheme(flib_netconn *conn, const flib_scheme *scheme) { + flib_scheme *copy = flib_scheme_copy(scheme); + if(copy) { + flib_scheme_destroy(conn->scheme); + conn->scheme = copy; + } +} + +flib_gamesetup *flib_netconn_create_gamesetup(flib_netconn *conn) { + flib_gamesetup *result = NULL; + if(!log_badargs_if(conn==NULL)) { + if(conn->teamlist.teamCount==0 || !conn->scheme || !conn->weaponset) { + flib_log_e("Incomplete room state"); + } else { + flib_gamesetup stackSetup = {0}; + stackSetup.gamescheme = conn->scheme; + stackSetup.map = conn->map; + stackSetup.style = conn->style; + stackSetup.teamlist = &conn->teamlist; + result = flib_gamesetup_copy(&stackSetup); + if(result) { + bool error = false; + for(int i=0; iteamlist->teamCount; i++) { + if(flib_team_set_weaponset(result->teamlist->teams[i], conn->weaponset)) { + error = true; + } + flib_team_set_health(result->teamlist->teams[i], flib_scheme_get_setting(conn->scheme, "health", 100)); + } + if(result->map->mapgen == MAPGEN_NAMED && result->map->name) { + flib_mapcfg mapcfg; + if(!flib_mapcfg_read(conn->dataDirPath, result->map->name, &mapcfg)) { + free(result->map->theme); + result->map->theme = flib_strdupnull(mapcfg.theme); + if(!result->map->theme) { + error = true; + } + } else { + flib_log_e("Unable to read map config for map %s", result->map->name); + } + } + if(error) { + flib_gamesetup_destroy(result); + result = NULL; + } + } + } + } + return result; +} + +static void flib_netconn_wrappedtick(flib_netconn *conn) { + flib_netmsg *netmsg; + flib_netbase *net = conn->netBase; + bool exit = false; + + while(!exit && !conn->destroyRequested && (netmsg=flib_netbase_recv_message(conn->netBase))) { + if(netmsg->partCount==0) { + flib_log_w("Empty server message"); + continue; + } + + if(flib_log_isActive(FLIB_LOGLEVEL_DEBUG)) { + char *buf = flib_join(netmsg->parts, netmsg->partCount, "|"); + if(buf) { + flib_log_d("[Net In]%s", buf); + } + free(buf); + } + + const char *cmd = netmsg->parts[0]; + + if (!strcmp(cmd, "NICK") && netmsg->partCount>=2) { + if(netmsg->partCount<2) { + flib_log_w("Net: Malformed NICK message"); + } else { + char *nick = flib_strdupnull(netmsg->parts[1]); + if(nick) { + free(conn->playerName); + conn->playerName = nick; + } else { + conn->netconnState = NETCONN_STATE_DISCONNECTED; + conn->onDisconnectedCb(conn->onDisconnectedCtx, NETCONN_DISCONNECT_INTERNAL_ERROR, "Out of memory"); + exit = true; + } + } + } else if (!strcmp(cmd, "PROTO")) { + // The server just echoes this back apparently + } else if (!strcmp(cmd, "ERROR")) { + if (netmsg->partCount >= 2) { + conn->onMessageCb(conn->onMessageCtx, NETCONN_MSG_TYPE_ERROR, netmsg->parts[1]); + } else { + conn->onMessageCb(conn->onMessageCtx, NETCONN_MSG_TYPE_ERROR, "Unknown Error"); + } + } else if(!strcmp(cmd, "WARNING")) { + if (netmsg->partCount >= 2) { + conn->onMessageCb(conn->onMessageCtx, NETCONN_MSG_TYPE_WARNING, netmsg->parts[1]); + } else { + conn->onMessageCb(conn->onMessageCtx, NETCONN_MSG_TYPE_WARNING, "Unknown Warning"); + } + } else if(!strcmp(cmd, "CONNECTED")) { + if(netmsg->partCount<3 || atol(netmsg->parts[2])netconnState = NETCONN_STATE_DISCONNECTED; + conn->onDisconnectedCb(conn->onDisconnectedCtx, NETCONN_DISCONNECT_SERVER_TOO_OLD, "Server too old"); + exit = true; + } else { + flib_netbase_sendf(net, "%s\n%s\n\n", "NICK", conn->playerName); + flib_netbase_sendf(net, "%s\n%i\n\n", "PROTO", (int)PROTOCOL_VERSION); + } + } else if(!strcmp(cmd, "PING")) { + if (netmsg->partCount > 1) { + flib_netbase_sendf(net, "%s\n%s\n\n", "PONG", netmsg->parts[1]); + } else { + flib_netbase_sendf(net, "%s\n\n", "PONG"); + } + } else if(!strcmp(cmd, "ROOMS")) { + if(netmsg->partCount % 8 != 1) { + flib_log_w("Net: Malformed ROOMS message"); + } else { + int roomCount = netmsg->partCount/8; + flib_room **rooms = flib_room_array_from_netmsg(netmsg->parts+1, roomCount); + if(rooms) { + conn->onRoomlistCb(conn->onRoomlistCtx, (const flib_room**)rooms, roomCount); + for(int i=0; ipartCount < 2) { + flib_log_w("Net: Empty SERVERMESSAGE message"); + } else { + conn->onMessageCb(conn->onMessageCtx, NETCONN_MSG_TYPE_SERVERMESSAGE, netmsg->parts[1]); + } + } else if (!strcmp(cmd, "CHAT")) { + if(netmsg->partCount < 3) { + flib_log_w("Net: Empty CHAT message"); + } else { + conn->onChatCb(conn->onChatCtx, netmsg->parts[1], netmsg->parts[2]); + } + } else if (!strcmp(cmd, "INFO")) { + if(netmsg->partCount < 5) { + flib_log_w("Net: Malformed INFO message"); + } else { + char *joined = flib_join(netmsg->parts+1, netmsg->partCount-1, "\n"); + if(joined) { + conn->onMessageCb(conn->onMessageCtx, NETCONN_MSG_TYPE_PLAYERINFO, joined); + } + free(joined); + } + } else if(!strcmp(cmd, "SERVER_VARS")) { + for(int offset=1; offset+2partCount; offset+=2) { + conn->onServerVarCb(conn->onServerVarCtx, netmsg->parts[offset], netmsg->parts[offset+1]); + } + } else if (!strcmp(cmd, "CLIENT_FLAGS")) { + if(netmsg->partCount < 3 || strlen(netmsg->parts[1]) < 2) { + flib_log_w("Net: Malformed CLIENT_FLAGS message"); + } else { + const char *flags = netmsg->parts[1]; + bool setFlag = flags[0] == '+'; + + for(int j = 2; j < netmsg->partCount; ++j) { + bool isSelf = !strcmp(conn->playerName, netmsg->parts[j]); + if(isSelf && strchr(flags, 'h')) { + conn->isChief = setFlag; + } + conn->onClientFlagsCb(conn->onClientFlagsCtx, netmsg->parts[j], flags+1, setFlag); + } + } + } else if (!strcmp(cmd, "ADD_TEAM")) { + if(netmsg->partCount != 24 || conn->netconnState!=NETCONN_STATE_ROOM) { + flib_log_w("Net: Bad ADD_TEAM message"); + } else { + flib_team *team = flib_team_from_netmsg(netmsg->parts+1); + if(!team || flib_teamlist_insert(&conn->teamlist, team, conn->teamlist.teamCount)) { + flib_team_destroy(team); + conn->netconnState = NETCONN_STATE_DISCONNECTED; + conn->onDisconnectedCb(conn->onDisconnectedCtx, NETCONN_DISCONNECT_INTERNAL_ERROR, "Internal error"); + exit = true; + } else { + conn->onTeamAddCb(conn->onTeamAddCtx, team); + } + } + } else if (!strcmp(cmd, "REMOVE_TEAM")) { + if(netmsg->partCount != 2 || conn->netconnState!=NETCONN_STATE_ROOM) { + flib_log_w("Net: Bad REMOVETEAM message"); + } else { + flib_teamlist_delete(&conn->teamlist, netmsg->parts[1]); + conn->onTeamDeleteCb(conn->onTeamDeleteCtx, netmsg->parts[1]); + } + } else if(!strcmp(cmd, "ROOMABANDONED")) { + netconn_leaveRoom(conn); + conn->onLeaveRoomCb(conn->onLeaveRoomCtx, NETCONN_ROOMLEAVE_ABANDONED, "Room destroyed"); + } else if(!strcmp(cmd, "KICKED")) { + netconn_leaveRoom(conn); + conn->onLeaveRoomCb(conn->onLeaveRoomCtx, NETCONN_ROOMLEAVE_KICKED, "You got kicked"); + } else if(!strcmp(cmd, "JOINED")) { + if(netmsg->partCount < 2) { + flib_log_w("Net: Bad JOINED message"); + } else { + for(int i = 1; i < netmsg->partCount; ++i) + { + bool isMe = !strcmp(conn->playerName, netmsg->parts[i]); + if (isMe) { + conn->netconnState = NETCONN_STATE_ROOM; + conn->onEnterRoomCb(conn->onEnterRoomCtx, conn->isChief); + } + + conn->onRoomJoinCb(conn->onRoomJoinCtx, netmsg->parts[i]); + } + } + } else if(!strcmp(cmd, "LOBBY:JOINED")) { + if(netmsg->partCount < 2) { + flib_log_w("Net: Bad JOINED message"); + } else { + for(int i = 1; i < netmsg->partCount; ++i) + { + bool isMe = !strcmp(conn->playerName, netmsg->parts[i]); + if (isMe && conn->netconnState == NETCONN_STATE_CONNECTING) { + conn->onConnectedCb(conn->onConnectedCtx); + conn->netconnState = NETCONN_STATE_LOBBY; + } + conn->onLobbyJoinCb(conn->onLobbyJoinCtx, netmsg->parts[i]); + } + } + } else if(!strcmp(cmd, "LEFT")) { + if(netmsg->partCount < 2) { + flib_log_w("Net: Bad LEFT message"); + } else { + conn->onRoomLeaveCb(conn->onRoomLeaveCtx, netmsg->parts[1], netmsg->partCount>2 ? netmsg->parts[2] : NULL); + } + } else if(!strcmp(cmd, "ROOM") && netmsg->partCount >= 2) { + const char *subcmd = netmsg->parts[1]; + if(!strcmp(subcmd, "ADD") && netmsg->partCount == 10) { + flib_room *room = flib_room_from_netmsg(netmsg->parts+2); + if(room) { + conn->onRoomAddCb(conn->onRoomAddCtx, room); + } + flib_room_destroy(room); + } else if(!strcmp(subcmd, "UPD") && netmsg->partCount == 11) { + flib_room *room = flib_room_from_netmsg(netmsg->parts+3); + if(room) { + conn->onRoomUpdateCb(conn->onRoomUpdateCtx, netmsg->parts[2], room); + } + flib_room_destroy(room); + } else if(!strcmp(subcmd, "DEL") && netmsg->partCount == 3) { + conn->onRoomDeleteCb(conn->onRoomDeleteCtx, netmsg->parts[2]); + } else { + flib_log_w("Net: Unknown or malformed ROOM subcommand: %s", subcmd); + } + } else if(!strcmp(cmd, "LOBBY:LEFT")) { + if(netmsg->partCount < 2) { + flib_log_w("Net: Bad LOBBY:LEFT message"); + } else { + conn->onLobbyLeaveCb(conn->onLobbyLeaveCtx, netmsg->parts[1], netmsg->partCount>2 ? netmsg->parts[2] : NULL); + } + } else if (!strcmp(cmd, "RUN_GAME")) { + conn->onRunGameCb(conn->onRunGameCtx); + } else if (!strcmp(cmd, "ASKPASSWORD")) { + conn->onPasswordRequestCb(conn->onPasswordRequestCtx, conn->playerName); + } else if (!strcmp(cmd, "NOTICE")) { + if(netmsg->partCount < 2) { + flib_log_w("Net: Bad NOTICE message"); + } else { + errno = 0; + long n = strtol(netmsg->parts[1], NULL, 10); + if(errno) { + flib_log_w("Net: Bad NOTICE message"); + } else if(n==0) { + conn->onNickTakenCb(conn->onNickTakenCtx, conn->playerName); + } else { + flib_log_w("Net: Unknown NOTICE message: %l", n); + } + } + } else if (!strcmp(cmd, "TEAM_ACCEPTED")) { + if (netmsg->partCount != 2 || conn->netconnState!=NETCONN_STATE_ROOM) { + flib_log_w("Net: Bad TEAM_ACCEPTED message"); + } else { + flib_team *team = flib_team_copy(flib_teamlist_find(&conn->pendingTeamlist, netmsg->parts[1])); + if(team) { + flib_teamlist_insert(&conn->teamlist, team, conn->teamlist.teamCount); + flib_teamlist_delete(&conn->pendingTeamlist, netmsg->parts[1]); + } else { + flib_log_e("Team accepted that was not requested: %s", netmsg->parts[1]); + } + conn->onTeamAcceptedCb(conn->onTeamAcceptedCtx, netmsg->parts[1]); + } + } else if (!strcmp(cmd, "CFG")) { + if(netmsg->partCount < 3 || conn->netconnState!=NETCONN_STATE_ROOM) { + flib_log_w("Net: Bad CFG message"); + } else { + const char *subcmd = netmsg->parts[1]; + if(!strcmp(subcmd, "SCHEME") && netmsg->partCount == flib_meta.modCount + flib_meta.settingCount + 3) { + flib_scheme *cfg = flib_scheme_from_netmsg(netmsg->parts+2); + if(cfg) { + flib_scheme_destroy(conn->scheme); + conn->scheme = cfg; + conn->onSchemeChangedCb(conn->onSchemeChangedCtx, cfg); + } else { + flib_log_e("Error processing CFG SCHEME message"); + } + } else if(!strcmp(subcmd, "FULLMAPCONFIG") && netmsg->partCount == 7) { + flib_map *map = flib_map_from_netmsg(netmsg->parts+2); + if(map) { + flib_map_destroy(conn->map); + conn->map = map; + conn->onMapChangedCb(conn->onMapChangedCtx, conn->map, NETCONN_MAPCHANGE_FULL); + } else { + flib_log_e("Error processing CFG FULLMAPCONFIG message"); + } + } else if(!strcmp(subcmd, "MAP") && netmsg->partCount == 3) { + char *mapname = flib_strdupnull(netmsg->parts[2]); + if(mapname) { + free(conn->map->name); + conn->map->name = mapname; + conn->onMapChangedCb(conn->onMapChangedCtx, conn->map, NETCONN_MAPCHANGE_MAP); + } else { + flib_log_e("Error processing CFG MAP message"); + } + } else if(!strcmp(subcmd, "THEME") && netmsg->partCount == 3) { + char *themename = flib_strdupnull(netmsg->parts[2]); + if(themename) { + free(conn->map->theme); + conn->map->theme = themename; + conn->onMapChangedCb(conn->onMapChangedCtx, conn->map, NETCONN_MAPCHANGE_THEME); + } else { + flib_log_e("Error processing CFG THEME message"); + } + } else if(!strcmp(subcmd, "SEED") && netmsg->partCount == 3) { + char *seed = flib_strdupnull(netmsg->parts[2]); + if(seed) { + free(conn->map->seed); + conn->map->seed = seed; + conn->onMapChangedCb(conn->onMapChangedCtx, conn->map, NETCONN_MAPCHANGE_SEED); + } else { + flib_log_e("Error processing CFG SEED message"); + } + } else if(!strcmp(subcmd, "TEMPLATE") && netmsg->partCount == 3) { + conn->map->templateFilter = atoi(netmsg->parts[2]); + conn->onMapChangedCb(conn->onMapChangedCtx, conn->map, NETCONN_MAPCHANGE_TEMPLATE); + } else if(!strcmp(subcmd, "MAPGEN") && netmsg->partCount == 3) { + conn->map->mapgen = atoi(netmsg->parts[2]); + conn->onMapChangedCb(conn->onMapChangedCtx, conn->map, NETCONN_MAPCHANGE_MAPGEN); + } else if(!strcmp(subcmd, "MAZE_SIZE") && netmsg->partCount == 3) { + conn->map->mazeSize = atoi(netmsg->parts[2]); + conn->onMapChangedCb(conn->onMapChangedCtx, conn->map, NETCONN_MAPCHANGE_MAZE_SIZE); + } else if(!strcmp(subcmd, "DRAWNMAP") && netmsg->partCount == 3) { + size_t drawnMapSize = 0; + uint8_t *drawnMapData = NULL; + if(!flib_drawnmapdata_from_netmsg(netmsg->parts[2], &drawnMapData, &drawnMapSize)) { + free(conn->map->drawData); + conn->map->drawData = drawnMapData; + conn->map->drawDataSize = drawnMapSize; + conn->onMapChangedCb(conn->onMapChangedCtx, conn->map, NETCONN_MAPCHANGE_DRAWNMAP); + } else { + flib_log_e("Error processing CFG DRAWNMAP message"); + } + } else if(!strcmp(subcmd, "SCRIPT") && netmsg->partCount == 3) { + netconn_setScript(conn, netmsg->parts[2]); + conn->onScriptChangedCb(conn->onScriptChangedCtx, netmsg->parts[2]); + } else if(!strcmp(subcmd, "AMMO") && netmsg->partCount == 4) { + flib_weaponset *weapons = flib_weaponset_from_ammostring(netmsg->parts[2], netmsg->parts[3]); + if(weapons) { + flib_weaponset_destroy(conn->weaponset); + conn->weaponset = weapons; + conn->onWeaponsetChangedCb(conn->onWeaponsetChangedCtx, weapons); + } else { + flib_log_e("Error processing CFG AMMO message"); + } + } else { + flib_log_w("Net: Unknown or malformed CFG subcommand: %s", subcmd); + } + } + } else if (!strcmp(cmd, "HH_NUM")) { + if (netmsg->partCount != 3 || conn->netconnState!=NETCONN_STATE_ROOM) { + flib_log_w("Net: Bad HH_NUM message"); + } else { + int hogs = atoi(netmsg->parts[2]); + if(hogs<=0 || hogs>HEDGEHOGS_PER_TEAM) { + flib_log_w("Net: Bad HH_NUM message: %s hogs", netmsg->parts[2]); + } else { + flib_team *team = flib_teamlist_find(&conn->teamlist, netmsg->parts[1]); + if(team) { + team->hogsInGame = hogs; + } else { + flib_log_e("HH_NUM message for unknown team %s", netmsg->parts[1]); + } + conn->onHogCountChangedCb(conn->onHogCountChangedCtx, netmsg->parts[1], hogs); + } + } + } else if (!strcmp(cmd, "TEAM_COLOR")) { + if (netmsg->partCount != 3 || conn->netconnState!=NETCONN_STATE_ROOM) { + flib_log_w("Net: Bad TEAM_COLOR message"); + } else { + long color; + if(sscanf(netmsg->parts[2], "%lu", &color) && color>=0 && colorteamlist, netmsg->parts[1]); + if(team) { + team->colorIndex = color; + } else { + flib_log_e("TEAM_COLOR message for unknown team %s", netmsg->parts[1]); + } + conn->onTeamColorChangedCb(conn->onTeamColorChangedCtx, netmsg->parts[1], color); + } else { + flib_log_w("Net: Bad TEAM_COLOR message: Color %s", netmsg->parts[2]); + } + } + } else if (!strcmp(cmd, "EM")) { + if(netmsg->partCount < 2) { + flib_log_w("Net: Bad EM message"); + } else { + for(int i = 1; i < netmsg->partCount; ++i) { + char *out = NULL; + size_t outlen; + bool ok = base64_decode_alloc(netmsg->parts[i], strlen(netmsg->parts[i]), &out, &outlen); + if(ok && outlen) { + conn->onEngineMessageCb(conn->onEngineMessageCtx, (uint8_t*)out, outlen); + } else { + flib_log_e("Net: Malformed engine message: %s", netmsg->parts[i]); + } + free(out); + } + } + } else if (!strcmp(cmd, "BYE")) { + if (netmsg->partCount < 2) { + flib_log_w("Net: Bad BYE message"); + } else { + conn->netconnState = NETCONN_STATE_DISCONNECTED; + if (!strcmp(netmsg->parts[1], "Authentication failed")) { + conn->onDisconnectedCb(conn->onDisconnectedCtx, NETCONN_DISCONNECT_AUTH_FAILED, netmsg->parts[1]); + } else { + conn->onDisconnectedCb(conn->onDisconnectedCtx, NETCONN_DISCONNECT_NORMAL, netmsg->parts[1]); + } + exit = true; + } + } else if (!strcmp(cmd, "ADMIN_ACCESS")) { + // deprecated + } else if (!strcmp(cmd, "ROOM_CONTROL_ACCESS")) { + // deprecated + } else { + flib_log_w("Unknown server command: %s", cmd); + } + flib_netmsg_destroy(netmsg); + } + + if(!exit && !conn->destroyRequested && !flib_netbase_connected(net)) { + conn->netconnState = NETCONN_STATE_DISCONNECTED; + conn->onDisconnectedCb(conn->onDisconnectedCtx, NETCONN_DISCONNECT_CONNLOST, "Connection lost"); + } +} + +void flib_netconn_tick(flib_netconn *conn) { + if(!log_badargs_if(conn==NULL) + && !log_w_if(conn->running, "Call to flib_netconn_tick from a callback") + && !log_w_if(conn->netconnState == NETCONN_STATE_DISCONNECTED, "We are already done.")) { + conn->running = true; + flib_netconn_wrappedtick(conn); + conn->running = false; + + if(conn->destroyRequested) { + flib_netconn_destroy(conn); + } + } +} diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/net/netconn.h --- a/project_files/frontlib/net/netconn.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/net/netconn.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,654 +1,654 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * This file contains functions for communicating with a Hedgewars server to chat, prepare and play - * rounds of Hedgewars. - * - * To use this, first create a netconn object by calling flib_netconn_create. This will start the - * connection to the game server (which might fail right away, the function returns null then). You - * should also register your callback functions right at the start to ensure you don't miss any - * callbacks. - * - * In order to allow the netconn to run, you should regularly call flib_netconn_tick(), which - * performs network I/O and calls your callbacks on interesting events. - * - * When the connection is closed, you will receive the onDisconnect callback. This is the signal to - * destroy the netconn and stop calling tick(). - * - * The connection process lasts from the time you create the netconn until you receive the - * onConnected callback (or onDisconnected in case something goes wrong). During that time, you - * might receive the onNickTaken and onPasswordRequest callbacks; see their description for more - * information on how to handle them. You could also receive other callbacks during connecting (e.g. - * about the room list), but it should be safe to ignore them. - * - * Once you are connected, you are in the lobby, and you can enter rooms and leave them again. The - * room and lobby states have different protocols, so many commands only work in either one or the - * other. If you are in a room you might also be in a game, but most of the functions behave the - * same ingame as in a room. - * - * The state changes from lobby to room when the server tells you that you just entered one, which - * will also trigger the onEnterRoom callback. This usually happens in reply to either a joinRoom, - * createRoom or playerFollow command. - * - * The state changes back to lobby when the room is dissolved, when you are kicked from the room, or - * when you actively leave the room using flib_netconn_send_leaveRoom. The first two events will - * trigger the onLeaveRoom callback. - */ - -#ifndef NETCONN_H_ -#define NETCONN_H_ - -#include "../model/gamesetup.h" -#include "../model/scheme.h" -#include "../model/room.h" - -#include -#include -#include - -#define NETCONN_STATE_CONNECTING 0 -#define NETCONN_STATE_LOBBY 1 -#define NETCONN_STATE_ROOM 2 -#define NETCONN_STATE_DISCONNECTED 10 - -#define NETCONN_DISCONNECT_NORMAL 0 //!< The connection was closed normally -#define NETCONN_DISCONNECT_SERVER_TOO_OLD 1 //!< The server has a lower protocol version than we do -#define NETCONN_DISCONNECT_AUTH_FAILED 2 //!< You sent a password with flib_netconn_send_password that was not accepted -#define NETCONN_DISCONNECT_CONNLOST 3 //!< The network connection was lost -#define NETCONN_DISCONNECT_INTERNAL_ERROR 100 //!< Something went wrong in frontlib itself - -#define NETCONN_ROOMLEAVE_ABANDONED 0 //!< The room was closed because the chief left -#define NETCONN_ROOMLEAVE_KICKED 1 //!< You have been kicked from the room - -#define NETCONN_MSG_TYPE_PLAYERINFO 0 //!< A response to flib_netconn_send_playerInfo -#define NETCONN_MSG_TYPE_SERVERMESSAGE 1 //!< The welcome message when connecting to the lobby -#define NETCONN_MSG_TYPE_WARNING 2 //!< A general warning message -#define NETCONN_MSG_TYPE_ERROR 3 //!< A general error message - -#define NETCONN_MAPCHANGE_FULL 0 -#define NETCONN_MAPCHANGE_MAP 1 -#define NETCONN_MAPCHANGE_MAPGEN 2 -#define NETCONN_MAPCHANGE_DRAWNMAP 3 -#define NETCONN_MAPCHANGE_MAZE_SIZE 4 -#define NETCONN_MAPCHANGE_TEMPLATE 5 -#define NETCONN_MAPCHANGE_THEME 6 -#define NETCONN_MAPCHANGE_SEED 7 - -typedef struct _flib_netconn flib_netconn; - -/** - * Create a new netplay connection with these parameters. - * The path to the data directory must end with a path delimiter (e.g. C:\Games\Hedgewars\Data\) - */ -flib_netconn *flib_netconn_create(const char *playerName, const char *dataDirPath, const char *host, int port); -void flib_netconn_destroy(flib_netconn *conn); - -/** - * Perform I/O operations and call callbacks if something interesting happens. - * Should be called regularly. - */ -void flib_netconn_tick(flib_netconn *conn); - -/** - * Are you currently the owner of this room? The return value only makes sense in - * NETCONN_STATE_ROOM and NETCONN_STATE_INGAME states. - */ -bool flib_netconn_is_chief(flib_netconn *conn); - -/** - * Returns the playername. This is *probably* the one provided on creation, but if that name was - * already taken, a different one could have been set by the onNickTaken callback or its default - * implementation. - */ -const char *flib_netconn_get_playername(flib_netconn *conn); - -/** - * Generate a game setup from the current room state. - * Returns NULL if the room state does not contain enough information for a complete game setup, - * or if an error occurs. - * - * The new gamesetup must be destroyed with flib_gamesetup_destroy(). - */ -flib_gamesetup *flib_netconn_create_gamesetup(flib_netconn *conn); - - - - -// Send functions needed when connecting and disconnecting - - /** - * Request a different nickname. - * This function only makes sense in reaction to an onNickTaken callback, because the netconn - * automatically requests the nickname you provide on creation, and once the server accepts the - * nickname it can no longer be changed. - */ - int flib_netconn_send_nick(flib_netconn *conn, const char *nick); - - /** - * Send the password in reply to a password request. - * If the server does not accept the password, you will be disconnected - * (NETCONN_DISCONNECT_AUTH_FAILED) - */ - int flib_netconn_send_password(flib_netconn *conn, const char *passwd); - - /** - * Tell the server that you want to leave. If successful, the server will disconnect you. - */ - int flib_netconn_send_quit(flib_netconn *conn, const char *quitmsg); - - -// Send functions that make sense both in the lobby and in rooms - - /** - * Send a chat message. This message is either sent to the lobby or the room, depending on - * whether you are in a room at the moment. The message is not echoed back to you. - */ - int flib_netconn_send_chat(flib_netconn *conn, const char *chat); - - /** - * Kick a player. This has different meanings in the lobby and in a room; - * In the lobby, it will kick the player from the server, and you need to be a server admin to - * do it. In a room, it will kick the player from the room, and you need to be room chief. - */ - int flib_netconn_send_kick(flib_netconn *conn, const char *playerName); - - /** - * Request information about a player (e.g. current room, version, partial IP). If the action - * succeeds, you will receive an onMessage callback with NETCONN_MSG_TYPE_PLAYERINFO containing - * the requested information. - */ - int flib_netconn_send_playerInfo(flib_netconn *conn, const char *playerName); - - -// Send functions that only make sense in the lobby - - /** - * Request an update of the room list. Only makes sense when in lobby state. - * If the action succeeds, you will receive an onRoomlist callback containing the current room - * data. - */ - int flib_netconn_send_request_roomlist(flib_netconn *conn); - - /** - * Join a room as guest (not chief). Only makes sense when in lobby state. If the action - * succeeds, you will receive an onEnterRoom callback with chief=false followed by other - * callbacks with current room information. - */ - int flib_netconn_send_joinRoom(flib_netconn *conn, const char *room); - - /** - * Follow a player. Only valid in the lobby. If the player is in a room (or in a game), this - * command is analogous to calling flib_netconn_send_joinRoom with that room. - */ - int flib_netconn_send_playerFollow(flib_netconn *conn, const char *playerName); - - /** - * Create and join a new room. Only makes sense when in lobby state. If the action succeeds, - * you will receive an onEnterRoom callback with chief=true. - */ - int flib_netconn_send_createRoom(flib_netconn *conn, const char *room); - - /** - * Ban a player. The scope of this ban depends on whether you are in a room or in the lobby. - * In a room, you need to be the room chief, and the ban will apply to the room only. In the - * lobby, you need to be server admin to ban someone, and the ban applies to the entire server. - */ - int flib_netconn_send_ban(flib_netconn *conn, const char *playerName); - - /** - * Does something administrator-y. At any rate you need to be an administrator and in the lobby - * to use this command. - */ - int flib_netconn_send_clearAccountsCache(flib_netconn *conn); - - /** - * Sets a server variable to the indicated value. Only makes sense if you are server admin and - * in the lobby. Known variables are MOTD_NEW, MOTD_OLD and LATEST_PROTO. MOTD_OLD is shown to - * players with older protocol versions, to inform them that they might want to update. - */ - int flib_netconn_send_setServerVar(flib_netconn *conn, const char *name, const char *value); - - /** - * Queries all server variables. Only makes sense if you are server admin and in the lobby. - * If the action succeeds, you will receive several onServerVar callbacks with the - * current values of all server variables. - */ - int flib_netconn_send_getServerVars(flib_netconn *conn); - - -// Send functions that only make sense in a room - - /** - * Leave the room for the lobby. Only makes sense in room state. msg can be NULL if you don't - * want to send a message. The server always accepts a part command, so once you send it off, - * you can just assume that you are back in the lobby. - */ - int flib_netconn_send_leaveRoom(flib_netconn *conn, const char *msg); - - /** - * Change your "ready" status in the room. Only makes sense when in room state. If the action - * succeeds, you will receive an onClientFlags callback containing the change. - */ - int flib_netconn_send_toggleReady(flib_netconn *conn); - - /** - * Add a team to the current room. Apart from the "fixed" team information, this also includes - * the color, but not the number of hogs. Only makes sense when in room state. If the action - * succeeds, you will receive an onTeamAccepted callback with the name of the team. - * - * Notes: Technically, sending a color here is the only way for a non-chief to set the color of - * her own team. The server remembers this color and even generates a separate teamColor message - * to inform everyone of it. However, at the moment the frontends generally override this color - * with one they choose themselves in order to deal with unfortunate behavior of the QtFrontend, - * which always sends color index 0 when adding a team but thinks that the team has a random - * color. The chief always sends a new color in order to bring the QtFrontend back into sync. - */ - int flib_netconn_send_addTeam(flib_netconn *conn, const flib_team *team); - - /** - * Remove the team with the name teamname. Only makes sense when in room state. - * The server does not send a reply on success. - */ - int flib_netconn_send_removeTeam(flib_netconn *conn, const char *teamname); - - -// Send functions that only make sense in a room and if you are room chief - - /** - * Rename the current room. Only makes sense in room state and if you are chief. If the action - * succeeds, you (and everyone else on the server) will receive an onRoomUpdate message - * containing the change. - */ - int flib_netconn_send_renameRoom(flib_netconn *conn, const char *roomName); - - /** - * Set the number of hogs for a team. Only makes sense in room state and if you are chief. - * The server does not send a reply. - */ - int flib_netconn_send_teamHogCount(flib_netconn *conn, const char *teamname, int hogcount); - - /** - * Set the teamcolor of a team. Only makes sense in room state and if you are chief. - * The server does not send a reply. - */ - int flib_netconn_send_teamColor(flib_netconn *conn, const char *teamname, int colorIndex); - - /** - * Set the weaponset for the room. Only makes sense in room state and if you are chief. - * The server does not send a reply. - */ - int flib_netconn_send_weaponset(flib_netconn *conn, const flib_weaponset *weaponset); - - /** - * Set the map for the room. Only makes sense in room state and if you are chief. - * The server does not send a reply. - */ - int flib_netconn_send_map(flib_netconn *conn, const flib_map *map); - - /** - * Set the mapname. Only makes sense in room state and if you are chief. - * The server does not send a reply. - */ - int flib_netconn_send_mapName(flib_netconn *conn, const char *mapName); - - /** - * Set the map generator (regular, maze, drawn, named). Only makes sense in room state and if - * you are chief. - * The server does not send a reply. - */ - int flib_netconn_send_mapGen(flib_netconn *conn, int mapGen); - - /** - * Set the map template for regular maps. Only makes sense in room state and if you are chief. - * The server does not send a reply. - */ - int flib_netconn_send_mapTemplate(flib_netconn *conn, int templateFilter); - - /** - * Set the maze template (maze size) for mazes. Only makes sense in room state and if you are - * chief. The server does not send a reply. - */ - int flib_netconn_send_mapMazeSize(flib_netconn *conn, int mazeSize); - - /** - * Set the seed for the map. Only makes sense in room state and if you are chief. - * The server does not send a reply. - */ - int flib_netconn_send_mapSeed(flib_netconn *conn, const char *seed); - - /** - * Set the theme for the map. Only makes sense in room state and if you are chief. - * The server does not send a reply. - */ - int flib_netconn_send_mapTheme(flib_netconn *conn, const char *theme); - - /** - * Set the draw data for the drawn map. Only makes sense in room state and if you are chief. - * The server does not send a reply. - */ - int flib_netconn_send_mapDrawdata(flib_netconn *conn, const uint8_t *drawData, size_t size); - - /** - * Set the script (game style). Only makes sense in room state and if you are chief. - * The server does not send a reply. - */ - int flib_netconn_send_script(flib_netconn *conn, const char *scriptName); - - /** - * Set the scheme. Only makes sense in room state and if you are chief. - * The server does not send a reply. - */ - int flib_netconn_send_scheme(flib_netconn *conn, const flib_scheme *scheme); - - /** - * Signal that you want to start the game. Only makes sense in room state and if you are chief. - * The server will check whether all players are ready and whether it believes the setup makes - * sense (e.g. more than one clan). If the server is satisfied, you will receive an onRunGame - * callback (all other clients in the room are notified the same way). Otherwise the server - * might answer with a warning, or might not answer at all. - */ - int flib_netconn_send_startGame(flib_netconn *conn); - - /** - * Allow/forbid players to join the room. Only makes sense in room state and if you are chief. - * The server does not send a reply. - */ - int flib_netconn_send_toggleRestrictJoins(flib_netconn *conn); - - /** - * Allow/forbid adding teams to the room. Only makes sense in room state and if you are chief. - * The server does not send a reply. - */ - int flib_netconn_send_toggleRestrictTeams(flib_netconn *conn); - - -// Send functions that are only needed for running a game - - /** - * Send a teamchat message, forwarded from the engine. Only makes sense ingame. - * The server does not send a reply. In contrast to a Chat message, the server - * automatically converts this into an engine message and passes it on to the other - * clients. - */ - int flib_netconn_send_teamchat(flib_netconn *conn, const char *msg); - - /** - * Send an engine message. Only makes sense when ingame. In a networked game, you have to pass - * all the engine messages from the engine here, and they will be spread to all other clients - * in the game to keep the game in sync. - */ - int flib_netconn_send_engineMessage(flib_netconn *conn, const uint8_t *message, size_t size); - - /** - * Inform the server that the round has ended. Call this when the engine has disconnected, - * passing 1 if the round ended normally, 0 otherwise. - */ - int flib_netconn_send_roundfinished(flib_netconn *conn, bool withoutError); - - - - - -// Callbacks that are important for connecting/disconnecting - - /** - * onNickTaken is called when connecting to the server, if it turns out that there is already a - * player with the same nick. - * In order to proceed, a new nickname needs to be sent to the server using - * flib_netconn_send_nick() (or of course you can bail out and send a QUIT). - * If you don't set a callback, the netconn will automatically react by generating a new name. - */ - void flib_netconn_onNickTaken(flib_netconn *conn, void (*callback)(void *context, const char *nick), void* context); - - /** - * When connecting with a registered nickname, the server will ask for a password before - * admitting you in. This callback is called when that happens. As a reaction, you can send the - * password using flib_netconn_send_password. If you don't register a callback, the default - * behavior is to just quit in a way that will cause a disconnect with - * NETCONN_DISCONNECT_AUTH_FAILED. - * - * You can't just choose a new nickname when you receive this callback, because at that point - * the server has already accepted your nick. - */ - void flib_netconn_onPasswordRequest(flib_netconn *conn, void (*callback)(void *context, const char *nick), void* context); - - /** - * This is called when the server has accepted our nickname (and possibly password) and we have - * entered the lobby. - */ - void flib_netconn_onConnected(flib_netconn *conn, void (*callback)(void *context), void* context); - - /** - * This is always the last callback (unless the netconn is destroyed early), and the netconn - * should be destroyed when it is received. The reason for the disconnect is passed as one of - * the NETCONN_DISCONNECT_ constants. Sometimes a message is included as well, but that - * parameter might also be NULL. - */ - void flib_netconn_onDisconnected(flib_netconn *conn, void (*callback)(void *context, int reason, const char *message), void* context); - - -// Callbacks that make sense in most situations - - /** - * Callback for several informational messages that should be displayed to the user - * (e.g. in the chat window), but do not require a reaction. If a game is running, you might - * want to redirect some of these messages to the engine as well so the user will see them. - */ - void flib_netconn_onMessage(flib_netconn *conn, void (*callback)(void *context, int msgtype, const char *msg), void* context); - - /** - * We received a chat message. Where this message belongs depends on the current state - * (lobby/room). If a game is running the message should be passed to the engine. - */ - void flib_netconn_onChat(flib_netconn *conn, void (*callback)(void *context, const char *nick, const char *msg), void* context); - - /** - * Callbacks for incremental room list updates. They will fire whenever these events occur, - * even before you first query the actual roomlist - so be sure not to blindly reference your - * room list in these callbacks. The server currently only sends updates when a room changes - * its name, so in order to update other room information you need to query the roomlist again - * (see send_request_roomlist / onRoomlist). - */ - void flib_netconn_onRoomAdd(flib_netconn *conn, void (*callback)(void *context, const flib_room *room), void* context); - void flib_netconn_onRoomDelete(flib_netconn *conn, void (*callback)(void *context, const char *name), void* context); - void flib_netconn_onRoomUpdate(flib_netconn *conn, void (*callback)(void *context, const char *oldName, const flib_room *room), void* context); - - /** - * Callbacks for players joining or leaving the lobby. In contrast to the roomlist updates, you - * will get a JOIN callback for every player already on the server when you join (and there is - * no direct way to query the current playerlist) - * - * NOTE: partMessage may be NULL. - */ - void flib_netconn_onLobbyJoin(flib_netconn *conn, void (*callback)(void *context, const char *nick), void* context); - void flib_netconn_onLobbyLeave(flib_netconn *conn, void (*callback)(void *context, const char *nick, const char *partMessage), void* context); - - /** - * This is called when the server informs us that one or more flags associated with a - * player/client have changed. - * - * nick is the name of the player, flags is a string containing one character for each modified - * flag (see below), and newFlagState signals whether the flags should be set to true or false. - * - * Some of these flags are important for protocol purposes (especially if they are set for you) - * while others are just informational. Also, some flags are only relevant for players who are - * in the same room as you, and the server will not inform you if they change for others. - * - * These are the currently known/used flags: - * a: Server admin. Always updated. - * h: Room chief. Updated when in the same room. - * r: Ready to play. Updated when in the same room. - * u: Registered user. Always updated. - * - * The server tells us the 'a' and 'u' flags for all players when we first join the lobby, and - * also tells us the 'r' and 'h' flags when we join or create a room. It assumes that all flags - * are initially false, so it will typically only tell you to set certain flags to true when - * transmitting the initial states. Reset the 'h' and 'r' flags to false when leaving a room, - * or when entering room state, to arrive at the right state for each player. - * - * The room chief state of yourself is particularly important because it determines whether you - * can modify settings of the current room. Generally, when you create a room you start out - * being room chief, and when you join an existing room you are not. However, if the original - * chief leaves a room, the server can choose a new chief, and if that happens the chief flag - * will be transferred to someone else. - */ - void flib_netconn_onClientFlags(flib_netconn *conn, void (*callback)(void *context, const char *nick, const char *flags, bool newFlagState), void *context); - -// Callbacks that happen only in response to specific requests - - /** - * Response to flib_netconn_send_request_roomlist(). - * The rooms array contains the current state of all rooms on the server. - */ - void flib_netconn_onRoomlist(flib_netconn *conn, void (*callback)(void *context, const flib_room **rooms, int roomCount), void* context); - - /** - * Response to flib_netconn_send_joinRoom, flib_netconn_send_playerFollow or - * flib_netconn_send_createRoom. - * - * You just left the lobby and entered a room. - * If chief is true, you can and should send a full configuration for the room now. This - * consists of ammo, scheme, script and map, where map apparently has to come last. - */ - void flib_netconn_onEnterRoom(flib_netconn *conn, void (*callback)(void *context, bool chief), void *context); - - /** - * Response to flib_netconn_send_addTeam. - * The server might reject your team for several reasons, e.g. because it has the same name as - * an existing team, or because the room chief restricted adding new teams. If the team is - * accepted by the server, this callback is fired. - * - * If you are the room chief, you are expected to provide the hog count for your own team now - * using flib_netconn_send_teamHogCount. The color of the team is already set to the one you - * provided in addTeam. - */ - void flib_netconn_onTeamAccepted(flib_netconn *conn, void (*callback)(void *context, const char *team), void *context); - - /** - * When you query the server vars with flib_netconn_send_getServerVars (only works as admin), - * the server replies with a list of them. This callback is called for each entry in that list. - */ - void flib_netconn_onServerVar(flib_netconn *conn, void (*callback)(void *context, const char *name, const char *value), void *context); - - -// Callbacks that are only relevant in a room - - /** - * You just left a room and entered the lobby again. - * reason is one of the NETCONN_ROOMLEAVE_ constants (usually a kick). - * This will not be called when you actively leave a room using PART. - * Don't confuse with onRoomLeave, which indicates that *someone else* left the room. - */ - void flib_netconn_onLeaveRoom(flib_netconn *conn, void (*callback)(void *context, int reason, const char *message), void *context); - - /** - * Someone joined or left the room you are currently in. - * Analogous to onLobbyJoin/leave, you will receive the join callback for all players that are - * already in the room when you join, including for yourself (this is actually how it is - * determined that you joined a room). - * - * However, you will *not* receive onRoomLeave messages for everyone when you leave the room. - */ - void flib_netconn_onRoomJoin(flib_netconn *conn, void (*callback)(void *context, const char *nick), void* context); - void flib_netconn_onRoomLeave(flib_netconn *conn, void (*callback)(void *context, const char *nick, const char *partMessage), void* context); - - /** - * A new team was added to the room. The person who adds a team does NOT receive this callback - * (he gets onTeamAccepted instead). - * - * The team does not contain bindings, stats, weaponset, color or the number of hogs (but it is - * assumed to be the default of 4). - * - * If you receive this message and you are the room chief, you may want to send a color and hog - * count for this team using flib_netconn_send_teamHogCount / teamColor for QtFrontend - * compatibility. - * - * The server currently sends another message with the color of the team to the same recipients - * as this teamAdd message, which will trigger an onTeamColorChanged callback. See the - * description of flib_netconn_send_addTeam for more information. - */ - void flib_netconn_onTeamAdd(flib_netconn *conn, void (*callback)(void *context, const flib_team *team), void *context); - - /** - * A team was removed from the room. The person who removed the team will not receive this - * callback. - */ - void flib_netconn_onTeamDelete(flib_netconn *conn, void (*callback)(void *context, const char *teamname), void *context); - - /** - * The number of hogs in a team has been changed by the room chief. If you are the chief and - * change the number of hogs yourself, you will not receive this callback. - */ - void flib_netconn_onHogCountChanged(flib_netconn *conn, void (*callback)(void *context, const char *teamName, int hogs), void *context); - - /** - * The color of a team has been set or changed. The client who set or changed the color will - * not receive this callback. - * - * Normally, only the chief can change the color of a team. However, this message is also - * generated when a team is added, so you can receive it even as chief. - */ - void flib_netconn_onTeamColorChanged(flib_netconn *conn, void (*callback)(void *context, const char *teamName, int colorIndex), void *context); - - /** - * The room chief has changed the game scheme (or you just joined a room). - * You will not receive this callback if you changed the scheme yourself. - */ - void flib_netconn_onSchemeChanged(flib_netconn *conn, void (*callback)(void *context, const flib_scheme *scheme), void *context); - - /** - * The room chief has changed the map (or you just joined a room). Only non-chiefs receive these - * messages. - * - * To reduce the number of callback functions, the netconn keeps track of the current map - * settings and always passes the entire current map config, but informs the callee about what - * has changed (see the NETCONN_MAPCHANGE_ constants). - * - * Caution: Due to the way the protocol works, the map might not be complete at this point if it - * is a hand-drawn map, because the "full" map config does not include the drawn map data. - */ - void flib_netconn_onMapChanged(flib_netconn *conn, void (*callback)(void *context, const flib_map *map, int changetype), void *context); - - /** - * The room chief has changed the game style (or you just joined a room). If you are the chief - * and change the style yourself, you will not receive this callback. - */ - void flib_netconn_onScriptChanged(flib_netconn *conn, void (*callback)(void *context, const char *script), void *context); - - /** - * The room chief has changed the weaponset (or you just joined a room). If you are the chief - * and change the weaponset yourself, you will not receive this callback. - */ - void flib_netconn_onWeaponsetChanged(flib_netconn *conn, void (*callback)(void *context, const flib_weaponset *weaponset), void *context); - - /** - * The game is starting. Fire up the engine and join in! - * You can let the netconn generate the right game setup using flib_netconn_create_gamesetup - */ - void flib_netconn_onRunGame(flib_netconn *conn, void (*callback)(void *context), void *context); - - /** - * You are in a room, a game is in progress, and the server is sending you the new input for the - * engine to keep up to date with the current happenings. Pass it on to the engine using - * flib_gameconn_send_enginemsg. - */ - void flib_netconn_onEngineMessage(flib_netconn *conn, void (*callback)(void *context, const uint8_t *message, size_t size), void *context); - -#endif +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * This file contains functions for communicating with a Hedgewars server to chat, prepare and play + * rounds of Hedgewars. + * + * To use this, first create a netconn object by calling flib_netconn_create. This will start the + * connection to the game server (which might fail right away, the function returns null then). You + * should also register your callback functions right at the start to ensure you don't miss any + * callbacks. + * + * In order to allow the netconn to run, you should regularly call flib_netconn_tick(), which + * performs network I/O and calls your callbacks on interesting events. + * + * When the connection is closed, you will receive the onDisconnect callback. This is the signal to + * destroy the netconn and stop calling tick(). + * + * The connection process lasts from the time you create the netconn until you receive the + * onConnected callback (or onDisconnected in case something goes wrong). During that time, you + * might receive the onNickTaken and onPasswordRequest callbacks; see their description for more + * information on how to handle them. You could also receive other callbacks during connecting (e.g. + * about the room list), but it should be safe to ignore them. + * + * Once you are connected, you are in the lobby, and you can enter rooms and leave them again. The + * room and lobby states have different protocols, so many commands only work in either one or the + * other. If you are in a room you might also be in a game, but most of the functions behave the + * same ingame as in a room. + * + * The state changes from lobby to room when the server tells you that you just entered one, which + * will also trigger the onEnterRoom callback. This usually happens in reply to either a joinRoom, + * createRoom or playerFollow command. + * + * The state changes back to lobby when the room is dissolved, when you are kicked from the room, or + * when you actively leave the room using flib_netconn_send_leaveRoom. The first two events will + * trigger the onLeaveRoom callback. + */ + +#ifndef NETCONN_H_ +#define NETCONN_H_ + +#include "../model/gamesetup.h" +#include "../model/scheme.h" +#include "../model/room.h" + +#include +#include +#include + +#define NETCONN_STATE_CONNECTING 0 +#define NETCONN_STATE_LOBBY 1 +#define NETCONN_STATE_ROOM 2 +#define NETCONN_STATE_DISCONNECTED 10 + +#define NETCONN_DISCONNECT_NORMAL 0 //!< The connection was closed normally +#define NETCONN_DISCONNECT_SERVER_TOO_OLD 1 //!< The server has a lower protocol version than we do +#define NETCONN_DISCONNECT_AUTH_FAILED 2 //!< You sent a password with flib_netconn_send_password that was not accepted +#define NETCONN_DISCONNECT_CONNLOST 3 //!< The network connection was lost +#define NETCONN_DISCONNECT_INTERNAL_ERROR 100 //!< Something went wrong in frontlib itself + +#define NETCONN_ROOMLEAVE_ABANDONED 0 //!< The room was closed because the chief left +#define NETCONN_ROOMLEAVE_KICKED 1 //!< You have been kicked from the room + +#define NETCONN_MSG_TYPE_PLAYERINFO 0 //!< A response to flib_netconn_send_playerInfo +#define NETCONN_MSG_TYPE_SERVERMESSAGE 1 //!< The welcome message when connecting to the lobby +#define NETCONN_MSG_TYPE_WARNING 2 //!< A general warning message +#define NETCONN_MSG_TYPE_ERROR 3 //!< A general error message + +#define NETCONN_MAPCHANGE_FULL 0 +#define NETCONN_MAPCHANGE_MAP 1 +#define NETCONN_MAPCHANGE_MAPGEN 2 +#define NETCONN_MAPCHANGE_DRAWNMAP 3 +#define NETCONN_MAPCHANGE_MAZE_SIZE 4 +#define NETCONN_MAPCHANGE_TEMPLATE 5 +#define NETCONN_MAPCHANGE_THEME 6 +#define NETCONN_MAPCHANGE_SEED 7 + +typedef struct _flib_netconn flib_netconn; + +/** + * Create a new netplay connection with these parameters. + * The path to the data directory must end with a path delimiter (e.g. C:\Games\Hedgewars\Data\) + */ +flib_netconn *flib_netconn_create(const char *playerName, const char *dataDirPath, const char *host, int port); +void flib_netconn_destroy(flib_netconn *conn); + +/** + * Perform I/O operations and call callbacks if something interesting happens. + * Should be called regularly. + */ +void flib_netconn_tick(flib_netconn *conn); + +/** + * Are you currently the owner of this room? The return value only makes sense in + * NETCONN_STATE_ROOM and NETCONN_STATE_INGAME states. + */ +bool flib_netconn_is_chief(flib_netconn *conn); + +/** + * Returns the playername. This is *probably* the one provided on creation, but if that name was + * already taken, a different one could have been set by the onNickTaken callback or its default + * implementation. + */ +const char *flib_netconn_get_playername(flib_netconn *conn); + +/** + * Generate a game setup from the current room state. + * Returns NULL if the room state does not contain enough information for a complete game setup, + * or if an error occurs. + * + * The new gamesetup must be destroyed with flib_gamesetup_destroy(). + */ +flib_gamesetup *flib_netconn_create_gamesetup(flib_netconn *conn); + + + + +// Send functions needed when connecting and disconnecting + + /** + * Request a different nickname. + * This function only makes sense in reaction to an onNickTaken callback, because the netconn + * automatically requests the nickname you provide on creation, and once the server accepts the + * nickname it can no longer be changed. + */ + int flib_netconn_send_nick(flib_netconn *conn, const char *nick); + + /** + * Send the password in reply to a password request. + * If the server does not accept the password, you will be disconnected + * (NETCONN_DISCONNECT_AUTH_FAILED) + */ + int flib_netconn_send_password(flib_netconn *conn, const char *passwd); + + /** + * Tell the server that you want to leave. If successful, the server will disconnect you. + */ + int flib_netconn_send_quit(flib_netconn *conn, const char *quitmsg); + + +// Send functions that make sense both in the lobby and in rooms + + /** + * Send a chat message. This message is either sent to the lobby or the room, depending on + * whether you are in a room at the moment. The message is not echoed back to you. + */ + int flib_netconn_send_chat(flib_netconn *conn, const char *chat); + + /** + * Kick a player. This has different meanings in the lobby and in a room; + * In the lobby, it will kick the player from the server, and you need to be a server admin to + * do it. In a room, it will kick the player from the room, and you need to be room chief. + */ + int flib_netconn_send_kick(flib_netconn *conn, const char *playerName); + + /** + * Request information about a player (e.g. current room, version, partial IP). If the action + * succeeds, you will receive an onMessage callback with NETCONN_MSG_TYPE_PLAYERINFO containing + * the requested information. + */ + int flib_netconn_send_playerInfo(flib_netconn *conn, const char *playerName); + + +// Send functions that only make sense in the lobby + + /** + * Request an update of the room list. Only makes sense when in lobby state. + * If the action succeeds, you will receive an onRoomlist callback containing the current room + * data. + */ + int flib_netconn_send_request_roomlist(flib_netconn *conn); + + /** + * Join a room as guest (not chief). Only makes sense when in lobby state. If the action + * succeeds, you will receive an onEnterRoom callback with chief=false followed by other + * callbacks with current room information. + */ + int flib_netconn_send_joinRoom(flib_netconn *conn, const char *room); + + /** + * Follow a player. Only valid in the lobby. If the player is in a room (or in a game), this + * command is analogous to calling flib_netconn_send_joinRoom with that room. + */ + int flib_netconn_send_playerFollow(flib_netconn *conn, const char *playerName); + + /** + * Create and join a new room. Only makes sense when in lobby state. If the action succeeds, + * you will receive an onEnterRoom callback with chief=true. + */ + int flib_netconn_send_createRoom(flib_netconn *conn, const char *room); + + /** + * Ban a player. The scope of this ban depends on whether you are in a room or in the lobby. + * In a room, you need to be the room chief, and the ban will apply to the room only. In the + * lobby, you need to be server admin to ban someone, and the ban applies to the entire server. + */ + int flib_netconn_send_ban(flib_netconn *conn, const char *playerName); + + /** + * Does something administrator-y. At any rate you need to be an administrator and in the lobby + * to use this command. + */ + int flib_netconn_send_clearAccountsCache(flib_netconn *conn); + + /** + * Sets a server variable to the indicated value. Only makes sense if you are server admin and + * in the lobby. Known variables are MOTD_NEW, MOTD_OLD and LATEST_PROTO. MOTD_OLD is shown to + * players with older protocol versions, to inform them that they might want to update. + */ + int flib_netconn_send_setServerVar(flib_netconn *conn, const char *name, const char *value); + + /** + * Queries all server variables. Only makes sense if you are server admin and in the lobby. + * If the action succeeds, you will receive several onServerVar callbacks with the + * current values of all server variables. + */ + int flib_netconn_send_getServerVars(flib_netconn *conn); + + +// Send functions that only make sense in a room + + /** + * Leave the room for the lobby. Only makes sense in room state. msg can be NULL if you don't + * want to send a message. The server always accepts a part command, so once you send it off, + * you can just assume that you are back in the lobby. + */ + int flib_netconn_send_leaveRoom(flib_netconn *conn, const char *msg); + + /** + * Change your "ready" status in the room. Only makes sense when in room state. If the action + * succeeds, you will receive an onClientFlags callback containing the change. + */ + int flib_netconn_send_toggleReady(flib_netconn *conn); + + /** + * Add a team to the current room. Apart from the "fixed" team information, this also includes + * the color, but not the number of hogs. Only makes sense when in room state. If the action + * succeeds, you will receive an onTeamAccepted callback with the name of the team. + * + * Notes: Technically, sending a color here is the only way for a non-chief to set the color of + * her own team. The server remembers this color and even generates a separate teamColor message + * to inform everyone of it. However, at the moment the frontends generally override this color + * with one they choose themselves in order to deal with unfortunate behavior of the QtFrontend, + * which always sends color index 0 when adding a team but thinks that the team has a random + * color. The chief always sends a new color in order to bring the QtFrontend back into sync. + */ + int flib_netconn_send_addTeam(flib_netconn *conn, const flib_team *team); + + /** + * Remove the team with the name teamname. Only makes sense when in room state. + * The server does not send a reply on success. + */ + int flib_netconn_send_removeTeam(flib_netconn *conn, const char *teamname); + + +// Send functions that only make sense in a room and if you are room chief + + /** + * Rename the current room. Only makes sense in room state and if you are chief. If the action + * succeeds, you (and everyone else on the server) will receive an onRoomUpdate message + * containing the change. + */ + int flib_netconn_send_renameRoom(flib_netconn *conn, const char *roomName); + + /** + * Set the number of hogs for a team. Only makes sense in room state and if you are chief. + * The server does not send a reply. + */ + int flib_netconn_send_teamHogCount(flib_netconn *conn, const char *teamname, int hogcount); + + /** + * Set the teamcolor of a team. Only makes sense in room state and if you are chief. + * The server does not send a reply. + */ + int flib_netconn_send_teamColor(flib_netconn *conn, const char *teamname, int colorIndex); + + /** + * Set the weaponset for the room. Only makes sense in room state and if you are chief. + * The server does not send a reply. + */ + int flib_netconn_send_weaponset(flib_netconn *conn, const flib_weaponset *weaponset); + + /** + * Set the map for the room. Only makes sense in room state and if you are chief. + * The server does not send a reply. + */ + int flib_netconn_send_map(flib_netconn *conn, const flib_map *map); + + /** + * Set the mapname. Only makes sense in room state and if you are chief. + * The server does not send a reply. + */ + int flib_netconn_send_mapName(flib_netconn *conn, const char *mapName); + + /** + * Set the map generator (regular, maze, drawn, named). Only makes sense in room state and if + * you are chief. + * The server does not send a reply. + */ + int flib_netconn_send_mapGen(flib_netconn *conn, int mapGen); + + /** + * Set the map template for regular maps. Only makes sense in room state and if you are chief. + * The server does not send a reply. + */ + int flib_netconn_send_mapTemplate(flib_netconn *conn, int templateFilter); + + /** + * Set the maze template (maze size) for mazes. Only makes sense in room state and if you are + * chief. The server does not send a reply. + */ + int flib_netconn_send_mapMazeSize(flib_netconn *conn, int mazeSize); + + /** + * Set the seed for the map. Only makes sense in room state and if you are chief. + * The server does not send a reply. + */ + int flib_netconn_send_mapSeed(flib_netconn *conn, const char *seed); + + /** + * Set the theme for the map. Only makes sense in room state and if you are chief. + * The server does not send a reply. + */ + int flib_netconn_send_mapTheme(flib_netconn *conn, const char *theme); + + /** + * Set the draw data for the drawn map. Only makes sense in room state and if you are chief. + * The server does not send a reply. + */ + int flib_netconn_send_mapDrawdata(flib_netconn *conn, const uint8_t *drawData, size_t size); + + /** + * Set the script (game style). Only makes sense in room state and if you are chief. + * The server does not send a reply. + */ + int flib_netconn_send_script(flib_netconn *conn, const char *scriptName); + + /** + * Set the scheme. Only makes sense in room state and if you are chief. + * The server does not send a reply. + */ + int flib_netconn_send_scheme(flib_netconn *conn, const flib_scheme *scheme); + + /** + * Signal that you want to start the game. Only makes sense in room state and if you are chief. + * The server will check whether all players are ready and whether it believes the setup makes + * sense (e.g. more than one clan). If the server is satisfied, you will receive an onRunGame + * callback (all other clients in the room are notified the same way). Otherwise the server + * might answer with a warning, or might not answer at all. + */ + int flib_netconn_send_startGame(flib_netconn *conn); + + /** + * Allow/forbid players to join the room. Only makes sense in room state and if you are chief. + * The server does not send a reply. + */ + int flib_netconn_send_toggleRestrictJoins(flib_netconn *conn); + + /** + * Allow/forbid adding teams to the room. Only makes sense in room state and if you are chief. + * The server does not send a reply. + */ + int flib_netconn_send_toggleRestrictTeams(flib_netconn *conn); + + +// Send functions that are only needed for running a game + + /** + * Send a teamchat message, forwarded from the engine. Only makes sense ingame. + * The server does not send a reply. In contrast to a Chat message, the server + * automatically converts this into an engine message and passes it on to the other + * clients. + */ + int flib_netconn_send_teamchat(flib_netconn *conn, const char *msg); + + /** + * Send an engine message. Only makes sense when ingame. In a networked game, you have to pass + * all the engine messages from the engine here, and they will be spread to all other clients + * in the game to keep the game in sync. + */ + int flib_netconn_send_engineMessage(flib_netconn *conn, const uint8_t *message, size_t size); + + /** + * Inform the server that the round has ended. Call this when the engine has disconnected, + * passing 1 if the round ended normally, 0 otherwise. + */ + int flib_netconn_send_roundfinished(flib_netconn *conn, bool withoutError); + + + + + +// Callbacks that are important for connecting/disconnecting + + /** + * onNickTaken is called when connecting to the server, if it turns out that there is already a + * player with the same nick. + * In order to proceed, a new nickname needs to be sent to the server using + * flib_netconn_send_nick() (or of course you can bail out and send a QUIT). + * If you don't set a callback, the netconn will automatically react by generating a new name. + */ + void flib_netconn_onNickTaken(flib_netconn *conn, void (*callback)(void *context, const char *nick), void* context); + + /** + * When connecting with a registered nickname, the server will ask for a password before + * admitting you in. This callback is called when that happens. As a reaction, you can send the + * password using flib_netconn_send_password. If you don't register a callback, the default + * behavior is to just quit in a way that will cause a disconnect with + * NETCONN_DISCONNECT_AUTH_FAILED. + * + * You can't just choose a new nickname when you receive this callback, because at that point + * the server has already accepted your nick. + */ + void flib_netconn_onPasswordRequest(flib_netconn *conn, void (*callback)(void *context, const char *nick), void* context); + + /** + * This is called when the server has accepted our nickname (and possibly password) and we have + * entered the lobby. + */ + void flib_netconn_onConnected(flib_netconn *conn, void (*callback)(void *context), void* context); + + /** + * This is always the last callback (unless the netconn is destroyed early), and the netconn + * should be destroyed when it is received. The reason for the disconnect is passed as one of + * the NETCONN_DISCONNECT_ constants. Sometimes a message is included as well, but that + * parameter might also be NULL. + */ + void flib_netconn_onDisconnected(flib_netconn *conn, void (*callback)(void *context, int reason, const char *message), void* context); + + +// Callbacks that make sense in most situations + + /** + * Callback for several informational messages that should be displayed to the user + * (e.g. in the chat window), but do not require a reaction. If a game is running, you might + * want to redirect some of these messages to the engine as well so the user will see them. + */ + void flib_netconn_onMessage(flib_netconn *conn, void (*callback)(void *context, int msgtype, const char *msg), void* context); + + /** + * We received a chat message. Where this message belongs depends on the current state + * (lobby/room). If a game is running the message should be passed to the engine. + */ + void flib_netconn_onChat(flib_netconn *conn, void (*callback)(void *context, const char *nick, const char *msg), void* context); + + /** + * Callbacks for incremental room list updates. They will fire whenever these events occur, + * even before you first query the actual roomlist - so be sure not to blindly reference your + * room list in these callbacks. The server currently only sends updates when a room changes + * its name, so in order to update other room information you need to query the roomlist again + * (see send_request_roomlist / onRoomlist). + */ + void flib_netconn_onRoomAdd(flib_netconn *conn, void (*callback)(void *context, const flib_room *room), void* context); + void flib_netconn_onRoomDelete(flib_netconn *conn, void (*callback)(void *context, const char *name), void* context); + void flib_netconn_onRoomUpdate(flib_netconn *conn, void (*callback)(void *context, const char *oldName, const flib_room *room), void* context); + + /** + * Callbacks for players joining or leaving the lobby. In contrast to the roomlist updates, you + * will get a JOIN callback for every player already on the server when you join (and there is + * no direct way to query the current playerlist) + * + * NOTE: partMessage may be NULL. + */ + void flib_netconn_onLobbyJoin(flib_netconn *conn, void (*callback)(void *context, const char *nick), void* context); + void flib_netconn_onLobbyLeave(flib_netconn *conn, void (*callback)(void *context, const char *nick, const char *partMessage), void* context); + + /** + * This is called when the server informs us that one or more flags associated with a + * player/client have changed. + * + * nick is the name of the player, flags is a string containing one character for each modified + * flag (see below), and newFlagState signals whether the flags should be set to true or false. + * + * Some of these flags are important for protocol purposes (especially if they are set for you) + * while others are just informational. Also, some flags are only relevant for players who are + * in the same room as you, and the server will not inform you if they change for others. + * + * These are the currently known/used flags: + * a: Server admin. Always updated. + * h: Room chief. Updated when in the same room. + * r: Ready to play. Updated when in the same room. + * u: Registered user. Always updated. + * + * The server tells us the 'a' and 'u' flags for all players when we first join the lobby, and + * also tells us the 'r' and 'h' flags when we join or create a room. It assumes that all flags + * are initially false, so it will typically only tell you to set certain flags to true when + * transmitting the initial states. Reset the 'h' and 'r' flags to false when leaving a room, + * or when entering room state, to arrive at the right state for each player. + * + * The room chief state of yourself is particularly important because it determines whether you + * can modify settings of the current room. Generally, when you create a room you start out + * being room chief, and when you join an existing room you are not. However, if the original + * chief leaves a room, the server can choose a new chief, and if that happens the chief flag + * will be transferred to someone else. + */ + void flib_netconn_onClientFlags(flib_netconn *conn, void (*callback)(void *context, const char *nick, const char *flags, bool newFlagState), void *context); + +// Callbacks that happen only in response to specific requests + + /** + * Response to flib_netconn_send_request_roomlist(). + * The rooms array contains the current state of all rooms on the server. + */ + void flib_netconn_onRoomlist(flib_netconn *conn, void (*callback)(void *context, const flib_room **rooms, int roomCount), void* context); + + /** + * Response to flib_netconn_send_joinRoom, flib_netconn_send_playerFollow or + * flib_netconn_send_createRoom. + * + * You just left the lobby and entered a room. + * If chief is true, you can and should send a full configuration for the room now. This + * consists of ammo, scheme, script and map, where map apparently has to come last. + */ + void flib_netconn_onEnterRoom(flib_netconn *conn, void (*callback)(void *context, bool chief), void *context); + + /** + * Response to flib_netconn_send_addTeam. + * The server might reject your team for several reasons, e.g. because it has the same name as + * an existing team, or because the room chief restricted adding new teams. If the team is + * accepted by the server, this callback is fired. + * + * If you are the room chief, you are expected to provide the hog count for your own team now + * using flib_netconn_send_teamHogCount. The color of the team is already set to the one you + * provided in addTeam. + */ + void flib_netconn_onTeamAccepted(flib_netconn *conn, void (*callback)(void *context, const char *team), void *context); + + /** + * When you query the server vars with flib_netconn_send_getServerVars (only works as admin), + * the server replies with a list of them. This callback is called for each entry in that list. + */ + void flib_netconn_onServerVar(flib_netconn *conn, void (*callback)(void *context, const char *name, const char *value), void *context); + + +// Callbacks that are only relevant in a room + + /** + * You just left a room and entered the lobby again. + * reason is one of the NETCONN_ROOMLEAVE_ constants (usually a kick). + * This will not be called when you actively leave a room using PART. + * Don't confuse with onRoomLeave, which indicates that *someone else* left the room. + */ + void flib_netconn_onLeaveRoom(flib_netconn *conn, void (*callback)(void *context, int reason, const char *message), void *context); + + /** + * Someone joined or left the room you are currently in. + * Analogous to onLobbyJoin/leave, you will receive the join callback for all players that are + * already in the room when you join, including for yourself (this is actually how it is + * determined that you joined a room). + * + * However, you will *not* receive onRoomLeave messages for everyone when you leave the room. + */ + void flib_netconn_onRoomJoin(flib_netconn *conn, void (*callback)(void *context, const char *nick), void* context); + void flib_netconn_onRoomLeave(flib_netconn *conn, void (*callback)(void *context, const char *nick, const char *partMessage), void* context); + + /** + * A new team was added to the room. The person who adds a team does NOT receive this callback + * (he gets onTeamAccepted instead). + * + * The team does not contain bindings, stats, weaponset, color or the number of hogs (but it is + * assumed to be the default of 4). + * + * If you receive this message and you are the room chief, you may want to send a color and hog + * count for this team using flib_netconn_send_teamHogCount / teamColor for QtFrontend + * compatibility. + * + * The server currently sends another message with the color of the team to the same recipients + * as this teamAdd message, which will trigger an onTeamColorChanged callback. See the + * description of flib_netconn_send_addTeam for more information. + */ + void flib_netconn_onTeamAdd(flib_netconn *conn, void (*callback)(void *context, const flib_team *team), void *context); + + /** + * A team was removed from the room. The person who removed the team will not receive this + * callback. + */ + void flib_netconn_onTeamDelete(flib_netconn *conn, void (*callback)(void *context, const char *teamname), void *context); + + /** + * The number of hogs in a team has been changed by the room chief. If you are the chief and + * change the number of hogs yourself, you will not receive this callback. + */ + void flib_netconn_onHogCountChanged(flib_netconn *conn, void (*callback)(void *context, const char *teamName, int hogs), void *context); + + /** + * The color of a team has been set or changed. The client who set or changed the color will + * not receive this callback. + * + * Normally, only the chief can change the color of a team. However, this message is also + * generated when a team is added, so you can receive it even as chief. + */ + void flib_netconn_onTeamColorChanged(flib_netconn *conn, void (*callback)(void *context, const char *teamName, int colorIndex), void *context); + + /** + * The room chief has changed the game scheme (or you just joined a room). + * You will not receive this callback if you changed the scheme yourself. + */ + void flib_netconn_onSchemeChanged(flib_netconn *conn, void (*callback)(void *context, const flib_scheme *scheme), void *context); + + /** + * The room chief has changed the map (or you just joined a room). Only non-chiefs receive these + * messages. + * + * To reduce the number of callback functions, the netconn keeps track of the current map + * settings and always passes the entire current map config, but informs the callee about what + * has changed (see the NETCONN_MAPCHANGE_ constants). + * + * Caution: Due to the way the protocol works, the map might not be complete at this point if it + * is a hand-drawn map, because the "full" map config does not include the drawn map data. + */ + void flib_netconn_onMapChanged(flib_netconn *conn, void (*callback)(void *context, const flib_map *map, int changetype), void *context); + + /** + * The room chief has changed the game style (or you just joined a room). If you are the chief + * and change the style yourself, you will not receive this callback. + */ + void flib_netconn_onScriptChanged(flib_netconn *conn, void (*callback)(void *context, const char *script), void *context); + + /** + * The room chief has changed the weaponset (or you just joined a room). If you are the chief + * and change the weaponset yourself, you will not receive this callback. + */ + void flib_netconn_onWeaponsetChanged(flib_netconn *conn, void (*callback)(void *context, const flib_weaponset *weaponset), void *context); + + /** + * The game is starting. Fire up the engine and join in! + * You can let the netconn generate the right game setup using flib_netconn_create_gamesetup + */ + void flib_netconn_onRunGame(flib_netconn *conn, void (*callback)(void *context), void *context); + + /** + * You are in a room, a game is in progress, and the server is sending you the new input for the + * engine to keep up to date with the current happenings. Pass it on to the engine using + * flib_gameconn_send_enginemsg. + */ + void flib_netconn_onEngineMessage(flib_netconn *conn, void (*callback)(void *context, const uint8_t *message, size_t size), void *context); + +#endif diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/net/netconn_callbacks.c --- a/project_files/frontlib/net/netconn_callbacks.c Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/net/netconn_callbacks.c Tue Nov 10 20:43:13 2015 +0100 @@ -1,149 +1,149 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "netconn_internal.h" - -#include "../util/logging.h" -#include "../util/util.h" - -#include -#include -#include - -static void defaultCallback_onMessage(void *context, int msgtype, const char *msg) { - flib_log_i("Net: [%i] %s", msgtype, msg); -} - -static void defaultCallback_onChat(void *context, const char *nick, const char *msg) { - flib_log_i("%s: %s", nick, msg); -} - -// Change the name by suffixing it with a number. If it already ends in a number, increase that number by 1. -static void defaultCallback_onNickTaken(void *context, const char *requestedNick) { - flib_netconn *conn = context; - size_t namelen = strlen(requestedNick); - int digits = 0; - while(digits0) { - suffix = atol(requestedNick+namelen-digits)+1; - } - char *newPlayerName = flib_asprintf("%.*s%li", namelen-digits, requestedNick, suffix); - if(newPlayerName) { - flib_netconn_send_nick(conn, newPlayerName); - } else { - flib_netconn_send_quit(conn, "Nick already taken."); - } - free(newPlayerName); -} - -// Default behavior: Quit -static void defaultCallback_onPasswordRequest(void *context, const char *requestedNick) { - flib_netconn_send_quit((flib_netconn*)context, "Authentication failed"); -} - -void netconn_clearCallbacks(flib_netconn *conn) { - flib_netconn_onMessage(conn, NULL, NULL); - flib_netconn_onConnected(conn, NULL, NULL); - flib_netconn_onDisconnected(conn, NULL, NULL); - flib_netconn_onRoomlist(conn, NULL, NULL); - flib_netconn_onRoomAdd(conn, NULL, NULL); - flib_netconn_onRoomDelete(conn, NULL, NULL); - flib_netconn_onRoomUpdate(conn, NULL, NULL); - flib_netconn_onClientFlags(conn, NULL, NULL); - flib_netconn_onChat(conn, NULL, NULL); - flib_netconn_onLobbyJoin(conn, NULL, NULL); - flib_netconn_onLobbyLeave(conn, NULL, NULL); - flib_netconn_onRoomJoin(conn, NULL, NULL); - flib_netconn_onRoomLeave(conn, NULL, NULL); - flib_netconn_onNickTaken(conn, NULL, NULL); - flib_netconn_onPasswordRequest(conn, NULL, NULL); - flib_netconn_onEnterRoom(conn, NULL, NULL); - flib_netconn_onLeaveRoom(conn, NULL, NULL); - flib_netconn_onTeamAdd(conn, NULL, NULL); - flib_netconn_onTeamDelete(conn, NULL, NULL); - flib_netconn_onRunGame(conn, NULL, NULL); - flib_netconn_onTeamAccepted(conn, NULL, NULL); - flib_netconn_onHogCountChanged(conn, NULL, NULL); - flib_netconn_onTeamColorChanged(conn, NULL, NULL); - flib_netconn_onEngineMessage(conn, NULL, NULL); - flib_netconn_onSchemeChanged(conn, NULL, NULL); - flib_netconn_onMapChanged(conn, NULL, NULL); - flib_netconn_onScriptChanged(conn, NULL, NULL); - flib_netconn_onWeaponsetChanged(conn, NULL, NULL); - flib_netconn_onServerVar(conn, NULL, NULL); -} - -/** - * This macro generates a callback setter function. It uses the name of the callback to - * automatically generate the function name and the fields to set, so a consistent naming - * convention needs to be enforced (not that that is a bad thing). If null is passed as - * callback to the generated function, the defaultCb will be set instead (with conn - * as the context). - */ -#define GENERATE_CB_SETTER(cbName, cbParameterTypes, defaultCb) \ - void flib_netconn_##cbName(flib_netconn *conn, void (*callback)cbParameterTypes, void *context) { \ - if(!log_badargs_if(conn==NULL)) { \ - conn->cbName##Cb = callback ? callback : &defaultCb; \ - conn->cbName##Ctx = callback ? context : conn; \ - } \ - } - -/** - * Generate a callback setter function like GENERATE_CB_SETTER, and automatically generate a - * no-op callback function as well that is used as default. - */ -#define GENERATE_CB_SETTER_AND_DEFAULT(cbName, cbParameterTypes) \ - static void _noop_callback_##cbName cbParameterTypes {} \ - GENERATE_CB_SETTER(cbName, cbParameterTypes, _noop_callback_##cbName) - -GENERATE_CB_SETTER(onMessage, (void *context, int msgtype, const char *msg), defaultCallback_onMessage); -GENERATE_CB_SETTER_AND_DEFAULT(onConnected, (void *context)); -GENERATE_CB_SETTER_AND_DEFAULT(onDisconnected, (void *context, int reason, const char *message)); -GENERATE_CB_SETTER_AND_DEFAULT(onRoomlist, (void *context, const flib_room **rooms, int roomCount)); -GENERATE_CB_SETTER_AND_DEFAULT(onRoomAdd, (void *context, const flib_room *room)); -GENERATE_CB_SETTER_AND_DEFAULT(onRoomDelete, (void *context, const char *name)); -GENERATE_CB_SETTER_AND_DEFAULT(onRoomUpdate, (void *context, const char *oldName, const flib_room *room)); -GENERATE_CB_SETTER_AND_DEFAULT(onClientFlags, (void *context, const char *nick, const char *flags, bool newFlagState)); -GENERATE_CB_SETTER(onChat, (void *context, const char *nick, const char *msg), defaultCallback_onChat); -GENERATE_CB_SETTER_AND_DEFAULT(onLobbyJoin, (void *context, const char *nick)); -GENERATE_CB_SETTER_AND_DEFAULT(onLobbyLeave, (void *context, const char *nick, const char *partMsg)); -GENERATE_CB_SETTER_AND_DEFAULT(onRoomJoin, (void *context, const char *nick)); -GENERATE_CB_SETTER_AND_DEFAULT(onRoomLeave, (void *context, const char *nick, const char *partMessage)); -GENERATE_CB_SETTER(onNickTaken, (void *context, const char *nick), defaultCallback_onNickTaken); -GENERATE_CB_SETTER(onPasswordRequest, (void *context, const char *nick), defaultCallback_onPasswordRequest); -GENERATE_CB_SETTER_AND_DEFAULT(onEnterRoom, (void *context, bool chief)); -GENERATE_CB_SETTER_AND_DEFAULT(onLeaveRoom, (void *context, int reason, const char *message)); -GENERATE_CB_SETTER_AND_DEFAULT(onTeamAdd, (void *context, const flib_team *team)); -GENERATE_CB_SETTER_AND_DEFAULT(onTeamDelete, (void *context, const char *teamname)); -GENERATE_CB_SETTER_AND_DEFAULT(onRunGame, (void *context)); -GENERATE_CB_SETTER_AND_DEFAULT(onTeamAccepted, (void *context, const char *teamName)); -GENERATE_CB_SETTER_AND_DEFAULT(onHogCountChanged, (void *context, const char *teamName, int hogs)); -GENERATE_CB_SETTER_AND_DEFAULT(onTeamColorChanged, (void *context, const char *teamName, int colorIndex)); -GENERATE_CB_SETTER_AND_DEFAULT(onEngineMessage, (void *context, const uint8_t *message, size_t size)); -GENERATE_CB_SETTER_AND_DEFAULT(onSchemeChanged, (void *context, const flib_scheme *scheme)); -GENERATE_CB_SETTER_AND_DEFAULT(onMapChanged, (void *context, const flib_map *map, int changetype)); -GENERATE_CB_SETTER_AND_DEFAULT(onScriptChanged, (void *context, const char *script)); -GENERATE_CB_SETTER_AND_DEFAULT(onWeaponsetChanged, (void *context, const flib_weaponset *weaponset)); -GENERATE_CB_SETTER_AND_DEFAULT(onServerVar, (void *context, const char *name, const char *value)); - -#undef GENERATE_CB_SETTER_AND_DEFAULT -#undef GENERATE_CB_SETTER +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "netconn_internal.h" + +#include "../util/logging.h" +#include "../util/util.h" + +#include +#include +#include + +static void defaultCallback_onMessage(void *context, int msgtype, const char *msg) { + flib_log_i("Net: [%i] %s", msgtype, msg); +} + +static void defaultCallback_onChat(void *context, const char *nick, const char *msg) { + flib_log_i("%s: %s", nick, msg); +} + +// Change the name by suffixing it with a number. If it already ends in a number, increase that number by 1. +static void defaultCallback_onNickTaken(void *context, const char *requestedNick) { + flib_netconn *conn = context; + size_t namelen = strlen(requestedNick); + int digits = 0; + while(digits0) { + suffix = atol(requestedNick+namelen-digits)+1; + } + char *newPlayerName = flib_asprintf("%.*s%li", namelen-digits, requestedNick, suffix); + if(newPlayerName) { + flib_netconn_send_nick(conn, newPlayerName); + } else { + flib_netconn_send_quit(conn, "Nick already taken."); + } + free(newPlayerName); +} + +// Default behavior: Quit +static void defaultCallback_onPasswordRequest(void *context, const char *requestedNick) { + flib_netconn_send_quit((flib_netconn*)context, "Authentication failed"); +} + +void netconn_clearCallbacks(flib_netconn *conn) { + flib_netconn_onMessage(conn, NULL, NULL); + flib_netconn_onConnected(conn, NULL, NULL); + flib_netconn_onDisconnected(conn, NULL, NULL); + flib_netconn_onRoomlist(conn, NULL, NULL); + flib_netconn_onRoomAdd(conn, NULL, NULL); + flib_netconn_onRoomDelete(conn, NULL, NULL); + flib_netconn_onRoomUpdate(conn, NULL, NULL); + flib_netconn_onClientFlags(conn, NULL, NULL); + flib_netconn_onChat(conn, NULL, NULL); + flib_netconn_onLobbyJoin(conn, NULL, NULL); + flib_netconn_onLobbyLeave(conn, NULL, NULL); + flib_netconn_onRoomJoin(conn, NULL, NULL); + flib_netconn_onRoomLeave(conn, NULL, NULL); + flib_netconn_onNickTaken(conn, NULL, NULL); + flib_netconn_onPasswordRequest(conn, NULL, NULL); + flib_netconn_onEnterRoom(conn, NULL, NULL); + flib_netconn_onLeaveRoom(conn, NULL, NULL); + flib_netconn_onTeamAdd(conn, NULL, NULL); + flib_netconn_onTeamDelete(conn, NULL, NULL); + flib_netconn_onRunGame(conn, NULL, NULL); + flib_netconn_onTeamAccepted(conn, NULL, NULL); + flib_netconn_onHogCountChanged(conn, NULL, NULL); + flib_netconn_onTeamColorChanged(conn, NULL, NULL); + flib_netconn_onEngineMessage(conn, NULL, NULL); + flib_netconn_onSchemeChanged(conn, NULL, NULL); + flib_netconn_onMapChanged(conn, NULL, NULL); + flib_netconn_onScriptChanged(conn, NULL, NULL); + flib_netconn_onWeaponsetChanged(conn, NULL, NULL); + flib_netconn_onServerVar(conn, NULL, NULL); +} + +/** + * This macro generates a callback setter function. It uses the name of the callback to + * automatically generate the function name and the fields to set, so a consistent naming + * convention needs to be enforced (not that that is a bad thing). If null is passed as + * callback to the generated function, the defaultCb will be set instead (with conn + * as the context). + */ +#define GENERATE_CB_SETTER(cbName, cbParameterTypes, defaultCb) \ + void flib_netconn_##cbName(flib_netconn *conn, void (*callback)cbParameterTypes, void *context) { \ + if(!log_badargs_if(conn==NULL)) { \ + conn->cbName##Cb = callback ? callback : &defaultCb; \ + conn->cbName##Ctx = callback ? context : conn; \ + } \ + } + +/** + * Generate a callback setter function like GENERATE_CB_SETTER, and automatically generate a + * no-op callback function as well that is used as default. + */ +#define GENERATE_CB_SETTER_AND_DEFAULT(cbName, cbParameterTypes) \ + static void _noop_callback_##cbName cbParameterTypes {} \ + GENERATE_CB_SETTER(cbName, cbParameterTypes, _noop_callback_##cbName) + +GENERATE_CB_SETTER(onMessage, (void *context, int msgtype, const char *msg), defaultCallback_onMessage); +GENERATE_CB_SETTER_AND_DEFAULT(onConnected, (void *context)); +GENERATE_CB_SETTER_AND_DEFAULT(onDisconnected, (void *context, int reason, const char *message)); +GENERATE_CB_SETTER_AND_DEFAULT(onRoomlist, (void *context, const flib_room **rooms, int roomCount)); +GENERATE_CB_SETTER_AND_DEFAULT(onRoomAdd, (void *context, const flib_room *room)); +GENERATE_CB_SETTER_AND_DEFAULT(onRoomDelete, (void *context, const char *name)); +GENERATE_CB_SETTER_AND_DEFAULT(onRoomUpdate, (void *context, const char *oldName, const flib_room *room)); +GENERATE_CB_SETTER_AND_DEFAULT(onClientFlags, (void *context, const char *nick, const char *flags, bool newFlagState)); +GENERATE_CB_SETTER(onChat, (void *context, const char *nick, const char *msg), defaultCallback_onChat); +GENERATE_CB_SETTER_AND_DEFAULT(onLobbyJoin, (void *context, const char *nick)); +GENERATE_CB_SETTER_AND_DEFAULT(onLobbyLeave, (void *context, const char *nick, const char *partMsg)); +GENERATE_CB_SETTER_AND_DEFAULT(onRoomJoin, (void *context, const char *nick)); +GENERATE_CB_SETTER_AND_DEFAULT(onRoomLeave, (void *context, const char *nick, const char *partMessage)); +GENERATE_CB_SETTER(onNickTaken, (void *context, const char *nick), defaultCallback_onNickTaken); +GENERATE_CB_SETTER(onPasswordRequest, (void *context, const char *nick), defaultCallback_onPasswordRequest); +GENERATE_CB_SETTER_AND_DEFAULT(onEnterRoom, (void *context, bool chief)); +GENERATE_CB_SETTER_AND_DEFAULT(onLeaveRoom, (void *context, int reason, const char *message)); +GENERATE_CB_SETTER_AND_DEFAULT(onTeamAdd, (void *context, const flib_team *team)); +GENERATE_CB_SETTER_AND_DEFAULT(onTeamDelete, (void *context, const char *teamname)); +GENERATE_CB_SETTER_AND_DEFAULT(onRunGame, (void *context)); +GENERATE_CB_SETTER_AND_DEFAULT(onTeamAccepted, (void *context, const char *teamName)); +GENERATE_CB_SETTER_AND_DEFAULT(onHogCountChanged, (void *context, const char *teamName, int hogs)); +GENERATE_CB_SETTER_AND_DEFAULT(onTeamColorChanged, (void *context, const char *teamName, int colorIndex)); +GENERATE_CB_SETTER_AND_DEFAULT(onEngineMessage, (void *context, const uint8_t *message, size_t size)); +GENERATE_CB_SETTER_AND_DEFAULT(onSchemeChanged, (void *context, const flib_scheme *scheme)); +GENERATE_CB_SETTER_AND_DEFAULT(onMapChanged, (void *context, const flib_map *map, int changetype)); +GENERATE_CB_SETTER_AND_DEFAULT(onScriptChanged, (void *context, const char *script)); +GENERATE_CB_SETTER_AND_DEFAULT(onWeaponsetChanged, (void *context, const flib_weaponset *weaponset)); +GENERATE_CB_SETTER_AND_DEFAULT(onServerVar, (void *context, const char *name, const char *value)); + +#undef GENERATE_CB_SETTER_AND_DEFAULT +#undef GENERATE_CB_SETTER diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/net/netconn_internal.h --- a/project_files/frontlib/net/netconn_internal.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/net/netconn_internal.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,151 +1,151 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * Common definitions needed by netconn functions, to allow splitting them into several files. - */ - -#ifndef NETCONN_INTERNAL_H_ -#define NETCONN_INTERNAL_H_ - -#include "netconn.h" -#include "netbase.h" -#include "../model/map.h" -#include "../model/team.h" -#include "../model/weapon.h" -#include "../model/room.h" - -#include -#include -#include - -struct _flib_netconn { - flib_netbase *netBase; - char *playerName; - char *dataDirPath; - - int netconnState; //!< One of the NETCONN_STATE constants - - bool isChief; //!< Player can modify the current room - flib_map *map; - flib_teamlist pendingTeamlist; - flib_teamlist teamlist; - flib_scheme *scheme; - char *style; - flib_weaponset *weaponset; - - void (*onMessageCb)(void *context, int msgtype, const char *msg); - void *onMessageCtx; - - void (*onConnectedCb)(void *context); - void *onConnectedCtx; - - void (*onDisconnectedCb)(void *context, int reason, const char *message); - void *onDisconnectedCtx; - - void (*onRoomlistCb)(void *context, const flib_room **rooms, int roomCount); - void *onRoomlistCtx; - - void (*onRoomAddCb)(void *context, const flib_room *room); - void *onRoomAddCtx; - - void (*onRoomDeleteCb)(void *context, const char *name); - void *onRoomDeleteCtx; - - void (*onRoomUpdateCb)(void *context, const char *oldName, const flib_room *room); - void *onRoomUpdateCtx; - - void (*onClientFlagsCb)(void *context, const char *nick, const char *flags, bool newFlagState); - void *onClientFlagsCtx; - - void (*onChatCb)(void *context, const char *nick, const char *msg); - void *onChatCtx; - - void (*onLobbyJoinCb)(void *context, const char *nick); - void *onLobbyJoinCtx; - - void (*onLobbyLeaveCb)(void *context, const char *nick, const char *partMessage); - void *onLobbyLeaveCtx; - - void (*onRoomJoinCb)(void *context, const char *nick); - void *onRoomJoinCtx; - - void (*onRoomLeaveCb)(void *context, const char *nick, const char *partMessage); - void *onRoomLeaveCtx; - - void (*onNickTakenCb)(void *context, const char *nick); - void *onNickTakenCtx; - - void (*onPasswordRequestCb)(void *context, const char *nick); - void *onPasswordRequestCtx; - - void (*onEnterRoomCb)(void *context, bool chief); - void *onEnterRoomCtx; - - void (*onLeaveRoomCb)(void *context, int reason, const char *message); - void *onLeaveRoomCtx; - - void (*onTeamAddCb)(void *context, const flib_team *team); - void *onTeamAddCtx; - - void (*onTeamDeleteCb)(void *context, const char *teamname); - void *onTeamDeleteCtx; - - void (*onRunGameCb)(void *context); - void *onRunGameCtx; - - void (*onTeamAcceptedCb)(void *context, const char *teamName); - void *onTeamAcceptedCtx; - - void (*onHogCountChangedCb)(void *context, const char *teamName, int hogs); - void *onHogCountChangedCtx; - - void (*onTeamColorChangedCb)(void *context, const char *teamName, int colorIndex); - void *onTeamColorChangedCtx; - - void (*onEngineMessageCb)(void *context, const uint8_t *message, size_t size); - void *onEngineMessageCtx; - - void (*onSchemeChangedCb)(void *context, const flib_scheme *scheme); - void *onSchemeChangedCtx; - - void (*onMapChangedCb)(void *context, const flib_map *map, int changetype); - void *onMapChangedCtx; - - void (*onScriptChangedCb)(void *context, const char *script); - void *onScriptChangedCtx; - - void (*onWeaponsetChangedCb)(void *context, const flib_weaponset *weaponset); - void *onWeaponsetChangedCtx; - - void (*onServerVarCb)(void *context, const char *name, const char *value); - void *onServerVarCtx; - - bool running; - bool destroyRequested; -}; - -void netconn_clearCallbacks(flib_netconn *conn); -void netconn_leaveRoom(flib_netconn *conn); -void netconn_setMap(flib_netconn *conn, const flib_map *map); -void netconn_setWeaponset(flib_netconn *conn, const flib_weaponset *weaponset); -void netconn_setScript(flib_netconn *conn, const char *script); -void netconn_setScheme(flib_netconn *conn, const flib_scheme *scheme); - -#endif +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * Common definitions needed by netconn functions, to allow splitting them into several files. + */ + +#ifndef NETCONN_INTERNAL_H_ +#define NETCONN_INTERNAL_H_ + +#include "netconn.h" +#include "netbase.h" +#include "../model/map.h" +#include "../model/team.h" +#include "../model/weapon.h" +#include "../model/room.h" + +#include +#include +#include + +struct _flib_netconn { + flib_netbase *netBase; + char *playerName; + char *dataDirPath; + + int netconnState; //!< One of the NETCONN_STATE constants + + bool isChief; //!< Player can modify the current room + flib_map *map; + flib_teamlist pendingTeamlist; + flib_teamlist teamlist; + flib_scheme *scheme; + char *style; + flib_weaponset *weaponset; + + void (*onMessageCb)(void *context, int msgtype, const char *msg); + void *onMessageCtx; + + void (*onConnectedCb)(void *context); + void *onConnectedCtx; + + void (*onDisconnectedCb)(void *context, int reason, const char *message); + void *onDisconnectedCtx; + + void (*onRoomlistCb)(void *context, const flib_room **rooms, int roomCount); + void *onRoomlistCtx; + + void (*onRoomAddCb)(void *context, const flib_room *room); + void *onRoomAddCtx; + + void (*onRoomDeleteCb)(void *context, const char *name); + void *onRoomDeleteCtx; + + void (*onRoomUpdateCb)(void *context, const char *oldName, const flib_room *room); + void *onRoomUpdateCtx; + + void (*onClientFlagsCb)(void *context, const char *nick, const char *flags, bool newFlagState); + void *onClientFlagsCtx; + + void (*onChatCb)(void *context, const char *nick, const char *msg); + void *onChatCtx; + + void (*onLobbyJoinCb)(void *context, const char *nick); + void *onLobbyJoinCtx; + + void (*onLobbyLeaveCb)(void *context, const char *nick, const char *partMessage); + void *onLobbyLeaveCtx; + + void (*onRoomJoinCb)(void *context, const char *nick); + void *onRoomJoinCtx; + + void (*onRoomLeaveCb)(void *context, const char *nick, const char *partMessage); + void *onRoomLeaveCtx; + + void (*onNickTakenCb)(void *context, const char *nick); + void *onNickTakenCtx; + + void (*onPasswordRequestCb)(void *context, const char *nick); + void *onPasswordRequestCtx; + + void (*onEnterRoomCb)(void *context, bool chief); + void *onEnterRoomCtx; + + void (*onLeaveRoomCb)(void *context, int reason, const char *message); + void *onLeaveRoomCtx; + + void (*onTeamAddCb)(void *context, const flib_team *team); + void *onTeamAddCtx; + + void (*onTeamDeleteCb)(void *context, const char *teamname); + void *onTeamDeleteCtx; + + void (*onRunGameCb)(void *context); + void *onRunGameCtx; + + void (*onTeamAcceptedCb)(void *context, const char *teamName); + void *onTeamAcceptedCtx; + + void (*onHogCountChangedCb)(void *context, const char *teamName, int hogs); + void *onHogCountChangedCtx; + + void (*onTeamColorChangedCb)(void *context, const char *teamName, int colorIndex); + void *onTeamColorChangedCtx; + + void (*onEngineMessageCb)(void *context, const uint8_t *message, size_t size); + void *onEngineMessageCtx; + + void (*onSchemeChangedCb)(void *context, const flib_scheme *scheme); + void *onSchemeChangedCtx; + + void (*onMapChangedCb)(void *context, const flib_map *map, int changetype); + void *onMapChangedCtx; + + void (*onScriptChangedCb)(void *context, const char *script); + void *onScriptChangedCtx; + + void (*onWeaponsetChangedCb)(void *context, const flib_weaponset *weaponset); + void *onWeaponsetChangedCtx; + + void (*onServerVarCb)(void *context, const char *name, const char *value); + void *onServerVarCtx; + + bool running; + bool destroyRequested; +}; + +void netconn_clearCallbacks(flib_netconn *conn); +void netconn_leaveRoom(flib_netconn *conn); +void netconn_setMap(flib_netconn *conn, const flib_map *map); +void netconn_setWeaponset(flib_netconn *conn, const flib_weaponset *weaponset); +void netconn_setScript(flib_netconn *conn, const char *script); +void netconn_setScheme(flib_netconn *conn, const flib_scheme *scheme); + +#endif diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/net/netconn_send.c --- a/project_files/frontlib/net/netconn_send.c Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/net/netconn_send.c Tue Nov 10 20:43:13 2015 +0100 @@ -1,495 +1,495 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "netconn_internal.h" - -#include "../util/logging.h" -#include "../util/util.h" -#include "../util/buffer.h" -#include "../md5/md5.h" -#include "../base64/base64.h" - -#include - -#include -#include -#include - -// cmdname is always given as literal from functions in this file, so it is never null. -static int sendVoid(flib_netconn *conn, const char *cmdname) { - if(log_e_if(!conn, "Invalid parameter sending %s command", cmdname)) { - return -1; - } - return flib_netbase_sendf(conn->netBase, "%s\n\n", cmdname); -} - -// Testing for !*str prevents sending 0-length parameters (they trip up the protocol) -static int sendStr(flib_netconn *conn, const char *cmdname, const char *str) { - if(log_e_if(!conn || flib_strempty(str), "Invalid parameter sending %s command", cmdname)) { - return -1; - } - return flib_netbase_sendf(conn->netBase, "%s\n%s\n\n", cmdname, str); -} - -static int sendInt(flib_netconn *conn, const char *cmdname, int param) { - if(log_e_if(!conn, "Invalid parameter sending %s command", cmdname)) { - return -1; - } - return flib_netbase_sendf(conn->netBase, "%s\n%i\n\n", cmdname, param); -} - -int flib_netconn_send_nick(flib_netconn *conn, const char *nick) { - int result = -1; - if(!log_badargs_if2(conn==NULL, flib_strempty(nick))) { - char *tmpName = flib_strdupnull(nick); - if(tmpName) { - if(!flib_netbase_sendf(conn->netBase, "%s\n%s\n\n", "NICK", nick)) { - free(conn->playerName); - conn->playerName = tmpName; - tmpName = NULL; - result = 0; - } - } - free(tmpName); - } - return result; -} - -int flib_netconn_send_password(flib_netconn *conn, const char *passwd) { - int result = -1; - if(!log_badargs_if2(conn==NULL, passwd==NULL)) { - md5_state_t md5state; - uint8_t md5bytes[16]; - char md5hex[33]; - md5_init(&md5state); - md5_append(&md5state, (unsigned char*)passwd, strlen(passwd)); - md5_finish(&md5state, md5bytes); - for(int i=0;inetBase, "%s\n%s\n\n", "PASSWORD", md5hex); - } - return result; -} - -int flib_netconn_send_quit(flib_netconn *conn, const char *quitmsg) { - return sendStr(conn, "QUIT", (quitmsg && *quitmsg) ? quitmsg : "User quit"); -} - -int flib_netconn_send_chat(flib_netconn *conn, const char *chat) { - if(!flib_strempty(chat)) { - return sendStr(conn, "CHAT", chat); - } - return 0; -} - -int flib_netconn_send_kick(flib_netconn *conn, const char *playerName) { - return sendStr(conn, "KICK", playerName); -} - -int flib_netconn_send_playerInfo(flib_netconn *conn, const char *playerName) { - return sendStr(conn, "INFO", playerName); -} - -int flib_netconn_send_request_roomlist(flib_netconn *conn) { - return sendVoid(conn, "LIST"); -} - -int flib_netconn_send_joinRoom(flib_netconn *conn, const char *room) { - if(!sendStr(conn, "JOIN_ROOM", room)) { - conn->isChief = false; - return 0; - } - return -1; -} - -int flib_netconn_send_playerFollow(flib_netconn *conn, const char *playerName) { - return sendStr(conn, "FOLLOW", playerName); -} - -int flib_netconn_send_createRoom(flib_netconn *conn, const char *room) { - if(!sendStr(conn, "CREATE_ROOM", room)) { - conn->isChief = true; - return 0; - } - return -1; -} - -int flib_netconn_send_ban(flib_netconn *conn, const char *playerName) { - return sendStr(conn, "BAN", playerName); -} - -int flib_netconn_send_clearAccountsCache(flib_netconn *conn) { - return sendVoid(conn, "CLEAR_ACCOUNTS_CACHE"); -} - -int flib_netconn_send_setServerVar(flib_netconn *conn, const char *name, const char *value) { - if(log_badargs_if3(conn==NULL, flib_strempty(name), flib_strempty(value))) { - return -1; - } - return flib_netbase_sendf(conn->netBase, "%s\n%s\n%s\n\n", "SET_SERVER_VAR", name, value); -} - -int flib_netconn_send_getServerVars(flib_netconn *conn) { - return sendVoid(conn, "GET_SERVER_VAR"); -} -int flib_netconn_send_leaveRoom(flib_netconn *conn, const char *str) { - int result = -1; - if(conn->netconnState==NETCONN_STATE_ROOM) { - result = (str && *str) ? sendStr(conn, "PART", str) : sendVoid(conn, "PART"); - if(!result) { - netconn_leaveRoom(conn); - } - } - return result; -} - -int flib_netconn_send_toggleReady(flib_netconn *conn) { - return sendVoid(conn, "TOGGLE_READY"); -} - -static void addTeamToPendingList(flib_netconn *conn, const flib_team *team) { - flib_team *teamcopy = flib_team_copy(team); - if(teamcopy) { - teamcopy->remoteDriven = false; - free(teamcopy->ownerName); - teamcopy->ownerName = flib_strdupnull(conn->playerName); - if(teamcopy->ownerName) { - flib_teamlist_delete(&conn->pendingTeamlist, team->name); - if(!flib_teamlist_insert(&conn->pendingTeamlist, teamcopy, 0)) { - teamcopy = NULL; - } - } - } - flib_team_destroy(teamcopy); -} - -int flib_netconn_send_addTeam(flib_netconn *conn, const flib_team *team) { - int result = -1; - if(!log_badargs_if2(conn==NULL, team==NULL)) { - bool missingInfo = flib_strempty(team->name) || flib_strempty(team->grave) || flib_strempty(team->fort) || flib_strempty(team->voicepack) || flib_strempty(team->flag); - for(int i=0; ihogs[i].name) || flib_strempty(team->hogs[i].hat); - } - if(!log_e_if(missingInfo, "Incomplete team definition")) { - flib_vector *vec = flib_vector_create(); - if(vec) { - bool error = false; - error |= flib_vector_appendf(vec, "ADD_TEAM\n%s\n%i\n%s\n%s\n%s\n%s\n%i\n", team->name, team->colorIndex, team->grave, team->fort, team->voicepack, team->flag, team->hogs[0].difficulty); - for(int i=0; ihogs[i].name, team->hogs[i].hat); - } - error |= flib_vector_appendf(vec, "\n"); - if(!error && !flib_netbase_send_raw(conn->netBase, flib_vector_data(vec), flib_vector_size(vec))) { - addTeamToPendingList(conn, team); - result = 0; - } - } - flib_vector_destroy(vec); - } - } - return result; -} - -int flib_netconn_send_removeTeam(flib_netconn *conn, const char *teamname) { - flib_team *team = flib_teamlist_find(&conn->teamlist, teamname); - if(team && !team->remoteDriven && !sendStr(conn, "REMOVE_TEAM", teamname)) { - flib_teamlist_delete(&conn->teamlist, teamname); - return 0; - } - return -1; -} - -int flib_netconn_send_renameRoom(flib_netconn *conn, const char *roomName) { - return sendStr(conn, "ROOM_NAME", roomName); -} - -int flib_netconn_send_teamHogCount(flib_netconn *conn, const char *teamname, int hogcount) { - if(!log_badargs_if5(conn==NULL, flib_strempty(teamname), hogcount<1, hogcount>HEDGEHOGS_PER_TEAM, !conn->isChief) - && !flib_netbase_sendf(conn->netBase, "HH_NUM\n%s\n%i\n\n", teamname, hogcount)) { - flib_team *team = flib_teamlist_find(&conn->teamlist, teamname); - if(team) { - team->hogsInGame = hogcount; - } - return 0; - } - return -1; -} - -int flib_netconn_send_teamColor(flib_netconn *conn, const char *teamname, int colorIndex) { - if(!log_badargs_if3(conn==NULL, flib_strempty(teamname), !conn->isChief) - && !flib_netbase_sendf(conn->netBase, "TEAM_COLOR\n%s\n%i\n\n", teamname, colorIndex)) { - flib_team *team = flib_teamlist_find(&conn->teamlist, teamname); - if(team) { - team->colorIndex = colorIndex; - } - return 0; - } - return -1; -} - -int flib_netconn_send_weaponset(flib_netconn *conn, const flib_weaponset *weaponset) { - if(!log_badargs_if3(conn==NULL, weaponset==NULL, flib_strempty(weaponset->name))) { - char ammostring[WEAPONS_COUNT*4+1]; - strcpy(ammostring, weaponset->loadout); - strcat(ammostring, weaponset->crateprob); - strcat(ammostring, weaponset->delay); - strcat(ammostring, weaponset->crateammo); - if(conn->isChief) { - if(!flib_netbase_sendf(conn->netBase, "CFG\nAMMO\n%s\n%s\n\n", weaponset->name, ammostring)) { - netconn_setWeaponset(conn, weaponset); - return 0; - } - } - } - return -1; -} - -int flib_netconn_send_map(flib_netconn *conn, const flib_map *map) { - if(log_badargs_if2(conn==NULL, map==NULL)) { - return -1; - } - bool error = false; - - if(map->seed) { - error |= flib_netconn_send_mapSeed(conn, map->seed); - } - error |= flib_netconn_send_mapTemplate(conn, map->templateFilter); - if(map->theme) { - error |= flib_netconn_send_mapTheme(conn, map->theme); - } - error |= flib_netconn_send_mapGen(conn, map->mapgen); - error |= flib_netconn_send_mapMazeSize(conn, map->mazeSize); - if(map->drawData && map->drawDataSize>0) { - error |= flib_netconn_send_mapDrawdata(conn, map->drawData, map->drawDataSize); - } - // Name is sent last, because the QtFrontend uses this to update its preview, and to show/hide - // certain fields - if(map->name) { - error |= flib_netconn_send_mapName(conn, map->name); - } - return error; -} - -int flib_netconn_send_mapName(flib_netconn *conn, const char *mapName) { - if(log_badargs_if2(conn==NULL, mapName==NULL)) { - return -1; - } - if(conn->isChief) { - if(!sendStr(conn, "CFG\nMAP", mapName)) { - char *copy = flib_strdupnull(mapName); - if(copy) { - free(conn->map->name); - conn->map->name = copy; - return 0; - } - } - } - return -1; -} - -int flib_netconn_send_mapGen(flib_netconn *conn, int mapGen) { - if(log_badargs_if(conn==NULL)) { - return -1; - } - if(conn->isChief) { - if(!sendInt(conn, "CFG\nMAPGEN", mapGen)) { - conn->map->mapgen = mapGen; - return 0; - } - } - return -1; -} - -int flib_netconn_send_mapTemplate(flib_netconn *conn, int templateFilter) { - if(log_badargs_if(conn==NULL)) { - return -1; - } - if(conn->isChief) { - if(!sendInt(conn, "CFG\nTEMPLATE", templateFilter)) { - conn->map->templateFilter = templateFilter; - return 0; - } - } - return -1; -} - -int flib_netconn_send_mapMazeSize(flib_netconn *conn, int mazeSize) { - if(log_badargs_if(conn==NULL)) { - return -1; - } - if(conn->isChief) { - if(!sendInt(conn, "CFG\nMAZE_SIZE", mazeSize)) { - conn->map->mazeSize = mazeSize; - return 0; - } - } - return -1; -} - -int flib_netconn_send_mapSeed(flib_netconn *conn, const char *seed) { - if(log_badargs_if2(conn==NULL, seed==NULL)) { - return -1; - } - if(conn->isChief) { - if(!sendStr(conn, "CFG\nSEED", seed)) { - char *copy = flib_strdupnull(seed); - if(copy) { - free(conn->map->seed); - conn->map->seed = copy; - return 0; - } - } - } - return -1; -} - -int flib_netconn_send_mapTheme(flib_netconn *conn, const char *theme) { - if(log_badargs_if2(conn==NULL, theme==NULL)) { - return -1; - } - if(conn->isChief) { - if(!sendStr(conn, "CFG\nTHEME", theme)) { - char *copy = flib_strdupnull(theme); - if(copy) { - free(conn->map->theme); - conn->map->theme = copy; - return 0; - } - } - } - return -1; -} - -int flib_netconn_send_mapDrawdata(flib_netconn *conn, const uint8_t *drawData, size_t size) { - int result = -1; - if(!log_badargs_if3(conn==NULL, drawData==NULL && size>0, size>SIZE_MAX/2) && conn->isChief) { - uLongf zippedSize = compressBound(size); - uint8_t *zipped = flib_malloc(zippedSize+4); // 4 extra bytes for header - if(zipped) { - // Create the QCompress size header (uint32 big endian) - zipped[0] = (size>>24) & 0xff; - zipped[1] = (size>>16) & 0xff; - zipped[2] = (size>>8) & 0xff; - zipped[3] = (size) & 0xff; - - if(compress(zipped+4, &zippedSize, drawData, size) != Z_OK) { - flib_log_e("Error compressing drawn map data."); - } else { - char *base64encout = NULL; - base64_encode_alloc((const char*)zipped, zippedSize+4, &base64encout); - if(!base64encout) { - flib_log_e("Error base64-encoding drawn map data."); - } else { - result = flib_netbase_sendf(conn->netBase, "CFG\nDRAWNMAP\n%s\n\n", base64encout); - } - free(base64encout); - } - } - free(zipped); - } - - if(!result) { - uint8_t *copy = flib_bufdupnull(drawData, size); - if(copy) { - free(conn->map->drawData); - conn->map->drawData = copy; - conn->map->drawDataSize = size; - } - } - return result; -} - -int flib_netconn_send_script(flib_netconn *conn, const char *scriptName) { - if(log_badargs_if2(conn==NULL, scriptName==NULL)) { - return -1; - } - if(conn->isChief) { - if(!sendStr(conn, "CFG\nSCRIPT", scriptName)) { - netconn_setScript(conn, scriptName); - return 0; - } - } - return -1; -} - -int flib_netconn_send_scheme(flib_netconn *conn, const flib_scheme *scheme) { - int result = -1; - if(!log_badargs_if3(conn==NULL, scheme==NULL, flib_strempty(scheme->name)) && conn->isChief) { - flib_vector *vec = flib_vector_create(); - if(vec) { - bool error = false; - error |= flib_vector_appendf(vec, "CFG\nSCHEME\n%s\n", scheme->name); - for(int i=0; imods[i] ? "true" : "false"); - } - for(int i=0; isettings[i]); - } - error |= flib_vector_appendf(vec, "\n"); - if(!error) { - result = flib_netbase_send_raw(conn->netBase, flib_vector_data(vec), flib_vector_size(vec)); - } - } - flib_vector_destroy(vec); - } - - if(!result) { - netconn_setScheme(conn, scheme); - } - return result; -} - -int flib_netconn_send_startGame(flib_netconn *conn) { - return sendVoid(conn, "START_GAME"); -} - -int flib_netconn_send_toggleRestrictJoins(flib_netconn *conn) { - return sendVoid(conn, "TOGGLE_RESTRICT_JOINS"); -} - -int flib_netconn_send_toggleRestrictTeams(flib_netconn *conn) { - return sendVoid(conn, "TOGGLE_RESTRICT_TEAMS"); -} - -int flib_netconn_send_teamchat(flib_netconn *conn, const char *chat) { - if(!flib_strempty(chat)) { - return sendStr(conn, "TEAMCHAT", chat); - } - return 0; -} - -int flib_netconn_send_engineMessage(flib_netconn *conn, const uint8_t *message, size_t size) { - int result = -1; - if(!log_badargs_if2(conn==NULL, message==NULL && size>0)) { - char *base64encout = NULL; - base64_encode_alloc((const char*)message, size, &base64encout); - if(base64encout) { - result = flib_netbase_sendf(conn->netBase, "EM\n%s\n\n", base64encout); - } - free(base64encout); - } - return result; -} - -int flib_netconn_send_roundfinished(flib_netconn *conn, bool withoutError) { - return sendInt(conn, "ROUNDFINISHED", withoutError ? 1 : 0); -} - +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "netconn_internal.h" + +#include "../util/logging.h" +#include "../util/util.h" +#include "../util/buffer.h" +#include "../md5/md5.h" +#include "../base64/base64.h" + +#include + +#include +#include +#include + +// cmdname is always given as literal from functions in this file, so it is never null. +static int sendVoid(flib_netconn *conn, const char *cmdname) { + if(log_e_if(!conn, "Invalid parameter sending %s command", cmdname)) { + return -1; + } + return flib_netbase_sendf(conn->netBase, "%s\n\n", cmdname); +} + +// Testing for !*str prevents sending 0-length parameters (they trip up the protocol) +static int sendStr(flib_netconn *conn, const char *cmdname, const char *str) { + if(log_e_if(!conn || flib_strempty(str), "Invalid parameter sending %s command", cmdname)) { + return -1; + } + return flib_netbase_sendf(conn->netBase, "%s\n%s\n\n", cmdname, str); +} + +static int sendInt(flib_netconn *conn, const char *cmdname, int param) { + if(log_e_if(!conn, "Invalid parameter sending %s command", cmdname)) { + return -1; + } + return flib_netbase_sendf(conn->netBase, "%s\n%i\n\n", cmdname, param); +} + +int flib_netconn_send_nick(flib_netconn *conn, const char *nick) { + int result = -1; + if(!log_badargs_if2(conn==NULL, flib_strempty(nick))) { + char *tmpName = flib_strdupnull(nick); + if(tmpName) { + if(!flib_netbase_sendf(conn->netBase, "%s\n%s\n\n", "NICK", nick)) { + free(conn->playerName); + conn->playerName = tmpName; + tmpName = NULL; + result = 0; + } + } + free(tmpName); + } + return result; +} + +int flib_netconn_send_password(flib_netconn *conn, const char *passwd) { + int result = -1; + if(!log_badargs_if2(conn==NULL, passwd==NULL)) { + md5_state_t md5state; + uint8_t md5bytes[16]; + char md5hex[33]; + md5_init(&md5state); + md5_append(&md5state, (unsigned char*)passwd, strlen(passwd)); + md5_finish(&md5state, md5bytes); + for(int i=0;inetBase, "%s\n%s\n\n", "PASSWORD", md5hex); + } + return result; +} + +int flib_netconn_send_quit(flib_netconn *conn, const char *quitmsg) { + return sendStr(conn, "QUIT", (quitmsg && *quitmsg) ? quitmsg : "User quit"); +} + +int flib_netconn_send_chat(flib_netconn *conn, const char *chat) { + if(!flib_strempty(chat)) { + return sendStr(conn, "CHAT", chat); + } + return 0; +} + +int flib_netconn_send_kick(flib_netconn *conn, const char *playerName) { + return sendStr(conn, "KICK", playerName); +} + +int flib_netconn_send_playerInfo(flib_netconn *conn, const char *playerName) { + return sendStr(conn, "INFO", playerName); +} + +int flib_netconn_send_request_roomlist(flib_netconn *conn) { + return sendVoid(conn, "LIST"); +} + +int flib_netconn_send_joinRoom(flib_netconn *conn, const char *room) { + if(!sendStr(conn, "JOIN_ROOM", room)) { + conn->isChief = false; + return 0; + } + return -1; +} + +int flib_netconn_send_playerFollow(flib_netconn *conn, const char *playerName) { + return sendStr(conn, "FOLLOW", playerName); +} + +int flib_netconn_send_createRoom(flib_netconn *conn, const char *room) { + if(!sendStr(conn, "CREATE_ROOM", room)) { + conn->isChief = true; + return 0; + } + return -1; +} + +int flib_netconn_send_ban(flib_netconn *conn, const char *playerName) { + return sendStr(conn, "BAN", playerName); +} + +int flib_netconn_send_clearAccountsCache(flib_netconn *conn) { + return sendVoid(conn, "CLEAR_ACCOUNTS_CACHE"); +} + +int flib_netconn_send_setServerVar(flib_netconn *conn, const char *name, const char *value) { + if(log_badargs_if3(conn==NULL, flib_strempty(name), flib_strempty(value))) { + return -1; + } + return flib_netbase_sendf(conn->netBase, "%s\n%s\n%s\n\n", "SET_SERVER_VAR", name, value); +} + +int flib_netconn_send_getServerVars(flib_netconn *conn) { + return sendVoid(conn, "GET_SERVER_VAR"); +} +int flib_netconn_send_leaveRoom(flib_netconn *conn, const char *str) { + int result = -1; + if(conn->netconnState==NETCONN_STATE_ROOM) { + result = (str && *str) ? sendStr(conn, "PART", str) : sendVoid(conn, "PART"); + if(!result) { + netconn_leaveRoom(conn); + } + } + return result; +} + +int flib_netconn_send_toggleReady(flib_netconn *conn) { + return sendVoid(conn, "TOGGLE_READY"); +} + +static void addTeamToPendingList(flib_netconn *conn, const flib_team *team) { + flib_team *teamcopy = flib_team_copy(team); + if(teamcopy) { + teamcopy->remoteDriven = false; + free(teamcopy->ownerName); + teamcopy->ownerName = flib_strdupnull(conn->playerName); + if(teamcopy->ownerName) { + flib_teamlist_delete(&conn->pendingTeamlist, team->name); + if(!flib_teamlist_insert(&conn->pendingTeamlist, teamcopy, 0)) { + teamcopy = NULL; + } + } + } + flib_team_destroy(teamcopy); +} + +int flib_netconn_send_addTeam(flib_netconn *conn, const flib_team *team) { + int result = -1; + if(!log_badargs_if2(conn==NULL, team==NULL)) { + bool missingInfo = flib_strempty(team->name) || flib_strempty(team->grave) || flib_strempty(team->fort) || flib_strempty(team->voicepack) || flib_strempty(team->flag); + for(int i=0; ihogs[i].name) || flib_strempty(team->hogs[i].hat); + } + if(!log_e_if(missingInfo, "Incomplete team definition")) { + flib_vector *vec = flib_vector_create(); + if(vec) { + bool error = false; + error |= flib_vector_appendf(vec, "ADD_TEAM\n%s\n%i\n%s\n%s\n%s\n%s\n%i\n", team->name, team->colorIndex, team->grave, team->fort, team->voicepack, team->flag, team->hogs[0].difficulty); + for(int i=0; ihogs[i].name, team->hogs[i].hat); + } + error |= flib_vector_appendf(vec, "\n"); + if(!error && !flib_netbase_send_raw(conn->netBase, flib_vector_data(vec), flib_vector_size(vec))) { + addTeamToPendingList(conn, team); + result = 0; + } + } + flib_vector_destroy(vec); + } + } + return result; +} + +int flib_netconn_send_removeTeam(flib_netconn *conn, const char *teamname) { + flib_team *team = flib_teamlist_find(&conn->teamlist, teamname); + if(team && !team->remoteDriven && !sendStr(conn, "REMOVE_TEAM", teamname)) { + flib_teamlist_delete(&conn->teamlist, teamname); + return 0; + } + return -1; +} + +int flib_netconn_send_renameRoom(flib_netconn *conn, const char *roomName) { + return sendStr(conn, "ROOM_NAME", roomName); +} + +int flib_netconn_send_teamHogCount(flib_netconn *conn, const char *teamname, int hogcount) { + if(!log_badargs_if5(conn==NULL, flib_strempty(teamname), hogcount<1, hogcount>HEDGEHOGS_PER_TEAM, !conn->isChief) + && !flib_netbase_sendf(conn->netBase, "HH_NUM\n%s\n%i\n\n", teamname, hogcount)) { + flib_team *team = flib_teamlist_find(&conn->teamlist, teamname); + if(team) { + team->hogsInGame = hogcount; + } + return 0; + } + return -1; +} + +int flib_netconn_send_teamColor(flib_netconn *conn, const char *teamname, int colorIndex) { + if(!log_badargs_if3(conn==NULL, flib_strempty(teamname), !conn->isChief) + && !flib_netbase_sendf(conn->netBase, "TEAM_COLOR\n%s\n%i\n\n", teamname, colorIndex)) { + flib_team *team = flib_teamlist_find(&conn->teamlist, teamname); + if(team) { + team->colorIndex = colorIndex; + } + return 0; + } + return -1; +} + +int flib_netconn_send_weaponset(flib_netconn *conn, const flib_weaponset *weaponset) { + if(!log_badargs_if3(conn==NULL, weaponset==NULL, flib_strempty(weaponset->name))) { + char ammostring[WEAPONS_COUNT*4+1]; + strcpy(ammostring, weaponset->loadout); + strcat(ammostring, weaponset->crateprob); + strcat(ammostring, weaponset->delay); + strcat(ammostring, weaponset->crateammo); + if(conn->isChief) { + if(!flib_netbase_sendf(conn->netBase, "CFG\nAMMO\n%s\n%s\n\n", weaponset->name, ammostring)) { + netconn_setWeaponset(conn, weaponset); + return 0; + } + } + } + return -1; +} + +int flib_netconn_send_map(flib_netconn *conn, const flib_map *map) { + if(log_badargs_if2(conn==NULL, map==NULL)) { + return -1; + } + bool error = false; + + if(map->seed) { + error |= flib_netconn_send_mapSeed(conn, map->seed); + } + error |= flib_netconn_send_mapTemplate(conn, map->templateFilter); + if(map->theme) { + error |= flib_netconn_send_mapTheme(conn, map->theme); + } + error |= flib_netconn_send_mapGen(conn, map->mapgen); + error |= flib_netconn_send_mapMazeSize(conn, map->mazeSize); + if(map->drawData && map->drawDataSize>0) { + error |= flib_netconn_send_mapDrawdata(conn, map->drawData, map->drawDataSize); + } + // Name is sent last, because the QtFrontend uses this to update its preview, and to show/hide + // certain fields + if(map->name) { + error |= flib_netconn_send_mapName(conn, map->name); + } + return error; +} + +int flib_netconn_send_mapName(flib_netconn *conn, const char *mapName) { + if(log_badargs_if2(conn==NULL, mapName==NULL)) { + return -1; + } + if(conn->isChief) { + if(!sendStr(conn, "CFG\nMAP", mapName)) { + char *copy = flib_strdupnull(mapName); + if(copy) { + free(conn->map->name); + conn->map->name = copy; + return 0; + } + } + } + return -1; +} + +int flib_netconn_send_mapGen(flib_netconn *conn, int mapGen) { + if(log_badargs_if(conn==NULL)) { + return -1; + } + if(conn->isChief) { + if(!sendInt(conn, "CFG\nMAPGEN", mapGen)) { + conn->map->mapgen = mapGen; + return 0; + } + } + return -1; +} + +int flib_netconn_send_mapTemplate(flib_netconn *conn, int templateFilter) { + if(log_badargs_if(conn==NULL)) { + return -1; + } + if(conn->isChief) { + if(!sendInt(conn, "CFG\nTEMPLATE", templateFilter)) { + conn->map->templateFilter = templateFilter; + return 0; + } + } + return -1; +} + +int flib_netconn_send_mapMazeSize(flib_netconn *conn, int mazeSize) { + if(log_badargs_if(conn==NULL)) { + return -1; + } + if(conn->isChief) { + if(!sendInt(conn, "CFG\nMAZE_SIZE", mazeSize)) { + conn->map->mazeSize = mazeSize; + return 0; + } + } + return -1; +} + +int flib_netconn_send_mapSeed(flib_netconn *conn, const char *seed) { + if(log_badargs_if2(conn==NULL, seed==NULL)) { + return -1; + } + if(conn->isChief) { + if(!sendStr(conn, "CFG\nSEED", seed)) { + char *copy = flib_strdupnull(seed); + if(copy) { + free(conn->map->seed); + conn->map->seed = copy; + return 0; + } + } + } + return -1; +} + +int flib_netconn_send_mapTheme(flib_netconn *conn, const char *theme) { + if(log_badargs_if2(conn==NULL, theme==NULL)) { + return -1; + } + if(conn->isChief) { + if(!sendStr(conn, "CFG\nTHEME", theme)) { + char *copy = flib_strdupnull(theme); + if(copy) { + free(conn->map->theme); + conn->map->theme = copy; + return 0; + } + } + } + return -1; +} + +int flib_netconn_send_mapDrawdata(flib_netconn *conn, const uint8_t *drawData, size_t size) { + int result = -1; + if(!log_badargs_if3(conn==NULL, drawData==NULL && size>0, size>SIZE_MAX/2) && conn->isChief) { + uLongf zippedSize = compressBound(size); + uint8_t *zipped = flib_malloc(zippedSize+4); // 4 extra bytes for header + if(zipped) { + // Create the QCompress size header (uint32 big endian) + zipped[0] = (size>>24) & 0xff; + zipped[1] = (size>>16) & 0xff; + zipped[2] = (size>>8) & 0xff; + zipped[3] = (size) & 0xff; + + if(compress(zipped+4, &zippedSize, drawData, size) != Z_OK) { + flib_log_e("Error compressing drawn map data."); + } else { + char *base64encout = NULL; + base64_encode_alloc((const char*)zipped, zippedSize+4, &base64encout); + if(!base64encout) { + flib_log_e("Error base64-encoding drawn map data."); + } else { + result = flib_netbase_sendf(conn->netBase, "CFG\nDRAWNMAP\n%s\n\n", base64encout); + } + free(base64encout); + } + } + free(zipped); + } + + if(!result) { + uint8_t *copy = flib_bufdupnull(drawData, size); + if(copy) { + free(conn->map->drawData); + conn->map->drawData = copy; + conn->map->drawDataSize = size; + } + } + return result; +} + +int flib_netconn_send_script(flib_netconn *conn, const char *scriptName) { + if(log_badargs_if2(conn==NULL, scriptName==NULL)) { + return -1; + } + if(conn->isChief) { + if(!sendStr(conn, "CFG\nSCRIPT", scriptName)) { + netconn_setScript(conn, scriptName); + return 0; + } + } + return -1; +} + +int flib_netconn_send_scheme(flib_netconn *conn, const flib_scheme *scheme) { + int result = -1; + if(!log_badargs_if3(conn==NULL, scheme==NULL, flib_strempty(scheme->name)) && conn->isChief) { + flib_vector *vec = flib_vector_create(); + if(vec) { + bool error = false; + error |= flib_vector_appendf(vec, "CFG\nSCHEME\n%s\n", scheme->name); + for(int i=0; imods[i] ? "true" : "false"); + } + for(int i=0; isettings[i]); + } + error |= flib_vector_appendf(vec, "\n"); + if(!error) { + result = flib_netbase_send_raw(conn->netBase, flib_vector_data(vec), flib_vector_size(vec)); + } + } + flib_vector_destroy(vec); + } + + if(!result) { + netconn_setScheme(conn, scheme); + } + return result; +} + +int flib_netconn_send_startGame(flib_netconn *conn) { + return sendVoid(conn, "START_GAME"); +} + +int flib_netconn_send_toggleRestrictJoins(flib_netconn *conn) { + return sendVoid(conn, "TOGGLE_RESTRICT_JOINS"); +} + +int flib_netconn_send_toggleRestrictTeams(flib_netconn *conn) { + return sendVoid(conn, "TOGGLE_RESTRICT_TEAMS"); +} + +int flib_netconn_send_teamchat(flib_netconn *conn, const char *chat) { + if(!flib_strempty(chat)) { + return sendStr(conn, "TEAMCHAT", chat); + } + return 0; +} + +int flib_netconn_send_engineMessage(flib_netconn *conn, const uint8_t *message, size_t size) { + int result = -1; + if(!log_badargs_if2(conn==NULL, message==NULL && size>0)) { + char *base64encout = NULL; + base64_encode_alloc((const char*)message, size, &base64encout); + if(base64encout) { + result = flib_netbase_sendf(conn->netBase, "EM\n%s\n\n", base64encout); + } + free(base64encout); + } + return result; +} + +int flib_netconn_send_roundfinished(flib_netconn *conn, bool withoutError) { + return sendInt(conn, "ROUNDFINISHED", withoutError ? 1 : 0); +} + diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/net/netprotocol.c --- a/project_files/frontlib/net/netprotocol.c Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/net/netprotocol.c Tue Nov 10 20:43:13 2015 +0100 @@ -1,192 +1,192 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "netprotocol.h" - -#include "../util/util.h" -#include "../util/logging.h" - -#include "../base64/base64.h" - -#include - -#include -#include -#include -#include - -static int fillTeamFromMsg(flib_team *team, char **parts) { - team->name = flib_strdupnull(parts[0]); - team->grave = flib_strdupnull(parts[1]); - team->fort = flib_strdupnull(parts[2]); - team->voicepack = flib_strdupnull(parts[3]); - team->flag = flib_strdupnull(parts[4]); - team->ownerName = flib_strdupnull(parts[5]); - if(!team->name || !team->grave || !team->fort || !team->voicepack || !team->flag || !team->ownerName) { - return -1; - } - - errno = 0; - long difficulty = strtol(parts[6], NULL, 10); - if(errno) { - return -1; - } - - for(int i=0; ihogs[i]; - hog->difficulty = difficulty; - hog->name = flib_strdupnull(parts[7+2*i]); - hog->hat = flib_strdupnull(parts[8+2*i]); - if(!hog->name || !hog->hat) { - return -1; - } - } - - // Set some default assumptions as well - team->colorIndex = DEFAULT_COLOR_INDEX; - team->hogsInGame = DEFAULT_HEDGEHOG_COUNT; - team->remoteDriven = true; - return 0; -} - -flib_team *flib_team_from_netmsg(char **parts) { - flib_team *result = NULL; - flib_team *tmpTeam = flib_calloc(1, sizeof(flib_team)); - if(tmpTeam) { - if(!fillTeamFromMsg(tmpTeam, parts)) { - result = tmpTeam; - tmpTeam = NULL; - } else { - flib_log_e("Error parsing team from net."); - } - } - flib_team_destroy(tmpTeam); - return result; -} - -flib_scheme *flib_scheme_from_netmsg(char **parts) { - flib_scheme *result = flib_scheme_create(parts[0]); - if(result) { - for(int i=0; imods[i] = !strcmp(parts[i+1], "true"); - } - for(int i=0; isettings[i] = atoi(parts[i+flib_meta.modCount+1]); - } - } - return result; -} - -flib_map *flib_map_from_netmsg(char **parts) { - flib_map *result = flib_map_create_named(parts[3], parts[0]); - if(result) { - result->mapgen = atoi(parts[1]); - result->mazeSize = atoi(parts[2]); - result->templateFilter = atoi(parts[4]); - } - return result; -} - -int flib_drawnmapdata_from_netmsg(char *netmsg, uint8_t** outbuf, size_t *outlen) { - int result = -1; - - // First step: base64 decoding - char *base64decout = NULL; - size_t base64declen; - bool ok = base64_decode_alloc(netmsg, strlen(netmsg), &base64decout, &base64declen); - if(ok && base64declen>3) { - // Second step: unzip with the QCompress header. That header is just a big-endian - // uint32 indicating the length of the uncompressed data. - uint8_t *ubyteBuf = (uint8_t*)base64decout; - uint32_t unzipLen = - (((uint32_t)ubyteBuf[0])<<24) - + (((uint32_t)ubyteBuf[1])<<16) - + (((uint32_t)ubyteBuf[2])<<8) - + ubyteBuf[3]; - if(unzipLen==0) { - *outbuf = NULL; - *outlen = 0; - result = 0; - } else { - uint8_t *out = flib_malloc(unzipLen); - if(out) { - uLongf actualUnzipLen = unzipLen; - int resultcode = uncompress(out, &actualUnzipLen, (Bytef*)(base64decout+4), base64declen-4); - if(resultcode == Z_OK) { - *outbuf = out; - *outlen = actualUnzipLen; - out = NULL; - result = 0; - } else { - flib_log_e("Uncompressing drawn map failed. Code: %i", resultcode); - } - } - free(out); - } - } else { - flib_log_e("base64 decoding of drawn map failed."); - } - free(base64decout); - return result; -} - -flib_room *flib_room_from_netmsg(char **params) { - flib_room *result = NULL; - flib_room *tmpRoom = flib_calloc(1, sizeof(flib_room)); - if(tmpRoom) { - tmpRoom->inProgress = !strcmp(params[0], "True"); - tmpRoom->name = flib_strdupnull(params[1]); - tmpRoom->playerCount = atoi(params[2]); - tmpRoom->teamCount = atoi(params[3]); - tmpRoom->owner = flib_strdupnull(params[4]); - tmpRoom->map = flib_strdupnull(params[5]); - tmpRoom->scheme = flib_strdupnull(params[6]); - tmpRoom->weapons = flib_strdupnull(params[7]); - if(tmpRoom->name && tmpRoom->owner && tmpRoom->map && tmpRoom->scheme && tmpRoom->weapons) { - result = tmpRoom; - tmpRoom = NULL; - } - } - flib_room_destroy(tmpRoom); - return result; -} - -int fillRoomArray(flib_room **array, char **params, int count) { - for(int i=0; i + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "netprotocol.h" + +#include "../util/util.h" +#include "../util/logging.h" + +#include "../base64/base64.h" + +#include + +#include +#include +#include +#include + +static int fillTeamFromMsg(flib_team *team, char **parts) { + team->name = flib_strdupnull(parts[0]); + team->grave = flib_strdupnull(parts[1]); + team->fort = flib_strdupnull(parts[2]); + team->voicepack = flib_strdupnull(parts[3]); + team->flag = flib_strdupnull(parts[4]); + team->ownerName = flib_strdupnull(parts[5]); + if(!team->name || !team->grave || !team->fort || !team->voicepack || !team->flag || !team->ownerName) { + return -1; + } + + errno = 0; + long difficulty = strtol(parts[6], NULL, 10); + if(errno) { + return -1; + } + + for(int i=0; ihogs[i]; + hog->difficulty = difficulty; + hog->name = flib_strdupnull(parts[7+2*i]); + hog->hat = flib_strdupnull(parts[8+2*i]); + if(!hog->name || !hog->hat) { + return -1; + } + } + + // Set some default assumptions as well + team->colorIndex = DEFAULT_COLOR_INDEX; + team->hogsInGame = DEFAULT_HEDGEHOG_COUNT; + team->remoteDriven = true; + return 0; +} + +flib_team *flib_team_from_netmsg(char **parts) { + flib_team *result = NULL; + flib_team *tmpTeam = flib_calloc(1, sizeof(flib_team)); + if(tmpTeam) { + if(!fillTeamFromMsg(tmpTeam, parts)) { + result = tmpTeam; + tmpTeam = NULL; + } else { + flib_log_e("Error parsing team from net."); + } + } + flib_team_destroy(tmpTeam); + return result; +} + +flib_scheme *flib_scheme_from_netmsg(char **parts) { + flib_scheme *result = flib_scheme_create(parts[0]); + if(result) { + for(int i=0; imods[i] = !strcmp(parts[i+1], "true"); + } + for(int i=0; isettings[i] = atoi(parts[i+flib_meta.modCount+1]); + } + } + return result; +} + +flib_map *flib_map_from_netmsg(char **parts) { + flib_map *result = flib_map_create_named(parts[3], parts[0]); + if(result) { + result->mapgen = atoi(parts[1]); + result->mazeSize = atoi(parts[2]); + result->templateFilter = atoi(parts[4]); + } + return result; +} + +int flib_drawnmapdata_from_netmsg(char *netmsg, uint8_t** outbuf, size_t *outlen) { + int result = -1; + + // First step: base64 decoding + char *base64decout = NULL; + size_t base64declen; + bool ok = base64_decode_alloc(netmsg, strlen(netmsg), &base64decout, &base64declen); + if(ok && base64declen>3) { + // Second step: unzip with the QCompress header. That header is just a big-endian + // uint32 indicating the length of the uncompressed data. + uint8_t *ubyteBuf = (uint8_t*)base64decout; + uint32_t unzipLen = + (((uint32_t)ubyteBuf[0])<<24) + + (((uint32_t)ubyteBuf[1])<<16) + + (((uint32_t)ubyteBuf[2])<<8) + + ubyteBuf[3]; + if(unzipLen==0) { + *outbuf = NULL; + *outlen = 0; + result = 0; + } else { + uint8_t *out = flib_malloc(unzipLen); + if(out) { + uLongf actualUnzipLen = unzipLen; + int resultcode = uncompress(out, &actualUnzipLen, (Bytef*)(base64decout+4), base64declen-4); + if(resultcode == Z_OK) { + *outbuf = out; + *outlen = actualUnzipLen; + out = NULL; + result = 0; + } else { + flib_log_e("Uncompressing drawn map failed. Code: %i", resultcode); + } + } + free(out); + } + } else { + flib_log_e("base64 decoding of drawn map failed."); + } + free(base64decout); + return result; +} + +flib_room *flib_room_from_netmsg(char **params) { + flib_room *result = NULL; + flib_room *tmpRoom = flib_calloc(1, sizeof(flib_room)); + if(tmpRoom) { + tmpRoom->inProgress = !strcmp(params[0], "True"); + tmpRoom->name = flib_strdupnull(params[1]); + tmpRoom->playerCount = atoi(params[2]); + tmpRoom->teamCount = atoi(params[3]); + tmpRoom->owner = flib_strdupnull(params[4]); + tmpRoom->map = flib_strdupnull(params[5]); + tmpRoom->scheme = flib_strdupnull(params[6]); + tmpRoom->weapons = flib_strdupnull(params[7]); + if(tmpRoom->name && tmpRoom->owner && tmpRoom->map && tmpRoom->scheme && tmpRoom->weapons) { + result = tmpRoom; + tmpRoom = NULL; + } + } + flib_room_destroy(tmpRoom); + return result; +} + +int fillRoomArray(flib_room **array, char **params, int count) { + for(int i=0; i - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef NETPROTOCOL_H_ -#define NETPROTOCOL_H_ - -#include "../model/team.h" -#include "../model/scheme.h" -#include "../model/map.h" -#include "../model/room.h" - -#include - -/** - * Create a new team from this 23-part net message - */ -flib_team *flib_team_from_netmsg(char **parts); - -/** - * Create a new scheme from this net message, which must have - * meta->modCount+meta->settingCount+1 parts. - */ -flib_scheme *flib_scheme_from_netmsg(char **parts); - -/** - * Create a new map from this five-part netmsg - */ -flib_map *flib_map_from_netmsg(char **parts); - -/** - * Decode the drawn map data from this netmessage line. - * - * The data is first base64 decoded and then quncompress()ed. - * The return value is a newly allocated byte buffer, the length - * is written to the variable pointed to by outlen. - * Returns NULL on error. - */ -int flib_drawnmapdata_from_netmsg(char *netmsg, uint8_t **outbuf, size_t *outlen); - -/** - * Create a new room from this 8-part net message - */ -flib_room *flib_room_from_netmsg(char **params); - -/** - * Create an array of count rooms from count*8 netmessage parts - */ -flib_room **flib_room_array_from_netmsg(char **params, int count); - -#endif /* NETPROTOCOL_H_ */ +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef NETPROTOCOL_H_ +#define NETPROTOCOL_H_ + +#include "../model/team.h" +#include "../model/scheme.h" +#include "../model/map.h" +#include "../model/room.h" + +#include + +/** + * Create a new team from this 23-part net message + */ +flib_team *flib_team_from_netmsg(char **parts); + +/** + * Create a new scheme from this net message, which must have + * meta->modCount+meta->settingCount+1 parts. + */ +flib_scheme *flib_scheme_from_netmsg(char **parts); + +/** + * Create a new map from this five-part netmsg + */ +flib_map *flib_map_from_netmsg(char **parts); + +/** + * Decode the drawn map data from this netmessage line. + * + * The data is first base64 decoded and then quncompress()ed. + * The return value is a newly allocated byte buffer, the length + * is written to the variable pointed to by outlen. + * Returns NULL on error. + */ +int flib_drawnmapdata_from_netmsg(char *netmsg, uint8_t **outbuf, size_t *outlen); + +/** + * Create a new room from this 8-part net message + */ +flib_room *flib_room_from_netmsg(char **params); + +/** + * Create an array of count rooms from count*8 netmessage parts + */ +flib_room **flib_room_array_from_netmsg(char **params, int count); + +#endif /* NETPROTOCOL_H_ */ diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/socket.c --- a/project_files/frontlib/socket.c Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/socket.c Tue Nov 10 20:43:13 2015 +0100 @@ -1,191 +1,191 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "socket.h" -#include "util/logging.h" -#include "util/util.h" -#include -#include -#include - -struct _flib_tcpsocket { - TCPsocket sock; - SDLNet_SocketSet sockset; -}; - -struct _flib_acceptor { - TCPsocket sock; - uint16_t port; -}; - -static uint32_t getPeerIp(TCPsocket sock) { - IPaddress *addr = SDLNet_TCP_GetPeerAddress(sock); - return SDLNet_Read32(&addr->host); -} - -static bool connectionIsLocal(TCPsocket sock) { - return getPeerIp(sock) == (uint32_t)((127UL<<24)+1); // 127.0.0.1 -} - -static flib_tcpsocket *createSocket(TCPsocket sdlsock) { - flib_tcpsocket *result = flib_calloc(1, sizeof(flib_tcpsocket)); - if(result) { - result->sock = sdlsock; - result->sockset = SDLNet_AllocSocketSet(1); - - if(!result->sockset) { - flib_log_e("Can't allocate socket: Out of memory!"); - SDLNet_FreeSocketSet(result->sockset); - free(result); - result = NULL; - } else { - SDLNet_AddSocket(result->sockset, (SDLNet_GenericSocket)result->sock); - } - } - return result; -} - -TCPsocket listen(uint16_t port) { - IPaddress addr; - addr.host = INADDR_ANY; - SDLNet_Write16(port, &addr.port); - TCPsocket sock = SDLNet_TCP_Open(&addr); - if(!sock) { - flib_log_w("Unable to listen on port %u: %s", (unsigned)port, SDLNet_GetError()); - } - return sock; -} - -flib_acceptor *flib_acceptor_create(uint16_t port) { - flib_acceptor *result = flib_calloc(1, sizeof(flib_acceptor)); - if(result) { - if(port > 0) { - result->port = port; - result->sock = listen(result->port); - } else { - /* SDL_net does not seem to have a way to listen on a random unused port - and find out which port that is, so let's try to find one ourselves. */ - srand(time(NULL)); - for(int i=0; !result->sock && i<1000; i++) { - // IANA suggests using ports in the range 49152-65535 for things like this - result->port = 49152+(rand()%(65536-49152)); - result->sock = listen(result->port); - } - } - if(!result->sock) { - flib_log_e("Failed to create acceptor."); - free(result); - result = NULL; - } - } - return result; -} - -uint16_t flib_acceptor_listenport(flib_acceptor *acceptor) { - if(!acceptor) { - flib_log_e("Call to flib_acceptor_listenport with acceptor==null"); - return 0; - } - return acceptor->port; -} - -void flib_acceptor_close(flib_acceptor *acceptor) { - if(acceptor) { - SDLNet_TCP_Close(acceptor->sock); - free(acceptor); - } -} - -flib_tcpsocket *flib_socket_accept(flib_acceptor *acceptor, bool localOnly) { - flib_tcpsocket *result = NULL; - if(!acceptor) { - flib_log_e("Call to flib_socket_accept with acceptor==null"); - } else { - TCPsocket sock = NULL; - while(!result && (sock = SDLNet_TCP_Accept(acceptor->sock))) { - if(localOnly && !connectionIsLocal(sock)) { - flib_log_i("Rejected nonlocal connection attempt from %s", flib_format_ip(getPeerIp(sock))); - } else { - result = createSocket(sock); - } - if(!result) { - SDLNet_TCP_Close(sock); - } - } - } - return result; -} - -flib_tcpsocket *flib_socket_connect(const char *host, uint16_t port) { - flib_tcpsocket *result = NULL; - if(!host || port==0) { - flib_log_e("Invalid parameter in flib_socket_connect"); - } else { - IPaddress ip; - if(SDLNet_ResolveHost(&ip,host,port)==-1) { - flib_log_e("SDLNet_ResolveHost: %s\n", SDLNet_GetError()); - } else { - TCPsocket sock=SDLNet_TCP_Open(&ip); - if(!sock) { - flib_log_e("SDLNet_TCP_Open: %s\n", SDLNet_GetError()); - } else { - result = createSocket(sock); - if(result) { - sock = NULL; - } - } - SDLNet_TCP_Close(sock); - } - } - return result; -} - -void flib_socket_close(flib_tcpsocket *sock) { - if(sock) { - SDLNet_DelSocket(sock->sockset, (SDLNet_GenericSocket)sock->sock); - SDLNet_TCP_Close(sock->sock); - SDLNet_FreeSocketSet(sock->sockset); - free(sock); - } -} - -int flib_socket_nbrecv(flib_tcpsocket *sock, void *data, int maxlen) { - if(!sock || (maxlen>0 && !data)) { - flib_log_e("Call to flib_socket_nbrecv with sock==null or data==null"); - return -1; - } - int readySockets = SDLNet_CheckSockets(sock->sockset, 0); - if(readySockets>0) { - int size = SDLNet_TCP_Recv(sock->sock, data, maxlen); - return size>0 ? size : -1; - } else if(readySockets==0) { - return 0; - } else { - flib_log_e("Error in select system call: %s", SDLNet_GetError()); - return -1; - } -} - -int flib_socket_send(flib_tcpsocket *sock, const void *data, int len) { - if(!sock || (len>0 && !data)) { - flib_log_e("Call to flib_socket_send with sock==null or data==null"); - return -1; - } - return SDLNet_TCP_Send(sock->sock, data, len); -} +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "socket.h" +#include "util/logging.h" +#include "util/util.h" +#include +#include +#include + +struct _flib_tcpsocket { + TCPsocket sock; + SDLNet_SocketSet sockset; +}; + +struct _flib_acceptor { + TCPsocket sock; + uint16_t port; +}; + +static uint32_t getPeerIp(TCPsocket sock) { + IPaddress *addr = SDLNet_TCP_GetPeerAddress(sock); + return SDLNet_Read32(&addr->host); +} + +static bool connectionIsLocal(TCPsocket sock) { + return getPeerIp(sock) == (uint32_t)((127UL<<24)+1); // 127.0.0.1 +} + +static flib_tcpsocket *createSocket(TCPsocket sdlsock) { + flib_tcpsocket *result = flib_calloc(1, sizeof(flib_tcpsocket)); + if(result) { + result->sock = sdlsock; + result->sockset = SDLNet_AllocSocketSet(1); + + if(!result->sockset) { + flib_log_e("Can't allocate socket: Out of memory!"); + SDLNet_FreeSocketSet(result->sockset); + free(result); + result = NULL; + } else { + SDLNet_AddSocket(result->sockset, (SDLNet_GenericSocket)result->sock); + } + } + return result; +} + +TCPsocket listen(uint16_t port) { + IPaddress addr; + addr.host = INADDR_ANY; + SDLNet_Write16(port, &addr.port); + TCPsocket sock = SDLNet_TCP_Open(&addr); + if(!sock) { + flib_log_w("Unable to listen on port %u: %s", (unsigned)port, SDLNet_GetError()); + } + return sock; +} + +flib_acceptor *flib_acceptor_create(uint16_t port) { + flib_acceptor *result = flib_calloc(1, sizeof(flib_acceptor)); + if(result) { + if(port > 0) { + result->port = port; + result->sock = listen(result->port); + } else { + /* SDL_net does not seem to have a way to listen on a random unused port + and find out which port that is, so let's try to find one ourselves. */ + srand(time(NULL)); + for(int i=0; !result->sock && i<1000; i++) { + // IANA suggests using ports in the range 49152-65535 for things like this + result->port = 49152+(rand()%(65536-49152)); + result->sock = listen(result->port); + } + } + if(!result->sock) { + flib_log_e("Failed to create acceptor."); + free(result); + result = NULL; + } + } + return result; +} + +uint16_t flib_acceptor_listenport(flib_acceptor *acceptor) { + if(!acceptor) { + flib_log_e("Call to flib_acceptor_listenport with acceptor==null"); + return 0; + } + return acceptor->port; +} + +void flib_acceptor_close(flib_acceptor *acceptor) { + if(acceptor) { + SDLNet_TCP_Close(acceptor->sock); + free(acceptor); + } +} + +flib_tcpsocket *flib_socket_accept(flib_acceptor *acceptor, bool localOnly) { + flib_tcpsocket *result = NULL; + if(!acceptor) { + flib_log_e("Call to flib_socket_accept with acceptor==null"); + } else { + TCPsocket sock = NULL; + while(!result && (sock = SDLNet_TCP_Accept(acceptor->sock))) { + if(localOnly && !connectionIsLocal(sock)) { + flib_log_i("Rejected nonlocal connection attempt from %s", flib_format_ip(getPeerIp(sock))); + } else { + result = createSocket(sock); + } + if(!result) { + SDLNet_TCP_Close(sock); + } + } + } + return result; +} + +flib_tcpsocket *flib_socket_connect(const char *host, uint16_t port) { + flib_tcpsocket *result = NULL; + if(!host || port==0) { + flib_log_e("Invalid parameter in flib_socket_connect"); + } else { + IPaddress ip; + if(SDLNet_ResolveHost(&ip,host,port)==-1) { + flib_log_e("SDLNet_ResolveHost: %s\n", SDLNet_GetError()); + } else { + TCPsocket sock=SDLNet_TCP_Open(&ip); + if(!sock) { + flib_log_e("SDLNet_TCP_Open: %s\n", SDLNet_GetError()); + } else { + result = createSocket(sock); + if(result) { + sock = NULL; + } + } + SDLNet_TCP_Close(sock); + } + } + return result; +} + +void flib_socket_close(flib_tcpsocket *sock) { + if(sock) { + SDLNet_DelSocket(sock->sockset, (SDLNet_GenericSocket)sock->sock); + SDLNet_TCP_Close(sock->sock); + SDLNet_FreeSocketSet(sock->sockset); + free(sock); + } +} + +int flib_socket_nbrecv(flib_tcpsocket *sock, void *data, int maxlen) { + if(!sock || (maxlen>0 && !data)) { + flib_log_e("Call to flib_socket_nbrecv with sock==null or data==null"); + return -1; + } + int readySockets = SDLNet_CheckSockets(sock->sockset, 0); + if(readySockets>0) { + int size = SDLNet_TCP_Recv(sock->sock, data, maxlen); + return size>0 ? size : -1; + } else if(readySockets==0) { + return 0; + } else { + flib_log_e("Error in select system call: %s", SDLNet_GetError()); + return -1; + } +} + +int flib_socket_send(flib_tcpsocket *sock, const void *data, int len) { + if(!sock || (len>0 && !data)) { + flib_log_e("Call to flib_socket_send with sock==null or data==null"); + return -1; + } + return SDLNet_TCP_Send(sock->sock, data, len); +} diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/socket.h --- a/project_files/frontlib/socket.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/socket.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,91 +1,91 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/* - * Sockets for TCP networking. - * - * This layer offers some functionality over what SDL_net offers directly: listening - * sockets (called acceptors here) can be bound to port 0, which will make them listen - * on a random unused port, if one can be found. To support this feature, you can also - * query the local port that an acceptor is listening on. - * - * Further, we support nonblocking reads here. - */ - -#ifndef SOCKET_H_ -#define SOCKET_H_ - -#include -#include - -typedef struct _flib_tcpsocket flib_tcpsocket; -typedef struct _flib_acceptor flib_acceptor; - -/** - * Create a new acceptor which will listen for incoming TCP connections - * on the given port. If port is 0, this will listen on a random - * unused port which can then be queried with flib_acceptor_listenport. - * - * Returns NULL on error. - */ -flib_acceptor *flib_acceptor_create(uint16_t port); - -/** - * Return the port on which the acceptor is listening. - */ -uint16_t flib_acceptor_listenport(flib_acceptor *acceptor); - -/** - * Close the acceptor and free its memory. NULL-safe. - */ -void flib_acceptor_close(flib_acceptor *acceptor); - -/** - * Try to accept a connection from an acceptor (listening socket). - * if localOnly is true, this will only accept connections which came from 127.0.0.1 - * Returns NULL if nothing can be accepted. - */ -flib_tcpsocket *flib_socket_accept(flib_acceptor *acceptor, bool localOnly); - -/** - * Try to connect to the server at the given address. - */ -flib_tcpsocket *flib_socket_connect(const char *host, uint16_t port); - -/** - * Close the socket and free its memory. NULL-safe. - */ -void flib_socket_close(flib_tcpsocket *socket); - -/** - * Attempt to receive up to maxlen bytes from the socket, but does not - * block if nothing is available. - * Returns the ammount of data received, 0 if there was nothing to receive, - * or a negative number if the connection was closed or an error occurred. - */ -int flib_socket_nbrecv(flib_tcpsocket *sock, void *data, int maxlen); - -/** - * Blocking send all the data in the data buffer. Returns the actual ammount - * of data sent, or a negative value on error. If the value returned here - * is less than len, either the connection closed or an error occurred. - */ -int flib_socket_send(flib_tcpsocket *sock, const void *data, int len); - -#endif /* SOCKET_H_ */ +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* + * Sockets for TCP networking. + * + * This layer offers some functionality over what SDL_net offers directly: listening + * sockets (called acceptors here) can be bound to port 0, which will make them listen + * on a random unused port, if one can be found. To support this feature, you can also + * query the local port that an acceptor is listening on. + * + * Further, we support nonblocking reads here. + */ + +#ifndef SOCKET_H_ +#define SOCKET_H_ + +#include +#include + +typedef struct _flib_tcpsocket flib_tcpsocket; +typedef struct _flib_acceptor flib_acceptor; + +/** + * Create a new acceptor which will listen for incoming TCP connections + * on the given port. If port is 0, this will listen on a random + * unused port which can then be queried with flib_acceptor_listenport. + * + * Returns NULL on error. + */ +flib_acceptor *flib_acceptor_create(uint16_t port); + +/** + * Return the port on which the acceptor is listening. + */ +uint16_t flib_acceptor_listenport(flib_acceptor *acceptor); + +/** + * Close the acceptor and free its memory. NULL-safe. + */ +void flib_acceptor_close(flib_acceptor *acceptor); + +/** + * Try to accept a connection from an acceptor (listening socket). + * if localOnly is true, this will only accept connections which came from 127.0.0.1 + * Returns NULL if nothing can be accepted. + */ +flib_tcpsocket *flib_socket_accept(flib_acceptor *acceptor, bool localOnly); + +/** + * Try to connect to the server at the given address. + */ +flib_tcpsocket *flib_socket_connect(const char *host, uint16_t port); + +/** + * Close the socket and free its memory. NULL-safe. + */ +void flib_socket_close(flib_tcpsocket *socket); + +/** + * Attempt to receive up to maxlen bytes from the socket, but does not + * block if nothing is available. + * Returns the ammount of data received, 0 if there was nothing to receive, + * or a negative number if the connection was closed or an error occurred. + */ +int flib_socket_nbrecv(flib_tcpsocket *sock, void *data, int maxlen); + +/** + * Blocking send all the data in the data buffer. Returns the actual ammount + * of data sent, or a negative value on error. If the value returned here + * is less than len, either the connection closed or an error occurred. + */ +int flib_socket_send(flib_tcpsocket *sock, const void *data, int len); + +#endif /* SOCKET_H_ */ diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/util/buffer.c --- a/project_files/frontlib/util/buffer.c Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/util/buffer.c Tue Nov 10 20:43:13 2015 +0100 @@ -1,177 +1,177 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "buffer.h" -#include "logging.h" -#include "util.h" - -#include -#include -#include - -#define MIN_VECTOR_CAPACITY 16 - -struct _flib_vector { - void *data; - size_t size; - size_t capacity; -}; - -flib_vector *flib_vector_create() { - flib_vector *result = NULL; - flib_vector *tmpVector = flib_calloc(1, sizeof(flib_vector)); - if(tmpVector) { - tmpVector->data = flib_malloc(MIN_VECTOR_CAPACITY); - if(tmpVector->data) { - tmpVector->size = 0; - tmpVector->capacity = MIN_VECTOR_CAPACITY; - result = tmpVector; - tmpVector = NULL; - } - } - flib_vector_destroy(tmpVector); - return result; -} - -void flib_vector_destroy(flib_vector *vec) { - if(vec) { - free(vec->data); - free(vec); - } -} - -static int setCapacity(flib_vector *vec, size_t newCapacity) { - if(newCapacity == vec->capacity) { - return 0; - } - void *newData = realloc(vec->data, newCapacity); - if(newData) { - vec->data = newData; - vec->capacity = newCapacity; - return 0; - } else { - return -1; - } -} - -static int allocateExtraCapacity(flib_vector *vec, size_t extraCapacity) { - if(extraCapacity <= SIZE_MAX - vec->capacity) { - return setCapacity(vec, vec->capacity + extraCapacity); - } else { - return -1; - } -} - -int flib_vector_resize(flib_vector *vec, size_t newSize) { - if(log_badargs_if(vec==NULL)) { - return -1; - } - - if(vec->capacity < newSize) { - // Resize exponentially for constant amortized time, - // But at least by as much as we need of course - size_t extraCapacity = (vec->capacity)/2; - size_t minExtraCapacity = newSize - vec->capacity; - if(extraCapacity < minExtraCapacity) { - extraCapacity = minExtraCapacity; - } - - if(allocateExtraCapacity(vec, extraCapacity)) { - allocateExtraCapacity(vec, minExtraCapacity); - } - } else if(vec->capacity/2 > newSize) { - size_t newCapacity = newSize+newSize/4; - if(newCapacity < MIN_VECTOR_CAPACITY) { - newCapacity = MIN_VECTOR_CAPACITY; - } - setCapacity(vec, newCapacity); - } - - if(vec->capacity >= newSize) { - vec->size = newSize; - return 0; - } else { - return -1; - } -} - -int flib_vector_append(flib_vector *vec, const void *data, size_t len) { - if(!log_badargs_if2(vec==NULL, data==NULL && len>0) - && !log_oom_if(len > SIZE_MAX-vec->size)) { - size_t oldSize = vec->size; - if(!log_oom_if(flib_vector_resize(vec, vec->size+len))) { - memmove(((uint8_t*)vec->data) + oldSize, data, len); - return 0; - } - } - return -1; -} - -int flib_vector_appendf(flib_vector *vec, const char *fmt, ...) { - int result = -1; - if(!log_badargs_if2(vec==NULL, fmt==NULL)) { - va_list argp; - va_start(argp, fmt); - char *formatted = flib_vasprintf(fmt, argp); - va_end(argp); - - - if(formatted) { - size_t len = strlen(formatted); - result = flib_vector_append(vec, formatted, len); - } - } - return result; -} - -flib_buffer flib_vector_as_buffer(flib_vector *vec) { - if(log_badargs_if(vec==NULL)) { - flib_buffer result = {NULL, 0}; - return result; - } else { - flib_buffer result = {vec->data, vec->size}; - return result; - } -} - -flib_constbuffer flib_vector_as_constbuffer(flib_vector *vec) { - if(log_badargs_if(vec==NULL)) { - flib_constbuffer result = {NULL, 0}; - return result; - } else { - flib_constbuffer result = {vec->data, vec->size}; - return result; - } -} - -void *flib_vector_data(flib_vector *vec) { - if(log_badargs_if(vec==NULL)) { - return NULL; - } else { - return vec->data; - } -} - -size_t flib_vector_size(flib_vector *vec) { - if(log_badargs_if(vec==NULL)) { - return 0; - } else { - return vec->size; - } -} +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "buffer.h" +#include "logging.h" +#include "util.h" + +#include +#include +#include + +#define MIN_VECTOR_CAPACITY 16 + +struct _flib_vector { + void *data; + size_t size; + size_t capacity; +}; + +flib_vector *flib_vector_create() { + flib_vector *result = NULL; + flib_vector *tmpVector = flib_calloc(1, sizeof(flib_vector)); + if(tmpVector) { + tmpVector->data = flib_malloc(MIN_VECTOR_CAPACITY); + if(tmpVector->data) { + tmpVector->size = 0; + tmpVector->capacity = MIN_VECTOR_CAPACITY; + result = tmpVector; + tmpVector = NULL; + } + } + flib_vector_destroy(tmpVector); + return result; +} + +void flib_vector_destroy(flib_vector *vec) { + if(vec) { + free(vec->data); + free(vec); + } +} + +static int setCapacity(flib_vector *vec, size_t newCapacity) { + if(newCapacity == vec->capacity) { + return 0; + } + void *newData = realloc(vec->data, newCapacity); + if(newData) { + vec->data = newData; + vec->capacity = newCapacity; + return 0; + } else { + return -1; + } +} + +static int allocateExtraCapacity(flib_vector *vec, size_t extraCapacity) { + if(extraCapacity <= SIZE_MAX - vec->capacity) { + return setCapacity(vec, vec->capacity + extraCapacity); + } else { + return -1; + } +} + +int flib_vector_resize(flib_vector *vec, size_t newSize) { + if(log_badargs_if(vec==NULL)) { + return -1; + } + + if(vec->capacity < newSize) { + // Resize exponentially for constant amortized time, + // But at least by as much as we need of course + size_t extraCapacity = (vec->capacity)/2; + size_t minExtraCapacity = newSize - vec->capacity; + if(extraCapacity < minExtraCapacity) { + extraCapacity = minExtraCapacity; + } + + if(allocateExtraCapacity(vec, extraCapacity)) { + allocateExtraCapacity(vec, minExtraCapacity); + } + } else if(vec->capacity/2 > newSize) { + size_t newCapacity = newSize+newSize/4; + if(newCapacity < MIN_VECTOR_CAPACITY) { + newCapacity = MIN_VECTOR_CAPACITY; + } + setCapacity(vec, newCapacity); + } + + if(vec->capacity >= newSize) { + vec->size = newSize; + return 0; + } else { + return -1; + } +} + +int flib_vector_append(flib_vector *vec, const void *data, size_t len) { + if(!log_badargs_if2(vec==NULL, data==NULL && len>0) + && !log_oom_if(len > SIZE_MAX-vec->size)) { + size_t oldSize = vec->size; + if(!log_oom_if(flib_vector_resize(vec, vec->size+len))) { + memmove(((uint8_t*)vec->data) + oldSize, data, len); + return 0; + } + } + return -1; +} + +int flib_vector_appendf(flib_vector *vec, const char *fmt, ...) { + int result = -1; + if(!log_badargs_if2(vec==NULL, fmt==NULL)) { + va_list argp; + va_start(argp, fmt); + char *formatted = flib_vasprintf(fmt, argp); + va_end(argp); + + + if(formatted) { + size_t len = strlen(formatted); + result = flib_vector_append(vec, formatted, len); + } + } + return result; +} + +flib_buffer flib_vector_as_buffer(flib_vector *vec) { + if(log_badargs_if(vec==NULL)) { + flib_buffer result = {NULL, 0}; + return result; + } else { + flib_buffer result = {vec->data, vec->size}; + return result; + } +} + +flib_constbuffer flib_vector_as_constbuffer(flib_vector *vec) { + if(log_badargs_if(vec==NULL)) { + flib_constbuffer result = {NULL, 0}; + return result; + } else { + flib_constbuffer result = {vec->data, vec->size}; + return result; + } +} + +void *flib_vector_data(flib_vector *vec) { + if(log_badargs_if(vec==NULL)) { + return NULL; + } else { + return vec->data; + } +} + +size_t flib_vector_size(flib_vector *vec) { + if(log_badargs_if(vec==NULL)) { + return 0; + } else { + return vec->size; + } +} diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/util/buffer.h --- a/project_files/frontlib/util/buffer.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/util/buffer.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,104 +1,104 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef BUFFER_H_ -#define BUFFER_H_ - -#include -#include - -/** - * A simple struct to hold both the pointer to an array and its size, - * for e.g. conveniently returning it from a function. - * - * Convention: Size is zero iff data is a NULL pointer. - */ -typedef struct { - void *data; - size_t size; -} flib_buffer; - -/** - * Just like flib_buffer, but the contents are not supposed to be modified. - */ -typedef struct { - const void *data; - size_t size; -} flib_constbuffer; - -/** - * Simple variable-capacity data structure that can be efficiently appended to. - */ -typedef struct _flib_vector flib_vector; - -/** - * Create a new vector. Needs to be destroyed again later with flib_vector_destroy. - * May return NULL if memory runs out. - */ -flib_vector *flib_vector_create(); - -/** - * Free the memory of this vector - */ -void flib_vector_destroy(flib_vector *vec); - -/** - * Resize the vector. This changes the size, and ensures the capacity is large enough to - * for the new size. Can also free memory if the new size is smaller. There is no guarantee - * about the contents of extra memory. - */ -int flib_vector_resize(flib_vector *vec, size_t newSize); - -/** - * Append the provided data to the end of the vector, enlarging it as required. - * The vector remains unchanged if appending fails. - * Returns 0 on success. - */ -int flib_vector_append(flib_vector *vec, const void *data, size_t len); - -/** - * Append data from a format string to the buffer (without trailing 0) - * Returns 0 on success. - */ -int flib_vector_appendf(flib_vector *vec, const char *template, ...); - -/** - * Return a pointer to the current data buffer of the vector. This pointer can - * become invalid if the vector size or capacity is changed. - */ -void *flib_vector_data(flib_vector *vec); - -/** - * Return the current size of the vector. - */ -size_t flib_vector_size(flib_vector *vec); - -/** - * Return a buffer pointing to the current contents of the vector. - * These will become invalid if the vector size or capacity is changed. - */ -flib_buffer flib_vector_as_buffer(flib_vector *vec); - -/** - * Return a constbuffer pointing to the current contents of the vector. - * These will become invalid if the vector size or capacity is changed. - */ -flib_constbuffer flib_vector_as_constbuffer(flib_vector *vec); - -#endif +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef BUFFER_H_ +#define BUFFER_H_ + +#include +#include + +/** + * A simple struct to hold both the pointer to an array and its size, + * for e.g. conveniently returning it from a function. + * + * Convention: Size is zero iff data is a NULL pointer. + */ +typedef struct { + void *data; + size_t size; +} flib_buffer; + +/** + * Just like flib_buffer, but the contents are not supposed to be modified. + */ +typedef struct { + const void *data; + size_t size; +} flib_constbuffer; + +/** + * Simple variable-capacity data structure that can be efficiently appended to. + */ +typedef struct _flib_vector flib_vector; + +/** + * Create a new vector. Needs to be destroyed again later with flib_vector_destroy. + * May return NULL if memory runs out. + */ +flib_vector *flib_vector_create(); + +/** + * Free the memory of this vector + */ +void flib_vector_destroy(flib_vector *vec); + +/** + * Resize the vector. This changes the size, and ensures the capacity is large enough to + * for the new size. Can also free memory if the new size is smaller. There is no guarantee + * about the contents of extra memory. + */ +int flib_vector_resize(flib_vector *vec, size_t newSize); + +/** + * Append the provided data to the end of the vector, enlarging it as required. + * The vector remains unchanged if appending fails. + * Returns 0 on success. + */ +int flib_vector_append(flib_vector *vec, const void *data, size_t len); + +/** + * Append data from a format string to the buffer (without trailing 0) + * Returns 0 on success. + */ +int flib_vector_appendf(flib_vector *vec, const char *template, ...); + +/** + * Return a pointer to the current data buffer of the vector. This pointer can + * become invalid if the vector size or capacity is changed. + */ +void *flib_vector_data(flib_vector *vec); + +/** + * Return the current size of the vector. + */ +size_t flib_vector_size(flib_vector *vec); + +/** + * Return a buffer pointing to the current contents of the vector. + * These will become invalid if the vector size or capacity is changed. + */ +flib_buffer flib_vector_as_buffer(flib_vector *vec); + +/** + * Return a constbuffer pointing to the current contents of the vector. + * These will become invalid if the vector size or capacity is changed. + */ +flib_constbuffer flib_vector_as_constbuffer(flib_vector *vec); + +#endif diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/util/inihelper.c --- a/project_files/frontlib/util/inihelper.c Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/util/inihelper.c Tue Nov 10 20:43:13 2015 +0100 @@ -1,321 +1,321 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "inihelper.h" -#include "../iniparser/dictionary.h" -#include "../iniparser/iniparser.h" - -#include "logging.h" -#include "util.h" - -#include -#include -#include -#include -#include -#include - -struct _flib_ini { - dictionary *inidict; - char *currentSection; -}; - -static char *createDictKey(const char *sectionName, const char *keyName) { - return flib_asprintf("%s:%s", sectionName, keyName); -} - -/** - * Turns a string into a lowercase string, in-place. - */ -static void strToLower(char *str) { - if(str) { - while(*str) { - *str = tolower(*str); - str++; - } - } -} - -flib_ini *flib_ini_create(const char *filename) { - flib_ini *result = NULL; - flib_ini *tmpIni = flib_calloc(1, sizeof(flib_ini)); - if(tmpIni) { - if(filename) { - tmpIni->inidict = iniparser_load(filename); - } - if(!tmpIni->inidict) { - tmpIni->inidict = dictionary_new(0); - } - if(tmpIni->inidict) { - result = tmpIni; - tmpIni = NULL; - } - } - flib_ini_destroy(tmpIni); - return result; -} - -flib_ini *flib_ini_load(const char *filename) { - flib_ini *result = NULL; - if(!log_badargs_if(filename==NULL)) { - flib_ini *tmpIni = flib_calloc(1, sizeof(flib_ini)); - if(tmpIni) { - tmpIni->inidict = iniparser_load(filename); - if(tmpIni->inidict) { - result = tmpIni; - tmpIni = NULL; - } - } - flib_ini_destroy(tmpIni); - } - return result; -} - -int flib_ini_save(flib_ini *ini, const char *filename) { - int result = INI_ERROR_OTHER; - if(!log_badargs_if2(ini==NULL, filename==NULL)) { - FILE *file = fopen(filename, "wb"); - if(!file) { - flib_log_e("Error opening file \"%s\" for writing.", filename); - } else { - iniparser_dump_ini(ini->inidict, file); - if(fclose(file)) { - flib_log_e("Write error on ini file \"%s\"", filename); - } else { - result = 0; - } - } - } - return result; -} - -void flib_ini_destroy(flib_ini *ini) { - if(ini) { - if(ini->inidict) { - iniparser_freedict(ini->inidict); - } - free(ini->currentSection); - free(ini); - } -} - -int flib_ini_enter_section(flib_ini *ini, const char *section) { - int result = INI_ERROR_OTHER; - if(ini) { - free(ini->currentSection); - ini->currentSection = NULL; - } - if(!log_badargs_if2(ini==NULL, section==NULL)) { - if(!iniparser_find_entry(ini->inidict, section)) { - flib_log_d("Ini section %s not found", section); - result = INI_ERROR_NOTFOUND; - } else { - ini->currentSection = flib_strdupnull(section); - if(ini->currentSection) { - // Usually iniparser ignores case, but some section-handling functions don't, - // so we set it to lowercase manually - strToLower(ini->currentSection); - result = 0; - } - } - } - return result; -} - -int flib_ini_create_section(flib_ini *ini, const char *section) { - int result = INI_ERROR_OTHER; - if(!log_badargs_if2(ini==NULL, section==NULL)) { - result = flib_ini_enter_section(ini, section); - if(result == INI_ERROR_NOTFOUND) { - if(iniparser_set(ini->inidict, section, NULL)) { - flib_log_e("Error creating ini section %s", section); - result = INI_ERROR_OTHER; - } else { - result = flib_ini_enter_section(ini, section); - } - } - } - return result; -} - -/** - * The result is an internal string of the iniparser, don't free it. - */ -static char *findValue(dictionary *dict, const char *section, const char *key) { - char *result = NULL; - char *dictKey = createDictKey(section, key); - if(dictKey) { - result = iniparser_getstring(dict, dictKey, NULL); - } - free(dictKey); - return result; -} - -int flib_ini_get_str(flib_ini *ini, char **outVar, const char *key) { - char *tmpValue = NULL; - int result = flib_ini_get_str_opt(ini, &tmpValue, key, NULL); - if(result==0) { - if(tmpValue == NULL) { - result = INI_ERROR_NOTFOUND; - } else { - *outVar = tmpValue; - tmpValue = NULL; - } - } - free(tmpValue); - return result; -} - -int flib_ini_get_str_opt(flib_ini *ini, char **outVar, const char *key, const char *def) { - int result = INI_ERROR_OTHER; - if(!log_badargs_if4(ini==NULL, ini->currentSection==NULL, outVar==NULL, key==NULL)) { - const char *value = findValue(ini->inidict, ini->currentSection, key); - if(!value) { - value = def; - } - char *valueDup = flib_strdupnull(value); - if(valueDup || !def) { - *outVar = valueDup; - result = 0; - } - } - return result; -} - -int flib_ini_get_int(flib_ini *ini, int *outVar, const char *key) { - char *tmpValue = NULL; - int result = flib_ini_get_str(ini, &tmpValue, key); - if(result==0) { - errno = 0; - long val = strtol(tmpValue, NULL, 10); - if(errno!=0 || valINT_MAX) { - flib_log_w("Cannot parse ini setting %s/%s = \"%s\" as integer.", ini->currentSection, key, tmpValue); - result = INI_ERROR_FORMAT; - } else { - *outVar = val; - } - } - free(tmpValue); - return result; -} - -int flib_ini_get_int_opt(flib_ini *ini, int *outVar, const char *key, int def) { - int tmpValue; - int result = flib_ini_get_int(ini, &tmpValue, key); - if(result == 0) { - *outVar = tmpValue; - } else if(result == INI_ERROR_NOTFOUND || result == INI_ERROR_FORMAT) { - *outVar = def; - result = 0; - } - return result; -} - -int flib_ini_get_bool(flib_ini *ini, bool *outVar, const char *key) { - char *tmpValue = NULL; - int result = flib_ini_get_str(ini, &tmpValue, key); - if(result==0) { - bool trueval = strchr("1tTyY", tmpValue[0]); - bool falseval = strchr("0fFnN", tmpValue[0]); - if(!trueval && !falseval) { - flib_log_w("ini setting %s/%s = \"%s\" is not a recognized truth value.", ini->currentSection, key, tmpValue); - result = INI_ERROR_FORMAT; - } else { - *outVar = trueval; - } - } - free(tmpValue); - return result; -} - -int flib_ini_get_bool_opt(flib_ini *ini, bool *outVar, const char *key, bool def) { - bool tmpValue; - int result = flib_ini_get_bool(ini, &tmpValue, key); - if(result == 0) { - *outVar = tmpValue; - } else if(result == INI_ERROR_NOTFOUND || result == INI_ERROR_FORMAT) { - *outVar = def; - result = 0; - } - return result; -} - -int flib_ini_set_str(flib_ini *ini, const char *key, const char *value) { - int result = INI_ERROR_OTHER; - if(!log_badargs_if4(ini==NULL, ini->currentSection==NULL, key==NULL, value==NULL)) { - char *dictKey = createDictKey(ini->currentSection, key); - if(dictKey) { - result = iniparser_set(ini->inidict, dictKey, value); - if(result) { - flib_log_e("Error setting ini entry %s to %s", dictKey, value); - } - } - free(dictKey); - } - return result; -} - -int flib_ini_set_int(flib_ini *ini, const char *key, int value) { - int result = INI_ERROR_OTHER; - char *strvalue = flib_asprintf("%i", value); - if(strvalue) { - result = flib_ini_set_str(ini, key, strvalue); - } - free(strvalue); - return result; -} - -int flib_ini_set_bool(flib_ini *ini, const char *key, bool value) { - return flib_ini_set_str(ini, key, value ? "true" : "false"); -} - -int flib_ini_get_sectioncount(flib_ini *ini) { - if(!log_badargs_if(ini==NULL)) { - return iniparser_getnsec(ini->inidict); - } - return INI_ERROR_OTHER; -} - -char *flib_ini_get_sectionname(flib_ini *ini, int number) { - if(!log_badargs_if2(ini==NULL, number<0)) { - return flib_strdupnull(iniparser_getsecname(ini->inidict, number)); - } - return NULL; -} - -int flib_ini_get_keycount(flib_ini *ini) { - if(!log_badargs_if2(ini==NULL, ini->currentSection==NULL)) { - return iniparser_getsecnkeys(ini->inidict, ini->currentSection); - } - return INI_ERROR_OTHER; -} - -char *flib_ini_get_keyname(flib_ini *ini, int number) { - char *result = NULL; - if(!log_badargs_if3(ini==NULL, ini->currentSection==NULL, number<0)) { - int keyCount = iniparser_getsecnkeys(ini->inidict, ini->currentSection); - char **keys = iniparser_getseckeys(ini->inidict, ini->currentSection); - if(keys && keyCount>number) { - // The keys are in the format section:key, so we have to skip the section and colon. - result = flib_strdupnull(keys[number]+strlen(ini->currentSection)+1); - } - free(keys); - } - return result; -} +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "inihelper.h" +#include "../iniparser/dictionary.h" +#include "../iniparser/iniparser.h" + +#include "logging.h" +#include "util.h" + +#include +#include +#include +#include +#include +#include + +struct _flib_ini { + dictionary *inidict; + char *currentSection; +}; + +static char *createDictKey(const char *sectionName, const char *keyName) { + return flib_asprintf("%s:%s", sectionName, keyName); +} + +/** + * Turns a string into a lowercase string, in-place. + */ +static void strToLower(char *str) { + if(str) { + while(*str) { + *str = tolower(*str); + str++; + } + } +} + +flib_ini *flib_ini_create(const char *filename) { + flib_ini *result = NULL; + flib_ini *tmpIni = flib_calloc(1, sizeof(flib_ini)); + if(tmpIni) { + if(filename) { + tmpIni->inidict = iniparser_load(filename); + } + if(!tmpIni->inidict) { + tmpIni->inidict = dictionary_new(0); + } + if(tmpIni->inidict) { + result = tmpIni; + tmpIni = NULL; + } + } + flib_ini_destroy(tmpIni); + return result; +} + +flib_ini *flib_ini_load(const char *filename) { + flib_ini *result = NULL; + if(!log_badargs_if(filename==NULL)) { + flib_ini *tmpIni = flib_calloc(1, sizeof(flib_ini)); + if(tmpIni) { + tmpIni->inidict = iniparser_load(filename); + if(tmpIni->inidict) { + result = tmpIni; + tmpIni = NULL; + } + } + flib_ini_destroy(tmpIni); + } + return result; +} + +int flib_ini_save(flib_ini *ini, const char *filename) { + int result = INI_ERROR_OTHER; + if(!log_badargs_if2(ini==NULL, filename==NULL)) { + FILE *file = fopen(filename, "wb"); + if(!file) { + flib_log_e("Error opening file \"%s\" for writing.", filename); + } else { + iniparser_dump_ini(ini->inidict, file); + if(fclose(file)) { + flib_log_e("Write error on ini file \"%s\"", filename); + } else { + result = 0; + } + } + } + return result; +} + +void flib_ini_destroy(flib_ini *ini) { + if(ini) { + if(ini->inidict) { + iniparser_freedict(ini->inidict); + } + free(ini->currentSection); + free(ini); + } +} + +int flib_ini_enter_section(flib_ini *ini, const char *section) { + int result = INI_ERROR_OTHER; + if(ini) { + free(ini->currentSection); + ini->currentSection = NULL; + } + if(!log_badargs_if2(ini==NULL, section==NULL)) { + if(!iniparser_find_entry(ini->inidict, section)) { + flib_log_d("Ini section %s not found", section); + result = INI_ERROR_NOTFOUND; + } else { + ini->currentSection = flib_strdupnull(section); + if(ini->currentSection) { + // Usually iniparser ignores case, but some section-handling functions don't, + // so we set it to lowercase manually + strToLower(ini->currentSection); + result = 0; + } + } + } + return result; +} + +int flib_ini_create_section(flib_ini *ini, const char *section) { + int result = INI_ERROR_OTHER; + if(!log_badargs_if2(ini==NULL, section==NULL)) { + result = flib_ini_enter_section(ini, section); + if(result == INI_ERROR_NOTFOUND) { + if(iniparser_set(ini->inidict, section, NULL)) { + flib_log_e("Error creating ini section %s", section); + result = INI_ERROR_OTHER; + } else { + result = flib_ini_enter_section(ini, section); + } + } + } + return result; +} + +/** + * The result is an internal string of the iniparser, don't free it. + */ +static char *findValue(dictionary *dict, const char *section, const char *key) { + char *result = NULL; + char *dictKey = createDictKey(section, key); + if(dictKey) { + result = iniparser_getstring(dict, dictKey, NULL); + } + free(dictKey); + return result; +} + +int flib_ini_get_str(flib_ini *ini, char **outVar, const char *key) { + char *tmpValue = NULL; + int result = flib_ini_get_str_opt(ini, &tmpValue, key, NULL); + if(result==0) { + if(tmpValue == NULL) { + result = INI_ERROR_NOTFOUND; + } else { + *outVar = tmpValue; + tmpValue = NULL; + } + } + free(tmpValue); + return result; +} + +int flib_ini_get_str_opt(flib_ini *ini, char **outVar, const char *key, const char *def) { + int result = INI_ERROR_OTHER; + if(!log_badargs_if4(ini==NULL, ini->currentSection==NULL, outVar==NULL, key==NULL)) { + const char *value = findValue(ini->inidict, ini->currentSection, key); + if(!value) { + value = def; + } + char *valueDup = flib_strdupnull(value); + if(valueDup || !def) { + *outVar = valueDup; + result = 0; + } + } + return result; +} + +int flib_ini_get_int(flib_ini *ini, int *outVar, const char *key) { + char *tmpValue = NULL; + int result = flib_ini_get_str(ini, &tmpValue, key); + if(result==0) { + errno = 0; + long val = strtol(tmpValue, NULL, 10); + if(errno!=0 || valINT_MAX) { + flib_log_w("Cannot parse ini setting %s/%s = \"%s\" as integer.", ini->currentSection, key, tmpValue); + result = INI_ERROR_FORMAT; + } else { + *outVar = val; + } + } + free(tmpValue); + return result; +} + +int flib_ini_get_int_opt(flib_ini *ini, int *outVar, const char *key, int def) { + int tmpValue; + int result = flib_ini_get_int(ini, &tmpValue, key); + if(result == 0) { + *outVar = tmpValue; + } else if(result == INI_ERROR_NOTFOUND || result == INI_ERROR_FORMAT) { + *outVar = def; + result = 0; + } + return result; +} + +int flib_ini_get_bool(flib_ini *ini, bool *outVar, const char *key) { + char *tmpValue = NULL; + int result = flib_ini_get_str(ini, &tmpValue, key); + if(result==0) { + bool trueval = strchr("1tTyY", tmpValue[0]); + bool falseval = strchr("0fFnN", tmpValue[0]); + if(!trueval && !falseval) { + flib_log_w("ini setting %s/%s = \"%s\" is not a recognized truth value.", ini->currentSection, key, tmpValue); + result = INI_ERROR_FORMAT; + } else { + *outVar = trueval; + } + } + free(tmpValue); + return result; +} + +int flib_ini_get_bool_opt(flib_ini *ini, bool *outVar, const char *key, bool def) { + bool tmpValue; + int result = flib_ini_get_bool(ini, &tmpValue, key); + if(result == 0) { + *outVar = tmpValue; + } else if(result == INI_ERROR_NOTFOUND || result == INI_ERROR_FORMAT) { + *outVar = def; + result = 0; + } + return result; +} + +int flib_ini_set_str(flib_ini *ini, const char *key, const char *value) { + int result = INI_ERROR_OTHER; + if(!log_badargs_if4(ini==NULL, ini->currentSection==NULL, key==NULL, value==NULL)) { + char *dictKey = createDictKey(ini->currentSection, key); + if(dictKey) { + result = iniparser_set(ini->inidict, dictKey, value); + if(result) { + flib_log_e("Error setting ini entry %s to %s", dictKey, value); + } + } + free(dictKey); + } + return result; +} + +int flib_ini_set_int(flib_ini *ini, const char *key, int value) { + int result = INI_ERROR_OTHER; + char *strvalue = flib_asprintf("%i", value); + if(strvalue) { + result = flib_ini_set_str(ini, key, strvalue); + } + free(strvalue); + return result; +} + +int flib_ini_set_bool(flib_ini *ini, const char *key, bool value) { + return flib_ini_set_str(ini, key, value ? "true" : "false"); +} + +int flib_ini_get_sectioncount(flib_ini *ini) { + if(!log_badargs_if(ini==NULL)) { + return iniparser_getnsec(ini->inidict); + } + return INI_ERROR_OTHER; +} + +char *flib_ini_get_sectionname(flib_ini *ini, int number) { + if(!log_badargs_if2(ini==NULL, number<0)) { + return flib_strdupnull(iniparser_getsecname(ini->inidict, number)); + } + return NULL; +} + +int flib_ini_get_keycount(flib_ini *ini) { + if(!log_badargs_if2(ini==NULL, ini->currentSection==NULL)) { + return iniparser_getsecnkeys(ini->inidict, ini->currentSection); + } + return INI_ERROR_OTHER; +} + +char *flib_ini_get_keyname(flib_ini *ini, int number) { + char *result = NULL; + if(!log_badargs_if3(ini==NULL, ini->currentSection==NULL, number<0)) { + int keyCount = iniparser_getsecnkeys(ini->inidict, ini->currentSection); + char **keys = iniparser_getseckeys(ini->inidict, ini->currentSection); + if(keys && keyCount>number) { + // The keys are in the format section:key, so we have to skip the section and colon. + result = flib_strdupnull(keys[number]+strlen(ini->currentSection)+1); + } + free(keys); + } + return result; +} diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/util/inihelper.h --- a/project_files/frontlib/util/inihelper.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/util/inihelper.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,178 +1,178 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * Convenience interface for ini reading/writing. - * - * We currently use iniparser in the background, but using its interface directly is a bit verbose. - * This module is supposed to 1. make ini reading and writing a bit more convenient, and 2. hide - * the iniparser dependency so it can at need be easily replaced. - */ - -#ifndef INIHELPER_H_ -#define INIHELPER_H_ - -#include - -#define INI_ERROR_NOTFOUND -1 -#define INI_ERROR_FORMAT -2 -#define INI_ERROR_OTHER -100 - -typedef struct _flib_ini flib_ini; - -/** - * Create a new ini data structure, pre-filled with the contents of - * the file "filename" if it exists. If filename is null, or the file - * is not found, an empty ini will be created. However, if an error - * occurs while reading the ini file (or any other error), null - * is returned. - * - * This behavior is useful for modifying an existing ini file without - * discarding unknown keys. - */ -flib_ini *flib_ini_create(const char *filename); - -/** - * Similar to flib_ini_create, but fails if the file is not found - * or if filename is null. - */ -flib_ini *flib_ini_load(const char *filename); - -/** - * Store the ini to the file "filename", overwriting - * the previous contents. Returns 0 on success. - */ -int flib_ini_save(flib_ini *ini, const char *filename); - -void flib_ini_destroy(flib_ini *ini); - -/** - * Enter the section with the specified name. Returns 0 on - * success, INI_ERROR_NOTFOUND if the section does not exist - * and a different value if another error occurs. - * If an error occurs, there is no current section. - * - * The section name should only consist of letters and - * numbers. - */ -int flib_ini_enter_section(flib_ini *ini, const char *section); - -/** - * Creates and enters the section with the specified name. Simply - * enters the section if it exists already. Returns 0 on success - * and a different value if another error occurs. - * If an error occurs, there is no current section. - */ -int flib_ini_create_section(flib_ini *ini, const char *section); - -/** - * Find a key in the current section and store the value in outVar - * as a newly allocated string. Returns 0 on success, INI_ERROR_NOTFOUND - * if the key was not found and a different value for other errors, - * e.g. if there is no current section. - */ -int flib_ini_get_str(flib_ini *ini, char **outVar, const char *key); - -/** - * Find a key in the current section and store the value in outVar - * as a newly allocated string. If the key is not found, the default - * value will be used instead. Returns 0 on success. - */ -int flib_ini_get_str_opt(flib_ini *ini, char **outVar, const char *key, const char *def); - -/** - * Find a key in the current section and store the value in outVar - * as an int. Returns 0 on success, INI_ERROR_NOTFOUND - * if the key was not found, INI_ERROR_FORMAT if it was found but - * could not be converted to an int, and a different value for other - * errors, e.g. if there is no current section. - */ -int flib_ini_get_int(flib_ini *ini, int *outVar, const char *key); - -/** - * Find a key in the current section and store the value in outVar - * as an int. If the key is not found, the default value will be used instead. - * Returns 0 on success, INI_ERROR_FORMAT if the value was found but - * could not be converted to int, and another value otherwise. - */ -int flib_ini_get_int_opt(flib_ini *ini, int *outVar, const char *key, int def); - -/** - * Find a key in the current section and store the value in outVar - * as a bool. Treats everything beginning with "Y", "T" or "1" as true, - * everything starting with "N", "F" or "1" as false. - * - * Returns 0 on success, INI_ERROR_NOTFOUND if the key was not found, - * INI_ERROR_FORMAT if the value could not be interpreted as boolean, - * and another value otherwise. - */ -int flib_ini_get_bool(flib_ini *ini, bool *outVar, const char *key); - -/** - * Find a key in the current section and store the value in outVar - * as a bool. If the key is not found, the default value will be - * used instead. Returns 0 on success, INI_ERROR_FORMAT if the - * value could not be interpreted as boolean, and another value otherwise. - */ -int flib_ini_get_bool_opt(flib_ini *ini, bool *outVar, const char *key, bool def); - -/** - * In the current section, associate key with value. Returns 0 on success. - */ -int flib_ini_set_str(flib_ini *ini, const char *key, const char *value); - -/** - * In the current section, associate key with value. Returns 0 on success. - */ -int flib_ini_set_int(flib_ini *ini, const char *key, int value); - -/** - * In the current section, associate key with value. Returns 0 on success. - */ -int flib_ini_set_bool(flib_ini *ini, const char *key, bool value); - -/** - * Returns the number of sections in the ini file, or a negative value on error. - */ -int flib_ini_get_sectioncount(flib_ini *ini); - -/** - * Returns the name of the section, or NULL on error. The returned string must - * be free()d. - * - * Note: There is no guarantee that the order of the sections - * will remain stable if the ini is modified. - */ -char *flib_ini_get_sectionname(flib_ini *ini, int number); - -/** - * Returns the number of keys in the current section, or -1 on error. - */ -int flib_ini_get_keycount(flib_ini *ini); - -/** - * Returns the name of the key in the current section, or NULL on error. - * The returned string must be free()d. - * - * Note: There is no guarantee that the order of the keys in a section - * will remain stable if the ini is modified. - */ -char *flib_ini_get_keyname(flib_ini *ini, int number); - -#endif /* INIHELPER_H_ */ +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * Convenience interface for ini reading/writing. + * + * We currently use iniparser in the background, but using its interface directly is a bit verbose. + * This module is supposed to 1. make ini reading and writing a bit more convenient, and 2. hide + * the iniparser dependency so it can at need be easily replaced. + */ + +#ifndef INIHELPER_H_ +#define INIHELPER_H_ + +#include + +#define INI_ERROR_NOTFOUND -1 +#define INI_ERROR_FORMAT -2 +#define INI_ERROR_OTHER -100 + +typedef struct _flib_ini flib_ini; + +/** + * Create a new ini data structure, pre-filled with the contents of + * the file "filename" if it exists. If filename is null, or the file + * is not found, an empty ini will be created. However, if an error + * occurs while reading the ini file (or any other error), null + * is returned. + * + * This behavior is useful for modifying an existing ini file without + * discarding unknown keys. + */ +flib_ini *flib_ini_create(const char *filename); + +/** + * Similar to flib_ini_create, but fails if the file is not found + * or if filename is null. + */ +flib_ini *flib_ini_load(const char *filename); + +/** + * Store the ini to the file "filename", overwriting + * the previous contents. Returns 0 on success. + */ +int flib_ini_save(flib_ini *ini, const char *filename); + +void flib_ini_destroy(flib_ini *ini); + +/** + * Enter the section with the specified name. Returns 0 on + * success, INI_ERROR_NOTFOUND if the section does not exist + * and a different value if another error occurs. + * If an error occurs, there is no current section. + * + * The section name should only consist of letters and + * numbers. + */ +int flib_ini_enter_section(flib_ini *ini, const char *section); + +/** + * Creates and enters the section with the specified name. Simply + * enters the section if it exists already. Returns 0 on success + * and a different value if another error occurs. + * If an error occurs, there is no current section. + */ +int flib_ini_create_section(flib_ini *ini, const char *section); + +/** + * Find a key in the current section and store the value in outVar + * as a newly allocated string. Returns 0 on success, INI_ERROR_NOTFOUND + * if the key was not found and a different value for other errors, + * e.g. if there is no current section. + */ +int flib_ini_get_str(flib_ini *ini, char **outVar, const char *key); + +/** + * Find a key in the current section and store the value in outVar + * as a newly allocated string. If the key is not found, the default + * value will be used instead. Returns 0 on success. + */ +int flib_ini_get_str_opt(flib_ini *ini, char **outVar, const char *key, const char *def); + +/** + * Find a key in the current section and store the value in outVar + * as an int. Returns 0 on success, INI_ERROR_NOTFOUND + * if the key was not found, INI_ERROR_FORMAT if it was found but + * could not be converted to an int, and a different value for other + * errors, e.g. if there is no current section. + */ +int flib_ini_get_int(flib_ini *ini, int *outVar, const char *key); + +/** + * Find a key in the current section and store the value in outVar + * as an int. If the key is not found, the default value will be used instead. + * Returns 0 on success, INI_ERROR_FORMAT if the value was found but + * could not be converted to int, and another value otherwise. + */ +int flib_ini_get_int_opt(flib_ini *ini, int *outVar, const char *key, int def); + +/** + * Find a key in the current section and store the value in outVar + * as a bool. Treats everything beginning with "Y", "T" or "1" as true, + * everything starting with "N", "F" or "1" as false. + * + * Returns 0 on success, INI_ERROR_NOTFOUND if the key was not found, + * INI_ERROR_FORMAT if the value could not be interpreted as boolean, + * and another value otherwise. + */ +int flib_ini_get_bool(flib_ini *ini, bool *outVar, const char *key); + +/** + * Find a key in the current section and store the value in outVar + * as a bool. If the key is not found, the default value will be + * used instead. Returns 0 on success, INI_ERROR_FORMAT if the + * value could not be interpreted as boolean, and another value otherwise. + */ +int flib_ini_get_bool_opt(flib_ini *ini, bool *outVar, const char *key, bool def); + +/** + * In the current section, associate key with value. Returns 0 on success. + */ +int flib_ini_set_str(flib_ini *ini, const char *key, const char *value); + +/** + * In the current section, associate key with value. Returns 0 on success. + */ +int flib_ini_set_int(flib_ini *ini, const char *key, int value); + +/** + * In the current section, associate key with value. Returns 0 on success. + */ +int flib_ini_set_bool(flib_ini *ini, const char *key, bool value); + +/** + * Returns the number of sections in the ini file, or a negative value on error. + */ +int flib_ini_get_sectioncount(flib_ini *ini); + +/** + * Returns the name of the section, or NULL on error. The returned string must + * be free()d. + * + * Note: There is no guarantee that the order of the sections + * will remain stable if the ini is modified. + */ +char *flib_ini_get_sectionname(flib_ini *ini, int number); + +/** + * Returns the number of keys in the current section, or -1 on error. + */ +int flib_ini_get_keycount(flib_ini *ini); + +/** + * Returns the name of the key in the current section, or NULL on error. + * The returned string must be free()d. + * + * Note: There is no guarantee that the order of the keys in a section + * will remain stable if the ini is modified. + */ +char *flib_ini_get_keyname(flib_ini *ini, int number); + +#endif /* INIHELPER_H_ */ diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/util/list.h --- a/project_files/frontlib/util/list.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/util/list.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,80 +1,80 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * Simple dynamic array manipulation functions. - */ - -#ifndef LIST_H_ -#define LIST_H_ - -#include -#include -#include -#include "util.h" -#include "logging.h" - -/** - * Generate a static function that inserts a new value into a heap array of the given type, - * using realloc and memmove to increase the capacity and shift existing values. - * The function takes a pointer to the array variable and a pointer to the size variable - * because both can be changed by this operation (realloc / increment). - * The function returns 0 on success and leaves the array unchanged on error. - */ -#define GENERATE_STATIC_LIST_INSERT(fname, type) \ - static int fname(type **listptr, int *listSizePtr, type element, int pos) { \ - int result = -1; \ - if(!log_badargs_if4(listptr==NULL, listSizePtr==NULL, pos < 0, pos > *listSizePtr)) { \ - type *newList = flib_realloc(*listptr, ((*listSizePtr)+1)*sizeof(type)); \ - if(newList) { \ - memmove(newList + (pos+1), newList + pos, ((*listSizePtr)-pos)*sizeof(type)); \ - newList[pos] = element; \ - (*listSizePtr)++; \ - *listptr = newList; \ - result = 0; \ - } \ - } \ - return result; \ - } - -/** - * Generate a static function that deletes a value from a heap array of the given type, - * using realloc and memmove to decrease the capacity and shift existing values. - * The function takes a pointer to the array variable and a pointer to the size variable - * because both can be changed by this operation (realloc / decrement). - * The function returns 0 on success and leaves the array unchanged on error. - */ -#define GENERATE_STATIC_LIST_DELETE(fname, type) \ - static int fname(type **listPtr, int *listSizePtr, int pos) { \ - int result = -1; \ - if(!log_badargs_if4(listPtr==NULL, listSizePtr==NULL, pos < 0, pos >= *listSizePtr)) { \ - memmove((*listPtr) + pos, (*listPtr) + (pos+1), ((*listSizePtr)-(pos+1))*sizeof(type)); \ - (*listSizePtr)--; \ - \ - size_t newCharSize = (*listSizePtr)*sizeof(type); \ - type *newList = flib_realloc((*listPtr), newCharSize); \ - if(newList || newCharSize==0) { \ - (*listPtr) = newList; \ - } /* If the realloc fails, just keep using the old buffer...*/ \ - result = 0; \ - } \ - return result; \ - } - -#endif /* LIST_H_ */ +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * Simple dynamic array manipulation functions. + */ + +#ifndef LIST_H_ +#define LIST_H_ + +#include +#include +#include +#include "util.h" +#include "logging.h" + +/** + * Generate a static function that inserts a new value into a heap array of the given type, + * using realloc and memmove to increase the capacity and shift existing values. + * The function takes a pointer to the array variable and a pointer to the size variable + * because both can be changed by this operation (realloc / increment). + * The function returns 0 on success and leaves the array unchanged on error. + */ +#define GENERATE_STATIC_LIST_INSERT(fname, type) \ + static int fname(type **listptr, int *listSizePtr, type element, int pos) { \ + int result = -1; \ + if(!log_badargs_if4(listptr==NULL, listSizePtr==NULL, pos < 0, pos > *listSizePtr)) { \ + type *newList = flib_realloc(*listptr, ((*listSizePtr)+1)*sizeof(type)); \ + if(newList) { \ + memmove(newList + (pos+1), newList + pos, ((*listSizePtr)-pos)*sizeof(type)); \ + newList[pos] = element; \ + (*listSizePtr)++; \ + *listptr = newList; \ + result = 0; \ + } \ + } \ + return result; \ + } + +/** + * Generate a static function that deletes a value from a heap array of the given type, + * using realloc and memmove to decrease the capacity and shift existing values. + * The function takes a pointer to the array variable and a pointer to the size variable + * because both can be changed by this operation (realloc / decrement). + * The function returns 0 on success and leaves the array unchanged on error. + */ +#define GENERATE_STATIC_LIST_DELETE(fname, type) \ + static int fname(type **listPtr, int *listSizePtr, int pos) { \ + int result = -1; \ + if(!log_badargs_if4(listPtr==NULL, listSizePtr==NULL, pos < 0, pos >= *listSizePtr)) { \ + memmove((*listPtr) + pos, (*listPtr) + (pos+1), ((*listSizePtr)-(pos+1))*sizeof(type)); \ + (*listSizePtr)--; \ + \ + size_t newCharSize = (*listSizePtr)*sizeof(type); \ + type *newList = flib_realloc((*listPtr), newCharSize); \ + if(newList || newCharSize==0) { \ + (*listPtr) = newList; \ + } /* If the realloc fails, just keep using the old buffer...*/ \ + result = 0; \ + } \ + return result; \ + } + +#endif /* LIST_H_ */ diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/util/logging.c --- a/project_files/frontlib/util/logging.c Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/util/logging.c Tue Nov 10 20:43:13 2015 +0100 @@ -1,145 +1,145 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "logging.h" - -#include -#include -#include -#include - -static int flib_loglevel = FLIB_LOGLEVEL_INFO; -static FILE *flib_logfile = NULL; -void (*flib_logCallback)(int level, const char *msg) = NULL; - -char* flib_format_ip(uint32_t numip) { - static char ip[16]; - snprintf(ip, 16, "%u.%u.%u.%u", (unsigned)(numip>>24), (unsigned)((numip>>16)&0xff), (unsigned)((numip>>8)&0xff), (unsigned)(numip&0xff)); - return ip; -} - -static inline FILE *flib_log_getfile() { - if(flib_logfile==NULL) { - return stdout; - } else { - return flib_logfile; - } -} - -static int log_time(char *buffer) { - time_t timer; - struct tm* tm_info; - - time(&timer); - tm_info = localtime(&timer); - - return strftime(buffer, 25, "%Y-%m-%d %H:%M:%S", tm_info); -} - -static char getPrefix(int level) { - switch(level) { - case FLIB_LOGLEVEL_ERROR: return 'E'; - case FLIB_LOGLEVEL_WARNING: return 'W'; - case FLIB_LOGLEVEL_INFO: return 'I'; - case FLIB_LOGLEVEL_DEBUG: return 'D'; - default: return '?'; - } -} - -static void _flib_vflog(const char *func, int level, const char *fmt, va_list args) { - if(level >= flib_loglevel) { - char logbuffer[1024]; - logbuffer[0] = getPrefix(level); - logbuffer[1] = ' '; - - int pos = 2; - - int len = log_time(logbuffer+pos); - if(len>=0) { - pos += len; - if(pos>sizeof(logbuffer)-1) pos = sizeof(logbuffer)-1; - } else { - return; - } - - len = snprintf(logbuffer+pos, sizeof(logbuffer)-pos, " [%-30s] ", func); - if(len>=0) { - pos += len; - if(pos>sizeof(logbuffer)-1) pos = sizeof(logbuffer)-1; - } else { - return; - } - - len = vsnprintf(logbuffer+pos, sizeof(logbuffer)-pos, fmt, args); - if(len>=0) { - pos += len; - if(pos>sizeof(logbuffer)-1) pos = sizeof(logbuffer)-1; - } else { - return; - } - - if(flib_logCallback != NULL) { - flib_logCallback(level, logbuffer); - } else { - FILE *logfile = flib_log_getfile(); - fputs(logbuffer, logfile); - fputc('\n', logfile); - fflush(logfile); - } - } -} - -void _flib_flog(const char *func, int level, const char *fmt, ...) { - va_list argp; - va_start(argp, fmt); - _flib_vflog(func, level, fmt, argp); - va_end(argp); -} - -bool _flib_fassert(const char *func, int level, bool cond, const char *fmt, ...) { - if(!cond) { - va_list argp; - va_start(argp, fmt); - _flib_vflog(func, level, fmt, argp); - va_end(argp); - } - return !cond; -} - -int flib_log_getLevel() { - return flib_loglevel; -} - -void flib_log_setLevel(int level) { - flib_loglevel = level; -} - -void flib_log_setFile(FILE *file) { - flib_logfile = file; - flib_logCallback = NULL; -} - -bool flib_log_isActive(int level) { - return level >= flib_log_getLevel(); -} - -void flib_log_setCallback(void (*logCallback)(int level, const char *msg)) { - flib_logCallback = logCallback; - flib_logfile = NULL; -} +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "logging.h" + +#include +#include +#include +#include + +static int flib_loglevel = FLIB_LOGLEVEL_INFO; +static FILE *flib_logfile = NULL; +void (*flib_logCallback)(int level, const char *msg) = NULL; + +char* flib_format_ip(uint32_t numip) { + static char ip[16]; + snprintf(ip, 16, "%u.%u.%u.%u", (unsigned)(numip>>24), (unsigned)((numip>>16)&0xff), (unsigned)((numip>>8)&0xff), (unsigned)(numip&0xff)); + return ip; +} + +static inline FILE *flib_log_getfile() { + if(flib_logfile==NULL) { + return stdout; + } else { + return flib_logfile; + } +} + +static int log_time(char *buffer) { + time_t timer; + struct tm* tm_info; + + time(&timer); + tm_info = localtime(&timer); + + return strftime(buffer, 25, "%Y-%m-%d %H:%M:%S", tm_info); +} + +static char getPrefix(int level) { + switch(level) { + case FLIB_LOGLEVEL_ERROR: return 'E'; + case FLIB_LOGLEVEL_WARNING: return 'W'; + case FLIB_LOGLEVEL_INFO: return 'I'; + case FLIB_LOGLEVEL_DEBUG: return 'D'; + default: return '?'; + } +} + +static void _flib_vflog(const char *func, int level, const char *fmt, va_list args) { + if(level >= flib_loglevel) { + char logbuffer[1024]; + logbuffer[0] = getPrefix(level); + logbuffer[1] = ' '; + + int pos = 2; + + int len = log_time(logbuffer+pos); + if(len>=0) { + pos += len; + if(pos>sizeof(logbuffer)-1) pos = sizeof(logbuffer)-1; + } else { + return; + } + + len = snprintf(logbuffer+pos, sizeof(logbuffer)-pos, " [%-30s] ", func); + if(len>=0) { + pos += len; + if(pos>sizeof(logbuffer)-1) pos = sizeof(logbuffer)-1; + } else { + return; + } + + len = vsnprintf(logbuffer+pos, sizeof(logbuffer)-pos, fmt, args); + if(len>=0) { + pos += len; + if(pos>sizeof(logbuffer)-1) pos = sizeof(logbuffer)-1; + } else { + return; + } + + if(flib_logCallback != NULL) { + flib_logCallback(level, logbuffer); + } else { + FILE *logfile = flib_log_getfile(); + fputs(logbuffer, logfile); + fputc('\n', logfile); + fflush(logfile); + } + } +} + +void _flib_flog(const char *func, int level, const char *fmt, ...) { + va_list argp; + va_start(argp, fmt); + _flib_vflog(func, level, fmt, argp); + va_end(argp); +} + +bool _flib_fassert(const char *func, int level, bool cond, const char *fmt, ...) { + if(!cond) { + va_list argp; + va_start(argp, fmt); + _flib_vflog(func, level, fmt, argp); + va_end(argp); + } + return !cond; +} + +int flib_log_getLevel() { + return flib_loglevel; +} + +void flib_log_setLevel(int level) { + flib_loglevel = level; +} + +void flib_log_setFile(FILE *file) { + flib_logfile = file; + flib_logCallback = NULL; +} + +bool flib_log_isActive(int level) { + return level >= flib_log_getLevel(); +} + +void flib_log_setCallback(void (*logCallback)(int level, const char *msg)) { + flib_logCallback = logCallback; + flib_logfile = NULL; +} diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/util/logging.h --- a/project_files/frontlib/util/logging.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/util/logging.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,106 +1,106 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef LOGGING_H_ -#define LOGGING_H_ - -#include -#include -#include - -#define FLIB_LOGLEVEL_ALL -100 -#define FLIB_LOGLEVEL_DEBUG -1 -#define FLIB_LOGLEVEL_INFO 0 -#define FLIB_LOGLEVEL_WARNING 1 -#define FLIB_LOGLEVEL_ERROR 2 -#define FLIB_LOGLEVEL_NONE 100 - -/** - * Returns a pointer to a static buffer, don't free or store. - */ -char* flib_format_ip(uint32_t numip); - -/** - * Evaluates the expression cond. If it is true, a formatted error will be logged. - * Returns true if an error is logged, false otherwise (i.e. the boolean value of the argument) - * Usage: log_e_if(errorHasHappened, "Format string", formatArg, ...); - */ -#define log_e_if(cond, ...) _flib_fassert(__func__, FLIB_LOGLEVEL_ERROR, !(bool)(cond), __VA_ARGS__) -#define log_w_if(cond, ...) _flib_fassert(__func__, FLIB_LOGLEVEL_WARNING, !(bool)(cond), __VA_ARGS__) - -/** - * Helper macros for log_badargs_if - * The t parameters are the textual representation of the c parameters. They need to be passed - * explicitly, to prevent them from being expanded in prescan. - */ -#define _flib_lbi(c1,t1) log_e_if(c1, "Invalid Argument (%s)", t1) -#define _flib_lbi2(c1,t1,c2,t2) (_flib_lbi(c1,t1) || _flib_lbi(c2,t2)) -#define _flib_lbi3(c1,t1,c2,t2,c3,t3) (_flib_lbi(c1,t1) || _flib_lbi2(c2,t2,c3,t3)) -#define _flib_lbi4(c1,t1,c2,t2,c3,t3,c4,t4) (_flib_lbi(c1,t1) || _flib_lbi3(c2,t2,c3,t3,c4,t4)) -#define _flib_lbi5(c1,t1,c2,t2,c3,t3,c4,t4,c5,t5) (_flib_lbi(c1,t1) || _flib_lbi4(c2,t2,c3,t3,c4,t4,c5,t5)) -#define _flib_lbi6(c1,t1,c2,t2,c3,t3,c4,t4,c5,t5,c6,t6) (_flib_lbi(c1,t1) || _flib_lbi5(c2,t2,c3,t3,c4,t4,c5,t5,c6,t6)) - -/** - * These macros log an "Invalid Argument" error for the first of their arguments that evaluates to true. - * The text of the argument is included in the log message. - * The expression returns true if any of its arguments is true (i.e. if an argument error was logged). - * - * For example, log_badargs_if(x==NULL) will log "Invalid Argument (x==NULL)" and return true if x is NULL. - */ -#define log_badargs_if(c1) _flib_lbi(c1,#c1) -#define log_badargs_if2(c1, c2) _flib_lbi2(c1,#c1,c2,#c2) -#define log_badargs_if3(c1, c2, c3) _flib_lbi3(c1,#c1,c2,#c2,c3,#c3) -#define log_badargs_if4(c1, c2, c3, c4) _flib_lbi4(c1,#c1,c2,#c2,c3,#c3,c4,#c4) -#define log_badargs_if5(c1, c2, c3, c4, c5) _flib_lbi5(c1,#c1,c2,#c2,c3,#c3,c4,#c4,c5,#c5) -#define log_badargs_if6(c1, c2, c3, c4, c5, c6) _flib_lbi6(c1,#c1,c2,#c2,c3,#c3,c4,#c4,c5,#c5,c6,#c6) - -#define log_oom_if(cond) log_e_if(cond, "Out of Memory") - -#define flib_log_e(...) _flib_flog(__func__, FLIB_LOGLEVEL_ERROR, __VA_ARGS__) -#define flib_log_w(...) _flib_flog(__func__, FLIB_LOGLEVEL_WARNING, __VA_ARGS__) -#define flib_log_i(...) _flib_flog(__func__, FLIB_LOGLEVEL_INFO, __VA_ARGS__) -#define flib_log_d(...) _flib_flog(__func__, FLIB_LOGLEVEL_DEBUG, __VA_ARGS__) - -bool _flib_fassert(const char *func, int level, bool cond, const char *fmt, ...); -void _flib_flog(const char *func, int level, const char *fmt, ...); - -/** - * Only log messages that are at least the indicated level - */ -void flib_log_setLevel(int level); -int flib_log_getLevel(); - -/** - * Log to the indicated file. You can pass NULL to log to stdout. - * This overrides setCallback and vice versa. - */ -void flib_log_setFile(FILE *logfile); - -/** - * Returns whether messages of this level are logged at the moment. - */ -bool flib_log_isActive(int level); - -/** - * Allows logging through an arbitrary callback function. Useful for integrating into an - * existing logging system. This overrides setFile and vice versa. - */ -void flib_log_setCallback(void (*logCallback)(int level, const char *msg)); - -#endif /* LOGGING_H_ */ +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef LOGGING_H_ +#define LOGGING_H_ + +#include +#include +#include + +#define FLIB_LOGLEVEL_ALL -100 +#define FLIB_LOGLEVEL_DEBUG -1 +#define FLIB_LOGLEVEL_INFO 0 +#define FLIB_LOGLEVEL_WARNING 1 +#define FLIB_LOGLEVEL_ERROR 2 +#define FLIB_LOGLEVEL_NONE 100 + +/** + * Returns a pointer to a static buffer, don't free or store. + */ +char* flib_format_ip(uint32_t numip); + +/** + * Evaluates the expression cond. If it is true, a formatted error will be logged. + * Returns true if an error is logged, false otherwise (i.e. the boolean value of the argument) + * Usage: log_e_if(errorHasHappened, "Format string", formatArg, ...); + */ +#define log_e_if(cond, ...) _flib_fassert(__func__, FLIB_LOGLEVEL_ERROR, !(bool)(cond), __VA_ARGS__) +#define log_w_if(cond, ...) _flib_fassert(__func__, FLIB_LOGLEVEL_WARNING, !(bool)(cond), __VA_ARGS__) + +/** + * Helper macros for log_badargs_if + * The t parameters are the textual representation of the c parameters. They need to be passed + * explicitly, to prevent them from being expanded in prescan. + */ +#define _flib_lbi(c1,t1) log_e_if(c1, "Invalid Argument (%s)", t1) +#define _flib_lbi2(c1,t1,c2,t2) (_flib_lbi(c1,t1) || _flib_lbi(c2,t2)) +#define _flib_lbi3(c1,t1,c2,t2,c3,t3) (_flib_lbi(c1,t1) || _flib_lbi2(c2,t2,c3,t3)) +#define _flib_lbi4(c1,t1,c2,t2,c3,t3,c4,t4) (_flib_lbi(c1,t1) || _flib_lbi3(c2,t2,c3,t3,c4,t4)) +#define _flib_lbi5(c1,t1,c2,t2,c3,t3,c4,t4,c5,t5) (_flib_lbi(c1,t1) || _flib_lbi4(c2,t2,c3,t3,c4,t4,c5,t5)) +#define _flib_lbi6(c1,t1,c2,t2,c3,t3,c4,t4,c5,t5,c6,t6) (_flib_lbi(c1,t1) || _flib_lbi5(c2,t2,c3,t3,c4,t4,c5,t5,c6,t6)) + +/** + * These macros log an "Invalid Argument" error for the first of their arguments that evaluates to true. + * The text of the argument is included in the log message. + * The expression returns true if any of its arguments is true (i.e. if an argument error was logged). + * + * For example, log_badargs_if(x==NULL) will log "Invalid Argument (x==NULL)" and return true if x is NULL. + */ +#define log_badargs_if(c1) _flib_lbi(c1,#c1) +#define log_badargs_if2(c1, c2) _flib_lbi2(c1,#c1,c2,#c2) +#define log_badargs_if3(c1, c2, c3) _flib_lbi3(c1,#c1,c2,#c2,c3,#c3) +#define log_badargs_if4(c1, c2, c3, c4) _flib_lbi4(c1,#c1,c2,#c2,c3,#c3,c4,#c4) +#define log_badargs_if5(c1, c2, c3, c4, c5) _flib_lbi5(c1,#c1,c2,#c2,c3,#c3,c4,#c4,c5,#c5) +#define log_badargs_if6(c1, c2, c3, c4, c5, c6) _flib_lbi6(c1,#c1,c2,#c2,c3,#c3,c4,#c4,c5,#c5,c6,#c6) + +#define log_oom_if(cond) log_e_if(cond, "Out of Memory") + +#define flib_log_e(...) _flib_flog(__func__, FLIB_LOGLEVEL_ERROR, __VA_ARGS__) +#define flib_log_w(...) _flib_flog(__func__, FLIB_LOGLEVEL_WARNING, __VA_ARGS__) +#define flib_log_i(...) _flib_flog(__func__, FLIB_LOGLEVEL_INFO, __VA_ARGS__) +#define flib_log_d(...) _flib_flog(__func__, FLIB_LOGLEVEL_DEBUG, __VA_ARGS__) + +bool _flib_fassert(const char *func, int level, bool cond, const char *fmt, ...); +void _flib_flog(const char *func, int level, const char *fmt, ...); + +/** + * Only log messages that are at least the indicated level + */ +void flib_log_setLevel(int level); +int flib_log_getLevel(); + +/** + * Log to the indicated file. You can pass NULL to log to stdout. + * This overrides setCallback and vice versa. + */ +void flib_log_setFile(FILE *logfile); + +/** + * Returns whether messages of this level are logged at the moment. + */ +bool flib_log_isActive(int level); + +/** + * Allows logging through an arbitrary callback function. Useful for integrating into an + * existing logging system. This overrides setFile and vice versa. + */ +void flib_log_setCallback(void (*logCallback)(int level, const char *msg)); + +#endif /* LOGGING_H_ */ diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/util/util.c --- a/project_files/frontlib/util/util.c Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/util/util.c Tue Nov 10 20:43:13 2015 +0100 @@ -1,212 +1,212 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "util.h" -#include "logging.h" - -#include -#include -#include -#include -#include -#include -#include - -char *flib_asprintf(const char *fmt, ...) { - va_list argp; - va_start(argp, fmt); - char *result = flib_vasprintf(fmt, argp); - va_end(argp); - return result; -} - -char *flib_vasprintf(const char *fmt, va_list args) { - char *result = NULL; - if(!log_badargs_if(fmt==NULL)) { - int requiredSize = vsnprintf(NULL, 0, fmt, args)+1; // Figure out how much memory we need, - if(!log_e_if(requiredSize<0, "Error formatting string with template \"%s\"", fmt)) { - char *tmpbuf = flib_malloc(requiredSize); // allocate it - if(tmpbuf && vsnprintf(tmpbuf, requiredSize, fmt, args)>=0) { // and then do the actual formatting. - result = tmpbuf; - tmpbuf = NULL; - } - free(tmpbuf); - } - } - return result; -} - -char *flib_join(char **parts, int partCount, const char *delimiter) { - char *result = NULL; - if(!log_badargs_if2(parts==NULL, delimiter==NULL)) { - size_t totalSize = 1; - size_t delimLen = strlen(delimiter); - for(int i=0; i0) { - strcpy(result+outpos, delimiter); - outpos += delimLen; - } - strcpy(result+outpos, parts[i]); - outpos += strlen(parts[i]); - } - } - } - return result; -} - -char *flib_strdupnull(const char *str) { - return str==NULL ? NULL : flib_asprintf("%s", str); -} - -void *flib_bufdupnull(const void *buf, size_t size) { - void *result = NULL; - if(!log_badargs_if(buf==NULL && size>0)) { - result = flib_malloc(size); - if(result) { - memcpy(result, buf, size); - } - } - return result; -} - -void *flib_malloc(size_t size) { - void *result = malloc(size); - if(!result && size>0) { - flib_log_e("Out of memory trying to malloc %zu bytes.", size); - } - return result; -} - -void *flib_calloc(size_t count, size_t elementsize) { - void *result = calloc(count, elementsize); - if(!result && count>0 && elementsize>0) { - flib_log_e("Out of memory trying to calloc %zu objects of %zu bytes each.", count, elementsize); - } - return result; -} - -void *flib_realloc(void *ptr, size_t size) { - void *result = realloc(ptr, size); - if(!result && size>0) { - flib_log_e("Out of memory trying to realloc %zu bytes.", size); - } - return result; -} - -static bool isAsciiAlnum(char c) { - return (c>='0' && c<='9') || (c>='a' && c <='z') || (c>='A' && c <='Z'); -} - -char *flib_urlencode(const char *inbuf) { - return flib_urlencode_pred(inbuf, isAsciiAlnum); -} - -static size_t countCharsToEscape(const char *inbuf, bool (*needsEscaping)(char c)) { - size_t result = 0; - for(const char *c=inbuf; *c; c++) { - if(needsEscaping(*c)) { - result++; - } - } - return result; -} - -char *flib_urlencode_pred(const char *inbuf, bool (*needsEscaping)(char c)) { - char *result = NULL; - if(inbuf && !log_badargs_if(needsEscaping == NULL)) { - size_t insize = strlen(inbuf); - if(!log_e_if(insize > SIZE_MAX/4, "String too long: %zu bytes.", insize)) { - size_t escapeCount = countCharsToEscape(inbuf, needsEscaping); - result = flib_malloc(insize + escapeCount*2 + 1); - } - if(result) { - char *out = result; - for(const char *in = inbuf; *in; in++) { - if(!needsEscaping(*in)) { - *out = *in; - out++; - } else { - snprintf(out, 4, "%%%02x", (unsigned)(*(uint8_t*)in)); - out += 3; - } - } - *out = 0; - } - } - return result; -} - -char *flib_urldecode(const char *inbuf) { - if(!inbuf) { - return NULL; - } - char *outbuf = flib_malloc(strlen(inbuf)+1); - if(!outbuf) { - return NULL; - } - - size_t inpos = 0, outpos = 0; - while(inbuf[inpos]) { - if(inbuf[inpos] == '%' && isxdigit(inbuf[inpos+1]) && isxdigit(inbuf[inpos+2])) { - char temp[3] = {inbuf[inpos+1],inbuf[inpos+2],0}; - outbuf[outpos++] = strtol(temp, NULL, 16); - inpos += 3; - } else { - outbuf[outpos++] = inbuf[inpos++]; - } - } - outbuf[outpos] = 0; - char *shrunk = realloc(outbuf, outpos+1); - return shrunk ? shrunk : outbuf; -} - -bool flib_contains_dir_separator(const char *str) { - if(!log_badargs_if(!str)) { - for(;*str;str++) { - if(*str=='\\' || *str=='/') { - return true; - } - } - } - return false; -} - -bool flib_strempty(const char *str) { - return !str || !*str; -} - -int flib_gets(char *str, size_t strlen) { - if(fgets(str, strlen, stdin)) { - for(char *s=str; *s; s++) { - if(*s=='\r' || *s=='\n') { - *s = 0; - break; - } - } - return 0; - } - return -1; -} +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "util.h" +#include "logging.h" + +#include +#include +#include +#include +#include +#include +#include + +char *flib_asprintf(const char *fmt, ...) { + va_list argp; + va_start(argp, fmt); + char *result = flib_vasprintf(fmt, argp); + va_end(argp); + return result; +} + +char *flib_vasprintf(const char *fmt, va_list args) { + char *result = NULL; + if(!log_badargs_if(fmt==NULL)) { + int requiredSize = vsnprintf(NULL, 0, fmt, args)+1; // Figure out how much memory we need, + if(!log_e_if(requiredSize<0, "Error formatting string with template \"%s\"", fmt)) { + char *tmpbuf = flib_malloc(requiredSize); // allocate it + if(tmpbuf && vsnprintf(tmpbuf, requiredSize, fmt, args)>=0) { // and then do the actual formatting. + result = tmpbuf; + tmpbuf = NULL; + } + free(tmpbuf); + } + } + return result; +} + +char *flib_join(char **parts, int partCount, const char *delimiter) { + char *result = NULL; + if(!log_badargs_if2(parts==NULL, delimiter==NULL)) { + size_t totalSize = 1; + size_t delimLen = strlen(delimiter); + for(int i=0; i0) { + strcpy(result+outpos, delimiter); + outpos += delimLen; + } + strcpy(result+outpos, parts[i]); + outpos += strlen(parts[i]); + } + } + } + return result; +} + +char *flib_strdupnull(const char *str) { + return str==NULL ? NULL : flib_asprintf("%s", str); +} + +void *flib_bufdupnull(const void *buf, size_t size) { + void *result = NULL; + if(!log_badargs_if(buf==NULL && size>0)) { + result = flib_malloc(size); + if(result) { + memcpy(result, buf, size); + } + } + return result; +} + +void *flib_malloc(size_t size) { + void *result = malloc(size); + if(!result && size>0) { + flib_log_e("Out of memory trying to malloc %zu bytes.", size); + } + return result; +} + +void *flib_calloc(size_t count, size_t elementsize) { + void *result = calloc(count, elementsize); + if(!result && count>0 && elementsize>0) { + flib_log_e("Out of memory trying to calloc %zu objects of %zu bytes each.", count, elementsize); + } + return result; +} + +void *flib_realloc(void *ptr, size_t size) { + void *result = realloc(ptr, size); + if(!result && size>0) { + flib_log_e("Out of memory trying to realloc %zu bytes.", size); + } + return result; +} + +static bool isAsciiAlnum(char c) { + return (c>='0' && c<='9') || (c>='a' && c <='z') || (c>='A' && c <='Z'); +} + +char *flib_urlencode(const char *inbuf) { + return flib_urlencode_pred(inbuf, isAsciiAlnum); +} + +static size_t countCharsToEscape(const char *inbuf, bool (*needsEscaping)(char c)) { + size_t result = 0; + for(const char *c=inbuf; *c; c++) { + if(needsEscaping(*c)) { + result++; + } + } + return result; +} + +char *flib_urlencode_pred(const char *inbuf, bool (*needsEscaping)(char c)) { + char *result = NULL; + if(inbuf && !log_badargs_if(needsEscaping == NULL)) { + size_t insize = strlen(inbuf); + if(!log_e_if(insize > SIZE_MAX/4, "String too long: %zu bytes.", insize)) { + size_t escapeCount = countCharsToEscape(inbuf, needsEscaping); + result = flib_malloc(insize + escapeCount*2 + 1); + } + if(result) { + char *out = result; + for(const char *in = inbuf; *in; in++) { + if(!needsEscaping(*in)) { + *out = *in; + out++; + } else { + snprintf(out, 4, "%%%02x", (unsigned)(*(uint8_t*)in)); + out += 3; + } + } + *out = 0; + } + } + return result; +} + +char *flib_urldecode(const char *inbuf) { + if(!inbuf) { + return NULL; + } + char *outbuf = flib_malloc(strlen(inbuf)+1); + if(!outbuf) { + return NULL; + } + + size_t inpos = 0, outpos = 0; + while(inbuf[inpos]) { + if(inbuf[inpos] == '%' && isxdigit(inbuf[inpos+1]) && isxdigit(inbuf[inpos+2])) { + char temp[3] = {inbuf[inpos+1],inbuf[inpos+2],0}; + outbuf[outpos++] = strtol(temp, NULL, 16); + inpos += 3; + } else { + outbuf[outpos++] = inbuf[inpos++]; + } + } + outbuf[outpos] = 0; + char *shrunk = realloc(outbuf, outpos+1); + return shrunk ? shrunk : outbuf; +} + +bool flib_contains_dir_separator(const char *str) { + if(!log_badargs_if(!str)) { + for(;*str;str++) { + if(*str=='\\' || *str=='/') { + return true; + } + } + } + return false; +} + +bool flib_strempty(const char *str) { + return !str || !*str; +} + +int flib_gets(char *str, size_t strlen) { + if(fgets(str, strlen, stdin)) { + for(char *s=str; *s; s++) { + if(*s=='\r' || *s=='\n') { + *s = 0; + break; + } + } + return 0; + } + return -1; +} diff -r 31570b766315 -r ed5a6478e710 project_files/frontlib/util/util.h --- a/project_files/frontlib/util/util.h Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/frontlib/util/util.h Tue Nov 10 20:43:13 2015 +0100 @@ -1,122 +1,122 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef FLIB_UTIL_H_ -#define FLIB_UTIL_H_ - -#include -#include -#include - -/** - * Prints a format string to a newly allocated buffer of the required size. - * Parameters are like those for printf. Returns NULL on error. - * - * Returned buffer must be free()d - */ -char *flib_asprintf(const char *fmt, ...); - -/** - * Exactly as flib_asprintf, but accepts a va_list. - */ -char *flib_vasprintf(const char *fmt, va_list args); - -/** - * Creates a new string (that must be freed) containing all parts - * joined together, with the specified delimiter between each. - */ -char *flib_join(char **parts, int partCount, const char *delimiter); - -/** - * Return a duplicate of the provided string, or NULL if an error - * occurs or if str is already NULL. - * - * Returned buffer must be free()d - */ -char *flib_strdupnull(const char *str); - -/** - * Return a duplicate of the provided buffer, or NULL if an error - * occurs or if buf is already NULL or if size is 0. - * - * Returned buffer must be free()d - */ -void *flib_bufdupnull(const void *buf, size_t size); - -/** - * Simple malloc wrapper that automatically logs an error if no memory - * is available. Otherwise behaves exactly like malloc. - */ -void *flib_malloc(size_t size); - -/** - * Simple calloc wrapper that automatically logs an error if no memory - * is available. Otherwise behaves exactly like calloc. - */ -void *flib_calloc(size_t count, size_t elementsize); - -/** - * Simple realloc wrapper that automatically logs an error if no memory - * is available. Otherwise behaves exactly like realloc. - */ -void *flib_realloc(void *ptr, size_t size); - -/** - * Replace all non-alphanumeric and non-ascii bytes with escape - * sequences in the form %XX. Does not modify the original string, - * but returns a newly allocated one that must be free()d. Returns - * null on failure or if null was passed as argument. - * - * This should work fine with all ASCII-based charsets including UTF-8. - */ -char *flib_urlencode(const char *str); - -/** - * Replace some bytes with escape sequences in the form %XX. - * Does not modify the original string, but returns a newly allocated - * one that must be free()d. - * - * All bytes for which the predicate function returns true are escaped. - * - * Returns null on failure or if null was passed as argument. - */ -char *flib_urlencode_pred(const char *str, bool (*needsEscaping)(char c)); - -/** - * Replace escape sequences of the form %XX with their byte values. - * Does not modify the original string, but returns a newly allocated - * one that must be free()d. Returns null on failure or if null was - * passed as argument. - */ -char *flib_urldecode(const char *str); - -/** - * Figure out if the string contains / or \. Useful in routines that - * construct filenames. - */ -bool flib_contains_dir_separator(const char *str); - -/** - * Returns true if str is either NULL or points to a 0-length string - */ -bool flib_strempty(const char *str); - -int flib_gets(char *str, size_t strlen); - -#endif +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef FLIB_UTIL_H_ +#define FLIB_UTIL_H_ + +#include +#include +#include + +/** + * Prints a format string to a newly allocated buffer of the required size. + * Parameters are like those for printf. Returns NULL on error. + * + * Returned buffer must be free()d + */ +char *flib_asprintf(const char *fmt, ...); + +/** + * Exactly as flib_asprintf, but accepts a va_list. + */ +char *flib_vasprintf(const char *fmt, va_list args); + +/** + * Creates a new string (that must be freed) containing all parts + * joined together, with the specified delimiter between each. + */ +char *flib_join(char **parts, int partCount, const char *delimiter); + +/** + * Return a duplicate of the provided string, or NULL if an error + * occurs or if str is already NULL. + * + * Returned buffer must be free()d + */ +char *flib_strdupnull(const char *str); + +/** + * Return a duplicate of the provided buffer, or NULL if an error + * occurs or if buf is already NULL or if size is 0. + * + * Returned buffer must be free()d + */ +void *flib_bufdupnull(const void *buf, size_t size); + +/** + * Simple malloc wrapper that automatically logs an error if no memory + * is available. Otherwise behaves exactly like malloc. + */ +void *flib_malloc(size_t size); + +/** + * Simple calloc wrapper that automatically logs an error if no memory + * is available. Otherwise behaves exactly like calloc. + */ +void *flib_calloc(size_t count, size_t elementsize); + +/** + * Simple realloc wrapper that automatically logs an error if no memory + * is available. Otherwise behaves exactly like realloc. + */ +void *flib_realloc(void *ptr, size_t size); + +/** + * Replace all non-alphanumeric and non-ascii bytes with escape + * sequences in the form %XX. Does not modify the original string, + * but returns a newly allocated one that must be free()d. Returns + * null on failure or if null was passed as argument. + * + * This should work fine with all ASCII-based charsets including UTF-8. + */ +char *flib_urlencode(const char *str); + +/** + * Replace some bytes with escape sequences in the form %XX. + * Does not modify the original string, but returns a newly allocated + * one that must be free()d. + * + * All bytes for which the predicate function returns true are escaped. + * + * Returns null on failure or if null was passed as argument. + */ +char *flib_urlencode_pred(const char *str, bool (*needsEscaping)(char c)); + +/** + * Replace escape sequences of the form %XX with their byte values. + * Does not modify the original string, but returns a newly allocated + * one that must be free()d. Returns null on failure or if null was + * passed as argument. + */ +char *flib_urldecode(const char *str); + +/** + * Figure out if the string contains / or \. Useful in routines that + * construct filenames. + */ +bool flib_contains_dir_separator(const char *str); + +/** + * Returns true if str is either NULL or points to a 0-length string + */ +bool flib_strempty(const char *str); + +int flib_gets(char *str, size_t strlen); + +#endif diff -r 31570b766315 -r ed5a6478e710 project_files/hedgewars.pro --- a/project_files/hedgewars.pro Tue Nov 10 18:16:35 2015 +0100 +++ b/project_files/hedgewars.pro Tue Nov 10 20:43:13 2015 +0100 @@ -12,6 +12,7 @@ INCLUDEPATH += ../QTfrontend/util/platform INCLUDEPATH += ../misc/libphysfs INCLUDEPATH += ../misc/libphyslayer +INCLUDEPATH += /usr/local/include/lua52/ DESTDIR = ../bin @@ -115,7 +116,8 @@ ../QTfrontend/ui/widget/lineeditcursor.h \ ../QTfrontend/servermessages.h \ ../QTfrontend/ui/widget/roomnameprompt.h \ - ../QTfrontend/weapons.h + ../QTfrontend/weapons.h \ + ../QTfrontend/net/hwmapoptimizer.h SOURCES += ../QTfrontend/model/ammoSchemeModel.cpp \ @@ -213,28 +215,29 @@ ../QTfrontend/util/MessageDialog.cpp \ ../QTfrontend/ui/widget/feedbackdialog.cpp \ ../QTfrontend/ui/widget/lineeditcursor.cpp \ - ../QTfrontend/ui/widget/roomnameprompt.cpp + ../QTfrontend/ui/widget/roomnameprompt.cpp \ + ../QTfrontend/net/hwmapoptimizer.cpp TRANSLATIONS += ../share/hedgewars/Data/Locale/hedgewars_ar.ts \ ../share/hedgewars/Data/Locale/hedgewars_bg.ts \ ../share/hedgewars/Data/Locale/hedgewars_cs.ts \ ../share/hedgewars/Data/Locale/hedgewars_da.ts \ - ../share/hedgewars/Data/Locale/hedgewars_de.ts \ + ../share/hedgewars/Data/Locale/hedgewars_de.ts \ ../share/hedgewars/Data/Locale/hedgewars_el.ts \ - ../share/hedgewars/Data/Locale/hedgewars_en.ts \ + ../share/hedgewars/Data/Locale/hedgewars_en.ts \ ../share/hedgewars/Data/Locale/hedgewars_es.ts \ ../share/hedgewars/Data/Locale/hedgewars_fi.ts \ - ../share/hedgewars/Data/Locale/hedgewars_fr.ts \ + ../share/hedgewars/Data/Locale/hedgewars_fr.ts \ ../share/hedgewars/Data/Locale/hedgewars_gl.ts \ - ../share/hedgewars/Data/Locale/hedgewars_hu.ts \ - ../share/hedgewars/Data/Locale/hedgewars_it.ts \ - ../share/hedgewars/Data/Locale/hedgewars_ja.ts \ - ../share/hedgewars/Data/Locale/hedgewars_ko.ts \ + ../share/hedgewars/Data/Locale/hedgewars_hu.ts \ + ../share/hedgewars/Data/Locale/hedgewars_it.ts \ + ../share/hedgewars/Data/Locale/hedgewars_ja.ts \ + ../share/hedgewars/Data/Locale/hedgewars_ko.ts \ ../share/hedgewars/Data/Locale/hedgewars_lt.ts \ ../share/hedgewars/Data/Locale/hedgewars_ms.ts \ - ../share/hedgewars/Data/Locale/hedgewars_nl.ts \ - ../share/hedgewars/Data/Locale/hedgewars_pl.ts \ + ../share/hedgewars/Data/Locale/hedgewars_nl.ts \ + ../share/hedgewars/Data/Locale/hedgewars_pl.ts \ ../share/hedgewars/Data/Locale/hedgewars_pt_BR.ts \ ../share/hedgewars/Data/Locale/hedgewars_pt_PT.ts \ ../share/hedgewars/Data/Locale/hedgewars_ro.ts \ @@ -248,7 +251,7 @@ RESOURCES += ../QTfrontend/hedgewars.qrc -LIBS += -L../bin -lhwphysfs -lphyslayer +LIBS += -L../bin -lphysfs -lphyslayer macx { QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.6 diff -r 31570b766315 -r ed5a6478e710 project_files/hwc/CMakeLists.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/hwc/CMakeLists.txt Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,102 @@ +#the usual set of dependencies +find_package(OpenGL REQUIRED) +find_package(GLEW REQUIRED) +find_package(SDL REQUIRED) +find_package(SDL_mixer REQUIRED) +find_package(SDL_net REQUIRED) +find_package(SDL_image REQUIRED) +find_package(SDL_ttf REQUIRED) + +#compile our rtl implementation +include_directories(${GLEW_INCLUDE_DIR}) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/rtl) +include_directories(${PHYSFS_INCLUDE_DIR}) +include_directories(${PHYSLAYER_INCLUDE_DIR}) +include_directories(${LUA_INCLUDE_DIR}) +include_directories(${SDL_INCLUDE_DIR}) +add_subdirectory(rtl) + +# convert list into pascal array +if(FONTS_DIRS) + list(LENGTH FONTS_DIRS ndirs) + set(FONTS_DIRS_ARRAY "array [0..${ndirs}] of PChar = (") + foreach(fontdir ${FONTS_DIRS}) + set(FONTS_DIRS_ARRAY "${FONTS_DIRS_ARRAY}\n_P'${fontdir}',") + endforeach(fontdir) + set(FONTS_DIRS_ARRAY "${FONTS_DIRS_ARRAY}\nnil);\n") +else(FONTS_DIRS) + set(FONTS_DIRS_ARRAY "array [0..1] of PChar = (nil, nil);") +endif(FONTS_DIRS) + +configure_file(${CMAKE_SOURCE_DIR}/hedgewars/config.inc.in ${CMAKE_CURRENT_BINARY_DIR}/config.inc) + +#get the list of pas files that are going to be converted and compiled +file(GLOB engine_sources_pas "${CMAKE_SOURCE_DIR}/hedgewars/*.pas") +#TODO: temporary until cmake can configure itself accordingly +list(REMOVE_ITEM engine_sources_pas "${CMAKE_SOURCE_DIR}/hedgewars/uWeb.pas") +list(REMOVE_ITEM engine_sources_pas "${CMAKE_SOURCE_DIR}/hedgewars/uVideoRec.pas") +list(REMOVE_ITEM engine_sources_pas "${CMAKE_SOURCE_DIR}/hedgewars/uTouch.pas") +list(REMOVE_ITEM engine_sources_pas "${CMAKE_SOURCE_DIR}/hedgewars/PNGh.pas") +list(REMOVE_ITEM engine_sources_pas "${CMAKE_SOURCE_DIR}/hedgewars/pas2cSystem.pas") +list(REMOVE_ITEM engine_sources_pas "${CMAKE_SOURCE_DIR}/hedgewars/pas2cRedo.pas") +list(REMOVE_ITEM engine_sources_pas "${CMAKE_SOURCE_DIR}/hedgewars/hwLibrary.pas") +list(REMOVE_ITEM engine_sources_pas "${CMAKE_SOURCE_DIR}/hedgewars/uMatrix.pas") + +#remove and readd hwengine so that it is compiled first, compiling every other file in the process +list(REMOVE_ITEM engine_sources_pas ${CMAKE_SOURCE_DIR}/hedgewars/hwengine.pas) +list(APPEND engine_sources_pas ${CMAKE_SOURCE_DIR}/hedgewars/hwengine.pas) + +#process files .pas -> .c +foreach(sourcefile ${engine_sources_pas}) + get_filename_component(sourcename ${sourcefile} NAME_WE) #drops .pas + list(APPEND engine_sources "${CMAKE_CURRENT_BINARY_DIR}/${sourcename}.c") +endforeach() + +#add again files for external functions and for fpcrtl_ functions +list(APPEND engine_sources_pas ${CMAKE_SOURCE_DIR}/hedgewars/pas2cSystem.pas) +list(APPEND engine_sources_pas ${CMAKE_SOURCE_DIR}/hedgewars/pas2cRedo.pas) + + +#invoke pas2c on main module, it will call all the others +add_custom_command(OUTPUT ${engine_sources} + COMMAND "${EXECUTABLE_OUTPUT_PATH}/pas2c${CMAKE_EXECUTABLE_SUFFIX}" + ARGS -n "hwengine" + -i "${CMAKE_SOURCE_DIR}/hedgewars" + -o "${CMAKE_CURRENT_BINARY_DIR}" + -a "${CMAKE_CURRENT_BINARY_DIR}" + -d "ENDIAN_LITTLE" + -d "DEBUGFILE" + DEPENDS pas2c #converter tool + ${engine_sources_pas} #original pascal file + ) + +#wrap conversion for all source in this command +add_custom_target(engine_c DEPENDS ${engine_sources}) + + +#compile the c files +add_definitions(-DPAS2C) +add_definitions(-Werror=incompatible-pointer-types) + +add_executable(hwengine WIN32 ${engine_sources}) + +target_link_libraries(hwengine fpcrtl + ${LUA_LIBRARY} + ${OPENGL_LIBRARY} + ${SDL_LIBRARY} + ${SDLMIXER_LIBRARY} + ${SDLNET_LIBRARY} + ${SDLIMAGE_LIBRARY} + ${SDLTTF_LIBRARY} + ${GLEW_LIBRARY} + physfs + physlayer + m + #TODO: add other libraries + ) +if(APPLE) + target_link_libraries(hwengine IOKit SDLmain) +endif() + +install(PROGRAMS "${EXECUTABLE_OUTPUT_PATH}/hwengine${CMAKE_EXECUTABLE_SUFFIX}" DESTINATION ${target_binary_install_dir}) + diff -r 31570b766315 -r ed5a6478e710 project_files/hwc/rtl/CMakeLists.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/hwc/rtl/CMakeLists.txt Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,16 @@ + +include_directories(${GLEW_INCLUDE_DIR}) + +file(GLOB fpcrtl_src *.c) + +add_library(fpcrtl STATIC ${fpcrtl_src}) + +#if(WEBGL) +# set_target_properties(fpcrtl PROPERTIES PREFIX "em") +# set_target_properties(fpcrtl PROPERTIES SUFFIX ".bc") +#endif(WEBGL) + + + + + diff -r 31570b766315 -r ed5a6478e710 project_files/hwc/rtl/GL.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/hwc/rtl/GL.h Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,8 @@ +#pragma once + +#ifdef __APPLE__ +#include +#else +#include "GL/gl.h" +#endif + diff -r 31570b766315 -r ed5a6478e710 project_files/hwc/rtl/Math.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/hwc/rtl/Math.h Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,4 @@ +#pragma once + +#include + diff -r 31570b766315 -r ed5a6478e710 project_files/hwc/rtl/SysUtils.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/hwc/rtl/SysUtils.h Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,44 @@ +#ifndef _FPCRTL_SYSUTILS_H_ +#define _FPCRTL_SYSUTILS_H_ + +#include "Types.h" + +// EFFECTS: return the current date time in pascal notation +// http://www.merlyn.demon.co.uk/del-prgg.htm#TDT +TDateTime fpcrtl_now(); +#define now fpcrtl_now +#define Now fpcrtl_now + +// EFFECTS: return the current time +// http://www.merlyn.demon.co.uk/del-prgg.htm#TDT +TDateTime fpcrtl_time(); + + +// EFFECTS: return the current date +// http://www.merlyn.demon.co.uk/del-prgg.htm#TDT +TDateTime fpcrtl_date(); +#define date fpcrtl_date +#define Date fpcrtl_date + +// EFFECTS: Trim strips blank characters (spaces) at the beginning and end of S +// and returns the resulting string. Only #32 characters are stripped. +// If the string contains only spaces, an empty string is returned. +string255 fpcrtl_trim(string255 s); +#define trim fpcrtl_trim +#define Trim fpcrtl_trim + +Integer fpcrtl_strToInt(string255 s); +#define StrToInt fpcrtl_strToInt +#define strToInt fpcrtl_strToInt + +string255 fpcrtl_extractFileDir(string255 f); +#define fpcrtl_ExtractFileDir fpcrtl_extractFileDir + +string255 fpcrtl_extractFileName(string255 f); +#define fpcrtl_ExtractFileName fpcrtl_extractFileName + +string255 fpcrtl_strPas(PChar); +#define fpcrtl_StrPas fpcrtl_strPas + + +#endif diff -r 31570b766315 -r ed5a6478e710 project_files/hwc/rtl/Types.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/hwc/rtl/Types.h Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,39 @@ +#ifndef _TYPES_H_ +#define _TYPES_H_ + +#include "pas2c.h" + +/* + * Not very useful currently + */ + +typedef double TDate; +typedef double TTime; +typedef double TDateTime; +typedef string255 TMonthNameArray[13]; +typedef string255 TWeekNameArray[8]; + +typedef struct { + Byte CurrencyFormat; + Byte NegCurrFormat; + Char ThousandSeparator; + Char DecimalSeparator; + Byte CurrencyDecimals; + Char DateSeparator; + Char TimeSeparator; + Char ListSeparator; + string255 CurrencyString; + string255 ShortDateFormat; + string255 LongDateFormat; + string255 TimeAMString; + string255 TimePMString; + string255 ShortTimeFormat; + string255 LongTimeFormat; + TMonthNameArray ShortMonthNames; + TMonthNameArray LongMonthNames; + TWeekNameArray ShortDayNames; + TWeekNameArray LongDayNames; + Word TwoDigitYearCenturyWindow; +}TFormatSettings; + +#endif diff -r 31570b766315 -r ed5a6478e710 project_files/hwc/rtl/fileio.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/hwc/rtl/fileio.c Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,229 @@ +/* + * XXX: assume all files are text files + */ + +#include "misc.h" +#include "fileio.h" +#include +#include +#include +#include + +io_result_t IOResult; +int FileMode; + +static void init(File f) { + f->fp = NULL; + f->eof = 0; + f->mode = NULL; + f->record_len = 0; +} + +void fpcrtl_assign__vars(File *f, string255 name) { + FIX_STRING(name); + *f = (File) malloc(sizeof(file_wrapper_t)); + strcpy((*f)->file_name, name.str); + init(*f); +} + +void fpcrtl_reset1(File f) { + f->fp = fopen(f->file_name, "r"); + if (!f->fp) { + IOResult = IO_ERROR_DUMMY; + printf("Failed to open %s\n", f->file_name); + return; + } else { +#ifdef FPCRTL_DEBUG + printf("Opened %s\n", f->file_name); +#endif + } + IOResult = IO_NO_ERROR; + f->mode = "r"; +} + +void fpcrtl_reset2(File f, int l) { + f->eof = 0; + f->fp = fopen(f->file_name, "rb"); + if (!f->fp) { + IOResult = IO_ERROR_DUMMY; + printf("Failed to open %s\n", f->file_name); + return; + } + IOResult = IO_NO_ERROR; + f->mode = "rb"; + f->record_len = l; +} + +void __attribute__((overloadable)) fpcrtl_rewrite(File f) { + f->fp = fopen(f->file_name, "w+"); + if (!f->fp) { + IOResult = IO_ERROR_DUMMY; + return; + } + IOResult = IO_NO_ERROR; + f->mode = "w+"; +} + +void __attribute__((overloadable)) fpcrtl_rewrite(File f, Integer l) { + IOResult = IO_NO_ERROR; + fpcrtl_rewrite(f); + if (f->fp) { + f->record_len = l; + } +} + +void fpcrtl_close(File f) { + IOResult = IO_NO_ERROR; + fclose(f->fp); + free(f); +} + +boolean fpcrtl_eof(File f) { + IOResult = IO_NO_ERROR; + if (f->eof || f->fp == NULL || feof(f->fp)) { + return true; + } else { + return false; + } +} + +void __attribute__((overloadable)) fpcrtl_readLn(File f) { + IOResult = IO_NO_ERROR; + char line[256]; + if (fgets(line, sizeof(line), f->fp) == NULL) { + f->eof = 1; + } + if (feof(f->fp)) { + f->eof = 1; + } +} + +void __attribute__((overloadable)) fpcrtl_readLn__vars(File f, Integer *i) { + string255 s; + + if (feof(f->fp)) { + f->eof = 1; + return; + } + + fpcrtl_readLn__vars(f, &s); + + *i = atoi(s.str); +} + +void __attribute__((overloadable)) fpcrtl_readLn__vars(File f, LongWord *i) { + string255 s; + + if (feof(f->fp)) { + f->eof = 1; + return; + } + + fpcrtl_readLn__vars(f, &s); + + *i = atoi(s.str); +} + +void __attribute__((overloadable)) fpcrtl_readLn__vars(File f, string255 *s) { + + if (fgets(s->str, 255, f->fp) == NULL) { + + s->len = 0; + s->str[0] = 0; + + f->eof = 1; + return; + } + + if (feof(f->fp)) { + s->len = 0; + f->eof = 1; + return; + } + + IOResult = IO_NO_ERROR; + + s->len = strlen(s->str); + if ((s->len > 0) && (s->str[s->len - 1] == '\n')) { + s->str[s->len - 1] = 0; + s->len--; + } +} + +void __attribute__((overloadable)) fpcrtl_write(File f, string255 s) { + FIX_STRING(s); + fprintf(f->fp, "%s", s.str); +} + +void __attribute__((overloadable)) fpcrtl_write(FILE *f, string255 s) { + FIX_STRING(s); + fprintf(f, "%s", s.str); +} + +void __attribute__((overloadable)) fpcrtl_writeLn(File f, string255 s) { + FIX_STRING(s); + // filthy hack to write to stderr + if (!f->fp) + fprintf(stderr, "%s\n", s.str); + else + fprintf(f->fp, "%s\n", s.str); +} + +void __attribute__((overloadable)) fpcrtl_writeLn(FILE *f, string255 s) { + FIX_STRING(s); + fprintf(f, "%s\n", s.str); +} + +void fpcrtl_blockRead__vars(File f, void *buf, Integer count, Integer *result) { + assert(f->record_len > 0); + *result = fread(buf, f->record_len, count, f->fp); +} + +/* + * XXX: dummy blockWrite + */ +void fpcrtl_blockWrite__vars(File f, const void *buf, Integer count, + Integer *result) { + assert(0); +} + +bool fpcrtl_directoryExists(string255 dir) { + + struct stat st; + FIX_STRING(dir); + + IOResult = IO_NO_ERROR; + +#ifdef FPCRTL_DEBUG + printf("Warning: directoryExists is called. This may not work when compiled to js.\n"); +#endif + + if (stat(dir.str, &st) == 0) { + return true; + } + + return false; +} + +bool fpcrtl_fileExists(string255 filename) { + + FIX_STRING(filename); + + IOResult = IO_NO_ERROR; + + FILE *fp = fopen(filename.str, "r"); + if (fp) { + fclose(fp); + return true; + } + return false; +} + +void __attribute__((overloadable)) fpcrtl_flush(Text f) { + fflush(f->fp); +} + +void __attribute__((overloadable)) fpcrtl_flush(FILE *f) { + fflush(f); +} + diff -r 31570b766315 -r ed5a6478e710 project_files/hwc/rtl/fileio.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/hwc/rtl/fileio.h Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,78 @@ +#ifndef FILEIO_H_ +#define FILEIO_H_ + +#include +#include "Types.h" +#include "misc.h" + +extern int FileMode; + +typedef enum{ + IO_NO_ERROR = 0, + IO_ERROR_DUMMY = 1 +}io_result_t; + +extern io_result_t IOResult; + +typedef struct{ + FILE *fp; + const char* mode; + char file_name[256]; + int eof; + int record_len; +}file_wrapper_t; + +typedef file_wrapper_t* File; +typedef File Text; +typedef Text TextFile; + +void __attribute__((overloadable)) fpcrtl_readLn(File f); +#define fpcrtl_readLn1(f) fpcrtl_readLn(f) + +void __attribute__((overloadable)) fpcrtl_readLn__vars(File f, Integer *i); +void __attribute__((overloadable)) fpcrtl_readLn__vars(File f, LongWord *i); +void __attribute__((overloadable)) fpcrtl_readLn__vars(File f, string255 *s); +#define fpcrtl_readLn2(f, t) fpcrtl_readLn__vars(f, &(t)) + +#define fpcrtl_readLn(...) macro_dispatcher(fpcrtl_readLn, __VA_ARGS__)(__VA_ARGS__) + + +void fpcrtl_blockRead__vars(File f, void *buf, Integer count, Integer *result); +#define fpcrtl_blockRead(f, buf, count, result) fpcrtl_blockRead__vars(f, &(buf), count, &(result)) +#define fpcrtl_BlockRead fpcrtl_blockRead + +#define fpcrtl_assign(f, name) fpcrtl_assign__vars(&f, name) +void fpcrtl_assign__vars(File *f, string255 name); + +boolean fpcrtl_eof(File f); + +void fpcrtl_reset1(File f); +void fpcrtl_reset2(File f, Integer l); +#define fpcrtl_reset1(f) fpcrtl_reset1(f) +#define fpcrtl_reset2(f, l) fpcrtl_reset2(f, l) +#define fpcrtl_reset(...) macro_dispatcher(fpcrtl_reset, __VA_ARGS__)(__VA_ARGS__) + +void fpcrtl_close(File f); + +void __attribute__((overloadable)) fpcrtl_rewrite(File f); +void __attribute__((overloadable)) fpcrtl_rewrite(File f, Integer l); + +void __attribute__((overloadable)) fpcrtl_flush(Text f); +void __attribute__((overloadable)) fpcrtl_flush(FILE *f); + +void __attribute__((overloadable)) fpcrtl_write(File f, string255 s); +void __attribute__((overloadable)) fpcrtl_write(FILE *f, string255 s); +void __attribute__((overloadable)) fpcrtl_writeLn(File f, string255 s); +void __attribute__((overloadable)) fpcrtl_writeLn(FILE *f, string255 s); + +void fpcrtl_blockWrite__vars(File f, const void *buf, Integer count, Integer *result); +#define fpcrtl_blockWrite(f, buf, count, result) fpcrtl_blockWrite__vars(f, &(buf), count, &(result)) +#define fpcrtl_BlockWrite fpcrtl_blockWrite + +bool fpcrtl_directoryExists(string255 dir); +#define fpcrtl_DirectoryExists fpcrtl_directoryExists + +bool fpcrtl_fileExists(string255 filename); +#define fpcrtl_FileExists fpcrtl_fileExists + +#endif /* FILEIO_H_ */ diff -r 31570b766315 -r ed5a6478e710 project_files/hwc/rtl/fpcrtl.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/hwc/rtl/fpcrtl.h Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,213 @@ +#ifndef _FPCRTL_H_ +#define _FPCRTL_H_ + +#include +#include +#include +#include +#include + +#include "SysUtils.h" +#include "system.h" +#include "misc.h" +#include "fileio.h" +#include "pmath.h" + +#ifndef EMSCRIPTEN +#if __APPLE__ +#define main SDL_main +#endif +#include "GL/glew.h" +#endif + +#define fpcrtl_memcpy memcpy + +#define luapas_lua_gettop lua_gettop +#define luapas_lua_close lua_close +#define luapas_lua_createtable lua_createtable +#define luapas_lua_error lua_error +#define luapas_lua_gc lua_gc +#define luapas_lua_getfield lua_getfield +#define luapas_lua_objlen lua_objlen +#define luapas_lua_call lua_call +#define luapas_lua_pcall lua_pcall +#define luapas_lua_pushboolean lua_pushboolean +#define luapas_lua_pushcclosure lua_pushcclosure +#define luapas_lua_pushinteger lua_pushinteger +#define luapas_lua_pushnil lua_pushnil +#define luapas_lua_pushnumber lua_pushnumber +#define luapas_lua_pushlstring lua_pushlstring +#define luapas_lua_pushstring lua_pushstring +#define luapas_lua_pushvalue lua_pushvalue +#define luapas_lua_rawgeti lua_rawgeti +#define luapas_lua_setfield lua_setfield +#define luapas_lua_settop lua_settop +#define luapas_lua_toboolean lua_toboolean +#define luapas_lua_tointeger lua_tointeger +#define luapas_lua_tolstring lua_tolstring +#define luapas_lua_tonumber lua_tonumber +#define luapas_lua_type lua_type +#define luapas_lua_typename lua_typename +#define luapas_luaL_argerror luaL_argerror +#define luapas_luaL_checkinteger luaL_checkinteger +#define luapas_luaL_checklstring luaL_checklstring +#define luapas_luaL_loadfile luaL_loadfile +#define luapas_luaL_loadstring luaL_loadstring +#define luapas_luaL_newstate luaL_newstate +#define luapas_luaL_optinteger luaL_optinteger +#define luapas_luaL_optlstring luaL_optlstring +#define luapas_luaL_prepbuffer luaL_prepbuffer +#define luapas_luaL_ref luaL_ref +#define luapas_luaL_unref luaL_unref +#define luapas_luaopen_base luaopen_base +#define luapas_luaopen_math luaopen_math +#define luapas_luaopen_string luaopen_string +#define luapas_luaopen_table luaopen_table +#define luapas_lua_load lua_load + +#define sdlh_IMG_Load IMG_Load +#define sdlh_IMG_Load_RW IMG_Load_RW + +#ifndef EMSCRIPTEN +#define sdlh_Mix_AllocateChannels Mix_AllocateChannels +#define sdlh_Mix_CloseAudio Mix_CloseAudio +#define sdlh_Mix_FadeInChannelTimed Mix_FadeInChannelTimed +#define sdlh_Mix_FadeInMusic Mix_FadeInMusic +#define sdlh_Mix_FadeOutChannel Mix_FadeOutChannel +#define sdlh_Mix_FreeChunk Mix_FreeChunk +#define sdlh_Mix_FreeMusic Mix_FreeMusic +#define sdlh_Mix_HaltChannel Mix_HaltChannel +#define sdlh_Mix_HaltMusic Mix_HaltMusic +#define sdlh_Mix_LoadMUS Mix_LoadMUS +#define sdlh_Mix_LoadMUS_RW Mix_LoadMUS_RW +#define sdlh_Mix_LoadWAV_RW Mix_LoadWAV_RW +#define sdlh_Mix_OpenAudio Mix_OpenAudio +#define sdlh_Mix_PauseMusic Mix_PauseMusic +#define sdlh_Mix_PlayChannelTimed Mix_PlayChannelTimed +#define sdlh_Mix_Playing Mix_Playing +#define sdlh_Mix_ResumeMusic Mix_ResumeMusic +#define sdlh_Mix_Volume Mix_Volume +#define sdlh_Mix_VolumeMusic Mix_VolumeMusic +#else +#define sdlh_Mix_AllocateChannels stub_Mix_AllocateChannels +#define sdlh_Mix_CloseAudio stub_Mix_CloseAudio +#define sdlh_Mix_FadeInChannelTimed stub_Mix_FadeInChannelTimed +#define sdlh_Mix_FadeInMusic stub_Mix_FadeInMusic +#define sdlh_Mix_FadeOutChannel stub_Mix_FadeOutChannel +#define sdlh_Mix_FreeChunk stub_Mix_FreeChunk +#define sdlh_Mix_FreeMusic stub_Mix_FreeMusic +#define sdlh_Mix_HaltChannel stub_Mix_HaltChannel +#define sdlh_Mix_HaltMusic stub_Mix_HaltMusic +#define sdlh_Mix_LoadMUS stub_Mix_LoadMUS +#define sdlh_Mix_LoadMUS_RW stub_Mix_LoadMUS_RW +#define sdlh_Mix_LoadWAV_RW stub_Mix_LoadWAV_RW +#define sdlh_Mix_OpenAudio stub_Mix_OpenAudio +#define sdlh_Mix_PauseMusic stub_Mix_PauseMusic +#define sdlh_Mix_PlayChannelTimed stub_Mix_PlayChannelTimed +#define sdlh_Mix_Playing stub_Mix_Playing +#define sdlh_Mix_ResumeMusic stub_Mix_ResumeMusic +#define sdlh_Mix_Volume stub_Mix_Volume +#define sdlh_Mix_VolumeMusic stub_Mix_VolumeMusic +#endif + +#define sdlh_SDL_ConvertSurface SDL_ConvertSurface +#define sdlh_SDL_CreateRGBSurface SDL_CreateRGBSurface +#define sdlh_SDL_CreateThread SDL_CreateThread +#define sdlh_SDL_Delay SDL_Delay +#define sdlh_SDL_EnableKeyRepeat SDL_EnableKeyRepeat +#define sdlh_SDL_EnableUNICODE SDL_EnableUNICODE +#define sdlh_SDL_FillRect SDL_FillRect +#define sdlh_SDL_FreeSurface SDL_FreeSurface +#define sdlh_SDL_GetError SDL_GetError +#define sdlh_SDL_GetKeyName SDL_GetKeyName +#define sdlh_SDL_GetKeyState SDL_GetKeyState +#define sdlh_SDL_GetMouseState SDL_GetMouseState +#define sdlh_SDL_GetRGBA SDL_GetRGBA +#define sdlh_SDL_GetTicks SDL_GetTicks +#define sdlh_SDL_GL_SetAttribute SDL_GL_SetAttribute +#define sdlh_SDL_GL_SwapBuffers SDL_GL_SwapBuffers +#define sdlh_SDL_Init SDL_Init +#define sdlh_SDL_InitSubSystem SDL_InitSubSystem +#define sdlh_SDL_JoystickClose SDL_JoystickClose +#define sdlh_SDL_JoystickEventState SDL_JoystickEventState +#define sdlh_SDL_JoystickName SDL_JoystickName +#define sdlh_SDL_JoystickNumAxes SDL_JoystickNumAxes +#define sdlh_SDL_JoystickNumButtons SDL_JoystickNumButtons +#define sdlh_SDL_JoystickNumHats SDL_JoystickNumHats +#define sdlh_SDL_JoystickOpen SDL_JoystickOpen +#define sdlh_SDL_LockSurface SDL_LockSurface +#define sdlh_SDL_MapRGB SDL_MapRGB +#define sdlh_SDL_MapRGBA SDL_MapRGBA +#define sdlh_SDL_NumJoysticks SDL_NumJoysticks +#define sdlh_SDL_PeepEvents SDL_PeepEvents +#define sdlh_SDL_PumpEvents SDL_PumpEvents +#define sdlh_SDL_Quit SDL_Quit +#define sdlh_SDL_RWFromFile SDL_RWFromFile +#define sdlh_SDL_SetColorKey SDL_SetColorKey +#define sdlh_SDL_SetVideoMode SDL_SetVideoMode +#define sdlh_SDL_WaitThread SDL_WaitThread +#define sdlh_SDL_CreateMutex SDL_CreateMutex +#define sdlh_SDL_DestroyMutex SDL_DestroyMutex +#define SDL_LockMutex SDL_mutexP +#define SDL_UnlockMutex SDL_mutexV +#ifndef EMSCRIPTEN +#define sdlh_SDL_ShowCursor SDL_ShowCursor +#else +#define sdlh_SDL_ShowCursor SDL_ShowCursor_patch +#endif +#define sdlh_SDL_UnlockSurface SDL_UnlockSurface +#define sdlh_SDL_UpperBlit SDL_UpperBlit +#define sdlh_SDL_VideoDriverName SDL_VideoDriverName +#define sdlh_SDL_WarpMouse SDL_WarpMouse +#define sdlh_SDL_WM_SetCaption SDL_WM_SetCaption +#define sdlh_SDL_WM_SetIcon SDL_WM_SetIcon +#define sdlh_SDLNet_AddSocket SDLNet_AddSocket +#define sdlh_SDLNet_AllocSocketSet SDLNet_AllocSocketSet +#define sdlh_SDLNet_CheckSockets SDLNet_CheckSockets +#define sdlh_SDLNet_FreeSocketSet SDLNet_FreeSocketSet +#define sdlh_SDLNet_Init SDLNet_Init +#define sdlh_SDLNet_Quit SDLNet_Quit +#define sdlh_SDLNet_ResolveHost SDLNet_ResolveHost +#define sdlh_SDLNet_TCP_Close SDLNet_TCP_Close +#define sdlh_SDLNet_TCP_Open SDLNet_TCP_Open +#define sdlh_SDLNet_TCP_Recv SDLNet_TCP_Recv +#define sdlh_SDLNet_TCP_Send SDLNet_TCP_Send +#define sdlh_TTF_Init TTF_Init +#define sdlh_TTF_OpenFont TTF_OpenFont +#define sdlh_TTF_OpenFontRW TTF_OpenFontRW +#define sdlh_TTF_Quit TTF_Quit +#define sdlh_TTF_RenderUTF8_Blended TTF_RenderUTF8_Blended +#define sdlh_TTF_RenderUTF8_Solid TTF_RenderUTF8_Solid +#define sdlh_TTF_SetFontStyle TTF_SetFontStyle +#define sdlh_TTF_SizeUTF8 TTF_SizeUTF8 + +#define uphysfslayer_physfsReaderSetBuffer physfsReaderSetBuffer +#define uphysfslayer_physfsReader physfsReader +#define uphysfslayer_hedgewarsMountPackage hedgewarsMountPackage +#define uphysfslayer_hedgewarsMountPackages hedgewarsMountPackages + +#define uphysfslayer_PHYSFSRWOPS_openRead PHYSFSRWOPS_openRead +#define uphysfslayer_PHYSFSRWOPS_openWrite PHYSFSRWOPS_openWrite + +#define _strconcat fpcrtl_strconcat +#define _strappend fpcrtl_strappend +#define _strprepend fpcrtl_strprepend +#define _strcompare fpcrtl_strcompare +#define _strncompare fpcrtl_strncompare +#define _strcomparec fpcrtl_strcomparec +#define _chrconcat fpcrtl_chrconcat +#define _pchar fpcrtl_pchar +#define _strconcatA fpcrtl_strconcatA +#define _strncompareA fpcrtl_strncompareA +#define _strappendA fpcrtl_strappendA + +// hooks are implemented in javascript +void start_hook(void); +void mainloop_hook(void); +void clear_filelist_hook(void); +void add_file_hook(const char* ptr); +void idb_loader_hook(); +void showcursor_hook(); +void hidecursor_hook(); +void drawworld_init_hook(); +#endif diff -r 31570b766315 -r ed5a6478e710 project_files/hwc/rtl/misc.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/hwc/rtl/misc.c Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,220 @@ +#include "misc.h" +#include +#include +#include +#include + +char strbuf[512]; + +void fpcrtl_assert(int i) +{ + if(!i){ + assert(0); + } +} + +// EFFECTS: return the nearest integer of the given number +int fpcrtl_round(double number) +{ + return (number >= 0) ? (int)(number + 0.5) : (int)(number - 0.5); +} + +void fpcrtl_printf(const char* format, ...) +{ +#ifdef FPCRTL_DEBUG + va_list args; + va_start (args, format); + vprintf (format, args); + va_end (args); +#endif +} + +// +//void fpcrtl_check_string(string255 str) +//{ +//#ifdef FPCRTL_DEBUG +// int len = strlen(str.str); +// if(len != str.len){ +// printf("String %s internal inconsistency error. Length should be %d but actually is %d.\n", str.str, len, str.len); +// } +// //assert(len == str.len); +//#endif +//} + +string255 fpcrtl_strconcat(string255 str1, string255 str2) +{ + int newlen = str1.len + str2.len; + if(newlen > 255) newlen = 255; + + memcpy(&(str1.str[str1.len]), str2.str, newlen - str1.len); + str1.len = newlen; + + return str1; +} + +astring fpcrtl_strconcatA(astring str1, astring str2) +{ + int newlen = str1.len + str2.len; + if(newlen > MAX_ANSISTRING_LENGTH) newlen = MAX_ANSISTRING_LENGTH; + + memcpy(&(str1.s[str1.len + 1]), &str2.s[1], newlen - str1.len); + str1.len = newlen; + + return str1; +} + +string255 fpcrtl_strappend(string255 s, char c) +{ + if(s.len < 255) + { + ++s.len; + s.s[s.len] = c; + } + + return s; +} + +astring fpcrtl_strappendA(astring s, char c) +{ + if(s.len < MAX_ANSISTRING_LENGTH) + { + s.s[s.len] = c; + ++s.len; + } + + return s; +} + +string255 fpcrtl_strprepend(char c, string255 s) +{ + uint8_t newlen = s.len < 255 ? s.len + 1 : 255; + memmove(s.str + 1, s.str, newlen); // also move '/0' + s.str[0] = c; + s.len = newlen; + + return s; +} + +string255 fpcrtl_chrconcat(char a, char b) +{ + string255 result; + + result.len = 2; + result.str[0] = a; + result.str[1] = b; + + return result; +} + +bool fpcrtl_strcompare(string255 str1, string255 str2) +{ + return memcmp(str1.s, str2.s, str1.len + 1) == 0; +} + +bool fpcrtl_strcomparec(string255 a, char b) +{ + if(a.len == 1 && a.str[0] == b){ + return true; + } + + return false; +} + +bool fpcrtl_strncompare(string255 a, string255 b) +{ + return !fpcrtl_strcompare(a, b); +} + +bool fpcrtl_strncompareA(astring a, astring b) +{ + return (a.len != b.len) || (memcmp(a.s, b.s, a.len) != 0); +} + + +string255 fpcrtl_pchar2str(const char *s) +{ + string255 result; + + if(!s) + { + result.len = 0; + } else + { + int rlen = strlen(s); + + if(rlen > 255){ + rlen = 255; + } + + result.len = rlen; + memcpy(result.str, s, rlen); + } + + return result; +} + + +string255 fpcrtl_make_string(const char* s) { + return fpcrtl_pchar2str(s); +} + + +astring fpcrtl_pchar2astr(const char *s) +{ + astring result; + int rlen = strlen(s); + + if(rlen > MAX_ANSISTRING_LENGTH){ + rlen = MAX_ANSISTRING_LENGTH; + } + + result.len = rlen; + memcpy(result.s + 1, s, rlen); + + return result; +} + +astring fpcrtl_str2astr(const string255 s) +{ + astring result; + + result.str255 = s; + result.len = s.len; + + return result; +} + +string255 fpcrtl_astr2str(const astring s) +{ + string255 result; + + result = s.str255; + result.len = s.len > 255 ? 255 : s.len; + + return result; +} + +char __pcharBuf[256]; + +char* fpcrtl__pchar__vars(const string255 * s) +{ + memcpy(__pcharBuf, &s->s[1], s->len); + __pcharBuf[s->len] = 0; + return __pcharBuf; +} + +char* fpcrtl__pcharA__vars(astring * s) +{ + if(s->len == MAX_ANSISTRING_LENGTH) + --s->len; + + s->s[s->len + 1] = 0; + return &s->s[1]; +} + +#ifdef EMSCRIPTEN +GLenum glewInit() +{ + return GLEW_OK; +} +#endif diff -r 31570b766315 -r ed5a6478e710 project_files/hwc/rtl/misc.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/hwc/rtl/misc.h Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,66 @@ +#ifndef _FPCRTL_MISC_H_ +#define _FPCRTL_MISC_H_ + +#include "pas2c.h" +#include +#include + +#ifdef EMSCRIPTEN +#include +#else +#include +#endif + +#define VA_NUM_ARGS(...) VA_NUM_ARGS_IMPL(__VA_ARGS__, 5,4,3,2,1) +#define VA_NUM_ARGS_IMPL(_1,_2,_3,_4,_5,N,...) N + +#define macro_dispatcher(func, ...) macro_dispatcher_(func, VA_NUM_ARGS(__VA_ARGS__)) +#define macro_dispatcher_(func, nargs) macro_dispatcher__(func, nargs) +#define macro_dispatcher__(func, nargs) func ## nargs + +//#define FPCRTL_DEBUG + +#define FIX_STRING(s) (s.str[s.len == 255 ? 254 : s.len] = 0) +//#define fpcrtl_check_string(s) do{ if(strlen((s).str) != (s).len){ \ +// printf("String %s internal inconsistency error. Length should be %d but actually is %d.\n", (s).str, strlen((s).str), (s).len); \ +// assert(0);\ +// }}while(0) + +void fpcrtl_assert(int); +void fpcrtl_print_trace (void); + +int fpcrtl_round(double number); +void fpcrtl_printf(const char* format, ...); + +string255 fpcrtl_make_string(const char* s); + +string255 fpcrtl_strconcat(string255 str1, string255 str2); +string255 fpcrtl_strappend(string255 s, char c); +string255 fpcrtl_strprepend(char c, string255 s); +string255 fpcrtl_chrconcat(char a, char b); + +astring fpcrtl_strconcatA(astring str1, astring str2); +astring fpcrtl_strappendA(astring s, char c); + +// return true if str1 == str2 +bool fpcrtl_strcompare(string255 str1, string255 str2); +bool fpcrtl_strcomparec(string255 a, char b); +bool fpcrtl_strncompare(string255 a, string255 b); +bool fpcrtl_strncompareA(astring a, astring b); + +#define fpcrtl__pchar(s) fpcrtl__pchar__vars(&(s)) +#define fpcrtl__pcharA(s) fpcrtl__pcharA__vars(&(s)) +char* fpcrtl__pchar__vars(const string255 * s); +char* fpcrtl__pcharA__vars(astring * s); +string255 fpcrtl_pchar2str(const char *s); +astring fpcrtl_pchar2astr(const char *s); +astring fpcrtl_str2astr(const string255 s); +string255 fpcrtl_astr2str(const astring s); +#define fpcrtl_TypeInfo sizeof // dummy + +#ifdef EMSCRIPTEN +#define GLEW_OK 1 +GLenum glewInit(); +#endif + +#endif diff -r 31570b766315 -r ed5a6478e710 project_files/hwc/rtl/pas2c.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/hwc/rtl/pas2c.h Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,84 @@ +#pragma once + +#include +#include +#include +#include +#include + +#define MAX_PARAMS 64 +#define MAX_ANSISTRING_LENGTH 16383 + +typedef union string255_ + { + struct { + unsigned char s[256]; + }; + struct { + unsigned char len; + unsigned char str[255]; + }; + } string255; + +typedef union astring_ + { + struct { + uint16_t len; + }; + struct { + unsigned char _dummy2; + unsigned char s[MAX_ANSISTRING_LENGTH + 1]; + }; + struct { + unsigned char _dummy1; + string255 str255; + }; + } astring; + +typedef string255 shortstring; + +typedef uint8_t Byte; +typedef int8_t ShortInt; +typedef uint16_t Word; +typedef int16_t SmallInt; +typedef uint32_t LongWord; +typedef int32_t LongInt; +typedef uint64_t QWord; +typedef int64_t Int64; +typedef LongWord Cardinal; + +typedef LongInt Integer; +typedef float extended; +typedef float real; +typedef float single; + +typedef bool boolean; +typedef int LongBool; + +typedef void * pointer; +typedef Byte * PByte; +typedef char * PChar; +typedef LongInt * PLongInt; +typedef LongWord * PLongWord; +typedef Integer * PInteger; +typedef ptrdiff_t PtrInt; +typedef wchar_t widechar; +typedef wchar_t* PWideChar; +typedef char Char; +typedef LongInt SizeInt; +typedef char ** PPChar; +typedef Word* PWord; + +string255 _strconcat(string255 a, string255 b); +string255 _strappend(string255 s, unsigned char c); +string255 _strprepend(unsigned char c, string255 s); +string255 _chrconcat(unsigned char a, unsigned char b); +bool _strcompare(string255 a, string255 b); +bool _strcomparec(string255 a, unsigned char b); +bool _strncompare(string255 a, string255 b); +bool _strncompareA(astring a, astring b); + + +#define STRINIT(a) {.len = sizeof(a) - 1, .str = a} +#define UNUSED(x) (void)(x) + diff -r 31570b766315 -r ed5a6478e710 project_files/hwc/rtl/pmath.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/hwc/rtl/pmath.c Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,49 @@ +#include "pmath.h" +#include +#include + +/* + * power raises base to the power power. + * This is equivalent to exp(power*ln(base)). Therefore base should be non-negative. + */ +float fpcrtl_power(float base, float exponent) +{ + return exp(exponent * log(base)); +} + +/* Currently the games only uses sign of an integer */ +int fpcrtl_signi(int x) +{ + if(x > 0){ + return 1; + } + else if(x < 0){ + return -1; + } + else{ + return 0; + } +} + +float fpcrtl_csc(float x) +{ + return 1 / sin(x); +} + +float __attribute__((overloadable)) fpcrtl_abs(float x) +{ + return fabs(x); +} +double __attribute__((overloadable)) fpcrtl_abs(double x) +{ + return fabs(x); +} +int __attribute__((overloadable)) fpcrtl_abs(int x) +{ + return abs(x); +} + +int64_t __attribute__((overloadable)) fpcrtl_abs(int64_t x) +{ + return x < 0 ? -x : x; +} diff -r 31570b766315 -r ed5a6478e710 project_files/hwc/rtl/pmath.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/hwc/rtl/pmath.h Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,24 @@ +#ifndef PMATH_H_ +#define PMATH_H_ + +#include +#include + +#define fpcrtl_min(a, b) ((a) < (b) ? (a) : (b)) +#define fpcrtl_max(a, b) ((a) > (b) ? (a) : (b)) + +float fpcrtl_power(float base, float exponent); + +/* Currently the games only uses sign of an integer */ +int fpcrtl_signi(int x); + +float fpcrtl_csc(float x); + +#define fpcrtl_arctan2(y, x) atan2(y, x) + +float __attribute__((overloadable)) fpcrtl_abs(float x); +double __attribute__((overloadable)) fpcrtl_abs(double x); +int __attribute__((overloadable)) fpcrtl_abs(int x); +int64_t __attribute__((overloadable)) fpcrtl_abs(int64_t x); + +#endif /* PMATH_H_ */ diff -r 31570b766315 -r ed5a6478e710 project_files/hwc/rtl/system.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/hwc/rtl/system.c Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,438 @@ +#include "system.h" +#include +#include +#include +#include + +#ifndef M_PI +// some math.h do not have M_PI macros +# define M_PI 3.14159265358979323846 /* pi */ +# define M_PI_2 1.57079632679489661923 /* pi/2 */ +# define M_PI_4 0.78539816339744830962 /* pi/4 */ +# define M_PIl 3.1415926535897932384626433832795029L /* pi */ +# define M_PI_2l 1.5707963267948966192313216916397514L /* pi/2 */ +# define M_PI_4l 0.7853981633974483096156608458198757L /* pi/4 */ +#endif + +double pi = M_PI; + +int paramCount; +string255 params[MAX_PARAMS]; + +string255 fpcrtl_copy(string255 s, Integer index, Integer count) { + string255 result = STRINIT(""); + + if (count < 1) { + return result; + } + + if (index < 1) { + index = 1; + } + + if (index > s.len) { + return result; + } + + if (index + count > s.len + 1) { + count = s.len + 1 - index; + } + + memcpy(result.str, s.str + index - 1, count); + + result.len = count; + + return result; +} + +astring fpcrtl_copyA(astring s, Integer index, Integer count) { + astring result; + + result.len = 0; + + if (count < 1) { + return result; + } + + if (index < 1) { + index = 1; + } + + if (index > s.len) { + return result; + } + + if (index + count > s.len + 1) { + count = s.len + 1 - index; + } + + memcpy(result.s + 1, s.s + index, count); + + result.len = count; + + return result; +} + +void fpcrtl_insert__vars(string255 *src, string255 *dst, SizeInt index) { + int num_insert; + int num_shift; + int num_preshift; + + // nothing to do if empty string is inserted or index invalid + if ((src->len == 0) || (index < 1) || (index > 255)) { + return; + } + + num_insert = src->len; + // number of chars from start of destination string to end of insertion + num_preshift = index - 1 + num_insert; + + // don't overflow on insert + if (num_preshift > 255) { + num_insert = 255 - (index - 1); + num_shift = 0; + } + // shift trailing chars + else { + // number of bytes to be shifted + num_shift = dst->len - (index - 1); + + if (num_shift > 0) { + // don't overflow when shifting + if (num_shift + num_preshift > 255) + num_shift = 255 - num_preshift; + + // time to move some bytes! + memmove(dst->str + num_preshift, dst->str + index - 1, num_shift); + } + } + + // actual byte insertion + memmove(dst->str + index - 1, src->str, num_insert); + // store new length + dst->len = num_shift + num_preshift; +} + +void __attribute__((overloadable)) fpcrtl_delete__vars(string255 *s, SizeInt index, SizeInt count) { + // number of chars to be move + int num_move; + int new_length; + + if (index < 1) { + // in fpc, if index < 1, the string won't be modified + return; + } + + if(index > s->len){ + return; + } + + if (count > s->len - index + 1) { + s->len = index - 1; + return; + } + + num_move = s->len - index + 1 - count; + new_length = s->len - count; + + memmove(s->str + index - 1, s->str + index - 1 + count, num_move); + s->str[new_length] = 0; + + s->len = new_length; + +} + +void __attribute__((overloadable)) fpcrtl_delete__vars(astring *s, SizeInt index, SizeInt count) { + // number of chars to be move + int num_move; + int new_length; + + if (index < 1) { + // in fpc, if index < 1, the string won't be modified + return; + } + + if(index > s->len){ + return; + } + + if (count > s->len - index + 1) { + s->len = index - 1; + return; + } + + num_move = s->len - index + 1 - count; + new_length = s->len - count; + + memmove(s->s + index, s->s + index + count, num_move); + + s->len = new_length; + +} + +string255 fpcrtl_floatToStr(double n) { + string255 t; + sprintf(t.str, "%f", n); + t.len = strlen(t.str); + + return t; +} + +void fpcrtl_move__vars(void *src, void *dst, SizeInt count) { + memmove(dst, src, count); +} + +Integer __attribute__((overloadable)) fpcrtl_pos(Char c, string255 str) { + + unsigned char* p; + + if (str.len == 0) { + return 0; + } + + FIX_STRING(str); + + p = strchr(str.str, c); + + if (p == NULL) { + return 0; + } + + return p - (unsigned char*)&str.s; +} + +Integer __attribute__((overloadable)) fpcrtl_pos(string255 substr, string255 str) { + + unsigned char* p; + + if (str.len == 0) { + return 0; + } + + if (substr.len == 0) { + return 0; + } + + FIX_STRING(substr); + FIX_STRING(str); + + p = strstr(str.str, substr.str); + + if (p == NULL) { + return 0; + } + + return p - (unsigned char*)&str.s; +} + +Integer __attribute__((overloadable)) fpcrtl_pos(Char c, astring str) { + unsigned char* p; + + if (str.len == 0) { + return 0; + } + + p = strchr(str.s + 1, c); + + if (p == NULL) { + return 0; + } + + return p - (unsigned char*)&str.s; + +} + +Integer __attribute__((overloadable)) fpcrtl_pos(string255 substr, astring str) { + + unsigned char* p; + + if (str.len == 0) { + return 0; + } + + if (substr.len == 0) { + return 0; + } + + FIX_STRING(substr); + str.s[str.len] = 0; + + p = strstr(str.s + 1, substr.str); + + if (p == NULL) { + return 0; + } + + return p - (unsigned char *)&str.s; +} + +Integer fpcrtl_length(string255 s) { + return s.len; +} + +Integer fpcrtl_lengthA(astring s) +{ + return s.len; +} + + +string255 fpcrtl_lowerCase(string255 s) { + int i; + + for (i = 0; i < s.len; i++) { + if (s.str[i] >= 'A' && s.str[i] <= 'Z') { + s.str[i] += 'a' - 'A'; + } + } + + return s; +} + +void fpcrtl_fillChar__vars(void *x, SizeInt count, Byte value) { + memset(x, value, count); +} + +void fpcrtl_new__vars(void **p, int size) { + *p = malloc(size); +} + +Integer fpcrtl_trunc(extended n) { + return (int) n; +} + +Integer fpcrtl_ceil(extended n) { + return (int) (ceil(n)); +} + +LongInt str_to_int(char *src) +{ + int i; + int len = strlen(src); + char *end; + for(i = 0; i < len; i++) + { + if(src[i] == '$'){ + // hex + return strtol(src + i + 1, &end, 16); + } + } + + // decimal + return atoi(src); +} + +void __attribute__((overloadable)) fpcrtl_val__vars(string255 s, LongInt *a) +{ + FIX_STRING(s); + *a = str_to_int(s.str); +} + +void __attribute__((overloadable)) fpcrtl_val__vars(string255 s, Byte *a) +{ + FIX_STRING(s); + *a = str_to_int(s.str); +} + +void __attribute__((overloadable)) fpcrtl_val__vars(string255 s, LongWord *a) +{ + FIX_STRING(s); + *a = str_to_int(s.str); +} + +LongInt fpcrtl_random(LongInt l) { + // random(0) is undefined in docs but effectively returns 0 in free pascal + if (l == 0) { + printf("WARNING: random(0) called!\n"); + return 0; + } + return (LongInt) (rand() / (double) RAND_MAX * l); +} + +void __attribute__((overloadable)) fpcrtl_str__vars(float x, string255 *s) { + sprintf(s->str, "%f", x); + s->len = strlen(s->str); +} +void __attribute__((overloadable)) fpcrtl_str__vars(double x, string255 *s) { + sprintf(s->str, "%f", x); + s->len = strlen(s->str); +} +void __attribute__((overloadable)) fpcrtl_str__vars(uint8_t x, string255 *s) { + sprintf(s->str, "%u", x); + s->len = strlen(s->str); +} +void __attribute__((overloadable)) fpcrtl_str__vars(int8_t x, string255 *s) { + sprintf(s->str, "%d", x); + s->len = strlen(s->str); +} +void __attribute__((overloadable)) fpcrtl_str__vars(uint16_t x, string255 *s) { + sprintf(s->str, "%u", x); + s->len = strlen(s->str); +} +void __attribute__((overloadable)) fpcrtl_str__vars(int16_t x, string255 *s) { + sprintf(s->str, "%d", x); + s->len = strlen(s->str); +} +void __attribute__((overloadable)) fpcrtl_str__vars(uint32_t x, string255 *s) { + sprintf(s->str, "%u", x); + s->len = strlen(s->str); +} +void __attribute__((overloadable)) fpcrtl_str__vars(int32_t x, string255 *s) { + sprintf(s->str, "%d", x); + s->len = strlen(s->str); +} +void __attribute__((overloadable)) fpcrtl_str__vars(uint64_t x, string255 *s) { + sprintf(s->str, "%llu", x); + s->len = strlen(s->str); +} +void __attribute__((overloadable)) fpcrtl_str__vars(int64_t x, string255 *s) { + sprintf(s->str, "%lld", x); + s->len = strlen(s->str); +} + +/* + * XXX No protection currently! + */ +void fpcrtl_interlockedIncrement__vars(int *i) { + (*i)++; +} + +void fpcrtl_interlockedDecrement__vars(int *i) { + (*i)--; +} + +/* + * This function should be called when entering main + */ +void fpcrtl_init(int argc, char** argv) { + int i; + paramCount = argc; + + printf("ARGC = %d\n", paramCount); + + for (i = 0; i < argc; i++) { + if (strlen(argv[i]) > 255) { + assert(0); + } + strcpy(params[i].str, argv[i]); + params[i].len = strlen(params[i].str); + } + +} + +int fpcrtl_paramCount() { + return paramCount - 1; // ignore the first one +} + +string255 fpcrtl_paramStr(int i) { + return params[i]; +} + +int fpcrtl_UTF8ToUnicode(PWideChar dest, PChar src, SizeInt maxLen) { + //return swprintf(dest, maxLen, L"%hs", "src"); //doesn't work in emscripten + return 0; +} + +uint32_t __attribute__((overloadable)) fpcrtl_lo(uint64_t i) { + return (i & 0xFFFFFFFF); +} + diff -r 31570b766315 -r ed5a6478e710 project_files/hwc/rtl/system.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/hwc/rtl/system.h Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,188 @@ +#ifndef SYSTEM_H_ +#define SYSTEM_H_ + +#include +#include +#include "Types.h" +#include "misc.h" + +extern double pi; + +typedef TDate* PDate; + +// dimension info for dynamic arrays +typedef struct { + int dim; + int a[4]; // at most 4 +} fpcrtl_dimension_t; + +/* + * Copy returns a string which is a copy if the Count characters in S, starting at position Index. + * If Count is larger than the length of the string S, the result is truncated. + * If Index is larger than the length of the string S, then an empty string is returned. + * Index is 1-based. + */ +string255 fpcrtl_copy(string255 s, Integer Index, Integer Count); +astring fpcrtl_copyA(astring s, Integer Index, Integer Count); + +/* + * Insert a shortstring in another at a specified index + */ +void fpcrtl_insert__vars(string255 *src, string255 *dst, SizeInt index); +#define fpcrtl_insert(src, dst, index) fpcrtl_insert__vars(&(src), &(dst), index); +#define fpcrtl_Insert fpcrtl_insert + +/* + * Delete removes Count characters from string S, starting at position Index. + * All characters after the deleted characters are shifted Count positions to the left, + * and the length of the string is adjusted. + */ +#define fpcrtl_delete(s, index, count) fpcrtl_delete__vars(&(s), index, count) +void __attribute__((overloadable)) fpcrtl_delete__vars(string255 *s, SizeInt index, SizeInt count); +void __attribute__((overloadable)) fpcrtl_delete__vars(astring *s, SizeInt index, SizeInt count); +#define fpcrtl_Delete fpcrtl_delete + +string255 fpcrtl_floatToStr(double n); + +/* + * Move data from one location in memory to another + */ +void fpcrtl_move__vars(void *src, void *dst, SizeInt count); +#define fpcrtl_move(src, dst, count) fpcrtl_move__vars(&(src), &(dst), count); +#define fpcrtl_Move fpcrtl_move + +Integer __attribute__((overloadable)) fpcrtl_pos(Char c, string255 str); +Integer __attribute__((overloadable)) fpcrtl_pos(string255 substr, string255 str); +Integer __attribute__((overloadable)) fpcrtl_pos(string255 substr, astring str); +Integer __attribute__((overloadable)) fpcrtl_pos(Char c, astring str); + +Integer fpcrtl_length(string255 s); +#define fpcrtl_Length fpcrtl_length +Integer fpcrtl_lengthA(astring s); +#define fpcrtl_LengthA fpcrtl_lengthA + +#define fpcrtl_SetLengthA(s, l) do{(s).len = (l);}while(0) + +#define fpcrtl_sqr(x) ((x) * (x)) + +#define fpcrtl_odd(x) ((x) % 2 != 0 ? true : false) + +#define fpcrtl_StrLen strlen + +#define SizeOf sizeof + +string255 fpcrtl_lowerCase(string255 s); +#define fpcrtl_LowerCase fpcrtl_lowerCase + +void fpcrtl_fillChar__vars(void *x, SizeInt count, Byte value); +#define fpcrtl_fillChar(x, count, value) fpcrtl_fillChar__vars(&(x), count, value) +#define fpcrtl_FillChar fpcrtl_fillChar + +void fpcrtl_new__vars(void **p, int size); +#define fpcrtl_new(a) fpcrtl_new__vars((void **)&(a), sizeof(*(a))) + +#define fpcrtl_dispose free + +#define fpcrtl_freeMem(p, size) free(p) +#define fpcrtl_FreeMem(p, size) free(p) + +#define fpcrtl_getMem(size) malloc(size) +#define fpcrtl_GetMem fpcrtl_getMem + +#define fpcrtl_assigned(p) ((p) != NULL) +#define fpcrtl_Assigned fpcrtl_assigned + +Integer fpcrtl_trunc(extended n); +Integer fpcrtl_ceil(extended n); + +#define fpcrtl_val(s, a) fpcrtl_val__vars(s, &(a)) +void __attribute__((overloadable)) fpcrtl_val__vars(string255 s, LongInt *a); +void __attribute__((overloadable)) fpcrtl_val__vars(string255 s, Byte *a); +void __attribute__((overloadable)) fpcrtl_val__vars(string255 s, LongWord *a); + +#define fpcrtl_randomize() srand(time(NULL)) + +/* + * Random returns a random number larger or equal to 0 and strictly less than L + */ +LongInt fpcrtl_random(LongInt l); + +string255 fpcrtl_paramStr(LongInt); +#define fpcrtl_ParamStr fpcrtl_paramStr + +/* + * Str returns a string which represents the value of X. X can be any numerical type. + */ +#define fpcrtl_str(x, s) fpcrtl_str__vars(x, &(s)) +void __attribute__((overloadable)) fpcrtl_str__vars(float x, string255 *s); +void __attribute__((overloadable)) fpcrtl_str__vars(double x, string255 *s); +void __attribute__((overloadable)) fpcrtl_str__vars(uint8_t x, string255 *s); +void __attribute__((overloadable)) fpcrtl_str__vars(int8_t x, string255 *s); +void __attribute__((overloadable)) fpcrtl_str__vars(uint16_t x, string255 *s); +void __attribute__((overloadable)) fpcrtl_str__vars(int16_t x, string255 *s); +void __attribute__((overloadable)) fpcrtl_str__vars(uint32_t x, string255 *s); +void __attribute__((overloadable)) fpcrtl_str__vars(int32_t x, string255 *s); +void __attribute__((overloadable)) fpcrtl_str__vars(uint64_t x, string255 *s); +void __attribute__((overloadable)) fpcrtl_str__vars(int64_t x, string255 *s); + +void fpcrtl_interlockedIncrement__vars(int *i); +void fpcrtl_interlockedDecrement__vars(int *i); + +#define fpcrtl_interlockedIncrement(i) fpcrtl_interlockedIncrement__vars(&(i)) +#define fpcrtl_interlockedDecrement(i) fpcrtl_interlockedDecrement__vars(&(i)) + +#define fpcrtl_InterlockedIncrement fpcrtl_interlockedIncrement +#define fpcrtl_InterlockedDecrement fpcrtl_interlockedDecrement + +void fpcrtl_init(int argc, char** argv); + +int fpcrtl_paramCount(); +#define fpcrtl_ParamCount fpcrtl_paramCount + +string255 fpcrtl_paramStr(int i); +#define fpcrtl_ParamStr fpcrtl_paramStr + +int fpcrtl_UTF8ToUnicode(PWideChar dest, PChar src, SizeInt maxLen); + +// #define fpcrtl_halt(t) assert(0) +#define fpcrtl_halt(t) exit(t) + +#define fpcrtl_Load_GL_VERSION_2_0() 1 + +uint32_t __attribute__((overloadable)) fpcrtl_lo(uint64_t); +#define fpcrtl_Lo fpcrtl_lo + +#define __SET_LENGTH2(arr, d, b) do{\ + d.dim = 1;\ + arr = realloc(arr, b * sizeof(typeof(*arr)));\ + d.a[0] = b;\ + }while(0) + +#define SET_LENGTH2(arr, b) __SET_LENGTH2(arr, arr##_dimension_info, (b)) + +#define __SET_LENGTH3(arr, d, b, c) do{\ + d.dim = 2;\ + for (int i = 0; i < d.a[0]; i++) {\ + arr[i] = realloc(arr[i], c * sizeof(typeof(**arr)));\ + }\ + if (d.a[0] > b) {\ + for (int i = b; i < d.a[0]; i++) {\ + free(arr[i]);\ + }\ + arr = realloc(arr, b * sizeof(typeof(*arr)));\ + } else if (d.a[0] < b) {\ + arr = realloc(arr, b * sizeof(typeof(*arr)));\ + for (int i = d.a[0]; i < b; i++) {\ + arr[i] = malloc(c * sizeof(typeof(**arr)));\ + memset(arr[i], 0, c * sizeof(typeof(**arr)));\ + }\ + }\ + d.a[0] = b;\ + d.a[1] = c;\ + }while(0) + +#define SET_LENGTH3(arr, b, c) __SET_LENGTH3(arr, arr##_dimension_info, (b), (c)) + +#define fpcrtl_SetLength(...) macro_dispatcher(SET_LENGTH, __VA_ARGS__)(__VA_ARGS__) + +#endif /* SYSTEM_H_ */ diff -r 31570b766315 -r ed5a6478e710 project_files/hwc/rtl/sysutils.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/hwc/rtl/sysutils.c Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,185 @@ +#include "SysUtils.h" + +#include +#include +#include +#include + +#include "system.h" +#include "misc.h" + +TDateTime fpcrtl_date() +{ + const int num_days_between_1900_1980 = 29220; + + struct tm ref_date; + struct tm cur_date; + time_t local_time; + time_t ref_time, cur_time; + + double timeDiff; + double day_time_frac; //fraction that represents the time in one day + int num_seconds; + int numDays; + + // unix epoch doesn't work, choose Jan 1st 1980 instead + ref_date.tm_year = 80; + ref_date.tm_mon = 0; + ref_date.tm_mday = 1; + ref_date.tm_hour = 0; + ref_date.tm_min = 0; + ref_date.tm_sec = 0; + ref_date.tm_isdst = 0; + ref_date.tm_wday = 0; // ignored + ref_date.tm_yday = 0; // ignored + + local_time = time(NULL); + cur_date = *localtime(&local_time); + + cur_date.tm_hour = 0; + cur_date.tm_min = 0; + cur_date.tm_sec = 0; + + ref_time = mktime(&ref_date); + cur_time = mktime(&cur_date); + + timeDiff = difftime(cur_time, ref_time); + numDays = fpcrtl_round(timeDiff / 3600 / 24) + num_days_between_1900_1980 + 1; + + fpcrtl_printf("[date] tim diff: %f\n", timeDiff); + fpcrtl_printf("[date] num days between 1980 and today: %d\n", fpcrtl_round(timeDiff/3600/24)); + fpcrtl_printf("[date] current date: %s\n", asctime(&cur_date)); + fpcrtl_printf("[date] reference date: %s\n", asctime(&ref_date)); + fpcrtl_printf("[date] num days: %d\n", numDays); + + return numDays; +} + +TDateTime fpcrtl_time() +{ + struct tm cur_date; + time_t local_time; + time_t cur_time; + + double day_time_frac; //fraction that represents the time in one day + int num_seconds; + + local_time = time(NULL); + cur_date = *localtime(&local_time); + + num_seconds = cur_date.tm_hour * 3600 + cur_date.tm_min * 60 + cur_date.tm_sec; + day_time_frac = num_seconds / 3600.0 / 24.0; + + fpcrtl_printf("%f\n", day_time_frac); + + return day_time_frac; +} + +TDateTime fpcrtl_now() +{ + return fpcrtl_date() + fpcrtl_time(); +} + +/* + * XXX: dummy + */ +string255 fpcrtl_formatDateTime(string255 FormatStr, TDateTime DateTime) +{ + string255 result = STRINIT("2012 01-01"); + return result; +} + +string255 fpcrtl_trim(string255 s) +{ + int left, right; + + if(s.len == 0){ + return s; + } + + for(left = 0; left < s.len; left++) + { + if(s.str[left] != ' '){ + break; + } + } + + for(right = s.len - 1; right >= 0; right--) + { + if(s.str[right] != ' '){ + break; + } + } + + if(left > right){ + s.len = 0; + s.str[0] = 0; + return s; + } + + s.len = right - left + 1; + memmove(s.str, s.str + left, s.len); + + s.str[s.len] = 0; + + return s; +} + +Integer fpcrtl_strToInt(string255 s) +{ + s.str[s.len] = 0; + return atoi(s.str); +} + +string255 fpcrtl_extractFileDir(string255 f) +{ + const char sep[] = {'\\', '/', ':'}; + LongInt i,j; + + i = f.len - 1; + while(i >= 0){ + for(j = 0; j < sizeof(sep); j++){ + if(f.str[i] == sep[j]){ + goto FPCRTL_EXTRACTFILEDIR_END; + } + } + i--; + } +FPCRTL_EXTRACTFILEDIR_END: + return fpcrtl_copy(f, 1, i); +} + +//function ExtractFileName(const FileName: string): string; +//var +// i : longint; +// EndSep : Set of Char; +//begin +// I := Length(FileName); +// EndSep:=AllowDirectorySeparators+AllowDriveSeparators; +// while (I > 0) and not (FileName[I] in EndSep) do +// Dec(I); +// Result := Copy(FileName, I + 1, MaxInt); +//end; + +string255 fpcrtl_extractFileName(string255 f) +{ + const char sep[] = {'\\', '/', ':'}; + LongInt i,j; + + i = f.len - 1; + while(i >= 0){ + for(j = 0; j < sizeof(sep); j++){ + if(f.str[i] == sep[j]){ + goto FPCRTL_EXTRACTFILENAME_END; + } + } + i--; + } +FPCRTL_EXTRACTFILENAME_END: + return fpcrtl_copy(f, i + 2, 256); +} + +string255 fpcrtl_strPas(PChar p) +{ + return fpcrtl_pchar2str(p); +} diff -r 31570b766315 -r ed5a6478e710 project_files/hwc/rtl/tests/check_check.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/hwc/rtl/tests/check_check.c Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,23 @@ +#include +#include +#include "check_check.h" + +int main(void) +{ + int number_failed; + + Suite *s1 = system_suite(); + Suite *s2 = misc_suite(); + Suite *s3 = sysutils_suite(); + Suite *s4 = fileio_suite(); + + SRunner *sr = srunner_create(s1); + srunner_add_suite(sr, s2); + srunner_add_suite(sr, s3); + srunner_add_suite(sr, s4); + + srunner_run_all(sr, CK_NORMAL); + number_failed = srunner_ntests_failed(sr); + srunner_free(sr); + return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; +} diff -r 31570b766315 -r ed5a6478e710 project_files/hwc/rtl/tests/check_check.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/hwc/rtl/tests/check_check.h Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,9 @@ +#ifndef _CHECK_CHECK_H_ +#define _CHECK_CHECK_H_ + +Suite *system_suite(); +Suite *misc_suite(); +Suite *sysutils_suite(); +Suite *fileio_suite(); + +#endif diff -r 31570b766315 -r ed5a6478e710 project_files/hwc/rtl/tests/check_fileio.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/hwc/rtl/tests/check_fileio.c Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,103 @@ +#include +#include +#include +#include "check_check.h" +#include "../src/fpcrtl.h" + +typedef struct __TResourceList +{ + Integer count; + string255 files[500 + 1]; +} TResourceList; + +string255 t = STRINIT("test"); +string255 Pathz[1] = +{ STRINIT("../../") }; +int ptCurrTheme = 0; +string255 cThemeCFGFilename = STRINIT("theme.cfg"); +const string255 __str79 = STRINIT("object"); +string255 c1 = STRINIT("="); +string255 c2 = STRINIT("\x2c"); +string255 c3 = STRINIT("\x2f"); + +static string255 make_string(const char* str) +{ + string255 s; + s.len = strlen(str); + memcpy(s.str, str, s.len + 1); + return s; +} + +TResourceList readThemeCfg_0() +{ + TResourceList readthemecfg_result; + string255 s; + string255 key; + TextFile f; + Integer i; + TResourceList res; + + s = _strconcat(_strappend(Pathz[ptCurrTheme], '\x2f'), cThemeCFGFilename); + //umisc_log(s); + + fpcrtl_assign(f, s); + + FileMode = 0; + fpcrtl_reset(f); + + res.count = 0; + while (!(fpcrtl_eof(f))) + { + fpcrtl_readLnS(f, s); + if ((fpcrtl_Length(s)) == (0)) + { + continue; + } + if ((s.s[1]) == ('\x3b')) + { + continue; + } + i = fpcrtl_pos('\x3d', s); + key = fpcrtl_trim(fpcrtl_copy(s, 1, i - 1)); + fpcrtl_delete(s, 1, i); + if (_strcompare(key, __str79)) + { + i = fpcrtl_pos('\x2c', s); + res.files[res.count] = _strconcat( + _strappend(Pathz[ptCurrTheme], '\x2f'), + fpcrtl_trim(fpcrtl_copy(s, 1, i - 1))); + ++res.count; + //umisc_log(fpcrtl_trim(fpcrtl_copy(s, 1, i - 1))); + } + } + fpcrtl_close(f); + readthemecfg_result = res; + return readthemecfg_result; +} + +START_TEST(test_readthemecfg) + { + int i; + TResourceList result; + + printf("-----Entering test readthemecfg-----\n"); + result = readThemeCfg_0(); + for (i = 0; i < result.count; i++) + { + printf("%s\n", result.files[i].str); + } + printf("-----Leaving test readthemecfg-----\n"); + }END_TEST + +Suite* fileio_suite(void) +{ + Suite *s = suite_create("fileio"); + + TCase *tc_core = tcase_create("Core"); + + tcase_add_test(tc_core, test_readthemecfg); + + suite_add_tcase(s, tc_core); + + return s; +} diff -r 31570b766315 -r ed5a6478e710 project_files/hwc/rtl/tests/check_misc.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/hwc/rtl/tests/check_misc.c Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,88 @@ +#include +#include +#include +#include "check_check.h" +#include "../src/misc.h" + +static string255 make_string(const char* str) +{ + string255 s; + s.len = strlen(str); + memcpy(s.str, str, s.len + 1); + return s; +} + +START_TEST(test_strconcat) +{ + string255 t; + t = fpcrtl_strconcat(make_string(""), make_string("")); + fail_if(strcmp(t.str, ""), "strconcat(\"\", \"\")"); + + t = fpcrtl_strconcat(make_string(""), make_string("a")); + fail_if(strcmp(t.str, "a"), "strconcat(\"\", \"a\")"); + + t = fpcrtl_strconcat(make_string("a"), make_string("")); + fail_if(strcmp(t.str, "a"), "strconcat(\"a\", \"\")"); + + t = fpcrtl_strconcat(make_string("ab"), make_string("")); + fail_if(strcmp(t.str, "ab"), "strconcat(\"ab\", \"\")"); + + t = fpcrtl_strconcat(make_string("ab"), make_string("cd")); + fail_if(strcmp(t.str, "abcd"), "strconcat(\"ab\", \"cd\")"); +} +END_TEST + +START_TEST (test_strappend) +{ + string255 t; + + t = fpcrtl_strappend(make_string(""), 'c'); + fail_if(strcmp(t.str, "c"), "strappend(\"\", 'c')"); + + t = fpcrtl_strappend(make_string("ab"), 'c'); + fail_if(strcmp(t.str, "abc"), "strappend(\"ab\", 'c')"); +} +END_TEST + +START_TEST (test_strprepend) +{ + string255 t; + + t = fpcrtl_strprepend('c', make_string("")); + fail_if(strcmp(t.str, "c"), "strprepend('c', \"\")"); + + t = fpcrtl_strprepend('c', make_string("ab")); + fail_if(strcmp(t.str, "cab"), "strprepend('c', \"ab\")"); +} +END_TEST + +START_TEST (test_strcompare) +{ + fail_unless(fpcrtl_strcompare(make_string(""), make_string("")), "strcompare(\"\", \"\")"); + fail_unless(fpcrtl_strcompare(make_string("a"), make_string("a")), "strcompare(\"a\", \"a\""); + fail_unless(!fpcrtl_strcompare(make_string("a"), make_string("b")), "strcompare(\"a\", \"b\")"); + fail_unless(!fpcrtl_strcompare(make_string("a"), make_string("ab")), "strcompare(\"a\", \"ab\")"); + + fail_unless(fpcrtl_strcomparec(make_string(" "), ' '), "strcomparec(\" \", ' ')"); + fail_unless(fpcrtl_strcomparec(make_string("a"), 'a'), "strcomparec(\"a\", 'a')"); + fail_unless(!fpcrtl_strcomparec(make_string(" "), ' '), "strcomparec(\" \", ' '"); + fail_unless(!fpcrtl_strcomparec(make_string(""), ' '), "strcomparec(\"\", ' ')"); + +} +END_TEST + +Suite* misc_suite(void) +{ + Suite *s = suite_create("misc"); + + TCase *tc_core = tcase_create("Core"); + + tcase_add_test(tc_core, test_strconcat); + tcase_add_test(tc_core, test_strappend); + tcase_add_test(tc_core, test_strprepend); + tcase_add_test(tc_core, test_strcompare); + + suite_add_tcase(s, tc_core); + + return s; +} diff -r 31570b766315 -r ed5a6478e710 project_files/hwc/rtl/tests/check_system.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/hwc/rtl/tests/check_system.c Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,251 @@ +#include +#include +#include +#include "check_check.h" +#include "../src/system.h" + +void check_string(string255 str) +{ + fail_unless(strlen(str.str) == str.len, "String internal inconsistency error"); +} + +static string255 make_string(const char* str) +{ + string255 s; + s.len = strlen(str); + memcpy(s.str, str, s.len + 1); + return s; +} + +START_TEST (test_copy) + { + string255 s = STRINIT("1234567"); + string255 t; + + t = fpcrtl_copy(s, 1, 1); + fail_if(strcmp(t.str, "1"), "Test copy fail 1"); + + t = fpcrtl_copy(s, 7, 1); + fail_if(strcmp(t.str, "7"), "Test copy fail 2"); + + t = fpcrtl_copy(s, 8, 1); + fail_if(t.len != 0, "Test copy fail 3"); + + t = fpcrtl_copy(s, 8, 100); + fail_if(t.len != 0, "Test copy fail 4"); + check_string(t); + + t = fpcrtl_copy(s, 0, 100); + fail_if(strcmp(t.str, "1234567"), "Test copy fail 5"); + + t = fpcrtl_copy(s, 0, 5); + fail_if(strcmp(t.str, "12345"), "Test copy fail 6"); + + t = fpcrtl_copy(s, 4, 100); + fail_if(strcmp(t.str, "4567"), "Test copy fail 7"); + + t = fpcrtl_copy(s, 4, 2); + fail_if(strcmp(t.str, "45"), "Test copy fail 8"); + }END_TEST + +START_TEST (test_delete) + { + string255 s = STRINIT("1234567"); + string255 s2 = STRINIT("1234567"); + string255 s3 = STRINIT("1234567"); + + fpcrtl_delete(s, 0, 10); + fail_if(strcmp(s.str, "1234567"), "delete(\"1234567\", 0, 10)"); + check_string(s); + + fpcrtl_delete(s, 1, 1); + fail_if(strcmp(s.str, "234567"), "delete(\"1234567\", 1, 1)"); + check_string(s); + + fpcrtl_delete(s, 1, 100); + fail_if(strcmp(s.str, ""), "delete(\"234567\", 1, 100)"); + check_string(s); + + fpcrtl_delete(s2, 3, 2); + fail_if(strcmp(s2.str, "12567"), "delete(\"1234567\", 3, 2)"); + check_string(s2); + + fpcrtl_delete(s3, 3, 100); + fail_if(strcmp(s3.str, "12"), "delete(\"1234567\", 3, 100)"); + check_string(s3); + + } +END_TEST + +START_TEST (test_FloatToStr) + { + double s = 1.2345; + string255 t = fpcrtl_floatToStr(s); + printf("-----Entering test floatToStr-----\n"); + printf("FloatToStr(%f) = %s\n", s, t.str); + printf("-----Leaving test floatToStr-----\n"); + } +END_TEST + +START_TEST (test_random) + { + fpcrtl_randomize(); + printf("-----Entering test random-----\n"); + printf("random(5000) = %d\n", fpcrtl_random(5000)); + printf("random(1) = %d\n", fpcrtl_random(1)); + printf("random(2) = %d\n", fpcrtl_random(2)); + printf("-----Leaving test random-----\n"); + + } +END_TEST + +START_TEST (test_posS) + { + string255 substr1 = STRINIT("123"); + string255 str1 = STRINIT("12345"); + + string255 substr2 = STRINIT("45"); + string255 str2 = STRINIT("12345"); + + string255 substr3 = STRINIT(""); + string255 str3 = STRINIT("12345"); + + string255 substr4 = STRINIT("123"); + string255 str4 = STRINIT(""); + + string255 substr5 = STRINIT("123"); + string255 str5 = STRINIT("456"); + + fail_unless(fpcrtl_posS(substr1, str1) == 1, "pos(123, 12345)"); + fail_unless(fpcrtl_posS(substr2, str2) == 4, "pos(45, 12345)"); + fail_unless(fpcrtl_posS(substr3, str3) == 0, "pos(, 12345)"); + fail_unless(fpcrtl_posS(substr4, str4) == 0, "pos(123, )"); + fail_unless(fpcrtl_posS(substr5, str5) == 0, "pos(123, 456)"); + } +END_TEST + +START_TEST (test_trunc) + { + fail_unless(fpcrtl_trunc(123.456) == 123, "trunc(123.456)"); + fail_unless(fpcrtl_trunc(-123.456) == -123, "trunc(-123.456)"); + fail_unless(fpcrtl_trunc(12.3456) == 12, "trunc(12.3456)"); + fail_unless(fpcrtl_trunc(-12.3456) == -12, "trunc(-12.3456)"); + } +END_TEST + +START_TEST (test_odd) +{ + fail_unless(fpcrtl_odd(123) != 0, "odd(123)"); + fail_unless(fpcrtl_odd(124) == 0, "odd(124)"); + fail_unless(fpcrtl_odd(0) == 0, "odd(0)"); + fail_unless(fpcrtl_odd(-1) != 0, "odd(-1)"); + fail_unless(fpcrtl_odd(-2) == 0, "odd(-2)"); +} +END_TEST + +START_TEST (test_sqr) +{ + fail_unless(fpcrtl_sqr(0) == 0, "sqr(0)"); + fail_unless(fpcrtl_sqr(5) == 25, "sqr(5)"); + fail_unless(fpcrtl_sqr(-5) == 25, "sqr(-5)"); +} +END_TEST + +START_TEST (test_lowercase) +{ + string255 s1 = STRINIT(""); + string255 s2 = STRINIT("a"); + string255 s3 = STRINIT("abc"); + string255 t; + + t = fpcrtl_lowerCase(make_string("")); + fail_if(strcmp(t.str, s1.str), "lowerCase(\"\")"); + + t = fpcrtl_lowerCase(make_string("a")); + fail_if(strcmp(t.str, s2.str), "lowerCase(\"a\")"); + + t = fpcrtl_lowerCase(make_string("A")); + fail_if(strcmp(t.str, s2.str), "lowerCase(\"A\")"); + + t = fpcrtl_lowerCase(make_string("AbC")); + fail_if(strcmp(t.str, s3.str), "lowerCase(\"AbC\")"); + + t = fpcrtl_lowerCase(make_string("abc")); + fail_if(strcmp(t.str, s3.str), "lowerCase(\"abc\")"); +} +END_TEST + +START_TEST (test_str) +{ + int8_t a1 = -8; + uint8_t a2 = 8; + int16_t a3 = -13; + uint16_t a4 = 13; + int32_t a5 = -19; + uint32_t a6 = 22; + int64_t a7 = -199999999999999; + uint64_t a8 = 200000000000000; + + float a9 = 12345.6789; + double a10 = -9876.54321; + + string255 s; + + printf("-----Entering test str-----\n"); + + fpcrtl_str(a1, s); + printf("%d == %s\n", a1, s.str); + + fpcrtl_str(a2, s); + printf("%u == %s\n", a2, s.str); + + fpcrtl_str(a3, s); + printf("%d == %s\n", a3, s.str); + + fpcrtl_str(a4, s); + printf("%u == %s\n", a4, s.str); + + fpcrtl_str(a5, s); + printf("%d == %s\n", a5, s.str); + + fpcrtl_str(a6, s); + printf("%u == %s\n", a6, s.str); + + fpcrtl_str(a7, s); + printf("%lld == %s\n", a7, s.str); + + fpcrtl_str(a8, s); + printf("%llu == %s\n", a8, s.str); + + fpcrtl_str(a9, s); + printf("%f == %s\n", a9, s.str); + + fpcrtl_str(a10, s); + printf("%f == %s\n", a10, s.str); + + printf("-----Leaving test str------\n"); +} +END_TEST + +Suite* system_suite(void) +{ + Suite *s = suite_create("system"); + + TCase *tc_core = tcase_create("Core"); + + tcase_add_test(tc_core, test_copy); + tcase_add_test(tc_core, test_FloatToStr); + tcase_add_test(tc_core, test_random); + tcase_add_test(tc_core, test_posS); + tcase_add_test(tc_core, test_trunc); + tcase_add_test(tc_core, test_delete); + tcase_add_test(tc_core, test_odd); + tcase_add_test(tc_core, test_sqr); + tcase_add_test(tc_core, test_lowercase); + tcase_add_test(tc_core, test_str); + + suite_add_tcase(s, tc_core); + + return s; +} + diff -r 31570b766315 -r ed5a6478e710 project_files/hwc/rtl/tests/check_sysutils.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/hwc/rtl/tests/check_sysutils.c Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,80 @@ +#include +#include +#include +#include "check_check.h" +#include "../src/sysutils.h" + +static string255 make_string(const char* str) +{ + string255 s; + s.len = strlen(str); + memcpy(s.str, str, s.len + 1); + return s; +} + +static int is_string_equal(string255 s1, string255 s2) +{ + return (s1.len == s2.len) && (strcmp(s1.str, s2.str) == 0); +} + +START_TEST (test_trim) +{ + string255 t; + + t = fpcrtl_trim(make_string("")); + fail_if(strcmp(t.str, ""), "trim(\"\")"); + + t = fpcrtl_trim(make_string("ab")); + fail_if(strcmp(t.str, "ab"), "trim(\"ab\")"); + + t = fpcrtl_trim(make_string(" ")); + fail_if(strcmp(t.str, ""), "trim(\" \")"); + + t = fpcrtl_trim(make_string(" ")); + fail_if(strcmp(t.str, ""), "trim(\" \")"); + + t = fpcrtl_trim(make_string(" ab")); + fail_if(strcmp(t.str, "ab"), "trim(\" ab\")"); + + t = fpcrtl_trim(make_string("ab ")); + fail_if(strcmp(t.str, "ab"), "trim(\"ab \")"); + + t = fpcrtl_trim(make_string(" ab ")); + fail_if(strcmp(t.str, "ab"), "trim(\" ab \")"); + +} +END_TEST + +START_TEST (test_strToInt) +{ + fail_unless(fpcrtl_strToInt(make_string("123")) == 123, "strToInt(\"123\")"); + fail_unless(fpcrtl_strToInt(make_string("0")) == 0, "strToInt(\"0\")"); + fail_unless(fpcrtl_strToInt(make_string("-123")) == -123, "strToInt(\"-123\")"); +} +END_TEST + +START_TEST (test_extractFileName) +{ + fail_unless(is_string_equal(fpcrtl_extractFileName(make_string("abc")), make_string("abc")), "extractFileName(\"abc\")"); + fail_unless(is_string_equal(fpcrtl_extractFileName(make_string("a:abc")), make_string("abc")), "extractFileName(\"a:abc\")"); + fail_unless(is_string_equal(fpcrtl_extractFileName(make_string("/abc")), make_string("abc")), "extractFileName(\"/abc\")"); + fail_unless(is_string_equal(fpcrtl_extractFileName(make_string("\\abc")), make_string("abc")), "extractFileName(\"\\abc\")"); + fail_unless(is_string_equal(fpcrtl_extractFileName(make_string("/usr/bin/abc")), make_string("abc")), "extractFileName(\"/usr/bin/abc\")"); + fail_unless(is_string_equal(fpcrtl_extractFileName(make_string("c:\\def\\abc")), make_string("abc")), "extractFileName(\"c:\\def\\abc\")"); +} +END_TEST + +Suite* sysutils_suite(void) +{ + Suite *s = suite_create("sysutils"); + + TCase *tc_core = tcase_create("Core"); + + tcase_add_test(tc_core, test_trim); + tcase_add_test(tc_core, test_strToInt); + tcase_add_test(tc_core, test_extractFileName); + + suite_add_tcase(s, tc_core); + + return s; +} diff -r 31570b766315 -r ed5a6478e710 project_files/hwc/rtl/tests/fileio_test.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/hwc/rtl/tests/fileio_test.c Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,59 @@ + +#include "pas2c.h" + +#include "fpcrtl.h" + +char Pathz[1][128] = {"./"}; +int ptCurrTheme = 0; +cThemeCFGFilename = "theme.cfg"; +const string255 __str79 = STRINIT("object"); + +typedef struct __TResourceList { + Integer count; + string255 files[500 + 1]; +} TResourceList; + +TResourceList readThemeCfg_0() +{ + TResourceList readthemecfg_result; + string255 s; + string255 key; + TextFile f; + Integer i; + TResourceList result; + s = _strconcat(_strappend(Pathz[ptCurrTheme], '\x2f'), cThemeCFGFilename); + + assign(f, s); + FileMode = 0; + reset(f); + result.count = 0; + while(!eof(f)) + { + readLnS(f, s); + if((Length(s)) == (0)) + { + continue; + } + if((s.s[1]) == ('\x3b')) + { + continue; + } + i = pos('\x3d', s); + key = trim(copy(s, 1, i - 1)); + delete(s, 1, i); + if(_strcompare(key, __str79)) + { + i = pos('\x2c', s); + result.files[result.count] = _strconcat(_strappend(Pathz[ptCurrTheme], '\x2f'), trim(copy(s, 1, i - 1))); + ++result.count; + } + } + close(f); + readthemecfg_result = result; + return readthemecfg_result; +}; + +int main(int argc, char** argv) +{ + readThemeCfg_0(); +} diff -r 31570b766315 -r ed5a6478e710 project_files/hwc/rtl/tests/main.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/hwc/rtl/tests/main.c Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,80 @@ +#if 0 +#include +#include "fpcrtl.h" +#include "fileio.h" + +string255 t = STRINIT("test"); +string255 Pathz[1] = {STRINIT(".")}; +//int ptCurrTheme = 0; +string255 cThemeCFGFilename = STRINIT("theme.cfg"); +const string255 __str79 = STRINIT("object"); +string255 c1 = STRINIT("="); +string255 c2 = STRINIT("\x2c"); +string255 c3 = STRINIT("\x2f"); + +typedef struct __TResourceList { + Integer count; + string255 files[500 + 1]; +} TResourceList; + +TResourceList readThemeCfg_0() +{ + TResourceList readthemecfg_result; + string255 s; + string255 key; + TextFile f; + Integer i; + TResourceList result; + + int t = 0; + + s = _strconcat(_strappend(Pathz[ptCurrTheme], '\x2f'), cThemeCFGFilename); + + assign(&f, s); + + reset(&f); + + if (f.fp == NULL) { + readthemecfg_result.count = 0; + return readthemecfg_result; + } + + result.count = 0; + while (!eof(&f)) { + readLnS(&f, &s); + + if ((Length(s)) == (0)) { + continue; + } + if ((s.s[1]) == ('\x3b')) { + continue; + } + + i = pos(c1, s); + + key = fpcrtl_trim(fpcrtl_copy(s, 1, i - 1)); + + fpcrtl_delete(&s, 1, i); + + if (_strcompare(key, __str79)) { + i = pos(c2, s); + result.files[result.count] = _strconcat(_strappend(Pathz[ptCurrTheme], '\x2f'), trim(copy(s, 1, i - 1))); + ++result.count; + } + } + + close(&f); + readthemecfg_result = result; + return readthemecfg_result; +} + +int main(int argc, char** argv) +{ + int i; + + TResourceList result = readThemeCfg_0(); + for(i = 0; i < result.count; i++) { + printf("%s\n", result.files[i].str); + } +} +#endif diff -r 31570b766315 -r ed5a6478e710 share/CMakeLists.txt --- a/share/CMakeLists.txt Tue Nov 10 18:16:35 2015 +0100 +++ b/share/CMakeLists.txt Tue Nov 10 20:43:13 2015 +0100 @@ -8,19 +8,22 @@ #CFBundleShortVersionString is HEDGEWARS_VERSION #libav/ffmpeg always brings in VideoDecoderAcceleration, avaible only from 10.6.3 - if(${FFMPEG_FOUND} AND ${minimum_macosx_version} VERSION_EQUAL "10.6") + if(LIBAV_FOUND AND ${minimum_macosx_version} VERSION_EQUAL "10.6") set(minimum_macosx_version "10.6.3") endif() - configure_file(${hedgewars_SOURCE_DIR}/share/Info.plist.in + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.in ${CMAKE_CURRENT_BINARY_DIR}/Info.plist) #path here should be Hedgewars.app/Contents/MacOS install(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/Info.plist" DESTINATION ../) - install(PROGRAMS "${hedgewars_SOURCE_DIR}/share/Icon.icns" + install(PROGRAMS "${CMAKE_CURRENT_SOURCE_DIR}/Icon.icns" DESTINATION ../Resources/) - install(PROGRAMS "${hedgewars_SOURCE_DIR}/share/hwico.icns" + install(PROGRAMS "${CMAKE_CURRENT_SOURCE_DIR}/hwico.icns" DESTINATION ../Resources/) - install(PROGRAMS "${hedgewars_SOURCE_DIR}/share/dsa_pub.pem" + install(PROGRAMS "${CMAKE_CURRENT_SOURCE_DIR}/dsa_pub.pem" DESTINATION ../Resources/) -endif(APPLE) +elseif(UNIX) + install(PROGRAMS "${CMAKE_CURRENT_SOURCE_DIR}/hedgewars.appdata.xml" + DESTINATION ${CMAKE_INSTALL_PREFIX}/share/appdata/) +endif() diff -r 31570b766315 -r ed5a6478e710 share/Info.plist.in --- a/share/Info.plist.in Tue Nov 10 18:16:35 2015 +0100 +++ b/share/Info.plist.in Tue Nov 10 20:43:13 2015 +0100 @@ -23,7 +23,7 @@ CFBundleShortVersionString ${HEDGEWARS_VERSION} NSHumanReadableCopyright - Copyright © 2004-2012, Hedgewars Project + Copyright © 2004-2015, Hedgewars Project NSAppleScriptEnabled LSRequiresNativeExecution @@ -45,6 +45,8 @@ LSMinimumSystemVersion ${minimum_macosx_version} + NSHighResolutionCapable + True SUPublicDSAKeyFile dsa_pub.pem SUFeedURL diff -r 31570b766315 -r ed5a6478e710 share/hedgewars.appdata.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars.appdata.xml Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,32 @@ + + + hedgewars.desktop + GFDL + Hedgewars + Funny turn-based artillery game, featuring fighting Hedgehogs! + +

+ Hedgewars is a turn based strategy, artillery, action and comedy game, featuring the antics of pink hedgehogs with attitude as they battle from the depths of hell to the depths of space. +

+

+ As commander, it's your job to assemble your crack team of hedgehog soldiers and bring the war to your enemy. +

+

Game Features:

+
    +
  • Hilarious and strategic turn based combat for up to 8 players
  • +
  • Both local and network multiplayer, with optional AI opponentsBattle on an infinite number of randomly generated maps, with over 22 environments
  • +
  • Utilise 47 (and counting) devastating weapons!
  • +
  • Including the piano strike and explosive robotic cake
  • +
  • Play the game your way, with 18 different game modifiers, tweak almost every aspect of the match
  • +
  • Customize your team, with over 120 costumes, 30 graves, 12 forts, 100s of flags and unique voice packs
  • +
  • Huge battles with up to 48 hogs
  • +
  • Play both singleplayer and multiplayer minigames
  • +
  • Plugin your own custom maps, costumes, and other artwork
  • +
+
+ + http://www.hedgewars.org/files/9rzprpb.png + + http://hedgewars.org/ + hedgewars-dev@gna.org +
diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/CMakeLists.txt --- a/share/hedgewars/Data/CMakeLists.txt Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/CMakeLists.txt Tue Nov 10 20:43:13 2015 +0100 @@ -1,3 +1,20 @@ -foreach(dir "Fonts" "Forts" "Graphics" "Locale" "Maps" "Music" "Sounds" "Themes" "Missions" "Names" "misc" "Scripts") - add_subdirectory(${dir}) +foreach(dir + Fonts + Forts + Graphics + Locale + Maps + Missions + Music + Names + Scripts + Sounds + Themes + misc + ) + add_subdirectory(${dir}) endforeach(dir) + +if(${GL2}) + add_subdirectory(Shaders) +endif(${GL2}) diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Fonts/CMakeLists.txt --- a/share/hedgewars/Data/Fonts/CMakeLists.txt Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Fonts/CMakeLists.txt Tue Nov 10 20:43:13 2015 +0100 @@ -1,4 +1,26 @@ -install(FILES +set(FONTFILES DejaVuSans-Bold.ttf - wqy-zenhei.ttc - DESTINATION ${SHAREPATH}Data/Fonts) + wqy-zenhei.ttc) + +if (FONTS_DIRS) + foreach(fontfile ${FONTFILES}) + set(missing 1) + foreach(fontdir ${FONTS_DIRS}) + if (EXISTS "${fontdir}/${fontfile}") + message(STATUS "Fonts: Found ${fontfile} in ${fontdir}") + set(missing 0) + break() + endif() + endforeach(fontdir) + if(missing) + set(MISSINGFONTFILES ${MISSINGFONTFILES} ${fontfile}) + message(STATUS "Fonts: Could not find ${fontfile}, it will be installed") + endif() + endforeach(fontfile) +else() + set(MISSINGFONTFILES ${FONTFILES}) +endif() + +if (MISSINGFONTFILES) + install(FILES ${MISSINGFONTFILES} DESTINATION ${SHAREPATH}Data/Fonts) +endif() diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Fonts/DroidSansFallback.ttf Binary file share/hedgewars/Data/Fonts/DroidSansFallback.ttf has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Forts/Cake-icon.png Binary file share/hedgewars/Data/Forts/Cake-icon.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Forts/Cake-preview.png Binary file share/hedgewars/Data/Forts/Cake-preview.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Forts/CakeR.png Binary file share/hedgewars/Data/Forts/CakeR.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Forts/Castle-icon.png Binary file share/hedgewars/Data/Forts/Castle-icon.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Forts/Castle-preview.png Binary file share/hedgewars/Data/Forts/Castle-preview.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Forts/CastleR.png Binary file share/hedgewars/Data/Forts/CastleR.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Forts/Earth-icon.png Binary file share/hedgewars/Data/Forts/Earth-icon.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Forts/Earth-preview.png Binary file share/hedgewars/Data/Forts/Earth-preview.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Forts/EvilChicken-icon.png Binary file share/hedgewars/Data/Forts/EvilChicken-icon.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Forts/EvilChicken-preview.png Binary file share/hedgewars/Data/Forts/EvilChicken-preview.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Forts/EvilChickenR.png Binary file share/hedgewars/Data/Forts/EvilChickenR.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Forts/Flowerhog-icon.png Binary file share/hedgewars/Data/Forts/Flowerhog-icon.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Forts/Flowerhog-preview.png Binary file share/hedgewars/Data/Forts/Flowerhog-preview.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Forts/FlowerhogR.png Binary file share/hedgewars/Data/Forts/FlowerhogR.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Forts/Hydrant-icon.png Binary file share/hedgewars/Data/Forts/Hydrant-icon.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Forts/Hydrant-preview.png Binary file share/hedgewars/Data/Forts/Hydrant-preview.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Forts/HydrantR.png Binary file share/hedgewars/Data/Forts/HydrantR.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Forts/Lego-icon.png Binary file share/hedgewars/Data/Forts/Lego-icon.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Forts/Lego-preview.png Binary file share/hedgewars/Data/Forts/Lego-preview.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Forts/LegoR.png Binary file share/hedgewars/Data/Forts/LegoR.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Forts/Plane-icon.png Binary file share/hedgewars/Data/Forts/Plane-icon.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Forts/Plane-preview.png Binary file share/hedgewars/Data/Forts/Plane-preview.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Forts/PlaneR.png Binary file share/hedgewars/Data/Forts/PlaneR.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Forts/Statue-icon.png Binary file share/hedgewars/Data/Forts/Statue-icon.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Forts/Statue-preview.png Binary file share/hedgewars/Data/Forts/Statue-preview.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Forts/StatueR.png Binary file share/hedgewars/Data/Forts/StatueR.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Forts/SteelTowerR.png Binary file share/hedgewars/Data/Forts/SteelTowerR.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Forts/Tank-icon.png Binary file share/hedgewars/Data/Forts/Tank-icon.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Forts/Tank-preview.png Binary file share/hedgewars/Data/Forts/Tank-preview.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Forts/TankR.png Binary file share/hedgewars/Data/Forts/TankR.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Forts/UFO-icon.png Binary file share/hedgewars/Data/Forts/UFO-icon.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Forts/UFO-preview.png Binary file share/hedgewars/Data/Forts/UFO-preview.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Forts/UFOR.png Binary file share/hedgewars/Data/Forts/UFOR.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Forts/Wood-icon.png Binary file share/hedgewars/Data/Forts/Wood-icon.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Forts/Wood-preview.png Binary file share/hedgewars/Data/Forts/Wood-preview.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Forts/WoodR.png Binary file share/hedgewars/Data/Forts/WoodR.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/AirBomb.png Binary file share/hedgewars/Data/Graphics/AirBomb.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/AirMine.png Binary file share/hedgewars/Data/Graphics/AirMine.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/AmmoMenu/Ammos.png Binary file share/hedgewars/Data/Graphics/AmmoMenu/Ammos.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/AmmoMenu/Ammos_bw.png Binary file share/hedgewars/Data/Graphics/AmmoMenu/Ammos_bw.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/AmmoMenu/Corners.png Binary file share/hedgewars/Data/Graphics/AmmoMenu/Corners.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/AmmoMenu/Slot.png Binary file share/hedgewars/Data/Graphics/AmmoMenu/Slot.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/AmmoMenu/SlotKeys.png Binary file share/hedgewars/Data/Graphics/AmmoMenu/SlotKeys.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/AmmoMenu/TurnsLeft.png Binary file share/hedgewars/Data/Graphics/AmmoMenu/TurnsLeft.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Arrow.png Binary file share/hedgewars/Data/Graphics/Arrow.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/BazookaShell.png Binary file share/hedgewars/Data/Graphics/BazookaShell.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/BigExplosion.png Binary file share/hedgewars/Data/Graphics/BigExplosion.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/BlueWater.png Binary file share/hedgewars/Data/Graphics/BlueWater.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Bubbles.png Binary file share/hedgewars/Data/Graphics/Bubbles.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Cake_walk.png Binary file share/hedgewars/Data/Graphics/Cake_walk.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Case.png Binary file share/hedgewars/Data/Graphics/Case.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Censored.png Binary file share/hedgewars/Data/Graphics/Censored.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/ClBomb.png Binary file share/hedgewars/Data/Graphics/ClBomb.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/ClParticle.png Binary file share/hedgewars/Data/Graphics/ClParticle.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Cross.png Binary file share/hedgewars/Data/Graphics/Cross.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Crosshair.png Binary file share/hedgewars/Data/Graphics/Crosshair.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Drill.png Binary file share/hedgewars/Data/Graphics/Drill.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Droplet.png Binary file share/hedgewars/Data/Graphics/Droplet.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Egg.png Binary file share/hedgewars/Data/Graphics/Egg.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/ExplPart.png Binary file share/hedgewars/Data/Graphics/ExplPart.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/ExplPart2.png Binary file share/hedgewars/Data/Graphics/ExplPart2.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Feather.png Binary file share/hedgewars/Data/Graphics/Feather.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Finger.png Binary file share/hedgewars/Data/Graphics/Finger.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/FirstAid.png Binary file share/hedgewars/Data/Graphics/FirstAid.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/afghanistan.png Binary file share/hedgewars/Data/Graphics/Flags/afghanistan.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/albania.png Binary file share/hedgewars/Data/Graphics/Flags/albania.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/algeria.png Binary file share/hedgewars/Data/Graphics/Flags/algeria.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/american_samoa.png Binary file share/hedgewars/Data/Graphics/Flags/american_samoa.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/andorra.png Binary file share/hedgewars/Data/Graphics/Flags/andorra.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/angola.png Binary file share/hedgewars/Data/Graphics/Flags/angola.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/anguilla.png Binary file share/hedgewars/Data/Graphics/Flags/anguilla.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/antigua_and_barbuda.png Binary file share/hedgewars/Data/Graphics/Flags/antigua_and_barbuda.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/arabemirates.png Binary file share/hedgewars/Data/Graphics/Flags/arabemirates.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/argentina.png Binary file share/hedgewars/Data/Graphics/Flags/argentina.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/armenia.png Binary file share/hedgewars/Data/Graphics/Flags/armenia.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/aruba.png Binary file share/hedgewars/Data/Graphics/Flags/aruba.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/australia.png Binary file share/hedgewars/Data/Graphics/Flags/australia.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/austria.png Binary file share/hedgewars/Data/Graphics/Flags/austria.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/azerbaijan.png Binary file share/hedgewars/Data/Graphics/Flags/azerbaijan.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/bahamas.png Binary file share/hedgewars/Data/Graphics/Flags/bahamas.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/bahrain.png Binary file share/hedgewars/Data/Graphics/Flags/bahrain.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/bangladesh.png Binary file share/hedgewars/Data/Graphics/Flags/bangladesh.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/barbados.png Binary file share/hedgewars/Data/Graphics/Flags/barbados.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/belarus.png Binary file share/hedgewars/Data/Graphics/Flags/belarus.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/belgium.png Binary file share/hedgewars/Data/Graphics/Flags/belgium.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/belize.png Binary file share/hedgewars/Data/Graphics/Flags/belize.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/benin.png Binary file share/hedgewars/Data/Graphics/Flags/benin.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/bhutan.png Binary file share/hedgewars/Data/Graphics/Flags/bhutan.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/bolivia.png Binary file share/hedgewars/Data/Graphics/Flags/bolivia.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/bosnia_and_herzegovina.png Binary file share/hedgewars/Data/Graphics/Flags/bosnia_and_herzegovina.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/botswana.png Binary file share/hedgewars/Data/Graphics/Flags/botswana.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/brazil.png Binary file share/hedgewars/Data/Graphics/Flags/brazil.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/brunei.png Binary file share/hedgewars/Data/Graphics/Flags/brunei.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/bulgaria.png Binary file share/hedgewars/Data/Graphics/Flags/bulgaria.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/burkina_faso.png Binary file share/hedgewars/Data/Graphics/Flags/burkina_faso.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/burundi.png Binary file share/hedgewars/Data/Graphics/Flags/burundi.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cambodia.png Binary file share/hedgewars/Data/Graphics/Flags/cambodia.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cameroon.png Binary file share/hedgewars/Data/Graphics/Flags/cameroon.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/canada.png Binary file share/hedgewars/Data/Graphics/Flags/canada.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cape_verde.png Binary file share/hedgewars/Data/Graphics/Flags/cape_verde.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/central_african_republic.png Binary file share/hedgewars/Data/Graphics/Flags/central_african_republic.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/chad.png Binary file share/hedgewars/Data/Graphics/Flags/chad.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/chile.png Binary file share/hedgewars/Data/Graphics/Flags/chile.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/china.png Binary file share/hedgewars/Data/Graphics/Flags/china.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/christmas_island.png Binary file share/hedgewars/Data/Graphics/Flags/christmas_island.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_anarchy.png Binary file share/hedgewars/Data/Graphics/Flags/cm_anarchy.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_balls.png Binary file share/hedgewars/Data/Graphics/Flags/cm_balls.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_balrog.png Binary file share/hedgewars/Data/Graphics/Flags/cm_balrog.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_belarus.png Binary file share/hedgewars/Data/Graphics/Flags/cm_belarus.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_binary.png Binary file share/hedgewars/Data/Graphics/Flags/cm_binary.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_bloodyblade.png Binary file share/hedgewars/Data/Graphics/Flags/cm_bloodyblade.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_brittany.png Binary file share/hedgewars/Data/Graphics/Flags/cm_brittany.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_bubbles.png Binary file share/hedgewars/Data/Graphics/Flags/cm_bubbles.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_cheese.png Binary file share/hedgewars/Data/Graphics/Flags/cm_cheese.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_cog.png Binary file share/hedgewars/Data/Graphics/Flags/cm_cog.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_crossedswords.png Binary file share/hedgewars/Data/Graphics/Flags/cm_crossedswords.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_crosshair.png Binary file share/hedgewars/Data/Graphics/Flags/cm_crosshair.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_cyborg.png Binary file share/hedgewars/Data/Graphics/Flags/cm_cyborg.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_danger_fire.png Binary file share/hedgewars/Data/Graphics/Flags/cm_danger_fire.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_danger_stripes.png Binary file share/hedgewars/Data/Graphics/Flags/cm_danger_stripes.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_duckhead.png Binary file share/hedgewars/Data/Graphics/Flags/cm_duckhead.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_earth2.png Binary file share/hedgewars/Data/Graphics/Flags/cm_earth2.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_eyeofhorus.png Binary file share/hedgewars/Data/Graphics/Flags/cm_eyeofhorus.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_eyes.png Binary file share/hedgewars/Data/Graphics/Flags/cm_eyes.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_female.png Binary file share/hedgewars/Data/Graphics/Flags/cm_female.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_firstaid.png Binary file share/hedgewars/Data/Graphics/Flags/cm_firstaid.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_flames.png Binary file share/hedgewars/Data/Graphics/Flags/cm_flames.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_flower.png Binary file share/hedgewars/Data/Graphics/Flags/cm_flower.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_girder.png Binary file share/hedgewars/Data/Graphics/Flags/cm_girder.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_grenade.png Binary file share/hedgewars/Data/Graphics/Flags/cm_grenade.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_hax0r.png Binary file share/hedgewars/Data/Graphics/Flags/cm_hax0r.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_heart.png Binary file share/hedgewars/Data/Graphics/Flags/cm_heart.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_hellish.png Binary file share/hedgewars/Data/Graphics/Flags/cm_hellish.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_hw.png Binary file share/hedgewars/Data/Graphics/Flags/cm_hw.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_hw2.png Binary file share/hedgewars/Data/Graphics/Flags/cm_hw2.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_iluvu.png Binary file share/hedgewars/Data/Graphics/Flags/cm_iluvu.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_kiwi.png Binary file share/hedgewars/Data/Graphics/Flags/cm_kiwi.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_lips.png Binary file share/hedgewars/Data/Graphics/Flags/cm_lips.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_magicskull.png Binary file share/hedgewars/Data/Graphics/Flags/cm_magicskull.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_male.png Binary file share/hedgewars/Data/Graphics/Flags/cm_male.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_mog.png Binary file share/hedgewars/Data/Graphics/Flags/cm_mog.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_music.png Binary file share/hedgewars/Data/Graphics/Flags/cm_music.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_pacman.png Binary file share/hedgewars/Data/Graphics/Flags/cm_pacman.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_pacman2.png Binary file share/hedgewars/Data/Graphics/Flags/cm_pacman2.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_piet.png Binary file share/hedgewars/Data/Graphics/Flags/cm_piet.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_pirate.png Binary file share/hedgewars/Data/Graphics/Flags/cm_pirate.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_pokemon.png Binary file share/hedgewars/Data/Graphics/Flags/cm_pokemon.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_scout.png Binary file share/hedgewars/Data/Graphics/Flags/cm_scout.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_shoppa.png Binary file share/hedgewars/Data/Graphics/Flags/cm_shoppa.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_sine.png Binary file share/hedgewars/Data/Graphics/Flags/cm_sine.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_skull.png Binary file share/hedgewars/Data/Graphics/Flags/cm_skull.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_sonic.png Binary file share/hedgewars/Data/Graphics/Flags/cm_sonic.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_soviet.png Binary file share/hedgewars/Data/Graphics/Flags/cm_soviet.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_star.png Binary file share/hedgewars/Data/Graphics/Flags/cm_star.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_swordshield.png Binary file share/hedgewars/Data/Graphics/Flags/cm_swordshield.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_swordshield2.png Binary file share/hedgewars/Data/Graphics/Flags/cm_swordshield2.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_test.png Binary file share/hedgewars/Data/Graphics/Flags/cm_test.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_vampire.png Binary file share/hedgewars/Data/Graphics/Flags/cm_vampire.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_waves.png Binary file share/hedgewars/Data/Graphics/Flags/cm_waves.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cm_yinyang.png Binary file share/hedgewars/Data/Graphics/Flags/cm_yinyang.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/colombia.png Binary file share/hedgewars/Data/Graphics/Flags/colombia.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/comoros.png Binary file share/hedgewars/Data/Graphics/Flags/comoros.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/congo-brazzaville.png Binary file share/hedgewars/Data/Graphics/Flags/congo-brazzaville.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/congo_kinshasa.png Binary file share/hedgewars/Data/Graphics/Flags/congo_kinshasa.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cook_islands.png Binary file share/hedgewars/Data/Graphics/Flags/cook_islands.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/costa_rica.png Binary file share/hedgewars/Data/Graphics/Flags/costa_rica.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cote_divoire.png Binary file share/hedgewars/Data/Graphics/Flags/cote_divoire.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cpu.png Binary file share/hedgewars/Data/Graphics/Flags/cpu.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cpu_plain.png Binary file share/hedgewars/Data/Graphics/Flags/cpu_plain.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/croatia.png Binary file share/hedgewars/Data/Graphics/Flags/croatia.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cuba.png Binary file share/hedgewars/Data/Graphics/Flags/cuba.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/cyprus.png Binary file share/hedgewars/Data/Graphics/Flags/cyprus.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/czech_republic.png Binary file share/hedgewars/Data/Graphics/Flags/czech_republic.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/denmark.png Binary file share/hedgewars/Data/Graphics/Flags/denmark.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/djibouti.png Binary file share/hedgewars/Data/Graphics/Flags/djibouti.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/dominica.png Binary file share/hedgewars/Data/Graphics/Flags/dominica.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/dominican_republic.png Binary file share/hedgewars/Data/Graphics/Flags/dominican_republic.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/easttimor.png Binary file share/hedgewars/Data/Graphics/Flags/easttimor.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/ecuador.png Binary file share/hedgewars/Data/Graphics/Flags/ecuador.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/egypt.png Binary file share/hedgewars/Data/Graphics/Flags/egypt.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/el_salvador.png Binary file share/hedgewars/Data/Graphics/Flags/el_salvador.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/equatorial_guinea.png Binary file share/hedgewars/Data/Graphics/Flags/equatorial_guinea.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/eritrea.png Binary file share/hedgewars/Data/Graphics/Flags/eritrea.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/esperanto.png Binary file share/hedgewars/Data/Graphics/Flags/esperanto.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/estonia.png Binary file share/hedgewars/Data/Graphics/Flags/estonia.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/ethiopia.png Binary file share/hedgewars/Data/Graphics/Flags/ethiopia.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/europeanunion.png Binary file share/hedgewars/Data/Graphics/Flags/europeanunion.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/fiji.png Binary file share/hedgewars/Data/Graphics/Flags/fiji.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/finland.png Binary file share/hedgewars/Data/Graphics/Flags/finland.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/france.png Binary file share/hedgewars/Data/Graphics/Flags/france.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/gabon.png Binary file share/hedgewars/Data/Graphics/Flags/gabon.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/gambia.png Binary file share/hedgewars/Data/Graphics/Flags/gambia.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/georgia.png Binary file share/hedgewars/Data/Graphics/Flags/georgia.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/germany.png Binary file share/hedgewars/Data/Graphics/Flags/germany.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/ghana.png Binary file share/hedgewars/Data/Graphics/Flags/ghana.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/greece.png Binary file share/hedgewars/Data/Graphics/Flags/greece.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/grenada.png Binary file share/hedgewars/Data/Graphics/Flags/grenada.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/guam.png Binary file share/hedgewars/Data/Graphics/Flags/guam.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/guatemala.png Binary file share/hedgewars/Data/Graphics/Flags/guatemala.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/guinea.png Binary file share/hedgewars/Data/Graphics/Flags/guinea.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/guyana.png Binary file share/hedgewars/Data/Graphics/Flags/guyana.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/haiti.png Binary file share/hedgewars/Data/Graphics/Flags/haiti.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/hedgewars.png Binary file share/hedgewars/Data/Graphics/Flags/hedgewars.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/honduras.png Binary file share/hedgewars/Data/Graphics/Flags/honduras.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/hungary.png Binary file share/hedgewars/Data/Graphics/Flags/hungary.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/iceland.png Binary file share/hedgewars/Data/Graphics/Flags/iceland.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/india.png Binary file share/hedgewars/Data/Graphics/Flags/india.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/indonesia.png Binary file share/hedgewars/Data/Graphics/Flags/indonesia.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/iran.png Binary file share/hedgewars/Data/Graphics/Flags/iran.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/iraq.png Binary file share/hedgewars/Data/Graphics/Flags/iraq.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/ireland.png Binary file share/hedgewars/Data/Graphics/Flags/ireland.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/israel.png Binary file share/hedgewars/Data/Graphics/Flags/israel.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/italy.png Binary file share/hedgewars/Data/Graphics/Flags/italy.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/jamaica.png Binary file share/hedgewars/Data/Graphics/Flags/jamaica.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/japan.png Binary file share/hedgewars/Data/Graphics/Flags/japan.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/jordan.png Binary file share/hedgewars/Data/Graphics/Flags/jordan.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/kazakhstan.png Binary file share/hedgewars/Data/Graphics/Flags/kazakhstan.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/kenya.png Binary file share/hedgewars/Data/Graphics/Flags/kenya.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/kiribati.png Binary file share/hedgewars/Data/Graphics/Flags/kiribati.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/kuwait.png Binary file share/hedgewars/Data/Graphics/Flags/kuwait.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/kyrgyzstan.png Binary file share/hedgewars/Data/Graphics/Flags/kyrgyzstan.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/laos.png Binary file share/hedgewars/Data/Graphics/Flags/laos.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/latvia.png Binary file share/hedgewars/Data/Graphics/Flags/latvia.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/lebanon.png Binary file share/hedgewars/Data/Graphics/Flags/lebanon.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/lesotho.png Binary file share/hedgewars/Data/Graphics/Flags/lesotho.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/liberia.png Binary file share/hedgewars/Data/Graphics/Flags/liberia.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/libya.png Binary file share/hedgewars/Data/Graphics/Flags/libya.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/liechtenstein.png Binary file share/hedgewars/Data/Graphics/Flags/liechtenstein.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/lithuania.png Binary file share/hedgewars/Data/Graphics/Flags/lithuania.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/luxembourg.png Binary file share/hedgewars/Data/Graphics/Flags/luxembourg.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/macau.png Binary file share/hedgewars/Data/Graphics/Flags/macau.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/macedonia.png Binary file share/hedgewars/Data/Graphics/Flags/macedonia.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/madagascar.png Binary file share/hedgewars/Data/Graphics/Flags/madagascar.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/malawi.png Binary file share/hedgewars/Data/Graphics/Flags/malawi.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/malaysia.png Binary file share/hedgewars/Data/Graphics/Flags/malaysia.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/maldives.png Binary file share/hedgewars/Data/Graphics/Flags/maldives.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/mali.png Binary file share/hedgewars/Data/Graphics/Flags/mali.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/malta.png Binary file share/hedgewars/Data/Graphics/Flags/malta.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/marshall_islands.png Binary file share/hedgewars/Data/Graphics/Flags/marshall_islands.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/mauritania.png Binary file share/hedgewars/Data/Graphics/Flags/mauritania.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/mauritius.png Binary file share/hedgewars/Data/Graphics/Flags/mauritius.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/mexico.png Binary file share/hedgewars/Data/Graphics/Flags/mexico.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/micronesia.png Binary file share/hedgewars/Data/Graphics/Flags/micronesia.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/moldova.png Binary file share/hedgewars/Data/Graphics/Flags/moldova.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/monaco.png Binary file share/hedgewars/Data/Graphics/Flags/monaco.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/mongolia.png Binary file share/hedgewars/Data/Graphics/Flags/mongolia.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/montserrat.png Binary file share/hedgewars/Data/Graphics/Flags/montserrat.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/morocco.png Binary file share/hedgewars/Data/Graphics/Flags/morocco.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/mozambique.png Binary file share/hedgewars/Data/Graphics/Flags/mozambique.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/myanmar.png Binary file share/hedgewars/Data/Graphics/Flags/myanmar.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/namibia.png Binary file share/hedgewars/Data/Graphics/Flags/namibia.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/nauru.png Binary file share/hedgewars/Data/Graphics/Flags/nauru.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/nepal.png Binary file share/hedgewars/Data/Graphics/Flags/nepal.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/netherlands.png Binary file share/hedgewars/Data/Graphics/Flags/netherlands.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/new_zealand.png Binary file share/hedgewars/Data/Graphics/Flags/new_zealand.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/nicaragua.png Binary file share/hedgewars/Data/Graphics/Flags/nicaragua.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/niger.png Binary file share/hedgewars/Data/Graphics/Flags/niger.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/nigeria.png Binary file share/hedgewars/Data/Graphics/Flags/nigeria.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/niue.png Binary file share/hedgewars/Data/Graphics/Flags/niue.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/northern_mariana.png Binary file share/hedgewars/Data/Graphics/Flags/northern_mariana.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/northkorea.png Binary file share/hedgewars/Data/Graphics/Flags/northkorea.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/norway.png Binary file share/hedgewars/Data/Graphics/Flags/norway.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/oman.png Binary file share/hedgewars/Data/Graphics/Flags/oman.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/pakistan.png Binary file share/hedgewars/Data/Graphics/Flags/pakistan.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/palau.png Binary file share/hedgewars/Data/Graphics/Flags/palau.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/palestine.png Binary file share/hedgewars/Data/Graphics/Flags/palestine.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/panama.png Binary file share/hedgewars/Data/Graphics/Flags/panama.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/papua_new_guinea.png Binary file share/hedgewars/Data/Graphics/Flags/papua_new_guinea.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/paraguay.png Binary file share/hedgewars/Data/Graphics/Flags/paraguay.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/peru.png Binary file share/hedgewars/Data/Graphics/Flags/peru.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/philippines.png Binary file share/hedgewars/Data/Graphics/Flags/philippines.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/poland.png Binary file share/hedgewars/Data/Graphics/Flags/poland.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/portugal.png Binary file share/hedgewars/Data/Graphics/Flags/portugal.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/puerto_rico.png Binary file share/hedgewars/Data/Graphics/Flags/puerto_rico.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/qatar.png Binary file share/hedgewars/Data/Graphics/Flags/qatar.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/quebec.png Binary file share/hedgewars/Data/Graphics/Flags/quebec.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/romania.png Binary file share/hedgewars/Data/Graphics/Flags/romania.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/russian_federation.png Binary file share/hedgewars/Data/Graphics/Flags/russian_federation.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/rwanda.png Binary file share/hedgewars/Data/Graphics/Flags/rwanda.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/saint_kitts_and_nevis.png Binary file share/hedgewars/Data/Graphics/Flags/saint_kitts_and_nevis.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/saint_lucia.png Binary file share/hedgewars/Data/Graphics/Flags/saint_lucia.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/saint_vincent_and_the_grenadines.png Binary file share/hedgewars/Data/Graphics/Flags/saint_vincent_and_the_grenadines.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/samoa.png Binary file share/hedgewars/Data/Graphics/Flags/samoa.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/san_marino.png Binary file share/hedgewars/Data/Graphics/Flags/san_marino.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/saotomeandprincipe.png Binary file share/hedgewars/Data/Graphics/Flags/saotomeandprincipe.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/saudiarabia.png Binary file share/hedgewars/Data/Graphics/Flags/saudiarabia.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/senegal.png Binary file share/hedgewars/Data/Graphics/Flags/senegal.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/serbia_and_montenegro.png Binary file share/hedgewars/Data/Graphics/Flags/serbia_and_montenegro.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/seychelles.png Binary file share/hedgewars/Data/Graphics/Flags/seychelles.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/sicily.png Binary file share/hedgewars/Data/Graphics/Flags/sicily.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/sierra_leone.png Binary file share/hedgewars/Data/Graphics/Flags/sierra_leone.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/singapore.png Binary file share/hedgewars/Data/Graphics/Flags/singapore.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/slovakia.png Binary file share/hedgewars/Data/Graphics/Flags/slovakia.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/slovenia.png Binary file share/hedgewars/Data/Graphics/Flags/slovenia.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/solomon_islands.png Binary file share/hedgewars/Data/Graphics/Flags/solomon_islands.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/somalia.png Binary file share/hedgewars/Data/Graphics/Flags/somalia.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/south_africa.png Binary file share/hedgewars/Data/Graphics/Flags/south_africa.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/south_korea.png Binary file share/hedgewars/Data/Graphics/Flags/south_korea.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/south_sudan.png Binary file share/hedgewars/Data/Graphics/Flags/south_sudan.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/spain.png Binary file share/hedgewars/Data/Graphics/Flags/spain.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/sri_lanka.png Binary file share/hedgewars/Data/Graphics/Flags/sri_lanka.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/sudan.png Binary file share/hedgewars/Data/Graphics/Flags/sudan.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/suisse.png Binary file share/hedgewars/Data/Graphics/Flags/suisse.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/suriname.png Binary file share/hedgewars/Data/Graphics/Flags/suriname.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/swaziland.png Binary file share/hedgewars/Data/Graphics/Flags/swaziland.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/sweden.png Binary file share/hedgewars/Data/Graphics/Flags/sweden.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/syrian_arab_republic.png Binary file share/hedgewars/Data/Graphics/Flags/syrian_arab_republic.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/taiwan.png Binary file share/hedgewars/Data/Graphics/Flags/taiwan.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/tajikistan.png Binary file share/hedgewars/Data/Graphics/Flags/tajikistan.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/tanzania.png Binary file share/hedgewars/Data/Graphics/Flags/tanzania.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/thailand.png Binary file share/hedgewars/Data/Graphics/Flags/thailand.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/tibet.png Binary file share/hedgewars/Data/Graphics/Flags/tibet.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/timor_leste.png Binary file share/hedgewars/Data/Graphics/Flags/timor_leste.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/togo.png Binary file share/hedgewars/Data/Graphics/Flags/togo.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/tokelau.png Binary file share/hedgewars/Data/Graphics/Flags/tokelau.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/tonga.png Binary file share/hedgewars/Data/Graphics/Flags/tonga.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/trinidad_and_tobago.png Binary file share/hedgewars/Data/Graphics/Flags/trinidad_and_tobago.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/tunisia.png Binary file share/hedgewars/Data/Graphics/Flags/tunisia.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/turkey.png Binary file share/hedgewars/Data/Graphics/Flags/turkey.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/turkmenistan.png Binary file share/hedgewars/Data/Graphics/Flags/turkmenistan.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/tuvalu.png Binary file share/hedgewars/Data/Graphics/Flags/tuvalu.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/uganda.png Binary file share/hedgewars/Data/Graphics/Flags/uganda.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/ukraine.png Binary file share/hedgewars/Data/Graphics/Flags/ukraine.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/united_arab_emirates.png Binary file share/hedgewars/Data/Graphics/Flags/united_arab_emirates.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/united_kingdom.png Binary file share/hedgewars/Data/Graphics/Flags/united_kingdom.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/united_states.png Binary file share/hedgewars/Data/Graphics/Flags/united_states.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/uruguay.png Binary file share/hedgewars/Data/Graphics/Flags/uruguay.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/uzbekistan.png Binary file share/hedgewars/Data/Graphics/Flags/uzbekistan.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/vanuatu.png Binary file share/hedgewars/Data/Graphics/Flags/vanuatu.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/vatican.png Binary file share/hedgewars/Data/Graphics/Flags/vatican.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/venezuela.png Binary file share/hedgewars/Data/Graphics/Flags/venezuela.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/vietnam.png Binary file share/hedgewars/Data/Graphics/Flags/vietnam.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/western_sahara.png Binary file share/hedgewars/Data/Graphics/Flags/western_sahara.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/yemen.png Binary file share/hedgewars/Data/Graphics/Flags/yemen.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/yugoslavia.png Binary file share/hedgewars/Data/Graphics/Flags/yugoslavia.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/zambia.png Binary file share/hedgewars/Data/Graphics/Flags/zambia.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flags/zimbabwe.png Binary file share/hedgewars/Data/Graphics/Flags/zimbabwe.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Flame.png Binary file share/hedgewars/Data/Graphics/Flame.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Frame.png Binary file share/hedgewars/Data/Graphics/Frame.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Girder.png Binary file share/hedgewars/Data/Graphics/Girder.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Graves/Bone.png Binary file share/hedgewars/Data/Graphics/Graves/Bone.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Graves/Cherry.png Binary file share/hedgewars/Data/Graphics/Graves/Cherry.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Graves/Flower.png Binary file share/hedgewars/Data/Graphics/Graves/Flower.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Graves/Grave.png Binary file share/hedgewars/Data/Graphics/Graves/Grave.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Graves/Plinko.png Binary file share/hedgewars/Data/Graphics/Graves/Plinko.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Graves/Rip.png Binary file share/hedgewars/Data/Graphics/Graves/Rip.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Graves/Rubberduck.png Binary file share/hedgewars/Data/Graphics/Graves/Rubberduck.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Graves/Simple.png Binary file share/hedgewars/Data/Graphics/Graves/Simple.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Graves/Statue.png Binary file share/hedgewars/Data/Graphics/Graves/Statue.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Graves/bp2.png Binary file share/hedgewars/Data/Graphics/Graves/bp2.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Graves/coffin.png Binary file share/hedgewars/Data/Graphics/Graves/coffin.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Graves/deadhog.png Binary file share/hedgewars/Data/Graphics/Graves/deadhog.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Graves/eyecross.png Binary file share/hedgewars/Data/Graphics/Graves/eyecross.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Graves/money.png Binary file share/hedgewars/Data/Graphics/Graves/money.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Graves/pokeball.png Binary file share/hedgewars/Data/Graphics/Graves/pokeball.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Graves/star.png Binary file share/hedgewars/Data/Graphics/Graves/star.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/HHDeath.png Binary file share/hedgewars/Data/Graphics/HHDeath.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hammer.png Binary file share/hedgewars/Data/Graphics/Hammer.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/4gsuif.png Binary file share/hedgewars/Data/Graphics/Hats/4gsuif.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/AkuAku.png Binary file share/hedgewars/Data/Graphics/Hats/AkuAku.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/Bandit.png Binary file share/hedgewars/Data/Graphics/Hats/Bandit.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/Coonskin3.png Binary file share/hedgewars/Data/Graphics/Hats/Coonskin3.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/Cowboy.png Binary file share/hedgewars/Data/Graphics/Hats/Cowboy.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/Disguise.png Binary file share/hedgewars/Data/Graphics/Hats/Disguise.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/Einstein.png Binary file share/hedgewars/Data/Graphics/Hats/Einstein.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/Elvis.png Binary file share/hedgewars/Data/Graphics/Hats/Elvis.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/Gasmask.png Binary file share/hedgewars/Data/Graphics/Hats/Gasmask.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/Glasses.png Binary file share/hedgewars/Data/Graphics/Hats/Glasses.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/HogInTheHat.png Binary file share/hedgewars/Data/Graphics/Hats/HogInTheHat.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/Jason.png Binary file share/hedgewars/Data/Graphics/Hats/Jason.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/MegaHogX.png Binary file share/hedgewars/Data/Graphics/Hats/MegaHogX.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/Meteorhelmet.png Binary file share/hedgewars/Data/Graphics/Hats/Meteorhelmet.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/NinjaFull.png Binary file share/hedgewars/Data/Graphics/Hats/NinjaFull.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/NinjaStraight.png Binary file share/hedgewars/Data/Graphics/Hats/NinjaStraight.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/NinjaTriangle.png Binary file share/hedgewars/Data/Graphics/Hats/NinjaTriangle.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/NoHat.png Binary file share/hedgewars/Data/Graphics/Hats/NoHat.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/OldMan.png Binary file share/hedgewars/Data/Graphics/Hats/OldMan.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/Plunger.png Binary file share/hedgewars/Data/Graphics/Hats/Plunger.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/RSR.png Binary file share/hedgewars/Data/Graphics/Hats/RSR.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/Rain.png Binary file share/hedgewars/Data/Graphics/Hats/Rain.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/Reserved/c2fb2dd15ec2ff9a332462ab19cfac4doldskool.png Binary file share/hedgewars/Data/Graphics/Hats/Reserved/c2fb2dd15ec2ff9a332462ab19cfac4doldskool.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/Reserved/chef.png Binary file share/hedgewars/Data/Graphics/Hats/Reserved/chef.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/Reserved/e587f6146ebfbdefdc028c591643f220alwayss.png Binary file share/hedgewars/Data/Graphics/Hats/Reserved/e587f6146ebfbdefdc028c591643f220alwayss.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/RobinHood.png Binary file share/hedgewars/Data/Graphics/Hats/RobinHood.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/Samurai.png Binary file share/hedgewars/Data/Graphics/Hats/Samurai.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/Santa.png Binary file share/hedgewars/Data/Graphics/Hats/Santa.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/ShortHair_Black.png Binary file share/hedgewars/Data/Graphics/Hats/ShortHair_Black.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/ShortHair_Brown.png Binary file share/hedgewars/Data/Graphics/Hats/ShortHair_Brown.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/ShortHair_Grey.png Binary file share/hedgewars/Data/Graphics/Hats/ShortHair_Grey.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/ShortHair_Red.png Binary file share/hedgewars/Data/Graphics/Hats/ShortHair_Red.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/ShortHair_Yellow.png Binary file share/hedgewars/Data/Graphics/Hats/ShortHair_Yellow.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/Skull.png Binary file share/hedgewars/Data/Graphics/Hats/Skull.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/StrawHat.png Binary file share/hedgewars/Data/Graphics/Hats/StrawHat.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/Sunglasses.png Binary file share/hedgewars/Data/Graphics/Hats/Sunglasses.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/TeamHeadband.png Binary file share/hedgewars/Data/Graphics/Hats/TeamHeadband.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/TeamSoldier.png Binary file share/hedgewars/Data/Graphics/Hats/TeamSoldier.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/TeamTophat.png Binary file share/hedgewars/Data/Graphics/Hats/TeamTophat.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/TeamWheatley.png Binary file share/hedgewars/Data/Graphics/Hats/TeamWheatley.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/Terminator_Glasses.png Binary file share/hedgewars/Data/Graphics/Hats/Terminator_Glasses.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/Viking.png Binary file share/hedgewars/Data/Graphics/Hats/Viking.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/WhySoSerious.png Binary file share/hedgewars/Data/Graphics/Hats/WhySoSerious.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/WizardHat.png Binary file share/hedgewars/Data/Graphics/Hats/WizardHat.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/android.png Binary file share/hedgewars/Data/Graphics/Hats/android.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/angel.png Binary file share/hedgewars/Data/Graphics/Hats/angel.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/anzac.png Binary file share/hedgewars/Data/Graphics/Hats/anzac.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/bb_bub.png Binary file share/hedgewars/Data/Graphics/Hats/bb_bub.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/bb_cororon.png Binary file share/hedgewars/Data/Graphics/Hats/bb_cororon.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/bb_kululun.png Binary file share/hedgewars/Data/Graphics/Hats/bb_kululun.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/beefeater.png Binary file share/hedgewars/Data/Graphics/Hats/beefeater.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/bushhider.png Binary file share/hedgewars/Data/Graphics/Hats/bushhider.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/cap_blue.png Binary file share/hedgewars/Data/Graphics/Hats/cap_blue.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/cap_green.png Binary file share/hedgewars/Data/Graphics/Hats/cap_green.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/cap_junior.png Binary file share/hedgewars/Data/Graphics/Hats/cap_junior.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/cap_red.png Binary file share/hedgewars/Data/Graphics/Hats/cap_red.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/cap_team.png Binary file share/hedgewars/Data/Graphics/Hats/cap_team.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/cap_thinking.png Binary file share/hedgewars/Data/Graphics/Hats/cap_thinking.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/cap_yellow.png Binary file share/hedgewars/Data/Graphics/Hats/cap_yellow.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/chef.png Binary file share/hedgewars/Data/Graphics/Hats/chef.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/chuckl.png Binary file share/hedgewars/Data/Graphics/Hats/chuckl.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/constructor.png Binary file share/hedgewars/Data/Graphics/Hats/constructor.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/cratehider.png Binary file share/hedgewars/Data/Graphics/Hats/cratehider.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/crown.png Binary file share/hedgewars/Data/Graphics/Hats/crown.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/cyclops.png Binary file share/hedgewars/Data/Graphics/Hats/cyclops.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/dish_Ladle.png Binary file share/hedgewars/Data/Graphics/Hats/dish_Ladle.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/dish_SauceBoatSilver.png Binary file share/hedgewars/Data/Graphics/Hats/dish_SauceBoatSilver.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/doctor.png Binary file share/hedgewars/Data/Graphics/Hats/doctor.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/dwarf.png Binary file share/hedgewars/Data/Graphics/Hats/dwarf.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/eastertop.png Binary file share/hedgewars/Data/Graphics/Hats/eastertop.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/fr_apple.png Binary file share/hedgewars/Data/Graphics/Hats/fr_apple.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/fr_lemon.png Binary file share/hedgewars/Data/Graphics/Hats/fr_lemon.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/fr_pumpkin.png Binary file share/hedgewars/Data/Graphics/Hats/fr_pumpkin.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/fr_tomato.png Binary file share/hedgewars/Data/Graphics/Hats/fr_tomato.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/fr_tomato.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Graphics/Hats/fr_tomato.svg Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,2210 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/hair_blue.png Binary file share/hedgewars/Data/Graphics/Hats/hair_blue.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/hair_green.png Binary file share/hedgewars/Data/Graphics/Hats/hair_green.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/hair_grey.png Binary file share/hedgewars/Data/Graphics/Hats/hair_grey.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/hair_orange.png Binary file share/hedgewars/Data/Graphics/Hats/hair_orange.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/hair_pink.png Binary file share/hedgewars/Data/Graphics/Hats/hair_pink.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/hair_purple.png Binary file share/hedgewars/Data/Graphics/Hats/hair_purple.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/hair_red.png Binary file share/hedgewars/Data/Graphics/Hats/hair_red.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/hair_team.png Binary file share/hedgewars/Data/Graphics/Hats/hair_team.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/hair_yellow.png Binary file share/hedgewars/Data/Graphics/Hats/hair_yellow.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/knight.png Binary file share/hedgewars/Data/Graphics/Hats/knight.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/lambda.png Binary file share/hedgewars/Data/Graphics/Hats/lambda.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/laurel.png Binary file share/hedgewars/Data/Graphics/Hats/laurel.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/metalband.png Binary file share/hedgewars/Data/Graphics/Hats/metalband.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/mickey_ears.png Binary file share/hedgewars/Data/Graphics/Hats/mickey_ears.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/mp3.png Binary file share/hedgewars/Data/Graphics/Hats/mp3.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/mv_Spidey.png Binary file share/hedgewars/Data/Graphics/Hats/mv_Spidey.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/ntd_Falcon.png Binary file share/hedgewars/Data/Graphics/Hats/ntd_Falcon.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/ntd_Kirby.png Binary file share/hedgewars/Data/Graphics/Hats/ntd_Kirby.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/ntd_Samus.png Binary file share/hedgewars/Data/Graphics/Hats/ntd_Samus.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/nurse.png Binary file share/hedgewars/Data/Graphics/Hats/nurse.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/pinksunhat.png Binary file share/hedgewars/Data/Graphics/Hats/pinksunhat.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/pirate_jack.png Binary file share/hedgewars/Data/Graphics/Hats/pirate_jack.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/pirate_jack_bandana.png Binary file share/hedgewars/Data/Graphics/Hats/pirate_jack_bandana.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/poke_ash.png Binary file share/hedgewars/Data/Graphics/Hats/poke_ash.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/poke_charmander.png Binary file share/hedgewars/Data/Graphics/Hats/poke_charmander.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/poke_chikorita.png Binary file share/hedgewars/Data/Graphics/Hats/poke_chikorita.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/poke_jigglypuff.png Binary file share/hedgewars/Data/Graphics/Hats/poke_jigglypuff.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/poke_lugia.png Binary file share/hedgewars/Data/Graphics/Hats/poke_lugia.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/poke_mudkip.png Binary file share/hedgewars/Data/Graphics/Hats/poke_mudkip.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/poke_squirtle.png Binary file share/hedgewars/Data/Graphics/Hats/poke_squirtle.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/poke_voltorb.png Binary file share/hedgewars/Data/Graphics/Hats/poke_voltorb.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/policecap.png Binary file share/hedgewars/Data/Graphics/Hats/policecap.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/policegirl.png Binary file share/hedgewars/Data/Graphics/Hats/policegirl.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/punkman.png Binary file share/hedgewars/Data/Graphics/Hats/punkman.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/quotecap.png Binary file share/hedgewars/Data/Graphics/Hats/quotecap.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/scif_2001O.png Binary file share/hedgewars/Data/Graphics/Hats/scif_2001O.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/scif_2001Y.png Binary file share/hedgewars/Data/Graphics/Hats/scif_2001Y.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/scif_Geordi.png Binary file share/hedgewars/Data/Graphics/Hats/scif_Geordi.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/scif_SparkssHelmet.png Binary file share/hedgewars/Data/Graphics/Hats/scif_SparkssHelmet.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/scif_cosmonaut.png Binary file share/hedgewars/Data/Graphics/Hats/scif_cosmonaut.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/scif_cyberpunk.png Binary file share/hedgewars/Data/Graphics/Hats/scif_cyberpunk.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/sf_honda.png Binary file share/hedgewars/Data/Graphics/Hats/sf_honda.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/sf_ryu.png Binary file share/hedgewars/Data/Graphics/Hats/sf_ryu.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/sm_luigi.png Binary file share/hedgewars/Data/Graphics/Hats/sm_luigi.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/sm_mario.png Binary file share/hedgewars/Data/Graphics/Hats/sm_mario.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/sm_toad.png Binary file share/hedgewars/Data/Graphics/Hats/sm_toad.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/snorkel.png Binary file share/hedgewars/Data/Graphics/Hats/snorkel.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/snowhog.png Binary file share/hedgewars/Data/Graphics/Hats/snowhog.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/spcartman.png Binary file share/hedgewars/Data/Graphics/Hats/spcartman.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/spkenny.png Binary file share/hedgewars/Data/Graphics/Hats/spkenny.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/spkyle.png Binary file share/hedgewars/Data/Graphics/Hats/spkyle.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/spstan.png Binary file share/hedgewars/Data/Graphics/Hats/spstan.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/sth_SonicClassic.png Binary file share/hedgewars/Data/Graphics/Hats/sth_SonicClassic.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/sth_Super.png Binary file share/hedgewars/Data/Graphics/Hats/sth_Super.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/tf_demoman.png Binary file share/hedgewars/Data/Graphics/Hats/tf_demoman.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/tf_scount.png Binary file share/hedgewars/Data/Graphics/Hats/tf_scount.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/tophats.png Binary file share/hedgewars/Data/Graphics/Hats/tophats.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/touhou_chen.png Binary file share/hedgewars/Data/Graphics/Hats/touhou_chen.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/touhou_marisa.png Binary file share/hedgewars/Data/Graphics/Hats/touhou_marisa.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/touhou_patchouli.png Binary file share/hedgewars/Data/Graphics/Hats/touhou_patchouli.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/touhou_remelia.png Binary file share/hedgewars/Data/Graphics/Hats/touhou_remelia.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/touhou_suwako.png Binary file share/hedgewars/Data/Graphics/Hats/touhou_suwako.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/touhou_yukari.png Binary file share/hedgewars/Data/Graphics/Hats/touhou_yukari.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/ushanka.png Binary file share/hedgewars/Data/Graphics/Hats/ushanka.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/vampirichog.png Binary file share/hedgewars/Data/Graphics/Hats/vampirichog.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/vc_gakupo.png Binary file share/hedgewars/Data/Graphics/Hats/vc_gakupo.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/vc_gumi.png Binary file share/hedgewars/Data/Graphics/Hats/vc_gumi.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/vc_kaito.png Binary file share/hedgewars/Data/Graphics/Hats/vc_kaito.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/vc_len.png Binary file share/hedgewars/Data/Graphics/Hats/vc_len.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/vc_luka.png Binary file share/hedgewars/Data/Graphics/Hats/vc_luka.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/vc_meiko.png Binary file share/hedgewars/Data/Graphics/Hats/vc_meiko.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/vc_miku.png Binary file share/hedgewars/Data/Graphics/Hats/vc_miku.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/vc_rin.png Binary file share/hedgewars/Data/Graphics/Hats/vc_rin.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/war_UNPeacekeeper01.png Binary file share/hedgewars/Data/Graphics/Hats/war_UNPeacekeeper01.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/war_UNPeacekeeper02.png Binary file share/hedgewars/Data/Graphics/Hats/war_UNPeacekeeper02.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/war_americanww2helmet.png Binary file share/hedgewars/Data/Graphics/Hats/war_americanww2helmet.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/war_britpthhelmet.png Binary file share/hedgewars/Data/Graphics/Hats/war_britpthhelmet.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/war_frenchww1helmet.png Binary file share/hedgewars/Data/Graphics/Hats/war_frenchww1helmet.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/war_grenadier1.png Binary file share/hedgewars/Data/Graphics/Hats/war_grenadier1.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/zoo_Bat.png Binary file share/hedgewars/Data/Graphics/Hats/zoo_Bat.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/zoo_Beaver.png Binary file share/hedgewars/Data/Graphics/Hats/zoo_Beaver.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/zoo_Bunny.png Binary file share/hedgewars/Data/Graphics/Hats/zoo_Bunny.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/zoo_Deer.png Binary file share/hedgewars/Data/Graphics/Hats/zoo_Deer.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/zoo_Hedgehog.png Binary file share/hedgewars/Data/Graphics/Hats/zoo_Hedgehog.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/zoo_Moose.png Binary file share/hedgewars/Data/Graphics/Hats/zoo_Moose.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/zoo_Porkey.png Binary file share/hedgewars/Data/Graphics/Hats/zoo_Porkey.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hats/zoo_Sheep.png Binary file share/hedgewars/Data/Graphics/Hats/zoo_Sheep.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Health.png Binary file share/hedgewars/Data/Graphics/Health.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hedgehog/Idle.png Binary file share/hedgewars/Data/Graphics/Hedgehog/Idle.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hedgehog/ShoutCorner.png Binary file share/hedgewars/Data/Graphics/Hedgehog/ShoutCorner.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hedgehog/ShoutEdge.png Binary file share/hedgewars/Data/Graphics/Hedgehog/ShoutEdge.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hedgehog/ShoutTail.png Binary file share/hedgewars/Data/Graphics/Hedgehog/ShoutTail.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hedgehog/SpeechCorner.png Binary file share/hedgewars/Data/Graphics/Hedgehog/SpeechCorner.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hedgehog/SpeechEdge.png Binary file share/hedgewars/Data/Graphics/Hedgehog/SpeechEdge.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hedgehog/SpeechTail.png Binary file share/hedgewars/Data/Graphics/Hedgehog/SpeechTail.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hedgehog/ThoughtCorner.png Binary file share/hedgewars/Data/Graphics/Hedgehog/ThoughtCorner.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hedgehog/ThoughtEdge.png Binary file share/hedgewars/Data/Graphics/Hedgehog/ThoughtEdge.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hedgehog/ThoughtTail.png Binary file share/hedgewars/Data/Graphics/Hedgehog/ThoughtTail.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hedgehog/Vampiric.png Binary file share/hedgewars/Data/Graphics/Hedgehog/Vampiric.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hedgehog/Wave.png Binary file share/hedgewars/Data/Graphics/Hedgehog/Wave.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hedgehog/amAirMine.png Binary file share/hedgewars/Data/Graphics/Hedgehog/amAirMine.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hedgehog/amBTorch_i.png Binary file share/hedgewars/Data/Graphics/Hedgehog/amBTorch_i.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hedgehog/amBTorch_w.png Binary file share/hedgewars/Data/Graphics/Hedgehog/amBTorch_w.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hedgehog/amBallgun.png Binary file share/hedgewars/Data/Graphics/Hedgehog/amBallgun.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hedgehog/amBaseball.png Binary file share/hedgewars/Data/Graphics/Hedgehog/amBaseball.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hedgehog/amBazooka.png Binary file share/hedgewars/Data/Graphics/Hedgehog/amBazooka.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hedgehog/amBee.png Binary file share/hedgewars/Data/Graphics/Hedgehog/amBee.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hedgehog/amCake.png Binary file share/hedgewars/Data/Graphics/Hedgehog/amCake.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hedgehog/amCheese.png Binary file share/hedgewars/Data/Graphics/Hedgehog/amCheese.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hedgehog/amCluster.png Binary file share/hedgewars/Data/Graphics/Hedgehog/amCluster.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hedgehog/amConstruction.png Binary file share/hedgewars/Data/Graphics/Hedgehog/amConstruction.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hedgehog/amDEagle.png Binary file share/hedgewars/Data/Graphics/Hedgehog/amDEagle.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hedgehog/amDEagle_w.png Binary file share/hedgewars/Data/Graphics/Hedgehog/amDEagle_w.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hedgehog/amDynamite.png Binary file share/hedgewars/Data/Graphics/Hedgehog/amDynamite.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hedgehog/amFlamethrower.png Binary file share/hedgewars/Data/Graphics/Hedgehog/amFlamethrower.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hedgehog/amFrozenHog.png Binary file share/hedgewars/Data/Graphics/Hedgehog/amFrozenHog.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hedgehog/amGrenade.png Binary file share/hedgewars/Data/Graphics/Hedgehog/amGrenade.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hedgehog/amHellish.png Binary file share/hedgewars/Data/Graphics/Hedgehog/amHellish.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hedgehog/amKnife.png Binary file share/hedgewars/Data/Graphics/Hedgehog/amKnife.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hedgehog/amMelon.png Binary file share/hedgewars/Data/Graphics/Hedgehog/amMelon.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hedgehog/amMine.png Binary file share/hedgewars/Data/Graphics/Hedgehog/amMine.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hedgehog/amMortar.png Binary file share/hedgewars/Data/Graphics/Hedgehog/amMortar.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hedgehog/amPortalGun.png Binary file share/hedgewars/Data/Graphics/Hedgehog/amPortalGun.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hedgehog/amResurrector.png Binary file share/hedgewars/Data/Graphics/Hedgehog/amResurrector.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hedgehog/amSMine.png Binary file share/hedgewars/Data/Graphics/Hedgehog/amSMine.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hedgehog/amSeduction.png Binary file share/hedgewars/Data/Graphics/Hedgehog/amSeduction.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hedgehog/amShotgun.png Binary file share/hedgewars/Data/Graphics/Hedgehog/amShotgun.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hedgehog/amShotgun_w.png Binary file share/hedgewars/Data/Graphics/Hedgehog/amShotgun_w.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hedgehog/amSkip.png Binary file share/hedgewars/Data/Graphics/Hedgehog/amSkip.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hedgehog/amSniperRifle.png Binary file share/hedgewars/Data/Graphics/Hedgehog/amSniperRifle.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hedgehog/amSnowball.png Binary file share/hedgewars/Data/Graphics/Hedgehog/amSnowball.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hedgehog/amVamp.png Binary file share/hedgewars/Data/Graphics/Hedgehog/amVamp.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Hedgehog/hh_small.png Binary file share/hedgewars/Data/Graphics/Hedgehog/hh_small.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/HellishBomb.png Binary file share/hedgewars/Data/Graphics/HellishBomb.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/LandIce.png Binary file share/hedgewars/Data/Graphics/LandIce.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/MineDead.png Binary file share/hedgewars/Data/Graphics/MineDead.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/MineOff.png Binary file share/hedgewars/Data/Graphics/MineOff.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/MineOn.png Binary file share/hedgewars/Data/Graphics/MineOn.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Missions/Training/Challenge_-_Speed_Shoppa_-_Hedgelove@2x.png Binary file share/hedgewars/Data/Graphics/Missions/Training/Challenge_-_Speed_Shoppa_-_Hedgelove@2x.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Missions/Training/Challenge_-_Speed_Shoppa_-_Ropes@2x.png Binary file share/hedgewars/Data/Graphics/Missions/Training/Challenge_-_Speed_Shoppa_-_Ropes@2x.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Missions/Training/Challenge_-_Speed_Shoppa_-_ShoppaKing@2x.png Binary file share/hedgewars/Data/Graphics/Missions/Training/Challenge_-_Speed_Shoppa_-_ShoppaKing@2x.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Missions/Training/ClimbHome.png Binary file share/hedgewars/Data/Graphics/Missions/Training/ClimbHome.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Missions/Training/ClimbHome@2x.png Binary file share/hedgewars/Data/Graphics/Missions/Training/ClimbHome@2x.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Missions/Training/Target_Practice_-_Bazooka_easy@2x.png Binary file share/hedgewars/Data/Graphics/Missions/Training/Target_Practice_-_Bazooka_easy@2x.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Missions/Training/Target_Practice_-_Bazooka_hard@2x.png Binary file share/hedgewars/Data/Graphics/Missions/Training/Target_Practice_-_Bazooka_hard@2x.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Missions/Training/Target_Practice_-_Cluster_Bomb@2x.png Binary file share/hedgewars/Data/Graphics/Missions/Training/Target_Practice_-_Cluster_Bomb@2x.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Missions/Training/Target_Practice_-_Grenade_easy@2x.png Binary file share/hedgewars/Data/Graphics/Missions/Training/Target_Practice_-_Grenade_easy@2x.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Missions/Training/Target_Practice_-_Grenade_hard@2x.png Binary file share/hedgewars/Data/Graphics/Missions/Training/Target_Practice_-_Grenade_hard@2x.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Missions/Training/Target_Practice_-_Homing_Bee@2x.png Binary file share/hedgewars/Data/Graphics/Missions/Training/Target_Practice_-_Homing_Bee@2x.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Missions/Training/Target_Practice_-_Shotgun@2x.png Binary file share/hedgewars/Data/Graphics/Missions/Training/Target_Practice_-_Shotgun@2x.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Missions/Training/User_Mission_-_Nobody_Laugh.png Binary file share/hedgewars/Data/Graphics/Missions/Training/User_Mission_-_Nobody_Laugh.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Molotov.png Binary file share/hedgewars/Data/Graphics/Molotov.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Mortar.png Binary file share/hedgewars/Data/Graphics/Mortar.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Note.png Binary file share/hedgewars/Data/Graphics/Note.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Parachute.png Binary file share/hedgewars/Data/Graphics/Parachute.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Power.png Binary file share/hedgewars/Data/Graphics/Power.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/PowerBar.png Binary file share/hedgewars/Data/Graphics/PowerBar.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/RopeHook.png Binary file share/hedgewars/Data/Graphics/RopeHook.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/RopeNode.png Binary file share/hedgewars/Data/Graphics/RopeNode.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/SMineOff.png Binary file share/hedgewars/Data/Graphics/SMineOff.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/SMineOn.png Binary file share/hedgewars/Data/Graphics/SMineOn.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Seduction.png Binary file share/hedgewars/Data/Graphics/Seduction.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Shells.png Binary file share/hedgewars/Data/Graphics/Shells.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/SmokeRing.png Binary file share/hedgewars/Data/Graphics/SmokeRing.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/SmokeTrace.png Binary file share/hedgewars/Data/Graphics/SmokeTrace.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/SmokeWhite.png Binary file share/hedgewars/Data/Graphics/SmokeWhite.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Snow.png Binary file share/hedgewars/Data/Graphics/Snow.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/SnowDust.png Binary file share/hedgewars/Data/Graphics/SnowDust.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Snowball.png Binary file share/hedgewars/Data/Graphics/Snowball.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/SuddenDeath/SDClouds.png Binary file share/hedgewars/Data/Graphics/SuddenDeath/SDClouds.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/SuddenDeath/SDDroplet.png Binary file share/hedgewars/Data/Graphics/SuddenDeath/SDDroplet.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/SuddenDeath/SDSplash.png Binary file share/hedgewars/Data/Graphics/SuddenDeath/SDSplash.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/SuddenDeath/SDWater.png Binary file share/hedgewars/Data/Graphics/SuddenDeath/SDWater.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Switch.png Binary file share/hedgewars/Data/Graphics/Switch.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/TARDIS.png Binary file share/hedgewars/Data/Graphics/TARDIS.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Target.png Binary file share/hedgewars/Data/Graphics/Target.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/TargetBee.png Binary file share/hedgewars/Data/Graphics/TargetBee.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Targetp.png Binary file share/hedgewars/Data/Graphics/Targetp.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/Timebox.png Binary file share/hedgewars/Data/Graphics/Timebox.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/WindBar.png Binary file share/hedgewars/Data/Graphics/WindBar.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/WindL.png Binary file share/hedgewars/Data/Graphics/WindL.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/WindR.png Binary file share/hedgewars/Data/Graphics/WindR.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/amAirplane.png Binary file share/hedgewars/Data/Graphics/amAirplane.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/amRubber.png Binary file share/hedgewars/Data/Graphics/amRubber.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/amRubber.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Graphics/amRubber.svg Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,657 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/amTeleport.png Binary file share/hedgewars/Data/Graphics/amTeleport.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/boing.png Binary file share/hedgewars/Data/Graphics/boing.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/boing.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Graphics/boing.svg Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,40 @@ + + + + + + + + image/svg+xml + + + + + + + + + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/botlevels.png Binary file share/hedgewars/Data/Graphics/botlevels.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/cheese.png Binary file share/hedgewars/Data/Graphics/cheese.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/custom1.png Binary file share/hedgewars/Data/Graphics/custom1.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/custom2.png Binary file share/hedgewars/Data/Graphics/custom2.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/dynamite.png Binary file share/hedgewars/Data/Graphics/dynamite.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/hhMask.png Binary file share/hedgewars/Data/Graphics/hhMask.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/hwengine.png Binary file share/hedgewars/Data/Graphics/hwengine.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/icetexture.png Binary file share/hedgewars/Data/Graphics/icetexture.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/missions.png Binary file share/hedgewars/Data/Graphics/missions.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/slider.png Binary file share/hedgewars/Data/Graphics/slider.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/star.png Binary file share/hedgewars/Data/Graphics/star.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Graphics/thinking.png Binary file share/hedgewars/Data/Graphics/thinking.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/CMakeLists.txt --- a/share/hedgewars/Data/Locale/CMakeLists.txt Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/CMakeLists.txt Tue Nov 10 20:43:13 2015 +0100 @@ -1,9 +1,13 @@ +find_package(Qt4 REQUIRED) +include(${QT_USE_FILE}) + file(GLOB txttrans2 ??.txt) file(GLOB txttrans5 ?????.txt) file(GLOB tsfiles *.ts) file(GLOB luafiles *.lua) file(GLOB missionfiles missions_*.txt) file(GLOB campaignfiles campaigns_*.txt) +file(GLOB tipfiles tips_*.xml) QT4_ADD_TRANSLATION(QM ${tsfiles}) @@ -19,6 +23,7 @@ ${luafiles} ${missionfiles} ${campaignfiles} + ${tipfiles} DESTINATION ${SHAREPATH}Data/Locale ) diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/campaigns_de.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Locale/campaigns_de.txt Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,43 @@ +A_Classic_Fairytale-first_blood.desc="Hilf Undichte Stelle dabei, sein Training zu absolvieren und zu einem richtigen Igelkrieger zu werden. Du wirst in der Kunst des Seils, Fallschirms, Shoryukens und der Desert Eagle trainiert." + +A_Classic_Fairytale-shadow.desc="Undichte Stelle und Dichte Wolke gehen für die Jagd raus. Sei auf Gefahren im Wald gefasst. Denk dran, bedenke deine Entscheidungen gut." + +A_Classic_Fairytale-journey.desc="Undichte Stelle muss zur anderen Seite der Insel gehen. Sei schnell und vorsichtig." + +A_Classic_Fairytale-united.desc="Nach seiner langen Reise kehrte Undichte Stelle endlich wieder zum Dorf zurück. Allerdings gibt es keine Zeit zum Ausruhen. Du musst das Dorf von der Rage der Kannibalen verteidigen." + +A_Classic_Fairytale-backstab.desc="Die monströsen Kannibalen jagen Undichte Stelle und seine Freunde. Besiege sie erneut und beschütze deine Freunde. Benutze deine Ressourcen entsprechend, um die eintreffenden Feinde zu besiegen!" + +A_Classic_Fairytale-dragon.desc="Undichte Stelle muss auf die andere Seite des Sees kommen. Werd zum Seilprofi und vermeide es, von feindlichen Schüssen getroffen zu werden." + +A_Classic_Fairytale-family.desc="Undichte Stelle muss erneut seine Freunde retten. Eliminiere die feindlichen Igel und befreie deine Kameraden. Benutze deine Ressourcen vorsichtig, weil sie begrenzt sind. Bohr ein paar Löcher an den richtigen Stellen und nähere dich der Prinzessin." + +A_Classic_Fairytale-queen.desc="Undichte Stelle muss noch einmal kämpfen. Um zu gewinnen, muss er den Veräräter bekämpfen und alle verfügbaren Ressourcen benutzen. Besieg den Feind!" + +A_Classic_Fairytale-enemy.desc="Was für eine umwerfende Wendung! Undichte Stelle muss mit den … »Kannibalen« gegen den gemeinsamen Feind – die bösen Cyborgs – kämpfen!" + +A_Classic_Fairytale-epil.desc="Gratulation! Undichte Stelle kann endlich in Frieden gehen und von seinen neuen Freunden und seinem Stamm angepriesen werden. Sei stolz auf das, was du erreicht hast! Du kannst vorherige Missionen wieder spielen und andere mögliche Enden sehen." + +A_Space_Adventure-cosmos.desc="Hogera, der Igelplanet, wird bald von einem riesigen Meteroid getroffen. In diesem Wettlauf ums Überleben musst du PAdIs besten Piloten, Igel Einsam, in einer Weltraumreise um die Nachbarplaneten führen, um alle 4 Teil des lang verschollenem Antigravitationsgeräts zu finden!" + +A_Space_Adventure-moon01.desc="Igel Einsam ist auf dem Mond gelandet, um seine fliegende Untertasse aufzutanken, aber Prof. Bösigel war zuerst da und hat einen Hinterhalt aufgestellt! Rette die gefangenen PAdI-Forscher und verscheuche Prof. Bösigel!" + +A_Space_Adventure-moon02.desc="Igel Einsam besucht einen Eremiten, einen alten PAdI-Veteran, der im Mond lebt, um Prof. Bösigel auszuspionieren. Allerdings muss er den Eremiten, Verrückter Renner, zuerst in einem Wettlauf besiegen!" + +A_Space_Adventure-ice01.desc="Willkommen auf dem Planeten des Eises. Hier ist es so kalt, dass die meisten Waffen von Igel Einsam nicht funktionieren werden. Du musst dir das verlorene Teil von dem Banditenanführer Thanta ergattern, indem du die Waffen, die du hier findest, verwendest!" + +A_Space_Adventure-ice02.desc="Igel Einsam konnt nicht einfach nur den Eisplaneten besuchen, ohne das Olympiastadion des Untertassenfliegens zu besuchen! In dieser Mission kannst du deine Flugkünste unter Beweis stellen und deinen Platz unter den Besten einnehmen!" + +A_Space_Adventure-desert01.desc="Du must auf dem Planeten aus Sand gelandet! Igel Einsam muss das fehlende Teil in den Berkwerksstollen finden. Sei vorsichtig, weil bösartige Schmuggler nur darauf warten, dich anzugreifen und auszurauben!" + +A_Space_Adventure-desert02.desc="Igel Einsam suchte nach dem Teil in diesem Tunnel, als er unerwarteterweise anfing, geflutet zu werden! Komm so schnell wie möglich zur Oberfläche und pass auf, keine Mine auszulösen." +A_Space_Adventure-desert03.desc="Igel Einsam hat etwas Zeit, um sein Funkflugzeug zu fliegen und etwas Spaß zu haben. Flieg das Funkflugzeug und triff alle Ziele!" +A_Space_Adventure-fruit01.desc="Auf dem Obstplaneten laufen die Dinge nicht so gut. Igel sammeln kein Obst, sondern sie bereiten sich auf den Kampf vor. Du musst dich entscheiden, ob du kämpfen oder fliehen wirst." +A_Space_Adventure-fruit02.desc="Igel Einsam nähert sich dem verlorenen Teil des Obstplaneten. Wird ihn Leutnant Limone dabei helfen, das Teil zu besorgen? Oder nicht?" + +A_Space_Adventure-fruit03.desc="Igel Einsam has sich verlaufen und ist in den Hinterhalt der Roten Erdbeeren geraten. Hilf ihm, sie zu eliminieren, um etwas zusätzliche Munition für die Mission »Zum Greifen nah« zu gewinnen." + +A_Space_Adventure-death01.desc="Auf dem Todesplaneten, dem sterilsten Planeten in der Gegend, ist Igel Einsam ganz kurz davor, das letzte Teil des Geräts zu holen! Allerdings erwartet ihn eine unangenehme Überraschnug." + +A_Space_Adventure-death02.desc="Igel Einsam ist wieder in eine schwierige Situation geraten. Hilf ihm, die »5 tödlichen Igel« in ihrem eigenem Spiel zu besiegen!" +A_Space_Adventure-final.desc="Igel Einsam muss ein paar Sprengkörper, die auf dem Meteriot platziert wurden, detonieren. Hilf ihm, diese Mission zu beenden, ohne verletzt zu werden!" diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/campaigns_el.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Locale/campaigns_el.txt Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,34 @@ +A_Classic_Fairytale-first_blood.desc="Βοήθησε τον Leaks a lot να ολοκληρώσει την εκπαίδευσή του και να γίνει ένας κανονικός πολεμιστής σκαντζόχοιρος. Θα εκπαιδευτείς στη τέχνη του σκοινιού, του αλεξίπτωτου, της μπουνιάς και της σκοποβολής με όπλο." + +A_Classic_Fairytale-shadow.desc="Ο Leaks a lot και ο Dense Cloud πηγαίνουν για κυνήγι. Να είσαι έτοιμος για τους κινδύνους που παραμονεύουν στο δάσος. Θυμίσου, κάνε τις επιλογές σου προσεκτικά." + +A_Classic_Fairytale-journey.desc="Ο Leaks a lot πρέπει να πάει στην άλλη μεριά του νησιού. Να είσαι γρήγορος και προσεκτικός." + +A_Classic_Fairytale-united.desc="Μετά το μεγάλο του ταξίδι ο Leaks a lot επιστρέφει επιτέλους στο χωριό. Παρόλα αυτά δεν υπάρχει χρόνος για ξεκούραση. Πρέπει να υπερασπιστείς το χωριό από την οργή των κανίβαλων." + +A_Classic_Fairytale-backstab.desc="Οι τερατώδεις κανίβαλοι κυνηγούν τον Leaks a lot και τους φίλους του. Νίκησε τους άλλη μία φορά και προστάτεψε τους συμμάχους σου. Χρησιμοποίησε τον εξοπλισμό σου κατάλληλα για να νικήσεις τους εχθρούς!" + +A_Classic_Fairytale-dragon.desc="Ο Leaks a lot πρέπει να φτάσει στην άλλη μεριά της λίμνης. Γίνε μαέστρος του σκοινιού και απέφυγε τα πυρά των αντιπάλων." + +A_Classic_Fairytale-family.desc="Ο Leaks a lot πρέπει να σώσει ξανά τους συμμάχους του. Εξόντωσε τους εχθρικούς σκαντζόχοιρους και ελευθέρωσε τους συμμάχους. Χρησιμοποίησε τον εξοπλισμό σου προσεκτικά καθώς είναι περιορισμένος. Άνοιξε μερικές τρύπες στο σωστό σημείο και πήγαινε κοντά στην πριγκίπισσα." + +A_Classic_Fairytale-queen.desc="Ο Leaks a lot πρέπει να πολεμήσει και πάλι. Για να νικήσεις πρέπει να πολεμήσεις τον προδότη και να χρησιμοποιήσεις όλο τον διαθέσιμο εξοπλισμό. Νίκησε τον εχθρό!" + +A_Classic_Fairytale-enemy.desc="Τι μεγάλη αλλαγή στην πλοκή! Ο Leaks a lot πρέπει να πολεμήσει πλαϊ στους… “κανίβαλους” εναντίον στον κοινό εχθρό. Τα υποχθόνια ανδροειδη!" + +A_Classic_Fairytale-epil.desc="Συγχαρητήρια! Ο Leaks a lot μπορεί επιτέλους να ζήσει ήσυχα και να δοξαστεί από τους νέους φίλους του και τη φυλή του. Να είσαι περίφανος για αυτό που κατάφερες! Μπορείς να παίξεις τις προηγούμενες αποστολές και δεις τα άλλα πιθανά αποτελέσματα." + +A_Space_Adventure-cosmos.desc="Η Hogera, ο πλανήτης των σκαντζόχοιρων πρόκειται να συγκρουστεί με έναν γιγαντιαίο μετεωρίτη. Σε αυτό τον αγώνα για επιβίωση πρέπει να οδηγήσετε τον καλύτερο πιλότο της PAotH, Hog Solo, σε ένα διαστημικό ταξίδι στους γειτονικούς πλανήτες για να συλλέξει τα 4 χαμένα κομμάτια της συσκευής αντιβαρύτητας!" +A_Space_Adventure-moon01.desc="Ο Hog Solo έχει προσγειωθεί στο φεγγάρι για να ανεφοδειάσει με κάυσιμα τον δίσκο αλλά ο καθηγητής Hogevil έχει φτάσει εκεί πρώτος και έχει στήσει ενέδρα! Σώσε τους φυλακισμένους ερευνητές του PAotH και διώξε τον καθηγητή Hogevil!" +A_Space_Adventure-moon02.desc="Ο Hog Solo επισκέπτεται έναν ερημίτη, παλιό βετεράνο του PAotH, που ζει στο φεγγάρι για να συλέξει πληροφορίες σχετικά με τον Καθηγητή Hogevil. Ωστόσο, πρέπει να νικήσει πρώτα τον ερημίτη, τον Soneek τον Τρελό Δρομέα, σε ένα παιχνίδι κυνηγητού!" +A_Space_Adventure-ice01.desc="Καλώς ήλθατε στον πλανήτη του πάγου. Εδώ, είναι τόσο κρύα που ο περισσότερος εξοπλισμός του Hog Solo δεν λειτουργεί. Πρέπει να πάρεις το χαμένο κομμάτι από τον Thanta, τον αρχηγό των κλεφτών, χρησιμοποιώντας τον εξοπλισμό που θα βρεις εκεί!" +A_Space_Adventure-ice02.desc="Ο Hog Solo δεν μπορούσε να επισκεφτεί απλά τον Παγωμένο Πλανήτη χωρίς να επισκεφτεί το ολυμπιακό στάδιο πτήσης δίσκων! Σε αυτή την αποστολή θα επιβεβαιώσετε τις ικανότητες πτήσης σας και θα διεκδικήσετε τη θέση που σας ανοίκει ανάμεσα στους καλύτερους!" +A_Space_Adventure-desert01.desc="Προσγειωθήκατε στον πλανήτη της άμμου! Ο Hog Solo πρέπει να βρει το χαμένο κομμάτι στις υπόγειες στοές. Προσοχή καθώς μοχθηροί κλέφτες περιμένουν να σας επιτεθούν και να σας ληστέψουν!" +A_Space_Adventure-desert02.desc="O Hog Solo έψαχνε το κομμάτι σε αυτή τη στοά όταν απρόσμενα ξεκίνησε να πλημμυρίζει! Πήγαινε στην επιφάνεια το συντομότερο δυνατό και πρόσεχε μην πυροδοτήσεις κάποια νάρκη." +A_Space_Adventure-desert03.desc="Ο Hog Solo έχει λίγο χρόνο για να πετάξει το τηλεκατευθυνόμενο αεροπλάνο του και να περάσει καλά. Πέτα το τηλεκατευθυνόμενο και χτύπα όλους τους στόχους!" +A_Space_Adventure-fruit01.desc="Στον Φρουτο-πλανήτη τα πράγματα δεν πηγαίνουν τόσο καλά. Οι σκαντζόχοιροι δεν μαζεύουν φρούτα αλλά ετοιμάζονται για μάχη. Θα πρέπει να επιλέξεις εάν θα πολεμήσεις ή θα υποχωρήσεις." +A_Space_Adventure-fruit02.desc="Ο Hog Solo πλησιάζει στο χαμένο κομμάτι στον Φρουτο-πλανήτη. Θα τον βοηθήσει ο Captain Lime να πάρει το κομμάτι ή όχι?" +A_Space_Adventure-fruit03.desc="Ο Hog Solo χάθηκε και έπεσε στην ενέδρα των Red Strawberies. Βοήθησε τον να τους εξοντώσει και κέρδισε περισσότερα πυρομαχικά για την αποστολή Getting to the device." +A_Space_Adventure-death01.desc="Στον Πλανήτη του Θανάτου, τον πιο άγονο πλανήτη απ'όλους, ο Hog Solo είναι πολύ κοντά να πάρει το τελευταίο κομμάτι της συσκευής! Ωστόσο μία δυσάρεστη έκλπηξη τον περιμένει..." +A_Space_Adventure-death02.desc="Ξανά ο Hog Solo έβαλε τον εαυτό του σε μία δύσκολη κατάσταση. Βοήθησε τον να νικήσει τους “5 deadly hogs“ στο δικό τους παιχνίδι!" +A_Space_Adventure-final.desc="Ο Hog Solo πρέπει να πυροδοτήσει μερικά εκρηκτικά που έχουν τοποθετηθεί στον μετεωρίτη. Βοήθησε τον να ολοκληρώσει την αποστολή του χωρίς να πάθει κακό!" diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/campaigns_en.txt --- a/share/hedgewars/Data/Locale/campaigns_en.txt Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/campaigns_en.txt Tue Nov 10 20:43:13 2015 +0100 @@ -1,34 +1,34 @@ -A_Classic_Fairytale-first_blood.desc="Help Leaks a lot to complete his training and become a proper hedgehog warrior. You will be trained in the art of rope, parachute, shoryuken and desert eagle." - -A_Classic_Fairytale-shadow.desc="Leaks a lot and Dense Cloud are going for hunting. Be prepared for the dangers awaiting you at the forest. Remember, make your choices wisely." - -A_Classic_Fairytale-journey.desc="Leaks a lot has to go to the other side of the island. Be fast and cautious." - -A_Classic_Fairytale-united.desc="After his long journey Leaks a lot is finally back to the village. However, there isn't time to rest. You have to defend the village from the rage of the cannibals." - -A_Classic_Fairytale-backstab.desc="The monstrous cannibals are hunting Leaks a lot and his friends. Defeat them once again and protect your allies. Use your resources accordingly to defeat the incoming enemies!" - -A_Classic_Fairytale-dragon.desc="Leaks a lot has to get to the other side of the lake. Become a rope master and avoid get hit by the enemy shots." - -A_Classic_Fairytale-family.desc="Leaks a lot has to save once more his allies. Eliminate the enemy hogs and free your comrades. Use your resources carefully as they are limited. Drill some holes in the right spot and go close to the princess." - -A_Classic_Fairytale-queen.desc="Leaks a lot has to fight once again. In order to win he'll have to fight the traitor and use all the resources available. Defeat the enemy!" - -A_Classic_Fairytale-enemy.desc="What a great twist! Leaks a lot has to fight side by side with the… “cannibals” against the common enemy. The evil cyborgs!" - -A_Classic_Fairytale-epil.desc="Congratulations! Leaks a lot can finally leave in peace and get praised by his new friends and his tribe. Be proud for what you succeed! You can play again previous missions and see the other possible endings." - -A_Space_Adventure-cosmos.desc="Hogera, the planet of hogs is about to be hit by a gigantic meteorite. In this race for survival you have to lead PAotH's best pilot, Hog Solo, in a space trip around the neighbor planets to collect all the 4 pieces of the long lost anti gravity device!" -A_Space_Adventure-moon01.desc="Hog Solo has landed on the moon to refuel his saucer but professor Hogevil has gone there first and set an ambush! Rescue the catpured PAotH researchers and drive professor Hogevil away!" -A_Space_Adventure-moon02.desc="Hog Solo visits an hermit, old PAotH veteran, who lives in moon in order to collect some intel about Pr. Hogevil. However, he has to beat the hermit, Soneek the Crazy Runner, in a chase game first!" -A_Space_Adventure-ice01.desc="Welcome to the planet of ice. Here, it's so cold that most of Hog Solo's weapons won't work. You have to get the lost part from the bandit leader Thanta using the weapons that you'll find there!" -A_Space_Adventure-ice02.desc="Hog Solo couldn't just visit the Ice Planet without visiting the olympic stadium of saucer flying! In this mission you can proove your flying skills and claim your place between the best!" -A_Space_Adventure-desert01.desc="You have landed to the planet of sand! Hog Solo has to find the missing part in the underground tunnels. Be careful as vicious smugglers await to attack and rob you!" -A_Space_Adventure-desert02.desc="Hog Solo was searching for the part in this tunnel when it unexpectedly start getting flooded! Get to the surface as soon as possible and be careful not to trigger a mine." -A_Space_Adventure-desert03.desc="Hog Solo has some time to fly his RC plane and have some fun. Fly the RC plane and hit all the targets!" -A_Space_Adventure-fruit01.desc="In the fruit planet things aren't going so well. Hogs aren't collecting fruits but they are preparing for battle. You'll have to choose if you'll fight or if you'll flee." -A_Space_Adventure-fruit02.desc="Hog Solo gets closer to the lost part in the Fruit Planet. Will Captain Lime help him acquire the part or not?" -A_Space_Adventure-fruit03.desc="Hog Solo got lost and got ambushed by the Red Strawberies. Help him eliminate them and win some extra ammo for the Getting to the device mission." -A_Space_Adventure-death01.desc="In the Death Planet, the most infertile planet around, Hog Solo is very close to get the last part of the device! However an upleasant surprise awaits him..." -A_Space_Adventure-death02.desc="Again Hog Solo has got himself in a difficult situation. Help him defeat the “5 deadly hogs“ in their own game!" -A_Space_Adventure-final.desc="Hog Solo has to detonate some explosives that have been placed on the meteorite. Help him complete his mission without getting hurt!" +A_Classic_Fairytale-first_blood.desc="Help Leaks a lot to complete his training and become a proper hedgehog warrior. You will be trained in the art of rope, parachute, shoryuken and desert eagle." + +A_Classic_Fairytale-shadow.desc="Leaks a lot and Dense Cloud are going for hunting. Be prepared for the dangers awaiting you at the forest. Remember, make your choices wisely." + +A_Classic_Fairytale-journey.desc="Leaks a lot has to go to the other side of the island. Be fast and cautious." + +A_Classic_Fairytale-united.desc="After his long journey Leaks a lot is finally back to the village. However, there isn't time to rest. You have to defend the village from the rage of the cannibals." + +A_Classic_Fairytale-backstab.desc="The monstrous cannibals are hunting Leaks a lot and his friends. Defeat them once again and protect your allies. Use your resources accordingly to defeat the incoming enemies!" + +A_Classic_Fairytale-dragon.desc="Leaks a lot has to get to the other side of the lake. Become a rope master and avoid get hit by the enemy shots." + +A_Classic_Fairytale-family.desc="Leaks a lot has to save once more his allies. Eliminate the enemy hogs and free your comrades. Use your resources carefully as they are limited. Drill some holes in the right spot and go close to the princess." + +A_Classic_Fairytale-queen.desc="Leaks a lot has to fight once again. In order to win he'll have to fight the traitor and use all the resources available. Defeat the enemy!" + +A_Classic_Fairytale-enemy.desc="What a great twist! Leaks a lot has to fight side by side with the… “cannibals” against the common enemy. The evil cyborgs!" + +A_Classic_Fairytale-epil.desc="Congratulations! Leaks a lot can finally leave in peace and get praised by his new friends and his tribe. Be proud for what you succeed! You can play again previous missions and see the other possible endings." + +A_Space_Adventure-cosmos.desc="Hogera, the planet of hogs is about to be hit by a gigantic meteorite. In this race for survival you have to lead PAotH's best pilot, Hog Solo, in a space trip around the neighbor planets to collect all the 4 pieces of the long lost anti gravity device!" +A_Space_Adventure-moon01.desc="Hog Solo has landed on the moon to refuel his saucer but professor Hogevil has gone there first and set an ambush! Rescue the captured PAotH researchers and drive professor Hogevil away!" +A_Space_Adventure-moon02.desc="Hog Solo visits an hermit, old PAotH veteran, who lives in moon in order to gather some intel about Pr. Hogevil. However, he has to beat the hermit, Soneek the Crazy Runner, in a chase game first!" +A_Space_Adventure-ice01.desc="Welcome to the planet of ice. Here, it's so cold that most of Hog Solo's weapons won't work. You have to get the lost part from the bandit leader Thanta using the weapons that you'll find there!" +A_Space_Adventure-ice02.desc="Hog Solo couldn't just visit the Ice Planet without visiting the Olympic stadium of saucer flying! In this mission you can prove your flying skills and claim your place between the best!" +A_Space_Adventure-desert01.desc="You have landed to the planet of sand! Hog Solo has to find the missing part in the underground tunnels. Be careful as vicious smugglers await to attack and rob you!" +A_Space_Adventure-desert02.desc="Hog Solo was searching for the part in this tunnel when it unexpectedly start getting flooded! Get to the surface as soon as possible and be careful not to trigger a mine." +A_Space_Adventure-desert03.desc="Hog Solo has some time to fly his RC plane and have some fun. Fly the RC plane and hit all the targets!" +A_Space_Adventure-fruit01.desc="In the fruit planet things aren't going so well. Hogs aren't collecting fruits but they are preparing for battle. You'll have to choose if you'll fight or if you'll flee." +A_Space_Adventure-fruit02.desc="Hog Solo gets closer to the lost part in the Fruit Planet. Will Captain Lime help him acquire the part or not?" +A_Space_Adventure-fruit03.desc="Hog Solo got lost and got ambushed by the Red Strawberries. Help him eliminate them and win some extra ammo for the Getting to the device mission." +A_Space_Adventure-death01.desc="In the Death Planet, the most infertile planet around, Hog Solo is very close to get the last part of the device! However an unpleasant surprise awaits him..." +A_Space_Adventure-death02.desc="Again Hog Solo has got himself in a difficult situation. Help him defeat the “5 deadly hogs“ in their own game!" +A_Space_Adventure-final.desc="Hog Solo has to detonate some explosives that have been placed on the meteorite. Help him complete his mission without getting hurt!" diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/campaigns_pt_BR.txt --- a/share/hedgewars/Data/Locale/campaigns_pt_BR.txt Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/campaigns_pt_BR.txt Tue Nov 10 20:43:13 2015 +0100 @@ -1,19 +1,19 @@ -A_Classic_Fairytale-first_blood.desc="Ajude Vaza Demais a completar seu treinamento e a se tornar um guerreiro ouriço. Você será treinado na arte da corda, do paraquedas, do shoryuken e da pistola." - -A_Classic_Fairytale-shadow.desc="Vaza Demais e Nuvem Densa saíram para caçar. Esteja preparado para os perigos à sua espera na floresta. Lembre-se de fazer suas escolhas sabiamente." - -A_Classic_Fairytale-journey.desc="Vaza Demais tem que ir ao outro lado da ilha. Seja rápido e cauteloso." - -A_Classic_Fairytale-united.desc="Depois de sua longa jornada, Vaza Demais está finalmente de volta à vila. Entretanto, não há tempo para descanso. Você tem que defender a vila da fúria dos canibais." - -A_Classic_Fairytale-backstab.desc="Os monstruosos canibais estão caçando Vaza Demais e seus amigos. Derrote-os de uma vez e proteja seus aliados. Use seus recursos para derrotas os inimigos que chegam!" - -A_Classic_Fairytale-dragon.desc="Vaza Demais tem que chegar ao outro lado do lago. Torne-se um mestre na corda e evite ser atingido pelos tiros dos inimigos." - -A_Classic_Fairytale-family.desc="Vaza Demais tem que salvar mais uma vez seus aliados. Elimine os ouriços inimigos e liberte seus companheiros. Use seus recursos com cuidado já que são limitados. Cave alguns buracos no lugar certo e se aproxime da princesa." - -A_Classic_Fairytale-queen.desc="Vaza Demais tem que lutar mais uma vez. Para vencer, ele terá que lutar contra o traidor e usar todos os recursos disponíveis. Derrote o inimigo!" - -A_Classic_Fairytale-enemy.desc="Que grande virada! Vaza Demais tem que lutar lado a lado com os… “canibais” contra o inimigo comum. Os ciborgues malignos!" - -A_Classic_Fairytale-epil.desc="Parabéns! Vaza Demais pode finalmente ficar em paz e ser exaltado pelos seus novos amigos e sua tribo. Orgulhe-se do que conquistou! Você pode jogar missões anteriores novamente e ver outros finais possíveis." +A_Classic_Fairytale-first_blood.desc="Ajude Vaza Demais a completar seu treinamento e a se tornar um guerreiro ouriço. Você será treinado na arte da corda, do paraquedas, do shoryuken e da pistola." + +A_Classic_Fairytale-shadow.desc="Vaza Demais e Nuvem Densa saíram para caçar. Esteja preparado para os perigos à sua espera na floresta. Lembre-se de fazer suas escolhas sabiamente." + +A_Classic_Fairytale-journey.desc="Vaza Demais tem que ir ao outro lado da ilha. Seja rápido e cauteloso." + +A_Classic_Fairytale-united.desc="Depois de sua longa jornada, Vaza Demais está finalmente de volta à vila. Entretanto, não há tempo para descanso. Você tem que defender a vila da fúria dos canibais." + +A_Classic_Fairytale-backstab.desc="Os monstruosos canibais estão caçando Vaza Demais e seus amigos. Derrote-os de uma vez e proteja seus aliados. Use seus recursos para derrotas os inimigos que chegam!" + +A_Classic_Fairytale-dragon.desc="Vaza Demais tem que chegar ao outro lado do lago. Torne-se um mestre na corda e evite ser atingido pelos tiros dos inimigos." + +A_Classic_Fairytale-family.desc="Vaza Demais tem que salvar mais uma vez seus aliados. Elimine os ouriços inimigos e liberte seus companheiros. Use seus recursos com cuidado já que são limitados. Cave alguns buracos no lugar certo e se aproxime da princesa." + +A_Classic_Fairytale-queen.desc="Vaza Demais tem que lutar mais uma vez. Para vencer, ele terá que lutar contra o traidor e usar todos os recursos disponíveis. Derrote o inimigo!" + +A_Classic_Fairytale-enemy.desc="Que grande virada! Vaza Demais tem que lutar lado a lado com os… “canibais” contra o inimigo comum. Os ciborgues malignos!" + +A_Classic_Fairytale-epil.desc="Parabéns! Vaza Demais pode finalmente ficar em paz e ser exaltado pelos seus novos amigos e sua tribo. Orgulhe-se do que conquistou! Você pode jogar missões anteriores novamente e ver outros finais possíveis." diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/campaigns_uk.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Locale/campaigns_uk.txt Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,34 @@ +A_Classic_Fairytale-first_blood.desc="Допоможіть Протікайку завершити своє навчання і стати справжнім їжако-воїном. Ви будете навчені мистецтву мотузки, парашуту, козацього удару і пустельного орла." + +A_Classic_Fairytale-shadow.desc="Leaks a lot and Dense Cloud are going for hunting. Be prepared for the dangers awaiting you at the forest. Remember, make your choices wisely." + +A_Classic_Fairytale-journey.desc="Протікайку треба перебратись на інший бік острова. Будь швидким і обережним." + +A_Classic_Fairytale-united.desc="Після довгої мандрівки Протікайко повернувся до села. Але немає коли відпочивати. Треба захистити село від нападу канібалів." + +A_Classic_Fairytale-backstab.desc="The monstrous cannibals are hunting Leaks a lot and his friends. Defeat them once again and protect your allies. Use your resources accordingly to defeat the incoming enemies!" + +A_Classic_Fairytale-dragon.desc="Протікайту треба перебратись на інший берег озера. Стань майстром мотузки і уникай пострілів ворога." + +A_Classic_Fairytale-family.desc="Leaks a lot has to save once more his allies. Eliminate the enemy hogs and free your comrades. Use your resources carefully as they are limited. Drill some holes in the right spot and go close to the princess." + +A_Classic_Fairytale-queen.desc="Протіайку треба йти в бій знову. Щоб перемогти треба битись зі зрадником і використати всі наявні ресурси. Подолай ворога!" + +A_Classic_Fairytale-enemy.desc="Який поворот! Протікайку треба битись пліч-о-пліч з… “канібалами” протиспільного ворога. Злих кіборгів!" + +A_Classic_Fairytale-epil.desc="Вітання! Протікайко нарешті може мирно жити і бути поцінованим новими друзями і йоо племенем. Гордись доясненнями! Ти можеш пройти попередні місії знов і глянути на інші кінцівки." + +A_Space_Adventure-cosmos.desc="На планету їжаків, Їжакію, незабаром має впасти гігантський метеорит. В боротьбі за виживання вам потрібно провести кращого пілота PAotH, Їжака Соло, в подорож сусідніми планетами щоб знайти всі 4 частини давно загубленого антигравітаційного пристрою!" +A_Space_Adventure-moon01.desc="Hog Solo has landed on the moon to refuel his saucer but professor Hogevil has gone there first and set an ambush! Rescue the captured PAotH researchers and drive professor Hogevil away!" +A_Space_Adventure-moon02.desc="Hog Solo visits an hermit, old PAotH veteran, who lives in moon in order to gather some intel about Pr. Hogevil. However, he has to beat the hermit, Soneek the Crazy Runner, in a chase game first!" +A_Space_Adventure-ice01.desc="Welcome to the planet of ice. Here, it's so cold that most of Hog Solo's weapons won't work. You have to get the lost part from the bandit leader Thanta using the weapons that you'll find there!" +A_Space_Adventure-ice02.desc="Hog Solo couldn't just visit the Ice Planet without visiting the Olympic stadium of saucer flying! In this mission you can prove your flying skills and claim your place between the best!" +A_Space_Adventure-desert01.desc="You have landed to the planet of sand! Hog Solo has to find the missing part in the underground tunnels. Be careful as vicious smugglers await to attack and rob you!" +A_Space_Adventure-desert02.desc="Hog Solo was searching for the part in this tunnel when it unexpectedly start getting flooded! Get to the surface as soon as possible and be careful not to trigger a mine." +A_Space_Adventure-desert03.desc="Hog Solo has some time to fly his RC plane and have some fun. Fly the RC plane and hit all the targets!" +A_Space_Adventure-fruit01.desc="In the fruit planet things aren't going so well. Hogs aren't collecting fruits but they are preparing for battle. You'll have to choose if you'll fight or if you'll flee." +A_Space_Adventure-fruit02.desc="Hog Solo gets closer to the lost part in the Fruit Planet. Will Captain Lime help him acquire the part or not?" +A_Space_Adventure-fruit03.desc="Hog Solo got lost and got ambushed by the Red Strawberries. Help him eliminate them and win some extra ammo for the Getting to the device mission." +A_Space_Adventure-death01.desc="In the Death Planet, the most infertile planet around, Hog Solo is very close to get the last part of the device! However an unpleasant surprise awaits him..." +A_Space_Adventure-death02.desc="Їжак Соло знов потрапляє в складну ситуацію. Допоможи йому подолати “5 убивчих їжаків“ в їхній власній грі!" +A_Space_Adventure-final.desc="Їжакові Соло треба підірвати закладену на метеориті вибухівку. Допоможи йому пройти місію без поранень!" diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/cs.lua --- a/share/hedgewars/Data/Locale/cs.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/cs.lua Tue Nov 10 20:43:13 2015 +0100 @@ -4,6 +4,10 @@ ["..."] = "...", -- ["011101000"] = "", -- A_Classic_Fairytale:dragon -- ["011101001"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:family, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united +-- ["+1 to a Bottom Feeder for killing anyone"] = "", -- Mutant +-- ["+1 to a Mutant for killing anyone"] = "", -- Mutant +-- ["-1 to anyone for a suicide"] = "", -- Mutant +-- ["+2 for becoming a Mutant"] = "", -- Mutant -- ["30 minutes later..."] = "", -- A_Classic_Fairytale:shadow -- ["About a month ago, a cyborg came and told us that you're the cannibals!"] = "", -- A_Classic_Fairytale:enemy ["Accuracy Bonus!"] = "Bonus za přesnost!", @@ -13,17 +17,27 @@ -- ["???"] = "", -- A_Classic_Fairytale:backstab -- ["Actually, you aren't worthy of life! Take this..."] = "", -- A_Classic_Fairytale:shadow -- ["A cy-what?"] = "", -- A_Classic_Fairytale:enemy +-- ["Advanced Repositioning Mode"] = "", -- Construction_Mode -- ["Adventurous"] = "", -- A_Classic_Fairytale:journey +-- ["a frenetic Hedgewars mini-game"] = "", -- Frenzy -- ["Africa"] = "", -- Continental_supplies -- ["After Leaks A Lot betrayed his tribe, he joined the cannibals..."] = "", -- A_Classic_Fairytale:first_blood -- ["After the shock caused by the enemy spy, Leaks A Lot and Dense Cloud went hunting to relax."] = "", -- A_Classic_Fairytale:shadow -- ["Again with the 'cannibals' thing!"] = "", -- A_Classic_Fairytale:enemy +-- ["Aggressively removes enemy hedgehogs."] = "", -- Construction_Mode -- ["a Hedgewars challenge"] = "", -- User_Mission_-_RCPlane_Challenge, User_Mission_-_Rope_Knock_Challenge ["a Hedgewars mini-game"] = "Hedgewars mini-hra", -- Space_Invasion, The_Specialists +-- ["a Hedgewars tag game"] = "", -- Mutant +-- ["AHHh, home sweet home. Made it in %d seconds."] = "", -- ClimbHome ["Aiming Practice"] = "Trénink přesnosti", --Bazooka, Shotgun, SniperRifle +-- ["Air Attack"] = "", -- Construction_Mode -- ["A leap in a leap"] = "", -- A_Classic_Fairytale:first_blood -- ["A little gift from the cyborgs"] = "", -- A_Classic_Fairytale:shadow -- ["All gone...everything!"] = "", -- A_Classic_Fairytale:enemy +-- ["Allows free teleportation between other nodes."] = "", -- Construction_Mode +-- ["Allows placement of girders, rubber-bands, mines, sticky mines and barrels."] = "", -- Construction_Mode +-- ["Allows placement of structures."] = "", -- Construction_Mode +-- ["Allows the placement of weapons, utiliites, and health crates."] = "", -- Construction_Mode -- ["All right, we just need to get to the other side of the island!"] = "", -- A_Classic_Fairytale:journey -- ["All walls touched!"] = "", -- WxW ["Ammo Depleted!"] = "Munice vyčerpána!", @@ -38,8 +52,11 @@ -- ["And so they discovered that cyborgs weren't invulnerable..."] = "", -- A_Classic_Fairytale:journey -- ["And where's all the weed?"] = "", -- A_Classic_Fairytale:dragon -- ["And you believed me? Oh, god, that's cute!"] = "", -- A_Classic_Fairytale:journey --- ["Anno 1032: [The explosion will make a strong push ~ wide range, wont affect hogs close to the target]"] = "", -- Continental_supplies +-- ["Anno 1032: [The explosion will make a strong push ~ Wide range, wont affect hogs close to the target]"] = "", -- Continental_supplies + -- ["Antarctica"] = "", -- Continental_supplies +-- ["Antarctic summer: - Will give you one girder/mudball and two sineguns/portals every fourth turn."] = "", -- Continental_supplies +-- ["Area"] = "", -- Continental_supplies -- ["Are we there yet?"] = "", -- A_Classic_Fairytale:shadow -- ["Are you accusing me of something?"] = "", -- A_Classic_Fairytale:backstab -- ["Are you saying that many of us have died for your entertainment?"] = "", -- A_Classic_Fairytale:enemy @@ -59,27 +76,35 @@ -- ["[Backspace]"] = "", -- ["Backstab"] = "", -- A_Classic_Fairytale:backstab -- ["Bad Team"] = "", -- User_Mission_-_The_Great_Escape +-- ["Ballgun"] = "", -- Construction_Mode -- ["Bamboo Thicket"] = "", -- ["Barrel Eater!"] = "", -- ["Barrel Launcher"] = "", +-- ["Barrel Placement Mode"] = "", -- Construction_Mode +-- ["Baseball Bat"] = "", -- Construction_Mode -- ["Baseballbat"] = "", -- Continental_supplies ["Bat balls at your enemies and|push them into the sea!"] = "Odpal míčky na své nepřátele|a odstrč je do vody!", ["Bat your opponents through the|baskets and out of the map!"] = "Odpal protivníky skrz|koše a pryč z mapy!", +-- ["Bazooka"] = "", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 ["Bazooka Training"] = "Trénink s bazukou", -- ["Beep Loopers"] = "", -- A_Classic_Fairytale:queen ["Best laps per team: "] = "Nejlepší kola dle týmů:", ["Best Team Times: "] = "Nejlepší týmový čas:", -- ["Beware, though! If you are slow, you die!"] = "", -- A_Classic_Fairytale:dragon +-- ["Bio-Filter"] = "", -- Construction_Mode -- ["Biomechanic Team"] = "", -- A_Classic_Fairytale:family +-- ["Birdy"] = "", -- Construction_Mode -- ["Blender"] = "", -- A_Classic_Fairytale:family -- ["Bloodpie"] = "", -- A_Classic_Fairytale:backstab -- ["Bloodrocutor"] = "", -- A_Classic_Fairytale:shadow -- ["Bloodsucker"] = "", -- A_Classic_Fairytale:shadow ["Bloody Rookies"] = "Zatravení zelenáči", -- 01#Boot_Camp, User_Mission_-_Dangerous_Ducklings, User_Mission_-_Diver, User_Mission_-_Spooky_Tree +-- ["Blowtorch"] = "", -- Construction_Mode, Frenzy +-- ["Blue Team"] = "", -- User_Mission_-_Dangerous_Ducklings -- ["Bone Jackson"] = "", -- A_Classic_Fairytale:backstab -- ["Bonely"] = "", -- A_Classic_Fairytale:shadow + ["BOOM!"] = "BUM!", ["Boom!"] = "Bum!", - ["BOOM!"] = "BUM!", ["Boss defeated!"] = "Velitel poražen!", ["Boss Slayer!"] = "Velitel zabit!", -- ["Brain Blower"] = "", -- A_Classic_Fairytale:journey @@ -89,6 +114,7 @@ -- ["Brain Teaser"] = "", -- A_Classic_Fairytale:backstab -- ["Brutal Lily"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil -- ["Brutus"] = "", -- A_Classic_Fairytale:backstab +-- ["Build a fortress and destroy your enemy."] = "", -- Construction_Mode -- ["Build a track and race."] = "", -- ["Bullseye"] = "", -- A_Classic_Fairytale:dragon -- ["But it proved to be no easy task!"] = "", -- A_Classic_Fairytale:dragon @@ -99,6 +125,7 @@ -- ["But why would they help us?"] = "", -- A_Classic_Fairytale:backstab -- ["But you're cannibals. It's what you do."] = "", -- A_Classic_Fairytale:enemy -- ["But you said you'd let her go!"] = "", -- A_Classic_Fairytale:journey +-- ["Cake"] = "", -- Construction_Mode -- ["Call me Beep! Well, 'cause I'm such a nice...person!"] = "", -- A_Classic_Fairytale:family -- ["Cannibals"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:first_blood -- ["Cannibal Sentry"] = "", -- A_Classic_Fairytale:journey @@ -108,8 +135,15 @@ -- ["Carol"] = "", -- A_Classic_Fairytale:family -- ["CHALLENGE COMPLETE"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Change Weapon"] = "", +-- ["changing range from %i%% to %i%% with period of %i msec"] = "", -- Gravity -- ["Choose your side! If you want to join the strange man, walk up to him.|Otherwise, walk away from him. If you decide to att...nevermind..."] = "", -- A_Classic_Fairytale:shadow +-- ["Cleaver"] = "", -- Construction_Mode +-- ["Cleaver Placement Mode"] = "", -- Construction_Mode +-- ["Climber"] = "", -- ClimbHome +-- ["Climb Home"] = "", -- ClimbHome +-- ["Clowns"] = "", -- User_Mission_-_Nobody_Laugh ["Clumsy"] = "Nešikovný", +-- ["Cluster Bomb"] = "", -- Construction_Mode -- ["Cluster Bomb MASTER!"] = "", -- Basic_Training_-_Cluster_Bomb -- ["Cluster Bomb Training"] = "", -- Basic_Training_-_Cluster_Bomb ["Codename: Teamwork"] = "Krycí jméno: Týmová práce", @@ -129,12 +163,19 @@ -- ["Congratulations! You needed only half of time|to eliminate all targets."] = "", -- Basic_Training_-_Cluster_Bomb -- ["Congratulations! You've completed the Rope tutorial! |- Tutorial ends in 10 seconds!"] = "", -- Basic_Training_-_Rope ["Congratulations! You've eliminated all targets|within the allowed time frame."] = "Gratuluji! Eliminoval jsi všechny cíle|během stanoveného limitu", --Bazooka, Shotgun, SniperRifle +-- ["CONSTRUCTION MODE"] = "", -- Construction_Mode +-- ["Construction Station"] = "", -- Construction_Mode -- ["Continental supplies"] = "", -- Continental_supplies ["Control pillars to score points."] = "Obsaď všechny sloupy, abys dostal body.", +-- ["Core"] = "", -- Construction_Mode -- ["Corporationals"] = "", -- A_Classic_Fairytale:queen -- ["Corpsemonger"] = "", -- A_Classic_Fairytale:shadow -- ["Corpse Thrower"] = "", -- A_Classic_Fairytale:epil +-- ["Cost"] = "", -- Construction_Mode +-- ["Crate Placement Tool"] = "", -- Construction_Mode -- ["Crates Left:"] = "", -- User_Mission_-_RCPlane_Challenge +-- ["Cricket time: [Drop a fireable mine! ~ Will work if fired close to your hog & far away from enemy ~ 1 sec]"] = "", -- Continental_supplies +-- ["Current setting is "] = "", -- Gravity ["Cybernetic Empire"] = "Kybernetická říše", -- ["Cyborg. It's what the aliens call themselves."] = "", -- A_Classic_Fairytale:enemy -- ["Dahmer"] = "", -- A_Classic_Fairytale:backstab @@ -142,15 +183,19 @@ ["DAMMIT, ROOKIE!"] = "ZATRACENĚ, ZELENÁČI!", ["Dangerous Ducklings"] = "Nebezpečná káčátka", ["Deadweight"] = "Mrtvá váha", +-- ["Decrease"] = "", -- Continental_supplies -- ["Defeat the cannibals"] = "", -- A_Classic_Fairytale:backstab -- ["Defeat the cannibals!|"] = "", -- A_Classic_Fairytale:united -- ["Defeat the cannibals!|Grenade hint: set the timer with [1-5], aim with [Up]/[Down] and hold [Space] to set power"] = "", -- A_Classic_Fairytale:shadow -- ["Defeat the cyborgs!"] = "", -- A_Classic_Fairytale:enemy +-- ["Defend your core from the enemy."] = "", -- Construction_Mode -- ["Defend yourself!|Hint: You can get tips on using weapons by moving your mouse over them in the weapon selection menu"] = "", -- A_Classic_Fairytale:shadow +-- ["Dematerializes weapons and equipment carried by enemy hedgehogs."] = "", -- Construction_Mode -- ["Demolition is fun!"] = "", -- ["Dense Cloud"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united -- ["Dense Cloud must have already told them everything..."] = "", -- A_Classic_Fairytale:shadow ["Depleted Kamikaze!"] = "Vyčerpaný sebevrah!", +-- ["Desert Eagle"] = "", -- Construction_Mode, A_Space_Adventure:death02 -- ["Destroy him, Leaks A Lot! He is responsible for the deaths of many of us!"] = "", -- A_Classic_Fairytale:first_blood ["Destroy invaders to score points."] = "Znič nájezdníky k získání bodů.", -- ["Destroy the targets!|Hint: Select the Shoryuken and hit [Space]|P.S. You can use it mid-air."] = "", -- A_Classic_Fairytale:first_blood @@ -169,9 +214,12 @@ -- ["Do you have any idea how valuable grass is?"] = "", -- A_Classic_Fairytale:enemy -- ["Do you think you're some kind of god?"] = "", -- A_Classic_Fairytale:enemy -- ["Dragon's Lair"] = "", -- A_Classic_Fairytale:dragon +-- ["Drill Rocket"] = "", -- Construction_Mode -- ["Drills"] = "", -- A_Classic_Fairytale:backstab +-- ["Drill Strike"] = "", -- Construction_Mode ["Drone Hunter!"] = "Lovec trubců!", --- ["Drop a bomb: [drop some heroic wind that will turn into a bomb on impact]"] = "", -- Continental_supplies +-- ["Drop a bomb: [Drop some heroic wind that will turn into a bomb on impact]"] = "", -- Continental_supplies + ["Drowner"] = "Utopenec", -- ["Dude, all the plants are gone!"] = "", -- A_Classic_Fairytale:family -- ["Dude, can you see Ramon and Spiky?"] = "", -- A_Classic_Fairytale:journey @@ -181,11 +229,15 @@ -- ["Dude, where are we?"] = "", -- A_Classic_Fairytale:backstab -- ["Dude, wow! I just had the weirdest high!"] = "", -- A_Classic_Fairytale:backstab -- ["Duration"] = "", -- Continental_supplies --- ["Dust storm: [Deals 20 damage to all enemies in the circle]"] = "", -- Continental_supplies +-- ["Dust storm: [Deals 15 damage to all enemies in the circle]"] = "", -- Continental_supplies + +-- ["Dynamite"] = "", -- Construction_Mode +-- ["Each turn is only ONE SECOND!"] = "", -- Frenzy ["Each turn you get 1-3 random weapons"] = "Každý tah dostaneš 1-3 náhodné zbraně", ["Each turn you get one random weapon"] = "Každý tah dostaneš jednu náhodnou zbraň", -- ["Eagle Eye"] = "", -- A_Classic_Fairytale:backstab --- ["Eagle Eye: [Blink to the impact ~ one shot]"] = "", -- Continental_supplies +-- ["Eagle Eye: [Blink to the impact ~ One shot]"] = "", -- Continental_supplies + -- ["Ear Sniffer"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:epil -- ["Elderbot"] = "", -- A_Classic_Fairytale:family -- ["Elimate your captor."] = "", -- User_Mission_-_The_Great_Escape @@ -208,8 +260,9 @@ -- ["Every single time!"] = "", -- A_Classic_Fairytale:dragon -- ["Everything looks OK..."] = "", -- A_Classic_Fairytale:enemy -- ["Exactly, man! That was my dream."] = "", -- A_Classic_Fairytale:backstab +-- ["Extra Damage"] = "", -- Construction_Mode +-- ["Extra Time"] = "", -- Construction_Mode -- ["Eye Chewer"] = "", -- A_Classic_Fairytale:journey --- ["INSANITY"] = "", -- Mutant -- ["Family Reunion"] = "", -- A_Classic_Fairytale:family ["Fastest lap: "] = "Nejrychlejší kolo: ", ["Feeble Resistance"] = "Slabý odpor", @@ -219,9 +272,10 @@ -- ["Femur Lover"] = "", -- A_Classic_Fairytale:shadow -- ["Fierce Competition!"] = "", -- Space_Invasion -- ["Fiery Water"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united +-- ["Filthy Blue"] = "", -- User_Mission_-_Dangerous_Ducklings -- ["Find your tribe!|Cross the lake!"] = "", -- A_Classic_Fairytale:dragon -- ["Finish your training|Hint: Animations can be skipped with the [Precise] key."] = "", -- A_Classic_Fairytale:first_blood --- ["Fire a mine: [Does what it says ~ Cant be dropped close to an enemy ~ 1 sec]"] = "", -- Continental_supplies + ["Fire"] = "Oheň", -- ["First aid kits?!"] = "", -- A_Classic_Fairytale:united -- ["First Blood"] = "", -- A_Classic_Fairytale:first_blood @@ -232,11 +286,15 @@ ["Flag returned!"] = "Vlajka navrácena!", ["Flags, and their home base will be placed where each team ends their first turn."] = "Vlajky a domovské základny budou umístěny tam, kde každý tým skončí svůj první tah.", -- ["Flamer"] = "", +-- ["Flamethrower"] = "", -- Construction_Mode -- ["Flaming Worm"] = "", -- A_Classic_Fairytale:backstab --- ["Flare: [fire up some bombs depending on hogs depending on hogs in the circle"] = "", -- Continental_supplies + -- ["Flesh for Brainz"] = "", -- A_Classic_Fairytale:journey +-- ["Flying Saucer"] = "", -- Construction_Mode, Frenzy -- ["For improved features/stability, play 0.9.18+"] = "", -- WxW -- ["Free Dense Cloud and continue the mission!"] = "", -- A_Classic_Fairytale:journey +-- ["Freezer"] = "", -- Construction_Mode +-- ["FRENZY"] = "", -- Frenzy -- ["Friendly Fire!"] = "", -- ["fuel extended!"] = "", ["GAME BEGUN!!!"] = "HRA ZAČALA!!!", @@ -246,6 +304,9 @@ -- ["Game? Was this a game to you?!"] = "", -- A_Classic_Fairytale:enemy -- ["GasBomb"] = "", -- Continental_supplies -- ["Gas Gargler"] = "", -- A_Classic_Fairytale:queen +-- ["General information"] = "", -- Continental_supplies +-- ["Generates power."] = "", -- Construction_Mode +-- ["Generator"] = "", -- Construction_Mode -- ["Get Dense Cloud out of the pit!"] = "", -- A_Classic_Fairytale:journey ["Get on over there and take him out!"] = "Běž tamhle a dostaň ho!", -- ["Get on the head of the mole"] = "", -- A_Classic_Fairytale:first_blood @@ -256,6 +317,8 @@ -- ["Get your teammates out of their natural prison and save the princess!|Hint: Drilling holes should solve everything.|Hint: It might be a good idea to place a girder before starting to drill. Just saying.|Hint: All your hedgehogs need to be above the marked height!|Hint: Leaks A Lot needs to get really close to the princess!"] = "", -- A_Classic_Fairytale:family -- ["GG!"] = "", -- User_Mission_-_Rope_Knock_Challenge -- ["Gimme Bones"] = "", -- A_Classic_Fairytale:backstab +-- ["Girder"] = "", -- Construction_Mode +-- ["Girder Placement Mode"] = "", -- Construction_Mode -- ["Glark"] = "", -- A_Classic_Fairytale:shadow ["Goal"] = "Cíl", ["GO! GO! GO!"] = "Běž! Běž! Běž!", @@ -272,12 +335,16 @@ -- ["Go surf!"] = "", -- WxW ["GOTCHA!"] = "Mám tě!", -- ["Grab Mines/Explosives"] = "", +-- ["Grants nearby hogs life-regeneration."] = "", -- Construction_Mode +-- ["Gravity"] = "", -- Gravity -- ["Great choice, Steve! Mind if I call you that?"] = "", -- A_Classic_Fairytale:shadow -- ["Great work! Now hit it with your Baseball Bat! |Tip: You can change weapon with 'Right Click'!"] = "", -- Basic_Training_-_Rope -- ["Great! You will be contacted soon for assistance."] = "", -- A_Classic_Fairytale:shadow --- ["Green lipstick bullet: [Is poisonous]"] = "", -- Continental_supplies + +-- ["Green lipstick bullet: [Poisonous, deals no damage]"] = "", -- Continental_supplies -- ["Greetings, "] = "", -- A_Classic_Fairytale:dragon -- ["Greetings, cloudy one!"] = "", -- A_Classic_Fairytale:shadow +-- ["Grenade"] = "", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 -- ["Grenade Training"] = "", -- Basic_Training_-_Grenade -- ["Grenadiers"] = "", -- Basic_Training_-_Grenade -- ["Guys, do you think there's more of them?"] = "", -- A_Classic_Fairytale:backstab @@ -285,23 +352,27 @@ -- ["Haha!"] = "", -- A_Classic_Fairytale:united ["Hahahaha!"] = "Hahahaha!", ["Haha, now THAT would be something!"] = "Haha, tak TOHLE bude něco!", +-- ["Hammer"] = "", -- Construction_Mode, Continental_supplies -- ["Hannibal"] = "", -- A_Classic_Fairytale:epil [" Hapless Hogs left!"] = "Nešťastný ježek odešel!", ["Hapless Hogs"] = "Nešťastný ježek", - -- [" HAS MUTATED"] = "", -- Mutant -- ["Hatless Jerry"] = "", -- A_Classic_Fairytale:queen -- ["Have no illusions, your tribe is dead, indifferent of your choice."] = "", -- A_Classic_Fairytale:shadow -- ["Have we ever attacked you first?"] = "", -- A_Classic_Fairytale:enemy +-- ["Healing Station"] = "", -- Construction_Mode +-- ["Health Crate Placement Mode"] = "", -- Construction_Mode -- ["Health crates extend your time."] = "", -- ["Heavy Cannfantry"] = "", -- A_Classic_Fairytale:united ["Heavy"] = "Těžký", -- ["Hedge-cogs"] = "", -- A_Classic_Fairytale:enemy --- ["Hedgehog projectile: [fire your hog like a Sticky Bomb]"] = "", -- Continental_supplies +-- ["Hedgehog projectile: [Fire your hog like a Sticky Bomb]"] = "", -- Continental_supplies + ["Hedgewars-Basketball"] = "Hedgewars-Basketbal", ["Hedgewars-Knockball"] = "Hedgewars=Vybíjená", -- ["Hedgibal Lecter"] = "", -- A_Classic_Fairytale:backstab ["Heh, it's not that bad."] = "Heh, to není tak špatné.", +-- ["Hellish Handgrenade"] = "", -- Construction_Mode -- ["Hello again, "] = "", -- A_Classic_Fairytale:family -- ["Help me, Leaks!"] = "", -- A_Classic_Fairytale:journey -- ["Help me, please!!!"] = "", -- A_Classic_Fairytale:journey @@ -333,6 +404,7 @@ -- ["Hogminator"] = "", -- A_Classic_Fairytale:family -- ["Hogs in sight!"] = "", -- Continental_supplies -- ["HOLY SHYTE!"] = "", -- Mutant +-- ["Homing Bee"] = "", -- Construction_Mode -- ["Honest Lee"] = "", -- A_Classic_Fairytale:enemy ["Hooray!"] = "Hurá!", -- ["Hostage Situation"] = "", -- A_Classic_Fairytale:family @@ -366,7 +438,6 @@ -- ["If you get stuck, use your Desert Eagle or restart the mission!|"] = "", -- A_Classic_Fairytale:journey -- ["If you know what I mean..."] = "", -- A_Classic_Fairytale:shadow -- ["If you say so..."] = "", -- A_Classic_Fairytale:shadow - -- ["I guess you'll have to kill them."] = "", -- A_Classic_Fairytale:dragon -- ["I have come to make you an offering..."] = "", -- A_Classic_Fairytale:shadow -- ["I have no idea where that mole disappeared...Can you see it?"] = "", -- A_Classic_Fairytale:shadow @@ -389,6 +460,7 @@ -- ["I'm not sure about that!"] = "", -- A_Classic_Fairytale:united -- ["Impressive...you are still dry as the corpse of a hawk after a week in the desert..."] = "", -- A_Classic_Fairytale:first_blood -- ["I'm so scared!"] = "", -- A_Classic_Fairytale:united +-- ["Increase"] = "", -- Continental_supplies -- ["Incredible..."] = "", -- A_Classic_Fairytale:shadow -- ["I need to find the others!"] = "", -- A_Classic_Fairytale:backstab -- ["I need to get to the other side of this island, fast!"] = "", -- A_Classic_Fairytale:journey @@ -397,12 +469,14 @@ -- ["I need to warn the others."] = "", -- A_Classic_Fairytale:backstab -- ["In fact, you are the only one that's been acting strangely."] = "", -- A_Classic_Fairytale:backstab -- ["In order to get to the other side, you need to collect the crates first.|"] = "", -- A_Classic_Fairytale:dragon +-- ["INSANITY"] = "", -- Mutant ["Instructor"] = "Instruktor", -- 01#Boot_Camp, User_Mission_-_Dangerous_Ducklings -- ["Interesting idea, haha!"] = "", -- A_Classic_Fairytale:enemy -- ["Interesting! Last time you said you killed a cannibal!"] = "", -- A_Classic_Fairytale:backstab -- ["In the meantime, take these and return to your \"friend\"!"] = "", -- A_Classic_Fairytale:shadow ["invaders destroyed"] = "nájezdník zničen", -- ["Invasion"] = "", -- A_Classic_Fairytale:united +-- ["Invulnerable"] = "", -- Construction_Mode -- ["I saw it with my own eyes!"] = "", -- A_Classic_Fairytale:shadow -- ["I see..."] = "", -- A_Classic_Fairytale:shadow -- ["I see you have already taken the leap of faith."] = "", -- A_Classic_Fairytale:first_blood @@ -445,6 +519,7 @@ -- ["Just kidding, none of you have died!"] = "", -- A_Classic_Fairytale:enemy -- ["Just on a walk."] = "", -- A_Classic_Fairytale:united -- ["Just wait till I get my hands on that trauma! ARGH!"] = "", -- A_Classic_Fairytale:family +-- ["Kamikaze"] = "", -- Construction_Mode ["Kamikaze Expert!"] = "Expert na sebevraždy!", -- ["Keep it up!"] = "", -- ["Kerguelen"] = "", -- Continental_supplies @@ -454,6 +529,8 @@ -- ["Kill the aliens!"] = "", -- A_Classic_Fairytale:dragon -- ["Kill the cannibal!"] = "", -- A_Classic_Fairytale:first_blood -- ["Kill the traitor...or spare his life!|Kill him or press [Precise]!"] = "", -- A_Classic_Fairytale:backstab +-- ["Land Sprayer"] = "", -- Construction_Mode +-- ["Laser Sight"] = "", -- Construction_Mode -- ["Last Target!"] = "", -- ["Leader"] = "", -- A_Classic_Fairytale:enemy -- ["Leaderbot"] = "", -- A_Classic_Fairytale:queen @@ -463,6 +540,7 @@ -- ["Leaks A Lot must survive!"] = "", -- A_Classic_Fairytale:journey -- ["Led Heart"] = "", -- A_Classic_Fairytale:queen -- ["Lee"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen +-- ["left shift"] = "", -- Continental_supplies ["[Left Shift]"] = "[Levý shift]", -- ["Let a Continent provide your weapons!"] = "", -- Continental_supplies -- ["Let me test your skills a little, will you?"] = "", -- A_Classic_Fairytale:journey @@ -473,41 +551,56 @@ -- ["Let them have a taste of my fury!"] = "", -- A_Classic_Fairytale:backstab -- ["Let us help, too!"] = "", -- A_Classic_Fairytale:backstab -- ["Light Cannfantry"] = "", -- A_Classic_Fairytale:united +-- ["Limburger"] = "", -- Construction_Mode ["Listen up, maggot!!"] = "Poslouchej, bídný červe!!", -- ["Little did they know that this hunt will mark them forever..."] = "", -- A_Classic_Fairytale:shadow -- ["Lively Lifeguard"] = "", --- ["Lonely Cries: [Rise the water if no hog is in the circle and deal 1 damage to all hogs]"] = "", -- Continental_supplies + +-- ["Lonely Cries: [Rise the water if no hog is in the circle and deal 7 damage to all enemy hogs]"] = "", -- Continental_supplies +-- ["Lonely Hog"] = "", -- ClimbHome -- ["Look, I had no choice!"] = "", -- A_Classic_Fairytale:backstab -- ["Look out! There's more of them!"] = "", -- A_Classic_Fairytale:backstab -- ["Look out! We're surrounded by cannibals!"] = "", -- A_Classic_Fairytale:enemy -- ["Looks like the whole world is falling apart!"] = "", -- A_Classic_Fairytale:enemy +-- ["Low Gravity"] = "", -- Construction_Mode, Frenzy -- ["Luckily, I've managed to snatch some of them."] = "", -- A_Classic_Fairytale:united -- ["LUDICROUS KILL"] = "", -- Mutant +-- ["Made it!"] = "", -- ClimbHome +-- ["- Massive weapon bonus on first turn"] = "", -- Continental_supplies -- ["May the spirits aid you in all your quests!"] = "", -- A_Classic_Fairytale:backstab -- ["Medicine: [Fire some exploding medicine that will heal all hogs effected by the explosion]"] = "", -- Continental_supplies -- ["MEGA KILL"] = "", -- Mutant -- ["Meiwes"] = "", -- A_Classic_Fairytale:backstab -- ["Mindy"] = "", -- A_Classic_Fairytale:united +-- ["Mine"] = "", -- Construction_Mode, Frenzy -- ["Mine Deployer"] = "", -- ["Mine Eater!"] = "", +-- ["Mine Placement Mode"] = "", -- Construction_Mode ["|- Mines Time:"] = "|- Časovač min:", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork +-- ["Mine Strike"] = "", -- Construction_Mode ["MISSION FAILED"] = "MISE NEÚSPĚŠNÁ", -- User_Mission_-_Dangerous_Ducklings, User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork ["MISSION SUCCESSFUL"] = "MISE ÚSPĚŠNÁ", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork ["MISSION SUCCESS"] = "MISE ÚSPĚŠNÁ", +-- ["Molotov Cocktail"] = "", -- Construction_Mode -- ["Molotov"] = "", -- Continental_supplies -- ["MONSTER KILL"] = "", -- Mutant -- ["More Natives"] = "", -- A_Classic_Fairytale:epil +-- ["Mortar"] = "", -- Construction_Mode, A_Space_Adventure:death02 ["Movement: [Up], [Down], [Left], [Right]"] = "Pohyb: [nahoru], [dolu], [vlevo], [vpravo]", +-- ["Mudball"] = "", -- Construction_Mode ["Multi-shot!"] = "Vícenásobná rána!", -- ["Muriel"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen -- ["Muscle Dissolver"] = "", -- A_Classic_Fairytale:shadow -- ["-------"] = "", -- Mutant +-- ["Mutant"] = "", -- Mutant -- ["Nade Boy"] = "", -- Basic_Training_-_Grenade -- ["Name"] = "", -- A_Classic_Fairytale:queen ["Nameless Heroes"] = "Bezejmenní hrdinové", -- ["Nancy Screw"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:queen +-- ["Napalm"] = "", -- Construction_Mode -- ["Napalm rocket: [Fire a bomb with napalm!]"] = "", -- Continental_supplies -- ["Natives"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:first_blood, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united +-- ["Naughty Ninja"] = "", -- User_Mission_-_Dangerous_Ducklings -- ["New Barrels Per Turn"] = "", ["NEW CLAN RECORD: "] = "NOVÝ KLANOVÝ REKORD: ", ["NEW fastest lap: "] = "NOVÉ nejrychlejší kolo: ", @@ -518,6 +611,7 @@ -- ["Nice work, "] = "", -- A_Classic_Fairytale:dragon -- ["Nice work!"] = "", -- A_Classic_Fairytale:enemy -- ["Nilarian"] = "", -- A_Classic_Fairytale:queen +-- ["Nobody Laugh"] = "", -- User_Mission_-_Nobody_Laugh -- ["No, I came back to help you out..."] = "", -- A_Classic_Fairytale:shadow -- ["No...I wonder where they disappeared?!"] = "", -- A_Classic_Fairytale:journey -- ["Nom-Nom"] = "", -- A_Classic_Fairytale:journey @@ -525,6 +619,7 @@ -- ["Nope. It was one fast mole, that's for sure."] = "", -- A_Classic_Fairytale:shadow -- ["No! Please, help me!"] = "", -- A_Classic_Fairytale:journey -- ["NORMAL"] = "", -- Continental_supplies +-- ["Normal players can only score points by killing the mutant."] = "", -- Mutant -- ["North America"] = "", -- Continental_supplies -- ["Not all hogs are born equal."] = "", -- Highlander ["NOT ENOUGH WAYPOINTS"] = "NEDOSTATEK NAVIGAČNÍCH BODŮ", @@ -537,6 +632,7 @@ -- ["No. Where did he come from?"] = "", -- A_Classic_Fairytale:shadow -- ["Now how do I get on the other side?!"] = "", -- A_Classic_Fairytale:dragon -- ["No. You and the rest of the tribe are safer there!"] = "", -- A_Classic_Fairytale:backstab +-- ["Object Placement Tool"] = "", -- Construction_Mode -- ["Obliterate them!|Hint: You might want to take cover..."] = "", -- A_Classic_Fairytale:shadow -- ["Obstacle course"] = "", -- A_Classic_Fairytale:dragon -- ["Of course I have to save her. What did I expect?!"] = "", -- A_Classic_Fairytale:family @@ -553,24 +649,30 @@ -- ["Once upon a time, on an island with great natural resources, lived two tribes in heated conflict..."] = "", -- A_Classic_Fairytale:first_blood -- ["ONE HOG PER TEAM! KILLING EXCESS HEDGES"] = "", -- Mutant -- ["One tribe was peaceful, spending their time hunting and training, enjoying the small pleasures of life..."] = "", -- A_Classic_Fairytale:first_blood +-- ["on Skip"] = "", -- Continental_supplies -- ["Oops...I dropped them."] = "", -- A_Classic_Fairytale:united -- ["Open that crate and we will continue!"] = "", -- A_Classic_Fairytale:first_blood ["Operation Diver"] = "Operace potápěč", ["Opposing Team: "] = "Protivníkův tým: ", +-- ["or 'g=50, g2=150, period=4000' for gravity changing|from 50 to 150 and back with period of 4000 msec"] = "", -- Gravity -- ["Orlando Boom!"] = "", -- A_Classic_Fairytale:queen +-- ["Other kills don't give you points."] = "", -- Mutant -- ["Ouch!"] = "", -- User_Mission_-_Rope_Knock_Challenge -- ["Our tribe, our beautiful island!"] = "", -- A_Classic_Fairytale:enemy -- ["Parachute"] = "", -- Continental_supplies ["Pathetic Hog #%d"] = "Žalostný ježek #%d", -- ["Pathetic Resistance"] = "", -- User_Mission_-_Bamboo_Thicket, User_Mission_-_Newton_and_the_Hammock +-- ["Penguin roar: [Deal 15 damage + 15% of your hogs health to all hogs around you and get 2/3 back]"] = "", -- Continental_supplies -- ["Perfect! Now try to get the next crate without hurting yourself!"] = "", -- A_Classic_Fairytale:first_blood ["Per-Hog Ammo"] = "Individuální munice", --- ["- Per team weapons|- 9 weaponschemes|- Unique new weapons| |Select continent first round with the Weapon Menu or by ([switch/tab]=Increase,[precise/left shift]=Decrease) on Skip|Some weapons have a second option. Find them with [switch/tab]"] = "", -- Continental_supplies +-- ["Personal Portal Device"] = "", -- Construction_Mode +-- ["Per team weapons"] = "", -- Continental_supplies -- ["Pfew! That was close!"] = "", -- A_Classic_Fairytale:shadow --- ["Piñata bullet: [Contains some sweet candy!]"] = "", -- Continental_supplies +-- ["Piano Strike"] = "", -- Construction_Mode +-- ["Pickhammer"] = "", -- Construction_Mode + -- ["Pings left:"] = "", -- Space_Invasion - -- ["Place more waypoints using the 'Air Attack' weapon."] = "", -- ["Planes Used:"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Planes Used"] = "", -- User_Mission_-_RCPlane_Challenge @@ -580,14 +682,18 @@ -- ["Please, stop releasing your \"smoke signals\"!"] = "", -- A_Classic_Fairytale:shadow -- ["Point Blank Combo!"] = "", -- Space_Invasion ["points"] = "body", -- Control, CTF_Blizzard, Basic_Training_-_Bazooka, Basic_Training_-_Shotgun, Basic_Training_-_Sniper_Rifle +-- ["POINTS"] = "", -- Mutant ["Poison"] = "Otrava", +-- ["Population"] = "", -- Continental_supplies -- ["Portal hint: one goes to the destination, and one is the entrance.|"] = "", -- A_Classic_Fairytale:dragon -- ["Portal mission"] = "", -- portal ["Power Remaining"] = "Zbývající energie", -- ["Prepare yourself"] = "", +-- ["presice"] = "", -- Continental_supplies -- ["Press [Enter] to accept this configuration."] = "", -- WxW -- ["Press [Left] or [Right] to move around, [Enter] to jump"] = "", -- A_Classic_Fairytale:first_blood ["Press [Precise] to skip intro"] = "Stiskni [přesnost] pro přeskočení", +-- ["Prestigious Pilot"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Private Novak"] = "", -- Basic_Training_-_Cluster_Bomb -- ["Protect yourselves!|Grenade hint: set the timer with [1-5], aim with [Up]/[Down] and hold [Space] to set power"] = "", -- A_Classic_Fairytale:shadow ["Race complexity limit reached."] = "Dosažen limit složitosti závodu.", @@ -596,25 +702,39 @@ -- ["Radar Ping"] = "", -- Space_Invasion -- ["Raging Buffalo"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united -- ["Ramon"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow +-- ["random in range from %i%% to %i%% with period of %i msec"] = "", -- Gravity +-- ["RC Plane"] = "", -- Construction_Mode -- ["RC PLANE TRAINING"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Really?! You thought you could harm me with your little toys?"] = "", -- A_Classic_Fairytale:shadow +-- ["Reflector Shield"] = "", -- Construction_Mode +-- ["Reflects enemy projectiles."] = "", -- Construction_Mode -- ["Regurgitator"] = "", -- A_Classic_Fairytale:backstab -- ["Reinforcements"] = "", -- A_Classic_Fairytale:backstab -- ["Remember: The rope only bend around objects, |if it doesn't hit anything it's always stright!"] = "", -- Basic_Training_-_Rope -- ["Remember this, pathetic animal: when the day comes, you will regret your blind loyalty!"] = "", -- A_Classic_Fairytale:shadow +-- ["REMOVED"] = "", -- Continental_supplies +-- ["Respawner"] = "", -- Construction_Mode +-- ["Resurrector"] = "", -- Construction_Mode +-- ["Resurrects dead hedgehogs."] = "", -- Construction_Mode [" - Return the enemy flag to your base to score | - First team to 3 captures wins | - You may only score when your flag is in your base | - Hogs will drop the flag if killed, or drowned | - Dropped flags may be returned or recaptured | - Hogs respawn when killed"] = " - Dones nepřátelskou vlajku do své základny k získání bodů | - První tým se třemi ukořistěními vítězí | - Můžeš bodovat, pokud je tvá vlajka v základně | - Ježci pustí vlajku, pokud jsou zabiti, nebo utopeni | - Upuštěná vlajka může být navrácena, nebo opět zajmuta | - Ježci jsou po smrti oživeni", -- ["Return to Leaks A Lot! If you get stuck, press [Precise] to try again!"] = "", -- A_Classic_Fairytale:shadow -- ["Righteous Beard"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:first_blood, A_Classic_Fairytale:queen, A_Classic_Fairytale:united +-- ["Rope"] = "", -- Construction_Mode -- ["ROPE-KNOCKING"] = "", -- User_Mission_-_Rope_Knock_Challenge +-- ["Rope to safety"] = "", -- ClimbHome -- ["Rope Training"] = "", -- Basic_Training_-_Rope -- ["Rot Molester"] = "", -- A_Classic_Fairytale:shadow -- ["Round Limit:"] = "", ["Round Limit"] = "Limit kol", -- ["Rounds Complete: "] = "", ["Rounds Complete"] = "Dokončených kol", +-- ["Rubber Band"] = "", -- Construction_Mode +-- ["Rubber Placement Mode"] = "", -- Construction_Mode +-- ["RULES"] = "", -- Frenzy, Mutant ["RULES OF THE GAME [Press ESC to view]"] = "PRAVIDLA HRY [Stiskni ESC pro prohlédnutí]", -- ["Rusty Joe"] = "", -- A_Classic_Fairytale:queen --- ["Sabotage: [Sabotage all hogs in the circle and deal ~10 dmg]"] = "", -- Continental_supplies +-- ["Sabotage/Flare: [Sabotage all hogs in the circle and deal ~1 dmg OR Fire a cluster up into the air]"] = "", -- Continental_supplies + -- ["Salivaslurper"] = "", -- A_Classic_Fairytale:united -- ["Salvation"] = "", -- A_Classic_Fairytale:family -- ["Salvation was one step closer now..."] = "", -- A_Classic_Fairytale:dragon @@ -626,7 +746,7 @@ -- ["Scalp Muncher"] = "", -- A_Classic_Fairytale:backstab -- ["Score"] = "", -- Mutant ["SCORE"] = "SKÓRE", --- ["Scream from a Walrus: [Deal 20 damage + 10% of your hogs health to all hogs around you and get half back]"] = "", -- Continental_supplies + ["sec"] = "vt.", -- CTF_Blizzard, TrophyRace, Basic_Training_-_Bazooka, Basic_Training_-_Shotgun, Basic_Training_-_Sniper_Rifle, User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork, Capture_the_Flag -- ["Seduction"] = "", -- Continental_supplies -- ["Seems like every time you take a \"walk\", the enemy find us!"] = "", -- A_Classic_Fairytale:backstab @@ -634,8 +754,11 @@ ["See ya!"] = "Uvidíme se!", -- ["Segmentation Paul"] = "", -- A_Classic_Fairytale:dragon -- ["Select continent!"] = "", -- Continental_supplies +-- ["Select continent first round with the Weapon Menu or by"] = "", -- Continental_supplies -- ["Select difficulty: [Left] - easier or [Right] - harder"] = "", -- A_Classic_Fairytale:first_blood -- ["selected!"] = "", +-- ["Set period to negative value for random gravity"] = "", -- Gravity +-- ["Setup:|'g=150', where 150 is 150% of normal gravity"] = "", -- Gravity -- ["... share your beauty with the world every morning, my princess!"] = "", -- A_Classic_Fairytale:journey -- ["She's behind that tall thingy."] = "", -- A_Classic_Fairytale:family ["Shield boosted! +30 power"] = "Štít posílen! +30 energie", @@ -646,16 +769,21 @@ ["Shield OFF:"] = "Štít VYPNUT:", ["Shield ON:"] = "Štít ZAPNUT:", ["Shield Seeker!"] = "Hledač štítů!", +-- ["Shoryuken"] = "", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 -- ["Shotgun"] = "", -- Continental_supplies ["Shotgun Team"] = "Brokovnicový tým", ["Shotgun Training"] = "Trénink s brokovnicí", -- ["shots remaining."] = "", ["Silly"] = "Hloupý", +-- ["SineGun"] = "", -- Construction_Mode ["Sinky"] = "Propadlý", -- ["Sirius Lee"] = "", -- A_Classic_Fairytale:enemy ["%s is out and Team %d|scored a penalty!| |Score:"] = "%s je venku a tým %d|má penaltu!| |Skóre:", -- Basketball, Knockball ["%s is out and Team %d|scored a point!| |Score:"] = "%s je venku a tým %d|skóruje!| |Skóre:", -- Basketball, Knockball -- ["Slippery"] = "", -- A_Classic_Fairytale:journey +-- ["Slot"] = "", -- Frenzy +-- ["Slot keys save time! (F1-F10 by default)"] = "", -- Frenzy +-- ["SLOTS"] = "", -- Frenzy -- ["Smith 0.97"] = "", -- A_Classic_Fairytale:enemy -- ["Smith 0.98"] = "", -- A_Classic_Fairytale:enemy -- ["Smith 0.99a"] = "", -- A_Classic_Fairytale:enemy @@ -667,6 +795,7 @@ ["Sniper Training"] = "Odstřelovací trénink", ["Sniperz"] = "Snajpři", -- ["So humiliating..."] = "", -- A_Classic_Fairytale:first_blood +-- ["Some weapons have a second option. Find them with"] = "", -- Continental_supplies -- ["South America"] = "", -- Continental_supplies -- ["So? What will it be?"] = "", -- A_Classic_Fairytale:shadow -- ["Spawn the crate, and attack!"] = "", -- WxW @@ -675,6 +804,8 @@ -- ["Spleenlover"] = "", -- A_Classic_Fairytale:united ["Sponge"] = "Mycí houba", ["Spooky Tree"] = "Strašidelný strom", +-- ["Sprite Placement Mode"] = "", -- Construction_Mode +-- ["Sprite Testing Mode"] = "", -- Construction_Mode ["s|"] = "s|", ["s"] = "s", -- GaudyRacer, Space_Invasion ["STATUS UPDATE"] = "AKTUALIZACE STAVU", -- GaudyRacer, Space_Invasion @@ -682,20 +813,36 @@ -- ["Step By Step"] = "", -- A_Classic_Fairytale:first_blood -- ["Steve"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen -- ["Sticky Mine"] = "", -- Continental_supplies +-- ["Sticky Mine Placement Mode"] = "", -- Construction_Mode -- ["Stronglings"] = "", -- A_Classic_Fairytale:shadow --- ["Structure"] = "", -- Continental_supplies + +-- ["Structure Placement Mode"] = "", -- Construction_Mode +-- ["Structure Placement Tool"] = "", -- Construction_Mode +-- ["Sundaland"] = "", -- Continental_supplies -- ["Super Weapons"] = "", -- WxW +-- ["Support Station"] = "", -- Construction_Mode -- ["Surf Before Crate"] = "", -- WxW -- ["Surfer! +15 points!"] = "", -- Space_Invasion -- ["Surfer!"] = "", -- WxW -- ["Survive!|Hint: Cinematics can be skipped with the [Precise] key."] = "", -- A_Classic_Fairytale:shadow -- ["Swing, Leaks A Lot, on the wings of the wind!"] = "", -- A_Classic_Fairytale:first_blood +-- ["switch"] = "", -- Continental_supplies ["Switched to "] = "Přepnut na ", +-- ["Switch Hog"] = "", -- Construction_Mode -- ["Syntax Errol"] = "", -- A_Classic_Fairytale:dragon +-- ["tab"] = "", -- Continental_supplies +-- ["Tagging Mode"] = "", -- Construction_Mode -- ["Talk about mixed signals..."] = "", -- A_Classic_Fairytale:dragon +-- ["Tardis"] = "", -- Construction_Mode +-- ["Target Placement Mode"] = "", -- Construction_Mode ["Team %d: "] = "Tým %d: ", ["Team Scores"] = "Týmové skóre", -- Control, Space_Invasion +-- ["Teleporation Node"] = "", -- Construction_Mode +-- ["Teleportation Mode"] = "", -- Construction_Mode +-- ["Teleportation Node"] = "", -- Construction_Mode +-- ["Teleport"] = "", -- Construction_Mode, Frenzy -- ["Teleport hint: just use the mouse to select the destination!"] = "", -- A_Classic_Fairytale:dragon +-- ["Teleport Unsuccessful. Please teleport within a clan teleporter's sphere of influence."] = "", -- Construction_Mode -- ["Thanks!"] = "", -- A_Classic_Fairytale:family -- ["Thank you, my hero!"] = "", -- A_Classic_Fairytale:family -- ["Thank you, oh, thank you, Leaks A Lot!"] = "", -- A_Classic_Fairytale:journey @@ -712,6 +859,7 @@ ["That was pointless."] = "To bylo bezúčelné.", -- ["The answer is...entertaintment. You'll see what I mean."] = "", -- A_Classic_Fairytale:backstab -- ["The anti-portal zone is all over the floor, and I have nothing to kill him...Droping something could hurt him enough to kill him..."] = "", -- portal +-- ["The Bottom Feeder can score points by killing anyone."] = "", -- Mutant -- ["The Bull's Eye"] = "", -- A_Classic_Fairytale:first_blood -- ["The caves are well hidden, they won't find us there!"] = "", -- A_Classic_Fairytale:united -- ["The Crate Frenzy"] = "", -- A_Classic_Fairytale:first_blood @@ -721,20 +869,26 @@ -- ["The Enemy Of My Enemy"] = "", -- A_Classic_Fairytale:enemy -- ["The First Blood"] = "", -- A_Classic_Fairytale:first_blood -- ["The First Encounter"] = "", -- A_Classic_Fairytale:shadow +-- ["The first player to kill someone becomes the Mutant."] = "", -- Mutant ["The flag will respawn next round."] = "Vlajka se obnoví příští kolo.", -- ["The food bites back"] = "", -- A_Classic_Fairytale:backstab -- ["The giant umbrella from the last crate should help break the fall."] = "", -- A_Classic_Fairytale:first_blood -- ["The Great Escape"] = "", -- User_Mission_-_The_Great_Escape +-- ["The Great Hog in the sky sees your sadness and grants you a boon."] = "", -- Construction_Mode -- ["The guardian"] = "", -- A_Classic_Fairytale:shadow -- ["The Individualist"] = "", -- A_Classic_Fairytale:shadow -- ["Their buildings were very primitive back then, even for an uncivilised island."] = "", -- A_Classic_Fairytale:united -- ["The Journey Back"] = "", -- A_Classic_Fairytale:journey -- ["The Leap of Faith"] = "", -- A_Classic_Fairytale:first_blood -- ["The Moonwalk"] = "", -- A_Classic_Fairytale:journey +-- ["The Mutant has super-weapons and a lot of health."] = "", -- Mutant +-- ["The Mutant loses health quickly if he doesn't keep scoring kills."] = "", -- Mutant ["The Nameless One"] = "Bezejmenný", -- ["The next one is pretty hard! |Tip: You have to do multiple swings!"] = "", -- Basic_Training_-_Rope -- ["Then how do they keep appearing?"] = "", -- A_Classic_Fairytale:shadow -- ["The other one were all cannibals, spending their time eating the organs of fellow hedgehogs..."] = "", -- A_Classic_Fairytale:first_blood +-- ["The player with least points (or most deaths) becomes the Bottom Feeder."] = "", -- Mutant +-- ["There are a variety of structures available to aid you."] = "", -- Construction_Mode -- ["There must be a spy among us!"] = "", -- A_Classic_Fairytale:backstab -- ["There's more of them? When did they become so hungry?"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united -- ["There's nothing more satisfying for me than seeing you share your beauty with the world every morning, my princess!"] = "", -- A_Classic_Fairytale:journey @@ -790,7 +944,7 @@ -- ["To the caves..."] = "", -- A_Classic_Fairytale:united ["Toxic Team"] = "Jedovatý tým", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork ["TRACK COMPLETED"] = "TRASA KOMPLETNÍ", --- ["TRACK FAILED!"] = "", + -- ["training"] = "", -- portal -- ["Traitors"] = "", -- A_Classic_Fairytale:epil -- ["Tribe"] = "", -- A_Classic_Fairytale:backstab @@ -807,6 +961,7 @@ -- ["ULTRA KILL"] = "", -- Mutant -- ["Under Construction"] = "", -- A_Classic_Fairytale:shadow -- ["Unexpected Igor"] = "", -- A_Classic_Fairytale:dragon +-- ["Unique new weapons"] = "", -- Continental_supplies -- ["Unit"] = "", -- ["Unit 0x0007"] = "", -- A_Classic_Fairytale:family -- ["Unit 334a$7%;.*"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united @@ -821,11 +976,14 @@ -- ["Use it wisely!"] = "", -- A_Classic_Fairytale:dragon -- ["Use it with precaution!"] = "", -- A_Classic_Fairytale:first_blood ["User Challenge"] = "Výzva", - +-- ["Use the air-attack weapons and the arrow keys to select structures."] = "", -- Construction_Mode -- ["Use the portal gun to get to the next crate, then use the new gun to get to the final destination!|"] = "", -- A_Classic_Fairytale:dragon -- ["Use the rope to get on the head of the mole, young one!"] = "", -- A_Classic_Fairytale:first_blood -- ["Use the rope to knock your enemies to their doom."] = "", -- User_Mission_-_Rope_Knock_Challenge +-- ["Use your ready time to think."] = "", -- Frenzy ["Use your rope to get from start to finish as fast as you can!"] = "Použij lano a dostaň se ze startu do cíle, jak nejrychleji umíš!", +-- ["Utility Crate Placement Mode"] = "", -- Construction_Mode +-- ["Vampirism"] = "", -- Construction_Mode -- ["Vedgies"] = "", -- A_Classic_Fairytale:journey -- ["Vegan Jack"] = "", -- A_Classic_Fairytale:enemy -- ["Victory!"] = "", -- Basic_Training_-_Rope @@ -837,10 +995,14 @@ -- ["Wannabe Flyboys"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Wannabe Shoppsta"] = "", -- User_Mission_-_Rope_Knock_Challenge -- ["Watch your steps, young one!"] = "", -- A_Classic_Fairytale:first_blood +-- ["Watermelon Bomb"] = "", -- Construction_Mode ["Waypoint placed."] = "Navigační bod umístěn.", -- ["Way-Points Remaining"] = "", -- ["Weaklings"] = "", -- A_Classic_Fairytale:shadow -- ["We all know what happens when you get frightened..."] = "", -- A_Classic_Fairytale:first_blood +-- ["Weapon Crate Placement Mode"] = "", -- Construction_Mode +-- ["Weapon Filter"] = "", -- Construction_Mode +-- ["weaponschemes"] = "", -- Continental_supplies -- ["Weapons reset."] = "", -- Highlander ["Weapons Reset"] = "Zbraně obnoveny", -- ["We are indeed."] = "", -- A_Classic_Fairytale:backstab @@ -893,6 +1055,7 @@ -- ["Where do you get that?!"] = "", -- A_Classic_Fairytale:enemy -- ["Where have you been?!"] = "", -- A_Classic_Fairytale:backstab -- ["Where have you been?"] = "", -- A_Classic_Fairytale:united +-- ["Whip"] = "", -- Construction_Mode -- ["? Why?"] = "", -- A_Classic_Fairytale:backstab -- ["Why "] = "", -- A_Classic_Fairytale:backstab -- ["! Why?!"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united @@ -905,8 +1068,10 @@ -- ["Why me?!"] = "", -- A_Classic_Fairytale:backstab -- ["Why would they do this?"] = "", -- A_Classic_Fairytale:backstab -- ["- Will Get 1-3 random weapons"] = "", -- Continental_supplies --- ["- Will refresh Parachute each turn."] = "", -- Continental_supplies --- ["- Will refresh portalgun each turn."] = "", -- Continental_supplies +-- ["- Will give you an airstrike every fifth turn."] = "", -- Continental_supplies +-- ["- Will give you a parachute every second turn."] = "", -- Continental_supplies + + -- ["Will this ever end?"] = "", -- ["WINNER IS "] = "", -- Mutant ["WINNING TIME: "] = "VÍTĚZNÝ ČAS: ", @@ -925,6 +1090,7 @@ -- ["Yes!"] = "", -- A_Classic_Fairytale:enemy -- ["Yes, yeees! You are now ready to enter the real world!"] = "", -- A_Classic_Fairytale:first_blood -- ["Yo, dude, we're here, too!"] = "", -- A_Classic_Fairytale:family +-- ["You are far from home, and the water is rising, climb up as high as you can!"] = "", -- ClimbHome -- ["You are given the chance to turn your life around..."] = "", -- A_Classic_Fairytale:shadow -- ["You are playing with our lives here!"] = "", -- A_Classic_Fairytale:enemy -- ["! You bastards!"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united @@ -957,6 +1123,8 @@ -- ["You know what? I don't even regret anything!"] = "", -- A_Classic_Fairytale:backstab -- ["You'll see what I mean!"] = "", -- A_Classic_Fairytale:enemy -- ["You may only attack from a rope!"] = "", -- WxW +-- ["You may only spawn 5 crates per turn."] = "", -- Construction_Mode +-- ["You may only use 1 Extra Time per turn."] = "", -- Construction_Mode -- ["You meatbags are pretty slow, you know!"] = "", -- A_Classic_Fairytale:enemy -- ["You might want to find a way to instantly kill arriving cannibals!"] = "", -- A_Classic_Fairytale:backstab -- ["Young one, you are telling us that they can instantly change location without a shaman?"] = "", -- A_Classic_Fairytale:united @@ -977,6 +1145,7 @@ ["You've failed. Try again."] = "Zklamal jsi. Zkus to znovu.", ["You've reached the goal!| |Time: "] = "Dosáhl jsi cíle!| |Čas: ", -- ["You will be avenged!"] = "", -- A_Classic_Fairytale:shadow +-- ["- You will recieve 2-4 weapons on each kill! (Even on own hogs)"] = "", -- Continental_supplies -- ["You won't believe what happened to me!"] = "", -- A_Classic_Fairytale:backstab -- ["Yuck! I bet they'll keep worshipping her even after I save the village!"] = "", -- A_Classic_Fairytale:family -- ["Zealandia"] = "", -- Continental_supplies diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/da.lua --- a/share/hedgewars/Data/Locale/da.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/da.lua Tue Nov 10 20:43:13 2015 +0100 @@ -4,6 +4,10 @@ ["..."] = "...", -- ["011101000"] = "", -- A_Classic_Fairytale:dragon -- ["011101001"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:family, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united +-- ["+1 to a Bottom Feeder for killing anyone"] = "", -- Mutant +-- ["+1 to a Mutant for killing anyone"] = "", -- Mutant +-- ["-1 to anyone for a suicide"] = "", -- Mutant +-- ["+2 for becoming a Mutant"] = "", -- Mutant -- ["30 minutes later..."] = "", -- A_Classic_Fairytale:shadow -- ["About a month ago, a cyborg came and told us that you're the cannibals!"] = "", -- A_Classic_Fairytale:enemy ["Accuracy Bonus!"] = "Præcisionsbonus", @@ -13,17 +17,27 @@ -- ["???"] = "", -- A_Classic_Fairytale:backstab -- ["Actually, you aren't worthy of life! Take this..."] = "", -- A_Classic_Fairytale:shadow -- ["A cy-what?"] = "", -- A_Classic_Fairytale:enemy +-- ["Advanced Repositioning Mode"] = "", -- Construction_Mode -- ["Adventurous"] = "", -- A_Classic_Fairytale:journey +-- ["a frenetic Hedgewars mini-game"] = "", -- Frenzy -- ["Africa"] = "", -- Continental_supplies -- ["After Leaks A Lot betrayed his tribe, he joined the cannibals..."] = "", -- A_Classic_Fairytale:first_blood -- ["After the shock caused by the enemy spy, Leaks A Lot and Dense Cloud went hunting to relax."] = "", -- A_Classic_Fairytale:shadow -- ["Again with the 'cannibals' thing!"] = "", -- A_Classic_Fairytale:enemy +-- ["Aggressively removes enemy hedgehogs."] = "", -- Construction_Mode -- ["a Hedgewars challenge"] = "", -- User_Mission_-_RCPlane_Challenge, User_Mission_-_Rope_Knock_Challenge ["a Hedgewars mini-game"] = "et Hedgewars-minispil", -- Space_Invasion, The_Specialists +-- ["a Hedgewars tag game"] = "", -- Mutant +-- ["AHHh, home sweet home. Made it in %d seconds."] = "", -- ClimbHome ["Aiming Practice"] = "Sigtetræning", --Bazooka, Shotgun, SniperRifle +-- ["Air Attack"] = "", -- Construction_Mode -- ["A leap in a leap"] = "", -- A_Classic_Fairytale:first_blood -- ["A little gift from the cyborgs"] = "", -- A_Classic_Fairytale:shadow -- ["All gone...everything!"] = "", -- A_Classic_Fairytale:enemy +-- ["Allows free teleportation between other nodes."] = "", -- Construction_Mode +-- ["Allows placement of girders, rubber-bands, mines, sticky mines and barrels."] = "", -- Construction_Mode +-- ["Allows placement of structures."] = "", -- Construction_Mode +-- ["Allows the placement of weapons, utiliites, and health crates."] = "", -- Construction_Mode -- ["All right, we just need to get to the other side of the island!"] = "", -- A_Classic_Fairytale:journey -- ["All walls touched!"] = "", -- WxW ["Ammo"] = "Ammunition", @@ -38,8 +52,11 @@ -- ["And so they discovered that cyborgs weren't invulnerable..."] = "", -- A_Classic_Fairytale:journey -- ["And where's all the weed?"] = "", -- A_Classic_Fairytale:dragon -- ["And you believed me? Oh, god, that's cute!"] = "", -- A_Classic_Fairytale:journey --- ["Anno 1032: [The explosion will make a strong push ~ wide range, wont affect hogs close to the target]"] = "", -- Continental_supplies +-- ["Anno 1032: [The explosion will make a strong push ~ Wide range, wont affect hogs close to the target]"] = "", -- Continental_supplies + -- ["Antarctica"] = "", -- Continental_supplies +-- ["Antarctic summer: - Will give you one girder/mudball and two sineguns/portals every fourth turn."] = "", -- Continental_supplies +-- ["Area"] = "", -- Continental_supplies -- ["Are we there yet?"] = "", -- A_Classic_Fairytale:shadow -- ["Are you accusing me of something?"] = "", -- A_Classic_Fairytale:backstab -- ["Are you saying that many of us have died for your entertainment?"] = "", -- A_Classic_Fairytale:enemy @@ -59,27 +76,35 @@ ["[Backspace]"] = "[Tilbage]", -- ["Backstab"] = "", -- A_Classic_Fairytale:backstab -- ["Bad Team"] = "", -- User_Mission_-_The_Great_Escape +-- ["Ballgun"] = "", -- Construction_Mode ["Bamboo Thicket"] = "Bambusbuskads", ["Barrel Eater!"] = "Tøndeæder!", ["Barrel Launcher"] = "Tøndekaster", +-- ["Barrel Placement Mode"] = "", -- Construction_Mode +-- ["Baseball Bat"] = "", -- Construction_Mode -- ["Baseballbat"] = "", -- Continental_supplies ["Bat balls at your enemies and|push them into the sea!"] = "Slå bolde på dine fjender og|skub dem i havet!", ["Bat your opponents through the|baskets and out of the map!"] = "Slå dine modstandere gennem|kurvene og ud af banen!", +-- ["Bazooka"] = "", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 ["Bazooka Training"] = "Træning med Bazooka", -- ["Beep Loopers"] = "", -- A_Classic_Fairytale:queen ["Best laps per team: "] = "Bedste omgang per hold: ", ["Best Team Times: "] = "Bedste Holdtid: ", -- ["Beware, though! If you are slow, you die!"] = "", -- A_Classic_Fairytale:dragon +-- ["Bio-Filter"] = "", -- Construction_Mode -- ["Biomechanic Team"] = "", -- A_Classic_Fairytale:family +-- ["Birdy"] = "", -- Construction_Mode -- ["Blender"] = "", -- A_Classic_Fairytale:family -- ["Bloodpie"] = "", -- A_Classic_Fairytale:backstab -- ["Bloodrocutor"] = "", -- A_Classic_Fairytale:shadow -- ["Bloodsucker"] = "", -- A_Classic_Fairytale:shadow ["Bloody Rookies"] = "Forbandede Begyndere", -- 01#Boot_Camp, User_Mission_-_Dangerous_Ducklings, User_Mission_-_Diver, User_Mission_-_Spooky_Tree +-- ["Blowtorch"] = "", -- Construction_Mode, Frenzy +-- ["Blue Team"] = "", -- User_Mission_-_Dangerous_Ducklings -- ["Bone Jackson"] = "", -- A_Classic_Fairytale:backstab -- ["Bonely"] = "", -- A_Classic_Fairytale:shadow + ["BOOM!"] = "BUM!", ["Boom!"] = "Bum!", - ["BOOM!"] = "BUM!", ["Boss defeated!"] = "Boss besejret!", ["Boss Slayer!"] = "Boss-morder!", -- ["Brain Blower"] = "", -- A_Classic_Fairytale:journey @@ -89,6 +114,7 @@ -- ["Brain Teaser"] = "", -- A_Classic_Fairytale:backstab -- ["Brutal Lily"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil -- ["Brutus"] = "", -- A_Classic_Fairytale:backstab +-- ["Build a fortress and destroy your enemy."] = "", -- Construction_Mode ["Build a track and race."] = "Byg en bane og ræs.", -- ["Bullseye"] = "", -- A_Classic_Fairytale:dragon -- ["But it proved to be no easy task!"] = "", -- A_Classic_Fairytale:dragon @@ -99,6 +125,7 @@ -- ["But why would they help us?"] = "", -- A_Classic_Fairytale:backstab -- ["But you're cannibals. It's what you do."] = "", -- A_Classic_Fairytale:enemy -- ["But you said you'd let her go!"] = "", -- A_Classic_Fairytale:journey +-- ["Cake"] = "", -- Construction_Mode -- ["Call me Beep! Well, 'cause I'm such a nice...person!"] = "", -- A_Classic_Fairytale:family -- ["Cannibals"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:first_blood -- ["Cannibal Sentry"] = "", -- A_Classic_Fairytale:journey @@ -108,8 +135,15 @@ -- ["Carol"] = "", -- A_Classic_Fairytale:family -- ["CHALLENGE COMPLETE"] = "", -- User_Mission_-_RCPlane_Challenge ["Change Weapon"] = "Skift Våben", +-- ["changing range from %i%% to %i%% with period of %i msec"] = "", -- Gravity -- ["Choose your side! If you want to join the strange man, walk up to him.|Otherwise, walk away from him. If you decide to att...nevermind..."] = "", -- A_Classic_Fairytale:shadow +-- ["Cleaver"] = "", -- Construction_Mode +-- ["Cleaver Placement Mode"] = "", -- Construction_Mode +-- ["Climber"] = "", -- ClimbHome +-- ["Climb Home"] = "", -- ClimbHome +-- ["Clowns"] = "", -- User_Mission_-_Nobody_Laugh ["Clumsy"] = "Kluntet", +-- ["Cluster Bomb"] = "", -- Construction_Mode -- ["Cluster Bomb MASTER!"] = "", -- Basic_Training_-_Cluster_Bomb -- ["Cluster Bomb Training"] = "", -- Basic_Training_-_Cluster_Bomb ["Codename: Teamwork"] = "Kodeord: Samarbejde", @@ -129,12 +163,19 @@ -- ["Congratulations! You needed only half of time|to eliminate all targets."] = "", -- Basic_Training_-_Cluster_Bomb -- ["Congratulations! You've completed the Rope tutorial! |- Tutorial ends in 10 seconds!"] = "", -- Basic_Training_-_Rope ["Congratulations! You've eliminated all targets|within the allowed time frame."] = "Tillykke! Du har elimineret alle målene|inden for den tilladte tidsramme.", --Bazooka, Shotgun, SniperRifle +-- ["CONSTRUCTION MODE"] = "", -- Construction_Mode +-- ["Construction Station"] = "", -- Construction_Mode -- ["Continental supplies"] = "", -- Continental_supplies ["Control pillars to score points."] = "Kontroller søjler for at score point.", +-- ["Core"] = "", -- Construction_Mode -- ["Corporationals"] = "", -- A_Classic_Fairytale:queen -- ["Corpsemonger"] = "", -- A_Classic_Fairytale:shadow -- ["Corpse Thrower"] = "", -- A_Classic_Fairytale:epil +-- ["Cost"] = "", -- Construction_Mode +-- ["Crate Placement Tool"] = "", -- Construction_Mode -- ["Crates Left:"] = "", -- User_Mission_-_RCPlane_Challenge +-- ["Cricket time: [Drop a fireable mine! ~ Will work if fired close to your hog & far away from enemy ~ 1 sec]"] = "", -- Continental_supplies +-- ["Current setting is "] = "", -- Gravity ["Cybernetic Empire"] = "Kybernetisk Imperium", -- ["Cyborg. It's what the aliens call themselves."] = "", -- A_Classic_Fairytale:enemy -- ["Dahmer"] = "", -- A_Classic_Fairytale:backstab @@ -142,15 +183,19 @@ ["DAMMIT, ROOKIE! GET OFF MY HEAD!"] = "FOR HELVEDE, REKRUT! KOM NED DERFRA!", ["Dangerous Ducklings"] = "Farlige Ællinger", ["Deadweight"] = "Dødvægt", +-- ["Decrease"] = "", -- Continental_supplies -- ["Defeat the cannibals"] = "", -- A_Classic_Fairytale:backstab -- ["Defeat the cannibals!|"] = "", -- A_Classic_Fairytale:united -- ["Defeat the cannibals!|Grenade hint: set the timer with [1-5], aim with [Up]/[Down] and hold [Space] to set power"] = "", -- A_Classic_Fairytale:shadow -- ["Defeat the cyborgs!"] = "", -- A_Classic_Fairytale:enemy +-- ["Defend your core from the enemy."] = "", -- Construction_Mode -- ["Defend yourself!|Hint: You can get tips on using weapons by moving your mouse over them in the weapon selection menu"] = "", -- A_Classic_Fairytale:shadow +-- ["Dematerializes weapons and equipment carried by enemy hedgehogs."] = "", -- Construction_Mode ["Demolition is fun!"] = "Nedrivning er sjovt!", -- ["Dense Cloud"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united -- ["Dense Cloud must have already told them everything..."] = "", -- A_Classic_Fairytale:shadow ["Depleted Kamikaze!"] = "Udtømt Kamikaze!", +-- ["Desert Eagle"] = "", -- Construction_Mode, A_Space_Adventure:death02 -- ["Destroy him, Leaks A Lot! He is responsible for the deaths of many of us!"] = "", -- A_Classic_Fairytale:first_blood ["Destroy invaders to score points."] = "Tilintetgør indtrængere for at score point.", -- ["Destroy the targets!|Hint: Select the Shoryuken and hit [Space]|P.S. You can use it mid-air."] = "", -- A_Classic_Fairytale:first_blood @@ -169,9 +214,12 @@ -- ["Do you have any idea how valuable grass is?"] = "", -- A_Classic_Fairytale:enemy -- ["Do you think you're some kind of god?"] = "", -- A_Classic_Fairytale:enemy -- ["Dragon's Lair"] = "", -- A_Classic_Fairytale:dragon +-- ["Drill Rocket"] = "", -- Construction_Mode -- ["Drills"] = "", -- A_Classic_Fairytale:backstab +-- ["Drill Strike"] = "", -- Construction_Mode ["Drone Hunter!"] = "Dronjæger!", --- ["Drop a bomb: [drop some heroic wind that will turn into a bomb on impact]"] = "", -- Continental_supplies +-- ["Drop a bomb: [Drop some heroic wind that will turn into a bomb on impact]"] = "", -- Continental_supplies + ["Drowner"] = "Drukner", -- ["Dude, all the plants are gone!"] = "", -- A_Classic_Fairytale:family -- ["Dude, can you see Ramon and Spiky?"] = "", -- A_Classic_Fairytale:journey @@ -181,11 +229,15 @@ -- ["Dude, where are we?"] = "", -- A_Classic_Fairytale:backstab -- ["Dude, wow! I just had the weirdest high!"] = "", -- A_Classic_Fairytale:backstab -- ["Duration"] = "", -- Continental_supplies --- ["Dust storm: [Deals 20 damage to all enemies in the circle]"] = "", -- Continental_supplies +-- ["Dust storm: [Deals 15 damage to all enemies in the circle]"] = "", -- Continental_supplies + +-- ["Dynamite"] = "", -- Construction_Mode +-- ["Each turn is only ONE SECOND!"] = "", -- Frenzy ["Each turn you get 1-3 random weapons"] = "Hver tur får du 1-3 tilfældige våben", ["Each turn you get one random weapon"] = "Hver tur får du ét tilfældigt våben", -- ["Eagle Eye"] = "", -- A_Classic_Fairytale:backstab --- ["Eagle Eye: [Blink to the impact ~ one shot]"] = "", -- Continental_supplies +-- ["Eagle Eye: [Blink to the impact ~ One shot]"] = "", -- Continental_supplies + -- ["Ear Sniffer"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:epil -- ["Elderbot"] = "", -- A_Classic_Fairytale:family -- ["Elimate your captor."] = "", -- User_Mission_-_The_Great_Escape @@ -208,8 +260,9 @@ -- ["Every single time!"] = "", -- A_Classic_Fairytale:dragon -- ["Everything looks OK..."] = "", -- A_Classic_Fairytale:enemy -- ["Exactly, man! That was my dream."] = "", -- A_Classic_Fairytale:backstab +-- ["Extra Damage"] = "", -- Construction_Mode +-- ["Extra Time"] = "", -- Construction_Mode -- ["Eye Chewer"] = "", -- A_Classic_Fairytale:journey --- ["INSANITY"] = "", -- Mutant -- ["Family Reunion"] = "", -- A_Classic_Fairytale:family ["Fastest lap: "] = "Hurtigste omgang: ", ["Feeble Resistance"] = "Sølle Modstand", @@ -219,9 +272,10 @@ -- ["Femur Lover"] = "", -- A_Classic_Fairytale:shadow -- ["Fierce Competition!"] = "", -- Space_Invasion -- ["Fiery Water"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united +-- ["Filthy Blue"] = "", -- User_Mission_-_Dangerous_Ducklings -- ["Find your tribe!|Cross the lake!"] = "", -- A_Classic_Fairytale:dragon -- ["Finish your training|Hint: Animations can be skipped with the [Precise] key."] = "", -- A_Classic_Fairytale:first_blood --- ["Fire a mine: [Does what it says ~ Cant be dropped close to an enemy ~ 1 sec]"] = "", -- Continental_supplies + ["Fire"] = "Skyd", -- ["First aid kits?!"] = "", -- A_Classic_Fairytale:united -- ["First Blood"] = "", -- A_Classic_Fairytale:first_blood @@ -232,11 +286,15 @@ ["Flag returned!"] = "Flag returneret!", ["Flags, and their home base will be placed where each team ends their first turn."] = "Flag og deres hjemmebase bliver placeret der hvor hvert hold afslutter sin første tur.", ["Flamer"] = "Hetzer", +-- ["Flamethrower"] = "", -- Construction_Mode -- ["Flaming Worm"] = "", -- A_Classic_Fairytale:backstab --- ["Flare: [fire up some bombs depending on hogs depending on hogs in the circle"] = "", -- Continental_supplies + -- ["Flesh for Brainz"] = "", -- A_Classic_Fairytale:journey +-- ["Flying Saucer"] = "", -- Construction_Mode, Frenzy -- ["For improved features/stability, play 0.9.18+"] = "", -- WxW -- ["Free Dense Cloud and continue the mission!"] = "", -- A_Classic_Fairytale:journey +-- ["Freezer"] = "", -- Construction_Mode +-- ["FRENZY"] = "", -- Frenzy ["Friendly Fire!"] = "Egenbeskydning!", ["fuel extended!"] = "brændstof udstrakt!", ["GAME BEGUN!!!"] = "SPILLET ER STARTET!!!", @@ -246,6 +304,9 @@ -- ["Game? Was this a game to you?!"] = "", -- A_Classic_Fairytale:enemy -- ["GasBomb"] = "", -- Continental_supplies -- ["Gas Gargler"] = "", -- A_Classic_Fairytale:queen +-- ["General information"] = "", -- Continental_supplies +-- ["Generates power."] = "", -- Construction_Mode +-- ["Generator"] = "", -- Construction_Mode -- ["Get Dense Cloud out of the pit!"] = "", -- A_Classic_Fairytale:journey ["Get on over there and take him out!"] = "Kom derover og tag ham ud!", -- ["Get on the head of the mole"] = "", -- A_Classic_Fairytale:first_blood @@ -256,6 +317,8 @@ -- ["Get your teammates out of their natural prison and save the princess!|Hint: Drilling holes should solve everything.|Hint: It might be a good idea to place a girder before starting to drill. Just saying.|Hint: All your hedgehogs need to be above the marked height!|Hint: Leaks A Lot needs to get really close to the princess!"] = "", -- A_Classic_Fairytale:family -- ["GG!"] = "", -- User_Mission_-_Rope_Knock_Challenge -- ["Gimme Bones"] = "", -- A_Classic_Fairytale:backstab +-- ["Girder"] = "", -- Construction_Mode +-- ["Girder Placement Mode"] = "", -- Construction_Mode -- ["Glark"] = "", -- A_Classic_Fairytale:shadow ["Goal"] = "Mål", ["GO! GO! GO!"] = "GO! GO! GO!", @@ -272,12 +335,16 @@ -- ["Go surf!"] = "", -- WxW ["GOTCHA!"] = "FIK DIG!", ["Grab Mines/Explosives"] = "Snup Miner/Sprængstof", +-- ["Grants nearby hogs life-regeneration."] = "", -- Construction_Mode +-- ["Gravity"] = "", -- Gravity -- ["Great choice, Steve! Mind if I call you that?"] = "", -- A_Classic_Fairytale:shadow -- ["Great work! Now hit it with your Baseball Bat! |Tip: You can change weapon with 'Right Click'!"] = "", -- Basic_Training_-_Rope -- ["Great! You will be contacted soon for assistance."] = "", -- A_Classic_Fairytale:shadow --- ["Green lipstick bullet: [Is poisonous]"] = "", -- Continental_supplies + +-- ["Green lipstick bullet: [Poisonous, deals no damage]"] = "", -- Continental_supplies -- ["Greetings, "] = "", -- A_Classic_Fairytale:dragon -- ["Greetings, cloudy one!"] = "", -- A_Classic_Fairytale:shadow +-- ["Grenade"] = "", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 -- ["Grenade Training"] = "", -- Basic_Training_-_Grenade -- ["Grenadiers"] = "", -- Basic_Training_-_Grenade -- ["Guys, do you think there's more of them?"] = "", -- A_Classic_Fairytale:backstab @@ -285,23 +352,27 @@ -- ["Haha!"] = "", -- A_Classic_Fairytale:united ["Hahahaha!"] = "Hahahaha!", ["Haha, now THAT would be something!"] = "Haha, ja DET ville være noget!", +-- ["Hammer"] = "", -- Construction_Mode, Continental_supplies -- ["Hannibal"] = "", -- A_Classic_Fairytale:epil [" Hapless Hogs left!"] = " Uheldige Pindsvin gik!", ["Hapless Hogs"] = "Uheldige Pindsvin", - -- [" HAS MUTATED"] = "", -- Mutant -- ["Hatless Jerry"] = "", -- A_Classic_Fairytale:queen -- ["Have no illusions, your tribe is dead, indifferent of your choice."] = "", -- A_Classic_Fairytale:shadow -- ["Have we ever attacked you first?"] = "", -- A_Classic_Fairytale:enemy +-- ["Healing Station"] = "", -- Construction_Mode +-- ["Health Crate Placement Mode"] = "", -- Construction_Mode ["Health crates extend your time."] = "Kasse med helbredelse forlænger din tid.", -- ["Heavy Cannfantry"] = "", -- A_Classic_Fairytale:united ["Heavy"] = "Tung", -- ["Hedge-cogs"] = "", -- A_Classic_Fairytale:enemy --- ["Hedgehog projectile: [fire your hog like a Sticky Bomb]"] = "", -- Continental_supplies +-- ["Hedgehog projectile: [Fire your hog like a Sticky Bomb]"] = "", -- Continental_supplies + ["Hedgewars-Basketball"] = "Hedgewars-Basketball", ["Hedgewars-Knockball"] = "Hedgewars-Knockball", -- ["Hedgibal Lecter"] = "", -- A_Classic_Fairytale:backstab ["Heh, it's not that bad."] = "Heh, det er ikke så slemt.", +-- ["Hellish Handgrenade"] = "", -- Construction_Mode -- ["Hello again, "] = "", -- A_Classic_Fairytale:family -- ["Help me, Leaks!"] = "", -- A_Classic_Fairytale:journey -- ["Help me, please!!!"] = "", -- A_Classic_Fairytale:journey @@ -333,6 +404,7 @@ -- ["Hogminator"] = "", -- A_Classic_Fairytale:family -- ["Hogs in sight!"] = "", -- Continental_supplies -- ["HOLY SHYTE!"] = "", -- Mutant +-- ["Homing Bee"] = "", -- Construction_Mode -- ["Honest Lee"] = "", -- A_Classic_Fairytale:enemy ["Hooray!"] = "Hurra!", -- ["Hostage Situation"] = "", -- A_Classic_Fairytale:family @@ -366,7 +438,6 @@ -- ["If you get stuck, use your Desert Eagle or restart the mission!|"] = "", -- A_Classic_Fairytale:journey -- ["If you know what I mean..."] = "", -- A_Classic_Fairytale:shadow -- ["If you say so..."] = "", -- A_Classic_Fairytale:shadow - -- ["I guess you'll have to kill them."] = "", -- A_Classic_Fairytale:dragon -- ["I have come to make you an offering..."] = "", -- A_Classic_Fairytale:shadow -- ["I have no idea where that mole disappeared...Can you see it?"] = "", -- A_Classic_Fairytale:shadow @@ -389,6 +460,7 @@ -- ["I'm not sure about that!"] = "", -- A_Classic_Fairytale:united -- ["Impressive...you are still dry as the corpse of a hawk after a week in the desert..."] = "", -- A_Classic_Fairytale:first_blood -- ["I'm so scared!"] = "", -- A_Classic_Fairytale:united +-- ["Increase"] = "", -- Continental_supplies -- ["Incredible..."] = "", -- A_Classic_Fairytale:shadow -- ["I need to find the others!"] = "", -- A_Classic_Fairytale:backstab -- ["I need to get to the other side of this island, fast!"] = "", -- A_Classic_Fairytale:journey @@ -397,12 +469,14 @@ -- ["I need to warn the others."] = "", -- A_Classic_Fairytale:backstab -- ["In fact, you are the only one that's been acting strangely."] = "", -- A_Classic_Fairytale:backstab -- ["In order to get to the other side, you need to collect the crates first.|"] = "", -- A_Classic_Fairytale:dragon +-- ["INSANITY"] = "", -- Mutant ["Instructor"] = "Instruktør", -- 01#Boot_Camp, User_Mission_-_Dangerous_Ducklings -- ["Interesting idea, haha!"] = "", -- A_Classic_Fairytale:enemy -- ["Interesting! Last time you said you killed a cannibal!"] = "", -- A_Classic_Fairytale:backstab -- ["In the meantime, take these and return to your \"friend\"!"] = "", -- A_Classic_Fairytale:shadow ["invaders destroyed"] = "indtrængere tilintetgjorte", -- ["Invasion"] = "", -- A_Classic_Fairytale:united +-- ["Invulnerable"] = "", -- Construction_Mode -- ["I saw it with my own eyes!"] = "", -- A_Classic_Fairytale:shadow -- ["I see..."] = "", -- A_Classic_Fairytale:shadow -- ["I see you have already taken the leap of faith."] = "", -- A_Classic_Fairytale:first_blood @@ -445,6 +519,7 @@ -- ["Just kidding, none of you have died!"] = "", -- A_Classic_Fairytale:enemy -- ["Just on a walk."] = "", -- A_Classic_Fairytale:united -- ["Just wait till I get my hands on that trauma! ARGH!"] = "", -- A_Classic_Fairytale:family +-- ["Kamikaze"] = "", -- Construction_Mode ["Kamikaze Expert!"] = "Kamikaze-ekspert!", ["Keep it up!"] = "Hold gejsten!", -- ["Kerguelen"] = "", -- Continental_supplies @@ -454,6 +529,8 @@ -- ["Kill the aliens!"] = "", -- A_Classic_Fairytale:dragon -- ["Kill the cannibal!"] = "", -- A_Classic_Fairytale:first_blood -- ["Kill the traitor...or spare his life!|Kill him or press [Precise]!"] = "", -- A_Classic_Fairytale:backstab +-- ["Land Sprayer"] = "", -- Construction_Mode +-- ["Laser Sight"] = "", -- Construction_Mode ["Last Target!"] = "Sidste Mål!", -- ["Leader"] = "", -- A_Classic_Fairytale:enemy -- ["Leaderbot"] = "", -- A_Classic_Fairytale:queen @@ -463,6 +540,7 @@ -- ["Leaks A Lot must survive!"] = "", -- A_Classic_Fairytale:journey -- ["Led Heart"] = "", -- A_Classic_Fairytale:queen -- ["Lee"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen +-- ["left shift"] = "", -- Continental_supplies ["[Left Shift]"] = "[Venstre Shift]", -- ["Let a Continent provide your weapons!"] = "", -- Continental_supplies -- ["Let me test your skills a little, will you?"] = "", -- A_Classic_Fairytale:journey @@ -473,41 +551,56 @@ -- ["Let them have a taste of my fury!"] = "", -- A_Classic_Fairytale:backstab -- ["Let us help, too!"] = "", -- A_Classic_Fairytale:backstab -- ["Light Cannfantry"] = "", -- A_Classic_Fairytale:united +-- ["Limburger"] = "", -- Construction_Mode ["Listen up, maggot!!"] = "Lyt efter, maddike!", -- ["Little did they know that this hunt will mark them forever..."] = "", -- A_Classic_Fairytale:shadow ["Lively Lifeguard"] = "Livlig Livredder", --- ["Lonely Cries: [Rise the water if no hog is in the circle and deal 1 damage to all hogs]"] = "", -- Continental_supplies + +-- ["Lonely Cries: [Rise the water if no hog is in the circle and deal 7 damage to all enemy hogs]"] = "", -- Continental_supplies +-- ["Lonely Hog"] = "", -- ClimbHome -- ["Look, I had no choice!"] = "", -- A_Classic_Fairytale:backstab -- ["Look out! There's more of them!"] = "", -- A_Classic_Fairytale:backstab -- ["Look out! We're surrounded by cannibals!"] = "", -- A_Classic_Fairytale:enemy -- ["Looks like the whole world is falling apart!"] = "", -- A_Classic_Fairytale:enemy +-- ["Low Gravity"] = "", -- Construction_Mode, Frenzy -- ["Luckily, I've managed to snatch some of them."] = "", -- A_Classic_Fairytale:united -- ["LUDICROUS KILL"] = "", -- Mutant +-- ["Made it!"] = "", -- ClimbHome +-- ["- Massive weapon bonus on first turn"] = "", -- Continental_supplies -- ["May the spirits aid you in all your quests!"] = "", -- A_Classic_Fairytale:backstab -- ["Medicine: [Fire some exploding medicine that will heal all hogs effected by the explosion]"] = "", -- Continental_supplies -- ["MEGA KILL"] = "", -- Mutant -- ["Meiwes"] = "", -- A_Classic_Fairytale:backstab -- ["Mindy"] = "", -- A_Classic_Fairytale:united +-- ["Mine"] = "", -- Construction_Mode, Frenzy ["Mine Deployer"] = "Mineudsætter", ["Mine Eater!"] = "Mineæder", +-- ["Mine Placement Mode"] = "", -- Construction_Mode ["|- Mines Time:"] = "|- Tid til Miner:", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork +-- ["Mine Strike"] = "", -- Construction_Mode ["MISSION FAILED"] = "MISSION MISLYKKEDES", -- User_Mission_-_Dangerous_Ducklings, User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork ["MISSION SUCCESSFUL"] = "MISSION VAR SUCCESFULD", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork ["MISSION SUCCESS"] = "MISSION LYKKEDES", +-- ["Molotov Cocktail"] = "", -- Construction_Mode -- ["Molotov"] = "", -- Continental_supplies -- ["MONSTER KILL"] = "", -- Mutant -- ["More Natives"] = "", -- A_Classic_Fairytale:epil +-- ["Mortar"] = "", -- Construction_Mode, A_Space_Adventure:death02 ["Movement: [Up], [Down], [Left], [Right]"] = "Bevægelse: [Op], [Ned], [Venstre], [Højre]", +-- ["Mudball"] = "", -- Construction_Mode ["Multi-shot!"] = "Flerskud!", -- ["Muriel"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen -- ["Muscle Dissolver"] = "", -- A_Classic_Fairytale:shadow -- ["-------"] = "", -- Mutant +-- ["Mutant"] = "", -- Mutant -- ["Nade Boy"] = "", -- Basic_Training_-_Grenade -- ["Name"] = "", -- A_Classic_Fairytale:queen ["Nameless Heroes"] = "Navnløse Helte", -- ["Nancy Screw"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:queen +-- ["Napalm"] = "", -- Construction_Mode -- ["Napalm rocket: [Fire a bomb with napalm!]"] = "", -- Continental_supplies -- ["Natives"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:first_blood, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united +-- ["Naughty Ninja"] = "", -- User_Mission_-_Dangerous_Ducklings ["New Barrels Per Turn"] = "Nye Tønder Per Tur", ["NEW CLAN RECORD: "] = "NY KLANREKORD: ", ["NEW fastest lap: "] = "NY hurtigste omgang: ", @@ -518,6 +611,7 @@ -- ["Nice work, "] = "", -- A_Classic_Fairytale:dragon -- ["Nice work!"] = "", -- A_Classic_Fairytale:enemy -- ["Nilarian"] = "", -- A_Classic_Fairytale:queen +-- ["Nobody Laugh"] = "", -- User_Mission_-_Nobody_Laugh -- ["No, I came back to help you out..."] = "", -- A_Classic_Fairytale:shadow -- ["No...I wonder where they disappeared?!"] = "", -- A_Classic_Fairytale:journey -- ["Nom-Nom"] = "", -- A_Classic_Fairytale:journey @@ -525,6 +619,7 @@ -- ["Nope. It was one fast mole, that's for sure."] = "", -- A_Classic_Fairytale:shadow -- ["No! Please, help me!"] = "", -- A_Classic_Fairytale:journey -- ["NORMAL"] = "", -- Continental_supplies +-- ["Normal players can only score points by killing the mutant."] = "", -- Mutant -- ["North America"] = "", -- Continental_supplies -- ["Not all hogs are born equal."] = "", -- Highlander ["NOT ENOUGH WAYPOINTS"] = "IKKE NOK RUTEPUNKTER", @@ -537,6 +632,7 @@ -- ["No. Where did he come from?"] = "", -- A_Classic_Fairytale:shadow -- ["Now how do I get on the other side?!"] = "", -- A_Classic_Fairytale:dragon -- ["No. You and the rest of the tribe are safer there!"] = "", -- A_Classic_Fairytale:backstab +-- ["Object Placement Tool"] = "", -- Construction_Mode -- ["Obliterate them!|Hint: You might want to take cover..."] = "", -- A_Classic_Fairytale:shadow -- ["Obstacle course"] = "", -- A_Classic_Fairytale:dragon -- ["Of course I have to save her. What did I expect?!"] = "", -- A_Classic_Fairytale:family @@ -553,24 +649,30 @@ -- ["Once upon a time, on an island with great natural resources, lived two tribes in heated conflict..."] = "", -- A_Classic_Fairytale:first_blood -- ["ONE HOG PER TEAM! KILLING EXCESS HEDGES"] = "", -- Mutant -- ["One tribe was peaceful, spending their time hunting and training, enjoying the small pleasures of life..."] = "", -- A_Classic_Fairytale:first_blood +-- ["on Skip"] = "", -- Continental_supplies -- ["Oops...I dropped them."] = "", -- A_Classic_Fairytale:united -- ["Open that crate and we will continue!"] = "", -- A_Classic_Fairytale:first_blood ["Operation Diver"] = "Operation Dykker", ["Opposing Team: "] = "Modstander: ", +-- ["or 'g=50, g2=150, period=4000' for gravity changing|from 50 to 150 and back with period of 4000 msec"] = "", -- Gravity -- ["Orlando Boom!"] = "", -- A_Classic_Fairytale:queen +-- ["Other kills don't give you points."] = "", -- Mutant -- ["Ouch!"] = "", -- User_Mission_-_Rope_Knock_Challenge -- ["Our tribe, our beautiful island!"] = "", -- A_Classic_Fairytale:enemy -- ["Parachute"] = "", -- Continental_supplies ["Pathetic Hog #%d"] = "Patetisk Pindsvin #%d", ["Pathetic Resistance"] = "Patetisk Modstand", -- User_Mission_-_Bamboo_Thicket, User_Mission_-_Newton_and_the_Hammock +-- ["Penguin roar: [Deal 15 damage + 15% of your hogs health to all hogs around you and get 2/3 back]"] = "", -- Continental_supplies -- ["Perfect! Now try to get the next crate without hurting yourself!"] = "", -- A_Classic_Fairytale:first_blood ["Per-Hog Ammo"] = "Ammunition Per Pindsvin", --- ["- Per team weapons|- 9 weaponschemes|- Unique new weapons| |Select continent first round with the Weapon Menu or by ([switch/tab]=Increase,[precise/left shift]=Decrease) on Skip|Some weapons have a second option. Find them with [switch/tab]"] = "", -- Continental_supplies +-- ["Personal Portal Device"] = "", -- Construction_Mode +-- ["Per team weapons"] = "", -- Continental_supplies -- ["Pfew! That was close!"] = "", -- A_Classic_Fairytale:shadow --- ["Piñata bullet: [Contains some sweet candy!]"] = "", -- Continental_supplies +-- ["Piano Strike"] = "", -- Construction_Mode +-- ["Pickhammer"] = "", -- Construction_Mode + -- ["Pings left:"] = "", -- Space_Invasion - ["Place more waypoints using the 'Air Attack' weapon."] = "Placer flere rutepunkter med 'Luftangreb'-våbnet", -- ["Planes Used:"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Planes Used"] = "", -- User_Mission_-_RCPlane_Challenge @@ -579,15 +681,19 @@ -- ["Please place the way-point in the open, within the map boundaries."] = "", -- Racer -- ["Please, stop releasing your \"smoke signals\"!"] = "", -- A_Classic_Fairytale:shadow -- ["Point Blank Combo!"] = "", -- Space_Invasion +-- ["POINTS"] = "", -- Mutant ["points"] = "point", -- Control, CTF_Blizzard, Basic_Training_-_Bazooka, Basic_Training_-_Shotgun, Basic_Training_-_Sniper_Rifle ["Poison"] = "Gift", +-- ["Population"] = "", -- Continental_supplies -- ["Portal hint: one goes to the destination, and one is the entrance.|"] = "", -- A_Classic_Fairytale:dragon -- ["Portal mission"] = "", -- portal ["Power Remaining"] = "Kraft Tilbage", ["Prepare yourself"] = "Gør dig klar", +-- ["presice"] = "", -- Continental_supplies -- ["Press [Enter] to accept this configuration."] = "", -- WxW -- ["Press [Left] or [Right] to move around, [Enter] to jump"] = "", -- A_Classic_Fairytale:first_blood ["Press [Precise] to skip intro"] = "Tryk på [Præcis] for at springe introen over", +-- ["Prestigious Pilot"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Private Novak"] = "", -- Basic_Training_-_Cluster_Bomb -- ["Protect yourselves!|Grenade hint: set the timer with [1-5], aim with [Up]/[Down] and hold [Space] to set power"] = "", -- A_Classic_Fairytale:shadow ["Race complexity limit reached."] = "Kompleksitetsgrænsen for ræset er nået.", @@ -596,25 +702,39 @@ -- ["Radar Ping"] = "", -- Space_Invasion -- ["Raging Buffalo"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united -- ["Ramon"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow +-- ["random in range from %i%% to %i%% with period of %i msec"] = "", -- Gravity +-- ["RC Plane"] = "", -- Construction_Mode -- ["RC PLANE TRAINING"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Really?! You thought you could harm me with your little toys?"] = "", -- A_Classic_Fairytale:shadow +-- ["Reflector Shield"] = "", -- Construction_Mode +-- ["Reflects enemy projectiles."] = "", -- Construction_Mode -- ["Regurgitator"] = "", -- A_Classic_Fairytale:backstab -- ["Reinforcements"] = "", -- A_Classic_Fairytale:backstab -- ["Remember: The rope only bend around objects, |if it doesn't hit anything it's always stright!"] = "", -- Basic_Training_-_Rope -- ["Remember this, pathetic animal: when the day comes, you will regret your blind loyalty!"] = "", -- A_Classic_Fairytale:shadow +-- ["REMOVED"] = "", -- Continental_supplies +-- ["Respawner"] = "", -- Construction_Mode +-- ["Resurrector"] = "", -- Construction_Mode +-- ["Resurrects dead hedgehogs."] = "", -- Construction_Mode [" - Return the enemy flag to your base to score | - First team to 3 captures wins | - You may only score when your flag is in your base | - Hogs will drop the flag if killed, or drowned | - Dropped flags may be returned or recaptured | - Hogs respawn when killed"] = " - Returner fjendens flag til din base for at score | - Første hold til at erobre 3 flag vinder | - Du kan kun score når dit flag er ved din base | Pindsvin taber flaget hvis de dør eller drukner | - Tabte flag kan returneres eller generobres | - Pindsvin genopliver når de bliver dræbt", -- ["Return to Leaks A Lot! If you get stuck, press [Precise] to try again!"] = "", -- A_Classic_Fairytale:shadow -- ["Righteous Beard"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:first_blood, A_Classic_Fairytale:queen, A_Classic_Fairytale:united +-- ["Rope"] = "", -- Construction_Mode -- ["ROPE-KNOCKING"] = "", -- User_Mission_-_Rope_Knock_Challenge +-- ["Rope to safety"] = "", -- ClimbHome -- ["Rope Training"] = "", -- Basic_Training_-_Rope -- ["Rot Molester"] = "", -- A_Classic_Fairytale:shadow ["Round Limit:"] = "Rundebegrænsning: ", ["Round Limit"] = "Rundebegrænsning", ["Rounds Complete: "] = "Runder Færdiggjort: ", ["Rounds Complete"] = "Runder Færdiggjort", +-- ["Rubber Band"] = "", -- Construction_Mode +-- ["Rubber Placement Mode"] = "", -- Construction_Mode +-- ["RULES"] = "", -- Frenzy, Mutant ["RULES OF THE GAME [Press ESC to view]"] = "SPILLETS REGLER [Tryk på ESC for at se]", -- ["Rusty Joe"] = "", -- A_Classic_Fairytale:queen --- ["Sabotage: [Sabotage all hogs in the circle and deal ~10 dmg]"] = "", -- Continental_supplies +-- ["Sabotage/Flare: [Sabotage all hogs in the circle and deal ~1 dmg OR Fire a cluster up into the air]"] = "", -- Continental_supplies + -- ["Salivaslurper"] = "", -- A_Classic_Fairytale:united -- ["Salvation"] = "", -- A_Classic_Fairytale:family -- ["Salvation was one step closer now..."] = "", -- A_Classic_Fairytale:dragon @@ -626,7 +746,7 @@ -- ["Scalp Muncher"] = "", -- A_Classic_Fairytale:backstab -- ["Score"] = "", -- Mutant ["SCORE"] = "SCORE", --- ["Scream from a Walrus: [Deal 20 damage + 10% of your hogs health to all hogs around you and get half back]"] = "", -- Continental_supplies + ["sec"] = "sek.", -- CTF_Blizzard, TrophyRace, Basic_Training_-_Bazooka, Basic_Training_-_Shotgun, Basic_Training_-_Sniper_Rifle, User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork, Capture_the_Flag -- ["Seduction"] = "", -- Continental_supplies -- ["Seems like every time you take a \"walk\", the enemy find us!"] = "", -- A_Classic_Fairytale:backstab @@ -634,8 +754,11 @@ ["See ya!"] = "Ses!", -- ["Segmentation Paul"] = "", -- A_Classic_Fairytale:dragon -- ["Select continent!"] = "", -- Continental_supplies +-- ["Select continent first round with the Weapon Menu or by"] = "", -- Continental_supplies -- ["Select difficulty: [Left] - easier or [Right] - harder"] = "", -- A_Classic_Fairytale:first_blood ["selected!"] = "valgt", +-- ["Set period to negative value for random gravity"] = "", -- Gravity +-- ["Setup:|'g=150', where 150 is 150% of normal gravity"] = "", -- Gravity -- ["... share your beauty with the world every morning, my princess!"] = "", -- A_Classic_Fairytale:journey -- ["She's behind that tall thingy."] = "", -- A_Classic_Fairytale:family ["Shield boosted! +30 power"] = "Skjold forstærket! +30 kraft", @@ -646,16 +769,21 @@ ["Shield OFF:"] = "Skjold SLÅET FRA:", ["Shield ON:"] = "Skjold SLÅET TIL:", ["Shield Seeker!"] = "Skjoldsøger!", +-- ["Shoryuken"] = "", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 -- ["Shotgun"] = "", -- Continental_supplies ["Shotgun Team"] = "Haglgeværdshold", ["Shotgun Training"] = "Træning med Haglgevær", ["shots remaining."] = "skud tilbage.", ["Silly"] = "Fjollet", +-- ["SineGun"] = "", -- Construction_Mode ["Sinky"] = "Synkende", -- ["Sirius Lee"] = "", -- A_Classic_Fairytale:enemy ["%s is out and Team %d|scored a penalty!| |Score:"] = "%s er ude og Hold %d|scored en straf!| |Score:", -- Basketball, Knockball ["%s is out and Team %d|scored a point!| |Score:"] = "%s er ude og Hold %d|scored et point!| |Score:", -- Basketball, Knockball -- ["Slippery"] = "", -- A_Classic_Fairytale:journey +-- ["Slot"] = "", -- Frenzy +-- ["Slot keys save time! (F1-F10 by default)"] = "", -- Frenzy +-- ["SLOTS"] = "", -- Frenzy -- ["Smith 0.97"] = "", -- A_Classic_Fairytale:enemy -- ["Smith 0.98"] = "", -- A_Classic_Fairytale:enemy -- ["Smith 0.99a"] = "", -- A_Classic_Fairytale:enemy @@ -667,6 +795,7 @@ ["Sniper Training"] = "Træning med Sniperriffel", ["Sniperz"] = "Sniperz", -- ["So humiliating..."] = "", -- A_Classic_Fairytale:first_blood +-- ["Some weapons have a second option. Find them with"] = "", -- Continental_supplies -- ["South America"] = "", -- Continental_supplies -- ["So? What will it be?"] = "", -- A_Classic_Fairytale:shadow -- ["Spawn the crate, and attack!"] = "", -- WxW @@ -675,6 +804,8 @@ -- ["Spleenlover"] = "", -- A_Classic_Fairytale:united ["Sponge"] = "Svamp", ["Spooky Tree"] = "Uhyggeligt Træ", +-- ["Sprite Placement Mode"] = "", -- Construction_Mode +-- ["Sprite Testing Mode"] = "", -- Construction_Mode ["s|"] = "s|", ["s"] = "s", -- GaudyRacer, Space_Invasion ["STATUS UPDATE"] = "STATUSOPDATERING", -- GaudyRacer, Space_Invasion @@ -682,20 +813,36 @@ -- ["Step By Step"] = "", -- A_Classic_Fairytale:first_blood -- ["Steve"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen -- ["Sticky Mine"] = "", -- Continental_supplies +-- ["Sticky Mine Placement Mode"] = "", -- Construction_Mode -- ["Stronglings"] = "", -- A_Classic_Fairytale:shadow --- ["Structure"] = "", -- Continental_supplies + +-- ["Structure Placement Mode"] = "", -- Construction_Mode +-- ["Structure Placement Tool"] = "", -- Construction_Mode +-- ["Sundaland"] = "", -- Continental_supplies -- ["Super Weapons"] = "", -- WxW +-- ["Support Station"] = "", -- Construction_Mode -- ["Surf Before Crate"] = "", -- WxW -- ["Surfer! +15 points!"] = "", -- Space_Invasion -- ["Surfer!"] = "", -- WxW -- ["Survive!|Hint: Cinematics can be skipped with the [Precise] key."] = "", -- A_Classic_Fairytale:shadow -- ["Swing, Leaks A Lot, on the wings of the wind!"] = "", -- A_Classic_Fairytale:first_blood +-- ["switch"] = "", -- Continental_supplies ["Switched to "] = "Skiftede til ", +-- ["Switch Hog"] = "", -- Construction_Mode -- ["Syntax Errol"] = "", -- A_Classic_Fairytale:dragon +-- ["tab"] = "", -- Continental_supplies +-- ["Tagging Mode"] = "", -- Construction_Mode -- ["Talk about mixed signals..."] = "", -- A_Classic_Fairytale:dragon +-- ["Tardis"] = "", -- Construction_Mode +-- ["Target Placement Mode"] = "", -- Construction_Mode ["Team %d: "] = "Hold %d: ", ["Team Scores"] = "Holdscore", -- Control, Space_Invasion +-- ["Teleporation Node"] = "", -- Construction_Mode +-- ["Teleportation Mode"] = "", -- Construction_Mode +-- ["Teleportation Node"] = "", -- Construction_Mode +-- ["Teleport"] = "", -- Construction_Mode, Frenzy -- ["Teleport hint: just use the mouse to select the destination!"] = "", -- A_Classic_Fairytale:dragon +-- ["Teleport Unsuccessful. Please teleport within a clan teleporter's sphere of influence."] = "", -- Construction_Mode -- ["Thanks!"] = "", -- A_Classic_Fairytale:family -- ["Thank you, my hero!"] = "", -- A_Classic_Fairytale:family -- ["Thank you, oh, thank you, Leaks A Lot!"] = "", -- A_Classic_Fairytale:journey @@ -712,6 +859,7 @@ ["That was pointless."] = "Det var meningsløst.", -- ["The answer is...entertaintment. You'll see what I mean."] = "", -- A_Classic_Fairytale:backstab -- ["The anti-portal zone is all over the floor, and I have nothing to kill him...Droping something could hurt him enough to kill him..."] = "", -- portal +-- ["The Bottom Feeder can score points by killing anyone."] = "", -- Mutant -- ["The Bull's Eye"] = "", -- A_Classic_Fairytale:first_blood -- ["The caves are well hidden, they won't find us there!"] = "", -- A_Classic_Fairytale:united -- ["The Crate Frenzy"] = "", -- A_Classic_Fairytale:first_blood @@ -721,20 +869,26 @@ -- ["The Enemy Of My Enemy"] = "", -- A_Classic_Fairytale:enemy -- ["The First Blood"] = "", -- A_Classic_Fairytale:first_blood -- ["The First Encounter"] = "", -- A_Classic_Fairytale:shadow +-- ["The first player to kill someone becomes the Mutant."] = "", -- Mutant ["The flag will respawn next round."] = "Flaget gendannes næste runde.", -- ["The food bites back"] = "", -- A_Classic_Fairytale:backstab -- ["The giant umbrella from the last crate should help break the fall."] = "", -- A_Classic_Fairytale:first_blood -- ["The Great Escape"] = "", -- User_Mission_-_The_Great_Escape +-- ["The Great Hog in the sky sees your sadness and grants you a boon."] = "", -- Construction_Mode -- ["The guardian"] = "", -- A_Classic_Fairytale:shadow -- ["The Individualist"] = "", -- A_Classic_Fairytale:shadow -- ["Their buildings were very primitive back then, even for an uncivilised island."] = "", -- A_Classic_Fairytale:united -- ["The Journey Back"] = "", -- A_Classic_Fairytale:journey -- ["The Leap of Faith"] = "", -- A_Classic_Fairytale:first_blood -- ["The Moonwalk"] = "", -- A_Classic_Fairytale:journey +-- ["The Mutant has super-weapons and a lot of health."] = "", -- Mutant +-- ["The Mutant loses health quickly if he doesn't keep scoring kills."] = "", -- Mutant ["The Nameless One"] = "Den Navnløse Ene", -- ["The next one is pretty hard! |Tip: You have to do multiple swings!"] = "", -- Basic_Training_-_Rope -- ["Then how do they keep appearing?"] = "", -- A_Classic_Fairytale:shadow -- ["The other one were all cannibals, spending their time eating the organs of fellow hedgehogs..."] = "", -- A_Classic_Fairytale:first_blood +-- ["The player with least points (or most deaths) becomes the Bottom Feeder."] = "", -- Mutant +-- ["There are a variety of structures available to aid you."] = "", -- Construction_Mode -- ["There must be a spy among us!"] = "", -- A_Classic_Fairytale:backstab -- ["There's more of them? When did they become so hungry?"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united -- ["There's nothing more satisfying for me than seeing you share your beauty with the world every morning, my princess!"] = "", -- A_Classic_Fairytale:journey @@ -790,7 +944,7 @@ -- ["To the caves..."] = "", -- A_Classic_Fairytale:united ["Toxic Team"] = "Giftigt Hold", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork ["TRACK COMPLETED"] = "BANE FULDFØRT", - ["TRACK FAILED!"] = "BANE MISLYKKEDES!", + -- ["training"] = "", -- portal -- ["Traitors"] = "", -- A_Classic_Fairytale:epil -- ["Tribe"] = "", -- A_Classic_Fairytale:backstab @@ -807,6 +961,7 @@ -- ["ULTRA KILL"] = "", -- Mutant -- ["Under Construction"] = "", -- A_Classic_Fairytale:shadow -- ["Unexpected Igor"] = "", -- A_Classic_Fairytale:dragon +-- ["Unique new weapons"] = "", -- Continental_supplies -- ["Unit 0x0007"] = "", -- A_Classic_Fairytale:family -- ["Unit 334a$7%;.*"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united ["Unit 3378"] = "Enhed 3378", @@ -821,11 +976,14 @@ -- ["Use it wisely!"] = "", -- A_Classic_Fairytale:dragon -- ["Use it with precaution!"] = "", -- A_Classic_Fairytale:first_blood ["User Challenge"] = "Brugerudfordring", - +-- ["Use the air-attack weapons and the arrow keys to select structures."] = "", -- Construction_Mode -- ["Use the portal gun to get to the next crate, then use the new gun to get to the final destination!|"] = "", -- A_Classic_Fairytale:dragon -- ["Use the rope to get on the head of the mole, young one!"] = "", -- A_Classic_Fairytale:first_blood -- ["Use the rope to knock your enemies to their doom."] = "", -- User_Mission_-_Rope_Knock_Challenge +-- ["Use your ready time to think."] = "", -- Frenzy ["Use your rope to get from start to finish as fast as you can!"] = "Brug dit reb til at komme fra start til slut så hurtigt som muligt!", +-- ["Utility Crate Placement Mode"] = "", -- Construction_Mode +-- ["Vampirism"] = "", -- Construction_Mode -- ["Vedgies"] = "", -- A_Classic_Fairytale:journey -- ["Vegan Jack"] = "", -- A_Classic_Fairytale:enemy -- ["Victory!"] = "", -- Basic_Training_-_Rope @@ -837,10 +995,14 @@ -- ["Wannabe Flyboys"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Wannabe Shoppsta"] = "", -- User_Mission_-_Rope_Knock_Challenge -- ["Watch your steps, young one!"] = "", -- A_Classic_Fairytale:first_blood +-- ["Watermelon Bomb"] = "", -- Construction_Mode ["Waypoint placed."] = "Rutepunkt placeret.", ["Way-Points Remaining"] = "Rutepunkter Tilbage", -- ["Weaklings"] = "", -- A_Classic_Fairytale:shadow -- ["We all know what happens when you get frightened..."] = "", -- A_Classic_Fairytale:first_blood +-- ["Weapon Crate Placement Mode"] = "", -- Construction_Mode +-- ["Weapon Filter"] = "", -- Construction_Mode +-- ["weaponschemes"] = "", -- Continental_supplies -- ["Weapons reset."] = "", -- Highlander ["Weapons Reset"] = "Våben Nulstillede", -- ["We are indeed."] = "", -- A_Classic_Fairytale:backstab @@ -893,6 +1055,7 @@ -- ["Where do you get that?!"] = "", -- A_Classic_Fairytale:enemy -- ["Where have you been?!"] = "", -- A_Classic_Fairytale:backstab -- ["Where have you been?"] = "", -- A_Classic_Fairytale:united +-- ["Whip"] = "", -- Construction_Mode -- ["? Why?"] = "", -- A_Classic_Fairytale:backstab -- ["Why "] = "", -- A_Classic_Fairytale:backstab -- ["! Why?!"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united @@ -905,8 +1068,10 @@ -- ["Why me?!"] = "", -- A_Classic_Fairytale:backstab -- ["Why would they do this?"] = "", -- A_Classic_Fairytale:backstab -- ["- Will Get 1-3 random weapons"] = "", -- Continental_supplies --- ["- Will refresh Parachute each turn."] = "", -- Continental_supplies --- ["- Will refresh portalgun each turn."] = "", -- Continental_supplies +-- ["- Will give you an airstrike every fifth turn."] = "", -- Continental_supplies +-- ["- Will give you a parachute every second turn."] = "", -- Continental_supplies + + ["Will this ever end?"] = "Slutter det her nogensinde?", -- ["WINNER IS "] = "", -- Mutant ["WINNING TIME: "] = "VINDENDE TID: ", @@ -925,6 +1090,7 @@ -- ["Yes!"] = "", -- A_Classic_Fairytale:enemy -- ["Yes, yeees! You are now ready to enter the real world!"] = "", -- A_Classic_Fairytale:first_blood -- ["Yo, dude, we're here, too!"] = "", -- A_Classic_Fairytale:family +-- ["You are far from home, and the water is rising, climb up as high as you can!"] = "", -- ClimbHome -- ["You are given the chance to turn your life around..."] = "", -- A_Classic_Fairytale:shadow -- ["You are playing with our lives here!"] = "", -- A_Classic_Fairytale:enemy -- ["! You bastards!"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united @@ -957,6 +1123,8 @@ -- ["You know what? I don't even regret anything!"] = "", -- A_Classic_Fairytale:backstab -- ["You'll see what I mean!"] = "", -- A_Classic_Fairytale:enemy -- ["You may only attack from a rope!"] = "", -- WxW +-- ["You may only spawn 5 crates per turn."] = "", -- Construction_Mode +-- ["You may only use 1 Extra Time per turn."] = "", -- Construction_Mode -- ["You meatbags are pretty slow, you know!"] = "", -- A_Classic_Fairytale:enemy -- ["You might want to find a way to instantly kill arriving cannibals!"] = "", -- A_Classic_Fairytale:backstab -- ["Young one, you are telling us that they can instantly change location without a shaman?"] = "", -- A_Classic_Fairytale:united @@ -977,6 +1145,7 @@ ["You've failed. Try again."] = "Det lykkedes dig ikke. Prøv igen.", ["You've reached the goal!| |Time: "] = "Du har nået målet!| |Tid: ", -- ["You will be avenged!"] = "", -- A_Classic_Fairytale:shadow +-- ["- You will recieve 2-4 weapons on each kill! (Even on own hogs)"] = "", -- Continental_supplies -- ["You won't believe what happened to me!"] = "", -- A_Classic_Fairytale:backstab -- ["Yuck! I bet they'll keep worshipping her even after I save the village!"] = "", -- A_Classic_Fairytale:family -- ["Zealandia"] = "", -- Continental_supplies diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/de.lua --- a/share/hedgewars/Data/Locale/de.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/de.lua Tue Nov 10 20:43:13 2015 +0100 @@ -1,989 +1,1824 @@ locale = { --- [":("] = "", --- ["!!!"] = "", --- ["..."] = "", --- ["011101000"] = "", -- A_Classic_Fairytale:dragon --- ["011101001"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:family, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united --- ["30 minutes later..."] = "", -- A_Classic_Fairytale:shadow --- ["About a month ago, a cyborg came and told us that you're the cannibals!"] = "", -- A_Classic_Fairytale:enemy - ["Accuracy Bonus!"] = "Präzisions-Bonus!", --- ["Ace"] = "", -- User_Mission_-_RCPlane_Challenge, User_Mission_-_Rope_Knock_Challenge --- ["Achievement Unlocked"] = "", -- User_Mission_-_Bamboo_Thicket, User_Mission_-_That_Sinking_Feeling, Tumbler --- ["A Classic Fairytale"] = "", -- A_Classic_Fairytale:first_blood --- ["???"] = "", -- A_Classic_Fairytale:backstab --- ["Actually, you aren't worthy of life! Take this..."] = "", -- A_Classic_Fairytale:shadow --- ["A cy-what?"] = "", -- A_Classic_Fairytale:enemy --- ["Adventurous"] = "", -- A_Classic_Fairytale:journey --- ["Africa"] = "", -- Continental_supplies --- ["After Leaks A Lot betrayed his tribe, he joined the cannibals..."] = "", -- A_Classic_Fairytale:first_blood --- ["After the shock caused by the enemy spy, Leaks A Lot and Dense Cloud went hunting to relax."] = "", -- A_Classic_Fairytale:shadow --- ["Again with the 'cannibals' thing!"] = "", -- A_Classic_Fairytale:enemy --- ["a Hedgewars challenge"] = "", -- User_Mission_-_RCPlane_Challenge, User_Mission_-_Rope_Knock_Challenge - ["a Hedgewars mini-game"] = "ein Hedgewars Mini-Spiel", -- Space_Invasion, The_Specialists - ["Aiming Practice"] = "Zielübung", --Bazooka, Shotgun, SniperRifle --- ["A leap in a leap"] = "", -- A_Classic_Fairytale:first_blood --- ["A little gift from the cyborgs"] = "", -- A_Classic_Fairytale:shadow --- ["All gone...everything!"] = "", -- A_Classic_Fairytale:enemy --- ["All right, we just need to get to the other side of the island!"] = "", -- A_Classic_Fairytale:journey --- ["All walls touched!"] = "", -- WxW - ["Ammo Depleted!"] = "Munition erschöpft!", - ["ammo extended!"] = "Munition aufgestockt!", - ["Ammo is reset at the end of your turn."] = "Munition wird am Ende des Spielzuges zurückgesetzt.", - ["Ammo Maniac!"] = "Munitionsverrückter!", - ["Ammo"] = "Munition", --- ["And how am I alive?!"] = "", -- A_Classic_Fairytale:enemy --- ["And so happenned that Leaks A Lot failed to complete the challenge! He landed, pressured by shame..."] = "", -- A_Classic_Fairytale:first_blood --- ["And so it began..."] = "", -- A_Classic_Fairytale:first_blood --- ["...and so the cyborgs took over the world..."] = "", -- A_Classic_Fairytale:shadow --- ["And so they discovered that cyborgs weren't invulnerable..."] = "", -- A_Classic_Fairytale:journey --- ["And where's all the weed?"] = "", -- A_Classic_Fairytale:dragon --- ["And you believed me? Oh, god, that's cute!"] = "", -- A_Classic_Fairytale:journey --- ["Anno 1032: [The explosion will make a strong push ~ wide range, wont affect hogs close to the target]"] = "", -- Continental_supplies --- ["Antarctica"] = "", -- Continental_supplies --- ["Are we there yet?"] = "", -- A_Classic_Fairytale:shadow --- ["Are you accusing me of something?"] = "", -- A_Classic_Fairytale:backstab --- ["Are you saying that many of us have died for your entertainment?"] = "", -- A_Classic_Fairytale:enemy --- ["Artur Detour"] = "", -- A_Classic_Fairytale:queen --- ["As a reward for your performance, here's some new technology!"] = "", -- A_Classic_Fairytale:dragon --- ["a shoppa minigame"] = "", -- WxW --- ["Asia"] = "", -- Continental_supplies --- ["Assault Team"] = "", -- A_Classic_Fairytale:backstab --- ["As the ammo is sparse, you might want to reuse ropes while mid-air.|"] = "", -- A_Classic_Fairytale:dragon --- ["As the challenge was completed, Leaks A Lot set foot on the ground..."] = "", -- A_Classic_Fairytale:first_blood --- ["As you can see, there is no way to get on the other side!"] = "", -- A_Classic_Fairytale:dragon --- ["Attack From Rope"] = "", -- WxW --- ["Australia"] = "", -- Continental_supplies - ["Available points remaining: "] = "Verfügbare Punkte verbleibend:", --- ["Back Breaker"] = "", -- A_Classic_Fairytale:backstab --- ["Back in the village, after telling the villagers about the threat..."] = "", -- A_Classic_Fairytale:united --- ["[Backspace]"] = "", --- ["Backstab"] = "", -- A_Classic_Fairytale:backstab --- ["Bad Team"] = "", -- User_Mission_-_The_Great_Escape --- ["Bamboo Thicket"] = "", - ["Barrel Eater!"] = "Fassfresser!", - ["Barrel Launcher"] = "Fasswerfer", --- ["Baseballbat"] = "", -- Continental_supplies - ["Bat balls at your enemies and|push them into the sea!"] = "Schlage Bälle auf deine Widersacher|und lass sie ins Meer fallen!", - ["Bat your opponents through the|baskets and out of the map!"] = "Schlage deine Widersacher durch|die Körbe und aus der Karte hinaus!", - ["Bazooka Training"] = "Bazooka-Training", --- ["Beep Loopers"] = "", -- A_Classic_Fairytale:queen - ["Best laps per team: "] = "Beste Rundenzeiten pro Team: ", - ["Best Team Times: "] = "Beste Team-Zeiten: ", --- ["Beware, though! If you are slow, you die!"] = "", -- A_Classic_Fairytale:dragon --- ["Biomechanic Team"] = "", -- A_Classic_Fairytale:family --- ["Blender"] = "", -- A_Classic_Fairytale:family --- ["Bloodpie"] = "", -- A_Classic_Fairytale:backstab --- ["Bloodrocutor"] = "", -- A_Classic_Fairytale:shadow --- ["Bloodsucker"] = "", -- A_Classic_Fairytale:shadow - ["Bloody Rookies"] = "Blutige Anfänger", -- 01#Boot_Camp, User_Mission_-_Dangerous_Ducklings, User_Mission_-_Diver, User_Mission_-_Spooky_Tree --- ["Bone Jackson"] = "", -- A_Classic_Fairytale:backstab --- ["Bonely"] = "", -- A_Classic_Fairytale:shadow - ["Boom!"] = "Bumm!", - ["BOOM!"] = "KABUMM!", - ["Boss defeated!"] = "Boss wurde besiegt!", - ["Boss Slayer!"] = "Boss-Töter!", --- ["Brain Blower"] = "", -- A_Classic_Fairytale:journey --- ["Brainiac"] = "", -- A_Classic_Fairytale:epil, A_Classic_Fairytale:first_blood, A_Classic_Fairytale:shadow --- ["Brainila"] = "", -- A_Classic_Fairytale:united --- ["Brain Stu"] = "", -- A_Classic_Fairytale:united --- ["Brain Teaser"] = "", -- A_Classic_Fairytale:backstab --- ["Brutal Lily"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil --- ["Brutus"] = "", -- A_Classic_Fairytale:backstab - ["Build a track and race."] = "Konstruiere eine Strecke und mach ein Wettrennen.", --- ["Bullseye"] = "", -- A_Classic_Fairytale:dragon --- ["But it proved to be no easy task!"] = "", -- A_Classic_Fairytale:dragon --- ["But that's impossible!"] = "", -- A_Classic_Fairytale:backstab --- ["But the ones alive are stronger in their heart!"] = "", -- A_Classic_Fairytale:enemy --- ["But...we died!"] = "", -- A_Classic_Fairytale:backstab --- ["But where can we go?"] = "", -- A_Classic_Fairytale:united --- ["But why would they help us?"] = "", -- A_Classic_Fairytale:backstab --- ["But you're cannibals. It's what you do."] = "", -- A_Classic_Fairytale:enemy --- ["But you said you'd let her go!"] = "", -- A_Classic_Fairytale:journey --- ["Call me Beep! Well, 'cause I'm such a nice...person!"] = "", -- A_Classic_Fairytale:family --- ["Cannibals"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:first_blood --- ["Cannibal Sentry"] = "", -- A_Classic_Fairytale:journey --- ["Cannibals?! You're the cannibals!"] = "", -- A_Classic_Fairytale:enemy - ["CAPTURE THE FLAG"] = "EROBERE DIE FAHNE", - ["Careless"] = "Achtlos", --- ["Carol"] = "", -- A_Classic_Fairytale:family --- ["CHALLENGE COMPLETE"] = "", -- User_Mission_-_RCPlane_Challenge - ["Change Weapon"] = "Waffenwechsel", --- ["Choose your side! If you want to join the strange man, walk up to him.|Otherwise, walk away from him. If you decide to att...nevermind..."] = "", -- A_Classic_Fairytale:shadow - ["Clumsy"] = "Hoppla", --- ["Cluster Bomb MASTER!"] = "", -- Basic_Training_-_Cluster_Bomb --- ["Cluster Bomb Training"] = "", -- Basic_Training_-_Cluster_Bomb - ["Codename: Teamwork"] = "Code-Name: Teamwork", --- ["Collateral Damage"] = "", -- A_Classic_Fairytale:journey --- ["Collateral Damage II"] = "", -- A_Classic_Fairytale:journey --- ["Collect all the crates, but remember, our time in this life is limited!"] = "", -- A_Classic_Fairytale:first_blood --- ["Collect or destroy all the health crates."] = "", -- User_Mission_-_RCPlane_Challenge --- ["Collect the crate on the right.|Hint: Select the rope, [Up] or [Down] to aim, [Space] to fire, directional keys to move.|Ropes can be fired again in the air!"] = "", -- A_Classic_Fairytale:first_blood --- ["Collect the crates within the time limit!|If you fail, you'll have to try again."] = "", -- A_Classic_Fairytale:first_blood --- ["Come closer, so that your training may continue!"] = "", -- A_Classic_Fairytale:first_blood --- ["Compete to use as few planes as possible!"] = "", -- User_Mission_-_RCPlane_Challenge - ["Complete the track as fast as you can!"] = "Durchlaufe die Strecke so schnell du kannst!", --- ["COMPLETION TIME"] = "", -- User_Mission_-_Rope_Knock_Challenge --- ["Configuration accepted."] = "", -- WxW --- ["Congratulations"] = "", -- Basic_Training_-_Rope - ["Congratulations!"] = "Gratulation!", --- ["Congratulations! You needed only half of time|to eliminate all targets."] = "", -- Basic_Training_-_Cluster_Bomb --- ["Congratulations! You've completed the Rope tutorial! |- Tutorial ends in 10 seconds!"] = "", -- Basic_Training_-_Rope - ["Congratulations! You've eliminated all targets|within the allowed time frame."] = "Gratulation! Du hast alle Ziele innerhalb der|verfügbaren Zeit ausgeschaltet.", --Bazooka, Shotgun, SniperRifle --- ["Continental supplies"] = "", -- Continental_supplies - ["Control pillars to score points."] = "Kontrolliere die Säulen um Punkte zu erhalten.", --- ["Corporationals"] = "", -- A_Classic_Fairytale:queen --- ["Corpsemonger"] = "", -- A_Classic_Fairytale:shadow --- ["Corpse Thrower"] = "", -- A_Classic_Fairytale:epil --- ["Crates Left:"] = "", -- User_Mission_-_RCPlane_Challenge - ["Cybernetic Empire"] = "Kybernetisches Imperium", --- ["Cyborg. It's what the aliens call themselves."] = "", -- A_Classic_Fairytale:enemy --- ["Dahmer"] = "", -- A_Classic_Fairytale:backstab - ["DAMMIT, ROOKIE! GET OFF MY HEAD!"] = "VERDAMMT, REKRUT! RUNTER VON MEINEM KOPF!", - ["DAMMIT, ROOKIE!"] = "VERDAMMT, REKRUT!", --- ["Dangerous Ducklings"] = "", - ["Deadweight"] = "Gravitus", --- ["Defeat the cannibals"] = "", -- A_Classic_Fairytale:backstab --- ["Defeat the cannibals!|"] = "", -- A_Classic_Fairytale:united --- ["Defeat the cannibals!|Grenade hint: set the timer with [1-5], aim with [Up]/[Down] and hold [Space] to set power"] = "", -- A_Classic_Fairytale:shadow --- ["Defeat the cyborgs!"] = "", -- A_Classic_Fairytale:enemy --- ["Defend yourself!|Hint: You can get tips on using weapons by moving your mouse over them in the weapon selection menu"] = "", -- A_Classic_Fairytale:shadow - ["Demolition is fun!"] = "Zerstörung macht Spaß!", --- ["Dense Cloud"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united --- ["Dense Cloud must have already told them everything..."] = "", -- A_Classic_Fairytale:shadow - ["Depleted Kamikaze!"] = "Munitionsloses Kamikaze!", --- ["Destroy him, Leaks A Lot! He is responsible for the deaths of many of us!"] = "", -- A_Classic_Fairytale:first_blood - ["Destroy invaders to score points."] = "Zerstöre die Angreifer um Punkte zu erhalten.", --- ["Destroy the targets!|Hint: Select the Shoryuken and hit [Space]|P.S. You can use it mid-air."] = "", -- A_Classic_Fairytale:first_blood --- ["Destroy the targets!|Hint: [Up], [Down] to aim, [Space] to shoot"] = "", -- A_Classic_Fairytale:first_blood --- ["Did anyone follow you?"] = "", -- A_Classic_Fairytale:united --- ["Did you see him coming?"] = "", -- A_Classic_Fairytale:shadow --- ["Did you warn the village?"] = "", -- A_Classic_Fairytale:shadow --- ["Die, die, die!"] = "", -- A_Classic_Fairytale:dragon --- ["Disguise as a Rockhopper Penguin: [Swap place with a random enemy hog in the circle]"] = "", -- Continental_supplies --- ["Dist: "] = "", -- Space_Invasion --- ["Do not laugh, inexperienced one, for he speaks the truth!"] = "", -- A_Classic_Fairytale:backstab --- ["Do not let his words fool you, young one! He will stab you in the back as soon as you turn away!"] = "", -- A_Classic_Fairytale:first_blood --- ["Do the deed"] = "", -- A_Classic_Fairytale:first_blood --- ["Double Kill!"] = "", --- ["DOUBLE KILL"] = "", -- Mutant --- ["Do you have any idea how valuable grass is?"] = "", -- A_Classic_Fairytale:enemy --- ["Do you think you're some kind of god?"] = "", -- A_Classic_Fairytale:enemy --- ["Dragon's Lair"] = "", -- A_Classic_Fairytale:dragon --- ["Drills"] = "", -- A_Classic_Fairytale:backstab --- ["Drone Hunter!"] = "", --- ["Drop a bomb: [drop some heroic wind that will turn into a bomb on impact]"] = "", -- Continental_supplies - ["Drowner"] = "Absäufer", --- ["Dude, all the plants are gone!"] = "", -- A_Classic_Fairytale:family --- ["Dude, can you see Ramon and Spiky?"] = "", -- A_Classic_Fairytale:journey --- ["Dude, that's so cool!"] = "", -- A_Classic_Fairytale:backstab --- ["Dude, we really need a new shaman..."] = "", -- A_Classic_Fairytale:shadow --- ["Dude, what's this place?!"] = "", -- A_Classic_Fairytale:dragon --- ["Dude, where are we?"] = "", -- A_Classic_Fairytale:backstab --- ["Dude, wow! I just had the weirdest high!"] = "", -- A_Classic_Fairytale:backstab --- ["Duration"] = "", -- Continental_supplies --- ["Dust storm: [Deals 20 damage to all enemies in the circle]"] = "", -- Continental_supplies - ["Each turn you get 1-3 random weapons"] = "Du bekommst jede Runde 1-3 zufällig gewählte Waffen", - ["Each turn you get one random weapon"] = "Du bekommst jede Runde eine zufällig gewählte Waffe.", --- ["Eagle Eye"] = "", -- A_Classic_Fairytale:backstab --- ["Eagle Eye: [Blink to the impact ~ one shot]"] = "", -- Continental_supplies --- ["Ear Sniffer"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:epil --- ["Elderbot"] = "", -- A_Classic_Fairytale:family --- ["Elimate your captor."] = "", -- User_Mission_-_The_Great_Escape - ["Eliminate all enemies"] = "Vernichte alle Gegner", - ["Eliminate all targets before your time runs out.|You have unlimited ammo for this mission."] = "Eliminiere alle Ziele bevor die Zeit ausläuft.|Du hast in dieser Mission unbegrenzte Munition.", --Bazooka, Shotgun, SniperRifle --- ["Eliminate enemy hogs and take their weapons."] = "", -- Highlander - ["Eliminate Poison before the time runs out"] = "Neutralisiere das Gift bevor die Zeit abgelaufen ist", - ["Eliminate the Blue Team"] = "Lösche das Blaue Team aus", - ["Eliminate the enemy before the time runs out"] = "Vernichte den Feind bevor die Zeit abgelaufen ist", -- User_Mission_-_Bamboo_Thicket, User_Mission_-_Newton_and_the_Hammock - ["Eliminate the enemy hogs to win."] = "Vernichte alle gegnerischen Igel um zu gewinnen", - ["Eliminate the enemy specialists."] = "Vernichte die gegnerischen Spezialisten", - ["- Eliminate Unit 3378 |- Feeble Resistance must survive"] = "- Vernichte Einheit 3378 | Kraftloser Widerstand muss überleben", --- ["Elmo"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen --- ["Energetic Engineer"] = "", - ["Enjoy the swim..."] = "Viel Spaß beim Schwimmen...", --- ["[Enter]"] = "", --- ["Europe"] = "", -- Continental_supplies --- [" ever done to you?!"] = "", -- A_Classic_Fairytale:backstab --- ["Everyone knows this."] = "", -- A_Classic_Fairytale:enemy --- ["Every single time!"] = "", -- A_Classic_Fairytale:dragon --- ["Everything looks OK..."] = "", -- A_Classic_Fairytale:enemy --- ["Exactly, man! That was my dream."] = "", -- A_Classic_Fairytale:backstab --- ["Eye Chewer"] = "", -- A_Classic_Fairytale:journey --- ["INSANITY"] = "", -- Mutant --- ["Family Reunion"] = "", -- A_Classic_Fairytale:family - ["Fastest lap: "] = "Schnellste Runde: ", - ["Feeble Resistance"] = "Kraftloser Widerstand", --- ["Fell From Grace"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen --- ["Fell From Heaven"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:first_blood, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen --- ["Fell From Heaven is the best! Fell From Heaven is the greatest!"] = "", -- A_Classic_Fairytale:family --- ["Femur Lover"] = "", -- A_Classic_Fairytale:shadow --- ["Fierce Competition!"] = "", -- Space_Invasion --- ["Fiery Water"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united --- ["Find your tribe!|Cross the lake!"] = "", -- A_Classic_Fairytale:dragon --- ["Finish your training|Hint: Animations can be skipped with the [Precise] key."] = "", -- A_Classic_Fairytale:first_blood --- ["Fire a mine: [Does what it says ~ Cant be dropped close to an enemy ~ 1 sec]"] = "", -- Continental_supplies - ["Fire"] = "Feuer", --- ["First aid kits?!"] = "", -- A_Classic_Fairytale:united --- ["First Blood"] = "", -- A_Classic_Fairytale:first_blood --- ["FIRST BLOOD MUTATES"] = "", -- Mutant --- ["First Steps"] = "", -- A_Classic_Fairytale:first_blood - ["Flag captured!"] = "Fahne erobert!", - ["Flag respawned!"] = "Fahne wieder erschienen!", - ["Flag returned!"] = "Fahne zurückgebracht!", - ["Flags, and their home base will be placed where each team ends their first turn."] = "Fahnen und deren Heimatstandort werden dort plaziert wo jedes Team deren ersten Zug beendet.", --- ["Flamer"] = "", --- ["Flaming Worm"] = "", -- A_Classic_Fairytale:backstab --- ["Flare: [fire up some bombs depending on hogs depending on hogs in the circle"] = "", -- Continental_supplies --- ["Flesh for Brainz"] = "", -- A_Classic_Fairytale:journey --- ["For improved features/stability, play 0.9.18+"] = "", -- WxW --- ["Free Dense Cloud and continue the mission!"] = "", -- A_Classic_Fairytale:journey --- ["Friendly Fire!"] = "", - ["fuel extended!"] = "Treibstoff aus!", - ["GAME BEGUN!!!"] = "SPIEL GESTARTET!!!", --- ["Game Modifiers: "] = "", -- The_Specialists - ["GAME OVER!"] = "SPIEL ZU ENDE!", - ["Game Started!"] = "Spiel Gestartet!]", --- ["Game? Was this a game to you?!"] = "", -- A_Classic_Fairytale:enemy --- ["GasBomb"] = "", -- Continental_supplies --- ["Gas Gargler"] = "", -- A_Classic_Fairytale:queen --- ["Get Dense Cloud out of the pit!"] = "", -- A_Classic_Fairytale:journey - ["Get on over there and take him out!"] = "Mach, dass du hinüber kommst und schalte ihn aus!", --- ["Get on the head of the mole"] = "", -- A_Classic_Fairytale:first_blood --- ["Get out of there!"] = "", -- User_Mission_-_The_Great_Escape --- ["Get that crate!"] = "", -- A_Classic_Fairytale:first_blood --- ["Get the crate on the other side of the island!|"] = "", -- A_Classic_Fairytale:journey --- ["Get to the target using your rope! |Controls: Left & Right to swing the rope - Up & Down to Contract and Expand!"] = "", -- Basic_Training_-_Rope --- ["Get your teammates out of their natural prison and save the princess!|Hint: Drilling holes should solve everything.|Hint: It might be a good idea to place a girder before starting to drill. Just saying.|Hint: All your hedgehogs need to be above the marked height!|Hint: Leaks A Lot needs to get really close to the princess!"] = "", -- A_Classic_Fairytale:family --- ["GG!"] = "", -- User_Mission_-_Rope_Knock_Challenge --- ["Gimme Bones"] = "", -- A_Classic_Fairytale:backstab --- ["Glark"] = "", -- A_Classic_Fairytale:shadow - ["Goal"] = "Ziel", - ["GO! GO! GO!"] = "Bewegung, Bewegung, Bewegung!", - ["Good birdy......"] = "Braver Vogel......", --- ["Good Dude"] = "", -- User_Mission_-_The_Great_Escape --- ["Good idea, they'll never find us there!"] = "", -- A_Classic_Fairytale:united --- ["Good luck...or else!"] = "", -- A_Classic_Fairytale:journey - ["Good luck out there!"] = "Viel Glück da draußen!", - ["Good so far!"] = "Gut soweit!", - ["Good to go!"] = "Startklar!", --- ["Go on top of the flower"] = "", -- A_Classic_Fairytale:first_blood --- ["Go, quick!"] = "", -- A_Classic_Fairytale:backstab --- ["Gorkij"] = "", -- A_Classic_Fairytale:journey --- ["Go surf!"] = "", -- WxW - ["GOTCHA!"] = "ERWISCHT!", - ["Grab Mines/Explosives"] = "Sammle Minen/Fässer", --- ["Great choice, Steve! Mind if I call you that?"] = "", -- A_Classic_Fairytale:shadow --- ["Great work! Now hit it with your Baseball Bat! |Tip: You can change weapon with 'Right Click'!"] = "", -- Basic_Training_-_Rope --- ["Great! You will be contacted soon for assistance."] = "", -- A_Classic_Fairytale:shadow --- ["Green lipstick bullet: [Is poisonous]"] = "", -- Continental_supplies --- ["Greetings, "] = "", -- A_Classic_Fairytale:dragon --- ["Greetings, cloudy one!"] = "", -- A_Classic_Fairytale:shadow --- ["Grenade Training"] = "", -- Basic_Training_-_Grenade --- ["Grenadiers"] = "", -- Basic_Training_-_Grenade --- ["Guys, do you think there's more of them?"] = "", -- A_Classic_Fairytale:backstab --- ["HAHA!"] = "", -- A_Classic_Fairytale:enemy --- ["Haha!"] = "", -- A_Classic_Fairytale:united --- ["Hahahaha!"] = "", - ["Haha, now THAT would be something!"] = "Haha, na DAS wär ja was!", --- ["Hannibal"] = "", -- A_Classic_Fairytale:epil - ["Hapless Hogs"] = "Glücklose Igel", - [" Hapless Hogs left!"] = " Glücklose Igel verbleibend!", - --- [" HAS MUTATED"] = "", -- Mutant --- ["Hatless Jerry"] = "", -- A_Classic_Fairytale:queen --- ["Have no illusions, your tribe is dead, indifferent of your choice."] = "", -- A_Classic_Fairytale:shadow --- ["Have we ever attacked you first?"] = "", -- A_Classic_Fairytale:enemy - ["Health crates extend your time."] = "Medipacks verlängern deine Zeit.", --- ["Heavy Cannfantry"] = "", -- A_Classic_Fairytale:united - ["Heavy"] = "Schwierig", --- ["Hedge-cogs"] = "", -- A_Classic_Fairytale:enemy --- ["Hedgehog projectile: [fire your hog like a Sticky Bomb]"] = "", -- Continental_supplies - ["Hedgewars-Basketball"] = "Hedgewars-Basketball", - ["Hedgewars-Knockball"] = "Hedgewars-Knockball", --- ["Hedgibal Lecter"] = "", -- A_Classic_Fairytale:backstab - ["Heh, it's not that bad."] = "Hehe, so schlimm ist es nicht.", --- ["Hello again, "] = "", -- A_Classic_Fairytale:family --- ["Help me, Leaks!"] = "", -- A_Classic_Fairytale:journey --- ["Help me, please!!!"] = "", -- A_Classic_Fairytale:journey --- ["Help me, please!"] = "", -- A_Classic_Fairytale:journey --- ["He moves like an eagle in the sky."] = "", -- A_Classic_Fairytale:first_blood --- ["He must be in the village already."] = "", -- A_Classic_Fairytale:journey --- ["Here, let me help you!"] = "", -- A_Classic_Fairytale:backstab --- ["Here, let me help you save her!"] = "", -- A_Classic_Fairytale:family --- ["Here...pick your weapon!"] = "", -- A_Classic_Fairytale:first_blood --- ["Hero Team"] = "", -- User_Mission_-_The_Great_Escape --- ["He's so brave..."] = "", -- A_Classic_Fairytale:first_blood --- ["He won't be selling us out anymore!"] = "", -- A_Classic_Fairytale:backstab --- ["Hey, guys!"] = "", -- A_Classic_Fairytale:backstab --- ["Hey guys!"] = "", -- A_Classic_Fairytale:united --- ["Hey! This is cheating!"] = "", -- A_Classic_Fairytale:journey --- ["HIGHLANDER"] = "", -- Highlander --- ["Hightime"] = "", -- A_Classic_Fairytale:first_blood --- ["Hint: Double Jump - Press [Backspace] twice"] = "", -- A_Classic_Fairytale:first_blood --- ["Hint: Select the BlowTorch, aim and press [Fire]. Press [Fire] again to stop.|Don't blow up the crate."] = "", -- A_Classic_Fairytale:journey --- ["Hint: Select the LowGravity and press [Fire]."] = "", -- A_Classic_Fairytale:journey --- ["Hint: you might want to stay out of sight and take all the crates...|"] = "", -- A_Classic_Fairytale:journey --- ["His arms are so strong!"] = "", -- A_Classic_Fairytale:first_blood --- ["Hit Combo!"] = "", --- ["Hmmm..."] = "", --- ["Hmmm...actually...I didn't either."] = "", -- A_Classic_Fairytale:enemy --- ["Hmmm, I'll have to find some way of moving him off this anti-portal surface..."] = "", -- portal --- ["Hmmm...it's a draw. How unfortunate!"] = "", -- A_Classic_Fairytale:enemy --- ["Hmmm...perhaps a little more time will help."] = "", -- A_Classic_Fairytale:first_blood --- ["Hogminator"] = "", -- A_Classic_Fairytale:family --- ["Hogs in sight!"] = "", -- Continental_supplies --- ["HOLY SHYTE!"] = "", -- Mutant --- ["Honest Lee"] = "", -- A_Classic_Fairytale:enemy - ["Hooray!"] = "Hurra!", --- ["Hostage Situation"] = "", -- A_Classic_Fairytale:family --- ["How can I ever repay you for saving my life?"] = "", -- A_Classic_Fairytale:journey --- ["How come in a village full of warriors, it's up to me to save it?"] = "", -- A_Classic_Fairytale:dragon --- ["How difficult would you like it to be?"] = "", -- A_Classic_Fairytale:first_blood --- ["HOW DO THEY KNOW WHERE WE ARE???"] = "", -- A_Classic_Fairytale:united --- ["However, if you fail to do so, she dies a most violent death, just like your friend! Muahahaha!"] = "", -- A_Classic_Fairytale:journey --- ["However, if you fail to do so, she dies a most violent death! Muahahaha!"] = "", -- A_Classic_Fairytale:journey --- ["However, my mates don't agree with me on letting you go..."] = "", -- A_Classic_Fairytale:dragon --- [" HP"] = "", -- Mutant - ["Hunter"] = "Jäger", --Bazooka, Shotgun, SniperRifle --- ["I believe there's more of them."] = "", -- A_Classic_Fairytale:backstab --- ["I can see you have been training diligently."] = "", -- A_Classic_Fairytale:first_blood --- ["I can't believe it worked!"] = "", -- A_Classic_Fairytale:shadow --- ["I can't believe this!"] = "", -- A_Classic_Fairytale:enemy --- ["I can't believe what I'm hearing!"] = "", -- A_Classic_Fairytale:backstab --- ["I can't wait any more, I have to save myself!"] = "", -- A_Classic_Fairytale:shadow --- ["I could just teleport myself there..."] = "", -- A_Classic_Fairytale:family --- ["I'd better get going myself."] = "", -- A_Classic_Fairytale:journey --- ["I didn't until about a month ago."] = "", -- A_Classic_Fairytale:enemy --- ["I don't know how you did that.. But good work! |The next one should be easy as cake for you!"] = "", -- Basic_Training_-_Rope --- ["I feel something...a place! They will arrive near the circles!"] = "", -- A_Classic_Fairytale:backstab --- ["If only I had a way..."] = "", -- A_Classic_Fairytale:backstab --- ["If only I were given a chance to explain my being here..."] = "", -- A_Classic_Fairytale:first_blood --- ["I forgot that she's the daughter of the chief, too..."] = "", -- A_Classic_Fairytale:backstab --- ["If they try coming here, they can have a taste of my delicious knuckles!"] = "", -- A_Classic_Fairytale:united --- ["If you agree to provide the information we need, you will be spared!"] = "", -- A_Classic_Fairytale:shadow --- ["If you can get that crate fast enough, your beloved \"princess\" may go free."] = "", -- A_Classic_Fairytale:journey --- ["If you decide to help us, though, we will no longer need to find a new governor for the island."] = "", -- A_Classic_Fairytale:shadow --- ["If you get stuck, use your Desert Eagle or restart the mission!|"] = "", -- A_Classic_Fairytale:journey --- ["If you know what I mean..."] = "", -- A_Classic_Fairytale:shadow --- ["If you say so..."] = "", -- A_Classic_Fairytale:shadow - --- ["I guess you'll have to kill them."] = "", -- A_Classic_Fairytale:dragon --- ["I have come to make you an offering..."] = "", -- A_Classic_Fairytale:shadow --- ["I have no idea where that mole disappeared...Can you see it?"] = "", -- A_Classic_Fairytale:shadow --- ["I have to follow that alien."] = "", -- A_Classic_Fairytale:backstab --- ["I have to get back to the village!"] = "", -- A_Classic_Fairytale:shadow --- ["I hope you are prepared for a small challenge, young one."] = "", -- A_Classic_Fairytale:first_blood --- ["I just don't want to sink to your level."] = "", -- A_Classic_Fairytale:backstab --- ["I just found out that they have captured your princess!"] = "", -- A_Classic_Fairytale:family --- ["I just wonder where Ramon and Spiky disappeared..."] = "", -- A_Classic_Fairytale:journey --- ["I'll hold them off while you return to the village!"] = "", -- A_Classic_Fairytale:shadow --- ["Imagine those targets are the wolves that killed your parents! Take your anger out on them!"] = "", -- A_Classic_Fairytale:first_blood --- ["I'm...alive? How? Why?"] = "", -- A_Classic_Fairytale:backstab --- ["I'm a ninja."] = "", -- A_Classic_Fairytale:dragon --- ["I marked the place of their arrival. You're welcome!"] = "", -- A_Classic_Fairytale:backstab --- ["I'm certain that this is a misunderstanding, fellow hedgehogs!"] = "", -- A_Classic_Fairytale:first_blood --- ["I mean, none of you ceased to live."] = "", -- A_Classic_Fairytale:enemy --- ["I'm getting old for this!"] = "", -- A_Classic_Fairytale:family --- ["I'm getting thirsty..."] = "", -- A_Classic_Fairytale:family --- ["I'm here to help you rescue her."] = "", -- A_Classic_Fairytale:family --- ["I'm not sure about that!"] = "", -- A_Classic_Fairytale:united --- ["Impressive...you are still dry as the corpse of a hawk after a week in the desert..."] = "", -- A_Classic_Fairytale:first_blood --- ["I'm so scared!"] = "", -- A_Classic_Fairytale:united --- ["Incredible..."] = "", -- A_Classic_Fairytale:shadow --- ["I need to find the others!"] = "", -- A_Classic_Fairytale:backstab --- ["I need to get to the other side of this island, fast!"] = "", -- A_Classic_Fairytale:journey --- ["I need to move the tribe!"] = "", -- A_Classic_Fairytale:united --- ["I need to prevent their arrival!"] = "", -- A_Classic_Fairytale:backstab --- ["I need to warn the others."] = "", -- A_Classic_Fairytale:backstab --- ["In fact, you are the only one that's been acting strangely."] = "", -- A_Classic_Fairytale:backstab --- ["In order to get to the other side, you need to collect the crates first.|"] = "", -- A_Classic_Fairytale:dragon - ["Instructor"] = "Ausbilder", -- 01#Boot_Camp, User_Mission_-_Dangerous_Ducklings --- ["Interesting idea, haha!"] = "", -- A_Classic_Fairytale:enemy --- ["Interesting! Last time you said you killed a cannibal!"] = "", -- A_Classic_Fairytale:backstab --- ["In the meantime, take these and return to your \"friend\"!"] = "", -- A_Classic_Fairytale:shadow - ["invaders destroyed"] = "Angreifer zerstört", --- ["Invasion"] = "", -- A_Classic_Fairytale:united --- ["I saw it with my own eyes!"] = "", -- A_Classic_Fairytale:shadow --- ["I see..."] = "", -- A_Classic_Fairytale:shadow --- ["I see you have already taken the leap of faith."] = "", -- A_Classic_Fairytale:first_blood --- ["I see you would like his punishment to be more...personal..."] = "", -- A_Classic_Fairytale:first_blood --- ["I sense another wave of cannibals heading my way!"] = "", -- A_Classic_Fairytale:backstab --- ["I sense another wave of cannibals heading our way!"] = "", -- A_Classic_Fairytale:backstab --- ["I shouldn't have drunk that last pint."] = "", -- A_Classic_Fairytale:dragon --- ["Is this place in my head?"] = "", -- A_Classic_Fairytale:dragon --- ["It doesn't matter. I won't let that alien hurt my daughter!"] = "", -- A_Classic_Fairytale:dragon --- ["I think we are safe here."] = "", -- A_Classic_Fairytale:backstab --- ["I thought their shaman died when he tried our medicine!"] = "", -- A_Classic_Fairytale:shadow --- ["It is called 'Hogs of Steel'."] = "", -- A_Classic_Fairytale:enemy --- ["It is time to practice your fighting skills."] = "", -- A_Classic_Fairytale:first_blood --- ["It must be a childhood trauma..."] = "", -- A_Classic_Fairytale:family --- ["It must be the aliens!"] = "", -- A_Classic_Fairytale:backstab --- ["It must be the aliens' deed."] = "", -- A_Classic_Fairytale:backstab --- ["It must be the cyborgs again!"] = "", -- A_Classic_Fairytale:enemy --- ["I told you, I just found them."] = "", -- A_Classic_Fairytale:backstab - ["It's a good thing SUDDEN DEATH is 99 turns away..."] = "Gut, dass SUDDEN DEATH noch 99 Runden entfernt ist...", --- ["It's always up to women to clear up the mess men created!"] = "", -- A_Classic_Fairytale:dragon --- ["It's a shame, I forgot how to do that!"] = "", -- A_Classic_Fairytale:family --- ["It's impossible to communicate with the spirits without a shaman."] = "", -- A_Classic_Fairytale:shadow --- ["It's over..."] = "", -- A_Classic_Fairytale:shadow --- ["It's time you learned that your actions have consequences!"] = "", -- A_Classic_Fairytale:journey --- ["It's worth more than wood!"] = "", -- A_Classic_Fairytale:enemy --- ["It wants our brains!"] = "", -- A_Classic_Fairytale:shadow --- ["It was not a dream, unwise one!"] = "", -- A_Classic_Fairytale:backstab --- ["I've seen this before. They just appear out of thin air."] = "", -- A_Classic_Fairytale:united --- ["I want to play a game..."] = "", -- A_Classic_Fairytale:journey --- ["I want to see how it handles this!"] = "", -- A_Classic_Fairytale:backstab --- ["I wish to help you, "] = "", -- A_Classic_Fairytale:dragon --- ["I wonder where Dense Cloud is..."] = "", -- A_Classic_Fairytale:journey, A_Classic_Fairytale:shadow --- ["I wonder why I'm so angry all the time..."] = "", -- A_Classic_Fairytale:family --- ["I won't let you kill her!"] = "", -- A_Classic_Fairytale:journey --- ["Jack"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen --- ["Jeremiah"] = "", -- A_Classic_Fairytale:dragon --- ["John"] = "", -- A_Classic_Fairytale:journey --- ["Judas"] = "", -- A_Classic_Fairytale:backstab - ["Jumping is disabled"] = "Sprünge sind deaktiviert!", --- ["Just kidding, none of you have died!"] = "", -- A_Classic_Fairytale:enemy --- ["Just on a walk."] = "", -- A_Classic_Fairytale:united --- ["Just wait till I get my hands on that trauma! ARGH!"] = "", -- A_Classic_Fairytale:family - ["Kamikaze Expert!"] = "Kamikazeexperte!", - ["Keep it up!"] = "Weiter so!", --- ["Kerguelen"] = "", -- Continental_supplies - ["Killing spree!"] = "Blutrausch!", --- ["KILL IT!"] = "", -- A_Classic_Fairytale:first_blood --- ["KILLS"] = "", --- ["Kill the aliens!"] = "", -- A_Classic_Fairytale:dragon --- ["Kill the cannibal!"] = "", -- A_Classic_Fairytale:first_blood --- ["Kill the traitor...or spare his life!|Kill him or press [Precise]!"] = "", -- A_Classic_Fairytale:backstab - ["Last Target!"] = "Letzte Zielscheibe!", --- ["Leader"] = "", -- A_Classic_Fairytale:enemy --- ["Leaderbot"] = "", -- A_Classic_Fairytale:queen --- ["Leaks A Lot"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:first_blood, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united --- ["Leaks A Lot, depressed for killing his loved one, failed to save the village..."] = "", -- A_Classic_Fairytale:journey --- ["Leaks A Lot gave his life for his tribe! He should have survived!"] = "", -- A_Classic_Fairytale:first_blood --- ["Leaks A Lot must survive!"] = "", -- A_Classic_Fairytale:journey --- ["Led Heart"] = "", -- A_Classic_Fairytale:queen --- ["Lee"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen --- ["[Left Shift]"] = "", --- ["Let a Continent provide your weapons!"] = "", -- Continental_supplies --- ["Let me test your skills a little, will you?"] = "", -- A_Classic_Fairytale:journey --- ["Let's go home!"] = "", -- A_Classic_Fairytale:journey --- ["Let's head back to the village!"] = "", -- A_Classic_Fairytale:shadow --- ["Let's see what your comrade does now!"] = "", -- A_Classic_Fairytale:journey --- ["Let's show those cannibals what we're made of!"] = "", -- A_Classic_Fairytale:backstab --- ["Let them have a taste of my fury!"] = "", -- A_Classic_Fairytale:backstab --- ["Let us help, too!"] = "", -- A_Classic_Fairytale:backstab --- ["Light Cannfantry"] = "", -- A_Classic_Fairytale:united - ["Listen up, maggot!!"] = "Aufgepasst, du Made!!", --- ["Little did they know that this hunt will mark them forever..."] = "", -- A_Classic_Fairytale:shadow --- ["Lively Lifeguard"] = "", --- ["Lonely Cries: [Rise the water if no hog is in the circle and deal 1 damage to all hogs]"] = "", -- Continental_supplies --- ["Look, I had no choice!"] = "", -- A_Classic_Fairytale:backstab --- ["Look out! There's more of them!"] = "", -- A_Classic_Fairytale:backstab --- ["Look out! We're surrounded by cannibals!"] = "", -- A_Classic_Fairytale:enemy --- ["Looks like the whole world is falling apart!"] = "", -- A_Classic_Fairytale:enemy --- ["Luckily, I've managed to snatch some of them."] = "", -- A_Classic_Fairytale:united --- ["LUDICROUS KILL"] = "", -- Mutant --- ["May the spirits aid you in all your quests!"] = "", -- A_Classic_Fairytale:backstab --- ["Medicine: [Fire some exploding medicine that will heal all hogs effected by the explosion]"] = "", -- Continental_supplies --- ["MEGA KILL"] = "", -- Mutant --- ["Meiwes"] = "", -- A_Classic_Fairytale:backstab --- ["Mindy"] = "", -- A_Classic_Fairytale:united - ["Mine Deployer"] = "Minenleger", - ["Mine Eater!"] = "Minenfresser!", - ["|- Mines Time:"] = "| - Minenzündzeit: ", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork - ["MISSION FAILED"] = "MISSION GESCHEITERT", -- User_Mission_-_Dangerous_Ducklings, User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork - ["MISSION SUCCESSFUL"] = "MISSION ERFOLGREICH", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork - ["MISSION SUCCESS"] = "MISSIONSERFOLG", --- ["Molotov"] = "", -- Continental_supplies --- ["MONSTER KILL"] = "", -- Mutant --- ["More Natives"] = "", -- A_Classic_Fairytale:epil - ["Movement: [Up], [Down], [Left], [Right]"] = "Bewegung: [Hoch], [Runter], [Links], [Rechts]", --- ["Multi-shot!"] = "", - ["Munition!"] = "Munition erschöpft!", --- ["Muriel"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen --- ["Muscle Dissolver"] = "", -- A_Classic_Fairytale:shadow --- ["-------"] = "", -- Mutant --- ["Nade Boy"] = "", -- Basic_Training_-_Grenade --- ["Name"] = "", -- A_Classic_Fairytale:queen - ["Nameless Heroes"] = "Namenlose Helden", --- ["Nancy Screw"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:queen --- ["Napalm rocket: [Fire a bomb with napalm!]"] = "", -- Continental_supplies --- ["Natives"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:first_blood, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united - ["New Barrels Per Turn"] = "Neue Fässer jede Runde", - ["NEW CLAN RECORD: "] = "NEUER KLAN-REKORD", - ["NEW fastest lap: "] = "NEUE schnellste Runde: ", - ["New Mines Per Turn"] = "Neue Minen jede Runde", - ["NEW RACE RECORD: "] = "NEUER RENNREKORD: ", --- ["Newton's Hammock"] = "", --- ["Nicely done, meatbags!"] = "", -- A_Classic_Fairytale:enemy --- ["Nice work, "] = "", -- A_Classic_Fairytale:dragon --- ["Nice work!"] = "", -- A_Classic_Fairytale:enemy --- ["Nilarian"] = "", -- A_Classic_Fairytale:queen --- ["No, I came back to help you out..."] = "", -- A_Classic_Fairytale:shadow --- ["No...I wonder where they disappeared?!"] = "", -- A_Classic_Fairytale:journey --- ["Nom-Nom"] = "", -- A_Classic_Fairytale:journey --- ["NomNom"] = "", -- A_Classic_Fairytale:united --- ["Nope. It was one fast mole, that's for sure."] = "", -- A_Classic_Fairytale:shadow --- ["No! Please, help me!"] = "", -- A_Classic_Fairytale:journey --- ["NORMAL"] = "", -- Continental_supplies --- ["North America"] = "", -- Continental_supplies --- ["Not all hogs are born equal."] = "", -- Highlander - ["NOT ENOUGH WAYPOINTS"] = "NICHT GENUG WEGPUNKTE", --- ["Not now, Fiery Water!"] = "", -- A_Classic_Fairytale:backstab - ["Not So Friendly Match"] = "Kein-so-Freundschaftsspiel", -- Basketball, Knockball --- ["Not you again! My head still hurts from last time!"] = "", -- A_Classic_Fairytale:shadow --- ["No, we made sure of that!"] = "", -- A_Classic_Fairytale:united --- ["Now find the next target! |Tip: Normally you lose health by falling down, so be careful!"] = "", -- Basic_Training_-_Rope --- ["No! What have I done?! What have YOU done?!"] = "", -- A_Classic_Fairytale:journey --- ["No. Where did he come from?"] = "", -- A_Classic_Fairytale:shadow --- ["Now how do I get on the other side?!"] = "", -- A_Classic_Fairytale:dragon --- ["No. You and the rest of the tribe are safer there!"] = "", -- A_Classic_Fairytale:backstab --- ["Obliterate them!|Hint: You might want to take cover..."] = "", -- A_Classic_Fairytale:shadow --- ["Obstacle course"] = "", -- A_Classic_Fairytale:dragon --- ["Of course I have to save her. What did I expect?!"] = "", -- A_Classic_Fairytale:family --- ["OH, COME ON!"] = "", -- A_Classic_Fairytale:journey --- ["Oh, my!"] = "", -- A_Classic_Fairytale:first_blood --- ["Oh, my! This is even more entertaining than I've expected!"] = "", -- A_Classic_Fairytale:backstab - ["Oh no! Just try again!"] = "Oh nein! Versuch's nochmal!", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork --- ["Oh no, not "] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united - ["Oh no! Time's up! Just try again."] = "Oh nein! Die Zeit ist um! Versuche es nochmal.", --Bazooka, Shotgun, SniperRifle --- ["Oh no! You failed! Just try again."] = "", -- Basic_Training_-_Cluster_Bomb --- ["Oh, silly me! I forgot that I'm the shaman."] = "", -- A_Classic_Fairytale:backstab --- ["Olive"] = "", -- A_Classic_Fairytale:united --- ["Omnivore"] = "", -- A_Classic_Fairytale:first_blood --- ["Once upon a time, on an island with great natural resources, lived two tribes in heated conflict..."] = "", -- A_Classic_Fairytale:first_blood --- ["ONE HOG PER TEAM! KILLING EXCESS HEDGES"] = "", -- Mutant --- ["One tribe was peaceful, spending their time hunting and training, enjoying the small pleasures of life..."] = "", -- A_Classic_Fairytale:first_blood --- ["Oops...I dropped them."] = "", -- A_Classic_Fairytale:united --- ["Open that crate and we will continue!"] = "", -- A_Classic_Fairytale:first_blood --- ["Operation Diver"] = "", - ["Opposing Team: "] = "Gegnerisches Team: ", --- ["Orlando Boom!"] = "", -- A_Classic_Fairytale:queen --- ["Ouch!"] = "", -- User_Mission_-_Rope_Knock_Challenge --- ["Our tribe, our beautiful island!"] = "", -- A_Classic_Fairytale:enemy --- ["Parachute"] = "", -- Continental_supplies - ["Pathetic Hog #%d"] = "Erbärmlicher Igel #%d", - ["Pathetic Resistance"] = "Erbärmlicher Widerstand", -- User_Mission_-_Bamboo_Thicket, User_Mission_-_Newton_and_the_Hammock --- ["Perfect! Now try to get the next crate without hurting yourself!"] = "", -- A_Classic_Fairytale:first_blood - ["Per-Hog Ammo"] = "Munition pro Igel", --- ["- Per team weapons|- 9 weaponschemes|- Unique new weapons| |Select continent first round with the Weapon Menu or by ([switch/tab]=Increase,[precise/left shift]=Decrease) on Skip|Some weapons have a second option. Find them with [switch/tab]"] = "", -- Continental_supplies - --- ["Pfew! That was close!"] = "", -- A_Classic_Fairytale:shadow --- ["Piñata bullet: [Contains some sweet candy!]"] = "", -- Continental_supplies --- ["Pings left:"] = "", -- Space_Invasion - - ["Place more waypoints using the 'Air Attack' weapon."] = "Platziere mehr Wegpunkte durch Verwenden der 'Luftangriff'-Waffe", --- ["Planes Used:"] = "", -- User_Mission_-_RCPlane_Challenge --- ["Planes Used"] = "", -- User_Mission_-_RCPlane_Challenge --- ["Play with me!"] = "", -- A_Classic_Fairytale:shadow --- ["Please place the way-point further from the waterline."] = "", -- Racer --- ["Please place the way-point in the open, within the map boundaries."] = "", -- Racer --- ["Please, stop releasing your \"smoke signals\"!"] = "", -- A_Classic_Fairytale:shadow --- ["Point Blank Combo!"] = "", -- Space_Invasion - ["points"] = "Punkte", -- Control, CTF_Blizzard, Basic_Training_-_Bazooka, Basic_Training_-_Shotgun, Basic_Training_-_Sniper_Rifle - ["Poison"] = "Gift", --- ["Portal hint: one goes to the destination, and one is the entrance.|"] = "", -- A_Classic_Fairytale:dragon --- ["Portal mission"] = "", -- portal - ["Power Remaining"] = "Verbleibende Energie", - ["Prepare yourself"] = "Mach dich bereit", --- ["Press [Enter] to accept this configuration."] = "", -- WxW --- ["Press [Left] or [Right] to move around, [Enter] to jump"] = "", -- A_Classic_Fairytale:first_blood --- ["Press [Precise] to skip intro"] = "", --- ["Private Novak"] = "", -- Basic_Training_-_Cluster_Bomb --- ["Protect yourselves!|Grenade hint: set the timer with [1-5], aim with [Up]/[Down] and hold [Space] to set power"] = "", -- A_Classic_Fairytale:shadow - ["PUNKTESTAND"] = "", - ["Race complexity limit reached."] = "Rennkomplexitätslimit erreicht.", --- ["RACER"] = "", --- ["Rachel"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen --- ["Radar Ping"] = "", -- Space_Invasion --- ["Raging Buffalo"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united --- ["Ramon"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow --- ["RC PLANE TRAINING"] = "", -- User_Mission_-_RCPlane_Challenge --- ["Really?! You thought you could harm me with your little toys?"] = "", -- A_Classic_Fairytale:shadow --- ["Regurgitator"] = "", -- A_Classic_Fairytale:backstab --- ["Reinforcements"] = "", -- A_Classic_Fairytale:backstab --- ["Remember: The rope only bend around objects, |if it doesn't hit anything it's always stright!"] = "", -- Basic_Training_-_Rope --- ["Remember this, pathetic animal: when the day comes, you will regret your blind loyalty!"] = "", -- A_Classic_Fairytale:shadow - [" - Return the enemy flag to your base to score | - First team to 3 captures wins | - You may only score when your flag is in your base | - Hogs will drop the flag if killed, or drowned | - Dropped flags may be returned or recaptured | - Hogs respawn when killed"] = " - Bringe die gegnerische Flagge zu deiner Heimatbasis um zu punkten. | - Das Team das zuerst 3 Flaggen erobert gewinnt. | - Du kannst nur punkten wenn deine eigene Flagge in deiner Basis ist | - Igel lassen die Flagge fallen wenn sie sterben oder ertrinken | - Fallen gelassene Flaggen können zurückgebracht oder wieder gestohlen werden | - Igel tauchen nach ihrem Tod wieder auf", --- ["Return to Leaks A Lot! If you get stuck, press [Precise] to try again!"] = "", -- A_Classic_Fairytale:shadow --- ["Righteous Beard"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:first_blood, A_Classic_Fairytale:queen, A_Classic_Fairytale:united --- ["ROPE-KNOCKING"] = "", -- User_Mission_-_Rope_Knock_Challenge --- ["Rope Training"] = "", -- Basic_Training_-_Rope --- ["Rot Molester"] = "", -- A_Classic_Fairytale:shadow --- ["Round Limit:"] = "", - ["Round Limit"] = "Rundenbegrenzung", --- ["Rounds Complete: "] = "", - ["Rounds Complete"] = "Runden Gespielt", - ["RULES OF THE GAME [Press ESC to view]"] = "SPIEL REGELN (Drücke ESC zum Anzeigen)", --- ["Rusty Joe"] = "", -- A_Classic_Fairytale:queen --- ["s|"] = "", --- ["Sabotage: [Sabotage all hogs in the circle and deal ~10 dmg]"] = "", -- Continental_supplies --- ["Salivaslurper"] = "", -- A_Classic_Fairytale:united --- ["Salvation"] = "", -- A_Classic_Fairytale:family --- ["Salvation was one step closer now..."] = "", -- A_Classic_Fairytale:dragon - ["Save as many hapless hogs as possible!"] = "Rette so viele glücklose Igel als möglich!", --- ["Save Fell From Heaven!"] = "", -- A_Classic_Fairytale:journey --- ["Save Leaks A Lot!|Hint: The Switch utility might be of help to you."] = "", -- A_Classic_Fairytale:shadow --- ["Save the princess! All your hogs must survive!|Hint: Kill the cyborgs first! Use the ammo very carefully!|Hint: You might want to spare a girder for cover!"] = "", -- A_Classic_Fairytale:family --- ["Save the princess by collecting the crate in under 12 turns!"] = "", -- A_Classic_Fairytale:journey --- ["Scalp Muncher"] = "", -- A_Classic_Fairytale:backstab --- ["Score"] = "", -- Mutant --- ["SCORE"] = "", -- Space_Invasion --- ["Scream from a Walrus: [Deal 20 damage + 10% of your hogs health to all hogs around you and get half back]"] = "", -- Continental_supplies --- ["sec"] = "", -- CTF_Blizzard, TrophyRace, Basic_Training_-_Bazooka, Basic_Training_-_Shotgun, Basic_Training_-_Sniper_Rifle, User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork, Capture_the_Flag --- ["Seduction"] = "", -- Continental_supplies --- ["Seems like every time you take a \"walk\", the enemy find us!"] = "", -- A_Classic_Fairytale:backstab --- ["See that crate farther on the right?"] = "", -- A_Classic_Fairytale:first_blood - ["See ya!"] = "Mach's gut!", --- ["Segmentation Paul"] = "", -- A_Classic_Fairytale:dragon --- ["Select continent!"] = "", -- Continental_supplies --- ["Select difficulty: [Left] - easier or [Right] - harder"] = "", -- A_Classic_Fairytale:first_blood - ["selected!"] = "ausgewählt!", --- ["s"] = "", -- GaudyRacer, Space_Invasion --- ["... share your beauty with the world every morning, my princess!"] = "", -- A_Classic_Fairytale:journey --- ["She's behind that tall thingy."] = "", -- A_Classic_Fairytale:family - ["Shield boosted! +30 power"] = "Schild verstärkt! +30 Energie", - ["Shield Depleted"] = "Schild aufgebraucht!", - ["Shield is fully recharged!"] = "Schild vollständig aufgeladen!", - ["Shield Master!"] = "Schildmeister!", - ["Shield Miser!"] = "Schildgieriger", - ["Shield OFF:"] = "Schild AUS:", - ["Shield ON:"] = "Schild AN:", - ["Shield Seeker!"] = "Schildsucher!", --- ["Shotgun"] = "", -- Continental_supplies - ["Shotgun Team"] = "Schrotflinten-Team", - ["Shotgun Training"] = "Schrotflinten-Training", - ["shots remaining."] = "Schüsse übrig", - ["Silly"] = "Doofi", - ["Sinky"] = "Blubb", --- ["Sirius Lee"] = "", -- A_Classic_Fairytale:enemy - ["%s is out and Team %d|scored a penalty!| |Score:"] = "%s ist draußen und Team %d|erhält eine Strafe!| |Punktestand:", -- Basketball, Knockball - ["%s is out and Team %d|scored a point!| |Score:"] = "%s ist draußen und Team %d|erhält einen Punkt!| |Punktestand:", -- Basketball, Knockball --- ["Slippery"] = "", -- A_Classic_Fairytale:journey --- ["Smith 0.97"] = "", -- A_Classic_Fairytale:enemy --- ["Smith 0.98"] = "", -- A_Classic_Fairytale:enemy --- ["Smith 0.99a"] = "", -- A_Classic_Fairytale:enemy --- ["Smith 0.99b"] = "", -- A_Classic_Fairytale:enemy --- ["Smith 0.99f"] = "", -- A_Classic_Fairytale:enemy --- ["Smith 1.0"] = "", -- A_Classic_Fairytale:enemy --- ["Sniper Rifle"] = "", -- Continental_supplies --- ["Sniper!"] = "", -- Space_Invasion - ["Sniper Training"] = "Scharfschützen-Training", - ["Sniperz"] = "Heckenschützen", --- ["So humiliating..."] = "", -- A_Classic_Fairytale:first_blood --- ["South America"] = "", -- Continental_supplies --- ["So? What will it be?"] = "", -- A_Classic_Fairytale:shadow --- ["Spawn the crate, and attack!"] = "", -- WxW --- ["Special Weapons:"] = "", -- Continental_supplies - ["Spielmodifikatoren: "] = "", --- ["Spiky Cheese"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow --- ["Spleenlover"] = "", -- A_Classic_Fairytale:united - ["Sponge"] = "Schwamm", --- ["Spooky Tree"] = "", --- ["STATUS UPDATE"] = "", -- GaudyRacer, Space_Invasion --- ["Steel Eye"] = "", -- A_Classic_Fairytale:queen --- ["Step By Step"] = "", -- A_Classic_Fairytale:first_blood --- ["Steve"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen --- ["Sticky Mine"] = "", -- Continental_supplies --- ["Stronglings"] = "", -- A_Classic_Fairytale:shadow --- ["Structure"] = "", -- Continental_supplies --- ["Super Weapons"] = "", -- WxW --- ["Surf Before Crate"] = "", -- WxW --- ["Surfer! +15 points!"] = "", -- Space_Invasion --- ["Surfer!"] = "", -- WxW --- ["Survive!|Hint: Cinematics can be skipped with the [Precise] key."] = "", -- A_Classic_Fairytale:shadow --- ["Swing, Leaks A Lot, on the wings of the wind!"] = "", -- A_Classic_Fairytale:first_blood - ["Switched to "] = "Gewechselt zu ", --- ["Syntax Errol"] = "", -- A_Classic_Fairytale:dragon --- ["Talk about mixed signals..."] = "", -- A_Classic_Fairytale:dragon --- ["Team %d: "] = "", - ["Team Scores"] = "Teampunktestand", -- Control, Space_Invasion --- ["Teleport hint: just use the mouse to select the destination!"] = "", -- A_Classic_Fairytale:dragon --- ["Thanks!"] = "", -- A_Classic_Fairytale:family --- ["Thank you, my hero!"] = "", -- A_Classic_Fairytale:family --- ["Thank you, oh, thank you, Leaks A Lot!"] = "", -- A_Classic_Fairytale:journey --- ["Thank you, oh, thank you, my heroes!"] = "", -- A_Classic_Fairytale:journey --- ["That is, indeed, very weird..."] = "", -- A_Classic_Fairytale:united --- ["That makes it almost invaluable!"] = "", -- A_Classic_Fairytale:enemy --- ["That ought to show them!"] = "", -- A_Classic_Fairytale:backstab --- ["That's for my father!"] = "", -- A_Classic_Fairytale:backstab --- ["That shaman sure knows what he's doing!"] = "", -- A_Classic_Fairytale:shadow --- ["That Sinking Feeling"] = "", --- ["That's not our problem!"] = "", -- A_Classic_Fairytale:enemy --- ["That's typical of you!"] = "", -- A_Classic_Fairytale:family --- ["That was just mean!"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united - ["That was pointless."] = "Das war sinnlos.", --- ["The answer is...entertaintment. You'll see what I mean."] = "", -- A_Classic_Fairytale:backstab --- ["The anti-portal zone is all over the floor, and I have nothing to kill him...Droping something could hurt him enough to kill him..."] = "", -- portal --- ["The Bull's Eye"] = "", -- A_Classic_Fairytale:first_blood --- ["The caves are well hidden, they won't find us there!"] = "", -- A_Classic_Fairytale:united --- ["The Crate Frenzy"] = "", -- A_Classic_Fairytale:first_blood --- ["The Dilemma"] = "", -- A_Classic_Fairytale:shadow --- ["The enemy can't move but it might be a good idea to stay out of sight!|"] = "", -- A_Classic_Fairytale:dragon - ["The enemy is hiding out on yonder ducky!"] = "Der Feind versteckt sich auf dem Entlein dort drüben!", --- ["The Enemy Of My Enemy"] = "", -- A_Classic_Fairytale:enemy --- ["The First Blood"] = "", -- A_Classic_Fairytale:first_blood --- ["The First Encounter"] = "", -- A_Classic_Fairytale:shadow - ["The flag will respawn next round."] = "Die Fahne wird nächste Runde wieder auftauchen.", --- ["The food bites back"] = "", -- A_Classic_Fairytale:backstab --- ["The giant umbrella from the last crate should help break the fall."] = "", -- A_Classic_Fairytale:first_blood --- ["The Great Escape"] = "", -- User_Mission_-_The_Great_Escape --- ["The guardian"] = "", -- A_Classic_Fairytale:shadow --- ["The Individualist"] = "", -- A_Classic_Fairytale:shadow --- ["Their buildings were very primitive back then, even for an uncivilised island."] = "", -- A_Classic_Fairytale:united --- ["The Journey Back"] = "", -- A_Classic_Fairytale:journey --- ["The Leap of Faith"] = "", -- A_Classic_Fairytale:first_blood --- ["The Moonwalk"] = "", -- A_Classic_Fairytale:journey - ["The Nameless One"] = "Der Namenlose", --- ["The next one is pretty hard! |Tip: You have to do multiple swings!"] = "", -- Basic_Training_-_Rope --- ["Then how do they keep appearing?"] = "", -- A_Classic_Fairytale:shadow --- ["The other one were all cannibals, spending their time eating the organs of fellow hedgehogs..."] = "", -- A_Classic_Fairytale:first_blood --- ["There must be a spy among us!"] = "", -- A_Classic_Fairytale:backstab --- ["There's more of them? When did they become so hungry?"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united --- ["There's nothing more satisfying for me than seeing you share your beauty with the world every morning, my princess!"] = "", -- A_Classic_Fairytale:journey --- ["There's nothing more satisfying to us than seeing you share your beauty..."] = "", -- A_Classic_Fairytale:journey --- ["There's nothing more satisfying to us than seeing you share your beauty with the world every morning, my princess!"] = "", -- A_Classic_Fairytale:journey --- ["The Rising"] = "", -- A_Classic_Fairytale:first_blood --- ["The Savior"] = "", -- A_Classic_Fairytale:journey --- ["These primitive people are so funny!"] = "", -- A_Classic_Fairytale:backstab --- ["The Shadow Falls"] = "", -- A_Classic_Fairytale:shadow --- ["The Showdown"] = "", -- A_Classic_Fairytale:shadow --- ["The Slaughter"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:first_blood - ["THE SPECIALISTS"] = "DIE SPEZIALISTEN", --- ["The spirits of the ancerstors are surely pleased, Leaks A Lot."] = "", -- A_Classic_Fairytale:first_blood --- ["The Torment"] = "", -- A_Classic_Fairytale:first_blood --- ["The Tunnel Maker"] = "", -- A_Classic_Fairytale:journey --- ["The Ultimate Weapon"] = "", -- A_Classic_Fairytale:first_blood --- ["The Union"] = "", -- A_Classic_Fairytale:enemy --- ["The village, unprepared, was destroyed by the cyborgs..."] = "", -- A_Classic_Fairytale:journey --- ["The walk of Fame"] = "", -- A_Classic_Fairytale:shadow --- ["The wasted youth"] = "", -- A_Classic_Fairytale:first_blood --- ["The weapon in that last crate was bestowed upon us by the ancients!"] = "", -- A_Classic_Fairytale:first_blood --- ["The what?!"] = "", -- A_Classic_Fairytale:dragon --- ["The wind whispers that you are ready to become familiar with tools, now..."] = "", -- A_Classic_Fairytale:first_blood --- ["They are all waiting back in the village, haha."] = "", -- A_Classic_Fairytale:enemy --- ["They Call Me Bullseye!"] = "", -- Space_Invasion --- ["They have weapons we've never seen before!"] = "", -- A_Classic_Fairytale:united --- ["They keep appearing like this. It's weird!"] = "", -- A_Classic_Fairytale:united --- ["They killed "] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united --- ["They must be trying to weaken us!"] = "", -- A_Classic_Fairytale:enemy --- ["They never learn"] = "", -- A_Classic_Fairytale:journey --- ["They told us to wear these clothes. They said that this is the newest trend."] = "", -- A_Classic_Fairytale:enemy --- ["They've been manipulating us all this time!"] = "", -- A_Classic_Fairytale:enemy --- ["Thighlicker"] = "", -- A_Classic_Fairytale:united --- ["This is it! It's time to make Fell From Heaven fall for me..."] = "", -- A_Classic_Fairytale:first_blood --- ["This island is the only place left on Earth with grass on it!"] = "", -- A_Classic_Fairytale:enemy --- ["This is typical!"] = "", -- A_Classic_Fairytale:dragon --- ["This must be some kind of sorcery!"] = "", -- A_Classic_Fairytale:shadow --- ["This must be the caves!"] = "", -- A_Classic_Fairytale:backstab - ["This one's tricky."] = "Der hier ist knifflig.", - ["This rain is really something..."] = "Das nenne ich mal einen Regenschauer...", --- ["This will be fun!"] = "", -- A_Classic_Fairytale:enemy --- ["Those aliens are destroying the island!"] = "", -- A_Classic_Fairytale:family - ["Timed Kamikaze!"] = "Pünktliches Kamikaze!", - ["Time Extended!"] = "Zeit verlängert!", - ["Time Extension"] = "Zeitverlängerung", - ["Time Left: "] = "Verbleibende Zeit", - ["TIME: "] = "ZEIT: ", --- ["Tip: The rope physics are different than in the real world, |use it to your advantage!"] = "", -- Basic_Training_-_Rope - ["Toggle Shield"] = "Schild ein/aus", --- ["To help you, of course!"] = "", -- A_Classic_Fairytale:journey --- ["To place a girder, select it, use [Left] and [Right] to select angle and length, place with [Left Click]"] = "", -- A_Classic_Fairytale:shadow --- ["Torn Muscle"] = "", -- A_Classic_Fairytale:journey --- [" to save the village."] = "", -- A_Classic_Fairytale:dragon --- ["To the caves..."] = "", -- A_Classic_Fairytale:united - ["Toxic Team"] = "Giftige Gegner", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork - ["TRACK COMPLETED"] = "STRECKENLAUF BEENDET", - ["TRACK FAILED!"] = "STRECKENLAUF GESCHEITERT", --- ["training"] = "", -- portal --- ["Traitors"] = "", -- A_Classic_Fairytale:epil --- ["Tribe"] = "", -- A_Classic_Fairytale:backstab --- ["TrophyRace"] = "", --- ["Try to protect the chief! You won't lose if he dies, but it is advised that he survives."] = "", -- A_Classic_Fairytale:united --- ["T_T"] = "", - ["Tumbling Time Extended!"] = "Purzelzeit verlängert!", --- ["Turns until Sudden Death: "] = "", -- A_Classic_Fairytale:dragon --- [" turns until Sudden Death! Better hurry!"] = "", -- A_Classic_Fairytale:dragon - ["Turn Time"] = "Zeit pro Zug", --- ["Two little hogs cooperating, getting past obstacles..."] = "", -- A_Classic_Fairytale:journey --- ["Uhm...I met one of them and took his weapons."] = "", -- A_Classic_Fairytale:shadow --- ["Uhmm...ok no."] = "", -- A_Classic_Fairytale:enemy --- ["ULTRA KILL"] = "", -- Mutant --- ["Under Construction"] = "", -- A_Classic_Fairytale:shadow --- ["Unexpected Igor"] = "", -- A_Classic_Fairytale:dragon --- ["Unit 0x0007"] = "", -- A_Classic_Fairytale:family --- ["Unit 334a$7%;.*"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united - ["Unit 3378"] = "Einheit 3378", - ["Unit 835"] = "Einheit 3378", --- ["United We Stand"] = "", -- A_Classic_Fairytale:united - ["Unit"] = "Einheit", - ["Unlimited Attacks"] = "Unbegrenzte Angriffe", --- ["Unlucky Sods"] = "", -- User_Mission_-_Rope_Knock_Challenge - ["Unstoppable!"] = "Unaufhaltbar!", --- ["Unsuspecting Louts"] = "", -- User_Mission_-_Rope_Knock_Challenge --- ["[Up], [Down] to aim, [Space] to shoot!"] = "", -- A_Classic_Fairytale:first_blood --- ["Use it wisely!"] = "", -- A_Classic_Fairytale:dragon --- ["Use it with precaution!"] = "", -- A_Classic_Fairytale:first_blood --- ["User Challenge"] = "", - --- ["Use the portal gun to get to the next crate, then use the new gun to get to the final destination!|"] = "", -- A_Classic_Fairytale:dragon --- ["Use the rope to get on the head of the mole, young one!"] = "", -- A_Classic_Fairytale:first_blood --- ["Use the rope to knock your enemies to their doom."] = "", -- User_Mission_-_Rope_Knock_Challenge - ["Use your rope to get from start to finish as fast as you can!"] = "Nutze das Seil um von Start zu Ziel zu gelangen - so schnell du kannst!", --- ["Vedgies"] = "", -- A_Classic_Fairytale:journey --- ["Vegan Jack"] = "", -- A_Classic_Fairytale:enemy --- ["Victory!"] = "", -- Basic_Training_-_Rope - ["Victory for the "] = "Sieg für ", -- CTF_Blizzard, Capture_the_Flag --- ["Violence is not the answer to your problems!"] = "", -- A_Classic_Fairytale:first_blood --- ["Walls Left"] = "", -- WxW --- ["Walls Required"] = "", -- WxW --- ["WALL TO WALL"] = "", -- WxW --- ["Wannabe Flyboys"] = "", -- User_Mission_-_RCPlane_Challenge --- ["Wannabe Shoppsta"] = "", -- User_Mission_-_Rope_Knock_Challenge --- ["Watch your steps, young one!"] = "", -- A_Classic_Fairytale:first_blood - ["Waypoint placed."] = "Wegpunkt gesetzt", - ["Way-Points Remaining"] = "Wegpunkte verbleibend", --- ["Weaklings"] = "", -- A_Classic_Fairytale:shadow --- ["We all know what happens when you get frightened..."] = "", -- A_Classic_Fairytale:first_blood --- ["Weapons reset."] = "", -- Highlander - ["Weapons Reset"] = "Waffenzurücksetzung", --- ["We are indeed."] = "", -- A_Classic_Fairytale:backstab --- ["We can't defeat them!"] = "", -- A_Classic_Fairytale:shadow --- ["We can't hold them up much longer!"] = "", -- A_Classic_Fairytale:united --- ["We can't let them take over our little island!"] = "", -- A_Classic_Fairytale:enemy --- ["We have no time to waste..."] = "", -- A_Classic_Fairytale:journey --- ["We have nowhere else to live!"] = "", -- A_Classic_Fairytale:enemy --- ["We have to protect the village!"] = "", -- A_Classic_Fairytale:united --- ["We have to unite and defeat those cylergs!"] = "", -- A_Classic_Fairytale:enemy --- ["Welcome, Leaks A Lot!"] = "", -- A_Classic_Fairytale:journey - ["Well done."] = "Gut gemacht.", --- ["We'll give you a problem then!"] = "", -- A_Classic_Fairytale:enemy --- ["We'll spare your life for now!"] = "", -- A_Classic_Fairytale:backstab --- ["Well, that was a waste of time."] = "", -- A_Classic_Fairytale:dragon --- ["Well, well! Isn't that the cutest thing you've ever seen?"] = "", -- A_Classic_Fairytale:journey --- ["Well, yes. This was a cyborg television show."] = "", -- A_Classic_Fairytale:enemy --- ["We made sure noone followed us!"] = "", -- A_Classic_Fairytale:backstab --- ["We need to move!"] = "", -- A_Classic_Fairytale:united --- ["We need to prevent their arrival!"] = "", -- A_Classic_Fairytale:backstab --- ["We need to warn the village."] = "", -- A_Classic_Fairytale:shadow --- ["We should head back to the village now."] = "", -- A_Classic_Fairytale:shadow --- ["We were trying to save her and we got lost."] = "", -- A_Classic_Fairytale:family --- ["We won't let you hurt her!"] = "", -- A_Classic_Fairytale:journey --- ["What?! A cannibal? Here? There is no time to waste! Come, you are prepared."] = "", -- A_Classic_Fairytale:first_blood --- ["What a douche!"] = "", -- A_Classic_Fairytale:enemy --- ["What am I gonna...eat, yo?"] = "", -- A_Classic_Fairytale:family --- ["What are you doing at a distance so great, young one?"] = "", -- A_Classic_Fairytale:first_blood --- ["What are you doing? Let her go!"] = "", -- A_Classic_Fairytale:journey --- ["What a ride!"] = "", -- A_Classic_Fairytale:shadow --- ["What a strange cave!"] = "", -- A_Classic_Fairytale:dragon --- ["What a strange feeling!"] = "", -- A_Classic_Fairytale:backstab --- ["What do my faulty eyes observe? A spy!"] = "", -- A_Classic_Fairytale:first_blood --- ["Whatever floats your boat..."] = "", -- A_Classic_Fairytale:shadow --- [" What !! For all of this struggle i just win some ... TIME o0"] = "", -- portal --- ["What has "] = "", -- A_Classic_Fairytale:backstab --- ["What? Here? How did they find us?!"] = "", -- A_Classic_Fairytale:backstab --- ["What is this place?"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy --- ["What shall we do with the traitor?"] = "", -- A_Classic_Fairytale:backstab --- ["WHAT?! You're the ones attacking us!"] = "", -- A_Classic_Fairytale:enemy --- ["When?"] = "", -- A_Classic_Fairytale:enemy --- ["When I find it..."] = "", -- A_Classic_Fairytale:dragon --- ["Where are all these crates coming from?!"] = "", -- A_Classic_Fairytale:shadow --- ["Where are they?!"] = "", -- A_Classic_Fairytale:backstab --- ["Where did that alien run?"] = "", -- A_Classic_Fairytale:dragon --- ["Where did you get the exploding apples?"] = "", -- A_Classic_Fairytale:shadow --- ["Where did you get the exploding apples and the magic bow that shoots many arrows?"] = "", -- A_Classic_Fairytale:shadow --- ["Where did you get the magic bow that shoots many arrows?"] = "", -- A_Classic_Fairytale:shadow --- ["Where did you get the weapons in the forest, Dense Cloud?"] = "", -- A_Classic_Fairytale:backstab --- ["Where do you get that?!"] = "", -- A_Classic_Fairytale:enemy --- ["Where have you been?!"] = "", -- A_Classic_Fairytale:backstab --- ["Where have you been?"] = "", -- A_Classic_Fairytale:united --- ["? Why?"] = "", -- A_Classic_Fairytale:backstab --- ["Why "] = "", -- A_Classic_Fairytale:backstab --- ["! Why?!"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united --- ["Why are you doing this?"] = "", -- A_Classic_Fairytale:journey --- ["Why are you helping us, uhm...?"] = "", -- A_Classic_Fairytale:family --- ["Why can't he just let her go?!"] = "", -- A_Classic_Fairytale:family --- ["Why do men keep hurting me?"] = "", -- A_Classic_Fairytale:first_blood --- ["Why do you not like me?"] = "", -- A_Classic_Fairytale:shadow --- ["Why do you want to take over our island?"] = "", -- A_Classic_Fairytale:enemy --- ["Why me?!"] = "", -- A_Classic_Fairytale:backstab --- ["Why would they do this?"] = "", -- A_Classic_Fairytale:backstab --- ["- Will Get 1-3 random weapons"] = "", -- Continental_supplies --- ["- Will refresh Parachute each turn."] = "", -- Continental_supplies --- ["- Will refresh portalgun each turn."] = "", -- Continental_supplies - ["Will this ever end?"] = "Wird dies je enden?", --- ["WINNER IS "] = "", -- Mutant - ["WINNING TIME: "] = "BESTZEIT: ", --- ["Wise Oak"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen --- ["With Dense Cloud on the land of shadows, I'm the village's only hope..."] = "", -- A_Classic_Fairytale:journey --- ["With the rest of the tribe gone, it was up to "] = "", -- A_Classic_Fairytale:dragon --- ["Worry not, for it is a peaceful animal! There is no reason to be afraid..."] = "", -- A_Classic_Fairytale:first_blood --- ["Wow, what a dream!"] = "", -- A_Classic_Fairytale:backstab --- ["Y3K1337"] = "", -- A_Classic_Fairytale:journey, A_Classic_Fairytale:shadow --- ["Yay, we won!"] = "", -- A_Classic_Fairytale:enemy --- ["Y Chwiliad"] = "", -- A_Classic_Fairytale:dragon --- ["Yeah...I think it's a 'he', lol."] = "", -- A_Classic_Fairytale:shadow --- ["Yeah, sure! I died. Hillarious!"] = "", -- A_Classic_Fairytale:backstab --- ["Yeah, take that!"] = "", -- A_Classic_Fairytale:dragon --- ["Yeah? Watcha gonna do? Cry?"] = "", -- A_Classic_Fairytale:journey --- ["Yes!"] = "", -- A_Classic_Fairytale:enemy --- ["Yes, yeees! You are now ready to enter the real world!"] = "", -- A_Classic_Fairytale:first_blood --- ["Yo, dude, we're here, too!"] = "", -- A_Classic_Fairytale:family --- ["You are given the chance to turn your life around..."] = "", -- A_Classic_Fairytale:shadow --- ["You are playing with our lives here!"] = "", -- A_Classic_Fairytale:enemy --- ["! You bastards!"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united --- ["You bear impressive skills, "] = "", -- A_Classic_Fairytale:dragon --- ["You can't fire a portal on the blue surface"] = "", -- portal --- ["You couldn't possibly believe that after refusing my offer I'd just let you go!"] = "", -- A_Classic_Fairytale:journey - ["You'd almost swear the water was rising!"] = "Man könnte fast schwören das Wasser würde steigen!", --- ["You'd better watch your steps..."] = "", -- A_Classic_Fairytale:journey --- ["You did not make it in time, try again!"] = "", -- Basic_Training_-_Rope --- ["You have 7 turns until the next wave arrives.|Make sure the arriving cannibals are greeted appropriately!|If the hog dies, the cause is lost.|Hint: you might want to use some mines..."] = "", -- A_Classic_Fairytale:backstab --- ["You have "] = "", -- A_Classic_Fairytale:dragon --- ["You have been giving us out to the enemy, haven't you!"] = "", -- A_Classic_Fairytale:backstab --- ["You have been respawned, at your last checkpoint!"] = "", -- Basic_Training_-_Rope --- ["You have been respawned, be more carefull next time!"] = "", -- Basic_Training_-_Rope --- ["You have chosen the perfect moment to leave."] = "", -- A_Classic_Fairytale:united --- ["You have failed to complete your task, young one!"] = "", -- A_Classic_Fairytale:journey --- ["You have failed to save the tribe!"] = "", -- A_Classic_Fairytale:backstab --- ["You have finally figured it out!"] = "", -- A_Classic_Fairytale:enemy --- ["You have kidnapped our whole tribe!"] = "", -- A_Classic_Fairytale:enemy --- ["You have killed an innocent hedgehog!"] = "", -- A_Classic_Fairytale:backstab --- ["You have proven yourself worthy to see our most ancient secret!"] = "", -- A_Classic_Fairytale:first_blood --- ["You have proven yourselves worthy!"] = "", -- A_Classic_Fairytale:enemy - ["You have SCORED!!"] = "Du hast GEPUNKTET!", --- ["You have to destroy 12 targets in 180 seconds"] = "", -- Basic_Training_-_Cluster_Bomb --- ["You have won the game by proving true cooperative skills!"] = "", -- A_Classic_Fairytale:enemy --- ["You just appeared out of thin air!"] = "", -- A_Classic_Fairytale:backstab --- ["You just committed suicide..."] = "", -- A_Classic_Fairytale:shadow --- ["You killed my father, you monster!"] = "", -- A_Classic_Fairytale:backstab --- ["You know...taking a stroll."] = "", -- A_Classic_Fairytale:backstab --- ["You know what? I don't even regret anything!"] = "", -- A_Classic_Fairytale:backstab --- ["You'll see what I mean!"] = "", -- A_Classic_Fairytale:enemy --- ["You may only attack from a rope!"] = "", -- WxW --- ["You meatbags are pretty slow, you know!"] = "", -- A_Classic_Fairytale:enemy --- ["You might want to find a way to instantly kill arriving cannibals!"] = "", -- A_Classic_Fairytale:backstab --- ["Young one, you are telling us that they can instantly change location without a shaman?"] = "", -- A_Classic_Fairytale:united --- ["You probably know what to do next..."] = "", -- A_Classic_Fairytale:first_blood --- ["Your deaths will be avenged, cannibals!"] = "", -- A_Classic_Fairytale:enemy --- ["Your death will not be in vain, Dense Cloud!"] = "", -- A_Classic_Fairytale:shadow --- ["You're...alive!? But we saw you die!"] = "", -- A_Classic_Fairytale:backstab --- ["You're a pathetic liar!"] = "", -- A_Classic_Fairytale:backstab --- ["You're funny!"] = "", -- A_Classic_Fairytale:journey --- ["You're getting pretty good! |Tip: When you shorten you rope you move faster! |and when you lengthen it you move slower"] = "", -- Basic_Training_-_Rope --- ["You're pathetic! You are not worthy of my attention..."] = "", -- A_Classic_Fairytale:shadow --- ["You're probably wondering why I bought you back..."] = "", -- A_Classic_Fairytale:backstab --- ["You're terrorizing the forest...We won't catch anything like this!"] = "", -- A_Classic_Fairytale:shadow --- ["Your hogs must survive!"] = "", -- A_Classic_Fairytale:journey --- ["Your movement skills will be evaluated now."] = "", -- A_Classic_Fairytale:first_blood - ["You saved"] = "Gerettet: ", --- ["You've been assaulting us, we have been just defending ourselves!"] = "", -- A_Classic_Fairytale:enemy - ["You've failed. Try again."] = "Du bist gescheitert. Versuche es nochmal.", - ["You've reached the goal!| |Time: "] = "Ziel erreicht!| |Zeit: ", --- ["You will be avenged!"] = "", -- A_Classic_Fairytale:shadow --- ["You won't believe what happened to me!"] = "", -- A_Classic_Fairytale:backstab --- ["Yuck! I bet they'll keep worshipping her even after I save the village!"] = "", -- A_Classic_Fairytale:family --- ["Zealandia"] = "", -- Continental_supplies - ["'Zooka Team"] = "Die Knalltüten", --- ["Zork"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen - } +[""]="", +["Bat your opponents through the|baskets and out of the map!"]="Schlage deine Widersacher durch|die Körbe und aus der Karte hinaus!", +["Hedgewars-Basketball"]="Hedgewars-Basketball", +["Not So Friendly Match"]="Kein-so-Freundschaftsspiel", +["%s is out and Team %d|scored a point!| |Score:"]="%s ist draußen und Team %d|erhält einen Punkt!| |Punktestand:", +["%s is out and Team %d|scored a penalty!| |Score:"]="%s ist draußen und Team %d|erhält eine Strafe!| |Punktestand:", +["GAME OVER!"]="SPIEL ZU ENDE!", +["Hooray!"]="Hurra!", +["Victory for the "]="Sieg für ", +["Flag respawned!"]="Fahne wieder erschienen!", +["Opposing Team: "]="Gegnerisches Team: ", +["You have SCORED!!"]="Du hast GEPUNKTET!", +["Flag returned!"]="Fahne zurückgebracht!", +["That was pointless."]="Das war sinnlos.", +["The flag will respawn next round."]="Die Fahne wird nächste Runde wieder auftauchen.", +["Flag captured!"]="Flagge genommen!", +["Boom!"]="Bumm!", +[" - Return the enemy flag to your base to score | - First team to 3 captures wins | - You may only score when your flag is in your base | - Hogs will drop the flag if killed, or drowned | - Dropped flags may be returned or recaptured | - Hogs respawn when killed"]=" – Bringe die gegnerische Flagge zu deiner Heimatbasis, um zu punkten. | – Das Team, das zuerst 3 Flaggen erobert, gewinnt. | – Du kannst nur punkten, wenn deine eigene Flagge in deiner Basis ist | – Igel lassen die Flagge fallen, wenn sie sterben oder ertrinken | – Fallengelassene Flaggen können zurückgebracht oder wieder gestohlen werden | – Igel tauchen nach ihrem Tod wieder auf", +["Climb Home"]="Nach Hause klettern", +["Rope to safety"]="Schwing dich in Sicherheit", +["You are far from home, and the water is rising, climb up as high as you can!|Your score will be based on your height."]="Du bist weit weg von Zuhause, und das Wasser steigt, klettere so hoch, wie du kannst!|Deine Punktzahl wird von deiner Höhe abhängen.", +["Victory!"]="Sieg!", +["Made it!"]="Geschafft!", +["Ahhh, home, sweet home. Made it in %d seconds."]="Ah, trautes Heim, Glück allein! Geschafft in %d Sekunden.", +["You have beaten the challenge!"]="Du hast die Herausforderung gemeistert!", +["Your height over time"]="Deine Höhe über die Zeit", +["%s reached home in %.3f seconds. Congratulations!"]="%s has das Zuhause in %.3f Sekunden erreicht. Gratulation!", +["%s bravely climbed up to a dizzy height of %d to reach home."]="Mutig erklomm %s eine schwindelerregende Höhe von %d, um das Zuhause zu erreichen.", +["seconds"]="Sekunden", +["%s has passed the best height of %s!"]="%s hat die beste Höhe von %s überschritten!", +["%s never got the ninja diploma."]="%s ist bei der Ninjaprüfung durchgefallen.", +["You have to move upwards, not downwards, %s!"]="Du musst nach oben, nicht nach unten, %s!", +["%s never wanted to reach for the sky in the first place."]="%s wollte nie nach den Sternen greifen.", +["%s should try the rope training mission first."]="%s sollte wohl zuerst das Seiltraining absolvieren.", +["%s skipped ninja classes."]="%s hat den Ninjaunterricht geschwänzt.", +["%s doesn’t really know how to handle a rope properly."]="%s weiß nicht, wie man mit einem Seil umgeht.", +["Better luck next time!"]="Vielleicht klappt's beim nächsten Mal!", +["It was all just bad luck!"]="So ein Pech!", +["Well, that escalated quickly!"]="Das ging aber schnell in die Hose!", +["What? Is it over already?"]="Wie? Ist es schon vorbei?", +["You lose!"]="Du verlierst!", +["%s was damn close to home."]="%s war verdammt nah an Zuhause.", +["%s was close to home."]="%s war nah an Zuhause.", +["%s was good, but not good enough."]="%s war gut, aber nicht gut genug.", +["%s managed to pass half of the distance towards home."]="%s hat die Hälfte des Weges nach Hause absolviert.", +["%s went over a quarter of the way towards home."]="%s hat über die Hälfte des Weges nach Hause absolviert.", +["%s still had a long way to go."]="%s hatte noch einen langen Weg.", +["%s made it past the hogosphere."]="%s hat es über die Igelspähre geschafft.", +["%s barely made it past the hogosphere."]="%s hat es so gerade noch über die Igelsphäre geschafft.", +["points"]="Punkte", +["%s wins!"]="%s gewinnt!", +["Team’s best heights per round"]="Die Besthöhen der Teams pro Runde", +["This round’s award for ultimate disappointment goes to: Everyone!"]="Der ultimative Enttäuschungspreis geht in dieser Runde an: alle!", +["%s (%s) reached for the sky and beyond with a height of %d!"]="%s (%s) griff nach den Sternen mit einer Höhe von %d!", +["%s (%s) was certainly not afraid of heights: Peak height of %d!"]="%s (%s) hatte ganz bestimmt keine Höhenangst: Besthöhe von %d!", +["%s (%s) does not have to feel ashamed for their best height of %d."]="%s (%s) braucht sich für die Besthöhe von %d nicht zu schämen.", +["%s (%s) reached a decent peak height of %d."]="%s (%s) erreichte eine gute Besthöhe von %d.", +["%s (%s) reached a peak height of %d."]="%s (%s) erreichte eine Besthöhe von %d.", +["The Navy greets %s for managing to get in a distance of %d away from the mainland!"]="Die Marine grüßt %s für einen Abstand von %d vom Festland!", +["Greetings from the Navy, %s (%s), for being a distance of %d away from the mainland!"]="Grüße von der Marine, %s (%s), für einen Abstand von %d vom Festland!", +["Your hedgehog was panicly afraid of the water and decided to go in a safe distance of %d from it."]="Dein Igel hatte panische Angst vorm Wasser und hatte einen Sicherheitsabstand von %d erreicht.", +["%s (%s) was panicly afraid of the water and decided to get in a safe distance of %d from it."]="%s (%s) hatte panische Angst vorm Wasser und hatte einen Sicherheitsabstand von %d erreicht.", +["Ouch! That must have hurt. You mutilated your poor hedgehog hog with %d damage."]="Autsch! Das muss wehgetan haben. Du hast deinen armen Igel mit %d verstümmelt.", +["Ouch! That must have hurt. %s (%s) hit the ground with %d damage points."]="Autsch! Das muss wehgetan haben. %s (%s) ist mit %d auf den Boden aufgeschlagen.", +["Control pillars to score points."]="Behalte die Kontrolle über die Säulen, um Punkte zu erhalten.", +["Goal"]="Ziel", +["Team Scores"]="Teampunktestand", +["Bat balls at your enemies and|push them into the sea!"]="Schlage Bälle auf deine Widersacher|und lass sie ins Meer fallen!", +["Hedgewars-Knockball"]="Hedgewars-Schlagball", +["TrophyRace"]="TrophyRace", +["Use your rope to get from start to finish as fast as you can!"]="Nutze das Seil um von Start zu Ziel zu gelangen - so schnell du kannst!", +["NEW fastest lap: "]="NEUE schnellste Runde: ", +["Fastest lap: "]="Schnellste Runde: ", +["Best laps per team: "]="Beste Rundenzeiten pro Team: ", +["Team %d: "]="Team %d: ", +["You've reached the goal!| |Time: "]="Ziel erreicht!| |Zeit: ", +["Dense Cloud"]="Dichte Wolke", +["Fiery Water"]="Feuerwasser", +["Leaks A Lot"]="Undichte Stelle", +["Fell From Grace"]="Fiel in Ungnade", +["Raging Buffalo"]="Wütender Büffel", +["Righteous Beard"]="Redlicher Bart", +["Eagle Eye"]="Adlerauge", +["Flaming Worm"]="Flammenwurm", +["Wise Oak"]="Weise Eiche", +["Bone Jackson"]="Knochen-Ede", +["Brain Teaser"]="Hirnreiz", +["Gimme Bones"]="Gib Knochen", +["Bloodpie"]="Blutkuchen", +["Hedgibal Lecter"]="Iglibal Lector", +["Scalp Muncher"]="Skalpknabberer", +["Back Breaker"]="Rückenbrecher", +["Dahmer"]="Dahmer", +["Meiwes"]="Meiwes", +["Ear Sniffer"]="Ohrenschnüffler", +["Muriel"]="Muriel", +["Regurgitator"]="Hochwürger", +["Let them have a taste of my fury!"]="Lasst sie von meinem Zorn kosten!", +["There's more of them? When did they become so hungry?"]="Es gibt mehr von ihnen? Seit wann wurden sie so hungrig?", +["We are indeed."]="Das sind wir in der Tat.", +["I think we are safe here."]="Ich glaub, hier sind wir in Sicherheit.", +["I'm...alive? How? Why?"]="Ich lebe? Wie? Warum?", +["But why would they help us?"]="Aber warum würden sie uns helfen?", +["It must be the aliens!"]="Es müssen diese Außerirdischen sein!", +["You just appeared out of thin air!"]="Du tauchtest aus dem Nichts auf!", +["But...we died!"]="Aber … wir sind gestorben!", +["This must be the caves!"]="Dies müssen die Höhlen sein!", +["Dude, where are we?"]="He, wo sind wir?", +["Why would they do this?"]="Warum würden sie das tun?", +["It must be the aliens' deed."]="Das muss die Tat der Außerirdischen sein.", +["Do not laugh, inexperienced one, for he speaks the truth!"]="Lach nicht, Unerfahrener, da er die Wahrheit spricht!", +["Yeah, sure! I died. Hillarious!"]="Ja, sicher! Ich starb. Urkomisch!", +["You're...alive!? But we saw you die!"]="Du … lebst? Aber wir sahen dich sterben!", +["???"]="???", +["Wow, what a dream!"]="Wow, was für ein Traum!", +["Dude, that's so cool!"]="Junge, das ist so cool!", +["But that's impossible!"]="Aber das ist unmöglich!", +["It was not a dream, unwise one!"]="Es war kein Traum, du Tor!", +["Exactly, man! That was my dream."]="Genau! Das war mein Traum.", +["Dude, wow! I just had the weirdest high!"]="Junge, wow! Ich hatte gerade das seltsamste Erlebnis!", +["The answer is...entertaintment. You'll see what I mean."]="Die Antwort lautet: Unterhaltung. Du wirst verstehen, was ich meine.", +["You're probably wondering why I bought you back..."]="Ihr fragt euch bestimmt, warum ich euch zurückgebracht habe.", +["What shall we do with the traitor?"]="Was sollen wir mit dem Verräter tun?", +["Here, let me help you!"]="Hier, lass mich dir helfen!", +["I forgot that she's the daughter of the chief, too..."]="Ich vergaß, dass sie auch die Tochter des Häuptlings ist.", +["You killed my father, you monster!"]="Du hast meinen Vater umgebracht, du Monster!", +["Look, I had no choice!"]="Versteh doch, ich hatte keine Wahl!", +["You have been giving us out to the enemy, haven't you!"]="Du hast uns an den Feind verkauft, nicht wahr?", +["You're a pathetic liar!"]="Du bist ein dreckiger Lügner!", +["Interesting! Last time you said you killed a cannibal!"]="Interessant. Das letzte mal sagtest du, dass du einen Kannibalen getötet hast.", +["I told you, I just found them."]="Ich sag's dir, ich habe sie gerade erst gefunden.", +["Where did you get the weapons in the forest, Dense Cloud?"]="Woher hast du die Waffen im Wald gefunden, Dichte Wolke?", +["Not now, Fiery Water!"]="Nicht jetzt, Feuerwasser!", +["I can't believe what I'm hearing!"]="Ich kann nicht glauben, was ich höre!", +["You know what? I don't even regret anything!"]="Weißt du was? Ich bereue nichts!", +["In fact, you are the only one that's been acting strangely."]="Tatsächlich bist du der Einzige, der sich seltsam benahm.", +["Are you accusing me of something?"]="Beschuldigst du mich?", +["Seems like every time you take a \"walk\", the enemy find us!"]="Es scheint so, dass jedes Mal, wenn du »Spazieren gehst«, findet uns der Feind!", +["You know...taking a stroll."]="Du weißt schon … umherbummeln.", +["Where have you been?!"]="Wo warst du?!", +["You won't believe what happened to me!"]="Ihr glaubt nicht, was mir passiert ist!", +["Hey, guys!"]="Hey, Leute!", +["There must be a spy among us!"]="Es muss ein Spion unter uns sein!", +["We made sure noone followed us!"]="Wir hatten sichergestellt, dass uns niemand folgte!", +["What? Here? How did they find us?!"]="Was? Hier? Wie haben sie uns gefunden?", +["Look out! There's more of them!"]="Passt auf! Da sind noch mehr von ihnen!", +["What a strange feeling!"]="Was für ein seltsames Gefühl!", +["I need to warn the others."]="Ich muss die anderen warnen.", +["If only I had a way..."]="Wenn ich nur wüsste, wie.", +["Oh, silly me! I forgot that I'm the shaman."]="Ach, ich Dummkopf! Ich vergaß, dass ich der Schamane bin.", +["I sense another wave of cannibals heading our way!"]="Ich nehme eine Welle von Kannibalen, die auf uns zu gehen!", +["I feel something...a place! They will arrive near the circles!"]="Ich fühle etwas … einen Ort! Sie werden in der Nähe der Kreise auftauchen!", +["We need to prevent their arrival!"]="Wir müssen ihre Ankunft verhindern!", +["Go, quick!"]="Los, schnell!", +["I want to see how it handles this!"]="Ich will sehen, wie es damit klar kommt.", +["I sense another wave of cannibals heading my way!"]="Ich nehme eine weitere Welle in meine Richtung wahr!", +["I need to prevent their arrival!"]="Ich muss ihre Ankunft verhindern!", +["Oh, my! This is even more entertaining than I've expected!"]="Haha! Das ist sogar noch lustiger, als ich erwartet hatte!", +["You might want to find a way to instantly kill arriving cannibals!"]="Du könntest eine Möglichkeit finden, um die ankommenden Kannibalen sofort zu töten.", +["I believe there's more of them."]="Ich glaube, es gibt noch mehr von ihnen.", +["I marked the place of their arrival. You're welcome!"]="Ich habe ihren Ankunftsort markiert. Gern geschehen!", +["Why me?!"]="Warum ich?", +["He won't be selling us out anymore!"]="Er wird uns nicht mehr verraten!", +["That's for my father!"]="Das ist für meinen Vater!", +["Let's show those cannibals what we're made of!"]="Lass uns diesen Kannibalen zeigen, aus welchem Holz wir geschnitzt sind!", +["We'll spare your life for now!"]="Wir werden dein Leben verschonen. Noch.", +["May the spirits aid you in all your quests!"]="Mögen die Geiste dich in all deinen Aufgaben begleiten!", +["I just don't want to sink to your level."]="Ich will nicht auf dein Niveau herabsinken.", +["Let us help, too!"]="Lass uns auch helfen!", +["No. You and the rest of the tribe are safer there!"]="Nein. Du und der Rest deines Stammes sind hier sicherer!", +["! You bastards!"]="! Ihr Bastarde!", +["They killed "]="Sie töteten ", +["! Why?!"]="! Wieso?", +["That was just mean!"]="Das war einfach nur gemein!", +["Oh no, not "]="Oh nein, nicht ", +["? Why?"]="? Warum", +["Why "]="Warum, ", +[" ever done to you?!"]=" jemals angetan?!", +["What has "]="Was hat dir ", +["Backstab"]="Verrat", +["Defeat the cannibals"]="Besiege die Kannibalen", +["The food bites back"]="Das Essen beißt zurück", +["Drills"]="Bohrer", +["You have 7 turns until the next wave arrives.|Make sure the arriving cannibals are greeted appropriately!|If the hog dies, the cause is lost.|Hint: you might want to use some mines..."]="Du hast 7 Züge, bis die nächste Welle ankommt.|Stell sicher, dass die ankommenden Kannibalen auf die passende Weise begrüßt werden.|Wenn der Igel stirbst, die die Mission verloren.|Tipp: Vielleicht solltest du ein paar Minen benutzen.", +["Judas"]="Judas", +["Kill the traitor...or spare his life!|Kill him or press [Precise]!"]="Töte den Verräter … oder verschone ihn!|Töte ihn oder drücke [Genaues Zielen]!", +["Brutus"]="Brutus", +["You have failed to save the tribe!"]="Du hast es nicht geschafft, den Stamm zu retten!", +["Natives"]="Eingeborene", +["Tribe"]="Stamm", +["011101001"]="011101001", +["You have killed an innocent hedgehog!"]="Du hast einen unschuldigen Igel getötet!", +["That ought to show them!"]="Das wird ihnen eine Lehre sein!", +["Guys, do you think there's more of them?"]="Leute, glaubt ihr, dass es noch mehr von ihnen gibt?", +["Where are they?!"]="Wo sind sie?!", +["These primitive people are so funny!"]="Diese primitiven Leute sind so lustig!", +["I need to find the others!"]="Ich muss die anderen finden!", +["I have to follow that alien."]="Ich muss diesem Außerirdischen finden.", +["Assault Team"]="Sturmtruppe", +["Reinforcements"]="Verstärkung", +["Unit 334a$7%;.*"]="Einheit 334a$7%;,*", +["Jack"]="Jochen", +["Steve"]="Steffen", +["Zork"]="Zork", +["Elmo"]="Elmo", +["Lee"]="Leo", +["Rachel"]="Ramona", +["Jeremiah"]="Jeremias", +["Segmentation Paul"]="Se Gmentf Ehler", +["Syntax Errol"]="Syntaxfehlel", +["Unexpected Igor"]="Ausnahmefelix", +["Bullseye"]="Volltreffer!", +["Die, die, die!"]="Stirb, stirb, stirb!", +["Yeah, take that!"]="Jawohl, nimm das!", +[" to save the village."]=" ab, um das Dorf zu retten.", +["With the rest of the tribe gone, it was up to "]="Ohne den Rest des Stammes, hing es von ", +["But it proved to be no easy task!"]="Aber es war keine einfache Aufgabe!", +["What a strange cave!"]="Was für eine seltsame Höhle!", +["Now how do I get on the other side?!"]="Aber wie komme ich auf die andere Seite?!", +["Dude, what's this place?!"]="Junge, was ist das für ein Ort?!", +["And where's all the weed?"]="Und wo ist all das Gras?", +["Is this place in my head?"]="Ist dieser Ort in meinem Kopf?", +["I shouldn't have drunk that last pint."]="Ich sollte nicht die ganze Flasche ausgetrunken haben.", +["Where did that alien run?"]="Wohin ist dieser Außerirdische gelaufen?", +["When I find it..."]="Wenn ich ihn in die Finger kriege …", +["This is typical!"]="Typisch!", +["It's always up to women to clear up the mess men created!"]="Es bleibt immer an Frauen hängen, das Chaos, das Männer hinterlassen haben, aufzuräumen!", +["What is this place?"]="Was ist dieser Ort?", +["It doesn't matter. I won't let that alien hurt my daughter!"]="Es ist egal. Ich werde diesen Außerirdischen nicht meine Tochter weh tun lassen!", +["Every single time!"]="Jedes Mal!", +["How come in a village full of warriors, it's up to me to save it?"]="Wie kommt es, dass es immer an mir liegt, ein Dorf voller Krieger zu retten?", +["Greetings, "]="Grüße, ", +["As you can see, there is no way to get on the other side!"]="Wie du siehst, gibt es keinen Weg, um auf die andere Seite zu kommen.", +["I wish to help you, "]="Ich möchte dir helfen, ", +["Beware, though! If you are slow, you die!"]="Aber Vorsicht! Wenn du langsam bist, wirst du sterben!", +["Talk about mixed signals..."]="Zuckerbrot und Peitsche …", +["Well, that was a waste of time."]="Tja, das war wohl Zeitverschwendung.", +["You bear impressive skills, "]="Du hast großartige Fähigkeiten, ", +["However, my mates don't agree with me on letting you go..."]="Aber meine Freunde wollen dich nicht gehen lassen …", +["I guess you'll have to kill them."]="Ich fürchte, du musst sie töten.", +["Nice work, "]="Gute Arbeit, ", +["As a reward for your performance, here's some new technology!"]="Als Belohnung für deine Leistung gebe ich dir eine neue Technologie!", +["Use it wisely!"]="Benutze sie weise!", +["Dragon's Lair"]="Die Höhle des Löwen", +["In order to get to the other side, you need to collect the crates first.|"]="Um auf die andere Seite zu gelangen, musst du zuerst die Kisten einsammeln.|", +["Obstacle course"]="Hindernislauf", +["As the ammo is sparse, you might want to reuse ropes while mid-air.|"]="Da die Munition knapp ist, solltest du vielleicht Seile in der Luft wiederverwenden.|", +["If you wish to restart the course, hold [Precise] while your turn ends (e.g with Skip)!|"]="Wenn du den Hindernislauf neustarten willst, drücke [Genaues Zielen], während dein Zug endet (z.B. mit Überspringen)!|", +["The enemy can't move but it might be a good idea to stay out of sight!|"]="Der Feind kann sich nicht bewegen, aber es wäre besser, aus seiner Schusslinie zu bleiben!|", +[" turns until Sudden Death! Better hurry!"]=" Züge bis zum Sudden Death! Beeilung!", +["You have "]="Du hast ", +["Kill the aliens!"]="Töte die Außerirdischen!", +["The Slaughter"]="Die Schlachtung", +["The what?!"]="Die was?!", +["Use the portal gun to get to the next crate, then use the new gun to get to the final destination!|"]="Benutze das Portalgewehr, um zur nächsten Kiste zu kommen, dann benutze das nächste Gewehr, um zum letzten Ziel zu kommen.|", +["Portal hint: one goes to the destination, and one is the entrance.|"]="Portaltipp: Eins geht zum Ziel, und das andere ist der Eingang.|", +["Teleport hint: just use the mouse to select the destination!"]="Teleportertipp: Benutze einfach die Maus, um das Ziel auszuwählen.", +["I'm a ninja."]="Ich bin ein Ninja.", +["Salvation was one step closer now..."]="Die Erlösung war nun einen Schritt näher.", +["011101000"]="011101000", +["Find your tribe!|Cross the lake!"]="Finde deinen Stamm!|Überquere den Fluss!", +["Y Chwiliad"]="Y Chwiliad", +["Turns until Sudden Death: "]="Züge bis zum Sudden Death: ", +["Ramon"]="Ramon", +["Spiky Cheese"]="Stachliger Käse", +["Honest Lee"]="Leo Ehrlich", +["Sirius Lee"]="Leo Ernst", +["Vegan Jack"]="Veganer-Jochen", +["Brutal Lily"]="Brutalo-Lilie", +["Smith 0.97"]="Smith 0.97", +["Smith 0.98"]="Smith 0.98", +["Smith 0.99a"]="Smith 0.99a", +["Smith 0.99b"]="Smith 0.99b", +["Smith 0.99f"]="Smith 0.99f", +["Smith 1.0"]="Smith 1.0", +["Everything looks OK..."]="Alles sieht gut aus.", +["This will be fun!"]="Das wird Spaß machen!", +["HAHA!"]="HAHA!", +["And how am I alive?!"]="Und wie kann es sein, dass ich am Leben bin?", +["It must be the cyborgs again!"]="Das müssen wohl wieder diese Cyborgs sein!", +["Looks like the whole world is falling apart!"]="Es scheint, als würde die ganze Welt auseinanderfallen!", +["Look out! We're surrounded by cannibals!"]="Passt auf! Wir sind von Kannibalen umzingelt!", +["Cannibals?! You're the cannibals!"]="Kannibalen?! Ihr seid die Kannibalen!", +["WHAT?! You're the ones attacking us!"]="WAS?! Ihr seid diejenigen, die uns angreifen!", +["You have kidnapped our whole tribe!"]="Ihr habt unseren ganzen Stamm entführt!", +["You've been assaulting us, we have been just defending ourselves!"]="Ihr habt uns überfallen, wir haben uns nur verteidigt!", +["I can't believe this!"]="Ich kann es nicht glauben!", +["Have we ever attacked you first?"]="Haben wir euch jemals zuerst angegriffen?", +["Yes!"]="Ja!", +["When?"]="Wann?", +["Uhmm...ok no."]="Ähm, okay, nein.", +["But you're cannibals. It's what you do."]="Aber ihr seid Kannibalen. Das ist, was ihr tut.", +["Again with the 'cannibals' thing!"]="Nicht schon wieder dieser »Kannibalen«-Unfug!", +["Where do you get that?!"]="Wo habt ihr das her?", +["Everyone knows this."]="Das weiß jeder.", +["I didn't until about a month ago."]="Ich wusste es nicht vor einem Monat.", +["Hmmm...actually...I didn't either."]="Hmmm, ich … eigentlich auch nicht.", +["About a month ago, a cyborg came and told us that you're the cannibals!"]="Vor etwa einem Monat kam ein Cyborg und erzählte uns, dass ihr die Kannibalen seid.", +["A cy-what?"]="Ein Cy-was?", +["Cyborg. It's what the aliens call themselves."]="Cyborg. So nennen sich die Außerirdischen selbst.", +["They told us to wear these clothes. They said that this is the newest trend."]="Sie sagten uns, dass wir diese Kleidung tragen sollten. Sie sagten, dass es der neueste Trend sei.", +["They've been manipulating us all this time!"]="Sie haben uns die ganze Zeit manipuliert!", +["They must be trying to weaken us!"]="Sie müssen versuchen, uns zu schwächen!", +["We have to unite and defeat those cylergs!"]="Wir müssen uns zusammentun, und diese Cylergs besiegen!", +["We can't let them take over our little island!"]="Wir können sie nicht unsere kleine Insel erobern lassen!", +["You have finally figured it out!"]="Ihr habt es endlich gemerkt!", +["You meatbags are pretty slow, you know!"]="Ihr Fleischklumpen seid ziemlich langsam, wisst ihr?", +["Why do you want to take over our island?"]="Warum wollt ihr unsere Insel erobern?", +["Do you have any idea how valuable grass is?"]="Habt ihr überhaupt eine Ahnung darüber, wie wertvoll Gras ist?", +["This island is the only place left on Earth with grass on it!"]="Diese Insel ist der einzige Ort auf der Welt, der noch Gras hat.", +["It's worth more than wood!"]="Es ist wertvoller als Holz!", +["That makes it almost invaluable!"]="Das macht es fast unbezahlbar!", +["We have nowhere else to live!"]="Wir haben sonst keinen Ort zu leben!", +["That's not our problem!"]="Das ist nicht unser Problem!", +["We'll give you a problem then!"]="Dann geben wir euch ein Problem!", +["Nicely done, meatbags!"]="Gut gemacht, Fleischkugeln!", +["You have won the game by proving true cooperative skills!"]="Ihr hab das Spiel gewonnen, indem ihr wahre kooperative Fähigkeiten gezeigt habt!", +["You have proven yourselves worthy!"]="Du hast dich bewährt.", +["Game? Was this a game to you?!"]="Spiel? War das ein Spiel für dich?!", +["Well, yes. This was a cyborg television show."]="Ähm, ja. Es war eine Cyborg-Fernsehsendung.", +["It is called 'Hogs of Steel'."]="Sie heißt »Igel aus Stahl«.", +["Are you saying that many of us have died for your entertainment?"]="Willst du damit sagen, dass viele von uns nur für eure Unterhaltung gestorben sind?", +["Our tribe, our beautiful island!"]="Unser Stamm, unsere schöne Insel!", +["All gone...everything!"]="Alles fort, alles!", +["But the ones alive are stronger in their heart!"]="Aber die Lebendigen sind in ihrem Herzen stärker.", +["Just kidding, none of you have died!"]="Nur ein Witz! Niemand von euch ist gestorben!", +["I mean, none of you ceased to live."]="Ich meine, niemand von euch hat aufgehört, zu leben.", +["You'll see what I mean!"]="Du wirst verstehen, was ich meine.", +["They are all waiting back in the village, haha."]="Sie warten alle im Dorf, haha.", +["You are playing with our lives here!"]="Du spielst mit unseren Leben!", +["Do you think you're some kind of god?"]="Hältst du dich für eine Art Gott?", +["Interesting idea, haha!"]="Interessanter Gedanke, haha!", +["What a douche!"]="Was für ein Blödian!", +["Defeat the cyborgs!"]="Besiege die Cyborgs!", +["The Enemy Of My Enemy"]="Der Feind meines Feindes", +["The Union"]="Die Einheit", +["Hmmm...it's a draw. How unfortunate!"]="Hmmm … Es ist unentschieden. Wie blöd!", +["Yay, we won!"]="Hurra, wir haben gewonnen!", +["Nice work!"]="Gute Arbeit!", +["Cannibals"]="Kannibalen", +["Fell From Heaven"]="Fiel Vom Himmel", +["Hedge-cogs"]="Stachelräder", +["Leader"]="Führer", +["Nancy Screw"]="Lockere Schraube", +["Your deaths will be avenged, cannibals!"]="Eure Tode werden gerächt sein, Kannibalen!", +["Brainiac"]="Hirni", +["Corpse Thrower"]="Leichenschmeißer", +["Hannibal"]="Hannibal", +["More Natives"]="Mehr Ureinwohner", +["Traitors"]="Verräter", +["Carol"]="Karol", +["Hogminator"]="Iglinator", +["Unit 0x0007"]="Einheit 0x0007", +["Blender"]="Blender", +["Elderbot"]="Altbot", +["Those aliens are destroying the island!"]="Diese Außerirdischen zerstören die Insel!", +["Dude, all the plants are gone!"]="Mann, all die Pflanzen sind fort!", +["What am I gonna...eat, yo?"]="Was werde ich … essen?", +["Fell From Heaven is the best! Fell From Heaven is the greatest!"]="Fiel Vom Himmel ist die Beste! Fiel Vom Himmel ist die Größte!", +["Yuck! I bet they'll keep worshipping her even after I save the village!"]="Pfui! Ich wette, sie werden sie verehren, selbst, wenn ich das Dorf rette.", +["I'm getting old for this!"]="Ich werd zu alt dafür!", +["I'm getting thirsty..."]="Ich hab Durst.", +["I wonder why I'm so angry all the time..."]="Ich frag mich, warum ich die ganze Zeit so wütend bin.", +["It must be a childhood trauma..."]="Es muss ein Kindheitstrauma sein.", +["Just wait till I get my hands on that trauma! ARGH!"]="Warte nur, bis ich mein Trauma in die Finger kriege! ARGH!", +["I could just teleport myself there..."]="Ich könnte mich einfach dorthin teleportieren.", +["It's a shame, I forgot how to do that!"]="Zu dumm, ich habe vergessen, wie man das macht.", +["Hello again, "]="Hallo, ", +["I just found out that they have captured your princess!"]="Ich habe gerade herausgefunden, dass sie deine Prinzessin gefangen haben!", +["Of course I have to save her. What did I expect?!"]="Natürlich muss ich sie retten. Was habe ich erwartet?", +["She's behind that tall thingy."]="Sie ist hinter diesem großen Dingsda.", +["I'm here to help you rescue her."]="Ich bin hier, um dir bei ihrer Rettung zu helfen.", +["Yo, dude, we're here, too!"]="Heda, wir sind auch da!", +["We were trying to save her and we got lost."]="Wir versuchten, sie zu retten, aber haben uns verlaufen.", +["That's typical of you!"]="Das ist so typisch für dich!", +["Why are you helping us, uhm...?"]="Warum hilfst du uns, äh, …?", +["Call me Beep! Well, 'cause I'm such a nice...person!"]="Nenn mich »Pieps«! Weil ich so eine nette … Person bin!", +["Here, let me help you save her!"]="Hier, lass mich dir helfen, sie zu retten!", +["Thanks!"]="Danke!", +["Why can't he just let her go?!"]="Warum kann er sie nicht einfach freilassen?", +["Family Reunion"]="Familientreffen", +["Get your teammates out of their natural prison and save the princess!|Hint: Drilling holes should solve everything.|Hint: It might be a good idea to place a girder before starting to drill. Just saying.|Hint: All your hedgehogs need to be above the marked height!|Hint: Leaks A Lot needs to get really close to the princess!"]="Befrei deine Teamkollegen aus ihrem natürlichen Gefängnis und rette die Prinzessin!|Tipp: Löcher bohren sollte alle Probleme lösen.|Tipp: Es könnte eine gute Idee sein, vor dem Bohren einen Träger zu platzieren. Ich mein ja nur.|Tipp: All deine Igel müssen sich über der markierten Höhe befinden.|Tipp: Undichte Stelle muss sich sehr nahe an der Prinzessin befinden.", +["Salvation"]="Erlösung", +["Hostage Situation"]="Geiselrettung", +["Save the princess! All your hogs must survive!|Hint: Kill the cyborgs first! Use the ammo very carefully!|Hint: You might want to spare a girder for cover!"]="Rette die Prinzessin! All deine Igel müssen überleben!|Tipp: Töte die Cyborgs zuerst! Benutze die Munition sehr vorsichtig!|Tipp: Du solltest vielleicht einen Träger als Deckung behalten!", +["Thank you, my hero!"]="Danke dir, mein Held!", +["Biomechanic Team"]="Biomechanisches Team", +["First Blood"]="Der erste Zusammenstoß", +["First Steps"]="Erste Schritte", +["Press [Left] or [Right] to move around, [Enter] to jump"]="Drücke [Links] oder [Rechts] zum Bewegen, [Eingabe] zum Springen.", +["A leap in a leap"]="Ein Sprung in einem Sprung", +["Go on top of the flower"]="Geh auf die Spitze der Blume", +["Collect the crate on the right.|Hint: Select the rope, [Up] or [Down] to aim, [Space] to fire, directional keys to move.|Ropes can be fired again in the air!"]="Sammle die Kiste auf der rechten Seite ein.|Tipp: Wähle das Seil, [Hoch] oder [Runter] zum Zielen, [Leer] zum feuern, Richtungstasten zum bewegen.|Seile können in der Luft erneut geschossen werden.", +["Hightime"]="Hoch hinaus", +["Get on the head of the mole"]="Geh auf den Kopf des Maulwurfs", +["Omnivore"]="Allesfresser", +["The Leap of Faith"]="Der Mutsprung", +["Use the parachute ([Space] while in air) to get the next crate"]="Benutze den Fallschirm ([Leer] drücken, wenn in der Luft), um die nächste Kiste zu erhalten.", +["Do the deed"]="Tu deine Pflicht", +["The Rising"]="Der Aufstieg", +["Destroy the targets!|Hint: Select the Shoryuken and hit [Space]|P.S. You can use it mid-air."]="Zerstör die Ziele!|Tipp: Wähle das Shoryuken und drücke [Leertaste]|PS: Du kannst es in der Luft benutzen.", +["Collect the crates within the time limit!|If you fail, you'll have to try again."]="Sammle die Kisten innerhalb der Zeitbegrenzung ein!|Wenn du versagst, musst es erneut versuchen.", +["The Crate Frenzy"]="Der Kistenrausch", +["Destroy the targets!|Hint: [Up], [Down] to aim, [Space] to shoot"]="Zerstöre die Ziele!|Tipp: [Hoch], [Runter] zum Zielen, [Leer] zum Schießen", +["The Ultimate Weapon"]="Die Ultimative Waffe", +["Kill the cannibal!"]="Töte den Kannibalen!", +["The First Blood"]="Der erste Zusammenstoß", +["KILL IT!"]="TÖTE ES!", +["Watch your steps, young one!"]="Pass auf deine Schritte auf, Jüngling!", +["Why do men keep hurting me?"]="Warum tun mir Männer ständig weh?", +["Violence is not the answer to your problems!"]="Gewalt ist nicht die Antwort auf deine Probleme!", +["Once upon a time, on an island with great natural resources, lived two tribes in heated conflict..."]="Es waren einmal zwei Stämme, die lebten auf einer Insel mit vielen natürlichen Rohstoffen und waren in einem bitteren Konflikt …", +["One tribe was peaceful, spending their time hunting and training, enjoying the small pleasures of life..."]="Unser Stamm war friedlich und verbrachte die Zeit mit der Jagd, Übungen und den kleinen Freuden des Lebens.", +["The other one were all cannibals, spending their time eating the organs of fellow hedgehogs..."]="Der andere Stamm bestand nur aus Kannibalen, sie verbrachten ihre Zeit damit, die Organe anderer Igel aufzufressen.", +["And so it began..."]="Und so fing es an …", +["What are you doing at a distance so great, young one?"]="Was tut du hier in so großer Entfernung, Jüngling?", +["Come closer, so that your training may continue!"]="Komm näher, damit deine Übungen fortfahren können!", +["This is it! It's time to make Fell From Heaven fall for me..."]="Das ist es! Es ist Zeit, um Fiel Vom Himmel in mich verfallen zu lassen …", +["I can see you have been training diligently."]="Ich sehe, dass du fleißig geübt hast.", +["The wind whispers that you are ready to become familiar with tools, now..."]="Der Wind flüstert, dass du jetzt bereit bist, mit den Werkzeugen vertraut zu werden.", +["Open that crate and we will continue!"]="Öffne diese Kiste und wir werden fortfahren!", +["He moves like an eagle in the sky."]="Er bewegt sich wie ein Adler in der Luft.", +["See that crate farther on the right?"]="Siehst du die Kiste weiter rechts?", +["Swing, Leaks A Lot, on the wings of the wind!"]="Schwing, Undichte Stelle, auf den Flügeln des Windes!", +["His arms are so strong!"]="Seine Arme sind so stark!", +["Use the rope to get on the head of the mole, young one!"]="Benutze das Seil, um auf den Kopf des Maulwurfst zu gelangen, Jüngling!", +["Worry not, for it is a peaceful animal! There is no reason to be afraid..."]="Hab keine Angst, da es ein friedliebendes Tier ist. Es gibt keinen Grund, Angst zu haben.", +["We all know what happens when you get frightened..."]="Wir wissen alle, was passiert, wenn du Angst kriegst.", +["So humiliating..."]="Welch Demütigung!", +["Perfect! Now try to get the next crate without hurting yourself!"]="Perfekt! Jetzt versuch, zur nächsten Kiste zu gelangen, ohne dich zu verletzen!", +["The giant umbrella from the last crate should help break the fall."]="Der Riesenschirm von der letzten Kiste sollte helfen, den Sturz abzubremsen.", +["He's so brave..."]="Er ist so mutig.", +["I see you have already taken the leap of faith."]="Ich sehe, du hast bereits den Mutsprung absolviert.", +["Get that crate!"]="Hol dir die Kiste!", +["Impressive...you are still dry as the corpse of a hawk after a week in the desert..."]="Großartig! Du bist immer noch so trocken wie der Kadaver eines Adlers nach einer Woche in der Wüste.", +["You probably know what to do next..."]="Du weißt vermutlich, was als nächstes zu tun ist.", +["It is time to practice your fighting skills."]="Es ist Zeit, dein Kämpfen zu üben.", +["Imagine those targets are the wolves that killed your parents! Take your anger out on them!"]="Stell dir vor, diese Zielscheiben sind die Wölfe, die eine Eltern getötet haben! Lass deine Wut an ihnen aus!", +["I hope you are prepared for a small challenge, young one."]="Ich hoffe, du bist für eine kleine Herausforderung gewappnet, Jüngling.", +["Your movement skills will be evaluated now."]="Deine Fortbewegungsfähigkeiten werden nun getestet.", +["Collect all the crates, but remember, our time in this life is limited!"]="Sammle all die Kisten ein, aber denk dran, unsere Zeit in diesem Leben ist begrenzt!", +["How difficult would you like it to be?"]="Wie schwer möchtest du es haben?", +["Hmmm...perhaps a little more time will help."]="Hmmm. Vielleicht wird etwas mehr Zeit helfen.", +["The spirits of the ancerstors are surely pleased, Leaks A Lot."]="Die Geister der Ahnen sind sicherlich erfreut, Undichte Stelle.", +["You have proven yourself worthy to see our most ancient secret!"]="Du hast dich bewährt, um unser ältestes Geheimnis zu sehen.", +["The weapon in that last crate was bestowed upon us by the ancients!"]="Die Waffe in der letzten Kiste wurde uns von den Urahnen übergeben!", +["Use it with precaution!"]="Benutze sie weise.", +["What do my faulty eyes observe? A spy!"]="Was sehen meine alten Augen? Einen Spion!", +["Destroy him, Leaks A Lot! He is responsible for the deaths of many of us!"]="Zerstöre ihn, Undichte Stelle! Er ist verantwortlich für viele Tote auf unserer Seite!", +["Oh, my!"]="Ohje!", +["I see you would like his punishment to be more...personal..."]="Ich sehe, du möchtest, dass seine Bestrafung etwas … persönlicher ausfällt.", +["I'm certain that this is a misunderstanding, fellow hedgehogs!"]="Ich bin mir sicher, dass das ein Missverständnis ist, liebe Igel.", +["If only I were given a chance to explain my being here..."]="Wenn ich nur eine Gelegenheit hätte, um meine Anwesenheit zu erklären …", +["Do not let his words fool you, young one! He will stab you in the back as soon as you turn away!"]="Lass dich nicht von seinen Worten einlullen, Jüngling! Er wird dich hinterrücks ermorden, sobald du ihm den Rücken zuwendest!", +["Here...pick your weapon!"]="Hier … wähl deine Waffe!", +["Yes, yeees! You are now ready to enter the real world!"]="Ja, Jaaa! Jetzt bist du bereit, die wirkliche Welt zu betreten!", +["What?! A cannibal? Here? There is no time to waste! Come, you are prepared."]="Was?! Ein Kannibale? Hier? Es gibt keine Zeit zu verlieren! Komm, du bist vorbereitet.", +["Leaks A Lot gave his life for his tribe! He should have survived!"]="Undichte Stelle gab sein Leben für seinen Stamm! Er hätte überleben sollen!", +["The wasted youth"]="Die vergeudete Jugend", +["After Leaks A Lot betrayed his tribe, he joined the cannibals..."]="Nachdem Undichte Stelle seinen Stamm betrogen hatte, trat er den Kannibalen bei.", +["Hint: Double Jump - Press [Backspace] twice"]="Tipp: Doppelsprung – Drück [Rücktaste] 2 Mal", +["Step By Step"]="Schritt für Schritt", +["As the challenge was completed, Leaks A Lot set foot on the ground..."]="Nachdem die Herausforderung abgeschlossen war, setzte Undichte Stelle einen Fuß auf den Boden.", +["And so happenned that Leaks A Lot failed to complete the challenge! He landed, pressured by shame..."]="Und somit versagte Undichte Stelle dabei, die Herausforderung abzuschließen. Unter Schande landete er.", +["The Bull's Eye"]="Ins Schwarze", +["[Up], [Down] to aim, [Space] to shoot!"]="[Hoch], [Runter] zum Zielen, [Leer] zum Schießen.", +["Select difficulty: [Left] - easier or [Right] - harder"]="Wähl einen Schwierigkeitsgrad: [Links] – leichter oder [Rechts] – schwerer", +["The Torment"]="Die Pein", +["A Classic Fairytale"]="Ein typisches Märchen", +["Finish your training|Hint: Animations can be skipped with the [Precise] key."]="Schließe deine Übungen ab.|Tipp: Animationen können mit der [Genaues Zielen]-Taste übersprungen werden.", +["Eye Chewer"]="Augenkauer", +["Flesh for Brainz"]="Fleisch gegen Hirn", +["John"]="Jonas", +["Torn Muscle"]="Loser Muskel", +["Brain Blower"]="Hirnpuster", +["Gorkij"]="Gorkidsch", +["Nom-Nom"]="Mjam-Mjam", +["Vedgies"]="Früchties", +["Collateral Damage"]="Kollateralschaden", +["Save the princess by collecting the crate in under 12 turns!"]="Rette die Prinzessin, indem du die Kiste vor Ablauf von 12 Zügen einsammelst!", +["The Journey Back"]="Die Rückreise", +["Collateral Damage II"]="Kollateralschaden II", +["Save Fell From Heaven!"]="Rette Fiel Vom Himmel!", +["Get the crate on the other side of the island!|"]="Hol dir die Kiste auf der anderen Seite der Insel!|", +["Hint: you might want to stay out of sight and take all the crates...|"]="Tipp: Du solltest vielleicht aus der Schusslinie bleiben und alle Kisten nehmen.|", +["If you get stuck, use your Desert Eagle or restart the mission!|"]="Wenn du stecken bleibst, benutze deine Desert Eagle oder starte die Mission neu.|", +["Leaks A Lot must survive!"]="Undichte Stelle muss überleben!", +["Your hogs must survive!"]="Deine Igel müssen überleben.", +["Adventurous"]="Abenteuerlich", +["Get Dense Cloud out of the pit!"]="Hol Dichte Wolke aus der Grube!", +["The Savior"]="Der Erlöser", +["Free Dense Cloud and continue the mission!"]="Befrei Dichte Wolke und setze die Mission fort!", +["They never learn"]="Sie lernen es nie.", +["I just wonder where Ramon and Spiky disappeared..."]="Ich frage mich lediglich, wohin Ramon und Stachli verschwunden sind.", +["I wonder where Dense Cloud is..."]="Ich frag mich, wo Dichte Wolke ist.", +["He must be in the village already."]="Er muss schon im Dorf sein.", +["I'd better get going myself."]="Ich geh jetzt besser weiter.", +["Welcome, Leaks A Lot!"]="Willkommen, Undichte Stelle!", +["I want to play a game..."]="Ich möchte ein Spiel spielen.", +["Help me, please!!!"]="Hilfe! Zu Hilfe! Bitte!", +["If you can get that crate fast enough, your beloved \"princess\" may go free."]="Wenn du diese Kiste schnell genug einsammelst, darfst du deine geliebte »Prinzessin« befreien.", +["However, if you fail to do so, she dies a most violent death! Muahahaha!"]="Wenn du aber versagst, wird sie den grausamsten Tod sterben! Muhahahaha!", +["Good luck...or else!"]="Viel Glück! Sonst …!", +["Hey! This is cheating!"]="Hey, das ist geschummelt!", +["I need to get to the other side of this island, fast!"]="Ich muss auf die andere Seite der Insel gelangen, und zwar schnell!", +["With Dense Cloud on the land of shadows, I'm the village's only hope..."]="Jetzt, wo Dichte Wolke im Land der Schatten ist, bin ich des Dorfs einzige Hoffnung.", +["However, if you fail to do so, she dies a most violent death, just like your friend! Muahahaha!"]="Aber wenn du versagst, wird sie den grausamsten Tod sterben, genau, wie dein Freund! Muhahahaha!", +["You have failed to complete your task, young one!"]="Du hast versagt, Jüngling!", +["It's time you learned that your actions have consequences!"]="Es ist Zeit, dass du lernst, dass dein Handeln Konsequenzen haben wird!", +["No! Please, help me!"]="Nein! Bitte hilf mir!", +["No! What have I done?! What have YOU done?!"]="Nein! Was habe ich getan?! Was hast DU getan?!", +["Help me, Leaks!"]="Hilf mir, Undichte!", +["But you said you'd let her go!"]="Aber du sagtest, dass du sie freilässt!", +["And you believed me? Oh, god, that's cute!"]="Und du hast mir geglaubt? Ach Gottchen, das ist so süß!", +["I won't let you kill her!"]="Ich werde nicht zulassen, dass du sie umbringst!", +["Leaks A Lot, depressed for killing his loved one, failed to save the village..."]="Traurig darüber, sein Liebling getötet zu haben, versagte Undichte Stelle dabei, das Dorf zu retten.", +["Thank you, oh, thank you, Leaks A Lot!"]="Danke, oh, danke, Undichte Stelle!", +["How can I ever repay you for saving my life?"]="Wie kann ich es jemals wieder gutmachen, dass du mein Leben gerettet hast?", +["There's nothing more satisfying for me than seeing you share your beauty with the world every morning, my princess!"]="Es gibt nichts befriedigenderes für mich, als dich jeden Morgen zu sehen, wie du deine Schönheit mit dem Rest der Welt teilst, meine Prinzessin!", +["Let's go home!"]="Lasst uns nach Hause gehen!", +["And so they discovered that cyborgs weren't invulnerable..."]="Und so fanden sie heraus, dass die Cyborgs nicht unverwundbar sind.", +["All right, we just need to get to the other side of the island!"]="Okay, wir müssen einfach nur auf die andere Seite der Insel gelangen!", +["We have no time to waste..."]="Wir haben keine Zeit zu verlieren.", +["Well, well! Isn't that the cutest thing you've ever seen?"]="Sieh mal einer an! Ist das nicht das süßeste Ding, dass du jemals gesehen hast?", +["Two little hogs cooperating, getting past obstacles..."]="Zwei Igelchen, sie arbeiten zusammen, bewältigen Hindernisse gemeinsam …", +["Let me test your skills a little, will you?"]="Lass mich deine Fertigkeiten ein wenig testen, okay?", +["Why are you doing this?"]="Warum tust du das?", +["To help you, of course!"]="Natürlich um dir zu helfen!", +["OH, COME ON!"]="ACH, KOMM!", +["Let's see what your comrade does now!"]="Sehen wir mal, was dein Kamerad jetzt anstellt.", +["Help me, please!"]="Hilf mir bitte!", +["What are you doing? Let her go!"]="Was tust du? Lass sie gehen!", +["Yeah? Watcha gonna do? Cry?"]="Ja und? Was willst du schon tun? Heulen?", +["We won't let you hurt her!"]="Wir werden nicht zulassen, dass du ihr wehtust!", +["Thank you, oh, thank you, my heroes!"]="Habt Dank, oh, habt Dank, meine Helden!", +["There's nothing more satisfying to us than seeing you share your beauty..."]="Es gibt nichts befriedigenderes für uns, als dich jeden Morgen zu sehen, wie du deine Schönheit …", +["... share your beauty with the world every morning, my princess!"]="…, ja, wie du deine Schönheit mit dem Rest der Welt teilst, meine Prinzessin!", +["Dude, can you see Ramon and Spiky?"]="He, kannst du Ramon und Stachli sehen?", +["No...I wonder where they disappeared?!"]="Nein. Ich frage mich, wohin sie verschwunden sind?!", +["You couldn't possibly believe that after refusing my offer I'd just let you go!"]="Du kannst wohl nicht ernsthaft glauben, dass ich dich einfach laufen lassen, nachdem du mein Angebot ablehnst!", +["You're funny!"]="Du bist lustig!", +["There's nothing more satisfying to us than seeing you share your beauty with the world every morning, my princess!"]="Es gibt nichts befriedigenderes für uns, als dich jeden Morgen zu sehen, wie du deine Schönheit mit dem Rest der Welt teilst, meine Prinzessin!", +["Cannibal Sentry"]="Kannibalenwache", +["The village, unprepared, was destroyed by the cyborgs..."]="Das unvorbereitete Dorf wurde von den Cyborgs zerstört.", +["Hint: Select the BlowTorch, aim and press [Fire]. Press [Fire] again to stop.|Don't blow up the crate."]="Tipp: Wähle den Schweißbrenner, ziele und drücke [Feuern]. Drücke [Feuern] erneut, um aufzuhören.|Spreng nicht die Kiste.", +["The Tunnel Maker"]="Der Tunnelbauer", +["Hint: Select the LowGravity and press [Fire]."]="Tipp: Wähle die niedrige Schwerkraft und drücke [Feuern].", +["The Moonwalk"]="Der Mondspaziergang", +["Slippery"]="Rutschig", +["You'd better watch your steps..."]="Pass besser auf, wohin du trittst.", +["Y3K1337"]="Y3K1337", +["Artur Detour"]="Artus Rück", +["Led Heart"]="Geführtes Herz", +["Nilarian"]="Nilarian", +["Orlando Boom!"]="Orlando Bumm!", +["Gas Gargler"]="Gasgurgler", +["Hatless Jerry"]="Hutloser Igor", +["Rusty Joe"]="Rostjonas", +["Steel Eye"]="Stahlauge", +["Leaderbot"]="Führboter", +["Beep Loopers"]="Piepskreisler", +["Corporationals"]="Kapitalista", +["Name"]="Name", +["Bloodrocutor"]="Blutfrierer", +["Bloodsucker"]="Blutsauger", +["Bonely"]="Knochi", +["Corpsemonger"]="Leichenschänder", +["Femur Lover"]="Schenkellieber", +["Glark"]="Glark", +["Muscle Dissolver"]="Muskellöser", +["Rot Molester"]="Rottiger Störenfried", +["Save Leaks A Lot!|Hint: The Switch utility might be of help to you."]="Rette Undichte Stelle!|Tipp: Die Igelwahl könnte behilflich sein.", +["The Shadow Falls"]="Die Schattenfälle", +["The Showdown"]="Das Showdown", +["Defend yourself!|Hint: You can get tips on using weapons by moving your mouse over them in the weapon selection menu"]="Verteidige dich!|Tipp: Du kannst Tipps über die Benutzung der Waffen erhalten, indem du im Waffenauswahlmenü mit dem Mauszeiger auf sie zeigst.", +["Play with me!"]="Spiel mit mir!", +["Obliterate them!|Hint: You might want to take cover..."]="Vernichte sie!|Tipp: Du solltest in Deckung gehen.", +["Why do you not like me?"]="Warum magst du mich nicht?", +["Choose your side! If you want to join the strange man, walk up to him.|Otherwise, walk away from him. If you decide to att...nevermind..."]="Wähl deine Seite! Wenn du dem seltsamen Mann beitreten willst, geh zu ihm hin.|Geh ansonsten von ihm fort. Wenn du angr… Vergiss es!", +["The Dilemma"]="Das Dilemma", +["Return to Leaks A Lot! If you get stuck, press [Precise] to try again!"]="Kehr zu Undichte Stelle zurück! Wenn du steckenbleibst, drücke [Genaues Zielen], um es erneut zu versuchen!", +["The walk of Fame"]="Die Ruhmesmeile", +["Defeat the cannibals!|Grenade hint: set the timer with [1-5], aim with [Up]/[Down] and hold [Space] to set power"]="Besiege die Kannibalen!|Granatentipp: Setze den Timer mit [1-5], ziele mit [Hoch]/[Runter] und halte [Leer], um die Stärke zu setzen.", +["The Individualist"]="Der Individualist", +["Pfew! That was close!"]="Puh! Das war knapp!", +["Where did you get the exploding apples and the magic bow that shoots many arrows?"]="Woher hast du die explodierenden Äpfel und den magischen Bogen, der so viele Pfeile verschießt?", +["Where did you get the exploding apples?"]="Woher hast du den explodierenden Apfel?", +["Where did you get the magic bow that shoots many arrows?"]="Woher hast du den magischen Bogen, der so viele Pfeile verschießt?", +["Did you warn the village?"]="Hast du das Dorf gewarnt?", +["No, I came back to help you out..."]="Nein, ich kam zurück, um dir zu helfen.", +["Uhm...I met one of them and took his weapons."]="Ähm, ich hab einen von ihnen getroffen und nahm seine Waffen.", +["We should head back to the village now."]="Wir sollten zum Dorf zurückkehren.", +["After the shock caused by the enemy spy, Leaks A Lot and Dense Cloud went hunting to relax."]="Nach dem Schock, der vom feindlichen Spion ausgelöst wurde, gingen Undichte Stelle und Dichte Wolke zur Entspannung auf die Jagd.", +["Little did they know that this hunt will mark them forever..."]="Sie ahnten nicht, dass diese Jagd sie für immer zusammenschweißen würde.", +["I have no idea where that mole disappeared...Can you see it?"]="Ich habe keine Ahnung, wohin dieser Maulwurf verschwand. Kannst du ihn sehen?", +["Nope. It was one fast mole, that's for sure."]="Nee. Es war ein schneller Maulwurf, das ist klar.", +["Please, stop releasing your \"smoke signals\"!"]="Bitte hör mit deinen »Rauchzeichen« auf!", +["You're terrorizing the forest...We won't catch anything like this!"]="Du terrorisierst den Wald. Wir werden auf diese Weise nichts fangen!", +["..."]="…", +["I can't believe it worked!"]="Ich kann nicht glauben, dass es funktioniert hat!", +["That shaman sure knows what he's doing!"]="Dieser Schamane weiß genau, was er tut!", +["Yeah...I think it's a 'he', lol."]="Ja, ich glaube, dass es ein »er« ist. (lach)", +["It wants our brains!"]="Es will unsere Gehirne!", +["Not you again! My head still hurts from last time!"]="Nicht du schon wieder! Mein Kopf tut mir immer noch vom letzten Mal weh!", +["Did you see him coming?"]="Hast du ihn kommen sehen?", +["No. Where did he come from?"]="Nein. Woher kam er?", +["Are we there yet?"]="Sind wir schon da?", +["This must be some kind of sorcery!"]="Das muss wohl eine Art Zauberei sein!", +["I thought their shaman died when he tried our medicine!"]="Ich dachte, ihr Schamane starb, als er unsere Medizin probierte.", +["I saw it with my own eyes!"]="Ich sah es mit meinen eigenen Augen!", +["Then how do they keep appearing?"]="Also woher kommen sie?", +["It's impossible to communicate with the spirits without a shaman."]="Es ist unmöglich, ohne einen Schamanen mit den Geistern zu kommunizieren.", +["We need to warn the village."]="Ich muss das Dorf warnen.", +["What a ride!"]="Was für eine Reise!", +["We can't defeat them!"]="Wir können sie nicht besiegen!", +["I'll hold them off while you return to the village!"]="Ich halte sie zurück, während du zum Dorf zurückkehrst.", +["30 minutes later..."]="30 Minuten später …", +["Greetings, cloudy one!"]="Grüße, du Wolkiger!", +["I have come to make you an offering..."]="Ich kam, um dir ein Angebot zu machen.", +["You are given the chance to turn your life around..."]="Ich gebe dir die Chance, dein Leben auf den Kopf zu stellen.", +["If you agree to provide the information we need, you will be spared!"]="Wenn du einverstanden bist, uns die Information, die wir brauchen, zu geben, wirst du verschont!", +["Have no illusions, your tribe is dead, indifferent of your choice."]="Mach dir keine Hoffnungen, dein Stamm ist tot, unabhängig von deiner Entscheidung.", +["If you decide to help us, though, we will no longer need to find a new governor for the island."]="Wenn du uns helfen willst, brauchen wir für diese Insel keinen neuen Anführer zu suchen.", +["If you know what I mean..."]="Wenn du verstehst, was ich meine.", +["So? What will it be?"]="Also? Was ist deine Entscheidung?", +["Great choice, Steve! Mind if I call you that?"]="Großartige Entscheidung, Stefan! Stört es dich, wenn ich dich so nenne?", +["Whatever floats your boat..."]="Worauf immer du Lust hast.", +["Great! You will be contacted soon for assistance."]="Gut! Du wirst schon bald für Unterstützung benachrichtigt.", +["In the meantime, take these and return to your \"friend\"!"]="In der Zwischenzeit, nimm diese und kehre zu deinem »Freund« zurück!", +["Your death will not be in vain, Dense Cloud!"]="Dein Tod wird nicht ungesühnt bleiben, Dichte Wolke!", +["You will be avenged!"]="Du wirst gerächt!", +["I see..."]="Ich verstehe …", +["Remember this, pathetic animal: when the day comes, you will regret your blind loyalty!"]="Denk dran, du erbärmliches Tier: Wenn der Tag gekommen ist, wirst du deine blinde Loyalität bereuen!", +["You just committed suicide..."]="Du hast gerade Selbstmord begangen.", +["If you say so..."]="Wenn du es sagst …", +["Dude, we really need a new shaman..."]="Mann, wir brauchen wirklich einen neuen Schamanen.", +["It's over..."]="Es ist vorbei.", +["Let's head back to the village!"]="Lass uns zurück zum Dorf gehen!", +["Really?! You thought you could harm me with your little toys?"]="Wirklich? Du dachtest, du könntest mich mit deinen kleinen Spielzeugen verletzen?", +["You're pathetic! You are not worthy of my attention..."]="Du bist erbärmlich! Du hast meine Aufmerksamkeit nicht verdient.", +["Actually, you aren't worthy of life! Take this..."]="Eigentlich hast du nicht das Recht, zu leben! Nimm das!", +["Incredible..."]="Unglaublich.", +["I can't wait any more, I have to save myself!"]="Ich kann nicht länger waren, ich muss selber zur Hilfe eilen!", +["Where are all these crates coming from?!"]="Woher kommen all die Kisten?!", +["I have to get back to the village!"]="Ich muss zum Dorf zurückkehren!", +["Dense Cloud must have already told them everything..."]="Dichte Wolke muss ihnen bereits alles gesagt haben.", +["Weaklings"]="Schwächlinge", +["Stronglings"]="Stärklinge", +["To place a girder, select it, use [Left] and [Right] to select angle and length, place with [Left Click]"]="Um einen Träger zu platzieren, wähle ihn, benutze [Links] und [Rechts], um den Winkel und die Länge zu wählen, platziere ihn mit [Linksklick].", +["Under Construction"]="Baustelle", +["A little gift from the cyborgs"]="Ein kleines Geschenk von den Cyborgs", +["Protect yourselves!|Grenade hint: set the timer with [1-5], aim with [Up]/[Down] and hold [Space] to set power"]="Beschütze dich!|Granatentipp: Setze den Timer mit [1-5], ziele mit [Hoch]/[Runter] und halte [Leer], um die Stärke zu setzen.", +["The guardian"]="Der Wächter", +["...and so the cyborgs took over the world..."]="Und so eroberten die Cyborgs die Welt …", +["Survive!|Hint: Cinematics can be skipped with the [Precise] key."]="Überlebe!|Tipp: Zwischensequenzen können mit der [Genaues Zielen]-Taste übersprungen werden.", +["The First Encounter"]="Das erste Zusammentreffen", +["Brain Stu"]="Hirntopf", +["Brainila"]="Hirnilia", +["Olive"]="Olive", +["Salivaslurper"]="Speichelschlürfer", +["Mindy"]="Intellekta", +["NomNom"]="Mjamjam", +["Spleenlover"]="Milzlieber", +["Thighlicker"]="Schenkelschlecker", +["Defeat the cannibals!|"]="Besiege die Kannibalen!|", +["Try to protect the chief! You won't lose if he dies, but it is advised that he survives."]="Versuche, den Häuptling zu beschützen! Du wirst nicht verlieren, wenn er stirbt, aber es ist ratsam, dass er überlebt.", +["Invasion"]="Invasion", +["United We Stand"]="Gemeinsam sind wir stark", +["I'm so scared!"]="Ich hab solche Angst!", +["Back in the village, after telling the villagers about the threat..."]="Zurück im Dorf, nachdem die Dorfbewohner vor der Gefahr gewarnt worden sind …", +["Their buildings were very primitive back then, even for an uncivilised island."]="Ihre Gebäude waren damals sehr primitiv, selbst für eine unzivilisierte Insel.", +["Young one, you are telling us that they can instantly change location without a shaman?"]="Jüngling, willst du uns etwa weiß machen, dass sie ihre Position sofort ändern können, ohne einen Schamanen?", +["That is, indeed, very weird..."]="Das ist tatsächlich sehr merkwürdig.", +["If they try coming here, they can have a taste of my delicious knuckles!"]="Wenn sie versuchen, hierher zukommen, können sie von meinen köstlichen Fäusten kosten!", +["Haha!"]="Haha!", +["I'm not sure about that!"]="Ich bin mir darüber nicht so sicher.", +["They have weapons we've never seen before!"]="Sie haben Waffen, die wir noch nie zuvor gesehen haben!", +["Luckily, I've managed to snatch some of them."]="Glücklicherweise konnte ich mir ein paar davon ergattern.", +["Oops...I dropped them."]="Upps, ich habe sie fallen gelassen.", +["They keep appearing like this. It's weird!"]="Sie tauchen einfach so auf. Es ist seltsam!", +["Did anyone follow you?"]="Ist dir irgendjemand gefolgt?", +["No, we made sure of that!"]="Nein, wir hatten extra aufgepasst.", +["First aid kits?!"]="Erste-Hilfe-Koffer?", +["I've seen this before. They just appear out of thin air."]="Ich hab das zuvor gesehen. Sie tauchen einfach aus dem Nichts auf.", +["Hey guys!"]="Hey, Leute!", +["Where have you been?"]="Wo warst du?", +["Just on a walk."]="Nur spazieren.", +["You have chosen the perfect moment to leave."]="Du hast den perfekten Augenblick ausgesucht, um zu gehen.", +["HOW DO THEY KNOW WHERE WE ARE???"]="WOHER WISSEN SIE, WO WIR SIND?", +["We have to protect the village!"]="Wir müssen das Dorf schützen!", +["We can't hold them up much longer!"]="Wir können sie nicht länger aufhalten!", +["We need to move!"]="Wir müssen weiter!", +["But where can we go?"]="Aber wohin können wir gehen?", +["To the caves..."]="Zu den Höhlen …", +["Good idea, they'll never find us there!"]="Gute Idee, hier werden sie uns niemals finden!", +["I need to move the tribe!"]="Ich muss den Stamm von hier fortführen.", +["The caves are well hidden, they won't find us there!"]="Die Höhlen sind gut versteckt, sie werden uns hier nicht finden!", +["Light Cannfantry"]="Leichte Kannfantrie", +["Heavy Cannfantry"]="Schwere Kannfantrie", +["Spacetrip"]="Weltraumreise", +["Go to the moon by using the flying saucer and complete the main mission"]="Komm zum Mond, indem du die fliegende Untertasse benutzt und die Hauptmission beendest.", +["Come back to this mission and visit the other planets to collect the crates"]="Kehre zu dieser Mission zurück und besuche die anderen Planeten, um die Kisten einzusammeln.", +["Visit the Death Planet after completing all the other planets' main missions"]="Besuche den Todesplaneten, nachdem du die Hauptmissionen aller anderen Planeten fertiggestellt hast.", +["Come back to this mission after collecting all the device parts"]="Kehre zu dieser Mission zurück, nachdem du alle Bauteile eingesammelt hast.", +["Getting ready"]="Bereitmachen", +["Go and collect the crate"]="Geh und sammle die Kiste.", +["Try not to get spotted by the guards!"]="Versuch, nicht von den Wächtern entdeckt zu werden!", +["The adventure begins!"]="Das Abenteuer beginnt!", +["Travel carefully as your fuel is limited"]="Reise vorsichtig, da dein Treibstoff begrenzt ist.", +["Use the saucer and fly to the moon"]="Benutze die Untertasse und flieg zum Mond.", +["An unexpected event!"]="Ein unerwartetes Ereignis!", +["Beware, any damage taken will stay until you complete the moon's main mission"]="Achtung, jeglicher Schaden, den du nimmst, wird bleiben, bis du die Hauptmission des Mondes fertiggestellt hast.", +["Use the saucer and fly away"]="Benutze die Untertasse und flieg davon!", +["Objectives"]="Ziele", +["Searching the stars!"]="Suche in den Sternen", +["Visit the planets of Ice, Desert and Fruit before you proceed to the Death Planet"]="Besuche den Eis-, Wüsten- und Fruchtplaneten, bevor du mit dem Todesplaneten fortfährst.", +["Fly to the meteorite and detonate the explosives"]="Fliege zum Meteroiten und sprenge die Bomben.", +["Saving Hogera"]="Hogera retten", +["Hog Solo"]="Igel Einsam", +["H"]="H", +["Dr.Cornelius"]="Dr. Cornelius", +["Bob"]="Bert", +["Sam"]="Steffen", +["PAotH"]="PAdI", +["Guards"]="Wächter", +["Help Hog Solo to find all the parts of the anti-gravity device."]="Hilf Igel Einsam, alle Bauteile des Antischwerkraftgerätes zu finden.", +["Travel to all the neighbor planets and collect all the pieces"]="Reise zu allen Nachbarplaneten und sammle alle Bauteile ein.", +["Now I have to climb these trees"]="Jetzt muss ich diese Bäume hochklettern.", +["Use the rope to get to the crate"]="Benutze das Seil, um zur Kiste zu gelangen.", +["One cannot simply walk in moon with rope!"]="Man kann nicht einfach so im Mond mit dem Seil spazieren!", +["This is the wrong way!"]="Das ist die falsche Richtung!", +["Collect the crate with the flying saucer"]="Sammle die Kiste mit der fliegenden Untertasse ein.", +["Fly to the moon"]="Flieg zum Mond.", +["Welcome to the moon!"]="Willkommen auf dem Mond!", +["the moon"]="der Mond", +["Welcome to the Fruit Planet!"]="Willkommen auf dem Fruchtplaneten!", +["the Fruit Planet"]="der Fruchtplanet", +["Welcome to the Desert Planet!"]="Willkommen auf dem Wüstenplaneten!", +["the Desert Planet"]="der Wüstenplanet", +["Welcome to the Planet of Ice!"]="Willkommen auf dem Eisplaneten!", +["the Ice Planet"]="der Eisplanet", +["Welcome to the Death Planet!"]="Willkommen auf dem Todesplaneten!", +["the Planet of Death"]="der Todesplanet!", +["Welcome to the meteorite!"]="Willkommen auf dem Meteorit!", +["the meteorite"]="der Meteorit", +["Near secret base 17 of PAotH in the rural Hogland..."]="In der Nähe der geheimen Basis 17 der PAdI im ländlichen Igelland …", +["So Hog Solo, here we are..."]="Also, Igel Einsam, da wären wir!", +["Behind these trees on the east side there is secret base 17"]="Hinter diesen Bäumen auf der Ostseite liegt die geheime Basis 17.", +["You have to continue alone from now on."]="Von hier an musst du alleine fortfahren.", +["Be careful, the future of Hogera is in your hands!"]="Sei vorsichtig, die Zukunft von Hogera liegt in deinen Händen!", +["We'll use our communicators to contact you"]="Wir werden unsere Kommunikatoren benutzen, um dich zu kontaktieren.", +["In am also entrusting you with some rope"]="Ich werde dir auch etwas Seil anvertrauen.", +["You may find it handy"]="Du könntest es gebrauchen.", +["Thank you Dr.Cornelius"]="Danke, Dr. Cornelius!", +["I'll make good use of it"]="Ich werde es klug anwenden.", +["It would be wiser to steal the space ship while PAotH guards are taking a brake!"]="Es wäre schlauer, das Raumschiff zu stehlen, während die PAdI-Wächter eine Pause machen!", +["Remember! Many will seek the anti-gravity device! Now go, hurry up!"]="Denk dran: Viele werden das Antischwerkraftgerät begehren! Geh jetzt! Beeilung!", +["CheckPoint reached!"]="Kontrollpunkt erreicht!", +["Got the saucer!"]="Ich hab die Untertasse!", +["Nice!"]="Nett!", +["Now use it and go to the moon PAotH station to get more fuel!"]="Benutze es jetzt und komme zur PAdI-Mondbasis, um mehr Treibstoff zu holen!", +["Prepare to flee!"]="Bereitmachen zum Fliehen!", +["Hey"]="Hey", +["Look, someone is stealing the saucer!"]="Sieh, jemand stiehlt die Untertasse!", +["I'll get him!"]="Den schnapp ich mir!", +["You are out of danger, time to go to the moon!"]="Du bist in Sicherheit. Zeit, zum Mond zu gelangen!", +["I guess we lost him!"]="Ich glaube, wir haben ihn verloren!", +["We should better report this and continue our watch!"]="Wir sollten dies besser melden und unsere Wache fortsetzen.", +["I guess I can't go far without fuels!"]="Ich fürchte, ohne Treibstoff komme ich nicht weit.", +["Go to go back"]="Ich muss umkehren.", +["You have to try again!"]="Du muss es nochmal versuchen!", +["Hm... Now I ran out of fuel..."]="Hmm … Jetzt ist mein Treibstoff alle.", +["This planet seems dangerous!"]="Dieser Planet scheint gefährlich zu sein!", +["I am not ready for this planet yet. I should visit it when I have found all the other device parts"]="Ich bin für diesen Planeten noch nicht bereit. Ich sollte ihn besuchen, sobald ich alle anderen Bauteile gefunden habe.", +["Under the meteorite shadow..."]="Unter dem Schatten des Meteorits …", +["You did great Hog Solo! However we aren't out of danger yet!"]="Du hast dich wacker geschlagen, Igel Einsam! Aber wir haben die Gefahren noch nicht überstanden.", +["The meteorite has come too close and the anti-gravity device isn't powerful enough to stop it now"]="Der Meteorit kam zu nah und das Antischwerkraftgerät ist zu schwach, um ihn jetzt zu stoppen.", +["We need it to get split into at least two parts"]="Wir müssen ihn in mindestens zwei Teile zerbrechen.", +["PAotH has sent explosives but unfortunately the trigger mechanism seems to be faulty!"]="PAdI hat Sprengstoffe geschickt, aber leider scheint der Auslöser defekt zu sein.", +["We need you to go there and detonate them yourself! Good luck!"]="Du musst dorthin gehen und sie selbst detonieren. Viel Glück!", +["Hog Solo arrived at "]="Igel Einsam ist angekommen an ", +["Return to the mission menu by pressing the \"Go back\" button"]="Kehre zum Missionsmenü zurück, indem du den »Zurück«-Knopf drückst.", +["You can choose another planet by replaying this mission"]="Du kannst einen anderen Planeten auswählen, indem du diese Mission erneut spielst.", +["Planets with completed main missions will be marked with a flower"]="Planeten, bei denen die Hauptmissionen erledigt wurden, werden mit einer Blume markiert.", +["You have to travel again"]="Du musst erneut reisen.", +["Your first destination is the moon in order to get more fuel"]="Dein erstes Ziel ist der Mond, um mehr Treibstoff zu erhalten.", +["You have to complete the main mission on moon in order to travel to other planets"]="Du musst die Hauptmission auf dem Mond erledigen, damit du zu den anderen Planeten reisen kannst.", +["You have to be careful and not die!"]="Du musst vorsichtig sein und darfst nicht sterben!", +["The last encounter"]="Das letzte Gefecht", +["Defeat Professor Hogevil!"]="Besiege Professor Bösigel!", +["The final part"]="Das letzte Bauteil", +["Professor"]="Professor", +["thug"]="Rowdy", +["Hog Solo lost, try again!"]="Igel Einsam hat verloren, versuch es nochmal!", +["To win the game you have to eliminate all your enemies"]="Um das Spiel zu gewinnen, musst du all deine Gegner eliminieren", +["Congratulations, you won!"]="Gratulation, du hast gewonnen!", +["You have successfully eliminated Professor Hogevil"]="Du hast Professor Bösigel erfolgreich eliminiert!", +["You have rescued H and Dr.Cornelius"]="Du hast H und Dr. Cornelius gerettet.", +["You have acquired the last device part"]="Du hast das letzte Bauteil erhalten.", +["Now go and play the menu mission to complete the campaign"]="Geh jetzt und spiele die Menümission, um die Kampagne zu beenden.", +["Somewhere in the uninhabitable Death Planet..."]="Irgendwo auf dem unbewohnbaren Todesplaneten …", +["Welcome Hog Solo, surprised to see me?"]="Hallo, Igel Einsam! Bist du überrascht, mich zu sehen?", +["As you can see I have survived our last encounter and I had time to plot my master plan!"]="Wie du sehen kannst, habe ich unser letztes Zusammentreffen überlebt und ich hatte Zeit, meinen Masterplan auszuhecken.", +["I've thought that the best way to get the device is to let you collect most of the parts for me!"]="Ich dachte mir, dass es am einfachsten ist, wenn ich dich einfach die meisten Bauteile für mich sammeln lasse.", +["So, now I got the last part and I have your friends captured..."]="Und jetzt habe ich das letzte Teil und deine Freunde gefangengenommen.", +["Will you give me the other parts?"]="Wirst du mir die anderen Teile geben?", +["I will never hand you the parts!"]="Niemals gebe ich dir die Teile!", +["Then prepare for battle!"]="Dann mach dich bereit für die Schlacht!", +["Killing the specialists"]="Die Spezialisten töten", +["Use your available weapons in order to eliminate the enemies"]="Benutze deine verfügbaren Waffen, um die Gegner zu eliminieren.", +["Each time you play this missions enemy hogs will play in a random order"]="Jedes mal, wenn du diese Mission spielst, werden die feindlichen Igel in einer zufälligen Reihenfolge spielen.", +["At the start of the game each enemy hog has only the weapon that he is named after"]="Am Anfang des Spiels hat jeder feindliche Igel nur die Waffe, nachdem er benannt wurde.", +["A random hedgehog will inherit the weapons of his deceased team-mates"]="Ein zufälliger Igel wird die Waffen seiner verstorbenen Teamkollegen erben.", +["If you kill a hedgehog with the respective weapon your health points will be set to 100"]="Wenn du einen Igel mit der entsprechenden Waffe tötest, wird deine Gesundheit auf 100 gesetzt.", +["If you injure a hedgehog you'll get 35% of the damage dealt"]="Wenn du einen Igel verletzt, wirst du 35% des angerichteten Schadens erhalten.", +["Every time you kill an enemy hog your ammo will get reset"]="Bei jedem Mal, in dem du einen feindlichen Igel tötest, wird deine Munition zurückgesetzt.", +["Rope won't get reset"]="Seil wird nicht zurückgesetzt.", +["Challenge Objectives"]="Herausforderungsziele", +["Mortar"]="Mörser", +["Desert Eagle"]="Desert Eagle", +["Grenade"]="Granate", +["Shoryuken"]="Shoryuken", +["Bazooka"]="Bazooka", +["5 deadly hogs"]="5 tödliche Igel", +["You have to eliminate all the enemies"]="Du musst alle Gegner eliminieren.", +["Read the Challenge Objectives from within the mission for more details"]="Lies die Herausforderungsziele in der Mission für mehr Details.", +["You complete the mission in "]="Du hast die Mission abgeschlossen in ", +["The next 4 times you play the \"The last encounter\" mission you'll get 20 more hit points and a Laser Sight"]="Die nächsten 4 Male, die du die Mission »Das letzte Gefecht« spielst, wirst du 20 weitere Trefferpunkte und ein Laservisier erhalten.", +["Somewhere in the Planet of Death..."]="Irgendwo auf dem Todesplaneten …", +["...Hog Solo fights for his life"]="… kämpft Igel Einsam ums Überleben.", +["A Space Adventure"]="Ein Weltraumabenteuer", +["Searching in the dust"]="Suche im Staub", +["The device part is hidden in one of the crates! Go and get it!"]="Das Bauteil ist in einer der Kisten versteckt. Geh und hole es!", +["Most of the destructible terrain in marked with blue color"]="Das meiste des zerstörbaren Geländes ist mit einer blauen Farbe markiert.", +["Chief Sandologist"]="Haupt-Sandologe", +["Sandy"]="Sandi", +["Spike"]="Stachel", +["Sandstorm"]="Sandsturm", +["Smugglers"]="Schmuggler", +["The part device is hidden in one of the crates! Go and get it!"]="Das Bauteil ist in einer der Kisten versteckt. Geh und hole es!", +["A smuggler! Prepare for battle"]="Ein Schmuggler! Bereitmachen zum Kämpfen!", +["Run away you coward!"]="Lauf weg, du Feigling!", +["Who's there?! I'll get you..."]="Wer ist da? Ich krieg dich …", +["In the Planet of Sand, you have to double check your moves..."]="Auf dem Sandplaneten musst du deine Züge gut überlegen …", +["Finally you are here..."]="Endlich bist du hier …", +["Thank you for meeting me on such a short notice!"]="Danke, dass du mich so kurzfristig getroffen hast!", +["No problem, I would do anything for H!"]="Kein Problem, ich würde alles für H tun!", +["Now listen carefully! Below us there are tunnels that have been created naturally over the years"]="Jetzt hör gut zu! Unter uns sind Tunnel, welche über die Jahre natürlich entstanden sind.", +["I have heard that the local tribes say that many years ago some PAotH scientists were dumping their waste here"]="Ich hörte, dass die örtlichen Stämme sagen, dass vor vielen Jahren einige PAdI-Wissenschaftler ihren Müll dort abgeliefert haben.", +["H confirmed that there isn't such a PAotH activity logged"]="H bestätigte, dass eine solche PAdI-Aktivität nicht protokolliert ist.", +["So, I believe that it's a good place to start"]="Also glaube ich, dass es ein guter Ort zum Anfangen ist.", +["Beware though! Many smugglers come often to explore these tunnels and scavenge whatever valuable items they can find"]="Aber Vorsicht! Viele Schmuggler kommen oft hier her, um diese Tunnel zu durchsuchen und alles mögliche, was sie finden, zu sammeln.", +["They won't hesitate to attack you in order to rob you!"]="Sie werden nicht zögern, dich anzugreifen, um dich auszurauben!", +["OK, I'll be extra careful!"]="Okay, ich werde besonders vorsichtig sein!", +["There is the tunnel entrance"]="Hier ist der Tunneleingang.", +["Good luck!"]="Viel Glück!", +["Get him Spike!"]="Hol ihn, Stachel!", +["This is seems like a wealthy hedgehog, nice..."]="Das sieht wie ein reicher Igel aus, nett.", +["Checkpoint reached!"]="Kontrollpunkt erreicht!", +["Haven't found it yet..."]="Ich hab es noch nicht gefunden.", +["Hoorah!!!"]="Hurra!", +["To win the game you had to collect the 2 crates with no specific order"]="Um das Spiel zu gewinnen, musst du die 2 Kisten in beliebiger Reihenfolge einsammeln.", +["To win the game you have to find the right crate"]="Um das Spiel zu gewinnen, musst du die richtige Kiste finden.", +["You can avoid some battles"]="Du kannst einige Kämpfe vermeiden.", +["Use your ammo wisely"]="Benutze deine Munition weise.", +["Don't destroy the device crate!"]="Zerstöre nicht die Kiste mit dem Bauteil!", +["Running for survival"]="Ums Überleben laufen", +["Use the rope to quickly get to the surface!"]="Benutze das Seil, um schnell zur Oberfläche zu gelangen!", +["To win the game you have to go to the surface"]="Um zu gewinnen, musst du zur Oberfläche gehen.", +["Most mines are not active"]="Die meisten Minen sind Blindgänger.", +["From the second turn and beyond the water rises"]="Vom 2. Zug an wird das Wasser steigen.", +["You have escaped successfully"]="Du bist erfolgreich geflohen.", +["Your escape took you "]="Deine Flucht dauerte ", +["Many meters below the surface..."]="Viele Meter unter der Oberfläche …", +["The tunnel is about to get flooded..."]="Der Tunnel wird gleich geflutet!", +["I have to reach the surface as quickly as I can..."]="Du muss die Oberfläche so schnell wie möglich erreichen.", +["Precise flying"]="Präzisionsfliegen", +["Use the RC plane and destroy the all the targets"]="Benutze das Funkflugzeug und zerstöre alle Ziele.", +["Each time you destroy all the targets on your current level you'll get teleported to the next level"]="Jedes mal, wenn du alle Ziele im aktuellen Level zerstörst, wirst du zum nächsten Level teleportiert", +["You'll have only one RC plane at the start of the mission"]="Am Anfang der Mission hast du nur ein Funkflugzeug.", +["During the game you can get new RC planes by collecting the weapon crates"]="Während des Spiels kannst du neue Funkflugzeuge erhalten, indem du die Waffenkisten sammest.", +["On the Desert Planet, Hog Solo found some time to play with his RC plane..."]="Auf dem Wüstenplaneten hat Igel Einsam etwas Zeit gefunden, um mit seinem Funkflugzeug zu spielen.", +["Level 1 clear!"]="Level 1 abgeschlossen!", +["Level 2 clear!"]="Level 2 abgeschlossen!", +["Congratulations, you are the best!"]="Gratulation, du bist der Beste!", +["You have destroyed all the targets"]="Du hast alle Ziele zerstört.", +["You are indeed the best PAotH pilot"]="Du bist wirklich der beste PAdI-Pilot.", +["Next time you play \"Searching in the dust\" you'll have an RC plane available"]="Das nächste Mal, wenn du die Mission »Suche im Staub« spielst, bekommst du ein Funkflugzeug.", +["You have to destroy all the targets"]="Du musst alle Ziele zerstören.", +["You will fail if you run out of ammo and there are still targets available"]="Du wirst verlieren, wenn du keine Munition mehr hast und immer noch Ziele übrigbleiben.", +["The big bang"]="Der Urknall", +["Find a way to detonate all the explosives and stay alive!"]="Finde einen Weg, alle Sprengstoffe zu detonieren und bleib am Leben!", +["Red areas are indestructible"]="Rote Bereiche sind unzerstörbar.", +["Green areas aren't portal enabled"]="Grüne Bereiche sind portalabweisend.", +["You have to destroy all the explosives without dying!"]="Du musst alle Sprengstoffe zerstören, ohne zu sterben!", +["Congratulations, you have saved Hogera!"]="Gratulation, du hast Hogera gerettet!", +["Hogera is safe!"]="Hogera ist in Sicherheit!", +["Bad timing"]="Schlechtes Timing", +["Ready for Battle?"]="Bereit für die Schlacht?", +["Walk left if you want to join Captain Lime or right if you want to decline his offer"]="Geh nach links, wenn du Leutnant Limone beitreten willst, oder nach rechts, wenn du sein Angebot ablehnen möchtest.", +["Battle Starts Now!"]="Jetzt beginnt die Schlacht!", +["You have chosen to fight! Lead the Green Bananas to battle and eliminate all the enemies"]="Du hast dich für die Schlacht entschieden! Führe die Grünen Bananen in die Schlacht und eliminiere alle Feinde.", +["Time to run!"]="Zeit, zu fliehen!", +["You have chosen to flee... Unfortunately the only place where you can launch your saucer is the left-most place on the map"]="Du hast dich für die Flucht entschieden. Leider ist der einzige Ort, wo du deine Untertasse starten kannst, ganz links auf der Karte.", +["Captain Lime"]="Leutnant Limone", +["Mister Pear"]="Herr Birne", +["Lady Mango"]="Frau Mango", +["Green Hog Grape"]="Grünigeltraube", +["Mr Mango"]="Mister Mango", +["General Lemon"]="General Limone", +["Robert Yellow Apple"]="Robert Gelbapfel", +["Summer Squash"]="Sommerkürbis", +["Tall Potato"]="Großkartoffel", +["Yellow Pepper"]="Gelbpaprika", +["Corn"]="Mais", +["Max Citrus"]="Max Zitron", +["Naranja Jed"]="Orangus Otus", +["Green Bananas"]="Grüne Bananen", +["Yellow Watermelons"]="Gelbe Wassermelonen", +["Green Bananas won!"]="Die Grünen Bananen haben gewonnen!", +["You have eliminated all visible enemy hedgehogs!"]="Du hast alle sichtbaren feindlichen Igel besiegt!", +["Hog Solo escaped successfully!"]="Igel Einsam ist erfolgreich geflohen!", +["You have reached the take-off area successfully!"]="Du hast das Startfeld erfolgreich erreicht!", +["Somewhere on the Planet of Fruits a terrible war is about to begin..."]="Irgendwo auf dem Planeten der Früchte steht ein fürchterlicher Krieg bevor.", +["I was told that as the leader of the king's guard, no one knows this world better than you!"]="Mir wurde gesagt, dass, als der Führer der königlichen Garde, niemand diese Welt besser als du kennst!", +["So, I kindly ask for your help"]="Also bitte ich dich ergebenst um Hilfe.", +["You couldn't have come to a worse time Hog Solo!"]="Du könntest du einer kaum schlechteren Zeit ankommen, Igel Einsam!", +["The clan of the Red Strawberry wants to take over the dominion and overthrone king Pineapple."]="Der Klan der Roten Erdbeere will die Herrschaft an sich reißen und König Ananas stürzen.", +["Under normal circumstances we could easily defeat them but we have kindly sent most of our men to the kingdom of Sand to help to the annual dusting of the king's palace."]="Unter normalen Bedingungen könnten wir sie leicht besiegen, aber wir hatten freundlicherweise die Meisten unserer Männer zum Sandkönigreich geschickt, um bei der jährlichen Entstaubung des Königspalasts zu helfen.", +["However the army of Yellow Watermelons is about to attack any moment now."]="Aber die Armee der Gelben Wassermelonen wird jeden Moment angreifen.", +["I would gladly help you if we won this battle but under these circumstances I'll only help you if you fight for our side."]="Ich würde dir gerne helfen, wenn wir diese Schlacht gewinnen, aber unter diesen Bedingungen kann ich dir nur helfen, wenn du an unserer Seite kämpfst.", +["What do you say? Will you fight for us?"]="Was sagst du? Wirst du für uns kämpfen?", +["You choose well Hog Solo!"]="Gute Wahl, Igel Einsam!", +["I have only 3 hogs available and they are all cadets"]="Ich habe nur 3 Igel, uns sie sind alle Kadetten.", +["As you are more experienced, I want you to lead them to the battle"]="Da du erfahrener bist, will ich, dass du sie in der Schlacht anführst.", +["I of course will observe the battle and intervene if necessary"]="Ich werde natürlich die Schlacht beobachten und, wenn nötig, einschreiten.", +["No problem Captain!"]="Kein Problem, Leutnant!", +["The enemies aren't many anyway, it is going to be easy!"]="Es sind eh nicht so viele Feinde, es wird einfach sein!", +["Don't be foolish son, there will be more"]="Sei kein Idiot, Sohn, es werden mehr kommen.", +["Try to be smart and eliminate them quickly. This way you might scare off the rest!"]="Versuch, schlau zu sein und sie schnell zu erledigen. Auf diese Weise könntest du den Rest abschrecken!", +["Too bad... Then you should really leave!"]="Schade. Dann solltest du wirklich gehen!", +["Things are going to get messy around here"]="Es wird hier gleich richtig hässlich werden.", +["Also, you should know that the only place where you can fly is the left-most part of this area"]="Außerdem solltest du wissen, dass der einzige Ort, wo du fliegen kannst, ganz links in diesem Gebiet ist.", +["All the other places are protected by our flight-inhibiting weapons"]="Alle anderen Orte sind von unseren flugverhindernden Waffen geschützt.", +["Now go and don't waste more of my time you coward..."]="Jetzt geh, und vergeude meine Zeit nicht noch weiter, du Feigling!", +["The Green Bananas lost, try again!"]="Die Grünen Bananen haben verloren, versuche es nochmal!", +["You have to eliminate all the visible enemies"]="Du musst alle sichtbaren Gegner eliminieren.", +["5 additional enemies will be spawned during the game"]="5 weitere Gegner werden während des Spiels auftauchen.", +["You are in control of all the active ally units"]="Du hast die Kontrolle über alle aktive verbündete Einheiten.", +["The ally units share their ammo"]="Die verbündeten Einheiten teilen ihre Munition.", +["Try to keep as many allies alive as possible"]="Versuch, so viele Verbündete wie möglich am Leben zu erhalten.", +["Hog Solo couldn't escape, try again!"]="Igel Einsam konnte nicht fliehen, versuch es nochmal!", +["You have to get to the left-most land and remove any enemy hog from there"]="Du musst zum linken Rand gelangen und von dort alle feindlichen Igel beseitigen.", +["You will play every 3 turns"]="Du wirst alle 3 Züge spielen.", +["Green hogs won't intentionally hurt you"]="Grüne Igel werden dich nicht absichtlich verletzen.", +["Next wave in 3 turns"]="Nächte Welle in 3 Zügen", +["Last wave in 3 turns"]="Letzte Welle in 3 Zügen", +["Getting to the device"]="Zum Greifen nah", +["Exploring the tunnel"]="Höhlenforscher", +["Hog Solo has to reach the last crates"]="Igel Einsam muss die letzten Kisten erreichen.", +["Search for the device with the help of the other hedgehogs "]="Such nach dem Gerät mit der Hilfe der anderen Igel.", +["Explore the tunnel with the other hedgehogs and search for the device"]="Erforsche den Tunnel mit den anderen Igeln und such nach dem Gerät.", +["Attack Captain Lime before he attacks back"]="Greif Leutnant Limone an, bevor er angreift.", +["Go to the surface!"]="Geh an die Oberfläche!", +["Return to the Surface"]="Zurück an die Oberfläche", +["Attack the assassins before they attack back"]="Greif die Assassinen an, bevor sie angreifen.", +["Poisonous Apple"]="Giftapfel", +["Dark Strawberry"]="Dunkle Erdbeere", +["Watermelon Heart"]="Wassermelonenherz", +["Deadly Grape"]="Traube des Todes", +["Hog Solo and GB"]="Igel Einsam und GB", +["Fruit Assassins"]="Fruchtassassinen", +["To win the game, Hog Solo has to get the bottom crates and come back to the surface"]="Um das Spiel zu gewinnen, muss Igel Einsam zu den unteren Kisten gelangen und wieder zurück zur Oberfläche kommen.", +["You can use the other 2 hogs to assist you"]="Du kannst die anderen beiden Igel benutzen, um dich zu unterstützen.", +["Do not destroy the crates"]="Zerstöre nicht die Kisten.", +["You'll have to eliminate the Strawberry Assassins at the end"]="Am Ende musst du die Erdbeerassassinen eliminieren.", +["You'll have to eliminate Captain Lime at the end"]="Am Ende musst du Leutnant Limone eliminieren.", +["Don't eliminate Captain Lime before collecting the last crate!"]="Eliminiere Leutnant Limone nicht, bevor du die letzte Kiste eingesammelt hast!", +["You retrieved the lost part"]="Du hast das verlorene Teil ergattert", +["You defended yourself against Captain Lime"]="Du hast dich gegen Leutnant Limone gewehrt", +["You defended yourself against Strawberry Assassins"]="Du hast dich gegen die Erdbeerassassinen gewehrt", +["Somewhere else on the planet of fruits Captain Lime helps Hog Solo..."]="Irgendwo anders auf dem Planeten der Früchte hilft Leutnant Limone Igel Einsam.", +["You fought bravely and you helped us win this battle!"]="Du hast mutig gekämpft und uns geholfen, diese Schlacht zu gewinnen!", +["So, as promised I have brought you where I think that the device you are looking for is hidden."]="Nun, wie versprochen habe ich dich an den Ort gebracht, von dem ich glaube, dass das Gerät dort versteckt ist.", +["I know that your resources are low due to the battle but I'll send two of my best hogs to assist you."]="Ich weiß, dass deine Ressourcen aufgrund der Schlacht begrenzt sind, aber ich werde dir zwei meiner besten Igel schicken, um die zu helfen.", +["Somewhere else on the planet of fruits Hog Solo gets closer to the device..."]="Anderswo auf dem Planeten der Früchte kommt Igel Einsam näher an das Gerät.", +["You are the one who fled! So, you are alive..."]="Du bist der, der floh! Du lebst also …", +["I'm still low on hogs. If you are not afraid I could use a set of extra hands"]="Ich habe immer noch wenige Igel. Wenn du keine Angst hast, könnte ich etwas Unterstützung gebrauchen.", +["I am sorry but I was looking for a device that may be hidden somewhere around here"]="Tut mir Leid, aber ich suchte nach einem Gerät, das hier irgendwo versteckt sein könnte.", +["Many long forgotten things can be found in the same tunnels that we are about to explore!"]="Viele vergessene Dinge können in denselben Tunneln, die wir gleich erforschen werden, finden.", +["If you help us you can keep the device if you find it but we'll keep everything else"]="Wenn du uns hilfst, darfst du das Gerät behalten, wenn du es findest, aber wir werden alles andere behalten.", +["What do you say? Are you in?"]="Was sagst du? Bist du dabei?", +["Ok then!"]="Alles klar!", +["Hoorah! I've found it, now I have to get back to Captain Lime!"]="Hurra! Ich habe es gefunden, nun muss ich zurück zu Leutnant Limone!", +["This Hog Solo is so naive! When he returns I'll shoot him and keep that device for myself!"]="Dieser Igel Einsam ist so naiv! Wenn er zurückkehrt, werde ich ihn erschießen und das Gerät für mich selbst behalten!", +["We have spotted the enemy! We'll attack when the enemies start gathering!"]="Wir haben den Feind gesichtet! Wir werden angreifen, sobald sich die Feinde versammeln.", +["Precise shooting"]="Präzisionsschießen", +["You can only use the Sniper Rifle or the Watermelon bomb"]="Du kannst nur das Scharfschützengewehr oder die Wassermelonenbombe benutzen.", +["You'll have only 2 watermelon bombs during the game"]="Du hast nur 2 Wassermelonenbomben während des Spiels.", +["You'll get an extra Sniper Rifle every time you kill an enemy hog with a limit of max 4 rifles"]="Du erhältst ein zusätzliches Scharfschützengewehr für jeden Igel, den du tötest (max. 4 Gewehre).", +["You'll get an extra Teleport every time you kill an enemy hog with a limit of max 2 teleports"]="Du erhältst einen zusätzlichen Teleporter für jeden Igel (max. 2 Teleporter).", +["The first turn will last 25 sec and every other turn 15 sec"]="Der 1. Zug wird 25 Sek., jeder andere Zug 15 Sek. dauern.", +["If you skip a turn then the turn time left will be added to your next turn"]="Wenn du einen Zug überspringst, wird die Zugzeit auf deinen nächsten Zug addiert.", +["Some parts of the land are indestructible"]="Einige Teile des Landes sind unzerstörbar.", +["Hog 1"]="Igel 1", +["Hog III"]="Igel III", +["Hog 100"]="Igel 100", +["Hog Saturn"]="Igel Saturn", +["Hog nueve"]="Igel nueve", +["Hog onze"]="Igel onze", +["Hog dertien"]="Igel dertien", +["Hog 3x5"]="Igel 3x5", +["Hog two"]="Igel zwei", +["Hog D"]="Igel D", +["Hog exi"]="Igel exi", +["Hog octo"]="Igel octo", +["Hog decar"]="Igel decar", +["Hog Hephaestus"]="Igel Hephaestus", +["Hog 7+7"]="Igel 7+7", +["Hog EOF"]="Igel EOF", +["RS1"]="RS1", +["RS2"]="RS2", +["You will gain some extra ammo from the crates the next time you play the \"Getting to the device\" mission"]="Du wirst etwas zusätzliche Munition aus den Kisten erhalten, wenn du das nächste mal die Mission »Zum Greifen nah« spielst", +["Somewhere in the Fruit Planet Hog Solo got lost..."]="Irgendwo im Fruchtplaneten hat sich Igel Einsam verlaufen.", +["...and got ambushed by the Red Strawberries"]="… und von den Roten Erdbeeren überfallen wurdest.", +["If you skip the game your time left will be added to your next turn"]="Wenn du das Spiel überspringst, wird deine verbleibende Zeit für deinen nächsten Zug addiert.", +["A frozen adventure"]="Ein frostiges Abenteuer", +["Collect the icegun and get the device part from Thanta"]="Sammle die Eiskanone ein und besorge das Bauteil von Thanta", +["Congratulations, you collected the device part!"]="Gratulation, du hast das Bauteil eingesammelt!", +["Win"]="Sieg", +["Paul McHoggy"]="Paul McIgel", +["Thanta"]="Thanta", +["Billy Frost"]="Bernd Frost", +["Ice Jake"]="Eis-Jakob", +["John Snow"]="Jonas Schnee", +["White Tee"]="Schneeweiß", +["Allies"]="Verbündete", +["Frozen Bandits"]="Frostbanditen", +["Go to Thanta and get the device part!"]="Gehe zu Thanta und ergattere das Bauteil!", +["To win the game you have to go next to Thanta"]="Um das Spiel zu gewinnen, muss du neben Thanta stehen", +["Most of the time you'll be able to use only the icegun"]="Die meiste Zeit wirst du nur die Eiskanone benutzen können", +["Use the bazooka and the flying saucer to get the icegun"]="Benutze die Bazooka und die fliegende Untertasse, um die Eiskanone zu ergattern", +["Noooo, Thanta has to stay alive!"]="Nein, Thanta muss am Leben bleiben!", +["On the Ice Planet, where ice rules..."]="Auf dem Eisplaneten, wo das Eis herrscht …", +["Hi! Nice to meet you"]="Hi! Schön, dich zu sehen.", +["Listen carefully! The bandit leader, Thanta, has recently found a very strange device"]="Hör gut zu! Der Anführer der Banditen, Thanta, hat neulich ein sehr seltsames Gerät gefunden.", +["He doesn't know it but this device is a part of the anti-gravity device"]="Er weiß es nicht, aber dieses Bauteil ist ein Teil des Antischwerkraftgeräts.", +["Nice, then I should get the part as soon as possible!"]="Interessant, dann sollte ich besser das Teil so früh wie möglich holen!", +["Be careful, your gadgets won't work in the bandit area. You should get an ice gun"]="Sei vorsichtig, deine Apparate werden im Banditenland nicht funktionieren. Du solltest eine Eiskanone holen.", +["There is one below us!"]="Da ist eine unter uns!", +["Congratulations, now you can take Thanta's device part..."]="Gratulation, nun kannst du dir Thantas Bauteil nehmen …", +["Oh! Please spare me. You can take all my treasures!"]="Oh, bitte verschone mich! Du kannst all meine Schätze nehmen.", +["I just want the strange device you found!"]="Ich will nur das seltsame Teil, das du gefunden hast.", +["Here! Take it..."]="Hier, nimm es …", +["Congratulations, you acquired the device part!"]="Gratulation, du hast das Bauteil erhalten!", +["At the end of the game your health was "]="Am Ende des Spiels war deine Gesundheit ", +["Hard flying"]="Schwerer Flug", +["To win the game you have to pass into the rings in time"]="Um dieses Spiel zu gewinnen, musst du rechtzeitig durch die Ringe fliegen.", +["You'll get extra time in case you need it when you pass a ring"]="Du erhältst Bonuszeit, wenn du sie brauchst, sobald du einen Ring passierst.", +["Every 2 rings, the ring color will be green and you'll get an extra flying saucer"]="Alle 2 Ringe wird der Ring grün und du erhältst eine neue fliegende Untertasse", +["Use space button twice to change flying saucer while floating in mid-air"]="Drücke die Leertaste 2 mal, um die fliegende Untertasse im Flug zu wechseln.", +["Hoorah! You are a champion!"]="Hurra! Du bist ein Champion!", +["You completed the mission in "]="Du hast die Mission fertiggestellt in ", +["You have used "]="Du hast benutzt ", +["You had "]="Du hattest ", +["In the Ice Planet flying saucer stadium..."]="Im Stadion der fliegenden Untertassen auf dem Eisplaneten …", +["This is the Olympic stadium of saucer flying..."]="Das ist das olympische Stadion des Untertassenflugs.", +["All the saucer pilots dream to come here one day in order to compete with the best!"]="Alle Untertassenpiloten träumen davon, hier eines Tages herzukommen, um gegen die Besten um die Wette zu fliegen!", +["Now you have the chance to try and claim the place that you deserve among the best..."]="Jetzt hast du die Gelegenheit, es selbst zu versuchen, und dir einen Rang unter den Besten zu verdienen.", +["Use the saucer and pass through the rings..."]="Benutze die Untertasse und passiere die Ringe.", +["Pause the game by pressing the pause key (default \"P\") for more details"]="Pausiere das Spiel, indem du die Pausetaste (standardmäßig »P«) drückst, um mehr zu erfahren.", +["... can you do it?"]="Kannst du es schaffen?", +["Got 1 more saucer"]="1 neue Untertasse", +[" and 8 more seconds added to the clock"]=" und 8 Bonussekunden auf die Uhr", +["6 more seconds added to the clock"]="6 Bonussekunden auf die Uhr", +["Oh man! Learn how to fly!"]="Oh, Mann! Lern erstmal fliegen!", +["Every 2 rings you'll get extra flying saucers"]="Alle 2 Ringe erhälst du neue fliegende Untertassen", +["Use space button twice to change flying saucer while being on air"]="Drücke die Leertaste 2 mal, um die fliegende Untertasse im Flug zu wechseln", +["The first stop"]="Der erste Halt", +["Go to the upper platform and get the weapons in the crates!"]="Geh zur oberen Plattform und nimm dir die Waffen in den Kisten!", +["Go down and save these PAotH hogs!"]="Geh runter und rette diese PAdI-Igel!", +["Prepare to fight"]="Bereitmachen zum Kämpfen", +["Neutralize your enemies and be careful!"]="Neutralisiere deine Gegner und sei vorsichtig!", +["The fight begins!"]="Die Schlacht beginnt!", +["Joe"]="Sepp", +["Bruce"]="Brutus", +["Helena"]="Helena", +["Boris"]="Boris", +["Prof. Hogevil"]="Prof. Bösigel", +["Minion"]="Lakai", +["Minions"]="Lakaien", +["Hog Solo has to refuel his saucer."]="Igel Einsam muss seine Untertasse auftanken.", +["Rescue the imprisoned PAotH team and get the fuel!"]="Rette das gefangene PAdI-Team und hol dir den Treibstoff!", +["You have to get the weapons and rescue the PAotH researchers"]="Wir müssen die Waffen besorgen und die PAdI-Forscher retten.", +["Don't hit me you fools!"]="Trefft mich nicht, ihr Idioten!", +["The boss has fallen! Retreat!"]="Der Anführer ist gefallen! Rückzug!", +["Congrats! You made them run away!"]="Gratulation! Du hast sie in die Flucht geschlagen!", +["Hog Solo wins, congratulations!"]="Igel Einsam gewinnt, Gratulation!", +["Eliminated the Professor Hogevil"]="Professor Bösigel eliminiert", +["Drove the minions away"]="Seine Lakaien vertrieben", +["I may lost this battle, but I haven't lost the war yet!"]="Ich mag vielleicht diese Schlacht verloren haben, aber ich habe den Krieg noch nicht verloren!", +["Congrats! You won!"]="Gratulation! Du hast gewonnen!", +["Eliminated the evil minions"]="Die bösen Lakaien eliminiert", +["Drove the Professor away"]="Den Professor vertrieben", +["Near PAotH base at moon..."]="In der Nähe der PAdI-Basis am Mond …", +["Hey Hog Solo! Finally you have come..."]="Hey, Igel Einsam! Endlich bist du angekommen …", +["It seems that Professor Hogevil has prepared for your arrival!"]="Es scheint, dass sich Professor Bösigel sich auf deine Ankunft vorbereitet hat!", +["He has captured the rest of the PAotH team and awaits to capture you!"]="Er hat den Rest des PAdI-Teams gefangen und wartet auf deine Gefangennahme!", +["We have to hurry! Are you armed?"]="Wir müssen uns beeilen! Bist du bewaffnet?", +["No, I am afraid I had to travel light"]="Nein, ich fürchte, dass ich mit wenig Gepäck reisen musste.", +["Ok, then you have to go and take some of the weapons we have hidden in case of an emergency!"]="Okay, dann musst du gehen und ein paar der Waffen, die wir für den Notfall versteckt haben, nehmen.", +["They are up there! Take this rope and hurry!"]="Sie sind da oben! Nimm dieses Seil und beeil dich!", +["Ehm... ok..."]="Aha, okay …", +["I've made it! YEAAAAAH!"]="Ich hab's geschafft! HURRA!", +["Nice! Now hurry and get down! You have to rescue my friends!"]="Nett! Nun beeil dich und komm runter! Du musst meine Freunde retten!", +["Get ready to fight!"]="Bereitmachen zum Kämpfen!", +["Look boss! There is the target!"]="Sieh, Boss! Hier ist das Ziel!", +["Prepare for battle!"]="Bereitmachen zum Kämpfen!", +["Oops, I've been spotted and I have no weapons! I am doomed!"]="Upps! Ich wurde entdeckt und ich habe keine Waffen! Ich bin verloren!", +["Here we go!"]="Auf geht's!", +["Chasing the blue hog"]="Jag' den blauen Igel", +["Use the rope in order to catch the blue hedgehog"]="Benutze das Seil, um den blauen Igel zu fangen.", +["You have to stand very close to him"]="Du musst sehr nahe an ihm stehen.", +["Crazy Runner"]="Verrückter Renner", +["On the other side of the moon..."]="Auf der anderen Seite des Mondes …", +["So you are interested in Professor Hogevil"]="Also bist du in Professor Bösigel interessiert.", +["We'll play a game first"]="Wir spielen zuerst ein Spiel.", +["I'll let you know whatever I know about him if you manage to catch me 3 times"]="Ich lass dich wissen, was ich über ihn weiß, wenn du es schaffst, mich 3 mal zu fangen.", +["Let's go!"]="Los geht's!", +["The truth about Professor Hogevil"]="Die Wahrheit über Professor Bösigel", +["Amazing! I was never beaten in a race before!"]="Großartig! Ich wurde zuvor noch nie in einem Wettlauf geschlagen!", +["So, let me tell you what I know about Professor Hogevil..."]="Also, lass mich erzählen, was ich über Professor Bösigel weiß.", +["Professor Hogevil, then known as James Hogus, worked for PAotH back in my time"]="Professor Bösigel, früher bekannt als Jakobus Iglus, arbeitete in meiner Zeit für PAdI.", +["He was the lab assistant of Dr. Goodhogan, the inventor of the anti-gravity device"]="Er war der Laborassistent von Dr. Gutigeln, dem Erfinder des Antischwerkraftgeräts.", +["During the final testing of the device an accident happened"]="Während des letzten Tests des Gerätes ist ein Unfall passiert.", +["In this accident Professor Hogevil lost all his spines on his head!"]="Bei diesem Unfall hat Professor Bösigel all seine Stacheln auf seinem Kopf verloren!", +["That's why he always wears a hat since then"]="Deshalb trägt er seit dem immer einen Hut.", +["After that incident he went underground and started working on his plan to steal the device"]="Nach dem Unfall ging er in den Untergrund und arbeitete an seinem Plan, um das Gerät zu stehlen.", +["He is a very tough and very determined hedgehog. I would be extremely careful if I were you"]="Er ist ein sehr starker und willensstarker Igel. An deiner Stelle wäre ich sehr vorsichtig.", +["I should go now, goodbye!"]="Ich sollte jetzt gehen. Tschüss!", +["Go get him again"]="Los, hol ihn dir wieder!", +["You got me"]="Du hast mich.", +["Too slow! Try again..."]="Zu langsam! Versuch es nochmal.", +["You have to catch the other hog 3 times"]="Du musst den anderen Igel 3 mal fangen.", +["The time that you have left when you reach the blue hedgehog will be added to the next turn"]="Deine Verbleibende Zeit wird zu deinem nächsten Zug addiert, sobald du den blauen Igel erreichst.", +["Each turn you'll have only one rope to use"]="In jedem Zug kannst du nur ein Seil benutzen.", +["You'll lose if you die or if your time is up"]="Du verlierst, wenn du stirbst oder deine Zeit abläuft.", +["Congratulations, you are the fastest!"]="Gratulation, du bist der Schnellste!", +["You have managed to catch the blue hedgehog in time"]="Du hast es geschafft, den blauen Igel rechtzeitig zu fangen.", +["'Zooka Team"]="Die Knalltüten", +["Hunter"]="Jäger", +["Aiming Practice"]="Zielübung", +["Bazooka Training"]="Bazooka-Training", +["Eliminate all targets before your time runs out.|You have unlimited ammo for this mission."]="Eliminiere alle Ziele, bevor die Zeit ausläuft.|Du hast in dieser Mission unbegrenzte Munition.", +["Oh no! Time's up! Just try again."]="Oh nein! Die Zeit ist um! Versuche es nochmal.", +["Aiming practice"]="Zielübung", +["Oh no! You failed! Just try again."]="Oh nein! Du hast versagt! Versuch es nochmal.", +["hits"]="Treffer", +["You have destroyed %d of %d targets."]="Du hast %d von %d Zielen zerstört.", +["You have launched %d bazookas."]="Du hast %d Bazookas abgefeuert.", +["Your accuracy was %.1f%%."]="Deine Treffgenauigkeit betrug %.1f%%.", +["%.1f seconds were remaining."]="Es verblieben %.1f.", +["Congratulations! You've eliminated all targets|within the allowed time frame."]="Gratulation! Du hast alle Ziele innerhalb der|verfügbaren Zeit ausgeschaltet.", +["Grenadiers"]="Grenadiere", +["Nade Boy"]="Granatenjunge", +["Grenade Training"]="Granatentraining", +["Now find the next target! |Tip: Normally you lose health by falling down, so be careful!"]="Nun finde das nächste Ziel! |Tipp: Normalerweise verlierst du Gesundheit, wenn du herunterfällst, also pass auf!", +["You're getting pretty good! |Tip: When you shorten you rope you move faster! |and when you lengthen it you move slower"]="Du wirst ziemlich gut! |Tipp: Wenn du dein Seil verkürzt, bewegst du dich schneller! |Und wenn du es verlängerst, wirst du langsamer.", +["The next one is pretty hard! |Tip: You have to do multiple swings!"]="Die Nächste ist ziemlich schwer! |Tipp: Du musst mehrmals schwingen!", +["I don't know how you did that.. But good work! |The next one should be easy as cake for you!"]="Ich weiß nicht, wie du das getan hast. Aber gute Arbeit! |Die Nächste solle idiotensicher für dich sein!", +["Congratulations"]="Gratulation", +["Congratulations! You've completed the Rope tutorial! |- Tutorial ends in 10 seconds!"]="Gratulation! Du hast die Seil-Einführung abgeschlossen! |- Die Einführung wird in 10 Sekunden beendet.", +["Achievement Unlocked"]="Neue Errungenschaft", +["Rope Master!"]="Seilmeister!", +["Rope Training"]="Seiltraining", +["Great work! Now hit it with your Baseball Bat! |Tip: You can change weapon with 'Right Click'!"]="Gute Arbeit! Nun triff es mit deinem Baseballschläger! |Tipp: Du kannst die Waffe mit [Rechtsklick] wechseln!", +["Remember: The rope only bend around objects, |if it doesn't hit anything it's always stright!"]="Denk dran: Das Seil verbiegt sich nur um Objekte, |wenn es nichts trifft, wird es immer gerade sein.", +["Rope Team"]="Seilteam", +["Get to the target using your rope! |Controls: Left & Right to swing the rope - Up & Down to Contract and Expand!"]="Gelange zum Ziel mit deinem Seil! |Steuerung: Links/Rechts zum Schwingen – Hoch/Runter zum Ein- und Ausfahren!", +["Tip: The rope physics are different than in the real world, |use it to your advantage!"]="Tipp: Die Seilphysik ist anders als in der realen Welt, |nutze das zu deinem Vorteil aus!", +["You did not make it in time, try again!"]="Du hast es nicht rechtzeitig geschafft, versuch es nochmal!", +["You have been respawned, at your last checkpoint!"]="Du wurdest zum letzten Kontrollpunkt zurückgesetzt!", +["You have been respawned, be more carefull next time!"]="Du wurdest wiederbelebt, sei beim nächsten Mal vorsichtiger!", +["Sniperz"]="Heckenschützen", +["Sniper Training"]="Scharfschützen-Training", +["Time's up!"]="Die Zeit ist um!", +["Good so far!"]="Gut soweit!", +["Keep it up!"]="Weiter so!", +["This one's tricky."]="Der hier ist knifflig.", +["Well done."]="Gut gemacht.", +["Demolition is fun!"]="Zerstörung macht Spaß!", +["Will this ever end?"]="Wird dies je enden?", +["Last Target!"]="Letzte Zielscheibe!", +["You have successfully finished the sniper rifle training!"]="Du hast das Scharfschützentraining abgeschlossen!", +["You have destroyed %d of %d targets (+%d points)."]="Du hast %d von %d Zielen zerstört (+%d Punkte).", +["You have made %d shots."]="Du hast %d Schüsse abgegeben.", +["Accuracy bonus: +%d points"]="Präzisions-Bonus: +%d Punkte", +["You had %.2fs remaining on the clock (+%d points)."]="Verbleibende Zeit: %.2fs (+%d Punkte).", +["Shoppa Love"]="Seilliebe", +["Team of Hearts"]="Team der Herzen", +["Heartful"]="Herzlich", +["Ropes and Crates"]="Seile und Kisten", +["Shoppa Union"]="Konsumentenunion", +["Hook"]="Haken", +["The Customor is King"]="Der Kunde ist König", +["King Customer"]="König Kunde", +["Lonely Hog"]="Einsamer Igel", +["Climber"]="Kletterer", +["Zook"]="Zook", +["Team Zook"]="Team Zook", +["Private Nolak"]="Gefreiter Nolak", +["The Hogies"]="Die Igelinge", +["You have thrown %d cluster bombs."]="Du hast %d Splitterbomben geworfen.", +["Grenadier"]="Grenadier", +["Grenade Group"]="Granatengruppe", +["You have thrown %d grenades."]="Du hast %d Granaten geworfen.", +["You have launched %d homing bees."]="Du hast %d zielsuchende Bienen abgefeuert.", +["Pathetic Resistance"]="Erbärmlicher Widerstand", +["Cybernetic Empire"]="Kybernetisches Imperium", +["Unit 835"]="Einheit 835", +["Bamboo Thicket"]="Bambusdickicht", +["Eliminate the enemy before the time runs out"]="Vernichte den Feind, bevor die Zeit abgelaufen ist", +["User Challenge"]="Benutzerherausforderung", +["Congratulations!"]="Gratulation!", +["MISSION SUCCESSFUL"]="MISSION ERFOLGREICH", +["Energetic Engineer"]="Energetischer Ingenieur", +["MISSION FAILED"]="MISSION GESCHEITERT", +["Oh no! Just try again!"]="Oh nein! Versuch's nochmal!", +["Bloody Rookies"]="Blutige Anfänger", +["Instructor"]="Ausbilder", +["Blue Team"]="Blaues Team", +["Filthy Blue"]="Blödblau", +["Dangerous Ducklings"]="Gefährliche Entchen", +["Eliminate the Blue Team"]="Lösche das Blaue Team aus", +["Listen up, maggot!!"]="Aufgepasst, du Made!!", +["!!!"]="!!!", +["The enemy is hiding out on yonder ducky!"]="Der Feind versteckt sich auf dem Entlein dort drüben!", +["Get on over there and take him out!"]="Mach, dass du hinüber kommst und schalte ihn aus!", +["GO! GO! GO!"]="Los, los, los!", +["DAMMIT, ROOKIE!"]="VERDAMMT, REKRUT!", +["DAMMIT, ROOKIE! GET OFF MY HEAD!"]="VERDAMMT, REKRUT! RUNTER VON MEINEM KOPF!", +[":("]=":(", +["You've failed. Try again."]="Du bist gescheitert. Versuche es nochmal.", +["See ya!"]="Mach's gut!", +["Naughty Ninja"]="Böser Ninja", +["Enjoy the swim..."]="Viel Spaß beim Schwimmen …", +["Toxic Team"]="Giftige Gegner", +["Poison"]="Gift", +["Eliminate Poison before the time runs out"]="Neutralisiere das Gift, bevor die Zeit abgelaufen ist.", +["Operation Diver"]="Taucher", +["sec"]="s", +["|- Mines Time:"]="|- Minenzündzeit:", +["Unit"]="Einheit", +["Newton's Hammock"]="Newtons Hängematte", +["Nameless Heroes"]="Namenlose Helden", +["Drowner"]="Absäufer", +["Clowns"]="Clowns", +["Nobody Laugh"]="Niemand darf lachen", +["Wannabe Flyboys"]="Möchtegernflieger", +["Ace"]="Ass", +["RC PLANE TRAINING"]="FUNKFLUGZEUGSTRAINING", +["a Hedgewars challenge"]="eine Hedgewars-Herausforderung", +["Collect or destroy all the health crates."]="Sammle oder zerstöre alle Gesundheitskisten.", +["Compete to use as few planes as possible!"]="Verwende so wenige Flugzeuge wie möglich!", +["Planes used: %d"]="Verwendete Flugzeuge: %d", +["Crates left: %d"]="Verbleibende Kisten: %d", +["Destroyer of planes"]="Flugzeug-Zerstörer", +["Hopeless case"]="Hoffnungsloser Fall", +["Drunk greenhorn"]="Betrunkener Grünschnabel", +["Greenhorn"]="Grünschnabel", +["Beginner"]="Anfänger", +["Experienced beginner"]="Erfahrener Anfänger", +["Below-average pilot"]="Unterdurchschnittlicher Pilot", +["Average pilot"]="Durchschnittlicher Pilot", +["Above-average pilot"]="Überdurchschnittlicher Pilot", +["Professional pilot"]="Profipilot", +["Professional stunt pilot"]="Profi-Stuntpilot", +["Elite pilot"]="Elitepilot", +["Upper-class elite pilot"]="Elitepilot der Oberklasse", +["Top-class elite pilot"]="Elitepilot der Spitzenklasse", +["Cheater"]="Cheater", +["Rank: %s"]="Rang: %s", +["Your rank: %s"]="Dein Rang: %s", +["Flawless victory!"]="Perfekter Sieg!", +["You have perfectly beaten the challenge!"]="Du hast die Herausforderung gemeistert!", +["You have used only 1 RC plane. Outstanding!"]="Du hast nur ein Funkflugzeug gebraucht. Ausgezeichnet!", +["You have finished the challenge!"]="Du hast die Herausforderung gemeistert!", +["You have used %d RC planes."]="Du hast %d Funkflugzeuge benutzt.", +["You have dropped %d missiles."]="Du hast %d Bomben abgeworfen.", +["In your best (and only) flight you took out %d crates with one RC plane!"]="In deinem besten (und einzigem) Flug hast du %d Kisten mit einem Funkflugzeug zerstört!", +["In your best flight you took out %d crates with one RC plane."]="In deinem besten Flug hast du %d Kisten mit einem Funkflugzeug zerstört.", +["This was an awesome performance! But this challenge can be finished with even just one RC plane. Can you figure out how?"]="Das war eine großartige Vorstellung! Aber diese Herausforderung kann sogar mit nur einem Funkflugzeug gemeistert werden. Kannst du herausfinden, wie?", +["Congratulations! You have truly mastered this challenge! Don't forget to save the demo."]="Gratulation! Du hast diese Herausforderung wahrhaft gemeistert! Vergiss nicht, die Wiederholung zu speichern.", +["Prestigious Pilot"]="Prestigeträchtiger Pilot", +["You have gained an achievement: %s"]="Du hast eine Errungenschaft erhalten: %s", +["CHALLENGE COMPLETE"]="HERAUSFORDERUNG ABGESCHLOSSEN", +["Wannabe Shoppsta"]="Möchtegernkäufer", +["Unsuspecting Louts"]="Nichtsahnende Lümmel", +["Unlucky Sods"]="Arme Schweine", +["ROPE-KNOCKING"]="SEILSCHUBSEN", +["COMPLETION TIME"]="ZEIT", +["MISSION SUCCESS"]="MISSIONSERFOLG", +["Use the rope to knock your enemies to their doom."]="Benutze das Seil, um deine Gegner in ihr Verderben zu stürzen!", +["GG!"]="Gut gemacht!", +["Ouch!"]="Autsch!", +["Eliminate all enemies"]="Vernichte alle Gegner", +["Spooky Tree"]="Spukiger Baum", +["Good birdy......"]="Braver Vogel …", +["Feeble Resistance"]="Kraftloser Widerstand", +["Pathetic Hog #%d"]="Erbärmlicher Igel #%d", +["Unit 3378"]="Einheit 3378", +["- Eliminate Unit 3378 |- Feeble Resistance must survive"]="- Vernichte Einheit 3378 |- Kraftloser Widerstand muss überleben", +["Codename: Teamwork"]="Code-Name: Teamwork", +["T_T"]="T_T", +["Hmmm..."]="Hmmm …", +["Good luck out there!"]="Viel Glück da draußen!", +["Challenge"]="Herausforderung", +["Save as many hapless hogs as possible!"]="Rette so viele glücklose Igel wie möglich!", +["That Sinking Feeling"]="Land unter", +["Hapless Hogs"]="Glücklose Igel", +["Sinky"]="Blubb", +["Heavy"]="Schwierig", +["Clumsy"]="Hoppla", +["Silly"]="Doofi", +["Careless"]="Achtlos", +["Sponge"]="Schwamm", +["Deadweight"]="Gravitus", +["The Nameless One"]="Der Namenlose", +["Press [Precise] to skip intro"]="Drücke [Genaues Zielen], um das Intro zu überspringen", +["This rain is really something..."]="Das nenne ich mal einen Regenschauer...", +["Heh, it's not that bad."]="Hehe, so schlimm ist es nicht.", +["You'd almost swear the water was rising!"]="Man könnte fast schwören das Wasser würde steigen!", +["Haha, now THAT would be something!"]="Haha, na DAS wär ja was!", +["Hahahaha!"]="Hahahaha!", +["It's a good thing SUDDEN DEATH is 99 turns away..."]="Gut, dass SUDDEN DEATH in 99 Runden ist …", +["Challenge completed!"]="Herausforderung bewältigt!", +["You saved %d of 8 Hapless Hogs."]="Du hast %d von 8 Glücklosen Igeln gerettet.", +["Achievement obtained: Lively Lifeguard"]="Errungenschaft erhalten: Lebhafter Lebensretter", +["You have obtained an achievement: Lively Lifeguard"]="Du hast eine Errungenschaft erhalten: Lebhafter Lebensretter", +["%d Hapless Hogs left"]="%d Glücklose Igel verbleibend", +["Disqualified!"]="Disqualifiziert!", +["Your hedgehog died!"]="Dein Igel ist gestorben!", +["You must survive the flood in order to score."]="Du musst das Hochwasser überleben um zu punkten.", +["You haven't rescued anyone."]="Du hast niemanden gerettet.", +["Hero Team"]="Heldenteam", +["Good Dude"]="Guter Junge", +["Bad Team"]="Böses Team", +["Elimate your captor."]="Eliminiere deinen", +["Get out of there!"]="Geh weg!", +["The Great Escape"]="Gesprengte Ketten", +["Portal mission"]="Portalmission", +["training"]="Training", +["Hmmm, I'll have to find some way of moving him off this anti-portal surface..."]="Hmmm, ich muss einen Weg finden, um ihn von dieser Antiportaloberfläche zu schubsen …", +["The anti-portal zone is all over the floor, and I have nothing to kill him...Droping something could hurt him enough to kill him..."]="Die Antiportalzone ist über den ganzen Boden und ich habe nichts, um ihn zu töten. Vielleicht könnte ich ihn genug verletzen, wenn ich etwas fallenlasse.", +["You can't fire a portal on the blue surface"]="Du kannst kein Portal auf der blauen Fläche öffnen.", +[" What !! For all of this struggle i just win some ... TIME o0"]="Was?! Für all die Mühen gewinne ich nur etwas … ZEIT?", +["Each turn you get 1-3 random weapons"]="Du bekommst jede Runde 1-3 zufällig gewählte Waffen", +["Game Started!"]="Spiel gestartet!", +["CAPTURE THE FLAG"]="SCHNAPP DIR DIE FLAGGE", +["Flags, and their home base will be placed where each team ends their first turn."]="Fahnen und deren Heimatstandort werden dort plaziert, wo jedes Team deren ersten Zug beendet.", +["RULES OF THE GAME [Press ESC to view]"]="SPIELREGELN (Drücke [Esc] zum Anzeigen)", +["Reflector Shield"]="Reflektorschild", +["Bio-Filter"]="Biofilter", +["Healing Station"]="Heilstation", +["Respawner"]="Wiederbeleber", +["Teleportation Node"]="Teleportationsstation", +["Core"]="Kern", +["Generator"]="Generator", +["Support Station"]="Waffenstation", +["Construction Station"]="Baustation", +["Weapon Filter"]="Waffenfilter", +["Teleport Unsuccessful. Please teleport within a clan teleporter's sphere of influence."]="Teleportation fehlgeschlagen. Bitte teleportiere nur innerhalb des Einzugsgebiets deiner Klanteleporter.", +["Teleportation Mode"]="Teleportationsmodus", +["Girder Placement Mode"]="Trägerplatzierungsmodus", +["Rubber Placement Mode"]="Gummiplatzierungsmodus", +["Mine Placement Mode"]="Minenplatzierungsmodus", +["Sticky Mine Placement Mode"]="Haftminenplatzierungsmodus", +["Barrel Placement Mode"]="Pulverfassplatzierungsmodus", +["Health Crate Placement Mode"]="Gesundheitskistenplatzierungsmodus", +["Weapon Crate Placement Mode"]="Waffenkistenplatzierungsmodus", +["Utility Crate Placement Mode"]="Werkzeugkistenplatzierungsmodus", +["Structure Placement Mode"]="Gebäudeplatzierungsmodus", +["Structure Placement Tool"]="Gebäudeplatzierungswerkzeug", +["Object Placement Tool"]="Objektplatzierungswerkzeug", +["Crate Placement Tool"]="Kistenplatzierungswerkzeug", +["Drill Rocket"]="Bohrkopfrakete", +["Mudball"]="Schlammball", +["Cluster Bomb"]="Splittergranate", +["Molotov Cocktail"]="Molotowcocktail", +["Watermelon Bomb"]="Wassermelonenbombe", +["Hellish Handgrenade"]="Höllische Handgranate", +["Limburger"]="Limburger", +["Shotgun"]="Schrotflinte", +["Flamethrower"]="Flammenwerfer", +["Sniper Rifle"]="Scharfschützengewehr", +["Freezer"]="Eiskanone", +["Land Sprayer"]="Landkanone", +["Whip"]="Peitsche", +["Baseball Bat"]="Baseballschläger", +["Seduction"]="Verführung", +["Hammer"]="Hammer", +["Mine"]="Mine", +["Dynamite"]="Dynamit", +["Cake"]="Kuchen", +["Ballgun"]="Ballkanone", +["Sticky Mine"]="Haftmine", +["Cleaver"]="Hackebeil", +["Birdy"]="Vogli", +["Blowtorch"]="Schweißbrenner", +["Pickhammer"]="Presslufthammer", +["Personal Portal Device"]="Portalgerät", +["Rope"]="Seil", +["Parachute"]="Fallschirm", +["Flying Saucer"]="Fliegende Untertasse", +["Invulnerable"]="Unverwundbar", +["Laser Sight"]="Laservisier", +["Vampirism"]="Vampirismus", +["Low Gravity"]="Niedrige Schwerkraft", +["Extra Damage"]="Extraschaden", +["Extra Time"]="Zusatzzeit", +["You may only use 1 Extra Time per turn."]="Du darfst pro Zug nur einmal Zusatzzeit benutzen.", +["You may only spawn 5 crates per turn."]="Du darfst pro Zug nur 5 Kisten platizeren.", +["Invalid Placement"]="Ungültige Position", +["Insufficient Power"]="Unzureichende Energie", +["The Great Hog in the sky sees your sadness and grants you a boon."]="Der Große Igel im Himmel sieht deine Traurigkeit und leistet dir eine Gabe.", +["Cost"]="Kosten", +["CONSTRUCTION MODE"]="BAUMODUS", +["a Hedgewars mini-game"]="ein Hedgewars Mini-Spiel", +["Build a fortress and destroy your enemy."]="Baue ein Fort und zerstöre deinen Feind.", +["There are a variety of structures available to aid you."]="Es gibt verschiedene Gebäude, um dich zu unterstützen.", +["Use the air-attack weapons and the arrow keys to select structures."]="Benutze die Luftangriffswaffen und die Pfeiltasten, um Gebäude auszuwählen.", +["Grants nearby hogs life-regeneration."]="Spendet nahen Igeln Lebensenergie.", +["Aggressively removes enemy hedgehogs."]="Entfernt feindliche Igel aggressiv.", +["Dematerializes weapons and equipment carried by enemy hedgehogs."]="Demateralisiert Waffen und Equipment, das von feindlichen Igeln getragen wird.", +["Reflects enemy projectiles."]="Stößt feindliche Projektile ab.", +["Generates power."]="Erzeugt Energie.", +["Resurrects dead hedgehogs."]="Belebt tote Igel wieder.", +["Allows free teleportation between other nodes."]="Ermöglicht kostenlose Teleportationen zwischen anderen Stationen.", +["Teleporation Node"]="Teleporterstation", +["Allows placement of girders, rubber-bands, mines, sticky mines and barrels."]="Ermöglicht die Platzierung von Trägern, Gummibändern, Minen, Haftminen und Pulverfässern.", +["Allows the placement of weapons, utiliites, and health crates."]="Ermöglicht die Platzierung von Waffen-, Werkzeug- und Gesundheitskisten", +["Note: Some weapons have a second option (See continent information). Find and use them with the \""]="Beachte: Einige Waffen haben eine Zweitoption (Siehe Kontinentinformationen). Finde und benutze sie mit \"", +["Per team weapons"]="Waffen pro Team", +["Select your continent/weaponset: with the \"Up\" or \"Down\" keys. You can also select one with the weapons menu."]="Wähle deinen Kontinent/Waffensatz mit den [Hoch]- oder [Runter]-Tasten. Du kannst ihn auch mit dem Waffenmenü auswählen.", +["Tip: See the \"esc\" key (this menu) if you want to see the currently playing teams continent, or that continents specials."]="Tipp: Benutze die [Esc]-Taste (dieses Menü), wenn du den Kontinent des aktuellen Teams sehen willst, oder die Besonderheiten dieses Kontinents sehen willst.", +["Unique new weapons"]="Einzigartige neue Waffen", +["key."]="Taste.", +["switch"]="Schalter", +["weaponschemes"]="Waffenschemata", +["Green lipstick bullet: [Poisonous, deals no damage]"]="Grüne Lippenstiftpatrone: (giftig, kein Schaden)", +["Cluck-cluck time: [Fire an egg ~ Sabotages and cures poison ~ Cannot be fired close to another hog]"]="Gackerzeit: (Schieß ein Ei – Sabotiert und kuriert Gift – kann nicht in der nähe anderer Igel gefeuert werden)", +["Anno 1032: [The explosion will make a strong push ~ Wide range, wont affect hogs close to the target]"]="Anno 1032: (Die Explosion wird stark schubsen – Große Reichweite, betrifft Igel in der Nähe des Ziels nicht)", +["Dust storm: [Deals 15 damage to all enemies in the circle]"]="Staubsturm: (15 Schaden für alle Gegner im Kreis)", +["Cricket time: [Fire away a 1 sec mine! ~ Cannot be fired close to another hog]"]="Kricket: (Feuere eine 1-Sek.-Mine! – kann nicht in der Nähe anderer Igel gefeuert werden)", +["Drop a bomb: [Drop some heroic wind that will turn into a bomb on impact]"]="Bombe fallenlassen: (Lass einen heroischen Wind, der sich bei Einschlag in eine Bombe verwandelt, fallen)", +["Penguin roar: [Deal 15 damage + 10% of your hogs health to all hogs around you and get 2/3 back]"]="Pinguinröhren: (Richte 15 Schaden + 10% deiner Igelgesundheit auf alle Igel um dich herum und bekomme 2/3 zurück)", +["Disguise as a Rockhopper Penguin: [Swap place with a random enemy hog in the circle]"]="Als Felsenpinguin tarnen: (Vertausche die Plätze mit einem zufälligen Igel im Kreis)", +["Lonely Cries: [Rise the water if no hog is in the circle and deal 6 damage to all enemy hogs.]"]="Einsame Heuler: (Erhöhe das Wasser, wenn kein Igel im Kreis ist und richte 6 Schaden auf alle gegnerischen Igel an.)", +["Hedgehog projectile: [Fire your hog like a Sticky Bomb]"]="Igelprojektil: (Feuer deinen Igel wie eine Haftmine)", +["Napalm rocket: [Fire a bomb with napalm!]"]="Napalmrakete: (Feuer eine Bombe mit Napalm ab!)", +["Eagle Eye: [Blink to the impact ~ One shot]"]="Adlerauge: (Teleportiere dich zum Einschlagspunkt – ein Schuss)", +["Medicine: [Fire some exploding medicine that will heal all hogs effected by the explosion]"]="Medizin: (Feuere eine explodierende Medizin, die alle Igel im Explosionsradius heilen wird)", +["Sabotage/Flare: [Sabotage all hogs in the circle and deal ~1 dmg OR Fire a cluster up into the air]"]="Sabotage/Fackel: (Sabotiere alle Igel im Kreis und richte ca. 1 Schaden an, ODER feuer eine Splittergranate in die Luft)", +["- You can switch between hogs at the start of your turns. (Not first one)"]="- Du kannst deinen Igel am Zugbeginn aussuchen (aber nicht am 1. Zug).", +["Area"]="Gebiet", +["Difficulty: "]="Schwierigkeitsgrad: ", +["EASY"]="EINFACH", +["North America"]="Nordamerika", +["Population"]="Einwohnerzahl", +["Special Weapons:"]="Sonderwaffen:", +["GasBomb"]="Gasbombe", +["MEDIUM"]="MITTEL", +["South America"]="Südamerika", +["Europe"]="Europa", +["Molotov"]="Molotowcocktail", +["Africa"]="Afrika", +["- Will give you a parachute every second turn."]="- Wird dir jeden 2. Zug einen Fallschirm geben", +["Asia"]="Asien", +["Australia"]="Australien", +["Baseballbat"]="Baseballschläger", +["Antarctic summer: - Will give you one girder/mudball and two sineguns/portals every fourth turn."]="Antarktischer Sommer: – Wird dir einen Träger/Schlammball und zwei Sinuskanonen/Portalgeräte jeden 4. Zug geben", +["Antarctica"]="Antarktika", +["HARD"]="SCHWER", +["Duration"]="Dauer", +["Kerguelen"]="Kerguelen", +["- Massive weapon bonus on first turn"]="- Großer Waffenbonus am ersten Zug", +["- Will Get 1-3 random weapons"]="- wird 1–3 zufällige Waffen erhalten", +["Zealandia"]="Neuseeland-Kontinent", +["- You will recieve 2-4 weapons on each kill! (Even on own hogs)"]="- Du wirst 2–4 Waffen für jeden Abschuss erhalten (sogar für eigene Igel)!", +["Sundaland"]="Sunda", +["General information"]="Allgemeine Informationen", +[" was extracted from the scheme|- This continent will be able to use the specials from the other continents!"]=" wurde vom Schema extahiert|– Dieser Kontinent wird alle Besonderheiten von den anderen Kontinenten benutzen können!", +["Continental supplies"]="Kontinentallieferungen", +["Let a continent provide your weapons!"]="Lass einen Kontinent dich mit Waffen beliefern!", +["Select continent!"]="Wähle einen Kontinent!", +["NORMAL"]="NORMAL", +["You are sabotaged, RUN!"]="Du wurdest sabotiert, LAUF!", +["WARNING: Sabotage detected!"]="WARNUNG: Sabotage erkannt!", +["Hogs in sight!"]="Igel in Sicht!", +["RULES"]="REGELN", +["Each turn is only ONE SECOND!"]="Jeder Zug dauert nur EINE SEKUNDE!", +["Use your ready time to think."]="Benutze deine Vorbereitungszeit zum Denken.", +["Slot keys save time! (F1-F10 by default)"]="Schnelltasten, um Zeit zu sparen! (standardmäßig F1–F10)", +["SLOTS"]="SLOTS", +["Slot"]="Slot", +["Teleport"]="Teleporter", +["FRENZY"]="WAHNSINN", +["a frenetic Hedgewars mini-game"]="ein hektisches Hedgewars-Minispiel", +["random in range from %i%% to %i%% with period of %i msec"]="Zufällig von %i%% bis %i%% mit einer Periode von %i ms", +["changing range from %i%% to %i%% with period of %i msec"]="Sich verändernde Grenzen von %i%% bis %i%% mit einer Periode von %i ms", +["Gravity"]="Schwerkraft", +["Current setting is "]="Aktuelle Einstellung ist ", +["Setup:|'g=150', where 150 is 150% of normal gravity"]="Syntax:|»g=150«, wobei »150« für 150% der normalen Schwerkraft steht.", +["or 'g=50, g2=150, period=4000' for gravity changing|from 50 to 150 and back with period of 4000 msec"]="Oder »g=50, g2=150, period=4000« für eine Schwerkraft,|die von 50 bis 150 vor und zurück mit einer Periode von 4000 ms oszilliert.", +["Set period to negative value for random gravity"]="Setze period auf einen negativen Werd für eine zufällige Schwerkraft", +["Homing Bee"]="Zielsuchende Biene", +["SineGun"]="Sinuskanone", +["Land Spray"]="Landkanone", +["Kamikaze"]="Kamikaze", +["RC Plane"]="Funkflugzeug", +["Air Attack"]="Luftangriff", +["Mine Strike"]="Minen-Luftangriff", +["Drill Strike"]="Bohr-Luftangriff", +["Air Mine"]="Luftmine", +["Napalm"]="Napalm-Luftangriff", +["Piano Strike"]="Piano-Angriff", +["BlowTorch"]="Schweißbrenner", +["PickHammer"]="Presslufthammer", +["Girder"]="Bauträger", +["Rubber"]="Gummi", +["Resurrector"]="Totenbeschwörung", +["Tardis"]="Zeitkasten", +["Switch Hog"]="Igel wechseln", +["Air Mine Placement Mode"]="Luftminenplatzierungsmodus", +["Target Placement Mode"]="Zielscheibenplatzierungsmodus", +["Cleaver Placement Mode"]="Hackebeilplatzierungsmodus", +["Advanced Repositioning Mode"]="Fortgeschrittner Verlegungsmodus", +["Tagging Mode"]="Markierungsmodus", +["Hog Identity Mode"]="Igelidentitätsmodus", +["Team Identity Mode"]="Team-Identitätsmodus", +["Health Modification Mode"]="Gesundheitsmodifikationsmodus", +["Sprite Placement Mode"]="Sprite-Platzierungsmodus", +["Sprite Modification Mode"]="Sprite-Modifikationsmodus", +["Waypoint Placement Mode"]="Wegpunktplatzierungsmodus", +["Selection Mode"]="Auswahlmodus", +["Placement Mode"]="Platzierungsmodus", +["Deletion Mode"]="Löschmodus", +["Please click on a hedgehog."]="Bitte klick auf einen Igel.", +["LandFlag Modification Mode"]="LandFlag-Modifikationsmodus", +["Sprite Erasure Mode"]="Sprite-Löschmodus", +["Tag Collection Mode"]="Markiermodus: Einsammeln", +["Please click on a crate."]="Bitte klick auf eine Kiste.", +["Tag Victory Mode"]="Markiermodus: Sieg", +["Tag Failure Mode"]="Markiermodus: Niederlage", +["Waypoint Deletion Mode"]="Wegpunktlöschmodus", +["Standard Target"]="Standardziel", +["Standard Cleaver"]="Standardhackebeil", +["Normal Sticky Mine"]="Normale Haftmine", +["Chef"]="Chefkoch", +["Clown"]="Clown", +["Commander"]="Kommandant", +["Engineer"]="Ingenieur", +["Ninja"]="Ninja", +["Physicist"]="Physiker", +["Pyro"]="Pyromane", +["Saint"]="Sankt", +["Sniper"]="Heckenschütze", +["Soldier"]="Soldat", +["Trapper"]="Trapper", +["Sprite Testing Mode"]="Sprite-Testmodus", +["Standard Waypoint"]="Standard-Wegpunkt", +["Level Data Saved!"]="Leveldaten gesichert!", +["HEDGE EDITOR"]="HEDGE EDITOR", +["(well... kind of...)"]="(naja, sozusagen …)", +["Place Girder: Girder"]="Bauträger platzieren: Bauträger", +["Place Rubber: Rubber"]="Gummi platzieren: Gummi", +["Place Gear: Air Attack"]="Gear platzieren: Luftangriff", +["Change Selection: [Up], [Down], [Left], [Right]"]="Auswahl ändern: [Hoch], [Runter], [Links], [Rechts]", +["Toggle Help: Precise+1 (While a tool is selected)"]="Hilfe umschalten: Genaues Zielen + 1 (Während ein Werkzeug ausgewählt ist)", +["COMMANDS: (Use while no weapon is selected)"]="BEFEHLE: (Benutzen, wenn keine Waffe gewählt ist)", +["Save Level: Precise+4"]="Level sichern: Genaues Zielen + 4", +["Toggle Editing Weapons and Tools: Precise+2"]="Waffen- und Werkzeugbearbeitung umschalten: Genaues Zielen + 2", +["GIRDER PLACEMENT MODE"]="BAUTRÄGERPLATZIERUNGSMODUS", +["Use this mode to place girders"]="Benutze diesen Modus, um Bauträger zu platzieren", +["Place Girder: [Left Click]"]="Bauträger platzieren: [Linksklick]", +["Change Rotation: [Left], [Right]"]="Rotieren: [Links], [Rechts]", +["Change LandFlag: [1], [2], [3], [4]"]="LandFlag ändern: [1], [2], [3], [4]", +["1 - Normal Girder"]="1 – Normaler Bauträger", +["2 - Indestructible Girder"]="2 – Unzerstörbarer Bauträger", +["3 - Icy Girder"]="3 – Eisiger Bauträger", +["4 - Bouncy Girder"]="4 – Elastischer Bauträger", +["Deletion Mode: [5]"]="Löschmodus: [5]", +["Toggle Help: Precise+1"]="Hilfe umschalten: Genaues Zielen + 1", +["RUBBER PLACEMENT MODE"]="GUMMIPLATZIERUNGSMODUS", +["Use this mode to place rubberbands"]="Benutze diesen Modus, um Gummibalken zu platzieren", +["Place Object: [Left Click]"]="Objekt platzieren: [Linksklick]", +["1 - Normal Rubber"]="1 – Normales Gummi", +["BARREL PLACEMENT MODE"]="FASSPLATZIERUNGSMODUS", +["Use this mode to place barrels"]="Benutze diesen Modus, um Pulverfässer zu platzieren", +["Change Health: [Left], [Right]"]="Gesundheit ändern: [Links], [Rechts]", +["Change Placement Mode: [Up], [Down]"]="Platzierungsmodus ändern: [Hoch], [Runter]", +["CLEAVER MINE PLACEMENT MODE"]="HACKEBEILPLATZIERUNGSMODUS", +["Use this mode to place cleavers"]="Benutze diesen Modus, um Hackebeile zu platzieren", +["TARGET MINE PLACEMENT MODE"]="ZIELSCHEIBENPLATZIERUNGSMODUS", +["Use this mode to place targets"]="Benutze diesen Modus, um Zielscheiben zu platzieren", +["WAYPOINT PLACEMENT MODE"]="WEGPUNKTPLATZIERUNGSMODUS", +["Use this mode to waypoints"]="Benutze diesen Modus, um Wegpunkte zu platzieren", +["Place Waypoint: [Left Click]"]="Wegpunkt platzieren: [Linksklick]", +["MINE PLACEMENT MODE"]="MINENPLATZIERUNGSMODUS", +["Use this mode to place mines"]="Benutze diesen Modus, um Minen zu platzieren", +["Change Timer (in milliseconds): [Left], [Right]"]="Zeitzünder (in Millisekunden) ändern: [Links], [Rechts]", +["STiCKY MINE PLACEMENT MODE"]="HAFTMINENPLATZIERUNGSMODUS", +["Use this mode to place sticky mines"]="Benutze diesen Modus, um Haftminen zu platzieren", +["AIR MINE PLACEMENT MODE"]="LUFTMINENPLATZIERUNGSMODUS", +["Use this mode to place air mines"]="Benutze diesen Modus, um Luftminen zu platzieren", +["Use this mode to place weapon crates"]="Benutze diesen Modus, um Waffenkisten zu platzieren", +["Change Content: [Left], [Right]"]="Inhalt ändern: [Links], [Rechts]", +["UTILITY CRATE PLACEMENT MODE"]="WERKZEUGKISTENPLATZIERUNGSMODUS", +["Use this mode to place utility crates"]="Benutze diesen Modus, um Werkzeugkisten zu platzieren", +["HEALTH CRATE PLACEMENT MODE"]="GESUNDHEITSKISTENPLATZIERUNGSMODUS", +["Change Health Boost: [Left], [Right]"]="Gesundheitsschub ändern: [Links], [Rechts]", +["ADVANCED REPOSITIONING MODE"]="FORTGESCHRITTENER VERLEGUNGSMODUS", +["Use this mode to select and reposition gears"]="Benutze diesen Modus, um Gears auszuwählen und zu verlegen", +["[Left], [Right]: Change between selection and placement mode."]="[Links], [Rechts]: Zwischen Auswahl- und Verlegungsmodus wechseln.", +["SPRITE MODIFICATION MODE"]="SPRITE-MODIFIKATIONSMODUS", +["Set LandFlag: [1], [2], [3], [4]"]="LandFlag setzen: [1], [2], [3], [4]", +["1 - Normal Land"]="1 – Normales Gelände", +["2 - Indestructible Land"]="2 – Unzerstörbares Gelände", +["3 - Icy Land"]="3 – Eisiges Gelände", +["4 - Bouncy Land"]="4 – Elastisches Gelände", +["SPRITE PLACEMENT MODE"]="SPRITE-PLATZIERUNGSMODUS", +["Use this mode to place custom sprites."]="Benutze diesen Modus, um benutzerdefinierte Sprites zu platzieren.", +["[Left], [Right]: Change sprite selection"]="[Links], [Rechts]: Sprite-Auswahl ändern", +["TAGGING MODE"]="MARKIERUNGSMODUS", +["Use this mode to tag gears for win/lose conditions."]="Benutze diesen Modus, um Gears für Sieg-/Niederlagebedingungen zu markieren.", +["Tag Gear: [Left Click]"]="Gear markieren: [Linksklick]", +["[Left], [Right]: Change between tagging modes."]="[Links], [Rechts]: Zwischen Markierungsmodi wechseln.", +["HOG IDENTITY MODE"]="IGELIDENTITÄTSMODUS", +["Use this mode to give a hog a preset identity and weapons."]="Benutze diesen Modus, um einem Igel ein voreingestelle Idendität sowie Waffen zu geben.", +["Set Identity: [Left Click]"]="Identität setzen: [Linksklick]", +["[Left], [Right]: Change between identities."]="[Links], [Rechts]: Identitäten wechseln.", +["TEAM IDENTITY MODE"]="TEAMIDENTITÄTSMODUS", +["Use this mode to give an entire team themed hats and names."]="Benutze diesen Modus, um einem Team einen Satz Hüte und Namen zu geben.", +["HEALTH MODIFICATION MODE"]="GESUNDHEITSMODIFIKATIONSMODUS", +["Use this mode to set the health of hogs."]="Benutze diesen Modus, um die Igelgesundheit einzustellen.", +["Set Health: [Left Click]"]="Gesundheit setzen: [Linksklick]", +["[Left], [Right]: Change health value."]="[Links], [Rechts]: Gesundheitswert auswählen", +["Warning: Deletition Mode Active"]="Achtung: Löschmodus aktiv", +["The editor weapons and tools have been removed!"]="Die Editorwaffen und -werkzeuge wurden entfernt!", +["The editor weapons and tools have been added!"]="Die Editorwaffen und -werkzeuge wurden hinzugefügt!", +["Bouncy Land"]="Sprunghaftes Gelände", +["Normal Land"]="Normales Gelände", +["Indestructible Land"]="Unzerstörbares Gelände", +["Icy Land"]="Eisiges Gelände", +["HIGHLANDER"]="HOCHLÄNDER", +["Not all hogs are born equal."]="Nicht alle Igel werden gleich geboren.", +["Eliminate enemy hogs and take their weapons."]="Vernichte alle gegnerischen Igel und nimm ihre Waffen.", +["Per-Hog Ammo"]="Munition pro Igel", +["Weapons reset."]="Waffen werden zurückgesetzt.", +["Unlimited Attacks"]="Unbegrenzte Angriffe", +["The first player to kill someone becomes the Mutant."]="Der erste Spieler, der einen umbringt, wird zum Mutanten.", +["The Mutant has super-weapons and a lot of health."]="Der Mutant hat Superwaffen und eine hohe Gesundheit.", +["The Mutant loses health quickly if he doesn't keep scoring kills."]="Der Mutant verliert schnell an Gesundheit, wenn er nicht schnell andere Igel tötet.", +["Normal players can only score points by killing the mutant."]="Andere Spieler erhalten nur durch das Töten des Mutanten Punkte.", +["The player with least points (or most deaths) becomes the Bottom Feeder."]="Der Spieler mit den wenigsten Punkten (oder den meisten Toden) wird zum Versager.", +["The Bottom Feeder can score points by killing anyone."]="Der Versager erhält Punkte durch das Töten beliebiger anderer Igel.", +["POINTS"]="PUNKTE", +["+2 for becoming a Mutant"]="+2 für die Verwandlung zum Mutanten", +["+1 to a Mutant for killing anyone"]="+1 für den Mutanten, der andere tötet", +["+1 to a Bottom Feeder for killing anyone"]="+1 für den Versager, der andere tötet", +["-1 to anyone for a suicide"]="-1 für Selbstmord", +["Other kills don't give you points."]="Andere Abschüsse bringen keine Punkte.", +["Mutant"]="Mutant", +["a Hedgewars tag game"]="ein Hedgewars-Fangenspiel", +["ONE HOG PER TEAM! KILLING EXCESS HEDGES"]="EIN IGEL PRO TEAM! ÜBERFLÜSSIGE IGEL WERDEN GETÖTET", +["FIRST BLOOD MUTATES"]="ERSTER MÖRDER MUTIERT", +["DOUBLE KILL"]="DOPPEL-ABSCHUSS", +["MEGA KILL"]="MEGA-ABSCHUSS", +["ULTRA KILL"]="ULTRA-ABSCHUSS", +["MONSTER KILL"]="MONSTRÖSER ABSCHUSS", +["LUDICROUS KILL"]="HAARSTRÄUBENDER ABSCHUSS", +["HOLY SHYTE!"]="HEILIGE SCHEISSE!", +["INSANITY"]="WAHNSINN", +["Score"]="Punktzahl", +["WINNER IS "]="DER SIEGER IST ", +["-------"]="-------", +[" HAS MUTATED"]=" MUTIERTE", +[" HP"]=" TP", +["Jumping is disabled"]="Sprünge sind deaktiviert!", +["Way-Points Remaining"]="Wegpunkte verbleibend", +["s"]="s", +["RACER"]="WETTRENNEN", +["TRACK COMPLETED"]="STRECKENLAUF BEENDET", +["NEW RACE RECORD: "]="NEUER RENNREKORD: ", +["WINNING TIME: "]="BESTZEIT: ", +["NEW CLAN RECORD: "]="NEUER KLAN-REKORD", +["TIME: "]="ZEIT: ", +["s|"]="s|", +["STATUS UPDATE"]="STATUSAKTUALISIERUNG", +["Rounds Complete: "]="Runden gespielt: ", +["Best Team Times: "]="Beste Team-Zeiten: ", +["Build a track and race."]="Konstruiere eine Strecke und mach ein Wettrennen.", +["Round Limit:"]="Rundenbegrenzung:", +["Available points remaining: "]="Verfügbare Punkte verbleibend:", +["Waypoint placed."]="Wegpunkt gesetzt", +["GAME BEGUN!!!"]="SPIEL GESTARTET!!!", +["Complete the track as fast as you can!"]="Durchlaufe die Strecke so schnell du kannst!", +["NOT ENOUGH WAYPOINTS"]="NICHT GENUG WEGPUNKTE", +["Place more waypoints using the 'Air Attack' weapon."]="Platziere mehr Wegpunkte durch Verwenden der »Luftangriff«-Waffe", +["Please place the way-point in the open, within the map boundaries."]="Bitte platziere den Wegpunkt in der Luft, innerhalb der Kartengrenzen.", +["Please place the way-point further from the waterline."]="Bitte platziere den Wegpunkt weiter weg vom Wasser.", +["Race complexity limit reached."]="Rennkomplexitätslimit erreicht.", +["Good to go!"]="Startklar!", +["Each turn you get one random weapon"]="Du bekommst jede Runde eine zufällig gewählte Waffe.", +["BOOM!"]="KABUMM!", +["SCORE"]="PUNKTZAHL", +["KILLS"]="ABSCHÜSSE", +["invaders destroyed"]="Angreifer zerstört", +["Rounds Complete"]="Runden gespielt", +["Flamer"]="Flammenwerfer", +["selected!"]="ausgewählt!", +["shots remaining."]="Schüsse übrig", +["Barrel Launcher"]="Fasswerfer", +["Ammo Depleted!"]="Munition erschöpft!", +["Mine Deployer"]="Minenleger", +["Shield Depleted"]="Schild aufgebraucht!", +["Power Remaining"]="Verbleibende Energie", +["Shield ON:"]="Schild AN:", +["Shield OFF:"]="Schild AUS:", +["Pings left:"]="Verbleibende Pings:", +["Destroy invaders to score points."]="Zerstöre die Angreifer um Punkte zu erhalten.", +["Round Limit"]="Rundenbegrenzung", +["Turn Time"]="Zeit pro Zug", +["Movement: [Up], [Down], [Left], [Right]"]="Bewegung: [Hoch], [Runter], [Links], [Rechts]", +["Fire"]="Feuer", +["[Left Shift]"]="[Umschalt links]", +["Toggle Shield"]="Schild ein/aus", +["[Enter]"]="[Eingabe]", +["Radar Ping"]="Radarsignal", +["[Backspace]"]="[Rücktaste]", +["Surfer! +15 points!"]="Surfer! +15 Punkte", +["Shield Miser!"]="Schildgieriger", +["Accuracy Bonus!"]="Präzisions-Bonus!", +["Fierce Competition!"]="Harter Wettkampf!", +["Time Extended!"]="Zeit verlängert!", +["Drone Hunter!"]="Drohnenjäger", +["Ammo"]="Munition", +["Ammo Maniac!"]="Munitionsverrückter!", +["Shield boosted! +30 power"]="Schild verstärkt! +30 Energie", +["Shield is fully recharged!"]="Schild vollständig aufgeladen!", +["Shield Seeker!"]="Schildsucher!", +["Boss defeated!"]="Boss wurde besiegt!", +["Boss Slayer!"]="Boss-Töter!", +["Hit Combo!"]="Treffer-Combo!", +["GOTCHA!"]="ERWISCHT!", +["Sniper!"]="Scharfschütze!", +["They Call Me Bullseye!"]="Man nennt mich »Adlerauge«!", +["Point Blank Combo!"]="Nahschuss-Combo!", +["Multi-shot!"]="Multischuss!", +["Shield Master!"]="Schildmeister!", +["Kamikaze Expert!"]="Kamikazeexperte!", +["Depleted Kamikaze!"]="Munitionsloses Kamikaze!", +["Timed Kamikaze!"]="Pünktliches Kamikaze!", +["You can further customize the race by changing the scheme script paramater."]="Du kannst das Renner ferner bearbeiten, indem du den Skriptparameter im Schema änderst.", +["THE SPECIALISTS"]="DIE SPEZIALISTEN", +["Eliminate the enemy specialists."]="Vernichte die gegnerischen Spezialisten", +["Game Modifiers: "]="Spiel-Modifikatoren", +["Weapons Reset"]="Waffenzurücksetzung", +["Switched to "]="Gewechselt zu ", +["Prepare yourself"]="Mach dich bereit", +["ammo extended!"]="Munition aufgestockt!", +["Barrel Eater!"]="Fassfresser!", +["Mine Eater!"]="Minenfresser!", +["Tumbling Time Extended!"]="Purzelzeit verlängert!", +["fuel extended!"]="Treibstoff aufgetankt!", +["Eliminate the enemy hogs to win."]="Vernichte alle gegnerischen Igel, um zu gewinnen.", +["New Mines Per Turn"]="Neue Minen jeden Zug", +["New Barrels Per Turn"]="Neue Fässer jeden Zug", +["Time Extension"]="Zeitverlängerung", +["Change Weapon"]="Waffenwechsel", +["Grab Mines/Explosives"]="Sammle Minen/Fässer", +["Health crates extend your time."]="Erste-Hilfe-Kisten verlängern deine Zeit.", +["Ammo is reset at the end of your turn."]="Munition wird am Ende des Spielzuges zurückgesetzt.", +["Double Kill!"]="Doppelmord!", +["Killing spree!"]="Blutrausch!", +["Unstoppable!"]="Unaufhaltsam!", +["Friendly Fire!"]="Eigenbeschuss!", +["For improved features/stability, play 0.9.18+"]="Für bessere Features/Stabilität, spiele 0.9.18 oder später", +["Surfer!"]="Surfer!", +["All walls touched!"]="Alle Wände berührt!", +["Go surf!"]="Los, surfe!", +["Walls Left"]="Verbleibende Wände", +["Configuration accepted."]="Konfiguration akzeptiert.", +["You may only attack from a rope!"]="Du darfst nur von einem Seil angreifen!", +["Spawn the crate, and attack!"]="Lass die Kiste auftauchen und greif an!", +["Press [Enter] to accept this configuration."]="Drücke [Eingabe], um diese Konfiguration zu akzeptieren.", +["Walls Required"]="Wände benötigt", +["Surf Before Crate"]="Surfen Vor Kiste", +["Attack From Rope"]="Angriff Vom Seil", +["Super Weapons"]="Superwaffen", +["WALL TO WALL"]="WAND-ZU-WAND", +["a shoppa minigame"]="ein Einkaufs-Minispiel", +["Roper"]="Seiler", +["Shoppers"]="Käufer", +["Use your rope to collect all crates as fast as possible."]="Benutze dein Seil, um alle Kisten so schnell wie möglich einzusammeln.", +["Speed Shoppa"]="Rasender Kistensammler", +["%d crate(s) remaining"]="Verbleibende Kisten: %d", +["milliseconds"]="Millisekunden", +["You have finished the challenge in %.3f s."]="Du hast die Herausforderung in %.3fs gemeistert.", +["Challenge failed!"]="Herausforderung gescheitert!", +["crate(s)"]="Kiste(n)", +["You have collected %d out of %d crate(s)."]="Du hast %d von %d Kiste(n) eingesammelt.", +["Trainee"]="Azubi", +["Training Team"]="Traningsteam", +["You have shot %d times."]="Du hast %d mal geschossen.", +["Time’s up!"]="Die Zeit ist um!", +["Targets left: %d"]="Verbleibende Ziele: %d", +["You have destroyed all targets!"]="Du hast alle Ziele zerstört!", +["Congratulations! You have destroyed all targets within the time."]="Gratulation! Du hast alle Ziele innerhalb der verfügbaren Zeit ausgeschaltet.", +["You have finished the target practice!"]="Du hast die Zielübung abgeschlossen!", +["Your accuracy was %.1f%% (+%d points)."]="Deine Treffgenauigkeit betrug %.1f%% (+%d Punkte).", +["You had %.1fs remaining on the clock (+%d points)."]="Du hattest eine verbleibende Zeit von %.1fs (+%d Punkte)." +} diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/de.txt --- a/share/hedgewars/Data/Locale/de.txt Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/de.txt Tue Nov 10 20:43:13 2015 +0100 @@ -29,7 +29,7 @@ 00:26=Wassermelonenbombe 00:27=Höllische Handgranate 00:28=Bohrkopfrakete -00:29=Ballpistole +00:29=Ballkanone 00:30=Napalm-Luftangriff 00:31=Funkflugzeug 00:32=Schwerkraft verringern @@ -40,9 +40,9 @@ 00:37=Vampirismus 00:38=Scharfschützengewehr 00:39=Fliegende Untertasse -00:40=Molotov-Cocktail -00:41=Birdy -00:42=Tragbares Portal Device +00:40=Molotowcocktail +00:41=Vogli +00:42=Tragbares Portalgerät 00:43=Piano-Angriff 00:44=Alter Limburger 00:45=Sinuskanone @@ -53,12 +53,13 @@ 00:50=Bohr-Luftangriff 00:51=Schlammball 00:52=Keine Waffe ausgewählt -00:53=ZeitBox +00:53=Zeitkasten ; 00:54=Bauwerk 00:54=Landkanone -00:55=Gefrierer +00:55=Eiskanone 00:56=Hackebeil - +00:57=Gummi +00:58=Luftmine 01:00=Auf in die Schlacht! 01:01=Unentschieden @@ -84,6 +85,9 @@ 01:19=Extreme 01:20=%1 Sprungkraft 01:21=Audio stumm +01:22=Abwesenheitsmodus +01:23=Autokamera aus +01:24=Autokamera an ; Event messages ; Hog (%1) died @@ -113,7 +117,7 @@ 02:00=%1 hat die letzte Melone geworfen 02:00=%1 hat die letzte Deagle gezogen 02:00=%1 nahm einen Schuss zu viel -02:00=%1 hätte wirklich ein Erste-Hilfe-Kit gebrauchen können +02:00=%1 hätte wirklich einen Erste-Hilfe-Koffer gebrauchen können 02:00=%1 ist gegangen, um ein besseres Spiel zu spielen 02:00=%1 will nicht mehr 02:00=%1 scheitert @@ -127,7 +131,7 @@ 02:00=%1 ist ab jetzt ein Ex-Igel 02:00=%1 sieht sich die Radieschen von unten an 02:00=%1 hat aufgehört zu existieren -02:00=Verabschieden Sie sich von %1 +02:00=Wir verabschieden uns von %1 02:00=Für %1 gibt es keine Hoffnung mehr 02:00=%1 trat von der Lebensbühne ab 02:00=%1 erleidet ein spontanes multiples Organversagen @@ -150,6 +154,21 @@ 02:00=%1 spürt keinen Schmerz mehr 02:00=%1 muss nicht mehr leiden 02:00=%1 hat eine Abkürzung gefunden … +02:00=%1 war ohnehin nur Kanonenfutter +02:00=Mir kommen die Tränen, %1! +02:00=Man wird dich rächen, %1! +02:00=%1 wartet auf die Wiederbelebung. +02:00=%1 hat ein Nach-Tod-Erlebnis +02:00=%1 hat im Spiel des Lebens verloren +02:00=%1 wurde vernichtend geschlagen +02:00=%1 hat alle Lebenspunkte aufgebraucht +02:00=%1 wird nicht mehr auf Futtersuche gehen müssen +02:00=%1 schläft den ganz langen Winterschlaf +02:00=Warum musstest du sterben, %1? +02:00=Oh, nein, %1! Wir hatten noch so viel vor … +02:00=Jetzt braucht sich %1 nicht mehr vor dem Tod zu fürchten. +02:00=%1 wurde von den Schrecken des Krieges erlöst +02:00=Klappe zu, %1 tot! ; Hog (%1) drowned 02:01=%1 geht auf Tauchstation! @@ -218,6 +237,7 @@ 02:01=%1 lässt sich diese einmalige Tauchgelegenheit nicht entgehen 02:01=Und wir dachten %1 könnte nicht noch tiefer sinken … 02:01=%1 zieht eine Etage tiefer +02:01=Seht, %1 kann schwimmen! Nein, doch nicht … ; Round starts 02:02=Auf in die Schlacht! @@ -250,7 +270,6 @@ 02:02=Lassen Sie den Kampf in der Woche beginnen 02:02=Lassen Sie den Kampf des Tages beginnen 02:02=Lassen Sie den Kampf der Stunde beginnen -02:02=Tun Sie Ihr Bestes! 02:02=Zerstört den Feind! 02:02=Viel Glück! 02:02=Viel Spaß! @@ -289,6 +308,18 @@ 02:05=Ein Grund zur Hoffnung! 02:05=Frisch aus dem Jungbrunnen 02:05=Lebenszeit in Kisten +02:05=Hilfe ist in Sicht! +02:05=Das macht kranke Igel wieder gesund +02:05=Schlagt das Lazarett auf! +02:05=Erhöhe deine Lebenserwartung … +02:05=Erste Hilfe! +02:05=Endlich kommt Hilfe! +02:05=Gesundmacher aus der Luft! +02:05=Lebenspunkterhöhungsmittel! +02:05=Kiste des Lebens +02:05=Tankt eure Lebensenergie wieder auf! +02:05=Hat jemand »Hatschi!« gesagt? +02:05=Damit fühlt sich der Igel wieder pudelwohl! ; New ammo crate 02:06=Nachschub! @@ -309,13 +340,30 @@ 02:06=Was auch immer da drin ist, es ist bestimmt nicht Pizza 02:06=Einsammlen! 02:06=Eine Waffenkiste! -02:06=Lassen Sie nicht zu, dass sich der Feind sie holt! +02:06=Lasse nicht zu, dass der Feind sie holt! 02:06=Schönes neues Spielzeug! 02:06=Eine geheimnisvolle Kiste! 02:06=Ein eckiges Ü-Ei! 02:06=Die Holzkiste der Pandora! 02:06=Willst du mit mir spielen? 02:06=Quadratisch, praktisch, … gefährlich? +02:06=Diese Kiste bringt Bombenstimmung! +02:06=Damit kann man dem Feind so richtig einheizen +02:06=Jetzt geht die Party erst richtig los! +02:06=Damit kommt Freude auf! +02:06=Ob da eine Melonenbombe drin ist? +02:06=Das ist wie ein Kindergeburtstag! +02:06=Wir brauchen Waffen, viele Waffen! +02:06=Davon kann man nie genug haben. +02:06=Neue Waffen, um das Spiel etwas spannender zu machen +02:06=Neue Waffen braucht das Land! +02:06=Nichts für Weicheier! +02:06=Achtung: Inhalt hochexplosiv +02:06=Wer zuerst kommt, mahlt zuerst! +02:06=Für die Waffennarren +02:06=Damit schlägt das Herz jedes Waffennarren höher! +02:06=Waffenkiste: Nur echt mit dem Fragezeichen +02:06=Dies könnte die spielentscheidende Waffe sein! ; New utility crate 02:07=Nützliches? @@ -324,11 +372,23 @@ 02:07=Lieferung frei Haus! 02:07=Mehr als nur eine Kiste! 02:07=Weitere Hilfsmittel! -02:07=Extras für Sie! +02:07=Extras für dich! 02:07=Dies sollte gut sein! -02:07=Verwenden Sie diese mit Bedacht +02:07=Verwende diese mit Bedacht 02:07=Uff, diese Box ist schwer 02:07=Futter für Strategen +02:07=Heimwerker atmen auf! +02:07=Schaffe, schaffe, Häusle baue +02:07=Werkzeuge kann man immer gebrauchen +02:07=Auf diese Kisten können Sie bauen +02:07=Ein Geschenk der Techniker! +02:07=Strategen freuen sich! +02:07=Dies könnte deine Mobilität wiederherstellen … +02:07=Verschaffe dir einen strategischen Vorteil +02:07=Muttern und Schrauben! +02:07=Lieferung aus den Igelwerken! +02:07=Damit schlägt das Herz jedes Mechanikers höher! +02:07=So viele Möglichkeiten … ; Hog (%1) skips his turn 02:08=%1 ist so ein Langeweiler … @@ -376,7 +436,7 @@ 02:08=%1 zählt Schäfchen 02:08=%1 lässt sich die Sonne auf den Bauch scheinen 02:08=%1 genießt die Stille -02:08=%1 fragt sich ob es schon Zeit für den Winterschlaf ist +02:08=%1 fragt sich, ob es schon Zeit für den Winterschlaf ist ; Hog (%1) hurts himself only 02:09=%1 sollte lieber zielen üben! @@ -389,7 +449,7 @@ 02:09=Das hat wohl nicht ganz geklappt, %1 02:09=%1 geht ein wenig zu sorglos mit gefährlichen Waffen um 02:09=%1 sollte eine Änderung der Laufbahn betrachten -02:09=Nein, nein, nein, %1, Sie müssen auf den Feind schießen! +02:09=Nein, nein, nein, %1, du musst auf den Feind schießen! 02:09=%1 bewegt sich einen Schritt näher zum Selbstmord 02:09=%1, Helfer des Feindes 02:09=%1 hatte das anders geplant @@ -415,6 +475,22 @@ 02:09=%1 wird vom Pech verfolgt 02:09=Auch %1 macht mal Fehler 02:09=Hoppla?! +02:09=%1 will unbedingt den Darwin-Award gewinnen +02:09=%1 macht sich lächerlich +02:09=%1 hat absolut nichts dazugelernt +02:09=%1 hat wohl nicht mehr alle Tassen im Schrank +02:09=%1 ist durchgeknallt +02:09=%1 bekommt so bald keine Beförderung mehr +02:09=%1 verstümmelt sich selbst +02:09=%1 mag Schmerzen +02:09=%1 ist heute auf dem falschen Bein aufgestanden +02:09=%1 schoss in die falsche Richtung +02:09=Das sah schmerzhaft aus! +02:09=%1 verwirrt den Feind +02:09=Was ist denn mit %1 los? +02:09=Keine Sorge, %1, nächstes Mal klappt’s bestimmt! +02:09=%1 ist eine Gefahr für sich selbst +02:09=%1 braucht keine Feinde mehr ; Hog (%1) shot an home run (using the bat and another hog) 02:10=Home Run! @@ -462,19 +538,19 @@ 03:08=Annäherungsmine 03:09=Pistole (mehrere Schüsse) 03:10=BUMM! -03:11=Bonk! +03:11=Voll auf die Zwölf! 03:12=Kampfkunst 03:13=NICHT IN VERWENDUNG 03:14=Fortbewegungsmittel 03:15=Luftschlag 03:16=Luftschlag -03:17=Grabwerkzeug +03:17=Grabewerkzeug 03:18=Werkzeug 03:19=Fortbewegungsmittel 03:20=Aktion 03:21=Ballistische Waffe 03:22=Nenn mich Indiana! -03:23=Kampfkunst +03:23=Tödliche Kampfkunst 03:24=Der Kuchen ist keine Lüge! 03:25=Verkleidung 03:26=Saftige Granate @@ -492,15 +568,15 @@ 03:38=Gewehr (mehrere Schüsse) 03:39=Fortbewegungsmittel 03:40=Brandbombe -03:41=Riesiger Squawks-Fan +03:41=Mach die Flatter! 03:42=Portalöffner ; the misspelled "Beethoven" is intentional (-> to beat) 03:43=Spiele Beathovens tödliche Sonate! 03:44=Ziemlich alt und stinkig 03:45=Die Macht der Wissenschaft 03:46=Heiß, heiß, heiß! -03:47=Mach es weg! -03:48=Stop! Hammer time! +03:47=Klebt (fast) überall +03:48=In-den-Boden-Stampfer 03:49=Tut, was man vermutet 03:50=Maulwurfsfreund 03:51=Am Boden gefunden @@ -508,64 +584,71 @@ 03:53=Typ 40 ;03:54=Baue etwas 03:54=Werkzeug +03:55=Cooler wird’s nicht +03:56=Bitte ge- oder missbrauchen +03:57=Werkzeug +03:58=Schwebende Annäherungsmine ; Weapon Descriptions (use | as line breaks) -04:00=Greife deine Feinde mit einfachen Granaten an.|Der Zeitzünder steuert den Explosionszeitpunkt.|1-5: Zeitzünder einstellen|Angriff: Halten, um mit mehr Kraft zu werfen -04:01=Greife deine Feinde mit Splittergranaten an.|Der Zeitzünder wird die Granate in mehrere|kleine Bomben zerspringen lassen.|1-5: Zeitzünder einstellen|Angriff: Halten, um mit mehr Kraft zu werfen +04:00=Greife deine Feinde mit einfachen Granaten an.|Der Zeitzünder steuert den Explosionszeitpunkt.|1–5: Zeitzünder einstellen|Genaues Zielen + 1-5: Sprungkraft einstellen|Angriff: Halten, um mit mehr Kraft zu werfen +04:01=Greife deine Feinde mit Splittergranaten an.|Der Zeitzünder wird die Granate in mehrere|kleine Bomben zerspringen lassen.|1–5: Zeitzünder einstellen|Genaues Zielen + 1-5: Sprungkraft einstellen|Angriff: Halten, um mit mehr Kraft zu werfen 04:02=Greife deine Feinde mit einem ballistischen|Projektil an, das vom Wind beeinflusst wird.|Angriff: Halten, um mit mehr Kraft zu feuern 04:03=Starte eine explosive Biene, die auf ein gewähltes|Ziel zusteuern wird. Feuere nicht mit voller Kraft,|um die Zielgenauigkeit zu verbessern.|Cursor: Ziel wählen|Angriff: Halten, um mit mehr Kraft zu feuern 04:04=Greife deine Feinde mit einer Schrotflinte und|zwei Schüssen an. Durch die Streuung musst du|nicht genau zielen, um trotzdem zu treffen.|Angriff: Feuern (mehrfach) -04:05=Ab in den Untergrund! Benutze den Presslufthammer,|um einen Schacht nach unten zu graben und so|andere Gebiete zu erreichen.|Angriff: Presslufthammer ein- oder ausschalten +04:05=Ab in den Untergrund! Benutze den Presslufthammer,|um einen Schacht nach unten zu graben und so|andere Gebiete zu erreichen.|Angriff: Presslufthammer ein- oder ausschalten|Links/Rechts: Schräg bohren 04:06=Gelangweilt? Keine Optionen? Munition sparen?|Kein Problem! Passe einfach diese Runde, Feigling!|Angriff: Runde ohne Angriff aussetzen -04:07=Überbrücke große Distanzen mit gezielt abgefeuerten|Seilschüssen. Benutze deine Bewegungsenergie, um|andere Igel zu schubsen oder wirf vom Seil aus Granaten|und ähnliche Waffen.|Angriff: Seil abfeuern oder lösen|Weiter Sprung: Waffe benutzen -04:08=Halte dir deine Feinde fern oder blockiere sie,|indem du ihnen Minen vor die Beine wirfst.|Sei aber schnell genug, damit du sie nicht noch|selbst auslöst!|Angriff: Mine legen +04:07=Überbrücke große Distanzen mit gezielt abgefeuerten|Seilschüssen. Benutze deine Bewegungsenergie, um|andere Igel zu schubsen oder wirf vom Seil aus Granaten|und ähnliche Waffen.|Angriff: Seil abfeuern oder lösen|Hoch/Runter: Seil verkürzen/verlängern|Weitsprung: Waffe benutzen +04:08=Halte dir deine Feinde fern oder blockiere sie,|indem du ihnen Minen vor die Beine wirfst.|Sei aber schnell genug, damit du sie nicht noch|selbst auslöst!|Angriff: Mine legen|Genaues Zielen + 1-5: Sprungkraft einstellen 04:09=Nicht so ganz zielsicher? Versuche es mit der|Desert Eagle, denn diese bietet dir vier Schuss.|Angriff: Feuern (mehrfach) -04:10=Pure Gewalt ist immer eine Option. Lege einfach|diesen klassischen Sprengsatz neben deinen Feinden|ab und mach dich aus dem Staub.|Angriff: Dynamitstange legen +04:10=Rohe Gewalt ist immer eine Lösung. Lege einfach|diesen klassischen Sprengsatz neben deinen Feinden|ab und mach dich aus dem Staub.|Angriff: Dynamitstange legen 04:11=Beseitige Feinde, indem du diese mit dem|Baseballschläger einfach von der Karte fegst.|Oder wie wäre es, wenn du deinen Freunden ein|paar Minen vor die Beine schlägst?|Angriff: Alles vor dem Igel schlagen -04:12=Rücke mit deinen Feinden näher zusammen und|entfessle die Kraft dieser so gut wie tödlichen|Kampftechnik.|Angriff: Feuerfaust einsetzen +04:12=Rücke mit deinen Feinden näher zusammen und|entfessle die Kraft dieser so gut wie tödlichen|Kampftechnik.|Angriff: Alles vor dem Igel schlagen 04:13=UNUSED -04:14=Höhenangst? Greif besser zum Fallschirm.|Er wird sich von alleine entfalten, wenn du|zu lange oder zu tief fällst, und so deinem|Igel den Hals retten.|Angriff: Fallschirm öffnen|Weiter Sprung: Waffe benutzen +04:14=Höhenangst? Greif besser zum Fallschirm.|Er wird sich von alleine entfalten, wenn du|zu lange oder zu tief fällst, und so deinem|Igel den Hals retten.|Angriff: Fallschirm manuell öffnen oder entfernen|Links/Rechts/Hoch/Runter: Flug steuern|Weitsprung: Waffe benutzen 04:15=Rufe ein Flugzeug, um deine Feinde mit einem|Bombenteppich einzudecken.|Links/Rechts: Angriffsrichtung wählen|Cursor: Zielgebiet wählen und Angriff starten 04:16=Rufe ein Flugzeug, um mehrere Minen im|Zielgebiet abwerfen zu lassen.|Links/Rechts: Angriffsrichtung wählen|Cursor: Zielgebiet wählen und Angriff starten -04:17=Unterschlupf gefällig? Benutze den Schweißbrenner,|um einen Tunnel in festen Untergrund zu graben|oder einem Feind eine heiße Bekanntschaft machen|zu lassen.|Angriff: Brenner ein- oder ausschalten -04:18=Brauchst du Schutz oder eine Möglichkeit, einen|Abgrund zu überwinden? Platziere einige Bauträger,|um dir zu helfen.|Links/Rechts: Bauform und Orientierung wählen|Cursor: Bauträger platzieren -04:19=Im richtigen Moment kann sich eine Teleportation|mächtiger als jede Waffe erweisen, da sich so ein|Igel gezielt einer gefährlichen Situation binnen|Sekunden entziehen kann.|Cursor: Zielposition wählen -04:20=Erlaubt es dir, den aktiven Igel zu wechseln|und mit einem anderen Igel fortzufahren.|Angriff: Wechsel aktivieren -04:21=Feuere ein granatenartiges Projektil in die|Richtung deines Gegners, das beim Aufschlag|mehrere kleine Bomben freisetzen wird.|Angriff: Mit voller Kraft feuern +04:17=Unterschlupf gefällig? Benutze den Schweißbrenner,|um einen Tunnel in festen Untergrund zu graben|oder einem Feind eine heiße Bekanntschaft machen|zu lassen.|Angriff: Brenner ein- oder ausschalten|Hoch/Runter: Graberichtung ändern +04:18=Brauchst du Schutz oder eine Möglichkeit, einen|Abgrund zu überwinden? Platziere einige Bauträger,|um dir zu helfen.|Links/Rechts: Bauform und Ausrichtung wählen|Cursor: Bauträger platzieren +04:19=Im richtigen Moment kann sich eine Teleportation|mächtiger als jede Waffe erweisen, da sich so ein|Igel gezielt einer gefährlichen Situation binnen|Sekunden entziehen kann.|Cursor: Zielposition wählen|Links/Rechts: Blickrichtung wählen +04:20=Ermöglicht es dir, den aktiven Igel zu wechseln|und mit einem anderen Igel fortzufahren.|Angriff: Igelwechsel aktivieren|Wechseln: Nächten Igel wählen|Genaues Zielen + Wechseln: Vorherigen Igel wählen +04:21=Feuere ein Projektil, welches mehrere Splitter|beim Einschlag freisetzen wird. Sie werden|zurückgeschleudert und sind gefährlicher|als das Hauptprojektil.|Angriff: Mit voller Kraft feuern 04:22=Nicht nur etwas für Indiana Jones! Die Peitsche|eignet sich besonders gut, um ungezogene Igel|eine Klippe hinunter zu treiben.|Angriff: Alles vor dem Igel schlagen 04:23=Wenn man nichts mehr zu verlieren hat …|Opfere deinen Igel, indem du ihn in eine|festgelegte Richtung losstürmen lässt.|Er wird alles auf dem Weg treffen und am|Ende selbst explodieren.|Angriff: Tödlichen Angriff starten -04:24=Alles Gute! Schick diesen Kuchen auf den Weg,|damit er deinen lieben Feinden eine explosive|Party beschert. Die Torte überwindet fast jedes|Terrain, verliert dabei aber an Laufzeit.|Angriff: Torte losschicken explodieren lassen +04:24=Alles Gute! Schick diesen Kuchen auf den Weg,|damit er deinen lieben Feinden eine explosive|Party beschert. Die Torte überwindet fast jedes|Terrain, verliert dabei aber an Laufzeit.|Angriff: Torte losschicken / explodieren lassen 04:25=Benutze diese Verkleidung, um einen Feind blind|vor Liebe in deine Richtung (und damit in einen|Abgrund oder ähnliches) springen zu lassen.|Angriff: Verkleiden und verführen -04:26=Wirf diese saftige Wassermelone auf deine Feinde.|Sobald die Zeit abgelaufen ist, wird sie in|einzelne und explosive Stücke zerspringen.|Angriff: Halten, um mit mehr Kraft zu werfen -04:27=Entfessle das Höllenfeuer und umgebe deine|Widersacher damit, indem du diesen teuflischen|Sprengsatz gegen sie einsetzt. Komm ihr aber|nicht zu nahe, denn die Flammen könnten|länger bestehen bleiben.|Angriff: Halten, um mit mehr Kraft zu werfen +04:26=Wirf diese saftige (und sprunghafte) Wassermelone auf|deine Feinde. Sobald die Zeit abgelaufen ist, wird|sie in einzelne und explosive Stücke zerspringen.|1-5: Zeitzünder einstellen|Angriff: Halten, um mit mehr Kraft zu werfen +04:27=Entfessle das Höllenfeuer und umgebe deine|Widersacher damit, indem du diesen teuflischen|Sprengsatz gegen sie einsetzt. Komm ihm aber|nicht zu nahe, denn die Flammen könnten|länger bestehen bleiben.|Angriff: Halten, um mit mehr Kraft zu werfen 04:28=Kurz nach dem Start wird diese Rakete beginnen,|sich durch soliden Grund zu graben. Sobald sie|wieder austritt oder der Zeitzünder abläuft,|wird sie explodieren.|Angriff: Halten, um mit mehr Kraft zu feuern -04:29=Das ist nichts für kleine Kinder! Die Ballpistole|feuert Tonnen kleiner farbiger Bälle, die mit|Sprengstoff gefüllt sind.|Angriff: Mit voller Kraft feuern|Hoch/Runter: Im Feuern zielen +04:29=Das ist nichts für kleine Kinder! Die Ballkanone|feuert Tonnen kleiner farbiger Bälle, die mit|Sprengstoff gefüllt sind.|Angriff: Losballern|Hoch/Runter: Weiterzielen 04:30=Rufe ein Flugzeug, um ein Areal gezielt mit|tödlichem Napalm einzudecken. Gut gezielt|lassen sich so große Teile der Karte auslöschen.|Links/Rechts: Angriffsrichtung wählen|Cursor: Zielgebiet wählen und Angriff starten -04:31=Das Funkflugzeug kann Kisten einsammeln und weit|entfernte Igel angreifen. Steuere es direkt in|ein Opfer oder wirf erst einige Bomben ab.|Angriff: Flugzeug starten und Bomben abwerfen|Weiter Sprung: "Ritt der Walküren"|Hoch/Runter: Flugzeug lenken +04:31=Das Funkflugzeug kann Kisten einsammeln und weit|entfernte Igel angreifen. Steuere es direkt in|ein Opfer oder wirf erst einige Bomben ab.|Angriff: Flugzeug starten und Bomben abwerfen|Weitsprung: »Ritt der Walküren«|Links/Rechts: Flugzeug lenken 04:32=Niedrige Schwerkraft ist effektiver als jede|Diät! Springe höher und weiter oder lass|einfach deine Gegner noch weiter fliegen.|Angriff: Aktivieren -04:33=Manchmal muss es eben doch ein bisschen|mehr sein …|Angreifen: Aktivieren -04:34=Can’t touch me!|Angreifen: Aktivieren -04:35=Manchmal vergeht die Zeit einfach zu schnell.|Schnapp dir einige zusätzliche Sekunden, um|deinen Angriff abzuschließen.|Angriff: Aktivieren +04:33=Manchmal muss es eben doch ein bisschen|mehr sein … Erhöhe den verursachten Schaden|um 50% für den Rest des Zuges.|Angriff: Aktivieren +04:34=Dies macht dich immun gegenüber Schaden für den Rest|des Zuges. Aber sei nicht zu übermütig, denn du könntest|immer noch ertrinken.|Angriff: Aktivieren +04:35=Manchmal vergeht die Zeit einfach zu schnell.|Schnapp dir 30 zusätzliche Sekunden, um|deinen Angriff abzuschließen.|Angriff: Aktivieren 04:36=Nun, manchmal trifft man einfach nicht. In solchen|Fällen kann die moderne Technik natürlich nachhelfen.|Angriff: Aktivieren -04:37=Fürchte nicht das Tageslicht! Die Wirkung hält|nur eine Runde an, aber sie erlaubt es deinem|Igel, den Schaden, den er direkt verursacht|als Leben zu absorbieren.|Angreifen: Aktivieren -04:38=Das Scharfschützengewehr kann die vernichtendste|Waffe im gesamten Arsenal sein, allerdings ist|es auf kurze Distanz sehr ineffektiv. Der|verursachte Schaden nimmt mit der Distanz zu.|Angriff: Feuern (mehrfach) -04:39=Fliege mit der fliegenden Untertasse in andere|Teile der Karte. Sie ist schwer zu beherrschen,|bringt dich aber an so gut wie jeden Ort.|Angriff: Aktivieren|Hoch/Links/Rechts: Beschleunigen|Weiter Sprung: Waffe benutzen +04:37=Fürchte nicht das Tageslicht! Die Wirkung hält|nur eine Runde an, aber sie erlaubt es deinem|Igel, 80% des Schadens, den andere Igel während|seines Zuges erleiden, als Leben zu absorbieren.|Angriff: Aktivieren +04:38=Das Scharfschützengewehr kann die vernichtendste|Waffe im gesamten Arsenal sein, allerdings ist|sie auf kurze Distanz sehr ineffektiv. Der|verursachte Schaden nimmt mit der Distanz zu.|Das Zielen ist schwierig, und du musst deine|Stellung halten, sobald die Waffe aktiviert wurde.|Angriff: Zielvisier aktivieren, dann feuern (zwei mal)|Links/Rechts: Umdrehen (zwischen Schüssen) +04:39=Fliege mit der fliegenden Untertasse in andere|Teile der Karte. Sie ist schwer zu beherrschen,|bringt dich aber an so gut wie jeden Ort.|Angriff: Aktivieren/Deaktivieren|Hoch/Links/Rechts: Einmalig in eine Richtung beschleunigen|Weitsprung: Waffe fallen lassen|Genaues Zielen + Weitsprung: Waffe in Zielrichtung feuern|Genaues Zielen + Hoch/Runter: Zielen 04:40=Entzünde einen Teil der Landschaft oder auch etwas|mehr mit dieser (schon bald) brennenden Flüssigkeit.|Angriff: Halten, um mit mehr Kraft zu werfen -04:41=Der Beweis, dass die Natur sogar die fliegende|Untertasse übertreffen könnte. Birdy kann|deinen Igel herumtragen und zudem Eier auf|deine Feinde fallen lassen.|Angriff: Aktivieren und Eier fallen lassen|Hoch/Links/Rechts: In eine Richtung flattern -04:42=Das tragbare Portal Device ermöglicht es dir,|dich, deine Feinde oder Waffen direkt zwischen|zwei Punkten auf der Karte zu|teleportieren.|Benutze es weise und deine Kampagne wird ein …|RIESENERFOLG!|Angriff: Öffnet ein Portal|Wechsel: Wechsle die Portalfarbe -04:43=Lass dein musikalisches Debüt einschlagen wie eine Bombe!|Lass ein Piano vom Himmel fallen, aber pass auf …|jemand muss es spielen und das könnte dich |dein Leben kosten!|Cursor: Zielgebiet wählen und Angriff starten|F1-F9: Spiel das Piano -04:44=Das ist nicht nur Käse, das ist biologische Kriegsführung!|Er wird nicht viel Schaden verursachen, sobald der Zünder|abgelaufen ist, aber er wird garantiert jeden in der Nähe|vergiften!|1-5: Zeitzünder einstellen|Angriff: Halten, um mit mehr Kraft zu werfen -04:45=All die Physikstunden haben sich endlich|bezahlt gemacht: Entfessle eine zerstörerische Sinuswelle|gegen deine Feinde.|Pass auf, die Waffe erzeugt einen ordentlichen Rückstoß.|(Diese Waffe ist unvollständig)|Angriff: Sinuswellen erzeugen -04:46=Brutzle deine Feinde mit fließenden Flammen.|Herzerwärmend!|Angriff: Aktivieren|Hoch/Runter: Im Feuern zielen|Links/Rechts: Durchfluss ändern -04:47=Verdopple den Spaß mit zwei spitzigen, schicken, klebrigen Minen.|Löse eine Kettenreaktion aus oder beschütze dich (oder beides).|Angriff: Halten, um mit mehr Kraft zu feuern (zweimal) -04:48=Warum sind Maulwürfe verhasst? Einen|Igel in den Boden zu stampfen kann sehr lustig sein!|Ein guter Treffer des Hammers wird ein Drittel|der Lebenspunkte eines Igels abziehen und ihn|im Boden versenken.|Angriff: Aktivieren -04:49=Hol deine Freunde zurück!|Aber pass auf, dass du keine Feinde beschwörst.|Angriff: Gedrückt halten, um Igel langsam wiederauferstehen zu lassen.|Hoch: Beschleunige Totenbeschwörung -04:50=Verstecken sich Feinde im Untergrund?|Grabe sie aus mit dem Bohr-Luftangriff!|Der Zeitzünder bestimmt wie tief dieser graben wird. -04:51=Wirf mit Dreck um dich!|Schmerzt ein wenig und schubst Igel weg. +04:41=Der Beweis, dass die Natur sogar die fliegende|Untertasse übertreffen könnte. Vogli kann|deinen Igel herumtragen und zudem faule Eier|auf deine Feinde fallen lassen, um sie zu vergiften.|Angriff: Aktivieren und Eier fallen lassen|Hoch/Links/Rechts: In eine Richtung flattern +04:42=Das tragbare Portalgerät ermöglicht es dir,|dich, deine Feinde oder Waffen direkt zwischen|zwei Punkten auf der Karte zu teleportieren.|Benutze es weise und deine Kampagne wird ein …|RIESENERFOLG!|Haftungsausschluss. Funktioniert nicht auf Gummi.|Angriff: Öffnet ein Portal|Wechseln: Wechselt die Portalfarbe +04:43=Lass dein musikalisches Debüt einschlagen wie eine Bombe!|Lass ein mächtiges Piano vom Himmel fallen, das alles|im Weg zerstampfen wird, aber beachte:|Dein Igel muss sein Leben geben, um das Piano zu spielen.|Cursor: Zielgebiet wählen und Angriff starten|F1–F9: Das Piano spielen +04:44=Das ist nicht nur Käse, das ist biologische Kriegsführung!|Er wird nicht viel Schaden verursachen, sobald der Zünder|abgelaufen ist, aber er wird garantiert jeden in der Nähe|vergiften!|1–5: Zeitzünder einstellen|Genaues Zielen + 1-5: Sprungkraft einstellen|Angriff: Halten, um mit mehr Kraft zu werfen +04:45=All die Physikstunden haben sich endlich bezahlt gemacht!|Entfessle eine zerstörerische Sinuswelle, die sich durch|das Gelände (und deine Feinde) brennen wird.|Pass auf, die Waffe erzeugt einen ordentlichen Rückstoß.|Angriff: Feuern +04:46=Brutzle deine Feinde mit fließenden Flammen.|Herzerwärmend!|Angriff: Aktivieren|Hoch/Runter: Beim Feuern zielen|Links/Rechts: Durchfluss ändern +04:47=Verdopple den Spaß mit zwei spitzigen, schicken, klebrigen Minen.|Löse eine Kettenreaktion aus oder beschütze dich (oder beides).|Angriff: Halten, um mit mehr Kraft zu feuern (zwei mal) +04:48=Warum sind Maulwürfe verhasst? Igel, Minen|oder Fässer in den Boden zu stampfen, kann|auch sehr lustig sein! Ein guter Treffer des Hammers wird|ein Drittel (mit Zusatzschaden sogar die Hälfte) der|Lebenspunkte eines Igels abziehen und ihn im Boden|versenken.|Angriff: Zuschlagen +04:49=Opfere deine Gesundheit, um deine Freunde zurückzuholen!|Aber pass auf, dass du keine Feinde beschwörst.|Angriff: Gedrückt halten, um Igel langsam wiederauferstehen zu lassen.|Hoch: Totenbeschwörung beschleunigen +04:50=Verstecken sich Feinde im Untergrund?|Grabe sie aus mit dem Bohr-Luftangriff!|Der Zeitzünder bestimmt, wie tief dieser graben wird.|Links/Rechts: Angriffsrichtung wählen|1-5: Zeitzünder einstellen|Cursor: Zielgebiet wählen und Angriff starten +04:51=Wirf mit Dreck um dich! Der Schlammball|schubst Igel und andere Dinge weg,|aber richtet keinen Schaden an.|Angriff: Halten, um mit mehr Kraft zu werfen 04:52=NICHT IN VERWENDUNG -04:53=Unternimm eine Reise durch Zeit und Raum,|während du deine Kameraden alleine am Schlachtfeld zurücklässt.|Sei darauf vorbereitet jederzeit wieder zurückzukommen,|oder auf Sudden Death wenn sie alle besiegt wurden.|Disclaimer: Nicht funktionstüchtig wenn in Sudden Death,|wenn du alleine bist - oder der König. -;04:54=IN ARBEIT -04:54=Versprühe einen Strahl klebriger Flocken.|Baue Brücken, begrabe Gegner, versiegle Tunnel.|Pass auf, dass du selbst nichts abbekommst! +04:53=Unternimm eine Reise durch Zeit und Raum,|während du deine Kameraden alleine am Schlachtfeld zurücklässt.|Sei darauf vorbereitet, jederzeit wieder zurückzukommen,|oder auf Sudden Death, oder wenn sie alle besiegt wurden.|Haftungsausschluss. Nicht funktionstüchtig, wenn in Sudden Death,|wenn du alleine bist – oder der König.|Angriff: Aktivieren +04:54=Versprühe einen Strahl klebriger Flocken.|Baue Brücken, begrabe Gegner, versiegle Tunnel.|Pass auf, dass du selbst nichts abbekommst!|Angriff: Aktivieren|Hoch/Runter: Beim Feuern zielen|Links/Rechts: Schussweite einstellen +04:55=Hol die Eiszeit zurück! Friere Igel ein,|mach den Boden rutschig oder|rette dich selbst vor dem Ertrinken,|indem du das Wasser einfrierst.|Angriff: Aktivieren/Deaktivieren|Hoch/Runter: Beim Feuern zielen +04:56=Du kannst zwei Hackebeile auf deinen Feind schleudern,|Passagen und Tunnel blockieren, und sie sogar zum Klettern benutzen!|Sei vorsichtig! Es ist gefährlich, mit Messern zu spielen.|Angriff: Gedrückt halten, um mit mehr Schwung zu werfen (zwei mal) +04:57=Bau einen SEHR elastischen Balken aus Gummi,|von dem Igel und andere Sachen abprallen,|ohne Fallschaden zu nehmen.|Links/Rechts: Ausrichtung des Gummis wählen|Cursor: Gummi platzieren +04:58=Diese Annäherungsmine wird frei in der Luft schweben und|verfolgt törichte Igel, die dumm genug sind, ihr zu nahe zu|kommen. Allerdings ist ihre Explosion schwächer als|die der Landmine.|Angriff: Halten, um mit mehr Kraft zu werfen ; Game goal strings 05:00=Spielmodifikationen @@ -573,21 +656,20 @@ 05:02=Festungen: Verteidige deine Festung; vertreibe deine Feinde! 05:03=Niedrige Schwerkraft: Pass auf, wo du hintrittst 05:04=Unverwundbarkeit: Igel sind (so gut wie) unkaputtbar -05:05=Vampirismus: Igel heilen sich um den von ihnen verursachten Schaden +05:05=Vampirismus: Igel heilen sich um 80% von dem von ihnen verursachten Schaden 05:06=Karma: Igel leiden an dem von ihnen verursachten Schaden -05:07=Schützt den König: Beschütze ihn um jeden Preis!|König platzieren: Wähle einen sicheren Startpunkt für deinen König +05:07=Schützt den König: Lass deinen König nicht sterben!|König platzieren: Wähle einen sicheren Startpunkt für deinen König 05:08=Igel platzieren: Wähle vor dem Spielstart die Positionen deiner Igel 05:09=Artillerie: Deine Igel können nicht laufen -05:10=Unzerstörbares Terrain: Explosionen zerstören den Boden nicht +05:10=Unzerstörbares Terrain: Die meisten Waffen zerstören das Gelände nicht 05:11=Gemeinsames Arsenal: Alle Teams gleicher Farbe teilen sich ihr Arsenal 05:12=Minenzünder: Minen explodieren nach %1 Sekunde(n) 05:13=Minenzünder: Minen explodieren sofort -05:14=Minenzünder: Minen explodieren nach 0-3 Sekunden +05:14=Minenzünder: Minen explodieren nach 0–5 Sekunden 05:15=Prozentualer Schaden: Alle Waffen verursachen %1 % Schaden -05:16=Lebenspunkter aller Igel wird am Ende jeder Runde zurückgesetzt +05:16=Alle Igel werden am Ende der Zuges bis zum Anfangswert geheilt 05:17=Computergesteuerte Igel erscheinen nach dem Tod wieder 05:18=Unbegrenzte Attacken 05:19=Waffen werden am Ende jedes Zuges zurückgesetzt 05:20=Igel teilen Waffen nicht untereinander 05:21=Tag Team: Teams gleicher Farbe kommen nacheinander dran und teilen sich ihre Zugzeit. - diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/en.txt --- a/share/hedgewars/Data/Locale/en.txt Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/en.txt Tue Nov 10 20:43:13 2015 +0100 @@ -1,11 +1,11 @@ ; English locale 00:00=Grenade -00:01=ClusterBomb +00:01=Cluster Bomb 00:02=Bazooka 00:03=Homing Bee 00:04=Shotgun -00:05=PickHammer +00:05=Pick Hammer 00:06=Skip 00:07=Rope 00:08=Mine @@ -53,12 +53,13 @@ 00:50=Drill Strike 00:51=Mudball 00:52=No weapon selected -00:53=TimeBox +00:53=Time Box ; 00:54=Structure 00:54=Land Spray 00:55=Freezer 00:56=Cleaver 00:57=Rubber +00:58=Air Mine 01:00=Let's fight! 01:01=Round draw @@ -69,7 +70,7 @@ 01:06=Sudden Death! 01:07=%1 remaining 01:08=Fuel -01:09=Synchronizing... +01:09=Synchronizing ... 01:10=Using this utility won't end your turn! 01:11=This weapon or utility is not yet available! 01:12=Last round till Sudden Death! @@ -83,6 +84,9 @@ 01:20=%1 Bounce 01:21=Audio Muted 01:22=AFK mode +01:23=Auto Camera Off +01:24=Auto Camera On +01:25=Press the target button to mark the target ; Event messages ; Hog (%1) died @@ -100,7 +104,6 @@ 02:00=%1 has timed out! 02:00=%1 says peace out! 02:00=%1 will be fondly remembered! -02:00=%1 has an aneurysm! 02:00=%1 leaves behind a wife and child 02:00=%1 has launched his last bazooka 02:00=%1 has tossed his last grenade @@ -115,8 +118,8 @@ 02:00=%1 has gone to play a better game 02:00=%1 has ragequit life 02:00=%1 fails -02:00=Poor poor %1... -02:00=%1 prefers wormux +02:00=Poor, poor %1 ... +02:00=%1 prefers WarMUX 02:00=%1 has been blocking shots with his face 02:00=%1 is a hero amongst me...err...hogs 02:00=%1 finds his place in Valhalla @@ -203,7 +206,7 @@ 02:02=Let's go! 02:02=Let's rock! 02:02=Let's jam! -02:02=It's beginning... +02:02=It's beginning ... 02:02=This is the start of something big 02:02=Welcome to Hedgewars 02:02=Welcome to the front lines @@ -259,7 +262,7 @@ 02:05=Medic! 02:05=First aid from the skies! 02:05=A health pack for you -02:05=Good health... in box form! +02:05=Good health ... in box form! 02:05=The doctor calls 02:05=Fresh band-aids! 02:05=This will make you feel better @@ -268,7 +271,7 @@ 02:05=Grab it 02:05=A healthy snack 02:05=A remedy to pain -02:05=Correct Dosage: as many as you can find! +02:05=Correct dosage: as many as you can find! 02:05=Urgent delivery 02:05=Supplies! @@ -299,7 +302,7 @@ ; New utility crate 02:07=Tooltime! -02:07=This could come in handy... +02:07=This could come in handy ... 02:07=Utilities! 02:07=Utilise this box 02:07=Watch out below @@ -311,7 +314,7 @@ 02:07=You might need this ; Hog (%1) skips his turn -02:08=%1 is sooo boring... +02:08=%1 is sooo boring ... 02:08=%1 couldn't be bothered 02:08=%1 is one lazy hog 02:08=%1 is thoughtless @@ -396,56 +399,56 @@ 02:11=%1 has to go ; Weapon Categories -03:00=Timed Grenade -03:01=Timed Grenade -03:02=Ballistic Weapon -03:03=Guided Weapon +03:00=Timed grenade +03:01=Timed grenade +03:02=Ballistic weapon +03:03=Guided weapon 03:04=Gun (multiple shots) -03:05=Digging Tool +03:05=Digging tool 03:06=Action -03:07=Transport Utility -03:08=Proximity Bomb +03:07=Transport utility +03:08=Proximity bomb 03:09=Gun (multiple shots) 03:10=BOOM! 03:11=Bonk! -03:12=Martial Arts +03:12=Martial arts 03:13=UNUSED -03:14=Transport Utility -03:15=Airborne Attack -03:16=Airborne Attack -03:17=Digging Tool +03:14=Transport utility +03:15=Airborne attack +03:16=Airborne attack +03:17=Digging tool 03:18=Utility -03:19=Transport Utility +03:19=Transport utility 03:20=Action -03:21=Ballistic Weapon +03:21=Ballistic weapon 03:22=Call me Indiana! 03:23=(Really) Martial Arts 03:24=The cake is NOT a lie! -03:25=Costume Kit -03:26=Juicy Grenade -03:27=Fiery Grenade -03:28=Ballistic Weapon -03:29=Ballistic Weapon -03:30=Airborne Attack -03:31=Remote Controlled Bomb -03:32=Temporary Effect -03:33=Temporary Effect -03:34=Temporary Effect -03:35=Temporary Effect -03:36=Temporary Effect -03:37=Temporary Effect +03:25=Costume kit +03:26=Juicy grenade +03:27=Fiery grenade +03:28=Ballistic weapon +03:29=Ballistic weapon +03:30=Airborne attack +03:31=Remote-controlled bomb +03:32=Temporary effect +03:33=Temporary effect +03:34=Temporary effect +03:35=Temporary effect +03:36=Temporary effect +03:37=Temporary effect 03:38=Gun (multiple shots) -03:39=Transport Utility -03:40=Incinerating Grenade +03:39=Transport utility +03:40=Incinerating grenade 03:41=Huge fan of Squawks -03:42=I'm making a note here... +03:42=I'm making a note here ... ; the misspelled "Beethoven" is intentional (-> to beat) 03:43=Performing Beathoven's deadly sonata 03:44=Best before: 1923 03:45=The power of science -03:46=Hot Hot Hot! +03:46=Hot, hot, hot! 03:47=Stick these somewhere useful! -03:48=It's Hammer time! +03:48=It's Hammer Time! 03:49=Bring back the dead TO hell! 03:50=Moles fan 03:51=Found on the ground @@ -455,65 +458,69 @@ 03:54=Utility 03:55=It doesn't get cooler than this! 03:56=Please use or misuse +03:57=Utility +03:58=Floating proximity bomb ; Weapon Descriptions (use | as line breaks) -04:00=Attack your enemies using a simple grenade.|It will explode once its timer reaches zero.|1-5: Set grenade's timer|Attack: Hold to throw with more power -04:01=Attack your enemies using a cluster bomb.|It will split into smaller bombs once its timer|reaches zero.|1-5: Set grenade's timer|Attack: Hold to throw with more power +04:00=Attack your enemies using a simple grenade.|It will explode once its timer reaches zero.|1-5: Set grenade's timer|Precise + 1-5: Set bounce strength|Attack: Hold to throw with more power +04:01=Attack your enemies using a cluster bomb.|It will split into smaller bombs once its timer|reaches zero.|1-5: Set cluster bomb's timer|Precise + 1-5: Set bounce strength|Attack: Hold to throw with more power 04:02=Attack your enemies using a ballistic projectile|that might be influenced by wind.|Attack: Hold to shoot with more power 04:03=Launch an explosive bee that will lock on|the selected target. Don't shoot with full power|to improve its precision.|Cursor: Pick target|Attack: Hold to shoot with more power 04:04=Attack your enemy using a shotgun with two shots.|Thanks to its spread you don't need direct hits|to harm your opponents.|Attack: Shoot (multiple times) -04:05=Move underground! Use the pickhammer to drill|a hole into the ground and reach other areas.|Attack: Start or stop digging +04:05=Move underground! Use the pick hammer to drill|a hole into the ground and reach other areas.|Attack: Start or stop digging|Left/Right: Move while drilling 04:06=Bored? No way to attack? Save your ammo?|No problem! Just skip your turn, coward!|Attack: Skip your turn without fighting -04:07=Bridge huge distances using timed shots with the|rope. Use your momentum to slide into other hogs|or drop grenades and other weapons on them.|Attack: Shoot or release the rope|Long Jump: Drop grenades or similar weapons -04:08=Keep your enemies away by dropping a mine in|narrow passages or right below their feet. Be|sure to retreat before you trigger it yourself!|Attack: Drop mine next to your feet +04:07=Bridge huge distances using timed shots with the|rope. Use your momentum to slide into other hogs|or drop grenades and other weapons on them.|Attack: Shoot or release the rope|Up/Down: Retract/Extend rope|Long Jump: Drop grenades or similar weapons +04:08=Keep your enemies away by dropping a mine in|narrow passages or right below their feet. Be|sure to retreat before you trigger it yourself!|Attack: Drop mine next to your feet|Precise + 1-5: Set mine's bounce strength 04:09=Not sure about your aiming? Use the Desert|Eagle to attack using up to four shots.|Attack: Shoot (multiple times) 04:10=Brute force is always an option. Drop this classic|explosive next to your enemies and retreat.|Attack: Drop dynamite next to your feet 04:11=Get rid of enemy hogs by batting them over|the map borders or into water. Or how about|knocking some mines to your friends?|Attack: Bat everything in front of you 04:12=Get close and personal to unleash the power of|this almost deadly martial arts technique.|Attack: Perform the amazing Shoryuken. 04:13=UNUSED -04:14=Fear of heights? Better grab a parachute.|It will unfold once|you fall too far and|save your hog from taking fall damage.|Attack: Unfold the parachute|Long Jump: Drop grenades or similar weapons +04:14=Fear of heights? Better grab a parachute.|It will unfold automatically once|you fall too far and|save your hog from taking fall damage.|Attack: Unfold or deactivate the parachute manually|Left/Right/Up/Down: Control your flight|Long Jump: Drop grenades or similar weapons 04:15=Call in an airplane to attack your enemies|using a bombing run.|Left/Right: Determine attack direction|Cursor: Select target region 04:16=Call in an airplane to drop several mines|in the target area.|Left/Right: Determine attack direction|Cursor: Select target region -04:17=Need shelter? Use the blow torch to dig|a tunnel into solid ground granting you|cover.|Attack: Start or stop digging +04:17=Need shelter? Use the blow torch to dig|a tunnel into solid ground granting you|cover.|Attack: Start or stop digging|Up/down: Change digging direction 04:18=Need additional protection or want to pass|unpassable ground? Place some girders as you|like.|Left/Right: Select girder to place|Cursor: Place girder in a valid position -04:19=Used at the right moment teleportation can|be more powerful than almost all weapons as|it allows you to save hogs from dangerous|situations within seconds.|Cursor: Select target region -04:20=Allows you to play the current turn with|a different hog.|Attack: Enable switching hogs -04:21=Shoot a grenade-like projectile that will|release multiple bombs upon impact.|Attack: Shoot at full power +04:19=Used at the right moment teleportation can|be more powerful than almost all weapons as|it allows you to save hogs from dangerous|situations within seconds.|Cursor: Select target region|Left/Right: Choose facing direction +04:20=Allows you to play the current turn with|a different hog.|Attack: Enable switching hogs|Switch: Select next hog|Precise + Switch: Select previous hog +04:21=Shoot a projectile that will release|multiple clusters upon impact. The|clusters are hurled backwards and are|more dangerous than the main projectile.|Attack: Shoot at full power 04:22=Not just for Indiana Jones! The whip is a|useful weapon in many situations. Especially|when you'd like to shove someone off a cliff.|Attack: Strike everything in front of you -04:23=If you have nothing to lose, this might be|quite handy. Sacrifice your hog by launching|him into a specific direction hurting everything|on his way and exploding at the end.|Attack: Launch the devastating and deadly attack +04:23=If you have nothing to lose, this might be|quite handy. Sacrifice your hog by launching|it into a specific direction hurting everything|on his way and exploding at the end.|Attack: Launch the devastating and deadly attack 04:24=Happy Birthday! Launch this cake, let it walk right|next to your enemies and let them have an explosive|party. The cake is able to pass almost all terrain|but he might detonate earlier this way.|Attack: Start the cake or let it stop and explode 04:25=Use this disguise kit to get your enemies to jump|towards your hog (and into some gap or hole).|Attack: Use the kit and try to seduce another hog -04:26=Throw this juicy watermelon at your enemies. Once|the timer expires, it will split into several|explosive pieces.|1-5: Set watermelon's timer|Attack: Hold to shoot with more power +04:26=Throw this juicy (and bouncy) watermelon at|your enemies. Once the timer expires, it will|split into several explosive pieces.|1-5: Set watermelon's timer|Attack: Hold to shoot with more power 04:27=Let hellfire rain onto your opponents by using|this fiendish explosive. Don't get too close to|the explosion as smaller fires might last longer.|Attack: Hold to shoot with more power 04:28=Short time after launching this rocket, it will|start drilling through solid ground and explode|once its fuse is triggered or it resurfaces again.|Attack: Hold to shoot with more power 04:29=This is nothing for small kids! The ball gun fires|tons of small colored balls filled with explosives.|Attack: Shoot at full power|Up/Down: Continue aiming 04:30=Call in an airplane to launch a powerful napalm|strike. With proper aiming this attack can eradicate|huge parts of landscape including unlucky hogs|sitting there.|Left/Right: Determine attack direction|Cursor: Select target region 04:31=The RC plane is the ideal weapon to collect crates or|attack far away hogs. Either steer it into enemies or|drop some bombs first.|Attack: Launch the plane or drop bombs|Long Jump: Let the valkyries ride into battle|Left/Right: Steer the plane 04:32=Low gravity is more effective than any diet! Jump|higher and over greater distances or let your enemies|fly even further.|Attack: Activate -04:33=Sometimes you just need that little extra boost to|deal some more damage.|Attack: Activate -04:34=Can't touch me!|Attack: Activate -04:35=Sometimes time's running too fast. Grab some extra|seconds to finish your attack.|Attack: Activate +04:33=Sometimes you just need that little extra boost to|deal some more damage. Activating this increases|the damage dealt by 50% for the rest of the turn.|Attack: Activate +04:34=Makes you immune to damage for the|rest of your turn. But don't be too|cocky, you could still drown.|Attack: Activate +04:35=Sometimes time's running too fast.|Grab 30 extra seconds to finish your attack.|Attack: Activate 04:36=Well, sometimes you're just too bad in aiming. Get|some assistance using modern day technology.|Attack: Activate -04:37=Don't fear the daylight. It will just last one turn|but will enable you to absorb the damage you do to|other hogs.|Attack: Activate -04:38=The sniper rifle can be the most devastating weapon|in your whole arsenal, however it's very ineffective|at close quarters. The damage dealt increases with|the distance to its target.|Attack: Shoot (twice) -04:39=Fly to other parts of the map using the flying|saucer. This hard to master utility can|take you to almost any position on the battlefield.|Attack: Activate|Up/Left/Right: Apply force in one direction|Long Jump: Drop grenades or similar weapons +04:37=Don't fear the daylight. It will just last one turn|but will enable you to absorb 80% of the damage|dealt to other hogs.|Attack: Activate +04:38=The sniper rifle can be the most devastating weapon|in your whole arsenal, however it's very ineffective|at close quarters. The damage dealt increases with|the distance to its target. Aiming is difficult, so as long this|weapon is activated, you have to hold your position.|Attack: Activate built-in laser sight, then fire (twice)|Left/Right: Turn around (between shots) +04:39=Fly to other parts of the map using the flying|saucer. This hard to master utility can|take you to almost any position on the battlefield.|Attack: Activate/Deactivate|Up/Left/Right: Apply a short boost into one direction|Long Jump: Drop grenades or similar weapons|Precise + Long Jump: Launch weapon to crosshair|Precise + Up/Down: Adjust aim 04:40=Set some ground on fire using this bottle filled|with (soon to be) burning liquid.|Attack: Hold to shoot with more power -04:41=The evidence nature might even top the flying|saucer. Birdy can carry your hog around and|drop eggs on your enemies!|Be quick, as using Birdy eats into your turn|time!|Attack: Activate and drop eggs|Up/Left/Right: Flap in one direction -04:42=This portable portal device is capable|of instantly transporting you, your enemies,|or your weaponry between two points on the|terrain.|Use it wisely and your campaign will be a...|HUGE SUCCESS!|Attack: Shoot a portal|Switch: Cycle portal colours -04:43=Make your musical debut an explosive success!|Drop a piano from the heavens, but beware...|someone needs to play it, and that may cost you|your life!|Cursor: Select target region|F1-F9: Play the piano -04:44=This isn't just cheese, it's biological warfare!|It won't cause an huge amount of damage once|the timer reaches zero but it will definitely|poison anyone unlucky to touch the smell!|1-5: Set grenade's timer|Attack: Hold to throw with more power -04:45=All those physics classes have finally|paid off, launch a devastating Sine|wave at your foes.|Watch out, this weapon packs quite a kick. (This weapon is incomplete)|Attack: Shoot +04:41=The evidence nature might even top the flying|saucer. Birdy can carry your hog around and|drop eggs on your enemies to poison them!|Be quick, as using Birdy eats into your turn|time!|Attack: Activate and drop eggs|Up/Left/Right: Flap in one direction +04:42=This portable portal device is capable|of instantly transporting you, your enemies,|or your weaponry between two points on the|terrain.|Use it wisely and your campaign will be a ...|HUGE SUCCESS!|Disclaimer. Does not work on rubber bands.|Attack: Shoot a portal|Switch: Change portal colour +04:43=Make your musical debut an explosive success!|Drop a mighty piano from the heavens,|stomping everything in its path, but beware:|Your hog must be sacrificed to play the piano.|Cursor: Select target region|F1-F9: Play the piano +04:44=This isn't just cheese, it's biological warfare!|It won't cause an huge amount of damage once|the timer reaches zero but it will definitely|poison anyone unlucky to touch the smell!|1-5: Set timer|Precise + 1-5: Set bounce strength|Attack: Hold to throw with more power +04:45=All those physics classes have finally paid off!|Launch a devastating sine wave which burns itself|through terrain.|Watch out, this weapon has a strong knockback.|Attack: Shoot 04:46=Cover your foes with sizzling liquid flame.|Heartwarming!|Attack: Activate|Up/Down: Continue aiming|Left/Right: Modify spitting power 04:47=Double the fun with two spiky, sneaky, sticky mines.|Set up a chain reaction or defend yourself (or both!)|Attack: Hold to shoot with more power (twice) -04:48=Why should the moles get all the abuse?|Wacking a hog can be just as fun! A good|blow from this hammer will shave off one|third of a hog's health and plunge them|underground.|Attack: Activate -04:49=Resurrect your friends!|But beware that this also resurrects your foes.|Attack: Keep attack pressed to resurrect slowly|Up: Accelerate resurrection -04:50=Is someone hiding underground?|Dig them out with a drill strike!|Timer controls how far it will dig.|Left/Right: Determine attack direction|Cursor: Select target region -04:51=Get in a free shot by hurling a ball of mud.|Stings a bit, and knocks hogs back.|Attack: Hold to shoot with more power +04:48=Why should the moles get all the abuse? Wacking|a hog (or mines, or barrels) can be just as fun!|A good blow from this hammer will shave off|one third of a hog's health (or one half with|Extra Damage) and plunge them underground.|Attack: Activate +04:49=Sacrifice your health to resurrect your friends!|But beware that this also resurrects your foes.|Attack: Keep attack pressed to resurrect slowly|Up: Accelerate resurrection +04:50=Is someone hiding underground?|Dig them out with a drill strike!|Timer controls how far it will dig.|Left/Right: Determine attack direction|1-5: Set timer|Cursor: Select target region +04:51=Get in a free shot by hurling a ball of mud.|Deals no damage, but knocks hogs and|objects back.|Attack: Hold to shoot with more power 04:52=UNUSED 04:53=Take a trip through time and space,|while leaving your comrades to fight on alone.|Be prepared to return at any time,|or for Sudden Death or if they are all defeated.|Disclaimer. Does not function in Sudden Death,|if you are alone, or if you are a King.|Attack: Activate 04:54=Spray a stream of sticky flakes.|Build bridges, bury enemies, seal off tunnels.|Be careful you don't get any on you!|Attack: Activate|Up/Down: Continue aiming|Left/Right: Modify spitting power -04:55=Bring back the ice-age!|Freeze hedgehogs, make the floor slippery or|save yourself from drowning by freezing the water.|Attack: Shoot +04:55=Bring back the ice-age!|Freeze hedgehogs, make the floor slippery or|save yourself from drowning by freezing the water.|Attack: Activate/Deactivate freezeray|Up/Down: Continue aiming 04:56=You can throw two cleavers at your enemy,|block passages and tunnels and even use them for climbing!|Be careful! Playing with knifes is dangerous.|Attack: Hold to shoot with more power (twice) +04:57=Build a VERY elastic rubber band, from which|hedgehogs and other things bounce off|without taking fall damage.|Left/Right: Change rubber band orientation|Cursor: Place rubber band in a valid position +04:58=This proximity bomb will float freely in the air and follow|hedgehogs careless enouogh to come too close to it.|Its explosion is weaker than that of the land mine, however.|Attack: Hold to shoot with more power ; Game goal strings 05:00=Game Modes @@ -521,7 +528,7 @@ 05:02=Forts: Defend your fortress; vanquish your enemies! 05:03=Low Gravity: Watch your step 05:04=Invulnerability: Hogs are (almost) invulnerable -05:05=Vampirism: Hogs will be healed for the damage dealt +05:05=Vampirism: Hogs will be healed for 80% of the damage dealt 05:06=Karma: Hogs will be damaged for the damage dealt 05:07=Protect the King: Don't let your king die!|Place the King: Pick a protected starting point for your King 05:08=Place Hedgehogs: Place your hogs before the game starts @@ -531,7 +538,7 @@ 05:12=Mine Timers: Mines will detonate after %1 second(s) 05:13=Mine Timers: Mines will detonate instantly 05:14=Mine Timers: Mines will detonate after 0 - 5 seconds -05:15=Damage Modifier: All weapons will do %1% damage +05:15=Damage Modifier: (Almost) all weapons will deal %1% damage 05:16=Health of all hogs is reset on end of turn 05:17=AI hogs respawn on death 05:18=Unlimited Attacks diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/es.lua --- a/share/hedgewars/Data/Locale/es.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/es.lua Tue Nov 10 20:43:13 2015 +0100 @@ -4,6 +4,10 @@ ["..."] = "...", -- ["011101000"] = "", -- A_Classic_Fairytale:dragon -- ["011101001"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:family, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united +-- ["+1 to a Bottom Feeder for killing anyone"] = "", -- Mutant +-- ["+1 to a Mutant for killing anyone"] = "", -- Mutant +-- ["-1 to anyone for a suicide"] = "", -- Mutant +-- ["+2 for becoming a Mutant"] = "", -- Mutant -- ["30 minutes later..."] = "", -- A_Classic_Fairytale:shadow -- ["About a month ago, a cyborg came and told us that you're the cannibals!"] = "", -- A_Classic_Fairytale:enemy ["Accuracy Bonus!"] = "¡Buena puntería!", @@ -13,17 +17,27 @@ -- ["???"] = "", -- A_Classic_Fairytale:backstab -- ["Actually, you aren't worthy of life! Take this..."] = "", -- A_Classic_Fairytale:shadow -- ["A cy-what?"] = "", -- A_Classic_Fairytale:enemy +-- ["Advanced Repositioning Mode"] = "", -- Construction_Mode -- ["Adventurous"] = "", -- A_Classic_Fairytale:journey +-- ["a frenetic Hedgewars mini-game"] = "", -- Frenzy -- ["Africa"] = "", -- Continental_supplies -- ["After Leaks A Lot betrayed his tribe, he joined the cannibals..."] = "", -- A_Classic_Fairytale:first_blood -- ["After the shock caused by the enemy spy, Leaks A Lot and Dense Cloud went hunting to relax."] = "", -- A_Classic_Fairytale:shadow -- ["Again with the 'cannibals' thing!"] = "", -- A_Classic_Fairytale:enemy +-- ["Aggressively removes enemy hedgehogs."] = "", -- Construction_Mode -- ["a Hedgewars challenge"] = "", -- User_Mission_-_RCPlane_Challenge, User_Mission_-_Rope_Knock_Challenge ["a Hedgewars mini-game"] = "un minijuego de Hedgewars", -- Space_Invasion, The_Specialists +-- ["a Hedgewars tag game"] = "", -- Mutant +-- ["AHHh, home sweet home. Made it in %d seconds."] = "", -- ClimbHome ["Aiming Practice"] = "Practica tu puntería", --Bazooka, Shotgun, SniperRifle +-- ["Air Attack"] = "", -- Construction_Mode -- ["A leap in a leap"] = "", -- A_Classic_Fairytale:first_blood -- ["A little gift from the cyborgs"] = "", -- A_Classic_Fairytale:shadow -- ["All gone...everything!"] = "", -- A_Classic_Fairytale:enemy +-- ["Allows free teleportation between other nodes."] = "", -- Construction_Mode +-- ["Allows placement of girders, rubber-bands, mines, sticky mines and barrels."] = "", -- Construction_Mode +-- ["Allows placement of structures."] = "", -- Construction_Mode +-- ["Allows the placement of weapons, utiliites, and health crates."] = "", -- Construction_Mode -- ["All right, we just need to get to the other side of the island!"] = "", -- A_Classic_Fairytale:journey -- ["All walls touched!"] = "", -- WxW ["Ammo Depleted!"] = "¡Munición agotada!", @@ -38,8 +52,11 @@ -- ["And so they discovered that cyborgs weren't invulnerable..."] = "", -- A_Classic_Fairytale:journey -- ["And where's all the weed?"] = "", -- A_Classic_Fairytale:dragon -- ["And you believed me? Oh, god, that's cute!"] = "", -- A_Classic_Fairytale:journey --- ["Anno 1032: [The explosion will make a strong push ~ wide range, wont affect hogs close to the target]"] = "", -- Continental_supplies +-- ["Anno 1032: [The explosion will make a strong push ~ Wide range, wont affect hogs close to the target]"] = "", -- Continental_supplies + -- ["Antarctica"] = "", -- Continental_supplies +-- ["Antarctic summer: - Will give you one girder/mudball and two sineguns/portals every fourth turn."] = "", -- Continental_supplies +-- ["Area"] = "", -- Continental_supplies -- ["Are we there yet?"] = "", -- A_Classic_Fairytale:shadow -- ["Are you accusing me of something?"] = "", -- A_Classic_Fairytale:backstab -- ["Are you saying that many of us have died for your entertainment?"] = "", -- A_Classic_Fairytale:enemy @@ -59,27 +76,35 @@ ["[Backspace]"] = "[Retroceso]", -- ["Backstab"] = "", -- A_Classic_Fairytale:backstab -- ["Bad Team"] = "", -- User_Mission_-_The_Great_Escape +-- ["Ballgun"] = "", -- Construction_Mode ["Bamboo Thicket"] = "Maraña de bambú", ["Barrel Eater!"] = "¡Tragabarriles!", ["Barrel Launcher"] = "Lanzador de barriles", +-- ["Barrel Placement Mode"] = "", -- Construction_Mode +-- ["Baseball Bat"] = "", -- Construction_Mode -- ["Baseballbat"] = "", -- Continental_supplies ["Bat balls at your enemies and|push them into the sea!"] = "¡Batea pelotas contra tus enemigos|y hazlos caer al agua!", ["Bat your opponents through the|baskets and out of the map!"] = "¡Batea a tus enemigos fuera del campo de juego|a través de las canastas laterales!", +-- ["Bazooka"] = "", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 ["Bazooka Training"] = "Entrenamiento con bazuca", -- ["Beep Loopers"] = "", -- A_Classic_Fairytale:queen ["Best laps per team: "] = "Mejores tiempos por equipo: ", ["Best Team Times: "] = "Mejores tiempos del equipo: ", -- ["Beware, though! If you are slow, you die!"] = "", -- A_Classic_Fairytale:dragon +-- ["Bio-Filter"] = "", -- Construction_Mode -- ["Biomechanic Team"] = "", -- A_Classic_Fairytale:family +-- ["Birdy"] = "", -- Construction_Mode -- ["Blender"] = "", -- A_Classic_Fairytale:family -- ["Bloodpie"] = "", -- A_Classic_Fairytale:backstab -- ["Bloodrocutor"] = "", -- A_Classic_Fairytale:shadow -- ["Bloodsucker"] = "", -- A_Classic_Fairytale:shadow ["Bloody Rookies"] = "Reclutas", -- 01#Boot_Camp, User_Mission_-_Dangerous_Ducklings, User_Mission_-_Diver, User_Mission_-_Spooky_Tree +-- ["Blowtorch"] = "", -- Construction_Mode, Frenzy +-- ["Blue Team"] = "", -- User_Mission_-_Dangerous_Ducklings -- ["Bone Jackson"] = "", -- A_Classic_Fairytale:backstab -- ["Bonely"] = "", -- A_Classic_Fairytale:shadow + ["BOOM!"] = "¡BUM!", ["Boom!"] = "¡Bum!", - ["BOOM!"] = "¡BUM!", ["Boss defeated!"] = "¡Jefe derrotado!", ["Boss Slayer!"] = "¡Matajefes!", -- ["Brain Blower"] = "", -- A_Classic_Fairytale:journey @@ -89,6 +114,7 @@ -- ["Brain Teaser"] = "", -- A_Classic_Fairytale:backstab -- ["Brutal Lily"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil -- ["Brutus"] = "", -- A_Classic_Fairytale:backstab +-- ["Build a fortress and destroy your enemy."] = "", -- Construction_Mode ["Build a track and race."] = "Dibuja un recorrido y compite.", -- ["Bullseye"] = "", -- A_Classic_Fairytale:dragon -- ["But it proved to be no easy task!"] = "", -- A_Classic_Fairytale:dragon @@ -99,6 +125,7 @@ -- ["But why would they help us?"] = "", -- A_Classic_Fairytale:backstab -- ["But you're cannibals. It's what you do."] = "", -- A_Classic_Fairytale:enemy -- ["But you said you'd let her go!"] = "", -- A_Classic_Fairytale:journey +-- ["Cake"] = "", -- Construction_Mode -- ["Call me Beep! Well, 'cause I'm such a nice...person!"] = "", -- A_Classic_Fairytale:family -- ["Cannibals"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:first_blood -- ["Cannibal Sentry"] = "", -- A_Classic_Fairytale:journey @@ -108,8 +135,15 @@ -- ["Carol"] = "", -- A_Classic_Fairytale:family -- ["CHALLENGE COMPLETE"] = "", -- User_Mission_-_RCPlane_Challenge ["Change Weapon"] = "Cambiar arma", +-- ["changing range from %i%% to %i%% with period of %i msec"] = "", -- Gravity -- ["Choose your side! If you want to join the strange man, walk up to him.|Otherwise, walk away from him. If you decide to att...nevermind..."] = "", -- A_Classic_Fairytale:shadow +-- ["Cleaver"] = "", -- Construction_Mode +-- ["Cleaver Placement Mode"] = "", -- Construction_Mode +-- ["Climber"] = "", -- ClimbHome +-- ["Climb Home"] = "", -- ClimbHome +-- ["Clowns"] = "", -- User_Mission_-_Nobody_Laugh ["Clumsy"] = "Patoso", +-- ["Cluster Bomb"] = "", -- Construction_Mode -- ["Cluster Bomb MASTER!"] = "", -- Basic_Training_-_Cluster_Bomb -- ["Cluster Bomb Training"] = "", -- Basic_Training_-_Cluster_Bomb ["Codename: Teamwork"] = "Nombre en clave: Trabajo en equipo", @@ -129,12 +163,19 @@ -- ["Congratulations! You needed only half of time|to eliminate all targets."] = "", -- Basic_Training_-_Cluster_Bomb -- ["Congratulations! You've completed the Rope tutorial! |- Tutorial ends in 10 seconds!"] = "", -- Basic_Training_-_Rope ["Congratulations! You've eliminated all targets|within the allowed time frame."] = "¡Felicidades! Has destruido todos los objectivos|dentro del tiempo establecido.", --Bazooka, Shotgun, SniperRifle +-- ["CONSTRUCTION MODE"] = "", -- Construction_Mode +-- ["Construction Station"] = "", -- Construction_Mode -- ["Continental supplies"] = "", -- Continental_supplies ["Control pillars to score points."] = "Controla los pilares para anotar puntos.", +-- ["Core"] = "", -- Construction_Mode -- ["Corporationals"] = "", -- A_Classic_Fairytale:queen -- ["Corpsemonger"] = "", -- A_Classic_Fairytale:shadow -- ["Corpse Thrower"] = "", -- A_Classic_Fairytale:epil +-- ["Cost"] = "", -- Construction_Mode +-- ["Crate Placement Tool"] = "", -- Construction_Mode -- ["Crates Left:"] = "", -- User_Mission_-_RCPlane_Challenge +-- ["Cricket time: [Drop a fireable mine! ~ Will work if fired close to your hog & far away from enemy ~ 1 sec]"] = "", -- Continental_supplies +-- ["Current setting is "] = "", -- Gravity ["Cybernetic Empire"] = "Imperio cibernético", -- ["Cyborg. It's what the aliens call themselves."] = "", -- A_Classic_Fairytale:enemy -- ["Dahmer"] = "", -- A_Classic_Fairytale:backstab @@ -142,15 +183,19 @@ ["DAMMIT, ROOKIE!"] = "¡MALDITA SEA, RECLUTA!", ["Dangerous Ducklings"] = "Patitos peligrosos", ["Deadweight"] = "Peso muerto", +-- ["Decrease"] = "", -- Continental_supplies -- ["Defeat the cannibals"] = "", -- A_Classic_Fairytale:backstab -- ["Defeat the cannibals!|"] = "", -- A_Classic_Fairytale:united -- ["Defeat the cannibals!|Grenade hint: set the timer with [1-5], aim with [Up]/[Down] and hold [Space] to set power"] = "", -- A_Classic_Fairytale:shadow -- ["Defeat the cyborgs!"] = "", -- A_Classic_Fairytale:enemy +-- ["Defend your core from the enemy."] = "", -- Construction_Mode -- ["Defend yourself!|Hint: You can get tips on using weapons by moving your mouse over them in the weapon selection menu"] = "", -- A_Classic_Fairytale:shadow +-- ["Dematerializes weapons and equipment carried by enemy hedgehogs."] = "", -- Construction_Mode ["Demolition is fun!"] = "¡Destruir es divertido!", -- ["Dense Cloud"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united -- ["Dense Cloud must have already told them everything..."] = "", -- A_Classic_Fairytale:shadow ["Depleted Kamikaze!"] = "¡No quedan más kamikazes!", +-- ["Desert Eagle"] = "", -- Construction_Mode, A_Space_Adventure:death02 -- ["Destroy him, Leaks A Lot! He is responsible for the deaths of many of us!"] = "", -- A_Classic_Fairytale:first_blood ["Destroy invaders to score points."] = "Acaba con los invasores para conseguir puntos.", -- ["Destroy the targets!|Hint: Select the Shoryuken and hit [Space]|P.S. You can use it mid-air."] = "", -- A_Classic_Fairytale:first_blood @@ -169,9 +214,12 @@ -- ["Do you have any idea how valuable grass is?"] = "", -- A_Classic_Fairytale:enemy -- ["Do you think you're some kind of god?"] = "", -- A_Classic_Fairytale:enemy -- ["Dragon's Lair"] = "", -- A_Classic_Fairytale:dragon +-- ["Drill Rocket"] = "", -- Construction_Mode -- ["Drills"] = "", -- A_Classic_Fairytale:backstab +-- ["Drill Strike"] = "", -- Construction_Mode ["Drone Hunter!"] = "Matadrones", --- ["Drop a bomb: [drop some heroic wind that will turn into a bomb on impact]"] = "", -- Continental_supplies +-- ["Drop a bomb: [Drop some heroic wind that will turn into a bomb on impact]"] = "", -- Continental_supplies + ["Drowner"] = "Ahogado", -- ["Dude, all the plants are gone!"] = "", -- A_Classic_Fairytale:family -- ["Dude, can you see Ramon and Spiky?"] = "", -- A_Classic_Fairytale:journey @@ -181,11 +229,15 @@ -- ["Dude, where are we?"] = "", -- A_Classic_Fairytale:backstab -- ["Dude, wow! I just had the weirdest high!"] = "", -- A_Classic_Fairytale:backstab -- ["Duration"] = "", -- Continental_supplies --- ["Dust storm: [Deals 20 damage to all enemies in the circle]"] = "", -- Continental_supplies +-- ["Dust storm: [Deals 15 damage to all enemies in the circle]"] = "", -- Continental_supplies + +-- ["Dynamite"] = "", -- Construction_Mode +-- ["Each turn is only ONE SECOND!"] = "", -- Frenzy ["Each turn you get 1-3 random weapons"] = "Cada turno tendrás de 1 a 3 armas elegidas aleatoriamente", ["Each turn you get one random weapon"] = "Cada turno tendrás un arma elegida aleatoriamente", -- ["Eagle Eye"] = "", -- A_Classic_Fairytale:backstab --- ["Eagle Eye: [Blink to the impact ~ one shot]"] = "", -- Continental_supplies +-- ["Eagle Eye: [Blink to the impact ~ One shot]"] = "", -- Continental_supplies + -- ["Ear Sniffer"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:epil -- ["Elderbot"] = "", -- A_Classic_Fairytale:family -- ["Elimate your captor."] = "", -- User_Mission_-_The_Great_Escape @@ -208,8 +260,9 @@ -- ["Every single time!"] = "", -- A_Classic_Fairytale:dragon -- ["Everything looks OK..."] = "", -- A_Classic_Fairytale:enemy -- ["Exactly, man! That was my dream."] = "", -- A_Classic_Fairytale:backstab +-- ["Extra Damage"] = "", -- Construction_Mode +-- ["Extra Time"] = "", -- Construction_Mode -- ["Eye Chewer"] = "", -- A_Classic_Fairytale:journey --- ["INSANITY"] = "", -- Mutant -- ["Family Reunion"] = "", -- A_Classic_Fairytale:family ["Fastest lap: "] = "Vuelta rápida: ", ["Feeble Resistance"] = "Resistencia Fútil", @@ -219,9 +272,10 @@ -- ["Femur Lover"] = "", -- A_Classic_Fairytale:shadow -- ["Fierce Competition!"] = "", -- Space_Invasion -- ["Fiery Water"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united +-- ["Filthy Blue"] = "", -- User_Mission_-_Dangerous_Ducklings -- ["Find your tribe!|Cross the lake!"] = "", -- A_Classic_Fairytale:dragon -- ["Finish your training|Hint: Animations can be skipped with the [Precise] key."] = "", -- A_Classic_Fairytale:first_blood --- ["Fire a mine: [Does what it says ~ Cant be dropped close to an enemy ~ 1 sec]"] = "", -- Continental_supplies + ["Fire"] = "Fuego", -- ["First aid kits?!"] = "", -- A_Classic_Fairytale:united -- ["First Blood"] = "", -- A_Classic_Fairytale:first_blood @@ -232,11 +286,15 @@ ["Flag returned!"] = "¡Bandera recuperada!", ["Flags, and their home base will be placed where each team ends their first turn."] = "Las banderas y las bases se colocarán donde los equipos acaben su primer turno.", ["Flamer"] = "Incinerador", +-- ["Flamethrower"] = "", -- Construction_Mode -- ["Flaming Worm"] = "", -- A_Classic_Fairytale:backstab --- ["Flare: [fire up some bombs depending on hogs depending on hogs in the circle"] = "", -- Continental_supplies + -- ["Flesh for Brainz"] = "", -- A_Classic_Fairytale:journey +-- ["Flying Saucer"] = "", -- Construction_Mode, Frenzy -- ["For improved features/stability, play 0.9.18+"] = "", -- WxW -- ["Free Dense Cloud and continue the mission!"] = "", -- A_Classic_Fairytale:journey +-- ["Freezer"] = "", -- Construction_Mode +-- ["FRENZY"] = "", -- Frenzy ["Friendly Fire!"] = "¡Fuego amigo!", ["fuel extended!"] = "¡Más combustible!", ["GAME BEGUN!!!"] = "¡EL JUEGO HA EMPEZADO!", @@ -246,6 +304,9 @@ -- ["Game? Was this a game to you?!"] = "", -- A_Classic_Fairytale:enemy -- ["GasBomb"] = "", -- Continental_supplies -- ["Gas Gargler"] = "", -- A_Classic_Fairytale:queen +-- ["General information"] = "", -- Continental_supplies +-- ["Generates power."] = "", -- Construction_Mode +-- ["Generator"] = "", -- Construction_Mode -- ["Get Dense Cloud out of the pit!"] = "", -- A_Classic_Fairytale:journey ["Get on over there and take him out!"] = "¡Ves allí y elimínalo!", -- ["Get on the head of the mole"] = "", -- A_Classic_Fairytale:first_blood @@ -256,6 +317,8 @@ -- ["Get your teammates out of their natural prison and save the princess!|Hint: Drilling holes should solve everything.|Hint: It might be a good idea to place a girder before starting to drill. Just saying.|Hint: All your hedgehogs need to be above the marked height!|Hint: Leaks A Lot needs to get really close to the princess!"] = "", -- A_Classic_Fairytale:family -- ["GG!"] = "", -- User_Mission_-_Rope_Knock_Challenge -- ["Gimme Bones"] = "", -- A_Classic_Fairytale:backstab +-- ["Girder"] = "", -- Construction_Mode +-- ["Girder Placement Mode"] = "", -- Construction_Mode -- ["Glark"] = "", -- A_Classic_Fairytale:shadow ["Goal"] = "Objetivo", ["GO! GO! GO!"] = "¡VAMOS! ¡VAMOS! ¡VAMOS!", @@ -272,12 +335,16 @@ -- ["Go surf!"] = "", -- WxW ["GOTCHA!"] = "¡TE PILLÉ!", ["Grab Mines/Explosives"] = "Coge minas/explosivos", +-- ["Grants nearby hogs life-regeneration."] = "", -- Construction_Mode +-- ["Gravity"] = "", -- Gravity -- ["Great choice, Steve! Mind if I call you that?"] = "", -- A_Classic_Fairytale:shadow -- ["Great work! Now hit it with your Baseball Bat! |Tip: You can change weapon with 'Right Click'!"] = "", -- Basic_Training_-_Rope -- ["Great! You will be contacted soon for assistance."] = "", -- A_Classic_Fairytale:shadow --- ["Green lipstick bullet: [Is poisonous]"] = "", -- Continental_supplies + +-- ["Green lipstick bullet: [Poisonous, deals no damage]"] = "", -- Continental_supplies -- ["Greetings, "] = "", -- A_Classic_Fairytale:dragon -- ["Greetings, cloudy one!"] = "", -- A_Classic_Fairytale:shadow +-- ["Grenade"] = "", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 -- ["Grenade Training"] = "", -- Basic_Training_-_Grenade -- ["Grenadiers"] = "", -- Basic_Training_-_Grenade -- ["Guys, do you think there's more of them?"] = "", -- A_Classic_Fairytale:backstab @@ -285,23 +352,27 @@ -- ["Haha!"] = "", -- A_Classic_Fairytale:united ["Hahahaha!"] = "¡Jajajaja!", ["Haha, now THAT would be something!"] = "¡Jajaja, eso SÍ que sería espectacular!", +-- ["Hammer"] = "", -- Construction_Mode, Continental_supplies -- ["Hannibal"] = "", -- A_Classic_Fairytale:epil [" Hapless Hogs left!"] = " pobres desgraciados restantes!", ["Hapless Hogs"] = "Pobres desgraciados", - -- [" HAS MUTATED"] = "", -- Mutant -- ["Hatless Jerry"] = "", -- A_Classic_Fairytale:queen -- ["Have no illusions, your tribe is dead, indifferent of your choice."] = "", -- A_Classic_Fairytale:shadow -- ["Have we ever attacked you first?"] = "", -- A_Classic_Fairytale:enemy +-- ["Healing Station"] = "", -- Construction_Mode +-- ["Health Crate Placement Mode"] = "", -- Construction_Mode ["Health crates extend your time."] = "Los botiquines aumentan el tiempo disponible.", -- ["Heavy Cannfantry"] = "", -- A_Classic_Fairytale:united ["Heavy"] = "Pesado", -- ["Hedge-cogs"] = "", -- A_Classic_Fairytale:enemy --- ["Hedgehog projectile: [fire your hog like a Sticky Bomb]"] = "", -- Continental_supplies +-- ["Hedgehog projectile: [Fire your hog like a Sticky Bomb]"] = "", -- Continental_supplies + ["Hedgewars-Basketball"] = "Hedgewars-Baloncesto", ["Hedgewars-Knockball"] = "Hedgewars-Knockball", -- ["Hedgibal Lecter"] = "", -- A_Classic_Fairytale:backstab ["Heh, it's not that bad."] = "Jeje, no es para tanto.", +-- ["Hellish Handgrenade"] = "", -- Construction_Mode -- ["Hello again, "] = "", -- A_Classic_Fairytale:family -- ["Help me, Leaks!"] = "", -- A_Classic_Fairytale:journey -- ["Help me, please!!!"] = "", -- A_Classic_Fairytale:journey @@ -333,6 +404,7 @@ -- ["Hogminator"] = "", -- A_Classic_Fairytale:family -- ["Hogs in sight!"] = "", -- Continental_supplies -- ["HOLY SHYTE!"] = "", -- Mutant +-- ["Homing Bee"] = "", -- Construction_Mode -- ["Honest Lee"] = "", -- A_Classic_Fairytale:enemy ["Hooray!"] = "¡Hurra!", -- ["Hostage Situation"] = "", -- A_Classic_Fairytale:family @@ -366,7 +438,6 @@ -- ["If you get stuck, use your Desert Eagle or restart the mission!|"] = "", -- A_Classic_Fairytale:journey -- ["If you know what I mean..."] = "", -- A_Classic_Fairytale:shadow -- ["If you say so..."] = "", -- A_Classic_Fairytale:shadow - -- ["I guess you'll have to kill them."] = "", -- A_Classic_Fairytale:dragon -- ["I have come to make you an offering..."] = "", -- A_Classic_Fairytale:shadow -- ["I have no idea where that mole disappeared...Can you see it?"] = "", -- A_Classic_Fairytale:shadow @@ -389,6 +460,7 @@ -- ["I'm not sure about that!"] = "", -- A_Classic_Fairytale:united -- ["Impressive...you are still dry as the corpse of a hawk after a week in the desert..."] = "", -- A_Classic_Fairytale:first_blood -- ["I'm so scared!"] = "", -- A_Classic_Fairytale:united +-- ["Increase"] = "", -- Continental_supplies -- ["Incredible..."] = "", -- A_Classic_Fairytale:shadow -- ["I need to find the others!"] = "", -- A_Classic_Fairytale:backstab -- ["I need to get to the other side of this island, fast!"] = "", -- A_Classic_Fairytale:journey @@ -397,12 +469,14 @@ -- ["I need to warn the others."] = "", -- A_Classic_Fairytale:backstab -- ["In fact, you are the only one that's been acting strangely."] = "", -- A_Classic_Fairytale:backstab -- ["In order to get to the other side, you need to collect the crates first.|"] = "", -- A_Classic_Fairytale:dragon +-- ["INSANITY"] = "", -- Mutant ["Instructor"] = "Instructor", -- 01#Boot_Camp, User_Mission_-_Dangerous_Ducklings -- ["Interesting idea, haha!"] = "", -- A_Classic_Fairytale:enemy -- ["Interesting! Last time you said you killed a cannibal!"] = "", -- A_Classic_Fairytale:backstab -- ["In the meantime, take these and return to your \"friend\"!"] = "", -- A_Classic_Fairytale:shadow ["invaders destroyed"] = "invasores destruídos", -- ["Invasion"] = "", -- A_Classic_Fairytale:united +-- ["Invulnerable"] = "", -- Construction_Mode -- ["I saw it with my own eyes!"] = "", -- A_Classic_Fairytale:shadow -- ["I see..."] = "", -- A_Classic_Fairytale:shadow -- ["I see you have already taken the leap of faith."] = "", -- A_Classic_Fairytale:first_blood @@ -445,6 +519,7 @@ -- ["Just kidding, none of you have died!"] = "", -- A_Classic_Fairytale:enemy -- ["Just on a walk."] = "", -- A_Classic_Fairytale:united -- ["Just wait till I get my hands on that trauma! ARGH!"] = "", -- A_Classic_Fairytale:family +-- ["Kamikaze"] = "", -- Construction_Mode ["Kamikaze Expert!"] = "¡Kamikaze experto!", ["Keep it up!"] = "¡Sigue así!", -- ["Kerguelen"] = "", -- Continental_supplies @@ -454,6 +529,8 @@ -- ["Kill the aliens!"] = "", -- A_Classic_Fairytale:dragon -- ["Kill the cannibal!"] = "", -- A_Classic_Fairytale:first_blood -- ["Kill the traitor...or spare his life!|Kill him or press [Precise]!"] = "", -- A_Classic_Fairytale:backstab +-- ["Land Sprayer"] = "", -- Construction_Mode +-- ["Laser Sight"] = "", -- Construction_Mode ["Last Target!"] = "¡Último objetivo!", -- ["Leader"] = "", -- A_Classic_Fairytale:enemy -- ["Leaderbot"] = "", -- A_Classic_Fairytale:queen @@ -463,6 +540,7 @@ -- ["Leaks A Lot must survive!"] = "", -- A_Classic_Fairytale:journey -- ["Led Heart"] = "", -- A_Classic_Fairytale:queen -- ["Lee"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen +-- ["left shift"] = "", -- Continental_supplies ["[Left Shift]"] = "[Shift izquierdo]", -- ["Let a Continent provide your weapons!"] = "", -- Continental_supplies -- ["Let me test your skills a little, will you?"] = "", -- A_Classic_Fairytale:journey @@ -473,41 +551,56 @@ -- ["Let them have a taste of my fury!"] = "", -- A_Classic_Fairytale:backstab -- ["Let us help, too!"] = "", -- A_Classic_Fairytale:backstab -- ["Light Cannfantry"] = "", -- A_Classic_Fairytale:united +-- ["Limburger"] = "", -- Construction_Mode ["Listen up, maggot!!"] = "¡Atento, escoria!", -- ["Little did they know that this hunt will mark them forever..."] = "", -- A_Classic_Fairytale:shadow ["Lively Lifeguard"] = "Salvavidas dicharachero", --- ["Lonely Cries: [Rise the water if no hog is in the circle and deal 1 damage to all hogs]"] = "", -- Continental_supplies + +-- ["Lonely Cries: [Rise the water if no hog is in the circle and deal 7 damage to all enemy hogs]"] = "", -- Continental_supplies +-- ["Lonely Hog"] = "", -- ClimbHome -- ["Look, I had no choice!"] = "", -- A_Classic_Fairytale:backstab -- ["Look out! There's more of them!"] = "", -- A_Classic_Fairytale:backstab -- ["Look out! We're surrounded by cannibals!"] = "", -- A_Classic_Fairytale:enemy -- ["Looks like the whole world is falling apart!"] = "", -- A_Classic_Fairytale:enemy +-- ["Low Gravity"] = "", -- Construction_Mode, Frenzy -- ["Luckily, I've managed to snatch some of them."] = "", -- A_Classic_Fairytale:united -- ["LUDICROUS KILL"] = "", -- Mutant +-- ["Made it!"] = "", -- ClimbHome +-- ["- Massive weapon bonus on first turn"] = "", -- Continental_supplies -- ["May the spirits aid you in all your quests!"] = "", -- A_Classic_Fairytale:backstab -- ["Medicine: [Fire some exploding medicine that will heal all hogs effected by the explosion]"] = "", -- Continental_supplies -- ["MEGA KILL"] = "", -- Mutant -- ["Meiwes"] = "", -- A_Classic_Fairytale:backstab -- ["Mindy"] = "", -- A_Classic_Fairytale:united +-- ["Mine"] = "", -- Construction_Mode, Frenzy ["Mine Deployer"] = "Plantador de minas", ["Mine Eater!"] = "¡Tragaminas!", +-- ["Mine Placement Mode"] = "", -- Construction_Mode ["|- Mines Time:"] = "|- Retraso de las minas:", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork +-- ["Mine Strike"] = "", -- Construction_Mode ["MISSION FAILED"] = "MISIÓN FRACASADA", -- User_Mission_-_Dangerous_Ducklings, User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork ["MISSION SUCCESSFUL"] = "MISIÓN COMPLETADA", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork ["MISSION SUCCESS"] = "MISIÓN COMPLETADA", +-- ["Molotov Cocktail"] = "", -- Construction_Mode -- ["Molotov"] = "", -- Continental_supplies -- ["MONSTER KILL"] = "", -- Mutant -- ["More Natives"] = "", -- A_Classic_Fairytale:epil +-- ["Mortar"] = "", -- Construction_Mode, A_Space_Adventure:death02 ["Movement: [Up], [Down], [Left], [Right]"] = "Movimiento: [Arriba], [Abajo], [Izquierda], [Derecha]", +-- ["Mudball"] = "", -- Construction_Mode ["Multi-shot!"] = "¡Disparo múltiple!", -- ["Muriel"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen -- ["Muscle Dissolver"] = "", -- A_Classic_Fairytale:shadow -- ["-------"] = "", -- Mutant +-- ["Mutant"] = "", -- Mutant -- ["Nade Boy"] = "", -- Basic_Training_-_Grenade -- ["Name"] = "", -- A_Classic_Fairytale:queen ["Nameless Heroes"] = "Héroes anónimos", -- ["Nancy Screw"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:queen +-- ["Napalm"] = "", -- Construction_Mode -- ["Napalm rocket: [Fire a bomb with napalm!]"] = "", -- Continental_supplies -- ["Natives"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:first_blood, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united +-- ["Naughty Ninja"] = "", -- User_Mission_-_Dangerous_Ducklings ["New Barrels Per Turn"] = "Barriles por turno", ["NEW CLAN RECORD: "] = "NUEVO RÉCORD PARA EL CLAN", ["NEW fastest lap: "] = "NUEVA vuelta rápida: ", @@ -518,6 +611,7 @@ -- ["Nice work, "] = "", -- A_Classic_Fairytale:dragon -- ["Nice work!"] = "", -- A_Classic_Fairytale:enemy -- ["Nilarian"] = "", -- A_Classic_Fairytale:queen +-- ["Nobody Laugh"] = "", -- User_Mission_-_Nobody_Laugh -- ["No, I came back to help you out..."] = "", -- A_Classic_Fairytale:shadow -- ["No...I wonder where they disappeared?!"] = "", -- A_Classic_Fairytale:journey -- ["Nom-Nom"] = "", -- A_Classic_Fairytale:journey @@ -525,6 +619,7 @@ -- ["Nope. It was one fast mole, that's for sure."] = "", -- A_Classic_Fairytale:shadow -- ["No! Please, help me!"] = "", -- A_Classic_Fairytale:journey -- ["NORMAL"] = "", -- Continental_supplies +-- ["Normal players can only score points by killing the mutant."] = "", -- Mutant -- ["North America"] = "", -- Continental_supplies -- ["Not all hogs are born equal."] = "", -- Highlander ["NOT ENOUGH WAYPOINTS"] = "NO HAY SUFICIENTES BALIZAS", @@ -537,6 +632,7 @@ -- ["No. Where did he come from?"] = "", -- A_Classic_Fairytale:shadow -- ["Now how do I get on the other side?!"] = "", -- A_Classic_Fairytale:dragon -- ["No. You and the rest of the tribe are safer there!"] = "", -- A_Classic_Fairytale:backstab +-- ["Object Placement Tool"] = "", -- Construction_Mode -- ["Obliterate them!|Hint: You might want to take cover..."] = "", -- A_Classic_Fairytale:shadow -- ["Obstacle course"] = "", -- A_Classic_Fairytale:dragon -- ["Of course I have to save her. What did I expect?!"] = "", -- A_Classic_Fairytale:family @@ -553,24 +649,30 @@ -- ["Once upon a time, on an island with great natural resources, lived two tribes in heated conflict..."] = "", -- A_Classic_Fairytale:first_blood -- ["ONE HOG PER TEAM! KILLING EXCESS HEDGES"] = "", -- Mutant -- ["One tribe was peaceful, spending their time hunting and training, enjoying the small pleasures of life..."] = "", -- A_Classic_Fairytale:first_blood +-- ["on Skip"] = "", -- Continental_supplies -- ["Oops...I dropped them."] = "", -- A_Classic_Fairytale:united -- ["Open that crate and we will continue!"] = "", -- A_Classic_Fairytale:first_blood ["Operation Diver"] = "Buzo", ["Opposing Team: "] = "Equipo enemigo: ", +-- ["or 'g=50, g2=150, period=4000' for gravity changing|from 50 to 150 and back with period of 4000 msec"] = "", -- Gravity -- ["Orlando Boom!"] = "", -- A_Classic_Fairytale:queen +-- ["Other kills don't give you points."] = "", -- Mutant -- ["Ouch!"] = "", -- User_Mission_-_Rope_Knock_Challenge -- ["Our tribe, our beautiful island!"] = "", -- A_Classic_Fairytale:enemy -- ["Parachute"] = "", -- Continental_supplies ["Pathetic Hog #%d"] = "Erizo patético #%d", ["Pathetic Resistance"] = "Patética resistencia", -- User_Mission_-_Bamboo_Thicket, User_Mission_-_Newton_and_the_Hammock +-- ["Penguin roar: [Deal 15 damage + 15% of your hogs health to all hogs around you and get 2/3 back]"] = "", -- Continental_supplies -- ["Perfect! Now try to get the next crate without hurting yourself!"] = "", -- A_Classic_Fairytale:first_blood ["Per-Hog Ammo"] = "Armamento individualizado", --- ["- Per team weapons|- 9 weaponschemes|- Unique new weapons| |Select continent first round with the Weapon Menu or by ([switch/tab]=Increase,[precise/left shift]=Decrease) on Skip|Some weapons have a second option. Find them with [switch/tab]"] = "", -- Continental_supplies +-- ["Personal Portal Device"] = "", -- Construction_Mode +-- ["Per team weapons"] = "", -- Continental_supplies -- ["Pfew! That was close!"] = "", -- A_Classic_Fairytale:shadow --- ["Piñata bullet: [Contains some sweet candy!]"] = "", -- Continental_supplies +-- ["Piano Strike"] = "", -- Construction_Mode +-- ["Pickhammer"] = "", -- Construction_Mode + -- ["Pings left:"] = "", -- Space_Invasion - ["Place more waypoints using the 'Air Attack' weapon."] = "Coloca más balizas usando el 'Bombardeo aéreo'", -- ["Planes Used:"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Planes Used"] = "", -- User_Mission_-_RCPlane_Challenge @@ -579,15 +681,19 @@ -- ["Please place the way-point in the open, within the map boundaries."] = "", -- Racer -- ["Please, stop releasing your \"smoke signals\"!"] = "", -- A_Classic_Fairytale:shadow -- ["Point Blank Combo!"] = "", -- Space_Invasion +-- ["POINTS"] = "", -- Mutant ["points"] = "puntos", -- Control, CTF_Blizzard, Basic_Training_-_Bazooka, Basic_Training_-_Shotgun, Basic_Training_-_Sniper_Rifle ["Poison"] = "Veneno", +-- ["Population"] = "", -- Continental_supplies -- ["Portal hint: one goes to the destination, and one is the entrance.|"] = "", -- A_Classic_Fairytale:dragon -- ["Portal mission"] = "", -- portal ["Power Remaining"] = "Energía restante", ["Prepare yourself"] = "Prepárate", +-- ["presice"] = "", -- Continental_supplies -- ["Press [Enter] to accept this configuration."] = "", -- WxW -- ["Press [Left] or [Right] to move around, [Enter] to jump"] = "", -- A_Classic_Fairytale:first_blood ["Press [Precise] to skip intro"] = "Aprieta [Incrementar precisión] para saltar la intro", +-- ["Prestigious Pilot"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Private Novak"] = "", -- Basic_Training_-_Cluster_Bomb -- ["Protect yourselves!|Grenade hint: set the timer with [1-5], aim with [Up]/[Down] and hold [Space] to set power"] = "", -- A_Classic_Fairytale:shadow ["Race complexity limit reached."] = "Máximo de complejidad para el recorrido alcanzado.", @@ -596,25 +702,39 @@ -- ["Radar Ping"] = "", -- Space_Invasion -- ["Raging Buffalo"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united -- ["Ramon"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow +-- ["random in range from %i%% to %i%% with period of %i msec"] = "", -- Gravity +-- ["RC Plane"] = "", -- Construction_Mode -- ["RC PLANE TRAINING"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Really?! You thought you could harm me with your little toys?"] = "", -- A_Classic_Fairytale:shadow +-- ["Reflector Shield"] = "", -- Construction_Mode +-- ["Reflects enemy projectiles."] = "", -- Construction_Mode -- ["Regurgitator"] = "", -- A_Classic_Fairytale:backstab -- ["Reinforcements"] = "", -- A_Classic_Fairytale:backstab -- ["Remember: The rope only bend around objects, |if it doesn't hit anything it's always stright!"] = "", -- Basic_Training_-_Rope -- ["Remember this, pathetic animal: when the day comes, you will regret your blind loyalty!"] = "", -- A_Classic_Fairytale:shadow +-- ["REMOVED"] = "", -- Continental_supplies +-- ["Respawner"] = "", -- Construction_Mode +-- ["Resurrector"] = "", -- Construction_Mode +-- ["Resurrects dead hedgehogs."] = "", -- Construction_Mode [" - Return the enemy flag to your base to score | - First team to 3 captures wins | - You may only score when your flag is in your base | - Hogs will drop the flag if killed, or drowned | - Dropped flags may be returned or recaptured | - Hogs respawn when killed"] = "- Vuelve a tu base con la bandera enemiga para anotar un punto | - El equipo que anote 3 puntos gana | - Sólo se puede anotar si tu propia bandera está en tu base | - Los erizos resucitan cuando mueren", -- ["Return to Leaks A Lot! If you get stuck, press [Precise] to try again!"] = "", -- A_Classic_Fairytale:shadow -- ["Righteous Beard"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:first_blood, A_Classic_Fairytale:queen, A_Classic_Fairytale:united +-- ["Rope"] = "", -- Construction_Mode -- ["ROPE-KNOCKING"] = "", -- User_Mission_-_Rope_Knock_Challenge +-- ["Rope to safety"] = "", -- ClimbHome -- ["Rope Training"] = "", -- Basic_Training_-_Rope -- ["Rot Molester"] = "", -- A_Classic_Fairytale:shadow ["Round Limit:"] = "Límite de rondas:", ["Round Limit"] = "Límite de rondas", ["Rounds Complete: "] = "Rondas completadas: ", ["Rounds Complete"] = "Rondas completadas", +-- ["Rubber Band"] = "", -- Construction_Mode +-- ["Rubber Placement Mode"] = "", -- Construction_Mode +-- ["RULES"] = "", -- Frenzy, Mutant ["RULES OF THE GAME [Press ESC to view]"] = "REGLAS DEL JUEGO (Presiona ESC para leerlas)", -- ["Rusty Joe"] = "", -- A_Classic_Fairytale:queen --- ["Sabotage: [Sabotage all hogs in the circle and deal ~10 dmg]"] = "", -- Continental_supplies +-- ["Sabotage/Flare: [Sabotage all hogs in the circle and deal ~1 dmg OR Fire a cluster up into the air]"] = "", -- Continental_supplies + -- ["Salivaslurper"] = "", -- A_Classic_Fairytale:united -- ["Salvation"] = "", -- A_Classic_Fairytale:family -- ["Salvation was one step closer now..."] = "", -- A_Classic_Fairytale:dragon @@ -626,7 +746,7 @@ -- ["Scalp Muncher"] = "", -- A_Classic_Fairytale:backstab -- ["Score"] = "", -- Mutant ["SCORE"] = "PUNTUACIÓN", --- ["Scream from a Walrus: [Deal 20 damage + 10% of your hogs health to all hogs around you and get half back]"] = "", -- Continental_supplies + ["sec"] = "segundo", -- CTF_Blizzard, TrophyRace, Basic_Training_-_Bazooka, Basic_Training_-_Shotgun, Basic_Training_-_Sniper_Rifle, User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork, Capture_the_Flag -- ["Seduction"] = "", -- Continental_supplies -- ["Seems like every time you take a \"walk\", the enemy find us!"] = "", -- A_Classic_Fairytale:backstab @@ -634,8 +754,11 @@ ["See ya!"] = "¡Hasta otra!", -- ["Segmentation Paul"] = "", -- A_Classic_Fairytale:dragon -- ["Select continent!"] = "", -- Continental_supplies +-- ["Select continent first round with the Weapon Menu or by"] = "", -- Continental_supplies -- ["Select difficulty: [Left] - easier or [Right] - harder"] = "", -- A_Classic_Fairytale:first_blood ["selected!"] = "¡Seleccionado!", +-- ["Set period to negative value for random gravity"] = "", -- Gravity +-- ["Setup:|'g=150', where 150 is 150% of normal gravity"] = "", -- Gravity -- ["... share your beauty with the world every morning, my princess!"] = "", -- A_Classic_Fairytale:journey -- ["She's behind that tall thingy."] = "", -- A_Classic_Fairytale:family ["Shield boosted! +30 power"] = "¡Escudo mejorado! +30 puntos", @@ -646,16 +769,21 @@ ["Shield OFF:"] = "Escudo desactivado:", ["Shield ON:"] = "Escudo activado:", ["Shield Seeker!"] = "¡A cubierto!", +-- ["Shoryuken"] = "", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 -- ["Shotgun"] = "", -- Continental_supplies ["Shotgun Team"] = "Escopeteros", ["Shotgun Training"] = "Entrenamiento con escopeta", ["shots remaining."] = "disparos restantes.", ["Silly"] = "Idiota", +-- ["SineGun"] = "", -- Construction_Mode ["Sinky"] = "Sumergible", -- ["Sirius Lee"] = "", -- A_Classic_Fairytale:enemy ["%s is out and Team %d|scored a penalty!| |Score:"] = "¡%s cayó y Equipo %d|anotó una falta!| |Puntuación:", -- Basketball, Knockball ["%s is out and Team %d|scored a point!| |Score:"] = "¡%s cayó y Equipo %d|anotó un tanto!| |Puntuación:", -- Basketball, Knockball -- ["Slippery"] = "", -- A_Classic_Fairytale:journey +-- ["Slot"] = "", -- Frenzy +-- ["Slot keys save time! (F1-F10 by default)"] = "", -- Frenzy +-- ["SLOTS"] = "", -- Frenzy -- ["Smith 0.97"] = "", -- A_Classic_Fairytale:enemy -- ["Smith 0.98"] = "", -- A_Classic_Fairytale:enemy -- ["Smith 0.99a"] = "", -- A_Classic_Fairytale:enemy @@ -667,6 +795,7 @@ ["Sniper Training"] = "Entrenamiento con rifle francotirador", ["Sniperz"] = "Francotiradores", -- ["So humiliating..."] = "", -- A_Classic_Fairytale:first_blood +-- ["Some weapons have a second option. Find them with"] = "", -- Continental_supplies -- ["South America"] = "", -- Continental_supplies -- ["So? What will it be?"] = "", -- A_Classic_Fairytale:shadow -- ["Spawn the crate, and attack!"] = "", -- WxW @@ -675,6 +804,8 @@ -- ["Spleenlover"] = "", -- A_Classic_Fairytale:united ["Sponge"] = "Esponja", ["Spooky Tree"] = "Árbol tenebroso", +-- ["Sprite Placement Mode"] = "", -- Construction_Mode +-- ["Sprite Testing Mode"] = "", -- Construction_Mode ["s|"] = "s|", ["s"] = "s", -- GaudyRacer, Space_Invasion ["STATUS UPDATE"] = "ACTUALIZACIÓN DE ESTADO", -- GaudyRacer, Space_Invasion @@ -682,20 +813,36 @@ -- ["Step By Step"] = "", -- A_Classic_Fairytale:first_blood -- ["Steve"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen -- ["Sticky Mine"] = "", -- Continental_supplies +-- ["Sticky Mine Placement Mode"] = "", -- Construction_Mode -- ["Stronglings"] = "", -- A_Classic_Fairytale:shadow --- ["Structure"] = "", -- Continental_supplies + +-- ["Structure Placement Mode"] = "", -- Construction_Mode +-- ["Structure Placement Tool"] = "", -- Construction_Mode +-- ["Sundaland"] = "", -- Continental_supplies -- ["Super Weapons"] = "", -- WxW +-- ["Support Station"] = "", -- Construction_Mode -- ["Surf Before Crate"] = "", -- WxW -- ["Surfer! +15 points!"] = "", -- Space_Invasion -- ["Surfer!"] = "", -- WxW -- ["Survive!|Hint: Cinematics can be skipped with the [Precise] key."] = "", -- A_Classic_Fairytale:shadow -- ["Swing, Leaks A Lot, on the wings of the wind!"] = "", -- A_Classic_Fairytale:first_blood +-- ["switch"] = "", -- Continental_supplies ["Switched to "] = "Cambiar a ", +-- ["Switch Hog"] = "", -- Construction_Mode -- ["Syntax Errol"] = "", -- A_Classic_Fairytale:dragon +-- ["tab"] = "", -- Continental_supplies +-- ["Tagging Mode"] = "", -- Construction_Mode -- ["Talk about mixed signals..."] = "", -- A_Classic_Fairytale:dragon +-- ["Tardis"] = "", -- Construction_Mode +-- ["Target Placement Mode"] = "", -- Construction_Mode ["Team %d: "] = "Equipo %d", ["Team Scores"] = "Puntuaciones", -- Control, Space_Invasion +-- ["Teleporation Node"] = "", -- Construction_Mode +-- ["Teleportation Mode"] = "", -- Construction_Mode +-- ["Teleportation Node"] = "", -- Construction_Mode +-- ["Teleport"] = "", -- Construction_Mode, Frenzy -- ["Teleport hint: just use the mouse to select the destination!"] = "", -- A_Classic_Fairytale:dragon +-- ["Teleport Unsuccessful. Please teleport within a clan teleporter's sphere of influence."] = "", -- Construction_Mode -- ["Thanks!"] = "", -- A_Classic_Fairytale:family -- ["Thank you, my hero!"] = "", -- A_Classic_Fairytale:family -- ["Thank you, oh, thank you, Leaks A Lot!"] = "", -- A_Classic_Fairytale:journey @@ -712,6 +859,7 @@ ["That was pointless."] = "Eso era innecesario.", -- ["The answer is...entertaintment. You'll see what I mean."] = "", -- A_Classic_Fairytale:backstab -- ["The anti-portal zone is all over the floor, and I have nothing to kill him...Droping something could hurt him enough to kill him..."] = "", -- portal +-- ["The Bottom Feeder can score points by killing anyone."] = "", -- Mutant -- ["The Bull's Eye"] = "", -- A_Classic_Fairytale:first_blood -- ["The caves are well hidden, they won't find us there!"] = "", -- A_Classic_Fairytale:united -- ["The Crate Frenzy"] = "", -- A_Classic_Fairytale:first_blood @@ -721,20 +869,26 @@ -- ["The Enemy Of My Enemy"] = "", -- A_Classic_Fairytale:enemy -- ["The First Blood"] = "", -- A_Classic_Fairytale:first_blood -- ["The First Encounter"] = "", -- A_Classic_Fairytale:shadow +-- ["The first player to kill someone becomes the Mutant."] = "", -- Mutant ["The flag will respawn next round."] = "La bandera reaparecerá en el próximo turno.", -- ["The food bites back"] = "", -- A_Classic_Fairytale:backstab -- ["The giant umbrella from the last crate should help break the fall."] = "", -- A_Classic_Fairytale:first_blood -- ["The Great Escape"] = "", -- User_Mission_-_The_Great_Escape +-- ["The Great Hog in the sky sees your sadness and grants you a boon."] = "", -- Construction_Mode -- ["The guardian"] = "", -- A_Classic_Fairytale:shadow -- ["The Individualist"] = "", -- A_Classic_Fairytale:shadow -- ["Their buildings were very primitive back then, even for an uncivilised island."] = "", -- A_Classic_Fairytale:united -- ["The Journey Back"] = "", -- A_Classic_Fairytale:journey -- ["The Leap of Faith"] = "", -- A_Classic_Fairytale:first_blood -- ["The Moonwalk"] = "", -- A_Classic_Fairytale:journey +-- ["The Mutant has super-weapons and a lot of health."] = "", -- Mutant +-- ["The Mutant loses health quickly if he doesn't keep scoring kills."] = "", -- Mutant ["The Nameless One"] = "Anónimo", -- ["The next one is pretty hard! |Tip: You have to do multiple swings!"] = "", -- Basic_Training_-_Rope -- ["Then how do they keep appearing?"] = "", -- A_Classic_Fairytale:shadow -- ["The other one were all cannibals, spending their time eating the organs of fellow hedgehogs..."] = "", -- A_Classic_Fairytale:first_blood +-- ["The player with least points (or most deaths) becomes the Bottom Feeder."] = "", -- Mutant +-- ["There are a variety of structures available to aid you."] = "", -- Construction_Mode -- ["There must be a spy among us!"] = "", -- A_Classic_Fairytale:backstab -- ["There's more of them? When did they become so hungry?"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united -- ["There's nothing more satisfying for me than seeing you share your beauty with the world every morning, my princess!"] = "", -- A_Classic_Fairytale:journey @@ -790,7 +944,7 @@ -- ["To the caves..."] = "", -- A_Classic_Fairytale:united ["Toxic Team"] = "Tóxicos", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork ["TRACK COMPLETED"] = "¡PISTA COMPLETADA!", - ["TRACK FAILED!"] = "¡PISTA FRACASADA!", + -- ["training"] = "", -- portal -- ["Traitors"] = "", -- A_Classic_Fairytale:epil -- ["Tribe"] = "", -- A_Classic_Fairytale:backstab @@ -807,6 +961,7 @@ -- ["ULTRA KILL"] = "", -- Mutant -- ["Under Construction"] = "", -- A_Classic_Fairytale:shadow -- ["Unexpected Igor"] = "", -- A_Classic_Fairytale:dragon +-- ["Unique new weapons"] = "", -- Continental_supplies -- ["Unit 0x0007"] = "", -- A_Classic_Fairytale:family -- ["Unit 334a$7%;.*"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united ["Unit 3378"] = "Unidad 3378", @@ -821,11 +976,14 @@ -- ["Use it wisely!"] = "", -- A_Classic_Fairytale:dragon -- ["Use it with precaution!"] = "", -- A_Classic_Fairytale:first_blood ["User Challenge"] = "Reto personal", - +-- ["Use the air-attack weapons and the arrow keys to select structures."] = "", -- Construction_Mode -- ["Use the portal gun to get to the next crate, then use the new gun to get to the final destination!|"] = "", -- A_Classic_Fairytale:dragon -- ["Use the rope to get on the head of the mole, young one!"] = "", -- A_Classic_Fairytale:first_blood -- ["Use the rope to knock your enemies to their doom."] = "", -- User_Mission_-_Rope_Knock_Challenge +-- ["Use your ready time to think."] = "", -- Frenzy ["Use your rope to get from start to finish as fast as you can!"] = "¡Usa tu cuerda para llegar a la salida lo más rápido que puedas!", +-- ["Utility Crate Placement Mode"] = "", -- Construction_Mode +-- ["Vampirism"] = "", -- Construction_Mode -- ["Vedgies"] = "", -- A_Classic_Fairytale:journey -- ["Vegan Jack"] = "", -- A_Classic_Fairytale:enemy -- ["Victory!"] = "", -- Basic_Training_-_Rope @@ -837,10 +995,14 @@ -- ["Wannabe Flyboys"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Wannabe Shoppsta"] = "", -- User_Mission_-_Rope_Knock_Challenge -- ["Watch your steps, young one!"] = "", -- A_Classic_Fairytale:first_blood +-- ["Watermelon Bomb"] = "", -- Construction_Mode ["Waypoint placed."] = "Baliza colocada.", ["Way-Points Remaining"] = "Balizas restantes", -- ["Weaklings"] = "", -- A_Classic_Fairytale:shadow -- ["We all know what happens when you get frightened..."] = "", -- A_Classic_Fairytale:first_blood +-- ["Weapon Crate Placement Mode"] = "", -- Construction_Mode +-- ["Weapon Filter"] = "", -- Construction_Mode +-- ["weaponschemes"] = "", -- Continental_supplies ["Weapons Reset"] = "Armamento reiniciado", -- ["Weapons reset."] = "", -- Highlander -- ["We are indeed."] = "", -- A_Classic_Fairytale:backstab @@ -893,6 +1055,7 @@ -- ["Where do you get that?!"] = "", -- A_Classic_Fairytale:enemy -- ["Where have you been?!"] = "", -- A_Classic_Fairytale:backstab -- ["Where have you been?"] = "", -- A_Classic_Fairytale:united +-- ["Whip"] = "", -- Construction_Mode -- ["? Why?"] = "", -- A_Classic_Fairytale:backstab -- ["Why "] = "", -- A_Classic_Fairytale:backstab -- ["! Why?!"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united @@ -905,8 +1068,10 @@ -- ["Why me?!"] = "", -- A_Classic_Fairytale:backstab -- ["Why would they do this?"] = "", -- A_Classic_Fairytale:backstab -- ["- Will Get 1-3 random weapons"] = "", -- Continental_supplies --- ["- Will refresh Parachute each turn."] = "", -- Continental_supplies --- ["- Will refresh portalgun each turn."] = "", -- Continental_supplies +-- ["- Will give you an airstrike every fifth turn."] = "", -- Continental_supplies +-- ["- Will give you a parachute every second turn."] = "", -- Continental_supplies + + ["Will this ever end?"] = "¿Es que nunca se va a terminar?", -- ["WINNER IS "] = "", -- Mutant ["WINNING TIME: "] = "MEJOR TIEMPO: ", @@ -925,6 +1090,7 @@ -- ["Yes!"] = "", -- A_Classic_Fairytale:enemy -- ["Yes, yeees! You are now ready to enter the real world!"] = "", -- A_Classic_Fairytale:first_blood -- ["Yo, dude, we're here, too!"] = "", -- A_Classic_Fairytale:family +-- ["You are far from home, and the water is rising, climb up as high as you can!"] = "", -- ClimbHome -- ["You are given the chance to turn your life around..."] = "", -- A_Classic_Fairytale:shadow -- ["You are playing with our lives here!"] = "", -- A_Classic_Fairytale:enemy -- ["! You bastards!"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united @@ -957,6 +1123,8 @@ -- ["You know what? I don't even regret anything!"] = "", -- A_Classic_Fairytale:backstab -- ["You'll see what I mean!"] = "", -- A_Classic_Fairytale:enemy -- ["You may only attack from a rope!"] = "", -- WxW +-- ["You may only spawn 5 crates per turn."] = "", -- Construction_Mode +-- ["You may only use 1 Extra Time per turn."] = "", -- Construction_Mode -- ["You meatbags are pretty slow, you know!"] = "", -- A_Classic_Fairytale:enemy -- ["You might want to find a way to instantly kill arriving cannibals!"] = "", -- A_Classic_Fairytale:backstab -- ["Young one, you are telling us that they can instantly change location without a shaman?"] = "", -- A_Classic_Fairytale:united @@ -977,6 +1145,7 @@ ["You've failed. Try again."] = "Has fracasado. Inténtalo de nuevo.", ["You've reached the goal!| |Time: "] = "¡Has llegado a la meta!| |Tiempo: ", -- ["You will be avenged!"] = "", -- A_Classic_Fairytale:shadow +-- ["- You will recieve 2-4 weapons on each kill! (Even on own hogs)"] = "", -- Continental_supplies -- ["You won't believe what happened to me!"] = "", -- A_Classic_Fairytale:backstab -- ["Yuck! I bet they'll keep worshipping her even after I save the village!"] = "", -- A_Classic_Fairytale:family -- ["Zealandia"] = "", -- Continental_supplies diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/fi.txt --- a/share/hedgewars/Data/Locale/fi.txt Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/fi.txt Tue Nov 10 20:43:13 2015 +0100 @@ -9,7 +9,7 @@ 00:06=Hyppää yli 00:07=Köysi 00:08=Miina -00:09=DEagle +00:09=Pistooli 00:10=Dynamiitti 00:11=Pesäpallomaila 00:12=Shoryuken @@ -43,13 +43,21 @@ 00:40=Polttopullo 00:41=Lintu 00:42=Siirrettävä portaalilaite -00:43=Piano-isku +00:43=Pianoisku 00:44=Vanha Limburger-juusto -00:45=Sini-aaltopyssy +00:45=Siniaaltopyssy 00:46=Liekinheitin 00:47=Tarttuva pommi 00:48=Vasara 00:49=Henkiinherättäjä +00:50=Poraisku +00:51=Mutapallo +00:52=Ei asetta valittuna +00:53=Aikakoppi +00:54=Maasuihke +00:55=Jäädytin +00:56=Jättiveitsi +00:57=Kuminauha 01:00=Taistelu alkakoon! 01:01=Tasapeli @@ -66,16 +74,25 @@ 01:12=Viimeinen kierros ennen äkkikuolemaa! 01:13=%1 kierrosta jäljellä äkkikuolemaan! 01:14=Valmistaudu, %1! - +01:15=Mitätön +01:16=Heikko +01:17=Normaali +01:18=Voimakas +01:19=Huima +01:20=%1 pomppu +01:21=Äänet hiljennetty +01:22=Poissa näppäimistöltä +01:23=Passiivinen kamera +01:24=Aktiivinen kamera ; Event messages ; Hog (%1) died 02:00=%1 potkaisi tyhjää! -02:00=%1 näki valon! +02:00=%1 koki valaistumisen! 02:00=%1 ei osannut odottaa tuota! 02:00=%1 heiluttaa näkemiin! 02:00=%1 on mennyt parempaan paikkaan -02:00=%1 tapaa luojansa! +02:00=%1 tapaa Luojansa! 02:00=%1 ei jaksa enää! 02:00=%1 on tehnyt tehtävänsä! 02:00=%1 tekee tärkeän uhrautumisen! @@ -100,15 +117,15 @@ 02:00=%1 ei vain osaa 02:00=Voi %1 parkaa... 02:00=%1 pitää enemmän Warmuxista -02:00=%1 on pysäyttänyt luoteja kasvoillaan +02:00=%1 pysäytti luoteja naamallaan 02:00=%1 on sankari ih...siilien joukossa 02:00=%1 löytää paikkansa Valhallasta 02:00=%1 on poistnut rakennuksesta 02:00=%1 seuraa dinosaurusten jalanjälkiä -02:00=%1 tuo siilet askelta lähemmäksi sukupuuttoa +02:00=%1 vie siilet askelta lähemmäksi sukupuuttoa 02:00=%1 tuo kyyneleen silmääni 02:00=%1 on ex-siili -02:00=%1 työntää kukkia esiin +02:00=%1:stä nauttii enää rikkaheinät 02:00=%1 on lakannut olemasta 02:00=Sano näkemiin %1:lle 02:00=%1:llä ei ole enää toivoa @@ -137,7 +154,7 @@ 02:01=%1 unohti surffilautansa kotiin 02:01=%1 unohti pelastusliivinsä 02:01=%1:stä kuuluu splish splash splish -02:01=%1 nukkuu kalojen kanssa +02:01=%1 lepää kalojen kanssa 02:01=%1:n mielestä veden fysiikka on ihan tyhmä tässä pelissä 02:01=%1 näyttää janoiselta 02:01=meri ottaa %1:n haltuunsa. @@ -161,7 +178,7 @@ 02:01=%1 löysi Atlantiksen kadonneen kaupungin 02:01=%1:n olisi pitänyt ottaa vesiskootteri mukaan 02:01=%1 ei pidä vesiurheilusta -02:01=%1 puhaltaa ikuisesti kuplia +02:01=%1 puhaltelee ikuisesti kuplia 02:01=%1 tarvitsee lautan 02:01=%1:n mielestä suolavesi on hyväksi iholle 02:01=%1 saa suolavettä haavoihinsa @@ -226,17 +243,17 @@ ; New health crate 02:05=Apua tulossa! -02:05=Lääkäri! +02:05=Lääkintämies! 02:05=Ensiapua taivaasta! 02:05=Terveyspaketti sinulle 02:05=Hyvää terveyttä laatikkomuodossa! -02:05=Tohtori soittaa +02:05=Tohtori kilauttaa 02:05=Tuoreita siteitä! 02:05=Tämä saa sinut tuntemaan itsesi terveemmäksi 02:05=Hi-Potion! Eiku väärä peli -02:05=Hae se! +02:05=Nappaa se! 02:05=Terveellinen välipala -02:05=Helpotus kipuun +02:05=Helpotusta kipuun 02:05=Oikea annostus: Niin monta kuin löydät! 02:05=Kiireellinen lähetys 02:05=Varusteita! @@ -286,7 +303,7 @@ 02:08=%1 on ajattelematon 02:08=%1 antoi periksi 02:08=Torkkumalla häviät, %1 -02:08=%1 häpeilemättömästi jättää vuoron välistä +02:08=%1 häpeilemättömästi jättää vuoronsa välistä 02:08=%1 on todella laiska 02:08=%1 tarvitsee lisää motivaatiota 02:08=%1 on pasifisti @@ -294,21 +311,21 @@ 02:08=%1 pitää tauon 02:08=%1 ottaa rennosti 02:08=%1 ei usko kykyihinsä -02:08=%1 päättää olla tekemättä mitään +02:08=%1 päättää olla tekemättä yhtään mitään 02:08=%1 antaa vihollisen tuhota itsensä -02:08=%1 olisi todella huono juhlissa +02:08=%1 olisi huonoa seuraa bileissä 02:08=%1 piiloutuu 02:08=%1 jättää mahdollisuuden käyttämättä -02:08=%1 päättää että paras asia minkä hän voi tehdä on...ei mitään +02:08=%1 toteaa että paras asia minkä hän voi tehdä on...ei mitään 02:08=%1 on pelkuri -02:08=Kot kot kot, %1 on pelkurikana +02:08=Kot kot kot, %1 on pelkurikana! 02:08=%1 kellertää 02:08=%1 on pelkuri! 02:08=%1 odottaa äkkikuolemaa 02:08=%1 ei ole taistelijatyyppiä -02:08=%1 harkitsee huudelleen elämänsä tarkoitusta -02:08=%1 eikoskaan osannut tähdätä muutenkaan -02:08=%1 ei olisi alunperinkään halunnutm ennä armeijaan +02:08=%1 harkitsee uudelleen elämänsä tarkoitusta +02:08=%1 ei koskaan oppinut tähtäämään muutenkaan +02:08=%1 ei olisi alunperinkään halunnut mennä armeijaan 02:08=Lakkaa haaskaamasta meidän aikaa, %1 02:08=Olen pettynyt sinuun, %1 02:08=Pystyt kyllä parempaankin, %1 @@ -336,7 +353,7 @@ 02:09=%1 siirtyy askeleen lähemmäksi itsemurhaa 02:09=%1 auttaa vihollista 02:09=Tuo oli tyhmää, %1 -02:09=%1 elää mantran "ei kipua, ei voittoa" mukaan +02:09=%1 elää mantran "ei kipua, ei hyötyä" mukaan 02:09=%1 on hämmentynyt 02:09=%1 satuttaa itseään hämmennyksessään 02:09=%1 tykkää nolata itseään @@ -353,8 +370,8 @@ 02:09=%1:n ase on selvästi epäkunnossa ; Hog shot an home run (using the bat and another hog) -02:10=Kotijuoksu! -02:10=Lintu, eiku lentokone, eiku... +02:10=Kunnari! +02:10=Onko se lintu, vai lentokone, eiku... 02:10=Se lensi pitkälle! ; Weapon Categories @@ -402,13 +419,21 @@ 03:41=Kääkkyvä kaveri 03:42=I'm making a note here... ; the misspelled "Beethoven" is intentional (-> to beat) -03:43=Soittaa Beathovenin tappavan soneetin +03:43=Soittaa Beathovenin tappavan sonaatin 03:44=Parasta ennen: 1923 03:45=Tieteen voima 03:46=Kuuma kuuma kuuma! 03:47=Kiinnitä nämä hyödylliseen paikkaan! 03:48=Vasarointiaika. 03:49=Tekee sitä mitä luulet sen tekevän. +03:50=Myyrien suosikki +03:51=Löytyi maasta +03:52=UNUSED +03:53=Mallia 40 +03:54=Työkalu +03:55=Tätä coolimpaa asetta ei ole! +03:56=Käytä tai väärinkäytä +03:57=Työkalu ; Weapon Descriptions (use | as line breaks) 04:00=Hyökkää yksinkertaisella kranaatilla.|Se räjähtää kun ajastimesta loppuu aika.|1-5: Säädä kranaatin ajastin|Hyökkää: Pidä pohjassa lisätäksesi heittovoimaa @@ -459,8 +484,16 @@ 04:45=Istuminen kaikilla niillä fysiikan tunneilla|kannatti viimein, laukaise tuhoisa|sini-aalto vihollisiasi päin.|Varo, tämä ase potkaisee aika kovaa.|Hyökkää: Ammu 04:46=Peitä vastustajasi sähisevällä liekehtivällä nesteellä.|Sydäntä lämmittävää!|Hyökkää: Aktivoi|Ylös/Alas: Jatka tähtäystä|Vasen/Oikea: Muuta sylkyvoimaa. 04:47=Kaksinkertaista hauskuus kahdella piikikkäällä,|petollisella, tarttuvalla miinalla.|Viritä ketjureaktio tai puolusta itseäsi (tai molempia!)|Hyökkää: Pidä pohjassa ampuaksesi kovemmalla voimalla (kahdesti) -04:48=Miksi vain myyrät saa kaiken pahoinpitelyn?|Siilien hakkaaminen voi olla ihan yhtä kivaa!|Sopiva isku tällä vasaralla iskee pois kolmanneksen|siilin terveydestä ja lyö ne maan alle.|Hyökkää: Aktivoi +04:48=Miksi vain myyrät saa kaiken pahoinpitelyn?|Siilien hakkaaminen voi olla ihan yhtä kivaa!|Sopiva isku tällä vasaralla iskee pois kolmanneksen|siilin terveydestä ja lyö ne maan alle.|Hyökkää: Ammu kohteen vierellä. 04:49=Herätä ystäväsi henkiin!|Mutta varo, tämä herättää myös vihollisesi henkiin.|Hyökkää: Pidä hyökkäysnappia pohjassa herättääksesi henkiin hitaasti.|Ylös: Kiihdytä henkiin herätystä +04:50=Piilotteleeko joku maan alla?|Kaiva heidät ulos poraiskulla!|Poraraketit räjähtävät ajastimen loputtua.|1-5: Säädä ajastin|Vasen/Oikea: Valitse hyökkäyssuunta|Osoitin: Valitse kohdealue +04:51=Heitä mutapallo, joka ei maksa siirtoasi.|Sysää siilet liikkeelle.|Hyökkää: Pidä pohjassa ampuaksesi kovemmalla voimalla +04:52=UNUSED +04:53=Lähde matkalle ajassa ja tilassa, jättäen| muut toverit taistelemaan yksin.|Valmistaudu palautumaan koska tahansa, |äkkikuolemassa tai kun muut joukkueesi siilet on tuhottu.|Ei toimi äkkikuolemassa, jos joukkueessa on enää yksi siili tai kuninkaalla.|Hyökkää: Aktivoi. +04:54=Suihkuttaa tahmeita hiutaleita, muodostaen maata.|Tuki reittejä, siiliä tai luo silta!|Ole tarkkana, ettet suihkuta itseesi.|Hyökkää: Aktivoi.|Ylös/Alas: Muuta tähtäystä|Vasen/Oikea: Muuta sylkyvoimaa +04:55=Palauta jääkausi!|Pakasta siilet usean vuoron ajaksi, tai jäädytä maata ja vettä.|Hyökkää: Aktivoi +04:56=Voit heittää kaksi veitseä vihollista kohti,|tukkia käytäviä tai vaikkapa tehdä niistä portaat!|Ole kuitenkin varovainen, teräaseilla leikkiminen on vaarallista!|Hyökkää: Aktivoi +04:57=Rakenna elastinen kumiseinä, josta siilet |ja aseet kimpoavat vahingoittumatta.|Vasen/Oikea: Käännä kumea|Hiiri: Sijoita kumi ; Game goal strings 05:00=Pelimoodit @@ -479,3 +512,9 @@ 05:13=Miinojen ajastimet: Miinat räjähtävät välittömästi 05:14=Miinojen ajastimet: Miinat räjähtävät 0 - 3 sekunnin kuluttua 05:15=Vahinkokerroin: Kaikki aseet tekevät %1% vahinkopistettä +05:16=Siilien terveys palautetaan vuoron vaihtuessa +05:17=Tekoälysiilet uudelleensyntyvät kuollessa +05:18=Rajattomat hyökkäykset +05:19=Aseet korvataan vuoron vaihtuessa +05:20=Aseita ei jaeta joukkueen kesken +05:21=Jaettu aika: Vuoron aika jaetaan tasan klaanin sisällä \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/fr.lua --- a/share/hedgewars/Data/Locale/fr.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/fr.lua Tue Nov 10 20:43:13 2015 +0100 @@ -1,10 +1,14 @@ locale = { +-- [":("] = "", +-- ["!!!"] = "", -- ["???"] = "", -- ["..."] = "", --- [":("] = "", --- ["!!!"] = "", -- ["011101000"] = "", -- ["011101001"] = "", +-- ["+1 to a Bottom Feeder for killing anyone"] = "", -- Mutant +-- ["+1 to a Mutant for killing anyone"] = "", -- Mutant +-- ["-1 to anyone for a suicide"] = "", -- Mutant +-- ["+2 for becoming a Mutant"] = "", -- Mutant ["30 minutes later..."] = "30 minutes plus tard...", ["About a month ago, a cyborg came and told us that you're the cannibals!"] = "Il y a un mois, un cyborg est venu et nous a dit que vous étiez des cannibales !", ["Accuracy Bonus!"] = "Bonus précision", @@ -13,17 +17,27 @@ ["A Classic Fairytale"] = "Un conte classique de fée", ["Actually, you aren't worthy of life! Take this..."] = "En fait, tu n'es pas digne de vivre ! Prends ça....", ["A cy-what?"] = "Un cy-quoi ?", +-- ["Advanced Repositioning Mode"] = "", -- Construction_Mode ["Adventurous"] = "Aventurier", +-- ["a frenetic Hedgewars mini-game"] = "", -- Frenzy -- ["Africa"] = "", -- Continental_supplies ["After Leaks A Lot betrayed his tribe, he joined the cannibals..."] = "Après que Grosse Fuite ait trahit sa tribu, il rejoignât les cannibales... ", ["After the shock caused by the enemy spy, Leaks A Lot and Dense Cloud went hunting to relax."] = "Après le choc causé par l'espion ennemi, Grosse Fuite et Nuage Dense partirent chasser pour se détendre.", ["Again with the 'cannibals' thing!"] = "Encore avec votre 'cannibale' truc", +-- ["Aggressively removes enemy hedgehogs."] = "", -- Construction_Mode -- ["a Hedgewars challenge"] = "", -- User_Mission_-_RCPlane_Challenge, User_Mission_-_Rope_Knock_Challenge ["a Hedgewars mini-game"] = "Un mini jeux d'Hedgewars", -- Space_Invasion, The_Specialists +-- ["a Hedgewars tag game"] = "", -- Mutant +-- ["AHHh, home sweet home. Made it in %d seconds."] = "", -- ClimbHome ["Aiming Practice"] = "Entraînement de tir", --Bazooka, Shotgun, SniperRifle +-- ["Air Attack"] = "", -- Construction_Mode ["A leap in a leap"] = "Un bond dans un bond", ["A little gift from the cyborgs"] = "Un petit cadeau de la part des cyborgs", ["All gone...everything!"] = "Évaporé...plus rien !", +-- ["Allows free teleportation between other nodes."] = "", -- Construction_Mode +-- ["Allows placement of girders, rubber-bands, mines, sticky mines and barrels."] = "", -- Construction_Mode +-- ["Allows placement of structures."] = "", -- Construction_Mode +-- ["Allows the placement of weapons, utiliites, and health crates."] = "", -- Construction_Mode ["All right, we just need to get to the other side of the island!"] = "Très bien, nous devons juste rejoindre l'autre côté de l'île !", -- ["All walls touched!"] = "", -- WxW ["Ammo Depleted!"] = "Munitions épuisées !", @@ -38,8 +52,11 @@ ["And so they discovered that cyborgs weren't invulnerable..."] = "Et c'est ainsi qu'ils découvrirent que les cyborgs n'étaient pas invulnérables...", ["And where's all the weed?"] = "Et où est toute l'herbe ?", ["And you believed me? Oh, god, that's cute!"] = "Et tu m'as cru ? Oh mon dieu, c'est mignon !", --- ["Anno 1032: [The explosion will make a strong push ~ wide range, wont affect hogs close to the target]"] = "", -- Continental_supplies +-- ["Anno 1032: [The explosion will make a strong push ~ Wide range, wont affect hogs close to the target]"] = "", -- Continental_supplies + -- ["Antarctica"] = "", -- Continental_supplies +-- ["Antarctic summer: - Will give you one girder/mudball and two sineguns/portals every fourth turn."] = "", -- Continental_supplies +-- ["Area"] = "", -- Continental_supplies ["Are we there yet?"] = "Sommes-nous toujours là ?", ["Are you accusing me of something?"] = "Es-tu en train de m'accuser de quelque chose ? ", ["Are you saying that many of us have died for your entertainment?"] = "Vous dites que beaucoup d'entre nous sont morts pour votre divertissement ? ", @@ -59,27 +76,35 @@ -- ["[Backspace]"] = "effacement arrière", --maybe the original name is better... ["Backstab"] = "Coup de poignard dans le dos", -- ["Bad Team"] = "", -- User_Mission_-_The_Great_Escape +-- ["Ballgun"] = "", -- Construction_Mode -- ["Bamboo Thicket"] = "", --really, i don't know the good translation for this ["Barrel Eater!"] = "Mangeur de barrils", ["Barrel Launcher"] = "Lanceur de barrils", --need the situation for me to understand sens of sentence +-- ["Barrel Placement Mode"] = "", -- Construction_Mode +-- ["Baseball Bat"] = "", -- Construction_Mode -- ["Baseballbat"] = "", -- Continental_supplies ["Bat balls at your enemies and|push them into the sea!"] = "Frappez vos ennemis à la batte|et envoyez-les à la mer !", ["Bat your opponents through the|baskets and out of the map!"] = "Frappez vos ennemis à la batte|, marquez des paniers ou envoyez-les à la mer !", +-- ["Bazooka"] = "", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 ["Bazooka Training"] = "Entraînement au Bazooka", -- ["Beep Loopers"] = "", ["Best laps per team: "] = "Meilleur temps par équipe", -- ["Best Team Times: "] = "", ["Beware, though! If you are slow, you die!"] = "Attention tout de même ! si tu es lent, tu meurt !", +-- ["Bio-Filter"] = "", -- Construction_Mode -- ["Biomechanic Team"] = "", +-- ["Birdy"] = "", -- Construction_Mode -- ["Blender"] = "", -- ["Bloodpie"] = "", -- ["Bloodrocutor"] = "", -- ["Bloodsucker"] = "", ["Bloody Rookies"] = "Nouvelles recrues", -- 01#Boot_Çamp, User_Mission_-_Dangerous_Ducklings, User_Mission_-_Diver, User_Mission_-_Spooky_Tree +-- ["Blowtorch"] = "", -- Construction_Mode, Frenzy +-- ["Blue Team"] = "", -- User_Mission_-_Dangerous_Ducklings -- ["Bone Jackson"] = "", ["Bonely"] = "Bonely", +-- ["BOOM!"] = "", -- ["Boom!"] = "", --- ["BOOM!"] = "", ["Boss defeated!"] = "Boss vaincu", ["Boss Slayer!"] = "Tueur de Boss !", -- ["Brain Blower"] = "", @@ -89,6 +114,7 @@ -- ["Brain Teaser"] = "", -- ["Brutal Lily"] = "", -- ["Brutus"] = "", +-- ["Build a fortress and destroy your enemy."] = "", -- Construction_Mode ["Build a track and race."] = "Construisez un parcours et faites la course.", ["Bullseye"] = "Dans le mille", ["But it proved to be no easy task!"] = "Mais cela ne s'avéra pas être une tâche facile !", @@ -99,17 +125,26 @@ ["But why would they help us?"] = "Mais pourquoi nous aideraient-ils ? ", ["But you're cannibals. It's what you do."] = "Mais vous êtes cannibales. C'est ce que vous faites.", ["But you said you'd let her go!"] = "Mais vous aviez dit que vous la laisseriez partir !", +-- ["Cake"] = "", -- Construction_Mode ["Çall me Beep! Well, 'cause I'm such a nice...person!"] = "Appelle-moi Beep ! Hum, parce que je suis du genre sympa !", ["Çannibals"] = "Çannibales", ["Çannibal Sentry"] = "Sentinelle cannibale", ["Çannibals?! You're the cannibals!"] = "Çannibales ? C'est vous les cannibales !", ["CAPTURE THE FLAG"] = "Çapturez le drapeau !", ["Çareless"] = "Imprudent", +-- ["Careless"] = "", -- User_Mission_-_That_Sinking_Feeling -- ["Çarol"] = "", -- ["CHALLENGE COMPLETE"] = "", -- User_Mission_-_RCPlane_Challenge ["Change Weapon"] = "Changez d'arme", +-- ["changing range from %i%% to %i%% with period of %i msec"] = "", -- Gravity ["Choose your side! If you want to join the strange man, walk up to him.|Otherwise, walk away from him. If you decide to att...nevermind..."] = "Choisis ton côté ! Si tu veux rejoindre l'étranger, marche vers lui. |Dans le cas contraire, éloigne toi de lui. Si tu décide de l'att...non laisse tomber...", +-- ["Cleaver"] = "", -- Construction_Mode +-- ["Cleaver Placement Mode"] = "", -- Construction_Mode +-- ["Climber"] = "", -- ClimbHome +-- ["Climb Home"] = "", -- ClimbHome +-- ["Clowns"] = "", -- User_Mission_-_Nobody_Laugh ["Clumsy"] = "Maladroit", +-- ["Cluster Bomb"] = "", -- Construction_Mode -- ["Cluster Bomb MASTER!"] = "", -- Basic_Training_-_Cluster_Bomb -- ["Cluster Bomb Training"] = "", -- Basic_Training_-_Cluster_Bomb ["Codename: Teamwork"] = "Nom de code : Travail d'équipe", @@ -129,12 +164,19 @@ -- ["Congratulations! You needed only half of time|to eliminate all targets."] = "", -- Basic_Training_-_Cluster_Bomb -- ["Congratulations! You've completed the Rope tutorial! |- Tutorial ends in 10 seconds!"] = "", -- Basic_Training_-_Rope ["Congratulations! You've eliminated all targets|within the allowed time frame."] = "Félicitations ! Vous avez éliminé toutes les cibles|dans le temps alloué.", --Bazooka, Shotgun, SniperRifle +-- ["CONSTRUCTION MODE"] = "", -- Construction_Mode +-- ["Construction Station"] = "", -- Construction_Mode -- ["Continental supplies"] = "", -- Continental_supplies ["Control pillars to score points."] = "Contrôlez les piliers pour marquer des points", +-- ["Core"] = "", -- Construction_Mode -- ["Corporationals"] = "", -- ["Corpsemonger"] = "", -- ["Corpse Thrower"] = "", +-- ["Cost"] = "", -- Construction_Mode +-- ["Crate Placement Tool"] = "", -- Construction_Mode -- ["Crates Left:"] = "", -- User_Mission_-_RCPlane_Challenge +-- ["Cricket time: [Drop a fireable mine! ~ Will work if fired close to your hog & far away from enemy ~ 1 sec]"] = "", -- Continental_supplies +-- ["Current setting is "] = "", -- Gravity ["Cybernetic Empire"] = "Empire cybernétique", ["Cyborg. It's what the aliens call themselves."] = "Cyborg. C'est ainsi que s'appellent les aliens entre eux.", -- ["Dahmer"] = "", @@ -142,14 +184,18 @@ ["DAMMIT, ROOKIE! GET OFF MY HEAD!"] = "Et merde, recrue ! Dégage de ma tête !", ["Dangerous Ducklings"] = "Çanetons dangereux", -- ["Deadweight"] = "poids mort/boulet", +-- ["Decrease"] = "", -- Continental_supplies ["Defeat the cannibals!|"] = "Bats les cannibales", ["Defeat the cannibals!|Grenade hint: set the timer with [1-5], aim with [Up]/[Down] and hold [Space] to set power"] = "Bat les cannibales ! |Astuce Grenade : règles le compte à rebour avec [1-5], vises avec [haut]/[bas] et maintiens [Espace] pour la puissance", ["Defeat the cyborgs!"] = "Bats les cyborgs !", +-- ["Defend your core from the enemy."] = "", -- Construction_Mode ["Defend yourself!|Hint: You can get tips on using weapons by moving your mouse over them in the weapon sélection menu"] = "Défends toi ! |Conseil : Tu peux obtenir des astuces sur l'utilisation des armes en plaçant ta souris dessus dans le menu de sélection des armes", +-- ["Dematerializes weapons and equipment carried by enemy hedgehogs."] = "", -- Construction_Mode ["Demolition is fun!"] = "La démolition c'est marrant", -- ["Dense Cloud"] = "", ["Dense Cloud must have already told them everything..."] = "Nuage Dense leur a sûrement déjà tout raconté...", -- ["Depleted Kamikaze!"] = "Kamikaze ... !", +-- ["Desert Eagle"] = "", -- Construction_Mode, A_Space_Adventure:death02 ["Destroy him, Leaks A Lot! He is responsible for the deaths of many of us!"] = "Détruis-le, Grosse Fuite ! Il est responsable de la mort de beaucoup des notres !", ["Destroy invaders to score points."] = "Détruisez les envahisseurs pour marquer des points", ["Destroy the targets!|Hint: Select the Shoryuken and hit [Space]|P.S. You can use it mid-air."] = "Détruis les cibles ! |Astuce : sélectionne le Shoryuken et appuyez sur [Espace] |P.S. vous pouvez l'utilisez en plein vol", @@ -168,9 +214,12 @@ ["Do you have any idea how valuable grass is?"] = "Est-ce que vous avez une idée de la valeur de votre herbe ?", ["Do you think you're some kind of god?"] = "Vous vous prenez pour un genre de dieu ?", ["Dragon's Lair"] = "La tanière du dragon", +-- ["Drill Rocket"] = "", -- Construction_Mode -- ["Drills"] = "", +-- ["Drill Strike"] = "", -- Construction_Mode ["Drone Hunter!"] = "Chasseur de drône", --- ["Drop a bomb: [drop some heroic wind that will turn into a bomb on impact]"] = "", -- Continental_supplies +-- ["Drop a bomb: [Drop some heroic wind that will turn into a bomb on impact]"] = "", -- Continental_supplies + -- ["Drowner"] = "",-- can't have a good translation, think its a merge of drone and owner so if wanna translate it will be : tueur de drone, wich is like drone hunter... ["Dude, all the plants are gone!"] = "Mec, toutes les plantes sont parties !", ["Dude, can you see Ramon and Spiky?"] = "Mec, peux tu voir Ramon et Spkiky ? ", @@ -180,11 +229,15 @@ ["Dude, where are we?"] = "Mec, on est où ? ", -- ["Dude, wow! I just had the weirdest high!"] = "", -- ["Duration"] = "", -- Continental_supplies --- ["Dust storm: [Deals 20 damage to all enemies in the circle]"] = "", -- Continental_supplies +-- ["Dust storm: [Deals 15 damage to all enemies in the circle]"] = "", -- Continental_supplies + +-- ["Dynamite"] = "", -- Construction_Mode +-- ["Each turn is only ONE SECOND!"] = "", -- Frenzy ["Each turn you get 1-3 random weapons"] = "À chaque tour, tu as 1 à 3 armes aléatoires", ["Each turn you get one random weapon"] = "À chaque tour, tu as une arme aléatoire", -- ["Eagle Eye"] = "", --- ["Eagle Eye: [Blink to the impact ~ one shot]"] = "", -- Continental_supplies +-- ["Eagle Eye: [Blink to the impact ~ One shot]"] = "", -- Continental_supplies + -- ["Ear Sniffer"] = "", -- ["Elderbot"] = "", -- ["Elimate your captor."] = "", -- User_Mission_-_The_Great_Escape @@ -207,9 +260,9 @@ ["Every single time!"] = "À chaque fois !", ["Everything looks OK..."] = "Tout a l'air d'être OK ...", ["Exactly, man! That was my dream."] = "Exactement, mec ! C'était mon rêve.", +-- ["Extra Damage"] = "", -- Construction_Mode +-- ["Extra Time"] = "", -- Construction_Mode ["Eye Chewer"] = "Mâcheur d'oeilr", --- ["INSANITY"] = "", -- Mutant - ["Get your teammates out of their natural prison and save the princess!|Hint: Drilling holes should solve everything.|Hint: It might be a good idea to place a girder before starting to drill. Just saying.|Hint: All your hedgehogs need to be above the marked height!|Hint: Leaks A Lot needs to get really close to the princess!"] = "Fais sortir tes coéquipiers de leur prison naturelle et sauve la princesse ! |Percer des trous résoudrait tout. |Ce serait une bonne idée de placer quelques poutres avant de commencer à percer. Moi j'dis ça mais j'dis rien. |Tous vos hérissons doivent être au dessus de la hauteur marquée ! | Grosse Fuite doit être très proche de la princesse ! ", ["Family Reunion"] = "Réunion de famille ", ["Fastest lap: "] = "Meilleur tour : ", ["Feeble Resistance"] = "Résistance Futile", @@ -219,6 +272,7 @@ -- ["Femur Lover"] = "", -- ["Fierce Competition!"] = "", -- Space_Invasion -- ["Fiery Water"] = "", +-- ["Filthy Blue"] = "", -- User_Mission_-_Dangerous_Ducklings ["Find your tribe!|Cross the lake!"] = "Trouve ta tribue ! |Traverse le lac !", ["Finish your training|Hint: Animations can be skipped with the [Precise] key."] = "Finis ton entraînement ! |Astuce : Les animations peuvent être passées en appuyant sur la touche [Precise]", -- ["Fire"] = "", @@ -232,11 +286,15 @@ ["Flag returned!"] = "Drapeau récupéré", ["Flags, and their home base will be placed where each team ends their first turn."] = "Les drapeaux et leur base seront placés là où chaque équipe finit son premier tour", -- ["Flamer"] = "", +-- ["Flamethrower"] = "", -- Construction_Mode -- ["Flaming Worm"] = "", --- ["Flare: [fire up some bombs depending on hogs depending on hogs in the circle"] = "", -- Continental_supplies + ["Flesh for Brainz"] = "Flesh for Brainz", +-- ["Flying Saucer"] = "", -- Construction_Mode, Frenzy -- ["For improved features/stability, play 0.9.18+"] = "", -- WxW ["Free Dense Cloud and continue the mission!"] = "Libérez Nuage Dense et continuez la mission !", +-- ["Freezer"] = "", -- Construction_Mode +-- ["FRENZY"] = "", -- Frenzy -- ["Friendly Fire!"] = "", ["fuel extended!"] = "Le plein d'essence !", ["GAME BEGUN!!!"] = "Le jeu a commencé !!!", @@ -246,6 +304,9 @@ ["Game? Was this a game to you?!"] = "Jeu ? Etait-ce un jeu pour vous ?!", -- ["GasBomb"] = "", -- Continental_supplies -- ["Gas Gargler"] = "", +-- ["General information"] = "", -- Continental_supplies +-- ["Generates power."] = "", -- Construction_Mode +-- ["Generator"] = "", -- Construction_Mode ["Get Dense Cloud out of the pit!"] = "Sortez Nuage Dense de la fosse", ["Get on over there and take him out!"] = "Viens par ici et débarrasse-toi de lui ! ", ["Get on the head of the mole"] = "Va sur la tête de la taupe", @@ -254,8 +315,11 @@ ["Get the crate on the other side of the island!|"] = "Prends la caisse de l'autre côté de l'île !", -- ["Get to the target using your rope! |Controls: Left & Right to swing the rope - Up & Down to Contract and Expand!"] = "", -- Basic_Training_-_Rope -- ["Get your teammates out of their natural prison and save the princess!|Hint: Drilling holes should solve everything.|Hint: It might be a good idea to place a girder before starting to drill. Just saying.|Hint: All your hedgehogs need to be above the marked height!|Hint: Leaks A Lot needs to get really close to the princess!"] = "", -- A_Classic_Fairytale:family + ["Get your teammates out of their natural prison and save the princess!|Hint: Drilling holes should solve everything.|Hint: It might be a good idea to place a girder before starting to drill. Just saying.|Hint: All your hedgehogs need to be above the marked height!|Hint: Leaks A Lot needs to get really close to the princess!"] = "Fais sortir tes coéquipiers de leur prison naturelle et sauve la princesse ! |Percer des trous résoudrait tout. |Ce serait une bonne idée de placer quelques poutres avant de commencer à percer. Moi j'dis ça mais j'dis rien. |Tous vos hérissons doivent être au dessus de la hauteur marquée ! | Grosse Fuite doit être très proche de la princesse ! ", -- ["GG!"] = "", -- User_Mission_-_Rope_Knock_Challenge -- ["Gimme Bones"] = "", +-- ["Girder"] = "", -- Construction_Mode +-- ["Girder Placement Mode"] = "", -- Construction_Mode -- ["Glark"] = "", -- ["Goal"] = "", -- ["GO! GO! GO!"] = "", @@ -272,19 +336,24 @@ -- ["Go surf!"] = "", -- WxW -- ["GOTCHA!"] = "je t'ai eu !", is this good ? ["Grab Mines/Explosives"] = "Emparez vous des Mines/Explosifs", +-- ["Grants nearby hogs life-regeneration."] = "", -- Construction_Mode +-- ["Gravity"] = "", -- Gravity ["Great choice, Steve! Mind if I call you that?"] = "Bon choix, Steve ! Ça t'ennuie si je t'appele comme ça ?", -- ["Great work! Now hit it with your Baseball Bat! |Tip: You can change weapon with 'Right Click'!"] = "", -- Basic_Training_-_Rope ["Great! You will be contacted soon for assistance."] = "Super ! Tu seras bientot contacté pour de l'aide.", --- ["Green lipstick bullet: [Is poisonous]"] = "", -- Continental_supplies + +-- ["Green lipstick bullet: [Poisonous, deals no damage]"] = "", -- Continental_supplies ["Greetings, cloudy one!"] = "Salutation, le nuageux !", ["Greetings, "] = "Salutations, ", +-- ["Grenade"] = "", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 -- ["Grenade Training"] = "", -- Basic_Training_-_Grenade -- ["Grenadiers"] = "", -- Basic_Training_-_Grenade ["Guys, do you think there's more of them?"] = "Les gars, vous pensez qu'il y en a encore plus ?", --- ["Hahahaha!"] = "", +-- ["HAHA!"] = "", -- ["Haha!"] = "", --- ["HAHA!"] = "", +-- ["Hahahaha!"] = "", ["Haha, now THAT would be something!"] = "Haha, maintenant ÇA, ça va être quelquechose !", +-- ["Hammer"] = "", -- Construction_Mode, Continental_supplies ["Hannibal"] = "Hannibal", -- ["Hapless Hogs"] = "", -- [" Hapless Hogs left!"] = "", @@ -292,15 +361,19 @@ -- ["Hatless Jerry"] = "", ["Have no illusions, your tribe is dead, indifferent of your choice."] = "N'aies pas d'illusion, ta tribue est morte, quel que soit ton choix", ["Have we ever attacked you first?"] = "Avons-nous jamais attaqué en premier ? ", +-- ["Healing Station"] = "", -- Construction_Mode +-- ["Health Crate Placement Mode"] = "", -- Construction_Mode ["Health crates extend your time."] = "Les caisses de vie augmentent votre temps.", -- ["Heavy"] = "", -- ["Heavy Çannfantry"] = "", -- ["Hedge-cogs"] = "", --- ["Hedgehog projectile: [fire your hog like a Sticky Bomb]"] = "", -- Continental_supplies +-- ["Hedgehog projectile: [Fire your hog like a Sticky Bomb]"] = "", -- Continental_supplies + -- ["Hedgewars-Basketball"] = "", -- ["Hedgewars-Knockball"] = "", -- ["Hedgibal Lecter"] = "", ["Heh, it's not that bad."] = "Hé, c'est pas si mal.", +-- ["Hellish Handgrenade"] = "", -- Construction_Mode ["Hello again, "] = "Re-bonjour,", ["Help me, Leaks!"] = "Aide moi, Fuite !", ["Help me, please!!!"] = "Aide moi, s'il te plaît !!!", @@ -332,6 +405,7 @@ -- ["Hogminator"] = "", -- ["Hogs in sight!"] = "", -- Continental_supplies -- ["HOLY SHYTE!"] = "", -- Mutant +-- ["Homing Bee"] = "", -- Construction_Mode -- ["Honest Lee"] = "", ["Hooray!"] = "Hourra ! ", ["Hostage Situation"] = "Situation d'otage", @@ -387,6 +461,7 @@ ["I'm not sure about that!"] = "Je n'en suis pas si sûr !", ["Impressive...you are still dry as the corpse of a hawk after a week in the desert..."] = "Impressionnant...tu es aussi sec que le cadavre d'un faucon après une semaine dans le désert...", ["I'm so scared!"] = "J'ai tellement peur !", +-- ["Increase"] = "", -- Continental_supplies ["Incredible..."] = "Incroyable...", ["I need to find the others!"] = "Je dois trouver les autres !", ["I need to get to the other side of this island, fast!"] = "Je dois aller sur l'autre côté de cette île, rapidemment !", @@ -395,12 +470,14 @@ ["I need to warn the others."] = "Je dois avertir les autres.", ["In fact, you are the only one that's been acting strangely."] = "En fait, tu es le seul qui ait agi étrangement.", ["In order to get to the other side, you need to collect the crates first.|"] = "Dans le but d'atteindre l'autre coté, tu dois d'abord collecter les caisses ", +-- ["INSANITY"] = "", -- Mutant ["Instructor"] = "Instructeur", -- 01#Boot_Çamp, User_Mission_-_Dangerous_Ducklings ["Interesting idea, haha!"] = "Idee intéressante, haha !", ["Interesting! Last time you said you killed a cannibal!"] = "Intéressant ! La dernière fois tu as dit que tu avais tué un cannibale !", -- ["In the meantime, take these and return to your \"friend\"!"] = "", -- A_Classic_Fairytale:shadow ["invaders destroyed"] = "Envahisseur détruit", ["Invasion"] = "Invasion", +-- ["Invulnerable"] = "", -- Construction_Mode ["I saw it with my own eyes!"] = "Je l'ai vu de mes propres yeux !", ["I see..."] = "Je vois...", ["I see you have already taken the leap of faith."] = "Je vois que tu as déjà fait le saut de la foi.", @@ -442,6 +519,7 @@ ["Just kidding, none of you have died!"] = "Je rigole, aucun d'entre vous n'est mort !", ["Just on a walk."] = "Je faisais juste une promenade", ["Just wait till I get my hands on that trauma! ARGH!"] = "Attends un peu que je mette la main sur ce traumatisme ! ARGH !", +-- ["Kamikaze"] = "", -- Construction_Mode -- ["Kamikaze Expert!"] = "", -- ["Keep it up!"] = "", -- ["Kerguelen"] = "", -- Continental_supplies @@ -451,6 +529,8 @@ -- ["Kill the aliens!"] = "", ["Kill the cannibal!"] = "Tue le cannibale !", ["Kill the traitor...or spare his life!|Kill him or press [Precise]!"] = "Tue le traître... ou épargne sa vie ! |Tue le ou appuie sur [Precise] !", +-- ["Land Sprayer"] = "", -- Construction_Mode +-- ["Laser Sight"] = "", -- Construction_Mode ["Last Target!"] = "Dernière cible !", -- ["Leader"] = "", -- ["Leaderbot"] = "", @@ -460,6 +540,7 @@ ["Leaks A Lot must survive!"] = "Grosse Fuite doit survivre !", -- ["Led Heart"] = "", -- ["Lee"] = "", +-- ["left shift"] = "", -- Continental_supplies -- ["[Left Shift]"] = "",-- touche majuscule gauche -- ["Let a Continent provide your weapons!"] = "", -- Continental_supplies ["Let me test your skills a little, will you?"] = "Laisse-moi te tester un peu, veux-tu ?", @@ -470,41 +551,56 @@ ["Let them have a taste of my fury!"] = "Ils vont goûter de ma fureur !", ["Let us help, too!"] = "Allons aider nous aussi !", -- ["Light Çannfantry"] = "", +-- ["Limburger"] = "", -- Construction_Mode ["Listen up, maggot!!"] = "Écoutez, asticots", ["Little did they know that this hunt will mark them forever..."] = "Savait-il que cette chasse allait les marquer à jamais...", -- ["Lively Lifeguard"] = "", --- ["Lonely Cries: [Rise the water if no hog is in the circle and deal 1 damage to all hogs]"] = "", -- Continental_supplies + +-- ["Lonely Cries: [Rise the water if no hog is in the circle and deal 7 damage to all enemy hogs]"] = "", -- Continental_supplies +-- ["Lonely Hog"] = "", -- ClimbHome ["Look, I had no choice!"] = "Écoute, je n'avais pas le choix !", ["Look out! There's more of them!"] = "Regarde, il y en a encore plus !", ["Look out! We're surrounded by cannibals!"] = "Regarde ! Nous sommes entourés par les cannibales !", ["Looks like the whole world is falling apart!"] = "On dirait que le monde entier tombe en morceaux !", +-- ["Low Gravity"] = "", -- Construction_Mode, Frenzy ["Luckily, I've managed to snatch some of them."] = "Heureusement, j'ai réussi à en avoir quelques unes", -- ["LUDICROUS KILL"] = "", -- Mutant +-- ["Made it!"] = "", -- ClimbHome +-- ["- Massive weapon bonus on first turn"] = "", -- Continental_supplies ["May the spirits aid you in all your quests!"] = "Puissent les esprits t'aider dans tes quêtes !", -- ["Medicine: [Fire some exploding medicine that will heal all hogs effected by the explosion]"] = "", -- Continental_supplies -- ["MEGA KILL"] = "", -- Mutant -- ["Meiwes"] = "", -- ["Mindy"] = "", +-- ["Mine"] = "", -- Construction_Mode, Frenzy -- ["Mine Deployer"] = "", ["Mine Eater!"] = "Mangeur de Mines", +-- ["Mine Placement Mode"] = "", -- Construction_Mode -- ["|- Mines Time:"] = "", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork +-- ["Mine Strike"] = "", -- Construction_Mode ["MISSION FAILED"] = "Mission échouée", -- User_Mission_-_Dangerous_Ducklings, User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork ["MISSION SUCCESSFUL"] = "Mission réussie", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork ["MISSION SUCCESS"] = "SUCCÈS DE LA MISSION", +-- ["Molotov Cocktail"] = "", -- Construction_Mode -- ["Molotov"] = "", -- Continental_supplies -- ["MONSTER KILL"] = "", -- Mutant ["More Natives"] = "Plus d'indigènes", +-- ["Mortar"] = "", -- Construction_Mode, A_Space_Adventure:death02 ["Movement: [Up], [Down], [Left], [Right]"] = "Mouvement: [haut], [bas], [gauche], [droite]", +-- ["Mudball"] = "", -- Construction_Mode -- ["Multi-shot!"] = "", -- ["Muriel"] = "", ["Muscle Dissolver"] = "Monsieur Muscle", -- ["-------"] = "", -- Mutant +-- ["Mutant"] = "", -- Mutant -- ["Nade Boy"] = "", -- Basic_Training_-_Grenade -- ["Name"] = "", ["Nameless Heroes"] = "Héros sans noms", -- ["Nancy Screw"] = "", +-- ["Napalm"] = "", -- Construction_Mode -- ["Napalm rocket: [Fire a bomb with napalm!]"] = "", -- Continental_supplies ["Natives"] = "Indigènes", +-- ["Naughty Ninja"] = "", -- User_Mission_-_Dangerous_Ducklings ["New Barrels Per Turn"] = "Nouveaux barrils par tour", -- ["NEW CLAN RECORD: "] = "", ["NEW fastest lap: "] = "Nouveau meilleur temps", @@ -515,13 +611,15 @@ ["Nice work, "] = "Beau boulot, ", ["Nice work!"] = "Beau travail !", -- ["Nilarian"] = "", +-- ["Nobody Laugh"] = "", -- User_Mission_-_Nobody_Laugh ["No, I came back to help you out..."] = "Non je suis revenu pour t'aider...", ["No...I wonder where they disappeared?!"] = "Non...Je me demande où ils ont disparu ?!", +-- ["Nom-Nom"] = "", -- ["NomNom"] = "", --- ["Nom-Nom"] = "", ["Nope. It was one fast mole, that's for sure."] = "Non. C'était une taupe rapide, ça c'est certain.", ["No! Please, help me!"] = "Non ! S'il te plaît, aide moi !", -- ["NORMAL"] = "", -- Continental_supplies +-- ["Normal players can only score points by killing the mutant."] = "", -- Mutant -- ["North America"] = "", -- Continental_supplies -- ["Not all hogs are born equal."] = "", -- Highlander ["NOT ENOUGH WAYPOINTS"] = "Pas assez de points de passage", @@ -534,6 +632,7 @@ ["No. Where did he come from?"] = "Non. D'où est-il venu ?", ["Now how do I get on the other side?!"] = "Maintenant, comment je me rends de l'autre coté ?", ["No. You and the rest of the tribe are safer there!"] = "Non, toi et le reste de la tribu êtes plus en sécurité ici ! ", +-- ["Object Placement Tool"] = "", -- Construction_Mode -- ["Obliterate them!|Hint: You might want to take cover..."] = "", ["Obstacle course"] = "Course d'obstacles", ["Of course I have to save her. What did I expect?!"] = "Bien sûr je dois la sauver. Qu'est ce que j'imaginais ?", @@ -550,21 +649,29 @@ ["Once upon a time, on an island with great natural resources, lived two tribes in heated conflict..."] = "Il était une fois, sur une île possédant de grandes ressources naturelles, vivaient deux tribus en violent conflit...", -- ["ONE HOG PER TEAM! KILLING EXCESS HEDGES"] = "", -- Mutant ["One tribe was peaceful, spending their time hunting and training, enjoying the small pleasures of life..."] = "L'une des deux tribus était pacifique, passant son temps à chasser et à s'entraîner, appréciant les petits plaisirs de la vie", +-- ["on Skip"] = "", -- Continental_supplies ["Oops...I dropped them."] = "Oups ... Je les ai laissées tomber.", ["Open that crate and we will continue!"] = "Ouvre cette caisse et nous pourrons continuer", -- ["Operation Diver"] = "", ["Opposing Team: "] = "Équipe opposée", +-- ["or 'g=50, g2=150, period=4000' for gravity changing|from 50 to 150 and back with period of 4000 msec"] = "", -- Gravity -- ["Orlando Boom!"] = "", +-- ["Other kills don't give you points."] = "", -- Mutant -- ["Ouch!"] = "", -- User_Mission_-_Rope_Knock_Challenge ["Our tribe, our beautiful island!"] = "Notre tibu, notre belle ile !", -- ["Parachute"] = "", -- Continental_supplies ["Pathetic Hog #%d"] = "Hérisson pathétique #%d", -- ["Pathetic Resistance"] = "", -- User_Mission_-_Bamboo_Thicket, User_Mission_-_Newton_and_the_Hammock +-- ["Penguin roar: [Deal 15 damage + 15% of your hogs health to all hogs around you and get 2/3 back]"] = "", -- Continental_supplies ["Perfect! Now try to get the next crate without hurting yourself!"] = "Parfait, maintenant essaies d'avoir la prochaine caisse sans te blesser !", ["Per-Hog Ammo"] = "Munitions par hérissons", --- ["- Per team weapons|- 9 weaponschemes|- Unique new weapons| |Select continent first round with the Weapon Menu or by ([switch/tab]=Increase,[precise/left shift]=Decrease) on Skip|Some weapons have a second option. Find them with [switch/tab]"] = "", -- Continental_supplies +-- ["Personal Portal Device"] = "", -- Construction_Mode + +-- ["Per team weapons"] = "", -- Continental_supplies ["Pfew! That was close!"] = "Ouf! C'est pas passé loin !", --- ["Piñata bullet: [Contains some sweet candy!]"] = "", -- Continental_supplies +-- ["Piano Strike"] = "", -- Construction_Mode +-- ["Pickhammer"] = "", -- Construction_Mode + -- ["Pings left:"] = "", -- Space_Invasion ["Place more waypoints using the 'Air Attack' weapon."] = "Place plus de points de passage avec l'arme : attaque aérienne.", -- ["Planes Used:"] = "", -- User_Mission_-_RCPlane_Challenge @@ -574,15 +681,19 @@ -- ["Please place the way-point in the open, within the map boundaries."] = "", -- Racer -- ["Please, stop releasing your \"smoke signals\"!"] = "", -- A_Classic_Fairytale:shadow -- ["Point Blank Combo!"] = "", -- Space_Invasion +-- ["POINTS"] = "", -- Mutant ["points"] = "points", -- Control, CTF_Blizzard, Basic_Training_-_Bazooka, Basic_Training_-_Shotgun, Basic_Training_-_Sniper_Rifle ["Poison"] = "Poison", +-- ["Population"] = "", -- Continental_supplies ["Portal hint: one goes to the destination, and one is the entrance.|"] = "Astuce du Portail : l'un est la destination, l'autre est l'entrée ", -- ["Portal mission"] = "", -- portal -- ["Power Remaining"] = "", ["Prepare yourself"] = "Prépare toi", +-- ["presice"] = "", -- Continental_supplies -- ["Press [Enter] to accept this configuration."] = "", -- WxW ["Press [Left] or [Right] to move around, [Enter] to jump"] = "Appuyez [Gauche] ou [Droite] pour vous déplacer, [Entrée] pour sauter", ["Press [Precise] to skip intro"] = "appuie sur [precise] pour passer l'intro", +-- ["Prestigious Pilot"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Private Novak"] = "", -- Basic_Training_-_Cluster_Bomb ["Protect yourselves!|Grenade hint: set the timer with [1-5], aim with [Up]/[Down] and hold [Space] to set power"] = "Protège toi ! |Astuce Grenade : Règle le compte à rebour avec [1-5], vise avec [haut]/[bas] et maintiens [Espace] pour la puissance", -- ["Race complexity limit reached."] = "", @@ -591,26 +702,40 @@ -- ["Radar Ping"] = "", -- Space_Invasion -- ["Raging Buffalo"] = "", -- ["Ramon"] = "", +-- ["random in range from %i%% to %i%% with period of %i msec"] = "", -- Gravity +-- ["RC Plane"] = "", -- Construction_Mode -- ["RC PLANE TRAINING"] = "", -- User_Mission_-_RCPlane_Challenge ["Really?! You thought you could harm me with your little toys?"] = "Vraiment ? Tu pensais pouvoir me blesser avec tes petits jouets ?", +-- ["Reflector Shield"] = "", -- Construction_Mode +-- ["Reflects enemy projectiles."] = "", -- Construction_Mode -- ["Regurgitator"] = "", -- ["Reinforcements"] = "", -- ["Remember: The rope only bend around objects, |if it doesn't hit anything it's always stright!"] = "", -- Basic_Training_-_Rope ["Remember this, pathetic animal: when the day comes, you will regret your blind loyalty!"] = "Souviens toi, pathétique animal : quand le jour viendra, tu regretteras ton aveugle loyauté !", +-- ["REMOVED"] = "", -- Continental_supplies +-- ["Respawner"] = "", -- Construction_Mode +-- ["Resurrector"] = "", -- Construction_Mode +-- ["Resurrects dead hedgehogs."] = "", -- Construction_Mode [" - Return the enemy flag to your base to score | - First team to 3 captures wins | - You may only score when your flag is in your base | - Hogs will drop the flag if killed, or drowned | - Dropped flags may be returned or recaptured | - Hogs respawn when killed"] = "Ramenez le drapeau ennemi dans votre base pour marquer | -La première équipe à 3 captures gagne | - Vous marquez uniquement si votre drapeau est dans votre base | - Les hérissons vont lâcher le drapeau s'ils sont tués ou noyés | - Les drapeaux lâchés peuvent être ramenés ou recapturés | - Les hérissons réapparaissent quand ils sont tués", ["Return to Leaks A Lot! If you get stuck, press [Precise] to try again!"] = "Retourne vers Grosse Fuite ! Si tu es bloqué, appuie sur [Precise] pour réessayer !", -- ["Righteous Beard"] = "Righteous Beard", +-- ["Rope"] = "", -- Construction_Mode -- ["ROPE-KNOCKING"] = "", -- User_Mission_-_Rope_Knock_Challenge +-- ["Rope to safety"] = "", -- ClimbHome -- ["Rope Training"] = "", -- Basic_Training_-_Rope ["Rot Molester"] = "Rot Molester", -- ["Round Limit:"] = "", -- ["Round Limit"] = "", -- ["Rounds Complete: "] = "", -- ["Rounds Complete"] = "", +-- ["Rubber Band"] = "", -- Construction_Mode +-- ["Rubber Placement Mode"] = "", -- Construction_Mode +-- ["RULES"] = "", -- Frenzy, Mutant ["RULES OF THE GAME [Press ESC to view]"] = "RÈGLES DU JEU | [Appuyez Échap pour voir]", -- ["Rusty Joe"] = "", -- ["s|"] = "", --- ["Sabotage: [Sabotage all hogs in the circle and deal ~10 dmg]"] = "", -- Continental_supplies +-- ["Sabotage/Flare: [Sabotage all hogs in the circle and deal ~1 dmg OR Fire a cluster up into the air]"] = "", -- Continental_supplies + -- ["Salivaslurper"] = "", ["Salvation"] = "Le salut", ["Salvation was one step closer now..."] = "Le salut était tout proche...", @@ -622,7 +747,7 @@ -- ["Scalp Muncher"] = "", -- ["SCORE"] = "", -- ["Score"] = "", -- Mutant --- ["Scream from a Walrus: [Deal 20 damage + 10% of your hogs health to all hogs around you and get half back]"] = "", -- Continental_supplies + -- ["sec"] = "", -- CTF_Blizzard, TrophyRace, Basic_Training_-_Bazooka, Basic_Training_-_Shotgun, Basic_Training_-_Sniper_Rifle, User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork, Çapture_the_Flag -- ["Seduction"] = "", -- Continental_supplies -- ["Seems like every time you take a \"walk\", the enemy find us!"] = "", -- A_Classic_Fairytale:backstab @@ -630,8 +755,11 @@ ["See ya!"] = "Bye bye", -- ["Segmentation Paul"] = "", -- ["Select continent!"] = "", -- Continental_supplies +-- ["Select continent first round with the Weapon Menu or by"] = "", -- Continental_supplies ["Select difficulty: [Left] - easier or [Right] - harder"] = "Choisis la difficulté : [Gauche] : plus facile, ou [Droite] : plus dur", -- ["selected!"] = "", +-- ["Set period to negative value for random gravity"] = "", -- Gravity +-- ["Setup:|'g=150', where 150 is 150% of normal gravity"] = "", -- Gravity -- ["s"] = "", -- GaudyRacer, Space_Invasion ["... share your beauty with the world every morning, my princess!"] = "...partage ta beauté avec le monde chaque matin, ma princesse !", ["She's behind that tall thingy."] = "Elle est derrière ce grand truc.", @@ -643,16 +771,21 @@ ["Shield OFF:"] = "Bouclier OFF", ["Shield ON:"] = "Bouclier ON", -- ["Shield Seeker!"] = "", +-- ["Shoryuken"] = "", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 -- ["Shotgun"] = "", -- Continental_supplies ["Shotgun Team"] = "Équipe de choc", ["Shotgun Training"] = "Entraînement au fusil", ["shots remaining."] = "Tirs restants", -- ["Silly"] = "", +-- ["SineGun"] = "", -- Construction_Mode -- ["Sinky"] = "", -- ["Sirius Lee"] = "", ["%s is out and Team %d|scored a penalty!| |Score:"] = "%s est dehors et l'équipe %d| reçoit une pénalité ! | |Score : ", -- Basketball, Knockball ["%s is out and Team %d|scored a point!| |Score:"] = "%s est dehors et l'équipe %d| reçoit un point ! | |Score : ", -- Basketball, Knockball ["Slippery"] = "Glissant", +-- ["Slot"] = "", -- Frenzy +-- ["Slot keys save time! (F1-F10 by default)"] = "", -- Frenzy +-- ["SLOTS"] = "", -- Frenzy -- ["Smith 0.97"] = "", -- ["Smith 0.98"] = "", -- ["Smith 0.99a"] = "", @@ -664,6 +797,7 @@ ["Sniper Training"] = "Entraînement au fusil de sniper", ["Sniperz"] = "Snipers", ["So humiliating..."] = "Si humiliant...", +-- ["Some weapons have a second option. Find them with"] = "", -- Continental_supplies -- ["South America"] = "", -- Continental_supplies ["So? What will it be?"] = "Alors ? Qu'est ce que ce sera ?", -- ["Spawn the crate, and attack!"] = "", -- WxW @@ -672,25 +806,43 @@ -- ["Spleenlover"] = "", -- ["Sponge"] = "éponde",--?? ["Spooky Tree"] = "Arbre fantomatique", +-- ["Sprite Placement Mode"] = "", -- Construction_Mode +-- ["Sprite Testing Mode"] = "", -- Construction_Mode -- ["STATUS UPDATE"] = "", -- GaudyRacer, Space_Invasion -- ["Steel Eye"] = "", ["Step By Step"] = "Pas à Pas", -- ["Steve"] = "", -- ["Sticky Mine"] = "", -- Continental_supplies +-- ["Sticky Mine Placement Mode"] = "", -- Construction_Mode -- ["Stronglings"] = "", --- ["Structure"] = "", -- Continental_supplies + +-- ["Structure Placement Mode"] = "", -- Construction_Mode +-- ["Structure Placement Tool"] = "", -- Construction_Mode +-- ["Sundaland"] = "", -- Continental_supplies -- ["Super Weapons"] = "", -- WxW +-- ["Support Station"] = "", -- Construction_Mode -- ["Surf Before Crate"] = "", -- WxW -- ["Surfer! +15 points!"] = "", -- Space_Invasion -- ["Surfer!"] = "", -- WxW ["Survive!|Hint: Cinematics can be skipped with the [Precise] key."] = "Survis ! Les cinématique peuvent être passées avec la touche [Precise]. ", ["Swing, Leaks A Lot, on the wings of the wind!"] = "Balance toi Grosse Fuite, sur les ailes du vent", +-- ["switch"] = "", -- Continental_supplies -- ["Switched to "] = "", +-- ["Switch Hog"] = "", -- Construction_Mode -- ["Syntax Errol"] = "", +-- ["tab"] = "", -- Continental_supplies +-- ["Tagging Mode"] = "", -- Construction_Mode ["Talk about mixed signals..."] = "Parlons des signaux mélangés", +-- ["Tardis"] = "", -- Construction_Mode +-- ["Target Placement Mode"] = "", -- Construction_Mode ["Team %d: "] = "Équipe %d : ", -- ["Team Scores"] = "", -- Control, Space_Invasion +-- ["Teleporation Node"] = "", -- Construction_Mode +-- ["Teleportation Mode"] = "", -- Construction_Mode +-- ["Teleportation Node"] = "", -- Construction_Mode +-- ["Teleport"] = "", -- Construction_Mode, Frenzy ["Teleport hint: just use the mouse to select the destination!"] = "Téléporte : utilise la souris pour sélectionner la destination !", +-- ["Teleport Unsuccessful. Please teleport within a clan teleporter's sphere of influence."] = "", -- Construction_Mode ["Thanks!"] = "Merci !", ["Thank you, my hero!"] = "Merci, mon héros !", ["Thank you, oh, thank you, Leaks A Lot!"] = "Merci, oh, merci, Grosse Fuite !", @@ -707,6 +859,7 @@ ["That was pointless."] = "C'était inutile.", ["The answer is...entertaintment. You'll see what I mean."] = "La réponse est... divertissement. Tu comprendras ce que je veux dire", -- ["The anti-portal zone is all over the floor, and I have nothing to kill him...Droping something could hurt him enough to kill him..."] = "", -- portal +-- ["The Bottom Feeder can score points by killing anyone."] = "", -- Mutant ["The Bull's Eye"] = "Dans le mille", ["The caves are well hidden, they won't find us there!"] = "Les cavernes sont bien cachées, ils ne nous y trouverons pas !", ["The Crate Frenzy"] = "Frénésie de caisses", @@ -716,20 +869,26 @@ ["The Enemy Of My Enemy"] = "Les ennemis de mes ennemis", ["The First Blood"] = "Le premier sang", ["The First Encounter"] = "La première rencontre", +-- ["The first player to kill someone becomes the Mutant."] = "", -- Mutant ["The flag will respawn next round."] = "Le drapeau va réapparaitre au prochain tour", ["The food bites back"] = "La nourriture mord en retour", ["The giant umbrella from the last crate should help break the fall."] = "La toile géante de la dernière caisse devrait aider à arrêter la chute.", -- ["The Great Escape"] = "", -- User_Mission_-_The_Great_Escape +-- ["The Great Hog in the sky sees your sadness and grants you a boon."] = "", -- Construction_Mode ["The guardian"] = "Le gardien", ["The Individualist"] = "L'individualiste", ["Their buildings were very primitive back then, even for an uncivilised island."] = "Leurs bâtiments étaient très primitif à l'époque, même pour une ile non civilisée.", ["The Journey Back"] = "Le voyage du retour", ["The Leap of Faith"] = "Le saut de la foi", ["The Moonwalk"] = "La Marche Lunaire", +-- ["The Mutant has super-weapons and a lot of health."] = "", -- Mutant +-- ["The Mutant loses health quickly if he doesn't keep scoring kills."] = "", -- Mutant ["The Nameless One"] = "Le sans nom", -- ["The next one is pretty hard! |Tip: You have to do multiple swings!"] = "", -- Basic_Training_-_Rope ["Then how do they keep appearing?"] = "Alors, comment continuent-il à apparaître ?", ["The other one were all cannibals, spending their time eating the organs of fellow hedgehogs..."] = "L'autre était une tribu de cannibales, ils passaient leur temps à manger les organes d'autres hérissons...", +-- ["The player with least points (or most deaths) becomes the Bottom Feeder."] = "", -- Mutant +-- ["There are a variety of structures available to aid you."] = "", -- Construction_Mode ["There must be a spy among us!"] = "Il doit y avoir un espion parmi nous", ["There's more of them? When did they become so hungry?"] = "Il y en encore ? Quand sont-ils devenu si affamés ?", ["There's nothing more satisfying for me than seeing you share your beauty with the world every morning, my princess!"] = "Il n'y a rien de plus satisfaisant pour moi que de te voir partager ta beauté avec le monde chaque matin, ma princesse !", @@ -754,6 +913,7 @@ -- ["The what?!"] = "", ["The wind whispers that you are ready to become familiar with tools, now..."] = "Le vent me murmure que tu es maintenant prêt à te familiariser avec les outils ...", ["They are all waiting back in the village, haha."] = "Ils attendent tous au village, haha.", +-- ["They Call Me Bullseye!"] = "", -- Space_Invasion -- ["They Çall Me Bullseye!"] = "", -- Space_Invasion ["They have weapons we've never seen before!"] = "Ils ont des armes que nous n'avons jamais vu avant !", -- ["They keep appearing like this. It's weird!"] = "", @@ -785,7 +945,7 @@ ["To the caves..."] = "Aux cavernes...", ["Toxic Team"] = "Équipe toxique", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork ["TRACK COMPLETED"] = "COURSE COMPLÉTÉE", - ["TRACK FAILED!"] = "COURSE RATÉE", + -- ["training"] = "", -- portal ["Traitors"] = "Traîtres", -- ["Tribe"] = "", @@ -802,6 +962,7 @@ -- ["ULTRA KILL"] = "", -- Mutant ["Under Construction"] = "En construction", -- ["Unexpected Igor"] = "", +-- ["Unique new weapons"] = "", -- Continental_supplies -- ["Unit"] = "", -- ["Unit 0x0007"] = "", -- ["Unit 334a$7%;.*"] = "", @@ -816,11 +977,15 @@ ["Use it wisely!"] = "à utiliser intelligemment", ["Use it with precaution!"] = "À utiliser avec précaution", -- ["User Challenge"] = "", +-- ["Use the air-attack weapons and the arrow keys to select structures."] = "", -- Construction_Mode ["Use the parachute ([Space] while in air) to get the next crate"] = "Utilisez le parachute ([Espace] en vol) pour atteindre la prochaine caisse ", ["Use the portal gun to get to the next crate, then use the new gun to get to the final destination!|"] = "Utilisez le fusil à portail pour atteindre la prochaine caisse, puis utilisez le nouveau fusil pour atteindre la destination finale", ["Use the rope to get on the head of the mole, young one!"] = "Utilise le grappin pour atteindre la tête de la taupe, le bleu !", -- ["Use the rope to knock your enemies to their doom."] = "", -- User_Mission_-_Rope_Knock_Challenge +-- ["Use your ready time to think."] = "", -- Frenzy ["Use your rope to get from start to finish as fast as you can!"] = "Utilisez votre Grappin pour aller du début à la fin aussi vite que vous pouvez !", +-- ["Utility Crate Placement Mode"] = "", -- Construction_Mode +-- ["Vampirism"] = "", -- Construction_Mode ["Vedgies"] = "Vedgies", -- ["Vegan Jack"] = "", -- ["Victory!"] = "", -- Basic_Training_-_Rope @@ -832,10 +997,14 @@ -- ["Wannabe Flyboys"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Wannabe Shoppsta"] = "", -- User_Mission_-_Rope_Knock_Challenge ["Watch your steps, young one!"] = "Regarde ou tu marches le bleu !", +-- ["Watermelon Bomb"] = "", -- Construction_Mode ["Waypoint placed."] = "Point de passage placé.", ["Way-Points Remaining"] = "Points de passage restants", ["Weaklings"] = "Faiblesses", ["We all know what happens when you get frightened..."] = "Nous savons tous ce qui arrive quand tu es effrayé", +-- ["Weapon Crate Placement Mode"] = "", -- Construction_Mode +-- ["Weapon Filter"] = "", -- Construction_Mode +-- ["weaponschemes"] = "", -- Continental_supplies ["Weapons Reset"] = "Armes réinitialisées", -- ["Weapons reset."] = "", -- Highlander ["We are indeed."] = "Nous le sommes, en effet.", @@ -887,6 +1056,7 @@ ["Where do you get that?!"] = "D'où ça vous vient ?!!", ["Where have you been?!"] = "Où étais-tu ?!", ["Where have you been?"] = "Où étais-tu ? ", +-- ["Whip"] = "", -- Construction_Mode -- ["? Why?"] = "", -- A_Classic_Fairytale:backstab -- ["Why "] = "", -- A_Classic_Fairytale:backstab -- ["! Why?!"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united @@ -899,8 +1069,10 @@ ["Why me?!"] = "Pourquoi moi ?!", ["Why would they do this?"] = "Pourquoi feraient-ils ça ?", -- ["- Will Get 1-3 random weapons"] = "", -- Continental_supplies --- ["- Will refresh Parachute each turn."] = "", -- Continental_supplies --- ["- Will refresh portalgun each turn."] = "", -- Continental_supplies +-- ["- Will give you an airstrike every fifth turn."] = "", -- Continental_supplies +-- ["- Will give you a parachute every second turn."] = "", -- Continental_supplies + + -- ["Will this ever end?"] = "", -- ["WINNER IS "] = "", -- Mutant ["WINNING TIME: "] = "Temps gagnant : ", @@ -919,6 +1091,7 @@ ["Yes!"] = "Oui !", ["Yes, yeees! You are now ready to enter the real world!"] = "Oui, Ouiii ! Maintenant tu es prêt à entrer dans le monde réel !", ["Yo, dude, we're here, too!"] = "Yo mec, on est là aussi !", +-- ["You are far from home, and the water is rising, climb up as high as you can!"] = "", -- ClimbHome ["You are given the chance to turn your life around..."] = "Tu as une chance de voir ta vie changer de cap...", ["You are playing with our lives here!"] = "Vous jouez avec nos vies !", -- ["! You bastards!"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united @@ -952,6 +1125,8 @@ ["You know what? I don't even regret anything!"] = "Tu sais quoi ? Je ne regrette rien !", ["You'll see what I mean!"] = "Vous allez comprendre ce que je veux dire !", -- ["You may only attack from a rope!"] = "", -- WxW +-- ["You may only spawn 5 crates per turn."] = "", -- Construction_Mode +-- ["You may only use 1 Extra Time per turn."] = "", -- Construction_Mode ["You meatbags are pretty slow, you know!"] = "Vous les sacs à viande êtes plutot lent vous savez !", ["You might want to find a way to instantly kill arriving cannibals!"] = "Tu aimerais sûrement trouver un moyen de tuer instantanément les cannibales qui arrivent !", ["Young one, you are telling us that they can instantly change location without a shaman?"] = "Disciple, tu es en train de nous dire qu'ils peuvent changer de place sans shaman ?", @@ -972,6 +1147,7 @@ ["You've failed. Try again."] = "Vous avez échoué. Essayez encore.", ["You've reached the goal!| |Time: "] = "Vous avez atteint le but !| |Temps : ", ["You will be avenged!"] = "Tu seras vengé !", +-- ["- You will recieve 2-4 weapons on each kill! (Even on own hogs)"] = "", -- Continental_supplies ["You won't believe what happened to me!"] = "Vous ne croirez pas ce qui m'est arrivé !", ["Yuck! I bet they'll keep worshipping her even after I save the village!"] = "Beurck ! je parie qu'ils continueront à l'adorer même après que j'aie sauvé le village !", -- ["Zealandia"] = "", -- Continental_supplies diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/fr.txt --- a/share/hedgewars/Data/Locale/fr.txt Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/fr.txt Tue Nov 10 20:43:13 2015 +0100 @@ -136,7 +136,7 @@ 02:01=%1 fait splish splash splosh ! 02:01=%1 va dormir avec les poissons ! 02:01=%1 pense que la physique de l'eau est nulle dans ce jeu ! -02:01=%1 a l'air assoiffé ! +02:01=%1 a l'air assoiffé ! 02:01=La mer réclame %1 ! 02:01=Un hérisson à la mer ! 02:01=%1 aurait dû prendre son masque et son tuba ! @@ -256,7 +256,7 @@ 02:06=Prends-la ou explose-la, le choix est tien ! 02:06=Mmmmh, Munitions ! 02:06=Une boîte de pouvoir destructif ! -02:06=Courrier aérien ! +02:06=Courrier aérien ! 02:06=Quelque soit ce qu'il y a dans cette boîte, ce n'est pas une pizza ! 02:06=Prends-la ! 02:06=Lâcher d'armes en approche ! @@ -270,7 +270,7 @@ ; New utility crate 02:07=Boite à outils ! 02:07=Ça peut être pratique... -02:07=Utilisez cette boîte ! +02:07=Utilisez cette boîte ! 02:07=Regardez en-dessous ! 02:07=Des outils pour toi ! 02:07=Ça devrait être bien ! diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/hedgewars_ar.ts --- a/share/hedgewars/Data/Locale/hedgewars_ar.ts Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/hedgewars_ar.ts Tue Nov 10 20:43:13 2015 +0100 @@ -22,7 +22,7 @@ جديد - copy of + copy of %1 @@ -212,6 +212,56 @@ Please check your installation! + + Usage + command-line + + + + OPTION + command-line + + + + CONNECTSTRING + command-line + + + + Options + command-line + + + + Display this help + command-line + + + + Custom path for configuration data and user data + command-line + + + + Custom path to the game data folder + command-line + + + + Hedgewars can use a %1 (e.g. "%2") to connect on start. + command-line + + + + Malformed option argument: %1 + command-line + + + + Unknown option argument: %1 + command-line + + HWAskQuitDialog @@ -401,6 +451,17 @@ Cannot open demofile %1 لم اتمكن من حفظ ملف اللعب %1 + + A Fatal ERROR occured! - The game engine had to stop. + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%1' button in the main menu! + +Last two engine messages: +%2 + + HWMapContainer @@ -528,6 +589,14 @@ Theme: %1 + + Random perlin + + + + Style: + + HWNetServersModel @@ -594,6 +663,10 @@ The server is too old. Disconnecting now. + + Server authentication error + + HWPasswordDialog @@ -774,6 +847,10 @@ This page requires an internet connection. + + Open packages directory + + PageDrawMap @@ -825,6 +902,10 @@ Ellipse + + Optimize + + PageEditTeam @@ -883,9 +964,12 @@ Ranking - + The best shot award was won by <b>%1</b> with <b>%2</b> pts. - + + + + The best killer is <b>%1</b> with <b>%2</b> kills in a turn. @@ -2073,6 +2157,10 @@ World Edge + + Script parameter + + QLineEdit @@ -2517,6 +2605,10 @@ Script + + Random Perlin + + SeedPrompt @@ -2560,7 +2652,7 @@ جديد - copy of + copy of %1 @@ -2575,6 +2667,15 @@ Error code: %2 + + The game engine died unexpectedly! +(exit code %1) + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%2' button in the main menu! + + TeamSelWidget @@ -2634,7 +2735,7 @@ find hedgehog - find hedgehog + find hedgehog ammo menu @@ -2768,6 +2869,14 @@ hedgehog info + + autocam / find hedgehog + + + + speed up replay + + binds (categories) @@ -2816,7 +2925,7 @@ Move the camera to the active hog: - الكامرة على اللاعب + الكامرة على اللاعب Move the cursor or camera without using the mouse: @@ -2858,6 +2967,14 @@ Hedgehog movement + + Toggle automatic camera / refocus on active hedgehog: + + + + Demo replay: + + binds (keys) @@ -3300,5 +3417,61 @@ Empty config entry + + You already have voted + + + + Voting closed + + + + New voting started + + + + Voting expired + + + + kick + + + + map + + + + pause + pause + + + Reconnected too fast + + + + Warning! Chat flood protection activated + + + + Excess flood + + + + Game messages flood detected - 1 + + + + Game messages flood detected - 2 + + + + Warning! Joins flood protection activated + + + + There's no voting going on + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/hedgewars_bg.ts --- a/share/hedgewars/Data/Locale/hedgewars_bg.ts Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/hedgewars_bg.ts Tue Nov 10 20:43:13 2015 +0100 @@ -23,7 +23,11 @@ copy of - копие на + копие на + + + copy of %1 + @@ -211,6 +215,56 @@ Please check your installation! + + Usage + command-line + + + + OPTION + command-line + + + + CONNECTSTRING + command-line + + + + Options + command-line + + + + Display this help + command-line + + + + Custom path for configuration data and user data + command-line + + + + Custom path to the game data folder + command-line + + + + Hedgewars can use a %1 (e.g. "%2") to connect on start. + command-line + + + + Malformed option argument: %1 + command-line + + + + Unknown option argument: %1 + command-line + + HWAskQuitDialog @@ -400,6 +454,17 @@ Cannot open demofile %1 Не може да се отвори демо файл %1 + + A Fatal ERROR occured! - The game engine had to stop. + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%1' button in the main menu! + +Last two engine messages: +%2 + + HWMapContainer @@ -527,6 +592,14 @@ Theme: %1 + + Random perlin + + + + Style: + + HWNetServersModel @@ -593,6 +666,10 @@ The server is too old. Disconnecting now. + + Server authentication error + + HWPasswordDialog @@ -773,6 +850,10 @@ This page requires an internet connection. + + Open packages directory + + PageDrawMap @@ -824,6 +905,10 @@ Ellipse + + Optimize + + PageEditTeam @@ -882,9 +967,12 @@ Ranking Класиране - + The best shot award was won by <b>%1</b> with <b>%2</b> pts. - Наградата за най-добър изстрел беше спечелена от <b>%1</b> с <b>%2</b> pts. + + Наградата за най-добър изстрел беше спечелена от <b>%1</b> с <b>%2</b> pts. + + The best killer is <b>%1</b> with <b>%2</b> kills in a turn. @@ -2104,6 +2192,10 @@ World Edge + + Script parameter + + QLineEdit @@ -2549,6 +2641,10 @@ Script + + Random Perlin + + SeedPrompt @@ -2593,7 +2689,11 @@ copy of - копие на + копие на + + + copy of %1 + @@ -2607,6 +2707,15 @@ Error code: %2 + + The game engine died unexpectedly! +(exit code %1) + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%2' button in the main menu! + + TeamSelWidget @@ -2722,7 +2831,7 @@ find hedgehog - Намери таралежа + Намери таралежа ammo menu @@ -2800,6 +2909,14 @@ hedgehog info + + autocam / find hedgehog + + + + speed up replay + + binds (categories) @@ -2848,7 +2965,7 @@ Move the camera to the active hog: - Преместете камерата към активния таралеж: + Преместете камерата към активния таралеж: Move the cursor or camera without using the mouse: @@ -2890,6 +3007,14 @@ Hedgehog movement + + Toggle automatic camera / refocus on active hedgehog: + + + + Demo replay: + + binds (keys) @@ -3332,5 +3457,61 @@ Empty config entry + + You already have voted + + + + Voting closed + + + + New voting started + + + + Voting expired + + + + kick + + + + map + + + + pause + Пауза + + + Reconnected too fast + + + + Warning! Chat flood protection activated + + + + Excess flood + + + + Game messages flood detected - 1 + + + + Game messages flood detected - 2 + + + + Warning! Joins flood protection activated + + + + There's no voting going on + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/hedgewars_cs.ts --- a/share/hedgewars/Data/Locale/hedgewars_cs.ts Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/hedgewars_cs.ts Tue Nov 10 20:43:13 2015 +0100 @@ -23,7 +23,11 @@ copy of - kopie + kopie + + + copy of %1 + @@ -217,6 +221,56 @@ Please check your installation! + + Usage + command-line + + + + OPTION + command-line + + + + CONNECTSTRING + command-line + + + + Options + command-line + + + + Display this help + command-line + + + + Custom path for configuration data and user data + command-line + + + + Custom path to the game data folder + command-line + + + + Hedgewars can use a %1 (e.g. "%2") to connect on start. + command-line + + + + Malformed option argument: %1 + command-line + + + + Unknown option argument: %1 + command-line + + HWAskQuitDialog @@ -406,6 +460,17 @@ Cannot open demofile %1 Nemohu otevřít soubor s ukázkou %1 + + A Fatal ERROR occured! - The game engine had to stop. + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%1' button in the main menu! + +Last two engine messages: +%2 + + HWMapContainer @@ -533,6 +598,14 @@ Theme: %1 + + Random perlin + + + + Style: + + HWNetServersModel @@ -599,6 +672,10 @@ The server is too old. Disconnecting now. + + Server authentication error + + HWPasswordDialog @@ -779,6 +856,10 @@ This page requires an internet connection. + + Open packages directory + + PageDrawMap @@ -830,6 +911,10 @@ Ellipse + + Optimize + + PageEditTeam @@ -888,9 +973,13 @@ Ranking Hodnocení - + The best shot award was won by <b>%1</b> with <b>%2</b> pts. - Cenu za nejlepší zásah vyhrál <b>%1</b> s <b>%2</b> body. + + Cenu za nejlepší zásah vyhrál <b>%1</b> s <b>%2</b> body. + + + The best killer is <b>%1</b> with <b>%2</b> kills in a turn. @@ -2119,6 +2208,10 @@ World Edge + + Script parameter + + QLineEdit @@ -2565,6 +2658,10 @@ Script + + Random Perlin + + SeedPrompt @@ -2609,7 +2706,11 @@ copy of - kopie + kopie + + + copy of %1 + @@ -2623,6 +2724,15 @@ Error code: %2 + + The game engine died unexpectedly! +(exit code %1) + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%2' button in the main menu! + + TeamSelWidget @@ -2682,7 +2792,7 @@ find hedgehog - najít ježka + najít ježka ammo menu @@ -2816,6 +2926,14 @@ hedgehog info + + autocam / find hedgehog + + + + speed up replay + + binds (categories) @@ -2864,7 +2982,7 @@ Move the camera to the active hog: - Pohni kamerou na aktivního ježka: + Pohni kamerou na aktivního ježka: Move the cursor or camera without using the mouse: @@ -2906,6 +3024,14 @@ Hedgehog movement + + Toggle automatic camera / refocus on active hedgehog: + + + + Demo replay: + + binds (keys) @@ -3348,5 +3474,61 @@ Empty config entry + + You already have voted + + + + Voting closed + + + + New voting started + + + + Voting expired + + + + kick + + + + map + + + + pause + pauza + + + Reconnected too fast + + + + Warning! Chat flood protection activated + + + + Excess flood + + + + Game messages flood detected - 1 + + + + Game messages flood detected - 2 + + + + Warning! Joins flood protection activated + + + + There's no voting going on + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/hedgewars_da.ts --- a/share/hedgewars/Data/Locale/hedgewars_da.ts Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/hedgewars_da.ts Tue Nov 10 20:43:13 2015 +0100 @@ -23,7 +23,11 @@ copy of - kopi af + kopi af + + + copy of %1 + @@ -215,6 +219,56 @@ Please check your installation! + + Usage + command-line + + + + OPTION + command-line + + + + CONNECTSTRING + command-line + + + + Options + command-line + + + + Display this help + command-line + + + + Custom path for configuration data and user data + command-line + + + + Custom path to the game data folder + command-line + + + + Hedgewars can use a %1 (e.g. "%2") to connect on start. + command-line + + + + Malformed option argument: %1 + command-line + + + + Unknown option argument: %1 + command-line + + HWAskQuitDialog @@ -404,6 +458,17 @@ Cannot open demofile %1 Kan ikke åbne demofil %1 + + A Fatal ERROR occured! - The game engine had to stop. + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%1' button in the main menu! + +Last two engine messages: +%2 + + HWMapContainer @@ -531,6 +596,14 @@ Theme: %1 + + Random perlin + + + + Style: + + HWNetServersModel @@ -597,6 +670,10 @@ The server is too old. Disconnecting now. + + Server authentication error + + HWPasswordDialog @@ -777,6 +854,10 @@ This page requires an internet connection. + + Open packages directory + + PageDrawMap @@ -828,6 +909,10 @@ Ellipse + + Optimize + + PageEditTeam @@ -886,9 +971,12 @@ Ranking Rangliste - + The best shot award was won by <b>%1</b> with <b>%2</b> pts. - Prisen for det bedste skud gik til <b>%1</b> med <b>%2</b> point. + + Prisen for det bedste skud gik til <b>%1</b> med <b>%2</b> point. + + The best killer is <b>%1</b> with <b>%2</b> kills in a turn. @@ -2112,6 +2200,10 @@ World Edge + + Script parameter + + QLineEdit @@ -2557,6 +2649,10 @@ Script + + Random Perlin + + SeedPrompt @@ -2601,7 +2697,11 @@ copy of - kopi af + kopi af + + + copy of %1 + @@ -2615,6 +2715,15 @@ Error code: %2 + + The game engine died unexpectedly! +(exit code %1) + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%2' button in the main menu! + + TeamSelWidget @@ -2674,7 +2783,7 @@ find hedgehog - find pindsvin + find pindsvin ammo menu @@ -2808,6 +2917,14 @@ hedgehog info + + autocam / find hedgehog + + + + speed up replay + + binds (categories) @@ -2856,7 +2973,7 @@ Move the camera to the active hog: - Flyt kameraet hen til det aktive pindsvin: + Flyt kameraet hen til det aktive pindsvin: Move the cursor or camera without using the mouse: @@ -2898,6 +3015,14 @@ Hedgehog movement + + Toggle automatic camera / refocus on active hedgehog: + + + + Demo replay: + + binds (keys) @@ -3340,5 +3465,61 @@ Empty config entry + + You already have voted + + + + Voting closed + + + + New voting started + + + + Voting expired + + + + kick + + + + map + + + + pause + pause + + + Reconnected too fast + + + + Warning! Chat flood protection activated + + + + Excess flood + + + + Game messages flood detected - 1 + + + + Game messages flood detected - 2 + + + + Warning! Joins flood protection activated + + + + There's no voting going on + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/hedgewars_de.ts --- a/share/hedgewars/Data/Locale/hedgewars_de.ts Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/hedgewars_de.ts Tue Nov 10 20:43:13 2015 +0100 @@ -1,9 +1,10 @@ - + About + Unknown Compiler Unbekannter Compiler @@ -11,6 +12,7 @@ AbstractPage + Go back Zurück @@ -18,61 +20,80 @@ AmmoSchemeModel + new - neu + Neu copy of - Kopie von + Kopie von + + + + copy of %1 + Kopie von %1 BanDialog + + IP IP-Adresse + Nick Spitzname + IP/Nick IP-Adresse/Spitzname + Reason Grund + Duration Dauer + Ok OK + Cancel Abbrechen + you know why du weißt schon, warum + Warning Warnung + Please, specify %1 Bitte leg %1 fest + nickname Spitzname + permanent Spitzname @@ -80,6 +101,7 @@ DataManager + Use Default Verwende Standard @@ -87,14 +109,17 @@ FeedbackDialog + View Ansehen + Cancel Abbrechen + Send Feedback Feedback senden @@ -103,6 +128,7 @@ Bitte gib uns Feedback! + We are always happy about suggestions, ideas, or bug reports. Wir freuen uns immer über Vorschläge, Ideen oder Fehlerberichte. @@ -115,25 +141,30 @@ Deine E-Mail-Adresse ist optional, aber wir könnten sie brauchen, um dich zu kontaktieren. + Send us feedback! Schicke uns dein Feedback! + If you found a bug, you can see if it's already been reported here: Falls du einen Fehler gefunden hast, kannst du hier sehen, ob er bereits bekannt is (auf Englisch): + Your email address is optional, but necessary if you want us to get back at you. - Deine E-Mail-Adresse ist optional, es sei denn du möchtest, dass wir dich zurückkontaktieren. + Deine E-Mail-Adresse ist optional, es sei denn du möchtest, dass wir dir antworten. FreqSpinBox + Never Nie + Every %1 turn Jede Runde @@ -144,26 +175,31 @@ GameCFGWidget + Edit weapons - Waffenzusammenstellung bearbeiten - - + Arsenal bearbeiten + + + Edit schemes - Spielprofile bearbeiten + Spielprofil bearbeiten Game Options Spieloptionen + Game scheme will auto-select a weapon - Spielschema wird eine Waffe automatisch aussuchen - - + Das Auswählen eines Spielprofils wird automatisch ein Arsenal auswählen + + + Map Karte + Game options Spieloptionen @@ -171,6 +207,7 @@ GameUIConfig + Guest Gast @@ -178,6 +215,8 @@ HWApplication + + %1 minutes %1 Minute @@ -185,6 +224,7 @@ + %1 hour %1 Stunde @@ -192,6 +232,9 @@ + + + %1 hours %1 Stunde @@ -199,6 +242,7 @@ + %1 day %1 Tag @@ -206,6 +250,9 @@ + + + %1 days %1 Tag @@ -213,27 +260,92 @@ + Scheme '%1' not supported - Das Schema »%1« wird nicht unterstützt - - + Das Spielprofil »%1« wird nicht unterstützt + + + Cannot create directory %1 Das Verzeichnis %1 konnte nicht angelegt werden + Failed to open data directory: %1 Please check your installation! - Ich konnte dieses Daten-Verzeichnis nicht öffnen: + Folgendes Daten-Verzeichnis konnte nicht geöffnet werden: %1 Bitte überprüfe deine Installation! + + + Usage + command-line + Verwendung + + + + OPTION + command-line + SCHALTER + + + + + CONNECTSTRING + command-line + VERBINDUNGSTEXT + + + + Options + command-line + Schalter + + + + Display this help + command-line + Diese Hilfe anzeigen + + + + Custom path for configuration data and user data + command-line + Benutzerdefinierter Pfad für Konfigurations- und Benutzerdaten + + + + Custom path to the game data folder + command-line + Benutzerdefinierter Pfad für das Spieldatenverzeichnis + + + + Hedgewars can use a %1 (e.g. "%2") to connect on start. + command-line + Hedgewars kann ein %1 (z.B. »%2«) verwenden, um beim Start zu verbinden. + + + + Malformed option argument: %1 + command-line + Fehlerhaftes Schalterargument: %1 + + + + Unknown option argument: %1 + command-line + Unbekannter Schalter: %1 + HWAskQuitDialog + Do you really want to quit? Willst du wirklich beenden? @@ -241,112 +353,140 @@ HWChatWidget + %1 has been removed from your ignore list %1 wurde aus deiner Ignorierliste entfernt + %1 has been added to your ignore list %1 wurde in deine Ignorierliste aufgenommen + %1 has been removed from your friends list %1 wurde aus deiner Freundesliste entfernt + %1 has been added to your friends list %1 wurde in deine Freundesliste aufgenommen + Stylesheet imported from %1 Stylesheet aus %1 importiert + Enter %1 if you want to use the current StyleSheet in future, enter %2 to reset! Gib %1 ein, wenn du das jetzige Stylesheet in Zukunft weiterverwenden willst; gib %2 ein, um es zurückzusetzen! + Couldn't read %1 Konnte %1 nicht lesen + StyleSheet discarded Stylesheet verworfen + StyleSheet saved to %1 Stylesheet wurde nach %1 gesichert + Failed to save StyleSheet to %1 Stylesheet konnte nicht nach %1 gesichert werden + %1 has joined %1 ist beigetreten + %1 has left %1 ist gegangen + %1 has left (%2) - %1 ist gegangen + %1 ist gegangen (%2) HWForm + + Cannot save record to file %1 Datei %1 konnte nicht gespeichert werden + DefaultTeam - - - + Standard-Team + + + Hedgewars Demo File File Types - Hedgewars Demo Datei - - + Hedgewars-Wiederholungsdatei + + + Hedgewars Save File File Types - Hedgewars gespeichertes Spiel - - + Hedgewars-Spielstandsdatei + + + Demo name - Demo-Name - - + Wiederholungsname + + + Demo name: - Demo-Name: - - + Wiederholungsname: + + + Game aborted Spiel abgebrochen + Nickname Spitzname + + No nickname supplied. Kein Spitznahme angegeben. + Someone already uses your nickname %1 on the server. Please pick another nickname: - Dein Spitzname '%1' ist bereits in Verwendung. Bitte wähle einen anderen Spitznamen: - - + Dein Spitzname »%1« ist bereits in Verwendung. Bitte wähle einen anderen Spitznamen: + + + %1's Team Team von %1 + Hedgewars - Nick registered Hedgewars – Spitzname registriert + This nick is registered, and you haven't specified a password. If this nick isn't yours, please register your own nick at www.hedgewars.org @@ -354,11 +494,12 @@ Password: Dieser Spitzname ist registriert und du hast kein Passwort angegeben. -Falls dieser Spitzname nicht deiner ist, dann registirier bitte deinen eigenen Spitznamen an www.hedgewars.org. +Falls dieser Spitzname nicht deiner ist, dann registriere bitte deinen eigenen Spitznamen an www.hedgewars.org. Passwort: + Your nickname is not registered. To prevent someone else from using it, please register it at www.hedgewars.org @@ -367,6 +508,7 @@ ihn bitte auf www.hedgewars.org + Your password wasn't saved either. @@ -375,46 +517,60 @@ Außerdem wurde auch dein Passwort nicht gespeichert. + + Hedgewars - Empty nickname Hedgewars – leerer Spitzname + Hedgewars - Wrong password Hedgewars – falsches Passwort + You entered a wrong password. Du hast ein falsches Passwort eingegeben. + Try Again noch einmal versuchen + Hedgewars - Connection error Hedgewars – Verbindungsfehler + You reconnected too fast. Please wait a few seconds and try again. Du hast dich zu früh erneut verbunden. Bitte warte ein paar Sekunden und versuch es noch einmal. + + + + Guest Gast + Room password Raumkennwort + The room is protected with password. Please, enter the password: Der Raum wird durch ein Kennwort geschützt. Bitte Kennwort eingeben: + This page requires an internet connection. Diese Seite benötigt eine Internetverbindung. @@ -422,117 +578,167 @@ HWGame + + en.txt de.txt + Cannot open demofile %1 - Demodatei %1 konnte nicht geöffnet werden + Wiederholungsdatei »%1« konnte nicht geöffnet werden + + + + A Fatal ERROR occured! - The game engine had to stop. + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%1' button in the main menu! + +Last two engine messages: +%2 + Ein kritischer FEHLER ist aufgetreten! Die Spiel-Engine musste angehalten werden. + +Diese Unannehmlichkeit tut uns fürchterlich Leid. :( + +Falls das öfters passiert, klicke auf den Knopf »%1« im Hauptmenü! + +Die letzten beiden Meldungen der Engine lauten: +%2 HWMapContainer + All Alles + Small Klein + Medium Mittel + Large Groß + Cavern Höhle + Wacky Verrückt + Small tunnels Kleine Tunnel + Medium tunnels - Mittlere Tunnel - - + Mittelgroße Tunnel + + + Seed Seed + Map type: Kartentyp: + Image map - Bild-Karte - - + Bild + + + Mission map - Missions-Karte - - + Missionskarte + + + Hand-drawn Handgemalt + Randomly generated Zufallsgeneriert + Random maze - Zufälliges Labyrinth - - + Zufallslabyrinth + + + Random Zufall + Map preview: Kartenvorschau: + Load map drawing - Lade gezeichnete Karte - - + Gezeichnete +Karte laden + + + Edit map drawing - Bearbeite gezeichnete Karte - - + Gezeichnete +Karte bearbeiten + + + Small islands Kleine Inseln + Medium islands Mittelgroße Inseln + Large islands Große Inseln + Map size: Kartengröße: + Maze style: Labyrinth-Art: + Mission: Mission: + Map: Karte: @@ -541,37 +747,56 @@ Thema: + Load drawn map Gezeichnete Karte laden + Drawn Maps Gezeichnete Karten + All files Alle Dateien + Large tunnels Große Tunnel + + Theme: %1 - Thema: %1 + Szenerie: %1 + + + + Random perlin + Perlinzufall + + + + Style: + Stil: HWNetServersModel + Title Spielname + IP IP + Port Port @@ -579,26 +804,33 @@ HWNewNet + The host was not found. Please check the host name and port settings. Der Server wurde nicht gefunden. Bitte überprüfe deine Einstellungen. + Connection refused Verbindungsaufbau abgelehnt + Quit reason: Gegangen wegen: + Room destroyed Raum geschlossen + You got kicked Du wurdest hinausgeworfen + + %1 *** %2 has joined the room %1 *** %2 hat den Raum betreten @@ -607,33 +839,45 @@ %1 *** %2 ist beigetreten + %1 *** %2 has left (%3) %1 *** %2 ist gegangen (%3) + %1 *** %2 has left %1 *** %2 ist gegangen + User quit Benutzer ist gegangen + Remote host has closed connection Die Verbindung wurde von der anderen Seite geschlossen. + The server is too old. Disconnecting now. Der Server ist zu alt. Verbindung wird beendet. + + + Server authentication error + Server-Authentifizierungsfehler + HWPasswordDialog + Login Einloggen + To connect to the server, please log in. If you don't have an account on www.hedgewars.org, @@ -644,21 +888,30 @@ dann trag einfach nur deinen Spitznamen ein. + Nickname: Spitzname: + Password: Passwort: + + + New Account + Neues Benutzerkonto + HWUploadVideoDialog + Upload video Video hochladen + Upload Hochladen @@ -666,6 +919,7 @@ HatButton + Change hat (%1) Hut wechseln (%1) @@ -673,14 +927,17 @@ HatPrompt + Cancel Abbrechen + Use selected hat Gewählten Hut auswählen + Search for a hat: Nach einem Hut suchen: @@ -695,6 +952,7 @@ KeyBinder + Category Kategorie @@ -715,29 +973,35 @@ %1 Bilder pro Sekunde, + Audio: Audio: + unknown unbekannt + Duration: %1m %2s Dauer: %1m %2s + Video: %1x%2 Video: %1x%2 + %1 fps - %1 Bilder pro Sekunde, + %1 Hz MapModel + No description available. Keine Beschreibung verfügbar. @@ -745,62 +1009,77 @@ PageAdmin + Clear Accounts Cache Zwischenspeicher leeren + Fetch data Lade Daten + Server message for latest version: Server-Nachricht für aktuelle Version: + Server message for previous versions: Server-Nachricht für ältere Versionen: + Latest version protocol number: Protokollnummer der neuesten Version: + MOTD preview: MOTD Vorschau: + Set data Speichere Daten + General Allgemein + Bans Verbannungen + IP/Nick IP-Adr./Spitzname + Expiration Ablaufzeitpunkt + Reason Grund + Refresh Aktualisieren + Add Hinzufügen + Remove Entfernen @@ -808,111 +1087,148 @@ PageConnecting + Connecting... - Verbinde ... + Verbinden … PageDataDownload + Loading, please wait. Ladevorgang. Bitte warten. + This page requires an internet connection. Diese Seite benötigt eine Internetverbindung. + + + Open packages directory + Paketeverzeichnis öffnen + PageDrawMap + Undo Rückgängig + Clear - Löschen - - + Leeren + + + Load Laden + Save - Sichern - - + Speichern + + + Load drawn map Gezeichnete Karte laden + Save drawn map Gezeichnete Karte sichern + + Drawn Maps Gezeichnete Karten + + All files Alle Dateien + Eraser Radierer + Polyline Linienzug + Rectangle Rechteck + Ellipse Ellipse + + + Optimize + Optimieren + PageEditTeam + General Allgemein + Select an action to choose a custom key bind for this team Wählt eine Aktion, um eine benutzerdefinierte Taste für dieses Team auszuwählen + Use my default Verwende meine Vorgabe + Reset all binds Alle Tastenbelegungen zurücksetzen + Custom Controls Benutzerdefinierte Steuerung + Hat Hut + Name Name + This hedgehog's name Name dieses Igels + Randomize this hedgehog's name Zufälligen Igelnamen generieren + Random Team Zufallsteam @@ -920,22 +1236,31 @@ PageGameStats + Details Details + + Health graph Lebenspunkteverlauf + Ranking - Ranking - - - The best shot award was won by <b>%1</b> with <b>%2</b> pts. - Der beste Schuss geht an <br>%1</b> mit <b>%2</b> Schadenspunkten. + Platzierung + + The best shot award was won by <b>%1</b> with <b>%2</b> pts. + + Der beste Schuss geht an <br>%1</b> mit <b>%2</b> Schadenspunkt. + Der beste Schuss geht an <br>%1</b> mit <b>%2</b> Schadenspunkten. + + + + The best killer is <b>%1</b> with <b>%2</b> kills in a turn. Der blutigste Kämpfer ist <b>%1</b> mit <b>%2</b> Opfer in einer Runde. @@ -943,6 +1268,7 @@ + A total of <b>%1</b> hedgehog(s) were killed during this round. Insgesamt fand <b>%1</b> Igel ein trauriges Ende in dieser Runde. @@ -950,6 +1276,7 @@ + (%1 kill) (%1 Opfer) @@ -957,20 +1284,23 @@ + <b>%1</b> thought it's good to shoot his own hedgehogs with <b>%2</b> pts. - <b>%1</b> dachte, es sei gut, die eigenen Igel mit <b>%2</b> Punkten zu verletzen. + <b>%1</b> dachte, es sei gut, die eigenen Igel mit <b>%2</b> Punkt zu verletzen. <b>%1</b> dachte, es sei gut, die eigenen Igel mit <b>%2</b> Punkten zu verletzen. + <b>%1</b> killed <b>%2</b> of his own hedgehogs. <b>%1</b> erledigte <b>%2</b> seiner eigenen Igel. - + <b>%1</b> erledigte <b>%2</b> seiner eigenen Igel. + <b>%1</b> was scared and skipped turn <b>%2</b> times. <b>%1</b> hatte Angst und übersprang <b>%2</b> Runde. @@ -978,14 +1308,17 @@ + Play again Nochmal spielen + Save - Sichern + Speichern + (%1 %2) (%1 %2) @@ -996,85 +1329,103 @@ PageInGame + In game... - Im Spiel... + Im Spiel … PageInfo + Open the snapshot folder - Schnappschuss-Ordner öffnen + Screenshot-Verzeichnis öffnen PageMain + Downloadable Content Herunterladbare Inhalte + Play a game on a single computer - Spiele auf einem einzelnen PC - - + Auf einen einzelnen Computer spielen + + + Play a game across a network - Spiele über ein Netzwerk - - + Über ein Netzwerk spielen + + + Read about who is behind the Hedgewars Project Lies wer hinter dem Hedgewars-Projekt steckt + Leave a feedback here reporting issues, suggesting features or just saying how you like Hedgewars - - - + Hier kannst du uns Feedback geben, indem du uns Probleme meldest, neue Funktionen vorschlägst oder einfach nur sagst, wie dir Hedgewars gefällt + + + Access the user created content downloadable from our website - Greife auf von Benutzern ergestellte Inhalte zu, herunterladbar von unserer Webseite - - + Auf von Benutzern erstellte Inhalte, die man von unserer Webseite herunterladen kann, zugreifen + + + Exit game Spiel verlassen + Manage videos recorded from game - Verwalte vom Spiel aufgenommene Videos - - + Vom Spiel aufgezeichnete Videos verwalten + + + Edit game preferences - Bearbeite Spieleinstellungen - - + Spieleinstellungen bearbeiten + + + Play a game across a local area network ein Spiel über ein lokales Netzwerk (LAN) spielen + Play a game on an official server ein Spiel auf einem offiziellen Server spielen + Feedback Feedback + Play local network game - Spiel im lokalen Netzwerk - - + Im lokalen Netzwerk spielen + + + Play official network game - Spiel im offiziellem Netzwerk + Im offiziellem Netzwerk spielen PageMultiplayer + Start - Start - - + Starten + + + Edit game preferences - Bearbeite Spieleinstellungen + Spieleinstellungen bearbeiten @@ -1084,18 +1435,22 @@ Steuerung + Edit game preferences - Bearbeite Spieleinstellungen - - + Spieleinstellungen bearbeiten + + + Start - Start - - + Starten + + + Update Aktualisieren + Room controls Raumeinstellungen @@ -1103,10 +1458,12 @@ PageNetServer + Click here for details Klick hier, um mehr zu erfahren + Insert your address here Gib deine Adress hier ein @@ -1114,181 +1471,226 @@ PageOptions + New team Neues Team + Edit team Team bearbeiten + Delete team Team löschen + You can't edit teams from team selection. Go back to main menu to add, edit or delete teams. Du kannst keine Teams bei der Team-Auswahl ändern. Gehe zum Hauptmenü zurück, um Teams hinzuzufügen, zu editieren oder zu löschen. + New scheme Neues Spielprofil + Edit scheme Spielprofil bearbeiten + Delete scheme Spielprofil löschen + New weapon set - Neues Waffenprofil - - + Neues Arsenal + + + Edit weapon set - Waffenprofil bearbeiten - - + Arsenal bearbeiten + + + Delete weapon set - Waffenprofil löschen - - + Arsenal löschen + + + Advanced Erweitert + Reset to default colors Auf Standard-Farben zurücksetzen + Proxy host Host + Proxy port Port + Proxy login - Login - - + Benutzername + + + Proxy password Passwort + No proxy Kein Proxy + Socks5 proxy Socks5-Proxy + HTTP proxy HTTP-Proxy + System proxy settings - Betriebsystem Proxy-Einstellungen - - + System-Proxy-Einstellungen + + + Select an action to change what key controls it - Wähle eine Aktion, um zu ändern, durch welche Taste sie kontrolliert wird - - + Wähle eine Aktion, um ihre Tastenbelegung zu ändern + + + Reset to default Auf Standard zurücksetzen + Reset all binds Alle Tastenbelegungen zurücksetzen + + Game Spiel + Graphics Grafik + Audio Ton + Controls Steuerung + Video Recording Videoaufzeichnung + Network Netzwerk + Teams Teams + Schemes - Schemata - - + Spielprofile + + + Weapons - Waffen - - + Arsenale + + + Frontend Benutzeroberfläche + Custom colors Benutzerdefinierte Farben + Game audio Ton im Spiel + Frontend audio Ton in der Benutzeroberfläche + Account Benutzerkonto + Proxy settings Proxy-Einstellungen + Miscellaneous Verschiedenes + Updates Updates + Check for updates nach Updates suchen + Video recording options - Videoaufnahmeoptionen + Videoaufzeichnungseinstellungen PagePlayDemo + Rename dialog Umbenennen + Enter new file name: Neuer Dateiname: @@ -1304,6 +1706,7 @@ Betreten + Admin features Verwalten @@ -1328,6 +1731,7 @@ Leeren + %1 players online %1 Spieler online @@ -1335,26 +1739,31 @@ + Search for a room: - Nach einem Raum suchen: - - + Raumsuche: + + + Create room Raum erstellen + Join room Raum beitreten + Room state - Raum-Status + Raumfilter Clear filters Filter leeren + Open server administration page Server-Administrationsseite öffnen @@ -1362,138 +1771,172 @@ PageScheme + New Neu + Delete Löschen + Gain 80% of the damage you do back in health - 80% des ausgeteilten Schadens werden in Lebenspunkte gewandelt - - + 80% des ausgeteilten Schadens werden dir als Gesundheitspunkte gutgeschrieben + + + Share your opponents pain, share their damage - Teile den Schmerz Deines Gegners, teile dessen verursachten Schaden - - + Teile den Schmerz deines Gegners, teile seinen verursachten Schaden + + + Your hogs are unable to move, put your artillery skills to the test Deine Igel können sich nicht bewegen, gib Dein Bestes im Fernkampf + Random Zufall + Seconds Sekunden + Defend your fort and destroy the opponents, two team colours max! - Verteidige Dein Fort und zerstöre das des Gegners, maximal zwei Teamfarben! - - + Verteidige deine Festung und zerstöre die des Gegners, maximal zwei Teamfarben! + + + Teams will start on opposite sides of the terrain, two team colours max! Die Teams starten auf gegenüberliegenden Terrainseiten, maximal zwei Teamfarben! + Land can not be destroyed! Die Landschaft ist nicht zerstörbar! + Lower gravity Verringerte Schwerkraft + Assisted aiming with laser sight Zielfhilfe durch Laservisier + All hogs have a personal forcefield Alle Igel haben ein eigenes Schutzschild + Order of play is random instead of in room order. Gespielt wird in zufälliger Reihenfolge. + Play with a King. If he dies, your side dies. Beschütze deinen König! Ohne ihn hast du verloren. + Take turns placing your hedgehogs before the start of play. Platziere deine Igel selbständig vor Rundenbeginn. + Ammo is shared between all teams that share a colour. Alle Teams mit gleicher Farbe teilen sich den gleichen Waffenvorrat. + Disable girders when generating random maps. - Platziere keine Bauträger auf Zufallskarten. - - + Keine Bauträger auf Zufallskarten platzieren. + + + Disable land objects when generating random maps. - Deaktiviere Landschaftsobjekte beim Generieren von Zufallskarten. - - + Keine Landschaftsobjekte beim Generieren von Zufallskarten platzieren. + + + AI respawns on death. KI wird wiederbelebt. + All (living) hedgehogs are fully restored at the end of turn Alle (lebenden) Igel werden am Ende der Runde vollkommen geheilt + Attacking does not end your turn. Angriffe beenden die Runde nicht. + Weapons are reset to starting values each turn. - Waffenarsenal wird jede Runde zurückgesetzt. - - + Arsenal wird jede Runde zurückgesetzt. + + + Each hedgehog has its own ammo. It does not share with the team. - Jeder igel hat sein eigenes Waffenarsenal. Es wird nicht mit dem Team geteilt. - - + Jeder Igel hat sein eigenes Arsenal. Es wird nicht mit dem Team geteilt. + + + You will not have to worry about wind anymore. Du wirst dich nicht mehr um Wind kümmern müssen. + Wind will affect almost everything. Wind beeinflusst fast alles. + Copy Kopieren + Teams in each clan take successive turns sharing their turn time. Teams gleicher Farbe kommen nacheinander dran und teilen sich ihre Zugzeit. + Add an indestructible border around the terrain - Füge dem Spielfeld eine unzerstörbare Randbegrenzung hinzu - - + Dem Spielfeld eine unzerstörbare Randbegrenzung hinzufügen + + + Add an indestructible border along the bottom - Füge dem unteren Kartenrand eine unzerstörbare Randbegrenzung an - - + Dem unteren Kartenrand eine unzerstörbare Randbegrenzung anfügen + + + None (Default) Keine (Standard) + Wrap (World wraps) Umbrechen (Welt wiederholt sich) + Bounce (Edges reflect) Abprallen (Grenzen reflektieren) + Sea (Edges connect to sea) Ozean (Grenzen sind mit dem Wasser verbunden) @@ -1501,18 +1944,22 @@ PageSelectWeapon + Default Standard + Delete Löschen + New Neu + Copy Kopieren @@ -1520,45 +1967,55 @@ PageSinglePlayer + Play a quick game against the computer with random settings - Spiele ein schnelles Spiel gegen den Computer - mit Zufallseinstellungen - - + Ein Schnellspiel gegen den Computer mit Zufallseinstellungen spielen + + + Play a hotseat game against your friends, or AI teams - Spiele gegen deine Freunde oder Computer-Teams - - + Gegen deine Freunde oder KI-Teams spielen + + + Campaign Mode Kampagnenmodus + Practice your skills in a range of training missions - Verbessere deine Fähigkeiten in verschiedenen Trainingsmissionen - - + Deine Fähigkeiten in verschiedenen Trainingsmissionen verbessern + + + Watch recorded demos - Sehe aufgenommene Demos an - - + Aufgezeichnete Widerholungen ansehen + + + Load a previously saved game - Lade ein vormals gespeichtes Spiel + Ein vormals gespeichertes Spiel ansehen PageTraining + No description available Keine Beschreibung verfügbar + Select a mission! Wähle eine Mission! + Pick the mission or training to play Wähle eine Mission oder ein Training + Start fighting Auf in den Kampf! @@ -1566,14 +2023,17 @@ PageVideos + Name Name + Size Größe + %1 bytes %1 Byte @@ -1581,14 +2041,17 @@ + (in progress...) - (in Bearbeitung...) - - + (in Bearbeitung …) + + + encoding encoden + uploading hochladen @@ -1603,10 +2066,12 @@ Größe: %1 + Date: %1 Datum: %1 + Size: %1 Größe: %1 @@ -1614,42 +2079,54 @@ QAction + Kick Hinauswerfen + Restrict Joins - Zugang beschränken - - + Beitreten unterbinden + + + Restrict Team Additions - Teamzugang beschränken - - + Hinzufügen weiterer Teams unterbinden + + + Info Info + Ban Verbannen + Follow Folgen + + Ignore Ignorieren + + Add friend Als Freund hinzufügen + Unignore Nicht mehr ignorieren + Remove friend Als Freund entfernen @@ -1658,140 +2135,186 @@ Aktualisieren + Restrict Unregistered Players Join - Verhindere das Beitreten unregistrierter Spieler - - + Beitreten unregistrierter Spieler unterbinden + + + Show games in lobby - Zeige Spiele in Vorbereitung - - + Spiele in Vorbereitung zeigen + + + Show games in-progress - Zeige zur Zeit laufende Spiele + Zur Zeit laufende Spiele zeigen + + + + Show password protected + Passwortgeschützte Spiele zeigen + + + + Show join restricted + Spiele mit Zutrittsverbot zeigen QCheckBox + Fullscreen Vollbild + Show FPS - FPS anzeigen - - + Bildwiederholrate anzeigen + + + Alternative damage show Alternativen Schaden anzeigen + Append date and time to record file name - Datum und Uhrzeit an Aufnahmedatei anhängen - - + Datum und Uhrzeit an Wiederholungsdateinamen anhängen + + + Check for updates at startup - Beim Start nach neuen Versionen suchen - - + Beim Spielstart nach neuen Versionen suchen + + + Show ammo menu tooltips Kurzinfos für Waffen anzeigen + + Save password Passwort speichern + Save account name and password Kontoname und Passwort speichern + Video is private Video ist privat + Record audio - Audio aufnehmen - - + Audio aufzeichnen + + + Use game resolution Spielauflösung verwenden + Visual effects Visuelle Effekte + + Sound Ton + In-game sound effects Toneffekte im Spiel + + Music Musik + In-game music Musik im Spiel + Frontend sound effects Toneffekte in der Benutzeroberfläche + Frontend music Musik in der Benutzeroberfläche + Team Team + Enable team tags by default - Aktiviere Team-Kennzeichnung bei Spielstart - - + Teambeschriftungsschilder standardmäßig aktivieren + + + Hog Igel + Enable hedgehog tags by default - Aktiviere Igel-Kennzeichnung bei Spielstart - - + Namensschilder standardmäßig aktivieren + + + Health Lebenspunkte + Enable health tags by default - Aktiviere Lebenspunkte-Kennzeichnung bei Spielstart - - + Lebenspunktebeschriftungsschilder standardmäßig aktivieren + + + Translucent - Durchsichtig - - + Transluzent + + + Enable translucent tags by default - Aktiviere durchsichtige bei Spielstart + Transluzente Beschriftungsschilder standardmäßig aktivieren QComboBox + Human Mensch + Level Stufe + (System default) (Systemstandard) + Community @@ -1808,101 +2331,125 @@ Im Spiel + Disabled Deaktiviert + Red/Cyan Rot/Türkis + Cyan/Red Türkis/Rot + Red/Blue Rot/Blau + Blue/Red Blau/Rot + Red/Green Rot/Grün + Green/Red Grün/Rot + Side-by-side Nebeneinander + Top-Bottom Übereinander + Red/Cyan grayscale - Rot/Türkis Graustufen - - + Rot/Türkis, Graustufen + + + Cyan/Red grayscale - Türkis/Rot Graustufen - - + Türkis/Rot, Graustufen + + + Red/Blue grayscale - Rot/Blau Graustufen - - + Rot/Blau, Graustufen + + + Blue/Red grayscale - Blau/Rot Graustufen - - + Blau/Rot, Graustufen + + + Red/Green grayscale - Rot/Grün Graustufen - - + Rot/Grün, Graustufen + + + Green/Red grayscale - Grün/Rot Graustufen + Grün/Rot, Graustufen QGroupBox + Team Members Teammitglieder + Fort Festung + Net game Netzwerkspiel + Playing teams Spielende Teams + Game Modifiers Spielmodifikatoren + Basic Settings Grundeinstellungen + Team Settings Teameinstellungen + Videos Videos + Description Beschreibung @@ -1910,30 +2457,37 @@ QLabel + Weapons - Waffen - - + Arsenal + + + Host: Host: + Port: Port: + Resolution Auflösung + FPS limit - FPS-Limit - - + Bildwiederholratenbegrenzung (Hz) + + + Server name: Servername: + Server port: Serverport: @@ -1942,70 +2496,92 @@ Version + Initial sound volume Ausgangslautstärke + Damage Modifier Prozentualer Schaden + Turn Time Rundenzeit + Initial Health Anfangslebenspunkte + Sudden Death Timeout Runden bis Sudden Death + Mines Time Minenzündzeit + Mines Minen + + Air Mines + Luftminen + + + Scheme Name: Spielprofil: + Crate Drops Kistenabwurf + % Dud Mines % Blindgänger + Name Name + Type Typ + Grave Grab + Flag Flagge + Voice Stimme + Locale Sprache + Explosives Pulverfässer @@ -2014,42 +2590,52 @@ Tipp: + Quality Qualität + % Health Crates - % Medipacks - - + % Erste-Hilfe-Koffer + + + Health in Crates - Lebenspunkte pro Medipack - - + Lebenspunkte in Erste-Hilfe-Koffern + + + Sudden Death Water Rise Steigen des Wassers + Sudden Death Health Decrease Schaden bei Sudden Death + % Rope Length % Seillänge + Stereo rendering Stereo-Rendering + Style Stil + Scheme Spielprofil + % Get Away Time % Rückzugszeit @@ -2058,6 +2644,7 @@ Dieses Spiel wird unter den Bedingungen der GNU General Public License v2 verbreitet + There are videos that are currently being processed. Exiting now will abort them. Do you really want to quit? @@ -2066,125 +2653,162 @@ Willst du wirklich verlassen? + Please provide either the YouTube account name or the email address associated with the Google Account. Bitte gib entwerder deinen YouTube-Kontonamen oder die entsprechende eMail-Adresse des Google-Kontos an. + Account name (or email): - Kontoname (oder eMail) - - + Kontoname (oder E-Mail): + + + Password: - Passwort - - + Passwort: + + + Video title: - Video-Titel - - + Videotitel: + + + Video description: - Video-Beschreibung - - + Videobeschreibung: + + + Tags (comma separated): - Tags (durch Beistriche getrennt) - - + Tags (durch Kommas getrennt): + + + Description Beschreibung + Nickname Spitzname + Format Format + Audio codec Audio-Codec + Video codec Video-Codec + Framerate Bildrate + Bitrate (Kbps) - Bitrate (Kbps) - - + Bitrate (kB/s) + + + This development build is 'work in progress' and may not be compatible with other versions of the game, while some features might be broken or incomplete! Diese Entwicklungsversion ist unfertig und könnte nicht kompatibel mit anderen Versionen des Spiels sein, wobei sogar einige Funktionen sogar kaputt oder unfertig sein könnten. + Fullscreen Vollbild + Fullscreen Resolution Vollbild-Auflösung + Windowed Resolution Fenster-Auflösung + Your Email Deine E-Mail-Adresse + Summary Zusammenfassung + Send system information Systeminformation senden + Type the security code: Gib den Sicherheitscode ein: + Revision Revision + This program is distributed under the %1 Dieses Programm wird unter der %1 veröffentlicht + + Tip: %1 Tipp: %1 + Displayed tags above hogs and translucent tags - Angezeigte Infos über Igel und Info-Durchsichtigkeit - - + Angezeigte/transluzente Beschriftungsschilder über Igel + + + This setting will be effective at next restart. Diese Einstellung tritt ab nächstem Neustart in Kraft. + World Edge Spielfeldgrenze + + + Script parameter + Skriptparameter + QLineEdit + unnamed unbenannt + + hedgehog %1 Igel %1 + anonymous anonym @@ -2192,6 +2816,7 @@ QMainWindow + Hedgewars %1 Hedgewars %1 @@ -2199,62 +2824,79 @@ QMessageBox + Connection to server is lost Verbindung zum Server wurde unterbrochen + Error Fehler + File association failed. Dateizuordnung fehlgeschlagen. + Error while authenticating at google.com: Fehler während Authentifizierung auf google.com: + Login or password is incorrect Login oder Passwort inkorrekt + Error while sending metadata to youtube.com: Fehler bei Senden von Meta-Daten zu youtube.com: + Teams - Are you sure? Teams - Bist du dir sicher? + Do you really want to delete the team '%1'? - Willst du das Team '%1' wirklich löschen? - - + Willst du das Team »%1« wirklich löschen? + + + + Cannot delete default scheme '%1'! - Standard-Profil '%1' kann nicht gelöscht werden! - - + Standard-Profil »%1« kann nicht gelöscht werden! + + + Please select a record from the list Bitte wähle eine Aufnahme in der Liste aus + Unable to start server - Konnte Server nicht starten - - + Server konnte nicht gestartet werden + + + + Hedgewars - Error - Hedgewars - Fehler - - + Hedgewars – Fehler + + + + Hedgewars - Success - Hedgewars - Erfolg - - + Hedgewars – Erfolg + + + All file associations have been set Alle Dateizuordnungen wurden gesetzt @@ -2293,76 +2935,102 @@ Fehler-Code: %1 + + Video upload - Error Video hochladen - Fehler + + Netgame - Error Netzwerkspiel - Fehler + Please select a server from the list Bitte wähle einen Server von der Liste + Please enter room name Bitte einen Raumnamen eingeben + + + + Record Play - Error Aufnahmewiedergabe - Fehler + + Please select record from the list Bitte eine Aufnahme aus der Liste auswählen + Cannot rename to Datei konnte nicht unbenannt werden nach + Cannot delete file Datei konnte nicht gelöscht werden + Room Name - Error Raumname - Fehler + Please select room from the list Bitte einen Raum aus der Liste auswählen + Room Name - Are you sure? Raumname - Bist du dir sicher? + The game you are trying to join has started. Do you still want to join the room? Das Spiel in das du beitreten möchtest hat bereits begonnen. Willst du trotzdem den Raum betreten? + Schemes - Warning - Spielprofil - Warnung - - + Spielprofile – Warnung + + + Schemes - Are you sure? - Spielprofil - Bist du dir sicher? - - + Spielprofile – Bist du dir sicher? + + + Do you really want to delete the game scheme '%1'? - Willst du das Profil '%1' wirklich löschen? - - + Willst du das Spielprofil »%1« wirklich löschen? + + + + + Videos - Are you sure? - Videos - Bist du dir sicher? - - + Videos – Bist du dir sicher? + + + Do you really want to delete the video '%1'? - Willst du das Video '%1' wirklich löschen? + Willst du das Video »%1« wirklich löschen? + Do you really want to remove %1 file(s)? Willst du wirklich %1 Datei entfernen? @@ -2370,87 +3038,113 @@ + Do you really want to cancel uploading %1? Willst du das Hochladen von %1 wirklich abbrechen? + + + File error Dateifehler + Cannot open '%1' for writing - '%1' konnte nicht geschrieben werden - - + »%1« konnte zum Schreiben nicht geöffnet werden + + + + Cannot open '%1' for reading - '%1' konnte nicht gelesen werden - - + »%1« konnte zum Lesen nicht geöffnet werden + + + Cannot use the ammo '%1'! - Munition '%1' kann nicht benutzt werden! - - + Munition »%1« kann nicht benutzt werden! + + + + Weapons - Warning - Waffenprofil - Warnung - - + Arsenal – Warnung + + + Cannot overwrite default weapon set '%1'! - Standard-Waffenprofil '%1' kann nicht überschrieben werden! - - + Standard-Arsenal »%1« kann nicht überschrieben werden! + + + Cannot delete default weapon set '%1'! - Standard-Waffenprofil '%1' kann nicht gelöscht werden! - - + Standard-Arsenal »%1« kann nicht gelöscht werden! + + + Weapons - Are you sure? - Waffenprofil - Bist du dir sicher? - - + Arsenal – Bist du dir sicher? + + + Do you really want to delete the weapon set '%1'? - Willst du das Waffenprofil '%1' wirklich löschen? - - + Willst du das Arsenal »%1« wirklich löschen? + + + Hedgewars - Nick not registered Hedgewars – Spitzname nicht registriert + System Information Preview Systeminformations-Vorschau + + Failed to generate captcha Captcha-Generierung fehlgeschlagen + Failed to download captcha Captcha-Download fehlgeschlagen + Please fill out all fields. Email is optional. Bitte füll alle Felder aus. Das Feld »E-Mail« ist optional. + Hedgewars - Warning Hedgewars – Warnung + Hedgewars - Information Hedgewars – Information + Not all players are ready Es sind nicht alle Spieler bereit + Are you sure you want to start this game? Not all players are ready. - Bist du sicher, dass du diesees Spiel staren willst? + Bist du sicher, dass du diesees Spiel starten willst? Es sind nicht alle Spieler bereit. QObject + + No description available Keine Beschreibung verfügbar @@ -2458,114 +3152,149 @@ QPushButton + + Go! Los! + default Standard + OK OK + + Cancel Abbrechen + Start server Server starten + Connect Verbinden + Update Aktualisieren + Specify - Verbinden zu ... - - + Verbinden zu … + + + Start - Start - - + Starten + + + + Play demo - Demo abspielen - - + Wiederholung abspielen + + + Rename Umbenennen + + + Delete Löschen + Load Laden + Associate file extensions - Ordne Dateitypen zu - - + Dateitypen zuordnen + + + More info Mehr Info + Set default options - Setzen - - + Auf Standardeinstellungen zurücksetzen + + + Open videos directory Videoverzeichnis anzeigen + Play - Spielen - - + Abspielen + + + + + Upload to YouTube Auf YouTube hochladen + Cancel uploading Hochladen abbrechen + Restore default coding parameters Standard-Kodierungs-Einstellungen wiederherstellen + Open the video directory in your system - das Videoverzeichnis deines Systems öffnen - - + Das Videoverzeichnis deines Systems öffnen + + + Play this video - dieses Video abspielen - - + Dieses Video abspielen + + + Delete this video - dieses Video löschen - - + Dieses Video löschen + + + Upload this video to your Youtube account - dieses Video zu deinem YouTube-Benutzerkonto hochladen - - + Dieses Video zu deinem YouTube-Benutzerkonto hochladen + + + Reset Zurücksetzen + Set the default server port for Hedgewars - den Standard-Server-Port für Hedgewars setzen - - + Den Standard-Server-Port für Hedgewars setzen + + + Invite your friends to your server in just 1 click! Lad deine Freunde zu deinem Server mit nur einem Klick ein! @@ -2574,29 +3303,35 @@ Klick, um deine einzigartige URL in die Zwischenablage zu kopieren. Versende diesen Link an deine Freunde, damit sie dich auf deinem Server besuchen können. + Start private server - privaten Server starten - - + Privaten Server starten + + + Click to copy your unique server URL to your clipboard. Send this link to your friends and they will be able to join you. - Klicke um deine Server-Adresse in die Zwischenablage zu kopieren. Sende diese als Link zu deinen Freunden damit sie dir beitreten können. + Klicke um deine Server-Adresse in die Zwischenablage zu kopieren. Sende diese als Link zu deinen Freunden, damit sie dir beitreten können. RoomNamePrompt + Enter a name for your room. Gib einen Namen für deinen Raum ein. + Cancel Abbrechen + Create room Raum erstellen + set password Kennwort setzen @@ -2604,69 +3339,90 @@ RoomsListModel + In progress Im Spiel + Room Name Raumname + C Sp. + T T. + Owner Besitzer + Map Karte + Rules - Regeln - - + Spielprofil + + + Weapons - Waffen - - + Arsenal + + + Random Map Zufallskarte + Random Maze Zufallslabyrinth + Hand-drawn Handgemalt + Script - Skript + Stil + + + + Random Perlin + Zufälliges Perlin SeedPrompt + The map seed is the basis for all random values generated by the game. Der sog. Seed (wörtlich übersetzt: engl. für »Saat«) ist die Basis für alle Zufallswerte, die vom Spiel generiert werden. + Cancel Abbrechen + Set seed Seed setzen + Close Schließen @@ -2674,46 +3430,78 @@ SelWeaponWidget + Weapon set - Bewaffnung - - + Anfangsbewaffnung + + + Probabilities - Nachschub - - + Wahrscheinlichkeiten + + + Ammo in boxes - Kisteninhalt - - + Kisteninhalte + + + Delays Verzögerungen + + new - neu + Neu copy of - Kopie von + Kopie von + + + + + copy of %1 + Kopie von %1 TCPBase + Unable to start server at %1. - Ich bin unfähig, den Server auf %1 zu starten. - - + Der Server konnte nicht gestartet werden. +Pfad: %1 + + + Unable to run engine at %1 Error code: %2 - Ich bin unfähig, die Engine auf %1 laufen zu lassen. + Die Spiel-Engine konnte nicht gestartet werden. +Pfad: %1 Fehlercode: %2 + + + The game engine died unexpectedly! +(exit code %1) + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%2' button in the main menu! + Die Spiel-Engine ist unerwartet abgeschmiert! +(Exit-Code: %1) + +Diese Unannehmlichkeit tut uns fürchterlich Leid. :( + +Falls das öfters passiert, klick bitte den Knopf »%2« im Hauptmenü an! + TeamSelWidget + At least two teams are required to play! Es sind mindestens zwei Teams für ein Spiel nötig! @@ -2728,204 +3516,266 @@ ThemePrompt + Cancel Abbrechen + Search for a theme: - Nach einem Thema suchen: - - + Nach einer Szenerie suchen: + + + Use selected theme - Ausgewähltes Thema benutzen + Ausgewählte Szenerie benutzen binds + + up Hoch + + left Links + + right Rechts + + down Runter + attack Angreifen + put Platzieren + switch Wechseln find hedgehog - Igel finden - - + Igel finden + + + ammo menu Munitions-Menü + slot 1 Slot 1 + slot 2 Slot 2 + slot 3 Slot 3 + slot 4 Slot 4 + slot 5 Slot 5 + slot 6 Slot 6 + slot 7 Slot 7 + slot 8 Slot 8 + slot 9 Slot 9 + timer 1 sec Timer 1 Sek. + timer 2 sec Timer 2 Sek. + timer 3 sec Timer 3 Sek. + timer 4 sec Timer 4 Sek. + timer 5 sec Timer 5 Sek. + pause Pause + volume down Lautstärke verringern + volume up Lautstärke erhöhen + change mode Modus ändern + capture Bildschirmfoto + quit Beenden + chat Chatten + chat history Chatverlauf + confirmation Bestätigung + precise aim Genaues Zielen + zoom in Vergrößern + zoom out Verkleinern + reset zoom Zurücksetzen + long jump - Weiter Sprung - - + Weitsprung + + + high jump - Hoher Sprung - - + Hochsprung + + + slot 10 Slot 10 + mute audio stummschalten + record - aufnehmen - - + aufzeichnen + + + hedgehog info Igel-Info + + + autocam / find hedgehog + Autokamera / Igel finden + + + + speed up replay + Wiederholung beschleunigen + binds (categories) + Movement Bewegung + Weapons Waffen + Camera Kamera + Miscellaneous Verschiedenes @@ -2933,389 +3783,496 @@ binds (descriptions) + Traverse gaps and obstacles by jumping: - Überwinde Abgründe und Hindernisse mit Sprüngen: - - + Abgründe und Hindernisse mit Sprüngen überwinden: + + + Fire your selected weapon or trigger an utility item: - Benutze deine gewählte Waffe oder Werkzeug: - - + Deine gewählte Waffe feuern oder dein Werkzeug benutzen: + + + Pick a weapon or a target location under the cursor: - Wähle eine Waffe oder einen Zielpunkt mit dem Cursor: - - + Eine Waffe oder einen Zielpunkt mit dem Cursor wählen: + + + Switch your currently active hog (if possible): - Wähle den zu steuernden Igel (falls möglich): - - + Den zu steuernden Igel wählen (falls möglich): + + + Pick a weapon or utility item: - Wähle eine Waffe oder Werkzeug aus: - - + Eine Waffe oder Werkzeug auswählen: + + + Set the timer on bombs and timed weapons: - Setze den Zeitzünder von verschiedenen Waffen: + Den Zeitzünder von verschiedenen Waffen setzen: Move the camera to the active hog: - Bewege die Kamera zum aktiven Igel: - - + Die Kamera zum aktiven Igel bewegen: + + + Move the cursor or camera without using the mouse: - Bewege den Zeiger oder die Kamera ohne die Maus: - - + Den Zeiger oder die Kamera ohne die Maus bewegen: + + + Modify the camera's zoom level: - Verändere den Bildausschnitt: - - + Den Zoom verändern: + + + Talk to your team or all participants: - Spreche mit anderen Spielern: - - + Mit anderen Spielern sprechen: + + + Pause, continue or leave your game: - Pausiere oder verlasse das Spiel: - - + Spiel pausieren, fortsetzen oder verlassen: + + + Modify the game's volume while playing: - Ändere die Lautstärke im Spiel: - - + Lautstärke im Spiel ändern: + + + Toggle fullscreen mode: - Schalte den Vollbildmodus um: - - + Vollbildmodus umschalten: + + + Take a screenshot: - Erstelle ein Bildschirmfoto: - - + Screenshot machen: + + + Toggle labels above hedgehogs: - Einblendungen über Igeln ein/ausschalten: - - + Beschriftungsschilder über Igel durchschalten: + + + Record video: - Video aufnehmen: - - + Video aufzeichnen: + + + Hedgehog movement Igel-Bewegung + + + Toggle automatic camera / refocus on active hedgehog: + Automatische Kamera umschalten / auf aktiven Igel wiederzentrieren: + + + + Demo replay: + Wiederholung abspielen: + binds (keys) + Axis Achse + + (Up) (Hoch) + + (Down) (Runter) + Hat Cooliehat + (Left) (Links) + (Right) (Rechts) + Button Taste + Keyboard Tastatur + Mouse: Left button Maus: Linke Taste + Mouse: Middle button Maus: Mittlere Taste + Mouse: Right button Maus: Rechte Taste + Mouse: Wheel up Maus: Mausrad hoch + Mouse: Wheel down Maus: Mausrad runter + Backspace Rückstelltaste + Tab Tabulator + Clear Clear + Return Eingabetaste + Pause Pause + Escape Escape + Space Leertaste + Delete Entf + Numpad 0 Ziffernblock 0 + Numpad 1 Ziffernblock 1 + Numpad 2 Ziffernblock 2 + Numpad 3 Ziffernblock 3 + Numpad 4 Ziffernblock 4 + Numpad 5 Ziffernblock 5 + Numpad 6 Ziffernblock 6 + Numpad 7 Ziffernblock 7 + Numpad 8 Ziffernblock 8 + Numpad 9 Ziffernblock 9 + Numpad . Ziffernblock , + Numpad / Ziffernblock / + Numpad * Ziffernblock * + Numpad - Ziffernblock - + Numpad + Ziffernblock + + Enter Enter + Equals Gleich + Up Hoch + Down Runter + Right Rechts + Left Links + Insert Einfg + Home Pos1 + End Ende + Page up - Bild hoch - - + Bild auf + + + Page down - Bild runter - - + Bild ab + + + Num lock Numlock + Caps lock Feststelltaste + Scroll lock Rollen + Right shift Rechte Umschalttaste + Left shift Linke Umschalttaste + Right ctrl Strg rechts + Left ctrl Strg links + Right alt Alt rechts + Left alt Alt links + Right meta Meta rechts + Left meta Meta links + A button A-Taste + B button B-Taste + X button X-Taste + Y button Y-Taste + LB button Linke Schultertaste + RB button Rechte Schultertaste + Back button Zurück-Taste + Start button Start-Taste + Left stick Linker Analogstick + Right stick Rechter Analogstick + Left stick (Right) Linker Analogstick (Rechts) + Left stick (Left) Linker Analogstick (Links) + Left stick (Down) Linker Analogstick (Runter) + Left stick (Up) Linker Analogstick (Hoch) + Left trigger Linker Auslöser + Right trigger Rechter Auslöser + Right stick (Down) Rechter Analogstick (Runter) + Right stick (Up) Rechter Analogstick (Hoch) + Right stick (Right) Rechter Analogstick (Rechts) + Right stick (Left) Rechter Analogstick (Links) + DPad Steuerkreuz @@ -3323,124 +4280,282 @@ server + Authentication failed Authentifizierung fehlgeschlagen + 60 seconds cooldown after kick 60 Sekunden Abkühlzeit nach Hinauswurf + kicked hinausgeworfen + Ping timeout Ping-Timeout + bye tschüss + + Your vote counted + Deine Stimme zählte + + + + Pause toggled + Pause umgeschaltet + + + + new seed + Neuer Seed + + + + number of hedgehogs in team + Anzahl der Igel im Team + + + Empty config entry Leerer Konfigurations-Eintrag + Corrupted hedgehogs info Kaputte Igel-Info + too many teams zu viele Teams + too many hedgehogs zu viele Igel + There's already a team with same name in the list Es gibt bereits ein Team mit dem selben Namen in der Liste + round in progress laufende Runde + restricted eingeschränkt + REMOVE_TEAM: no such team REMOVE_TEAM: kein solches Team + Not team owner! Nicht Team-Besitzer*In! + Less than two clans! - Weniger als zwei Clans! - - + Weniger als zwei Klans! + + + Room with such name already exists ein Raum mit einem solchen Namen existiert bereits + + /maxteams: specify number from 2 to 8 + /maxteams: Zahl zwischen 2 und 8 wählen + + + + Available callvote commands: kick <nickname>, map <name>, pause, newseed, hedgehogs + Verfügbare »callvote«-Befehle: kick <Spitzname>, map <Name>, pause, newseed, hedgehogs + + + + callvote kick: specify nickname + callvote kick: Spitznamen festlegen + + + + callvote kick: no such user + callvote kick: Benutzer existiert nicht + + + + callvote map: no such map + callvote map: Karte existiert nicht + + + + callvote pause: no game in progress + callvote pause: es läuft kein Spiel + + + + callvote hedgehogs: specify number from 1 to 8 + callvote hedgehogs: Zahl zwischen 1 und 8 wählen + + + Illegal room name - verbotener Raumname - - + Verbotener Raumname + + + No such room - kein solcher Raum - - + Ein solcher Raum existiert nicht + + + Joining restricted - eingeschränkter Zugang - - + Zutritt verboten + + + Registered users only - nur für registrierte Benutzer - - + Nur für registrierte Benutzer + + + You are banned in this room - Du wurdest von diesem Raum verbannt - - + Du wurdest aus diesem Raum verbannt + + + Nickname already chosen Spitzname bereits gewählt + Illegal nickname Verbotener Spitzname + Protocol already known Protokoll bereits bekannt + Bad number Schlechte Zahl + Nickname is already in use Spitzname bereits in Benutzung + Restricted - - - + Eingeschränkt + + + Not room master - - - + Nicht Gastgeber + + + No checker rights - - - + Keine Rechte zum Benutzen des Inspektionshilfsprogramms + + + Room version incompatible to your hedgewars version - + Die Raumversion ist inkompatibel zu deiner Hedgewars-Version + + + + You already have voted + Du hast bereits deine Stimme abgegeben + + + + Voting closed + Abstimmung abgeschlossen + + + + New voting started + Neue Abstimmung gestartet + + + + Voting expired + Abstimmung abgelaufen + + + + kick + hinauswerfen + + + + map + Karte + + + + pause + pausieren + + + + Reconnected too fast + Zu schnell wieder verbunden + + + + Warning! Chat flood protection activated + Nicht jeder weiß, was »Flooding« heißt, daher ist die Übersetzung etwas ausführlicher. + Achtung! Chat-Flood-Schutz ist aktiv. Bitte red etwas langsamer. + + + + Excess flood + Nicht jeder weiß, was »Flooding« heißt, daher wird es hier umschrieben. + Zu viele Nachrichten in kurzer Zeit abgeschickt + + + + Game messages flood detected - 1 + Zu viele Spielnachrichten in kurzer Zeit ermittelt – 1 + + + + Game messages flood detected - 2 + Zu viele Spielnachrichten in kurzer Zeit ermittelt – 2 + + + + Warning! Joins flood protection activated + Nicht jeder weiß, was »Flooding« heißt, daher ist die Übersetzung etwas ausführlicher und umschreibend. + Achtung! Der Server wird ein zu schnelles Beitreten in kurzer Zeit nicht akzeptieren + + + + There's no voting going on + Zur Zeit findet keine Abstimmung statt diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/hedgewars_el.ts --- a/share/hedgewars/Data/Locale/hedgewars_el.ts Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/hedgewars_el.ts Tue Nov 10 20:43:13 2015 +0100 @@ -22,7 +22,7 @@ Νέο - copy of + copy of %1 @@ -211,6 +211,56 @@ Please check your installation! + + Usage + command-line + + + + OPTION + command-line + + + + CONNECTSTRING + command-line + + + + Options + command-line + + + + Display this help + command-line + + + + Custom path for configuration data and user data + command-line + + + + Custom path to the game data folder + command-line + + + + Hedgewars can use a %1 (e.g. "%2") to connect on start. + command-line + + + + Malformed option argument: %1 + command-line + + + + Unknown option argument: %1 + command-line + + HWAskQuitDialog @@ -402,6 +452,17 @@ en.txt + + A Fatal ERROR occured! - The game engine had to stop. + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%1' button in the main menu! + +Last two engine messages: +%2 + + HWMapContainer @@ -529,6 +590,14 @@ Theme: %1 + + Random perlin + + + + Style: + + HWNetServersModel @@ -595,6 +664,10 @@ The server is too old. Disconnecting now. + + Server authentication error + + HWPasswordDialog @@ -775,6 +848,10 @@ This page requires an internet connection. + + Open packages directory + + PageDrawMap @@ -826,6 +903,10 @@ Ellipse + + Optimize + + PageEditTeam @@ -884,9 +965,12 @@ Ranking Κατάταξη - + The best shot award was won by <b>%1</b> with <b>%2</b> pts. - Το βραβείο καλύτερης βολής κερδίθηκε από τον <b>%1</b> με <b>%2</b> πόντους. + + Το βραβείο καλύτερης βολής κερδίθηκε από τον <b>%1</b> με <b>%2</b> πόντους. + + The best killer is <b>%1</b> with <b>%2</b> kills in a turn. @@ -2106,6 +2190,10 @@ World Edge + + Script parameter + + QLineEdit @@ -2551,6 +2639,10 @@ Script + + Random Perlin + + SeedPrompt @@ -2594,7 +2686,7 @@ Νέο - copy of + copy of %1 @@ -2609,6 +2701,15 @@ Error code: %2 + + The game engine died unexpectedly! +(exit code %1) + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%2' button in the main menu! + + TeamSelWidget @@ -2668,7 +2769,7 @@ find hedgehog - εύρεση σκατζόχοιρου + εύρεση σκατζόχοιρου ammo menu @@ -2802,6 +2903,14 @@ hedgehog info + + autocam / find hedgehog + + + + speed up replay + + binds (categories) @@ -2850,7 +2959,7 @@ Move the camera to the active hog: - Μετακινήστε την κάμερα στον τρέχον σκατζόχοιρο : + Μετακινήστε την κάμερα στον τρέχον σκατζόχοιρο : Move the cursor or camera without using the mouse: @@ -2892,6 +3001,14 @@ Hedgehog movement + + Toggle automatic camera / refocus on active hedgehog: + + + + Demo replay: + + binds (keys) @@ -3334,5 +3451,61 @@ Empty config entry + + You already have voted + + + + Voting closed + + + + New voting started + + + + Voting expired + + + + kick + + + + map + + + + pause + παύση + + + Reconnected too fast + + + + Warning! Chat flood protection activated + + + + Excess flood + + + + Game messages flood detected - 1 + + + + Game messages flood detected - 2 + + + + Warning! Joins flood protection activated + + + + There's no voting going on + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/hedgewars_en.ts --- a/share/hedgewars/Data/Locale/hedgewars_en.ts Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/hedgewars_en.ts Tue Nov 10 20:43:13 2015 +0100 @@ -22,7 +22,7 @@ new - copy of + copy of %1 @@ -211,6 +211,56 @@ Please check your installation! + + Usage + command-line + + + + OPTION + command-line + + + + CONNECTSTRING + command-line + + + + Options + command-line + + + + Display this help + command-line + + + + Custom path for configuration data and user data + command-line + + + + Custom path to the game data folder + command-line + + + + Hedgewars can use a %1 (e.g. "%2") to connect on start. + command-line + + + + Malformed option argument: %1 + command-line + + + + Unknown option argument: %1 + command-line + + HWAskQuitDialog @@ -400,6 +450,17 @@ Cannot open demofile %1 Cannot open demofile %1 + + A Fatal ERROR occured! - The game engine had to stop. + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%1' button in the main menu! + +Last two engine messages: +%2 + + HWMapContainer @@ -527,6 +588,14 @@ Theme: %1 + + Random perlin + + + + Style: + + HWNetServersModel @@ -593,6 +662,10 @@ The server is too old. Disconnecting now. + + Server authentication error + + HWPasswordDialog @@ -773,6 +846,10 @@ This page requires an internet connection. + + Open packages directory + + PageDrawMap @@ -824,6 +901,10 @@ Ellipse + + Optimize + + PageEditTeam @@ -882,9 +963,12 @@ Ranking Ranking - + The best shot award was won by <b>%1</b> with <b>%2</b> pts. - The best shot award was won by <b>%1</b> with <b>%2</b> pts. + + The best shot award was won by <b>%1</b> with <b>%2</b> pts. + + The best killer is <b>%1</b> with <b>%2</b> kills in a turn. @@ -2072,6 +2156,10 @@ World Edge + + Script parameter + + QLineEdit @@ -2517,6 +2605,10 @@ Script + + Random Perlin + + SeedPrompt @@ -2560,7 +2652,7 @@ new - copy of + copy of %1 @@ -2575,6 +2667,15 @@ Error code: %2 + + The game engine died unexpectedly! +(exit code %1) + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%2' button in the main menu! + + TeamSelWidget @@ -2634,7 +2735,7 @@ find hedgehog - find hedgehog + find hedgehog ammo menu @@ -2768,6 +2869,14 @@ hedgehog info + + autocam / find hedgehog + + + + speed up replay + + binds (categories) @@ -2816,7 +2925,7 @@ Move the camera to the active hog: - Move the camera to the active hog: + Move the camera to the active hog: Move the cursor or camera without using the mouse: @@ -2858,6 +2967,14 @@ Hedgehog movement + + Toggle automatic camera / refocus on active hedgehog: + + + + Demo replay: + + binds (keys) @@ -3300,5 +3417,61 @@ Empty config entry + + You already have voted + + + + Voting closed + + + + New voting started + + + + Voting expired + + + + kick + + + + map + + + + pause + pause + + + Reconnected too fast + + + + Warning! Chat flood protection activated + + + + Excess flood + + + + Game messages flood detected - 1 + + + + Game messages flood detected - 2 + + + + Warning! Joins flood protection activated + + + + There's no voting going on + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/hedgewars_es.ts --- a/share/hedgewars/Data/Locale/hedgewars_es.ts Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/hedgewars_es.ts Tue Nov 10 20:43:13 2015 +0100 @@ -23,7 +23,11 @@ copy of - Copia de + Copia de + + + copy of %1 + @@ -215,6 +219,56 @@ Please check your installation! + + Usage + command-line + + + + OPTION + command-line + + + + CONNECTSTRING + command-line + + + + Options + command-line + + + + Display this help + command-line + + + + Custom path for configuration data and user data + command-line + + + + Custom path to the game data folder + command-line + + + + Hedgewars can use a %1 (e.g. "%2") to connect on start. + command-line + + + + Malformed option argument: %1 + command-line + + + + Unknown option argument: %1 + command-line + + HWAskQuitDialog @@ -404,6 +458,17 @@ Cannot open demofile %1 No se pudo abrir la demo %1 + + A Fatal ERROR occured! - The game engine had to stop. + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%1' button in the main menu! + +Last two engine messages: +%2 + + HWMapContainer @@ -531,6 +596,14 @@ Theme: %1 + + Random perlin + + + + Style: + + HWNetServersModel @@ -597,6 +670,10 @@ The server is too old. Disconnecting now. + + Server authentication error + + HWPasswordDialog @@ -777,6 +854,10 @@ This page requires an internet connection. + + Open packages directory + + PageDrawMap @@ -828,6 +909,10 @@ Ellipse + + Optimize + + PageEditTeam @@ -886,9 +971,12 @@ Ranking Clasificación - + The best shot award was won by <b>%1</b> with <b>%2</b> pts. - El premio al mejor disparo es para <b>%1</b>, con <b>%2</b> pts. + + El premio al mejor disparo es para <b>%1</b>, con <b>%2</b> pts. + + The best killer is <b>%1</b> with <b>%2</b> kills in a turn. @@ -2108,6 +2196,10 @@ World Edge + + Script parameter + + QLineEdit @@ -2553,6 +2645,10 @@ Script + + Random Perlin + + SeedPrompt @@ -2597,7 +2693,11 @@ copy of - Copia de + Copia de + + + copy of %1 + @@ -2611,6 +2711,15 @@ Error code: %2 + + The game engine died unexpectedly! +(exit code %1) + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%2' button in the main menu! + + TeamSelWidget @@ -2666,7 +2775,7 @@ find hedgehog - buscar erizo + buscar erizo ammo menu @@ -2804,6 +2913,14 @@ hedgehog info + + autocam / find hedgehog + + + + speed up replay + + binds (categories) @@ -2852,7 +2969,7 @@ Move the camera to the active hog: - Centra la cámara en el erizo activo: + Centra la cámara en el erizo activo: Move the cursor or camera without using the mouse: @@ -2894,6 +3011,14 @@ Hedgehog movement + + Toggle automatic camera / refocus on active hedgehog: + + + + Demo replay: + + binds (keys) @@ -3336,5 +3461,61 @@ Empty config entry + + You already have voted + + + + Voting closed + + + + New voting started + + + + Voting expired + + + + kick + + + + map + + + + pause + pausa + + + Reconnected too fast + + + + Warning! Chat flood protection activated + + + + Excess flood + + + + Game messages flood detected - 1 + + + + Game messages flood detected - 2 + + + + Warning! Joins flood protection activated + + + + There's no voting going on + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/hedgewars_fi.ts --- a/share/hedgewars/Data/Locale/hedgewars_fi.ts Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/hedgewars_fi.ts Tue Nov 10 20:43:13 2015 +0100 @@ -1,18 +1,22 @@ + + + + About Unknown Compiler - + Tuntematon kääntäjä AbstractPage Go back - + Takaisin @@ -22,97 +26,97 @@ uusi - copy of - + copy of %1 + %1 kopio BanDialog IP - IP + IP Nick - + Nimi IP/Nick - + IP/Nimi Reason - + Syy Duration - + Kesto Ok - + Ok Cancel - Peruuta + Peruuta you know why - + tiedät kyllä, miksi Warning - + Varoitus Please, specify %1 - + Tarkenna: %1 nickname - + nimimerkki permanent - + ikuinen DataManager Use Default - + Käytä oletusta FeedbackDialog View - + Näytä Cancel - Peruuta + Peruuta Send Feedback - + Lähetä palaute We are always happy about suggestions, ideas, or bug reports. - + Otamme mielellämme vastaan ideoita ja vikailmoituksia. Send us feedback! - + Lähetä palautetta! If you found a bug, you can see if it's already been reported here: - + Jos olet löytänyt bugin, voit tarkistaa täältä, onko se jo ilmoitettu: Your email address is optional, but necessary if you want us to get back at you. - + Sähköposti on valinnainen, jos et halua meidän ottavan yhteyttä. @@ -137,141 +141,194 @@ Edit schemes - Muokkaa kaavaa + Muokkaa sääntöjä Game scheme will auto-select a weapon - + Aseet valitaan sääntöjen mukaan Map - Kartta + Kartta Game options - + Peliasetukset GameUIConfig Guest - + Vieras HWApplication %1 minutes - - - + + %1 minuutti + %1 minuuttia %1 hour - - - + + %1 tunti + %1 tuntia %1 hours - - - + + %1 tunti + %1 tuntia %1 day - - - + + %1 päivä + %1 päivää %1 days - - - + + %1 päivä + %1 päivää Scheme '%1' not supported - + Säännöille '%1' ei ole tukea Cannot create directory %1 - Hakemiston %1 luonti epäonnistui + Hakemiston %1 luonti epäonnistui Failed to open data directory: %1 Please check your installation! - + Hakemiston avaaminen epäonnistui: +%1 + +Tarkista, että peli on asennettu oikein! + + + Usage + command-line + Käyttö + + + OPTION + command-line + PARAMETRI + + + CONNECTSTRING + command-line + YHTEYSOSOITE + + + Options + command-line + Valinnat + + + Display this help + command-line + Näytä tämä ohje + + + Custom path for configuration data and user data + command-line + Valinnainen sijainti asetus- ja käyttäjätiedostoille + + + Custom path to the game data folder + command-line + Valinnainen sijainti pelitiedostoille + + + Hedgewars can use a %1 (e.g. "%2") to connect on start. + command-line + Hedgewars käyttää parametria %1 (esim: "%2") yhteyden muodostamiseen. + + + Malformed option argument: %1 + command-line + Virheellinen parametri: %1 + + + Unknown option argument: %1 + command-line + Tuntematon parametri: %1 HWAskQuitDialog Do you really want to quit? - + Haluatko varmasti lopettaa? HWChatWidget %1 has been removed from your ignore list - + %1 on poistettu estolistaltasi. %1 has been added to your ignore list - + %1 on lisätty estolistaasi. %1 has been removed from your friends list - + %1 on poistettu kavereistasi %1 has been added to your friends list - + %1 on lisätty kavereihisi Stylesheet imported from %1 - + Tyylitiedosto lisätty lähteestä %1 Enter %1 if you want to use the current StyleSheet in future, enter %2 to reset! - + Kirjoita %1 jos haluat käyttää nykyistä tyylitiedostoa jatkossa, tai %2 resetoidaksesi. Couldn't read %1 - + Ei pysty lukemaan: %1 StyleSheet discarded - + Tyylitiedosto hylätty StyleSheet saved to %1 - + Tyylitiedosto tallennettu hakemistoon %1 Failed to save StyleSheet to %1 - + Tyylitiedoston tallennus epäonnistui hakemistoon %1 %1 has joined - + %1 saapui %1 has left - + %1 poistui %1 has left (%2) - + %1 poistui (syy: %2) @@ -282,50 +339,51 @@ DefaultTeam - OletusJoukkue + Oletusjoukkue Hedgewars Demo File File Types - + Hedgewars Demotiedosto Hedgewars Save File File Types - + Hedgewars Pelitallennus Demo name - + Demon nimi Demo name: - + Demon nimi: Game aborted - + Peli keskeytetty Nickname - Nimimerkki + Nimimerkki No nickname supplied. - + Ei asetettua nimimerkkiä. Someone already uses your nickname %1 on the server. Please pick another nickname: - + Nimimerkkisi %1 on jo käytössä. +Valiste jokin muu: %1's Team - + %1n joukkue Hedgewars - Nick registered - + Hedgewars - Rekisteröity nimimerkki This nick is registered, and you haven't specified a password. @@ -333,61 +391,71 @@ If this nick isn't yours, please register your own nick at www.hedgewars.org Password: - + Tämä nimimerkki on rekisteröity, etkä antanut salasanaa. + +Jos tämä ei ole nimesi, rekisteröi omasi osoitteessa hedgewars.org + +Salasana: Your nickname is not registered. To prevent someone else from using it, please register it at www.hedgewars.org - + Nimimerkkiäsi ei ole rekisteröity. +Estääksesi muita käyttämästä sitä, +voit rekisteröidä sen osoitteessa hedgewars.org Your password wasn't saved either. - + + +Salasanaasi ei tallennettu. Hedgewars - Empty nickname - + Hedgewars - Tyhjä nimimerkki Hedgewars - Wrong password - + Hedgewars - Väärä salasana You entered a wrong password. - + Annoit väärän salasanan. Try Again - + Yritä uudelleen Hedgewars - Connection error - + Hedgewars - Yhteysvirhe You reconnected too fast. Please wait a few seconds and try again. - + Yhdistit uudelleen liian pian. +Odota hetki ja yritä uudelleen. This page requires an internet connection. - + Tämä sivu vaatii internet-yhteyden. Guest - + Vieras Room password - + Huoneen salasana The room is protected with password. Please, enter the password: - + Huoneeseen pääsee vain salasanalla. +Salasana: @@ -400,6 +468,24 @@ Cannot open demofile %1 Demotiedostoa %1 ei pystytty avaamaan + + A Fatal ERROR occured! - The game engine had to stop. + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%1' button in the main menu! + +Last two engine messages: +%2 + Vakava virhe tapahtui, ja pelimoottori kaatui! + +Olemme pahoillamme, että näin pääsi käymään :( + +Jos vika toistuu jatkuvasti, lähetä palautetta päävalikon %1-napista! + +Kaksi viimeistä pelimoottorin viestiä: +%2 + HWMapContainer @@ -437,95 +523,103 @@ Seed - + Siemen Map type: - + Karttatyyppi: Image map - + Kuvakartta Mission map - + Tehtäväkartta Hand-drawn - + Piirretty kartta Randomly generated - + Generoitu kartta Random maze - + Generoitu sokkelo Random - Satunnainen + Sekoita Map preview: - + Esikatselu: Load map drawing - + Hae piirros Edit map drawing - + Muokkaa piirrosta Small islands - + Pieniä saaria Medium islands - + Keskikokoisia saaria Large islands - + Isoja saaria Map size: - + Kartan koko: Maze style: - + Kartan tyyppi: Mission: - + Tehtävä: Map: - + Kartta: Load drawn map - + Lataa piirretty kartta Drawn Maps - + Piirretyt kartat All files - + Kaikki tiedostot Large tunnels - + Isoja tunneleita Theme: %1 - + Teema: %1 + + + Random perlin + Generoitu Perlin-kartta + + + Style: + Tyyli: @@ -559,7 +653,7 @@ Quit reason: - Poistumisssyy: + Poistumissyy: You got kicked @@ -583,70 +677,81 @@ User quit - + Pelaaja poistui Remote host has closed connection - + Palvelin katkaisi yhteyden The server is too old. Disconnecting now. - + Palvelinohjelma on liian vanha. Yhteys katkaistaan välittömästi. + + + Server authentication error + Palvelimen tunnistamisvirhe HWPasswordDialog Login - + Kirjaudu To connect to the server, please log in. If you don't have an account on www.hedgewars.org, just enter your nickname. - + Kirjaudu yhdistääksesi palvelimelle. + +Jos et ole rekisteröitynyt, +pelkkä nimimerkki riittää. Nickname: - + Nimimerkki: Password: - + Salasana: + + + New Account + Rekisteröidy HWUploadVideoDialog Upload video - + Julkaise video Upload - + Julkaise HatButton Change hat (%1) - + Vaihda hattua (%1) HatPrompt Cancel - Peruuta + Peruuta Use selected hat - + Käytä valittua hattua Search for a hat: - + Etsi hattua: @@ -660,37 +765,37 @@ KeyBinder Category - + Kategoria LibavInteraction Audio: - + Ääni: unknown - + tuntematon Duration: %1m %2s - + Kesto: %1min %2sek Video: %1x%2 - + %1 fps - + %1 kuvaa/s MapModel No description available. - + Ei kuvausta saatavilla. @@ -725,35 +830,35 @@ General - Yleiset + Yleiset Bans - + Porttikiellot IP/Nick - + IP/Nimim Expiration - + Kesto Reason - + Syy Refresh - + Päivitä Add - + Lisää Remove - + Poista @@ -767,62 +872,70 @@ PageDataDownload Loading, please wait. - + Ladataan, odota hetki... This page requires an internet connection. - + Tämä sivu vaatii internet-yhteyden. + + + Open packages directory + Avaa pakettikansio PageDrawMap Undo - + Kumoa Clear - Tyhjennä + Tyhjennä Load - Lataa + Lataa Save - + Tallenna Load drawn map - + Avaa piirretty kartta Save drawn map - + Tallenna piirretty kartta Drawn Maps - + Piirretyt Kartat All files - + Kaikki tiedostot Eraser - + Pyyhkijä Polyline - + Vapaa Rectangle - + Suorakulmio Ellipse - + Ellipsi + + + Optimize + Optimoi @@ -833,39 +946,39 @@ Select an action to choose a custom key bind for this team - + Valitse joukkuekohtaiset näppäinasettelut Use my default - + Käytä oletusta Reset all binds - + Kumoa kaikki asettelut Custom Controls - + Näppäinasettelut Hat - Hattu + Hattu Name - Nimi + Nimi This hedgehog's name - + Tämän siilen nimi Randomize this hedgehog's name - + Generoi tämän siilen nimi Random Team - Satunnainen joukkue + Satunnainen joukkue @@ -876,15 +989,18 @@ Health graph - Terveys-kuvaaja + Terveyskäyrä Ranking - Ranking - - + Tulos + + The best shot award was won by <b>%1</b> with <b>%2</b> pts. - Paras laukaus-mitalin voitti <b>%1</b> <b>%2</b> vahinkopisteellä. + + Parhaan laukauksen mitalin voitti <b>%1</b> <b>%2</b> vahinkopisteellä. + Parhaan laukauksen mitalin voitti <b>%1</b> <b>%2</b> vahinkopisteellä. + The best killer is <b>%1</b> with <b>%2</b> kills in a turn. @@ -896,49 +1012,49 @@ A total of <b>%1</b> hedgehog(s) were killed during this round. - Yhteensä <b>%1</b> siili tapettiin tämän erän aikana. + <b>%1</b> siili tapettiin tämän erän aikana. Yhteensä <b>%1</b> siiltä tapettiin tämän erän aikana. (%1 kill) - + (%1 tappo) - + (%1 tappoa) <b>%1</b> thought it's good to shoot his own hedgehogs with <b>%2</b> pts. - - <b>%1</b> ajatteli että omia siilejä on hyvä vahingoittaa <b>%2</b> vahinkopisteellä. - + + <b>%1</b> ajatteli, että omia siilejä on hienoa vahingoittaa <b>%2</b> vahinkopisteellä. + <b>%1</b> ajatteli, että omia siilejä on hienoa vahingoittaa <b>%2</b> vahinkopisteellä. <b>%1</b> killed <b>%2</b> of his own hedgehogs. - + <b>%1</b> tappoi <b>%2</b> omaa siiltä. - + <b>%1</b> tappoi <b>%2</b> omaa siiltä. <b>%1</b> was scared and skipped turn <b>%2</b> times. - - <b>%1</b> pelkäsi ja jätti vuoronsa väliin <b>%2</b> kertaa. - + + <b>%1</b> pelkuroi ja jätti vuoronsa väliin <b>%2</b> kertaa. + <b>%1</b> pelkuroi ja jätti vuoronsa väliin <b>%2</b> kertaa. Play again - + Pelaa uudestaan Save - + Tallenna (%1 %2) - + @@ -948,73 +1064,73 @@ PageInGame In game... - + Peli käynnissä... PageInfo Open the snapshot folder - + Avaa kuvankaappauskansio PageMain Downloadable Content - + Ladattava sisältö Play a game on a single computer - + Pelaa tällä tietokoneella Play a game across a network - + Pelaa verkossa Read about who is behind the Hedgewars Project - + Lisätietoa Hedgewars-projektista Leave a feedback here reporting issues, suggesting features or just saying how you like Hedgewars - + Kirjoita palautetta, ehdotuksia, bugi-ilmoituksia ja mitä pidät pelistä Access the user created content downloadable from our website - + Verkkosivuiltamme tarjolla olevaa ladattavaa sisältöä Exit game - + Lopeta peli Manage videos recorded from game - + Hallinnoi peleistä nauhoitettuja videoita Edit game preferences - + Muokkaa asetuksia Play a game across a local area network - + Pelaa lähiverkossa Play a game on an official server - + Pelaa virallisella palvelimella Feedback - + Palaute Play local network game - + Lähiverkkopeli Play official network game - + Internet-peli @@ -1025,7 +1141,7 @@ Edit game preferences - + Muokkaa asetuksia @@ -1036,30 +1152,30 @@ Edit game preferences - + Muokkaa asetuksia Start - + Aloita Update - Päivitä + Päivitä Room controls - + Huoneen hallinta PageNetServer Click here for details - + Klikkaa saadaksesi lisätietoja Insert your address here - + Anna osoitteesi tähän @@ -1078,166 +1194,166 @@ You can't edit teams from team selection. Go back to main menu to add, edit or delete teams. - Et voi muokata joukkueita joukkuevalinnassa. Mene takaisin päävalikkoon lisätäksesi, muokataksesi tai poistaaksesi joukkueita. + Et voi muokata joukkueita niitä valitessa. Mene takaisin päävalikkoon lisätäksesi, muokataksesi tai poistaaksesi joukkueita. New scheme - + Uudet säännöt Edit scheme - + Muokkaa sääntöjä Delete scheme - + Poista säännöt New weapon set - + Uusi asesetti Edit weapon set - + Muokkaa asesettiä Delete weapon set - + Poista asesetti Advanced - Lisäasetukset + Lisäasetukset Reset to default colors - + Palauta oletukset Proxy host - + Osoite Proxy port - + Portti Proxy login - + Tunnus Proxy password - + Salasana No proxy - + Ei välityspalvelinta Socks5 proxy - + SOCKS5-palvelin HTTP proxy - + HTTP-palvelin System proxy settings - + Järjestelmän oletukset Select an action to change what key controls it - + Valitse, millä napeilla ohjaat peliä. Reset to default - + Palauta oletukset Reset all binds - + Palauta kaikki oletukset Game - + Peligrafiikka Graphics - + Grafiikka Audio - + Ääni Controls - + Ohjaus Video Recording - + Videotallennus Network - + Verkko Teams - Joukkueet + Joukkueet Schemes - + Säännöt Weapons - Aseet + Aseet Frontend - + Käyttöliittymä Custom colors - + Joukkuevärit Game audio - + Peliäänet Frontend audio - + Käyttöliittymän äänet Account - + Tunnus Proxy settings - + Välityspalvelinasetukset Miscellaneous - + Sekalaiset Updates - + Päivitykset Check for updates - + Tarkista päivitykset Video recording options - + Videotallennusasetukset PagePlayDemo Rename dialog - Uudelleennimeämis-dialogi + Uudelleennimeämisikkuna Enter new file name: @@ -1280,37 +1396,37 @@ %1 players online - - - + + Yksi pelaaja linjoilla + %1 pelaajaa linjoilla Search for a room: - + Etsi huonetta: Create room - + Uusi huone Join room - + Siirry huoneeseen Room state - + Huoneen tilanne Open server administration page - + Avaa ylläpitäjän sivu PageScheme Defend your fort and destroy the opponents, two team colours max! - Puolusta linnaasi ja tuhoa vastustajasi, maksimissaan kaksi joukkueväriä! + Puolusta linnaasi ja tuhoa vastustajasi, enintään kaksi joukkueväriä! Teams will start on opposite sides of the terrain, two team colours max! @@ -1322,7 +1438,7 @@ Lower gravity - Matalampi painovoima + Heikompi painovoima Assisted aiming with laser sight @@ -1342,7 +1458,7 @@ Your hogs are unable to move, put your artillery skills to the test - Kaikki siilit ovat liikkumattomia, testaa tykistötaitojasi + Siilit eivät voi liikkua, testaa tykistötaitojasi Random @@ -1382,7 +1498,7 @@ Disable land objects when generating random maps. - Poista maaobjektit satunnaisten karttojen luonnissa. + Poista maaesteet satunnaisten karttojen luonnissa. AI respawns on death. @@ -1390,35 +1506,35 @@ All (living) hedgehogs are fully restored at the end of turn - + Kaikki elossa olevat siilet palautetaan täyteen terveyteen vuoron lopussa Attacking does not end your turn. - + Ampuminen ei lopeta vuoroasi. Weapons are reset to starting values each turn. - + Aseet palautetaan alkutilaan vuoron lopussa. Each hedgehog has its own ammo. It does not share with the team. - + Jokaisella siilellä on omakohtaiset ammukset, jotka eivät jakaudu joukkueen kesken. You will not have to worry about wind anymore. - + Tuulella ei ole vaikutusta. Wind will affect almost everything. - + Tuuli vaikuttaa lähes kaikkeen. Copy - + Kopioi Teams in each clan take successive turns sharing their turn time. - + Vuoron aika jaetaan klaanin joukkueiden kesken. Add an indestructible border around the terrain @@ -1426,23 +1542,23 @@ Add an indestructible border along the bottom - + Lisää tuhoutumaton lattia veden pinnalle None (Default) - + Ei mitään (oletus) Wrap (World wraps) - + Kierto (kartta toistuu reunoista) Bounce (Edges reflect) - + Kimmoke (reunat peilaa) Sea (Edges connect to sea) - + Meri (seinät ovat merta) @@ -1457,95 +1573,95 @@ New - Uusi + Uusi Copy - + Kopioi PageSinglePlayer Play a quick game against the computer with random settings - + Pelaa nopea peli tietokonetta vastaan satunnaisilla asetuksilla Play a hotseat game against your friends, or AI teams - + Pelaa kavereitasi tai tekoälyä vastaan Campaign Mode - + Tehtävät (englanniksi) Practice your skills in a range of training missions - + Harjoittele taitojasi tehtäväradoilla Watch recorded demos - + Katsele nauhoitettuja demoja Load a previously saved game - + Avaa tallennettu peli PageTraining No description available - + Ei kuvausta saatavilla Select a mission! - + Valitse tehtävä! Pick the mission or training to play - + Valitse tehtävä tai harjoitus luettelosta Start fighting - + Käynnistä harjoitus PageVideos Name - Nimi + Nimi Size - + Koko %1 bytes - - - + + yksi tavu + %1 tavua (in progress...) - + (käynnissä...) encoding - + enkoodaus uploading - + lähetetään Date: %1 - + Päiväys: %1 Size: %1 - + Koko: %1 @@ -1596,15 +1712,15 @@ Restrict Unregistered Players Join - + Estä rekisteröimättömiä liittymästä Show games in lobby - + Näytä aulan pelit Show games in-progress - + Näytä alkaneet pelit @@ -1635,83 +1751,83 @@ Save password - + Tallenna salasana Save account name and password - + Tallenna tunnus ja salasana Video is private - + Video on yksityinen Record audio - + Nauhoita ääntä Use game resolution - + Käytä ikkunan kokoa Visual effects - + Silmäkarkki Sound - + Ääni In-game sound effects - + Äänitehosteet Music - + Musiikki In-game music - + Pelimusiikki Frontend sound effects - + Käyttöliittymän äänitehosteet Frontend music - + Käyttöliittymän musiikki Team - + Joukkue Enable team tags by default - + Näytä joukkuekupla oletuksena Hog - + Siili Enable hedgehog tags by default - + Näytä nimikupla oletuksena Health - + Terveys Enable health tags by default - + Näytä terveyskupla oletuksena Translucent - + Läpinäkyvyys Enable translucent tags by default - + Näytä kuplat läpinäkyvinä @@ -1746,63 +1862,63 @@ Disabled - + Pois päältä Red/Cyan - + Punainen/Syaani Cyan/Red - + Syaani/Punainen Red/Blue - + Punainen/Sininen Blue/Red - + Sininen/Punainen Red/Green - + Punainen/Vihreä Green/Red - + Vihreä/Punainen Side-by-side - + Vierekkäin Top-Bottom - + Päällekkäin Red/Cyan grayscale - + Punainen/Syaani harmaasävy Cyan/Red grayscale - + Syaani/Punainen harmaasävy Red/Blue grayscale - + Punainen/Sininen harmaasävy Blue/Red grayscale - + Sininen/Punainen harmaasävy Red/Green grayscale - + Punainen/Vihreä harmaasävy Green/Red grayscale - + Vihreä/Punainen harmaasävy @@ -1837,11 +1953,11 @@ Videos - + Videot Description - + Kuvaus @@ -1888,11 +2004,11 @@ Initial sound volume - Alkuperäinen äänten voimakkuus + Äänten voimakkuus Damage Modifier - Vahinkomuuttuja + Vahinkokerroin Turn Time @@ -1904,7 +2020,7 @@ Sudden Death Timeout - Äkkikuoleman ajastus + Vuoroja äkkikuolemaan Scheme Name: @@ -1916,7 +2032,7 @@ % Dud Mines - % suutarimiinoja + Suutarimiinoja (%) Name @@ -1956,153 +2072,159 @@ % Health Crates - + Ensiapulaatikoita (%) Health in Crates - + Laatikoiden terveys Sudden Death Water Rise - + Äkkikuoleman vedennousun nopeus Sudden Death Health Decrease - + Äkkikuoleman terveyspudotus vuorossa % Rope Length - + Köyden pituus (%) Stereo rendering - + Stereoskopia Style - + Tyyli Scheme - + Säännöt % Get Away Time - + Pakoaika (%) There are videos that are currently being processed. Exiting now will abort them. Do you really want to quit? - + Videoiden prosessointi on käynnissä. +Sulkeminen keskeyttää tämän. +Haluatko varmasti lopettaa? Please provide either the YouTube account name or the email address associated with the Google Account. - + Anna joko YouTube-tunnuksesi tai siihen liitetty Google Account -sähköpostiosoite. Account name (or email): - + Tunnus (tai sähköposti): Password: - + Salasana: Video title: - + Videon otsikko: Video description: - + Videon kuvaus: Tags (comma separated): - + Hakusanat (pilkulla eroteltuna): Description - + Kuvaus Nickname - Nimimerkki + Nimimerkki Format - + Muoto Audio codec - + Äänikoodekki Video codec - + Videokoodekki Framerate - + Kuvanopeus Bitrate (Kbps) - + Laatu (Kbps) This development build is 'work in progress' and may not be compatible with other versions of the game, while some features might be broken or incomplete! - + Tämä kehitysversio on keskeneräinen, eikä ole välttämättä yhteensopiva muiden versioiden kanssa. Osa ominaisuuksista saattaa olla rikki tai vajaita! Fullscreen - Koko ruutu + Koko ruutu Fullscreen Resolution - + Koko ruudun tarkkuus Windowed Resolution - + Ikknan koko Your Email - + Sähköposti Summary - + Kooste Send system information - + Lähetä järjestelmätiedot Type the security code: - + Todista, että olet ihminen: Revision - + Revisio This program is distributed under the %1 - + Tämän ohjelman lisenssi: %1 This setting will be effective at next restart. - + Asetukset otetaan käyttöön uudelleenkäynnistyksen yhteydessä. Tip: %1 - + Vinkki: %1 Displayed tags above hogs and translucent tags - + Tietokuplat siilien yläpuolella World Edge - + Pelialueen reunat + + + Script parameter + Skriptin parametri @@ -2113,11 +2235,11 @@ hedgehog %1 - + siili %1 anonymous - + anonyymi @@ -2139,53 +2261,55 @@ File association failed. - + Tiedostotyyppien varaaminen epäonnistui. Error while authenticating at google.com: - + Virhe kirjautuessa google.comiin: + Login or password is incorrect - + Tunnus tai salasana ovat virheellisiä Error while sending metadata to youtube.com: - + Virhe lähetettäessä oheistietoja youtube.comiin: + Teams - Are you sure? - + Joukkueet - Oletko varma? Do you really want to delete the team '%1'? - + Haluatko varmasti poistaa joukkueen '%1'? Cannot delete default scheme '%1'! - + Ei voi poistaa vakiosääntöjä '%1'! Please select a record from the list - + Valitse tallenne listalta Unable to start server - + Palvelimen käynnistys epäonnistui Hedgewars - Error - + Hedgewars - Virhe Hedgewars - Success - + Hedgewars - Onnistui All file associations have been set - + Tiedostotyypit ovat varattu Cannot create directory %1 @@ -2197,164 +2321,165 @@ Video upload - Error - + Videon lähetys - Virhe Netgame - Error - + Verkkopeli - Virhe Please select a server from the list - + Valitse palvelin listalta Please enter room name - Ole hyvä ja syötä huoneen nimi + Ole hyvä ja syötä huoneen nimi Record Play - Error - + Nauhoituksen katselu - Virhe Please select record from the list - Ole hyvä ja valitse nauhoite listasta + Ole hyvä ja valitse nauhoite listasta Cannot rename to - + Ei voi uudelleennimetä: Cannot delete file - + Ei voi poistaa: Room Name - Error - + Huoneen nimi - Virhe Please select room from the list - Ole hyvä ja valitse huone listalta + Ole hyvä ja valitse huone listalta Room Name - Are you sure? - + Huoneen nimi - Oletko varma? The game you are trying to join has started. Do you still want to join the room? - Peli johon yrität liittyä on jo alkanut. + Peli johon yrität liittyä on jo alkanut. Haluatko silti liittyä huoneeseen? Schemes - Warning - + Säännöt - Varoitus Schemes - Are you sure? - + Säännöt - Oletko varma? Do you really want to delete the game scheme '%1'? - + Haluatko varmasti poistaa säännöt '%1'? Videos - Are you sure? - + Videot - Oletko varma? Do you really want to delete the video '%1'? - + Haluatko varmasti poistaa videon '%1'? Do you really want to remove %1 file(s)? - - - + + Haluatko varmasti poistaa yhden tiedoston? + Haluatko varmasti poistaa %1 tiedostoa? Do you really want to cancel uploading %1? - + Haluatko varmasti peruuttaa %1 lähetyksen? File error - + Tiedostovirhe Cannot open '%1' for writing - + Ei voi avata '%1' tallennusta varten Cannot open '%1' for reading - + Ei voi avata '%1' lukua varten Cannot use the ammo '%1'! - + Ei voi käyttää ammusta '%1'! Weapons - Warning - + Aseet - Varoitus Cannot overwrite default weapon set '%1'! - + Ei voi ylikirjoittaa asesettiä '%1'! Cannot delete default weapon set '%1'! - + Ei voi poistaa vakioasesettiä '%1'! Weapons - Are you sure? - + Aseet - Oletko varma? Do you really want to delete the weapon set '%1'? - + Haluatko varmasti poistaa asesetin '%1'? Hedgewars - Nick not registered - + Hedgewars - Rekisteröimätön nimimerkki System Information Preview - + Järjestelmätiedot Failed to generate captcha - + Captchan generointi epäonnistui Failed to download captcha - + Captchan lataus epäonnistui Please fill out all fields. Email is optional. - + Täytä kaikki kentät. Sähköposti on valinnainen. Hedgewars - Warning - + Hedgewars - Varoitus Hedgewars - Information - + Hedgewars - Ilmoitus Not all players are ready - + Kaikki pelaajat eivät ole valmiita Are you sure you want to start this game? Not all players are ready. - + Haluatko varmasti aloittaa pelin? +Kaikki pelaajat eivät ole valmiita. QObject No description available - + Ei kuvausta saatavilla @@ -2413,160 +2538,164 @@ Associate file extensions - + Tunnistuta tiedostotyypit More info - + Lisätietoja Set default options - + Aseta oletukset Open videos directory - + Avaa videokansio Play - + Toista Upload to YouTube - + Julkaise YouTubessa Cancel uploading - + Peruuta lähetys Restore default coding parameters - + Palauta alkuperäiset nauhoitusparametrit Open the video directory in your system - + Avaa videokansio järjestelmän selaimella Play this video - + Katso tämä video Delete this video - + Poista tämä video Upload this video to your Youtube account - + Julkaise tämä video YouTube-tililläsi Reset - + Palauta Set the default server port for Hedgewars - + Aseta vakioportti Hedgewars-pelipalvelimelle Invite your friends to your server in just 1 click! - + Kutsu kavereita palvelimellesi yhdellä klikkauksella! Click to copy your unique server URL to your clipboard. Send this link to your friends and they will be able to join you. - + Klikkaa kopioidaksesi palvelimen osoitteen leikepöydälle. Lähetä tämä linkki kavereillesi, jotta he pystyvät liittymään peliin. Start private server - + Käynnistä oma palvelin RoomNamePrompt Enter a name for your room. - + Anna nimi huoneellesi. Cancel - Peruuta + Peruuta Create room - + Uusi huone set password - + salasana RoomsListModel In progress - Kesken + Kesken Room Name - Huoneen nimi + Huoneen nimi C - A + A T - J + J Owner - Omistaja + Omistaja Map - Kartta + Kartta Rules - Säännöt + Säännöt Weapons - Aseet + Aseet Random Map - Satunnainen kartta + Satunnainen kartta Random Maze - Satunnainen sokkelo + Satunnainen sokkelo Hand-drawn - + Piirretty Script - + Kaava + + + Random Perlin + Satunnainen Perlin SeedPrompt The map seed is the basis for all random values generated by the game. - + Kartan siemen on pohja kaikille pelissä generoiduille satunnaisluvuille. Cancel - Peruuta + Peruuta Set seed - + Aseta siemen Close - + Sulje @@ -2589,45 +2718,60 @@ new - uusi - - - copy of - + uusi + + + copy of %1 + %1 kopio TCPBase Unable to start server at %1. - + Palvelimen käynnistäminen %1:ssä epäonnistui. Unable to run engine at %1 Error code: %2 - + Pelimoottorin käynnistäminen %1:ssä epäonnistui +Vikakoodi: %2 + + + The game engine died unexpectedly! +(exit code %1) + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%2' button in the main menu! + Pelimoottori kaatui yllättäen! +(Vikakoodi: %1) + +Olemme pahoillamme tapahtuneesta :( + +Jos vika toistuu jatkuvasti, lähetä palautetta päävalikon Palaute-napista! TeamSelWidget At least two teams are required to play! - + Vähintään kaksi joukkuetta tarvitaan pelin aloittamiseen! ThemePrompt Cancel - Peruuta + Peruuta Search for a theme: - + Etsi teemaa: Use selected theme - + Käytä valittua teemaa @@ -2650,7 +2794,7 @@ attack - hyökkäys + hyökkäys precise aim @@ -2658,7 +2802,7 @@ put - laita + aseta switch @@ -2666,7 +2810,7 @@ find hedgehog - etsi siili + etsi siili ammo menu @@ -2790,34 +2934,42 @@ mute audio - + hiljennä äänet record - + nauhoita hedgehog info - + siilitiedot + + + autocam / find hedgehog + automaattikamera / etsi siili + + + speed up replay + nopeuta videoa binds (categories) Movement - + Liike Weapons - Aseet + Aseet Camera - + Kamera Miscellaneous - + Sekalaiset @@ -2848,7 +3000,7 @@ Move the camera to the active hog: - Liikuta kamera aktiivisen siilen luokse: + Liikuta kamera aktiivisen siilen luokse: Move the cursor or camera without using the mouse: @@ -2884,11 +3036,19 @@ Record video: - + Nauhoita videolle: Hedgehog movement - + Siilen liikkuminen + + + Toggle automatic camera / refocus on active hedgehog: + Liikuta kameraa automaattisesti huomioitaviin kohteisiin: + + + Demo replay: + Demojen katselu: @@ -2943,7 +3103,7 @@ Backspace - Askelapalutin + Askelpalautin Tab @@ -2975,63 +3135,63 @@ Numpad 0 - Numpad 0 + Numeronäppäimistö 0 Numpad 1 - Numpad 1 + Numeronäppäimistö 1 Numpad 2 - Numpad 2 + Numeronäppäimistö 2 Numpad 3 - Numpad 3 + Numeronäppäimistö 3 Numpad 4 - Numpad 4 + Numeronäppäimistö 4 Numpad 5 - Numpad 5 + Numeronäppäimistö 5 Numpad 6 - Numpad 6 + Numeronäppäimistö 6 Numpad 7 - Numpad 7 + Numeronäppäimistö 7 Numpad 8 - Numpad 8 + Numeronäppäimistö 8 Numpad 9 - Numpad 9 + Numeronäppäimistö 9 Numpad . - Numpad . + Numeronäppäimistö . Numpad / - Numpad / + Numeronäppäimistö / Numpad * - Numpad * + Numeronäppäimistö * Numpad - - Numpad - + Numeronäppäimistö - Numpad + - Numpad + + Numeronäppäimistö + Enter @@ -3059,7 +3219,7 @@ Insert - Lisää-nappi + Insert-nappi Home @@ -3214,123 +3374,179 @@ server Restricted - + Rajoitettu Not room master - + Ei huoneen omistaja Corrupted hedgehogs info - + Rapistuneen siilin tiedot too many teams - + liikaa joukkueita too many hedgehogs - + liikaa siiliä There's already a team with same name in the list - + Listalla on jo samanniminen joukkue round in progress - + peli on käynnissä restricted - + rajoitettu REMOVE_TEAM: no such team - + POISTA_JOUKKUE: joukkuetta ei löydy Not team owner! - + Et ole joukkueen omistaja! Less than two clans! - + Alle kaksi klaania! Illegal room name - + Virheellinen huoneen nimi Room with such name already exists - + Samanniminen huone on jo olemassa Nickname already chosen - + Nimimerkki on jo käytössä Illegal nickname - + Virheellinen nimimerkki Protocol already known - + Protokolla jo tiedossa Bad number - + Virheellinen numero Nickname is already in use - + Nimimerkki varattu No checker rights - + Ei tarkistusoikeutta Authentication failed - + Tunnistautuminen epäonnistui 60 seconds cooldown after kick - + 60sek odotusaika potkujen jälkeen kicked - + potkittu Ping timeout - + Yhteyden aikakatkaisu bye - + näkemiin No such room - + Ei moista huonetta Room version incompatible to your hedgewars version - + Huoneen versio ei ole yhteensopiva pelin versioosi Joining restricted - + Liittyminen estetty Registered users only - + Vain rekisteröityneille You are banned in this room - + Sinulla on porttikielto huoneeseen Empty config entry - + Tyhjä asetus + + + You already have voted + Olet jo äänestänyt + + + Voting closed + Äänestys päättyi + + + New voting started + Uusi äänestys alkoi + + + Voting expired + Äänestysaika loppui + + + kick + potki + + + map + kartta + + + pause + tauko + + + Reconnected too fast + Uudelleenyhdistetty liian nopeasti + + + Warning! Chat flood protection activated + Varoitus! Keskustelun spämmisuodatin aktivoitu. + + + Excess flood + Tulva havaittu + + + Game messages flood detected - 1 + Peliviestien tulva havaittu - 1 + + + Game messages flood detected - 2 + Peliviestien tulva havaittu - 2 + + + Warning! Joins flood protection activated + Varoitus! Liittymisien tulvasuoja aktivoitu + + + There's no voting going on + Äänestyksiä ei ole meneillään - + \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/hedgewars_fr.ts --- a/share/hedgewars/Data/Locale/hedgewars_fr.ts Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/hedgewars_fr.ts Tue Nov 10 20:43:13 2015 +0100 @@ -23,7 +23,11 @@ copy of - Copier à partir de ... + Copier à partir de ... + + + copy of %1 + @@ -226,6 +230,56 @@ Veuillez verifier que votre jeu est installé correctement! + + Usage + command-line + + + + OPTION + command-line + + + + CONNECTSTRING + command-line + + + + Options + command-line + + + + Display this help + command-line + + + + Custom path for configuration data and user data + command-line + + + + Custom path to the game data folder + command-line + + + + Hedgewars can use a %1 (e.g. "%2") to connect on start. + command-line + + + + Malformed option argument: %1 + command-line + + + + Unknown option argument: %1 + command-line + + HWAskQuitDialog @@ -425,6 +479,17 @@ Cannot open demofile %1 Erreur lors de l'ouverture du fichier de démo %1 + + A Fatal ERROR occured! - The game engine had to stop. + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%1' button in the main menu! + +Last two engine messages: +%2 + + HWMapContainer @@ -556,6 +621,14 @@ Theme: %1 Thème: %1 + + Random perlin + + + + Style: + + HWNetServersModel @@ -622,6 +695,10 @@ The server is too old. Disconnecting now. La version du serveur n'est pas à jour. Déconnexion. + + Server authentication error + + HWPasswordDialog @@ -818,6 +895,10 @@ This page requires an internet connection. Cette page nécessite une connexion internet. + + Open packages directory + + PageDrawMap @@ -869,6 +950,10 @@ Ellipse + + Optimize + + PageEditTeam @@ -927,9 +1012,12 @@ Ranking Rang - + The best shot award was won by <b>%1</b> with <b>%2</b> pts. - Le prix du meilleur tir a été décerné à <b>%1</b> avec <b>%2</b> points. + + Le prix du meilleur tir a été décerné à <b>%1</b> avec <b>%2</b> points. + + The best killer is <b>%1</b> with <b>%2</b> kills in a turn. @@ -2166,6 +2254,10 @@ World Edge + + Script parameter + + QLineEdit @@ -2618,6 +2710,10 @@ Script + + Random Perlin + + SeedPrompt @@ -2662,7 +2758,11 @@ copy of - Copie de + Copie de + + + copy of %1 + @@ -2677,6 +2777,15 @@ Impossible de lancer le jeu sur %1 Erreur du code : %2 + + The game engine died unexpectedly! +(exit code %1) + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%2' button in the main menu! + + TeamSelWidget @@ -2799,7 +2908,7 @@ find hedgehog - trouver l'hérisson + trouver l'hérisson ammo menu @@ -2878,6 +2987,14 @@ hedgehog info Informations sur l'hérisson + + autocam / find hedgehog + + + + speed up replay + + binds (categories) @@ -2926,7 +3043,7 @@ Move the camera to the active hog: - Déplacez la caméra sur le hérisson actif: + Déplacez la caméra sur le hérisson actif: Move the cursor or camera without using the mouse: @@ -2968,6 +3085,14 @@ Hedgehog movement Déplacement du herisson + + Toggle automatic camera / refocus on active hedgehog: + + + + Demo replay: + + binds (keys) @@ -3410,5 +3535,61 @@ Room version incompatible to your hedgewars version + + You already have voted + + + + Voting closed + + + + New voting started + + + + Voting expired + + + + kick + + + + map + + + + pause + pause + + + Reconnected too fast + + + + Warning! Chat flood protection activated + + + + Excess flood + + + + Game messages flood detected - 1 + + + + Game messages flood detected - 2 + + + + Warning! Joins flood protection activated + + + + There's no voting going on + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/hedgewars_gd.ts --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Locale/hedgewars_gd.ts Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,3459 @@ + + + About + + Unknown Compiler + Trusaiche neo-aithnichte + + + + AbstractPage + + Go back + Air ais + + + + AmmoSchemeModel + + new + ùr + + + copy of %1 + lethbhreac de %1 + + + + BanDialog + + IP + IP + + + Nick + Far-ainm + + + IP/Nick + IP/Far-ainm + + + Reason + Adhbhar + + + Duration + Faide + + + Ok + Ceart ma-thà + + + Cancel + Sguir dheth + + + you know why + tha fios agad carson + + + Warning + Rabhadh + + + Please, specify %1 + Feuch an sònraidh thu %1 + + + nickname + far-ainm + + + permanent + buan + + + + DataManager + + Use Default + Cleachd a' bhun-roghainn + + + + FeedbackDialog + + View + Seall + + + Cancel + Sguir dheth + + + Send Feedback + Cuir beachd thugainn + + + We are always happy about suggestions, ideas, or bug reports. + Tha sinn deònach air molaidhean, beachdan no aithris air bugaichean uair sam bith. + + + Send us feedback! + Cuir beachd thugainn! + + + If you found a bug, you can see if it's already been reported here: + Ma lorg thu buga, thoir sùil an deach aithris mar-thà an-seo: + + + Your email address is optional, but necessary if you want us to get back at you. + Cha leig thu leas seòladh puist-d a chur seachad ach ma tha thu airson freagairt fhaighinn. + + + + FreqSpinBox + + Never + Chan ann idir + + + Every %1 turn + Gach %1d cuairtGach %1a cuairtGach %1mh cuairtGach %1mh cuairt + + + + GameCFGWidget + + Edit weapons + Deasaich na h-airm + + + Edit schemes + Deasaich na sgeamaichean + + + Game scheme will auto-select a weapon + Taghaidh sgeama a' gheama arm gu fèin-obrachail + + + Map + Mapa + + + Game options + Roghainnean a' gheama + + + + GameUIConfig + + Guest + Aoigh + + + + HWApplication + + %1 minutes + %1 mhionaid%1 mhionaid%1 mionaidean%1 mionaid + + + %1 hour + %1 uair%1 uair%1 uairean%1 uair + + + %1 hours + %1 uair%1 uair%1 uairean%1 uair + + + %1 day + %1 latha%1 latha%1 làithean%1 latha + + + %1 days + %1 latha%1 latha%1 làithean%1 latha + + + Scheme '%1' not supported + Cha chuir sinn taic ris an sgeama "%1" + + + Cannot create directory %1 + Chan urrainn dhuinn am pasgan "%1" a chruthachadh + + + Failed to open data directory: +%1 + +Please check your installation! + Cha deach leinn am pasgan dàta fhosgladh: +%1 + +Feuch an dearbhaich thu an stàladh agad! + + + Usage + command-line + Cleachdadh + + + OPTION + command-line + ROGHAINN + + + CONNECTSTRING + command-line + TEACSACEANGLAIDH + + + Options + command-line + Roghainnean + + + Display this help + command-line + Seall a' chobhair seo + + + Custom path for configuration data and user data + command-line + Slighe ghnàthaichte airson dàta rèiteachaidh 's a' chleachdaiche + + + Custom path to the game data folder + command-line + Slighe ghnàthaichte gu pasgan dàta a' gheama + + + Hedgewars can use a %1 (e.g. "%2") to connect on start. + command-line + 'S urrainn do Hedgewars %1 (m.e. "%2") a chleachdadh gus ceangal leis an tòiseachadh. + + + Malformed option argument: %1 + command-line + Droch chumadh air argamaid roghainne: %1 + + + Unknown option argument: %1 + command-line + Argamaid roghainne nach aithne dhuinn: %1 + + + + HWAskQuitDialog + + Do you really want to quit? + A bheil thu airson fàgail dha-rìribh? + + + + HWChatWidget + + %1 has been removed from your ignore list + Chaidh %1 a thoirt air falbh on liosta neo-shuime agad + + + %1 has been added to your ignore list + Chaidh %1 a chur ris an liosta neo-shuime agad + + + %1 has been removed from your friends list + Chaidh %1 a thoirt air falbh o liosta nan caraidean agad + + + %1 has been added to your friends list + Chaidh %1 a chur ri liosta nan caraidean agad + + + Stylesheet imported from %1 + Chaidh siota-stoidhle ion-phortachadh o %1 + + + Enter %1 if you want to use the current StyleSheet in future, enter %2 to reset! + Cuir a-steach %1 ma tha thu airson an siota-stoidhle làithreach a chleachdadh san àm ri teach no %2 gus ath-shuidheachadh! + + + Couldn't read %1 + Cha b' urrainn dhuinn %1 a leughadh + + + StyleSheet discarded + Chaidh an siota-stoidhle a thilgeil air falbh + + + StyleSheet saved to %1 + Chaidh an siota-stoidhle a shàbhaladh gu %1 + + + Failed to save StyleSheet to %1 + Cha b' urrainn dhuinn an siota-stoidhle a shàbhaladh gu %1 + + + %1 has joined + Thàinig %1 a-steach + + + %1 has left + Dh'fhalbh %1 + + + %1 has left (%2) + Dh'fhalbh %1 (%2) + + + + HWForm + + Cannot save record to file %1 + Chan urrainn dhuinn an clàr a shàbhaladh gun fhaidhle %1 + + + DefaultTeam + Sgioba tùsail + + + Hedgewars Demo File + File Types + Faidhle demo Hedgewars + + + Hedgewars Save File + File Types + Faidhle sàbhalaidh Hedgewars + + + Demo name + Ainm an demo + + + Demo name: + Ainm an demo: + + + Game aborted + Chaidh sgur dhen gheama + + + Nickname + Far-ainm + + + No nickname supplied. + Cha deach far-ainm a thoirt seachad. + + + Someone already uses your nickname %1 on the server. +Please pick another nickname: + Cha cuideigin a' chleachdadh d' fhar-ainm %1 air an fhrithealaiche mar-thà. +Feuch an tagh thu far-ainm eile: + + + %1's Team + An sgioba aig %1 + + + Hedgewars - Nick registered + Hedgewars - Far-ainm clàraichte + + + This nick is registered, and you haven't specified a password. + +If this nick isn't yours, please register your own nick at www.hedgewars.org + +Password: + Tha am far-ainm seo clàraichte 's cha chuir thu facal-faire a-steach. + +Mur ann agadsa a tha am far-ainm seo, clàraich fear agad fhèin air www.hedgewars.org + +Facal-faire: + + + Your nickname is not registered. +To prevent someone else from using it, +please register it at www.hedgewars.org + Chan eil d' fhar-ainm clàraichte. +'S urrainn dhut a chlàradh air www.hedgewars.org +ach nach cleachd duine eile e. + + + + +Your password wasn't saved either. + + +Cha deach am facal-faire agad a shàbhaladh nas motha. + + + Hedgewars - Empty nickname + Hedgewars - Far-ainm falamh + + + Hedgewars - Wrong password + Hedgewars - Facal-faire ceàrr + + + You entered a wrong password. + Cha do chuir thu am facal-faire a-steach mar bu chòir. + + + Try Again + Feuch ris a-rithist + + + Hedgewars - Connection error + Hedgewars - Mearachd leis a' cheangal + + + You reconnected too fast. +Please wait a few seconds and try again. + Rinn thu ath-cheangal ro luath. +Fuirich diog no dhà mus feuch thu ris a-rithist. + + + This page requires an internet connection. + Tha an duilleag seo feumach air ceangal dhan eadar-lìn. + + + Guest + Aoigh + + + Room password + Facal-faire an t-seòmair + + + The room is protected with password. +Please, enter the password: + Chaidh an seòmar seo a dhìon le facal-faire. +Cuir a-steach am facal-faire: + + + + HWGame + + en.txt + gd.txt + + + Cannot open demofile %1 + Chan urrainn dhuinn faidhle an demo %1 fhosgladh + + + A Fatal ERROR occured! - The game engine had to stop. + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%1' button in the main menu! + +Last two engine messages: +%2 + Thachair MEARACHD mharbhtach! - Thug seo stad air inneal a' gheama. + +Tha sinn glè dhuilich mun trioblaid seo :( + +Ma thachras seo a-rithist 's a-rithist, briog air a' phutan "%1" sa phrìomh chlàr-taice! + +An dà theachdaireachd mu dheireadh aig an inneal: +%2 + + + + HWMapContainer + + All + Na h-uile + + + Small + Beag + + + Medium + Meadhanach + + + Large + Mòr + + + Cavern + Uamh + + + Wacky + Neònach + + + Small tunnels + Tunailean beaga + + + Medium tunnels + Tunailean meadhanach + + + Seed + Sìol + + + Map type: + Seòrsa a' mhapa: + + + Image map + Mapa deilbh + + + Mission map + Mapa misein + + + Hand-drawn + Air a tharraing a làimh + + + Randomly generated + Air a ghintinn air thuaiream + + + Random maze + Cuartan air thuaiream + + + Random + Air thuaiream + + + Map preview: + Ro-shealladh air a' mhapa: + + + Load map drawing + Luchdaich tarraing mapa + + + Edit map drawing + Deasaich tarraing mapa + + + Small islands + Eileanan beaga + + + Medium islands + Eileanan meadhanach + + + Large islands + Eileanan mòra + + + Map size: + Meud a' mhapa: + + + Maze style: + Stoidhle a' chuartain: + + + Mission: + Misean: + + + Map: + Mapa: + + + Load drawn map + Luchdaich mapa air a tharraing a làimh + + + Drawn Maps + Mapaichean air an tarraing a làimh + + + All files + A h-uile faidhle + + + Large tunnels + Tunailean mòra + + + Theme: %1 + Ùrlar: %1 + + + Random perlin + Perlin tuaireamach + + + Style: + Stoidhle: + + + + HWNetServersModel + + Title + Tiotal + + + IP + IP + + + Port + Port + + + + HWNewNet + + The host was not found. Please check the host name and port settings. + Cha deach an t-òstair a lorg. Dearbhaich ainm an òstair agus roghainnean a' phuirt. + + + Connection refused + Chaidh an ceangal a dhiùltadh + + + Room destroyed + Chaidh an seòmar a mhilleadh + + + Quit reason: + Abhbhar fàgail: + + + You got kicked + Fhuair thu a' bhog + + + %1 *** %2 has joined the room + Thàinig %1 *** %2 a-steach dhan t-seòmar + + + %1 *** %2 has joined + + + + %1 *** %2 has left (%3) + Dh'fhalbh %1 *** %2 (%3) + + + %1 *** %2 has left + Dh'fhalbh %1 *** %2 + + + User quit + Dh'fhàg an cleachdaiche an-seo + + + Remote host has closed connection + Dhùin an t-òstair cèin an ceangal + + + The server is too old. Disconnecting now. + Tha am frithealaiche ro shean. 'Ga dhì-cheangal a-nis. + + + Server authentication error + Mearachd dearbhadh an fhrithealaiche + + + + HWPasswordDialog + + Login + Logadh a-steach + + + To connect to the server, please log in. + +If you don't have an account on www.hedgewars.org, +just enter your nickname. + Log a-steach gus ceangal ris an fhrithealaiche. + +Cha leig thu leas ach far-ainm a chur a-steach +mur eil cunntas air www.hedgewars.org agad. + + + Nickname: + Far-ainm: + + + Password: + Facal-faire: + + + + HWUploadVideoDialog + + Upload video + Luchdaidh suas video + + + Upload + Luchdadh suas + + + + HatButton + + Change hat (%1) + Cuir ad eile ort (%1) + + + + HatPrompt + + Cancel + Sguir dheth + + + Use selected hat + Cleachd an ad a thagh thu + + + Search for a hat: + Lorg ad: + + + + KB + + SDL_ttf returned error while rendering text, most propably it is related to the bug in freetype2. It's recommended to update your freetype lib. + + + + + KeyBinder + + Category + Roinn-seòrsa + + + + LibavInteraction + + Audio: + Fuaim: + + + unknown + chan eil fhios + + + Duration: %1m %2s + Faide: %1m %2d + + + Video: %1x%2 + Video: %1x%2 + + + %1 fps + %1 fps + + + + MapModel + + No description available. + Chan eil tuairisgeul ri làimh. + + + + PageAdmin + + Clear Accounts Cache + Falamhaich tasgadan nan cunntasan + + + Fetch data + Faigh dàta + + + Server message for latest version: + Teachdaireachd an fhrithealaiche airson an tionndaidh as ùire: + + + Server message for previous versions: + Teachdaireachd an fhrithealaiche airson nan tionndaidhean roimhe: + + + Latest version protocol number: + Àireamh a' phròtacail as ùire: + + + MOTD preview: + Ro-shealladh air maidse an latha: + + + Set data + Suidhich an dàta + + + General + Coitcheann + + + Bans + Toirmeasg + + + IP/Nick + IP/Far-ainm + + + Expiration + Àm a dh'fhalbhas an ùine air + + + Reason + Adhbhar + + + Refresh + Ath-nuadhaich + + + Add + Cuir ris + + + Remove + Thoir air falbh + + + + PageConnecting + + Connecting... + 'Ga cheangal... + + + + PageDataDownload + + Loading, please wait. + 'Ga cheangal, fuirich ort. + + + This page requires an internet connection. + Tha an duilleag seo feumach air ceangal dhan eadar-lìn. + + + Open packages directory + Fosgail pasgan nam pacaidean + + + + PageDrawMap + + Undo + Neo-dhèan + + + Clear + Falamhaich + + + Load + Luchdaich + + + Save + Sàbhail + + + Load drawn map + Luchdaich mapa air a tharraing + + + Save drawn map + Sàbhail mapa air a tharraing + + + Drawn Maps + Mapaichean air an tarraing + + + All files + A h-uile faidhle + + + Eraser + Suathan + + + Polyline + Loidhne ioma-cheàrnach + + + Rectangle + Ceart-cheàrnach + + + Ellipse + Eileaps + + + Optimize + Pisich + + + + PageEditTeam + + General + Coitcheann + + + Select an action to choose a custom key bind for this team + Tagh gnìomh gus nasgadh ri iuchair ghnàthaichte a thaghadh airson an sgioba seo + + + Use my default + Cleachd na bun-roghainnean agam + + + Reset all binds + Ath-shuidhich gach nasgadh + + + Custom Controls + Uidheaman-smachd gnàthaichte + + + Hat + Ad + + + Name + Ainm + + + This hedgehog's name + Ainm na gràineige seo + + + Randomize this hedgehog's name + Thoir ainm air thuaiream air a' ghràineag seo + + + Random Team + Sgioba air thuaiream + + + + PageGameStats + + Details + Fiosrachadh + + + Health graph + Graf na slàinte + + + Ranking + Rangachadh + + + The best shot award was won by <b>%1</b> with <b>%2</b> pts. + Bhuannaich <b>%1</b> duais an losgaidh as fhearr le <b>%2</b> phuing.Bhuannaich <b>%1</b> duais an losgaidh as fhearr le <b>%2</b> phuing.Bhuannaich <b>%1</b> duais an losgaidh as fhearr le <b>%2</b> puingean.Bhuannaich <b>%1</b> duais an losgaidh as fhearr le <b>%2</b> puing. + + + The best killer is <b>%1</b> with <b>%2</b> kills in a turn. + Is <b>%1</b> am marbhaiche as fhearr le <b>%2</b> mharbhadh ann an cuairt.Is <b>%1</b> am marbhaiche as fhearr le <b>%2</b> mharbhadh ann an cuairt.Is <b>%1</b> am marbhaiche as fhearr le <b>%2</b> marbhaidhean ann an cuairt.Is <b>%1</b> am marbhaiche as fhearr le <b>%2</b> marbhadh ann an cuairt. + + + A total of <b>%1</b> hedgehog(s) were killed during this round. + Chaidh <b>%1</b> ghràineag a mharbhadh uile gu lèir sa chuairt seo.Chaidh <b>%1</b> ghràineag a mharbhadh uile gu lèir sa chuairt seo.Chaidh <b>%1</b> gràineagan a mharbhadh uile gu lèir sa chuairt seo.Chaidh <b>%1</b> gràineag a mharbhadh uile gu lèir sa chuairt seo. + + + (%1 kill) + (%1 mharbhadh)(%1 mharbhadh)(%1 marbhaidhean)(%1 marbhadh) + + + <b>%1</b> thought it's good to shoot his own hedgehogs with <b>%2</b> pts. + Bha <b>%1</b> dhen bheachd gum b' fheairrde e na gràineagan aige fhèin a mharbhadh le <b>%2</b> phuing.Bha <b>%1</b> dhen bheachd gum b' fheairrde e na gràineagan aige fhèin a mharbhadh le <b>%2</b> phuing.Bha <b>%1</b> dhen bheachd gum b' fheairrde e na gràineagan aige fhèin a mharbhadh le <b>%2</b> puingean.Bha <b>%1</b> dhen bheachd gum b' fheairrde e na gràineagan aige fhèin a mharbhadh le <b>%2</b> puing. + + + <b>%1</b> killed <b>%2</b> of his own hedgehogs. + Mharbh <b>%1</b> <b>%2</b> dhe na gràineagan aige fhèin.Mharbh <b>%1</b> <b>%2</b> dhe na gràineagan aige fhèin.Mharbh <b>%1</b> <b>%2</b> dhe na gràineagan aige fhèin.Mharbh <b>%1</b> <b>%2</b> dhe na gràineagan aige fhèin. + + + <b>%1</b> was scared and skipped turn <b>%2</b> times. + Thàinig an t-eagal air <b>%1</b> agus leig e seachad a chuairt <b>%2</b> turas.Thàinig an t-eagal air <b>%1</b> agus leig e seachad a chuairt <b>%2</b> thuras.Thàinig an t-eagal air <b>%1</b> agus leig e seachad a chuairt <b>%2</b> tursan.Thàinig an t-eagal air <b>%1</b> agus leig e seachad a chuairt <b>%2</b> turas. + + + Play again + Cluich a-rithist + + + Save + Sàbhail + + + (%1 %2) + (%1 %2)(%1 %2)(%1 %2)(%1 %2) + + + + PageInGame + + In game... + Sa gheama... + + + + PageInfo + + Open the snapshot folder + Fosgail pasgan nan glacaidhean-sgrìn + + + + PageMain + + Downloadable Content + Susbaint ri luchdadh a-nuas + + + Play a game on a single computer + Cluich geama air an aon choimpiutair + + + Play a game across a network + Cluich geama air lìonra + + + Read about who is behind the Hedgewars Project + Leugh air cò tha air cùlaibh a' phròiseict Hedgewars + + + Leave a feedback here reporting issues, suggesting features or just saying how you like Hedgewars + Fàg beachd an-seo mu dhuilgheadasan, molaidhean air feartan no innis dhuinn ciamar a tha Hedgewars a' chòrdadh riut + + + Access the user created content downloadable from our website + Inntrig susbaint a rinn cleachdaichean 's a ghabhas luchdadh a-nuas on làrach-lìn againn + + + Exit game + Fàg an geama + + + Manage videos recorded from game + Stiùirich na videothan a chaidh a chlàradh on gheama + + + Edit game preferences + Deasaich roghainnean a' gheama + + + Play a game across a local area network + Cluich geama air lìonra ionadail + + + Play a game on an official server + Cluich geama air frithealaiche oifigeil + + + Feedback + Beachd thugainn + + + Play local network game + Cluich geama air an lìonra ionadail + + + Play official network game + Cluich geama lìonraidh oifigeil + + + + PageMultiplayer + + Start + Tòisich + + + Edit game preferences + Deasaich roghainnean a' gheama + + + + PageNetGame + + Control + + + + Edit game preferences + Deasaich roghainnean a' gheama + + + Start + Tòisich + + + Update + Ùraich + + + Room controls + Uidheaman-smachd an t-seòmair + + + + PageNetServer + + Click here for details + Briog an-seo airson barrachd fiosrachaidh + + + Insert your address here + Cuir an seòladh agad a-steach an-seo + + + + PageOptions + + New team + Sgioba ùr + + + Edit team + Deasaich an sgioba + + + Delete team + Sguab às an sgioba + + + You can't edit teams from team selection. Go back to main menu to add, edit or delete teams. + Chan urrainn dhut sgioba a dheasachadh o thaghadh nan sgioba. Till dhan phrìomh chlàr-taice gus sgioba a chur ris, a dheasachadh no a sguabadh às. + + + New scheme + Sgeama ùr + + + Edit scheme + Deasaich an sgeama + + + Delete scheme + Sguab às an sgeama + + + New weapon set + Seata arm ùr + + + Edit weapon set + Deasach seata nan arm + + + Delete weapon set + Sguab às seata nan arm + + + Advanced + Adhartach + + + Reset to default colors + Ath-suidhich air na dathan tùsail + + + Proxy host + Òstair a' phrogsaidh + + + Proxy port + Port a' phrogsaidh + + + Proxy login + Logadh a-steach a' phrogsaidh + + + Proxy password + Facal-faire a' phrogsaidh + + + No proxy + Gun phrogsaidh + + + Socks5 proxy + Progsaidh Socks5 + + + HTTP proxy + Progsaidh HTTP + + + System proxy settings + Roghainnean progsaidh an t-siostaim + + + Select an action to change what key controls it + Tagh gnìomh gus atharrachadh dè an iuchair a chuireas smachd air + + + Reset to default + Ah-shuidhich air a' bhun-roghainn + + + Reset all binds + Ath-shuidhich gach nasgadh + + + Game + Geama + + + Graphics + Grafaigeachd + + + Audio + Fuaim + + + Controls + Uidheaman-smachd + + + Video Recording + Clàradh video + + + Network + Lìonra + + + Teams + Sgiobaidhean + + + Schemes + Sgeamaichean + + + Weapons + Airm + + + Frontend + Eadar-aghaidh + + + Custom colors + Dathan gnàthaichte + + + Game audio + Fuaim a' gheama + + + Frontend audio + Fuaim na h-eadar-aghaidh + + + Account + Cunntas + + + Proxy settings + Roghainnean a' phrogsaidh + + + Miscellaneous + Measgaichte + + + Updates + Ùrachadh + + + Check for updates + Thoir sùil airson ùrachadh + + + Video recording options + Roghainnean clàradh video + + + + PagePlayDemo + + Rename dialog + Thoir ainm ùr air a' chòmhradh + + + Enter new file name: + Cuir a-steach ainm an fhaidhle ùir: + + + + PageRoomsList + + Create + + + + Join + + + + Admin features + Feartan rianachd + + + Room Name: + + + + %1 players online + %1 chluicheadair air loidhne%1 chluicheadair air loidhne%1 cluicheadairean air loidhne%1 cluicheadair air loidhne + + + Search for a room: + Lorg seòmar: + + + Create room + Cruthaich seòmar + + + Join room + Gabh pàirt ann an seòmar + + + Room state + Staid an t-seòmair + + + Open server administration page + Fosgail duilleag rianachd an fhrithealaiche + + + + PageScheme + + Defend your fort and destroy the opponents, two team colours max! + Dìon an dùn agad agus mill na nàimhdean, dà dhath sgioba air a char as motha! + + + Teams will start on opposite sides of the terrain, two team colours max! + Tòisichidh na sgiobaidhean taobh thall o chàch a chèile, dà dhath sgioba air a char as motha! + + + Land can not be destroyed! + Cha ghabh an tìr a mhilleadh! + + + Lower gravity + Ìslich an iom-tharraing + + + Assisted aiming with laser sight + Cuideachadh dhan amas le fradharc leusair + + + All hogs have a personal forcefield + Bidh raon forsa pearsanta aig gach gràineag + + + Gain 80% of the damage you do back in health + Buannaich slàinte le 80% dhen dochann a nì thu + + + Share your opponents pain, share their damage + Co-roinn pian 's dochann nan nàimhdean + + + Your hogs are unable to move, put your artillery skills to the test + Chan urrainn dha na gràineagan agad gluasad, cuir na sgilean làmhachais agad fo dheuchainn + + + Random + Air thuaiream + + + Seconds + Diog(an) + + + New + Ùr + + + Delete + Sguab às + + + Order of play is random instead of in room order. + Tha òrdugh a' chluiche air thuaiream seach 'na òrdugh an t-seòmair. + + + Play with a King. If he dies, your side dies. + Cluich le rìgh. Gheibh do thaobh bàs ma thèid a mharbhadh. + + + Take turns placing your hedgehogs before the start of play. + Cuir na gràineagan ann fear mu seach mus tòisich an t-sabaid. + + + Ammo is shared between all teams that share a colour. + Co-roinnidh gach sgioba air a bheil an t-aon dath an cuid connaidh. + + + Disable girders when generating random maps. + Cuir teannadairean à comas le gintinn nam mapaichean air thuaiream. + + + Disable land objects when generating random maps. + Cuir oibseactan tìre à comas le gintinn nam mapaichean air thuaiream. + + + AI respawns on death. + Tillidh an IF às dèidh a bhàis. + + + All (living) hedgehogs are fully restored at the end of turn + Gheibh gach gràineag (bheò) a slàinte air ais aig deireadh na cuairte + + + Attacking does not end your turn. + Cha chuir ionnsaigh crìoch air a' chuairt agad. + + + Weapons are reset to starting values each turn. + Thèid na h-airm ath-shuidheachadh air na luachan tùsail aca aig toiseach gach cuairte. + + + Each hedgehog has its own ammo. It does not share with the team. + Tha connadh fa leth aig gach gràineag. Cha cho-roinn i leis an sgioba. + + + You will not have to worry about wind anymore. + Cha bhi dragh ort mun ghaoth tuilleadh. + + + Wind will affect almost everything. + Bidh buair aig a' ghaoth air cha mhòr a h-uile rud. + + + Copy + Dèan lethbhreac + + + Teams in each clan take successive turns sharing their turn time. + Cluichidh buill sgioba fear mu seach, a' co-roinneadh ùine nan cuairtean aca. + + + Add an indestructible border around the terrain + Cuir iomall nach gabh milleadh mun chruth-tìre + + + Add an indestructible border along the bottom + Cuir iomall nach gabh milleadh ris a' bhonn + + + None (Default) + Gun gin (bun-roghainn) + + + Wrap (World wraps) + Pasgadh (pasgaichidh an saoghal) + + + Bounce (Edges reflect) + Bogadh (nì na-h-oirean ath-thilgeil) + + + Sea (Edges connect to sea) + Muir (ceanglaidh na h-oirean ris a' mhuir) + + + + PageSelectWeapon + + Default + Bun-roghainn + + + Delete + Sguab às + + + New + Ùr + + + Copy + Dèan lethbhreac + + + + PageSinglePlayer + + Play a quick game against the computer with random settings + Cluich geama luath an aghaidh a' hoimpiutair le roghainnean air thuaiream + + + Play a hotseat game against your friends, or AI teams + Cluich geama ionadail an aghaidh do charaidean no sgiobaidhean IF + + + Campaign Mode + Modh iomairte + + + Practice your skills in a range of training missions + Cuir gleus air na sgilean agad le miseanan trèanaidh + + + Watch recorded demos + Coimhead air demo clàraichte + + + Load a previously saved game + Luchdaich geama air a shàbhaladh + + + + PageTraining + + No description available + Chan eil tuairisgeul ri làimh + + + Select a mission! + Tagh misean! + + + Pick the mission or training to play + Tagh am misean no trèanadh airson cluiche + + + Start fighting + Tòisich air sabaid + + + + PageVideos + + Name + Ainm + + + Size + Meud + + + %1 bytes + %1 bhaidht%1 bhaidht%1 baidhtichean%1 baidht + + + (in progress...) + (a' dol air adhart...) + + + encoding + 'ga chòdachadh + + + uploading + 'ga luchdadh suas + + + Date: %1 + Ceann-là: %1 + + + Size: %1 + Meud: %1 + + + + QAction + + Kick + Thoir a' bhròg dha + + + Info + Fiosrachadh + + + Restrict Joins + Cuingich a' bhallrachd + + + Restrict Team Additions + Cuingich cur ris sgiobaidhean + + + Ban + Toirmisg + + + Follow + Lean air + + + Ignore + Leig seachad + + + Add friend + Cuir ris na caraidean + + + Unignore + Na leig seachad tuilleadh + + + Remove friend + Thoir air falbh o na caraidean + + + Update + + + + Restrict Unregistered Players Join + Cuingich cluicheadairean gun chlàradh + + + Show games in lobby + Seall geamannan san lobaidh + + + Show games in-progress + Seall na geamannan a tha a' dol + + + + QCheckBox + + Check for updates at startup + Lorg airson ùrachaidhean leis an tòiseachadh + + + Fullscreen + Làn-sgrìn + + + Show FPS + Seall FPS + + + Alternative damage show + Sealladh eile air dochann + + + Append date and time to record file name + Cuir ceann-là 's àm ri ainm faidhle a' chlàraidh + + + Show ammo menu tooltips + Seall gliocasan ann an clàr-taice a' chonnaidh + + + Save password + Sàbhail am facal-faire + + + Save account name and password + Sàbhail ainm a' chunntais 's am facal-faire + + + Video is private + Tha a' video prìobhaideach + + + Record audio + Clàraich an fhuaim + + + Use game resolution + Cleachd dùmhlachd-bhreacaidh a' gheama + + + Visual effects + Èifeachdan lèirsinne + + + Sound + Fuaim + + + In-game sound effects + Èifeachdan fuaime sa gheama + + + Music + Ceòl + + + In-game music + Ceòl sa gheama + + + Frontend sound effects + Èifeachan-fuaime na h-eadar-aghaidh + + + Frontend music + Ceòl na h-eadar-aghaidh + + + Team + Sgioba + + + Enable team tags by default + Cuir tagaichean sgioba an comas o thùs + + + Hog + Gràineag + + + Enable hedgehog tags by default + Cuir tagaichean gràineige an comas o thùs + + + Health + Slàinte + + + Enable health tags by default + Cuir tagaichean slàinte an comas o thùs + + + Translucent + Trìd-shoilleir + + + Enable translucent tags by default + Cuir tagaichean trìd-shoilleir an comas o thùs + + + + QComboBox + + Human + Daonna + + + Level + Leibheil + + + (System default) + (Bun-roghainn an t-siostaim) + + + Community + Coimhearsnachd + + + Disabled + À comas + + + Red/Cyan + Dearg/Saidhean + + + Cyan/Red + Saidhean/Dearg + + + Red/Blue + Dearg/Gorm + + + Blue/Red + Gorm/Dearg + + + Red/Green + Dearg/Uaine + + + Green/Red + Uaine/Dearg + + + Side-by-side + Taobh ri taobh + + + Top-Bottom + Barr gu bonn + + + Red/Cyan grayscale + Liath-sgèile dearg/saidhean + + + Cyan/Red grayscale + Liath-sgèile saidhean/dearg + + + Red/Blue grayscale + Liath-sgèile dearg/gorm + + + Blue/Red grayscale + Liath-sgèile gorm/dearg + + + Red/Green grayscale + Liath-sgèile dearg/uaine + + + Green/Red grayscale + Liath-sgèile uaine/dearg + + + + QGroupBox + + Team Members + Buill an sgioba + + + Fort + Dùn + + + Net game + Geama lìonraidh + + + Playing teams + Sgiobaidhean a chluicheas + + + Game Modifiers + Atharraichearan a' gheama + + + Basic Settings + Roghainnean bunaiteach + + + Team Settings + Roghainnean an sgioba + + + Videos + Videothan + + + Description + Tuairisgeul + + + + QLabel + + Mines Time + Ùine nam mèinnean + + + Mines + Mèinnean + + + Version + + + + Weapons + Airm + + + Host: + Òstair: + + + Port: + Port: + + + Resolution + Dùmhlachd-bhreacaidh + + + FPS limit + Cuingeachadh FPS + + + Server name: + Ainm an fhrithealaiche: + + + Server port: + Port an fhrithealaiche: + + + Initial sound volume + Àirde tùsail na fuaime + + + Damage Modifier + Atharraichearan an dochainn + + + Turn Time + Ùine nan cuartan + + + Initial Health + Slàinte tùsail + + + Sudden Death Timeout + Bàs obann nuair a dh'fhalbhas an ùine + + + Scheme Name: + Ainm an sgeama: + + + Crate Drops + Tuiteam creataichean + + + % Dud Mines + % de mhèinnean gun fheum + + + Name + Ainm + + + Type + Seòrsa + + + Grave + Uaigh + + + Flag + Bratach + + + Voice + Guth + + + Locale + Cànan + + + Explosives + Stuth spreadhaidh + + + Quality + Càileachd + + + % Health Crates + % de chreataichean slàinte + + + Health in Crates + Slàinte ann an creataichean + + + Sudden Death Water Rise + Bàs obann nuair a dh'fhàsas an t-uisge + + + Sudden Death Health Decrease + Bàs obann le droch slàinte + + + % Rope Length + % de dh'fhaide nan ropannan + + + Stereo rendering + Reandaradh stereo + + + Style + Stoidhle + + + Scheme + Sgeama + + + % Get Away Time + % a dh'ùine gus teicheadh + + + There are videos that are currently being processed. +Exiting now will abort them. +Do you really want to quit? + Tha videothan 'gam pròiseasadh an-dràsta. +Sguiridh tu dheth ma dh'fhàgas tu an-seo. +A bheil thu airson fàgail an-seo dha-rìribh? + + + Please provide either the YouTube account name or the email address associated with the Google Account. + Cuir a-steach ainm a' chunntais agad air YouTube no an seòladh puist-d a tha co-cheangailte ris a' chunntas Google agad. + + + Account name (or email): + Ainm a' chunntais (no post-d): + + + Password: + Facal-faire: + + + Video title: + Tiotal a' video: + + + Video description: + Tuairisgeul a' video: + + + Tags (comma separated): + Tagaichean (sgaraichte le cromagan): + + + Description + Tuairisgeul + + + Nickname + Far-ainm + + + Format + Fòrmat + + + Audio codec + Codec fuaime + + + Video codec + Codec video + + + Framerate + Astar nam frèam + + + Bitrate (Kbps) + Bitrate (Kbps) + + + This development build is 'work in progress' and may not be compatible with other versions of the game, while some features might be broken or incomplete! + 'S e "obair 'ga dhèanamh" a tha san togail leasachaidh seo agus dh'fhaoidte nach eil e co-chòrdail ri tionndaidhean eile a' gheama agus gu bheil cuid a dh'fheartan briste no neo-choileanta! + + + Fullscreen + Làn-sgrìn + + + Fullscreen Resolution + Dùmhlachd-bhreacaidh làn-sgrìn + + + Windowed Resolution + Dùmhlachd-bhreacaidh sa mhodh uinneagach + + + Your Email + Am post-d agad + + + Summary + Gearr-chunntas + + + Send system information + Cuir fiosrachadh an t-siostaim + + + Type the security code: + Sgrìobh còd na tèarainteachd: + + + Revision + Lèirmheas + + + This program is distributed under the %1 + Tha am prògram seo 'ga sgaoileadh fo cheadachas %1 + + + This setting will be effective at next restart. + Bidh an roghainn seo an sàs nuair a bhios tu air tòiseachadh às ùr. + + + Tip: %1 + Gliocas: %1 + + + Displayed tags above hogs and translucent tags + Tagaichean a nochdas os cionn ghràineagan 's tagaichean trìd-shoilleir + + + World Edge + Oir an t-saoghail + + + Script parameter + Paramadair an sgriobt + + + + QLineEdit + + unnamed + gun ainm + + + hedgehog %1 + gràineag %1 + + + anonymous + gun ainm + + + + QMainWindow + + Hedgewars %1 + Hedgewars %1 + + + + QMessageBox + + Connection to server is lost + Chaidh an ceangal ris an fhrithealaiche air chall + + + Error + Mearachd + + + File association failed. + Dh'fhaillig le co-cheangal an fhaidhle. + + + Error while authenticating at google.com: + + Mearachd le dearbhadh le google.com: + + + + Login or password is incorrect + Chan eil an t-ainm-clàraidh no facal-faire mar bu chòir + + + Error while sending metadata to youtube.com: + + Mearachd a' cur meata-dàta gu youtube.com: + + + + Teams - Are you sure? + Sgiobaidhean - A bheil thu cinnteach? + + + Do you really want to delete the team '%1'? + A bheil thu airson an sgioba "%1" a sguabadh às dha-rìribh? + + + Cannot delete default scheme '%1'! + Chan urrainn dhut an sgeama tùsail "%1" a sguabadh às! + + + Please select a record from the list + Tagh clàr on liosta + + + Unable to start server + Cha ghabh am frithealaiche a thòiseachadh + + + Hedgewars - Error + Hedgewars - Mearachd + + + Hedgewars - Success + Hedgewars - Shoirbhich leis + + + All file associations have been set + Chaidh gach co-cheangal faidhle a shuidheachadh + + + Cannot create directory %1 + + + + Unable to start the server: %1. + + + + Video upload - Error + Luchdadh suas video - Mearachd + + + Netgame - Error + Geama lìonraidh - Mearachd + + + Please select a server from the list + Tagh frithealaiche on liosta + + + Please enter room name + Cuir a-steach ainm an t-seòmair + + + Record Play - Error + Cluiche clàraidh - Mearachd + + + Please select record from the list + Tagh clàradh on liosta + + + Cannot rename to + Cha ghabh ainm atharrachadh gu + + + Cannot delete file + Chan urrainn dhuinn am faidhle a sguabadh às + + + Room Name - Error + Ainm an t-seòmair - Mearachd + + + Please select room from the list + Tagh seòmar on liosta + + + Room Name - Are you sure? + Ainm an t-seòmair - A bheil thu cinnteach? + + + The game you are trying to join has started. +Do you still want to join the room? + Tha an geama sa bheil thu airson tighinn a-steach air tòiseachadh. +A bheil thu airson tighinn a-steach dhan t-seòmar fhathast? + + + Schemes - Warning + Sgeamaichean - Rabhadh + + + Schemes - Are you sure? + Sgeamaichean - A bheil thu cinnteach? + + + Do you really want to delete the game scheme '%1'? + A bheil thu airson sgeama a' gheama "%1" a sguabadh às dha-rìribh? + + + Videos - Are you sure? + Videothan - A bheil thu cinnteach? + + + Do you really want to delete the video '%1'? + A bheil thu airson a' video "%1" a sguabadh às dha-rìribh? + + + Do you really want to remove %1 file(s)? + A bheil thu airson %1 fhaidhle a sguabadh às dha-rìribh?A bheil thu airson %1 fhaidhle a sguabadh às dha-rìribh?A bheil thu airson %1 faidhlichean a sguabadh às dha-rìribh?A bheil thu airson %1 faidhle a sguabadh às dha-rìribh? + + + Do you really want to cancel uploading %1? + A bheil thu airson sgur de luchdadh suas %1? + + + File error + Mearachd faidhle + + + Cannot open '%1' for writing + Cha ghabh "%1" fosgladh airson sgrìobhadh ann + + + Cannot open '%1' for reading + Cha ghabh "%1" fosgladh airson a leughadh + + + Cannot use the ammo '%1'! + Cha ghabh an connadh "%1" cleachdadh! + + + Weapons - Warning + Airm - Rabhadh + + + Cannot overwrite default weapon set '%1'! + Cha ghabh sgrìobhadh thairis air seata nan arm tùsail "%1"! + + + Cannot delete default weapon set '%1'! + Cha ghabh seata nan arm tùsail "%1" sguabadh às! + + + Weapons - Are you sure? + Airm - A bheil thu cinnteach? + + + Do you really want to delete the weapon set '%1'? + A bheil thu airson seata nan arm "%1" a sguabadh às dha-rìribh? + + + Hedgewars - Nick not registered + Hedgewars - Far-ainm gun chlàradh + + + System Information Preview + Ro-shealladh air fiosrachadh an t-siostaim + + + Failed to generate captcha + Cha deach leinn captcha a ghintinn + + + Failed to download captcha + Cha deach leinn captcha a luchdadh a-nuas + + + Please fill out all fields. Email is optional. + Feuch an lìon thu a h-uile raon. Cha leig thu leas am post-d a lìonadh. + + + Hedgewars - Warning + Hedgewars - Rabhadh + + + Hedgewars - Information + Hedgewars - Fiosrachadh + + + Not all players are ready + Chan eil gach cluicheadair ullamh fhathast + + + Are you sure you want to start this game? +Not all players are ready. + A bheil thu cinnteach gu bheil thu airson an geama seo a thòiseachadh? +Chan eil a h-uile cluicheadair ullamh. + + + + QObject + + No description available + Chan eil tuairisgeul ri làimh + + + + QPushButton + + default + bun-roghainn + + + OK + Ceart ma-thà + + + Cancel + Sguir dheth + + + Start server + Tòisich an fhrithealaiche + + + Connect + Ceangail + + + Update + Ùraich + + + Specify + Sònraich + + + Start + Tòisich + + + Go! + Siuthad! + + + Play demo + Cluich demo + + + Rename + Thoir ainm ùr air + + + Delete + Sguab às + + + Load + Luchdaich + + + Associate file extensions + Co-cheangail leudachain faidhle. + + + More info + Barrachd fiosrachaidh + + + Set default options + Suidhich na bun-roghainnean + + + Open videos directory + Fosgail pasgan nam videothan + + + Play + Cluich + + + Upload to YouTube + Luchdaich suas gu YouTube + + + Cancel uploading + Sguir dhen luchdadh suas + + + Restore default coding parameters + Aisig paramadairean tùsail a' chòdachaidh + + + Open the video directory in your system + Fosgail pasgan nam videothan san t-siostam agad + + + Play this video + Cluich a' video seo + + + Delete this video + Sguab às a' video seo + + + Upload this video to your Youtube account + Luchdaich suas a' video seo dhan chunntas Youtube agad + + + Reset + Ah-shuidhich + + + Set the default server port for Hedgewars + Suidhich port tùsail an fhrithealaiche airson Hedgewars + + + Invite your friends to your server in just 1 click! + Na dèan ach 1 bhriogadh gus cuireadh dhan fhrithealaiche a thoirt dha na caraidean agad! + + + Click to copy your unique server URL to your clipboard. Send this link to your friends and they will be able to join you. + Briog gus lethbhreac de URL sònraichte an fhrithealaiche agad a chur dhan stòr-bhòrd. Cuir an ceangal seo dha na caraidean agad ach an tig iad a-steach. + + + Start private server + Tòisich frithealaiche prìobhaideach + + + + RoomNamePrompt + + Enter a name for your room. + Cuir a-steach ainm an t-seòmair agad. + + + Cancel + Sguir dheth + + + Create room + Cruthaich seòmar + + + set password + suidhich am facal-faire + + + + RoomsListModel + + In progress + 'Ga dhèanamh + + + Room Name + Ainm an t-seòmair + + + C + Cl. + + + T + Sg. + + + Owner + Seilbheadair + + + Map + Mapa + + + Rules + Riaghailtean + + + Weapons + Airm + + + Random Map + Mapa air thuaiream + + + Random Maze + Cuartan air thuaiream + + + Hand-drawn + Air a tharraing a làimh + + + Script + Sgriobt + + + Random Perlin + Perlin tuaireamach + + + + SeedPrompt + + The map seed is the basis for all random values generated by the game. + Tha sìol a' mhapa 'na bhunait airson gach luach air thuaiream a ghineas an geama. + + + Cancel + Sguir dheth + + + Set seed + Suidhich an sìol + + + Close + Dùin + + + + SelWeaponWidget + + Weapon set + Seata arm + + + Probabilities + Coltachdan + + + Ammo in boxes + Connadh ann am bogsaichean + + + Delays + Dàlaichean + + + new + ùr + + + copy of %1 + lethbhreac de %1 + + + + TCPBase + + Unable to start server at %1. + Cha ghabh am frithealaiche a thòiseachadh air %1. + + + Unable to run engine at %1 +Error code: %2 + Cha ghabh an t-einnsean a ruith air %1 +Còd na mearachd: %2 + + + The game engine died unexpectedly! +(exit code %1) + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%2' button in the main menu! + Bhàsaich inneal a' gheama gun dùil. +(còd fàgail %1) + +Tha sinn glè dhuilich mun trioblaid seo :( + +Ma thachras seo a-rithist 's a-rithist, briog air a' phutan "%2" sa phrìomh chlàr-taice! + + + + TeamSelWidget + + At least two teams are required to play! + Feumadh tu co-dhiù dà sgioba airson cluiche! + + + + ThemePrompt + + Cancel + Sguir dheth + + + Search for a theme: + Lorg ùrlar: + + + Use selected theme + Cleachd an t-ùrlar a thagh thu + + + + binds + + up + suas + + + left + gu clì + + + right + gu deas + + + down + sìos + + + attack + ionnsaigh + + + precise aim + amas pongail + + + put + cuir + + + switch + dèan suids + + + find hedgehog + + + + ammo menu + clàr-taice a' chonnaidh + + + slot 1 + slot 1 + + + slot 2 + slot 2 + + + slot 3 + slot 3 + + + slot 4 + slot 4 + + + slot 5 + slot 5 + + + slot 6 + slot 6 + + + slot 7 + slot 7 + + + slot 8 + slot 8 + + + slot 9 + slot 9 + + + timer 1 sec + tìmear 1 diog + + + timer 2 sec + tìmear 2 dhiog + + + timer 3 sec + tìmear 3 diogan + + + timer 4 sec + tìmear 4 diogan + + + timer 5 sec + tìmear 5 diogan + + + chat + cabadaich + + + chat history + eachdraidh a' chabadaich + + + pause + cuir 'na stad + + + confirmation + dearbhadh + + + volume down + fuaim sìos + + + volume up + fuaim suas + + + change mode + atharraich am modh + + + capture + glac + + + quit + fàg an-seo + + + zoom in + sùm a-steach + + + zoom out + sùm a-mach + + + reset zoom + ath-shuidhich an sùm + + + long jump + leum fada + + + high jump + leum àrd + + + slot 10 + slot 10 + + + mute audio + mùch an fhuaim + + + record + clàraich + + + hedgehog info + fiosrachadh na gràineige + + + autocam / find hedgehog + camara fèin-obrachail / lorg gràineag + + + speed up replay + luathaich an ath-chluiche + + + + binds (categories) + + Movement + Gluasad + + + Weapons + Airm + + + Camera + Camara + + + Miscellaneous + Measgaichte + + + + binds (descriptions) + + Traverse gaps and obstacles by jumping: + Leum thairis air beàrnan 's ribean: + + + Fire your selected weapon or trigger an utility item: + Loisg an t-arm a thagh thu no cleachd acainn: + + + Pick a weapon or a target location under the cursor: + Tagh arm no ceann-uidhe fon chùrsair: + + + Switch your currently active hog (if possible): + Gearr leum gu gràineag eile (ma ghabhas seo dèanamh): + + + Pick a weapon or utility item: + Tagh arm no acainn: + + + Set the timer on bombs and timed weapons: + Suidhich an tìmear air boma no arm eile le tìmear: + + + Move the camera to the active hog: + + + + Move the cursor or camera without using the mouse: + Gluais an cùrsair no an camara gun a bhith a' cleachdadh na luchaige: + + + Modify the camera's zoom level: + Atharraich sùmadh a' chamara: + + + Talk to your team or all participants: + Bruidhinn ris an sgioba agad no ris a h-uile duine: + + + Pause, continue or leave your game: + Cuir an geama agad 'na stad, lean air no fàg e: + + + Modify the game's volume while playing: + Atharraich àirde fuaime a' gheama fhad 's a bhios tu a' cluich: + + + Toggle fullscreen mode: + Toglaich am modh làn-sgrìn: + + + Take a screenshot: + Tog glacadh-sgrìn: + + + Toggle labels above hedgehogs: + Toglaich na leubailean os cionn nan gràineagan: + + + Record video: + Clàraich video: + + + Hedgehog movement + Gluasad nan gràineagan + + + Toggle automatic camera / refocus on active hedgehog: + Toglaich an camara fèin-obrachail / cuir am fòcas air a' ghràineag ghnìomhach a-rithist: + + + Demo replay: + Ath-chluiche an demo: + + + + binds (keys) + + Axis + Aiseal + + + (Up) + (Suas) + + + (Down) + (Sìos) + + + Hat + Ad + + + (Left) + (Gu clì) + + + (Right) + (Gu deas) + + + Button + Putan + + + Keyboard + Meur-chlàr + + + Delete + Delete + + + Mouse: Left button + Luchag: putan clì + + + Mouse: Middle button + Luchag: putan meadhanach + + + Mouse: Right button + Luchag: putan deas + + + Mouse: Wheel up + Luchag: cuibhle suas + + + Mouse: Wheel down + Luchag: cuibhle sìos + + + Backspace + Backspace + + + Tab + Taba + + + Clear + Clear + + + Return + Return + + + Pause + Pause + + + Escape + Escape + + + Space + Space + + + Numpad 0 + 0 air pada nan àireamh + + + Numpad 1 + 1 air pada nan àireamh + + + Numpad 2 + 2 air pada nan àireamh + + + Numpad 3 + 3 air pada nan àireamh + + + Numpad 4 + 4 air pada nan àireamh + + + Numpad 5 + 5 air pada nan àireamh + + + Numpad 6 + 6 air pada nan àireamh + + + Numpad 7 + 7 air pada nan àireamh + + + Numpad 8 + 8 air pada nan àireamh + + + Numpad 9 + 9 air pada nan àireamh + + + Numpad . + . air pada nan àireamh + + + Numpad / + / air pada nan àireamh + + + Numpad * + * air pada nan àireamh + + + Numpad - + - air pada nan àireamh + + + Numpad + + + air pada nan àireamh + + + Enter + Enter + + + Equals + Co-ionnnannachd + + + Up + Suas + + + Down + Sìos + + + Right + Gu clì + + + Left + Gu deas + + + Insert + Insert + + + Home + Home + + + End + End + + + Page up + Page up + + + Page down + Page down + + + Num lock + Num lock + + + Caps lock + Caps lock + + + Scroll lock + Scroll lock + + + Right shift + Shift deas + + + Left shift + Shift clì + + + Right ctrl + Ctrl deas + + + Left ctrl + Ctrl clì + + + Right alt + Alt deas + + + Left alt + Alt clì + + + Right meta + Meta deas + + + Left meta + Meta clì + + + A button + Putan A + + + B button + Putan B + + + X button + Putan X + + + Y button + Putan Y + + + LB button + Putan LB + + + RB button + Putan RB + + + Back button + Putan Back + + + Start button + Putan Start + + + Left stick + Stick clì + + + Right stick + Stick deas + + + Left stick (Right) + Stick clì (gu deas) + + + Left stick (Left) + Stick clì (gu clì) + + + Left stick (Down) + Stick clì (sìos) + + + Left stick (Up) + Stick clì (suas) + + + Left trigger + Trigear clì + + + Right trigger + Trigear deas + + + Right stick (Down) + Stick deas (sìos) + + + Right stick (Up) + Stick deas (suas) + + + Right stick (Right) + Stick deas (gu deas) + + + Right stick (Left) + Stick deas (gu clì) + + + DPad + DPad + + + + server + + Restricted + Cuingichte + + + Not room master + Cha tusa ceannard an t-seòmair + + + Corrupted hedgehogs info + Fiosrachadh hedgehogs coirbte + + + too many teams + cus sgiobaidhean + + + too many hedgehogs + cus gràineagan + + + There's already a team with same name in the list + Tha sgioba air a bheil an t-aon ainm air an liosta mar-thà + + + round in progress + tha cuairt a' dol + + + restricted + cuingichte + + + REMOVE_TEAM: no such team + REMOVE_TEAM: chan eil an sgioba seo ann + + + Not team owner! + Chan ann leatsa a tha an sgioba seo! + + + Less than two clans! + Tha nas lugha na dà chinneadh ann! + + + Illegal room name + Ainm an t-seòmair mì-dhligheach + + + Room with such name already exists + Cha seòmair air a bheil an t-ainm seo ann mar-thà + + + Nickname already chosen + Chaidh am far-ainm seo a thaghadh mar-thà + + + Illegal nickname + Far-ainm mì-dhligheach + + + Protocol already known + Tha am pròtacail aithnichte mar-thà + + + Bad number + Droch àireamh + + + Nickname is already in use + Tha am far-ainm 'ga chleachdadh mar-thà + + + No checker rights + Chan eil ceadan dearbhaidh ann + + + Authentication failed + Dh'fhàillig leis an dearbhadh + + + 60 seconds cooldown after kick + Gabh air do shocair fad 60 diog às dèidh a' bhròg fhaighinn + + + kicked + fhuair thu a' bhròg + + + Ping timeout + Dh'fhalbh an ùine air ping + + + bye + mar sin leat + + + No such room + Chan eil an seòmar seo ann + + + Room version incompatible to your hedgewars version + Tha tionndadh dhen t-seòmar mì-chòrdail ris an tionndadh de hedgewars agad + + + Joining restricted + Tha tighinn a-steach cuingichte + + + Registered users only + Buill clàraichte a-mhàin + + + You are banned in this room + Chaidh do thoirmeasg on t-seòmar seo + + + Empty config entry + Innteart rèiteachaidh falamh + + + You already have voted + Rinn thu bhòtadh mar-thà + + + Voting closed + Chaidh bhòtadh a dhùnadh + + + New voting started + Thòisich bhòtadh ùr + + + Voting expired + Dh'fhalbh an ùine air a' bhòtadh + + + kick + thoir a' bhròg + + + map + mapa + + + pause + cuir 'na stad + + + Reconnected too fast + Chaidh ath-cheangal ro luath + + + Warning! Chat flood protection activated + Rabhadh! Chaidh dìon tuile na cabadaich a ghnìomhachadh + + + Excess flood + Tuile a bharrachd + + + Game messages flood detected - 1 + Mhothaich sinn air tuile teachdaireachdan a' gheama - 1 + + + Game messages flood detected - 2 + Mhothaich sinn air tuile teachdaireachdan a' gheama - 2 + + + Warning! Joins flood protection activated + Rabhadh! Chan fhaod torr dhaoine ùra tighinn dhan fhrithealaiche gu luath + + + There's no voting going on + Chan eil bhòtadh a' tachairt + + + \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/hedgewars_gl.ts --- a/share/hedgewars/Data/Locale/hedgewars_gl.ts Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/hedgewars_gl.ts Tue Nov 10 20:43:13 2015 +0100 @@ -22,7 +22,7 @@ novo - copy of + copy of %1 @@ -211,6 +211,56 @@ Please check your installation! + + Usage + command-line + + + + OPTION + command-line + + + + CONNECTSTRING + command-line + + + + Options + command-line + + + + Display this help + command-line + + + + Custom path for configuration data and user data + command-line + + + + Custom path to the game data folder + command-line + + + + Hedgewars can use a %1 (e.g. "%2") to connect on start. + command-line + + + + Malformed option argument: %1 + command-line + + + + Unknown option argument: %1 + command-line + + HWAskQuitDialog @@ -400,6 +450,17 @@ Cannot open demofile %1 Non se pode abrir a demostración %1 + + A Fatal ERROR occured! - The game engine had to stop. + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%1' button in the main menu! + +Last two engine messages: +%2 + + HWMapContainer @@ -527,6 +588,14 @@ Theme: %1 + + Random perlin + + + + Style: + + HWNetServersModel @@ -593,6 +662,10 @@ The server is too old. Disconnecting now. + + Server authentication error + + HWPasswordDialog @@ -773,6 +846,10 @@ This page requires an internet connection. + + Open packages directory + + PageDrawMap @@ -824,6 +901,10 @@ Ellipse + + Optimize + + PageEditTeam @@ -882,9 +963,12 @@ Ranking - + The best shot award was won by <b>%1</b> with <b>%2</b> pts. - + + + + The best killer is <b>%1</b> with <b>%2</b> kills in a turn. @@ -2076,6 +2160,10 @@ World Edge + + Script parameter + + QLineEdit @@ -2520,6 +2608,10 @@ Script + + Random Perlin + + SeedPrompt @@ -2563,7 +2655,7 @@ novo - copy of + copy of %1 @@ -2578,6 +2670,15 @@ Error code: %2 + + The game engine died unexpectedly! +(exit code %1) + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%2' button in the main menu! + + TeamSelWidget @@ -2637,7 +2738,7 @@ find hedgehog - atopar ourizo + atopar ourizo ammo menu @@ -2771,6 +2872,14 @@ hedgehog info + + autocam / find hedgehog + + + + speed up replay + + binds (categories) @@ -2819,7 +2928,7 @@ Move the camera to the active hog: - Move a cámara ao ourizo activo: + Move a cámara ao ourizo activo: Move the cursor or camera without using the mouse: @@ -2861,6 +2970,14 @@ Hedgehog movement + + Toggle automatic camera / refocus on active hedgehog: + + + + Demo replay: + + binds (keys) @@ -3303,5 +3420,61 @@ Empty config entry + + You already have voted + + + + Voting closed + + + + New voting started + + + + Voting expired + + + + kick + + + + map + + + + pause + pausa + + + Reconnected too fast + + + + Warning! Chat flood protection activated + + + + Excess flood + + + + Game messages flood detected - 1 + + + + Game messages flood detected - 2 + + + + Warning! Joins flood protection activated + + + + There's no voting going on + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/hedgewars_hu.ts --- a/share/hedgewars/Data/Locale/hedgewars_hu.ts Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/hedgewars_hu.ts Tue Nov 10 20:43:13 2015 +0100 @@ -22,7 +22,7 @@ új - copy of + copy of %1 @@ -205,6 +205,56 @@ Please check your installation! + + Usage + command-line + + + + OPTION + command-line + + + + CONNECTSTRING + command-line + + + + Options + command-line + + + + Display this help + command-line + + + + Custom path for configuration data and user data + command-line + + + + Custom path to the game data folder + command-line + + + + Hedgewars can use a %1 (e.g. "%2") to connect on start. + command-line + + + + Malformed option argument: %1 + command-line + + + + Unknown option argument: %1 + command-line + + HWAskQuitDialog @@ -394,6 +444,17 @@ Cannot open demofile %1 Nem sikerült megnyitni a %1 demót + + A Fatal ERROR occured! - The game engine had to stop. + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%1' button in the main menu! + +Last two engine messages: +%2 + + HWMapContainer @@ -521,6 +582,14 @@ Theme: %1 + + Random perlin + + + + Style: + + HWNetServersModel @@ -587,6 +656,10 @@ The server is too old. Disconnecting now. + + Server authentication error + + HWPasswordDialog @@ -767,6 +840,10 @@ This page requires an internet connection. + + Open packages directory + + PageDrawMap @@ -818,6 +895,10 @@ Ellipse + + Optimize + + PageEditTeam @@ -876,9 +957,11 @@ Ranking - + The best shot award was won by <b>%1</b> with <b>%2</b> pts. - + + + The best killer is <b>%1</b> with <b>%2</b> kills in a turn. @@ -2061,6 +2144,10 @@ World Edge + + Script parameter + + QLineEdit @@ -2504,6 +2591,10 @@ Script + + Random Perlin + + SeedPrompt @@ -2547,7 +2638,7 @@ új - copy of + copy of %1 @@ -2562,6 +2653,15 @@ Error code: %2 + + The game engine died unexpectedly! +(exit code %1) + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%2' button in the main menu! + + TeamSelWidget @@ -2621,7 +2721,7 @@ find hedgehog - süni megtalálása + süni megtalálása ammo menu @@ -2755,6 +2855,14 @@ hedgehog info + + autocam / find hedgehog + + + + speed up replay + + binds (categories) @@ -2803,7 +2911,7 @@ Move the camera to the active hog: - Kamera mozgatása az aktív sünire: + Kamera mozgatása az aktív sünire: Move the cursor or camera without using the mouse: @@ -2845,6 +2953,14 @@ Hedgehog movement + + Toggle automatic camera / refocus on active hedgehog: + + + + Demo replay: + + binds (keys) @@ -3287,5 +3403,61 @@ Empty config entry + + You already have voted + + + + Voting closed + + + + New voting started + + + + Voting expired + + + + kick + + + + map + + + + pause + szünet + + + Reconnected too fast + + + + Warning! Chat flood protection activated + + + + Excess flood + + + + Game messages flood detected - 1 + + + + Game messages flood detected - 2 + + + + Warning! Joins flood protection activated + + + + There's no voting going on + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/hedgewars_it.ts --- a/share/hedgewars/Data/Locale/hedgewars_it.ts Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/hedgewars_it.ts Tue Nov 10 20:43:13 2015 +0100 @@ -22,8 +22,8 @@ nuovo - copy of - copia di + copy of %1 + copia di %1 @@ -58,7 +58,7 @@ you know why - + tu sai perché Warning @@ -99,22 +99,10 @@ Invia commento - Please give us feedback! - Per favore, inviaci un commento! - - We are always happy about suggestions, ideas, or bug reports. Siamo sempre felici di ricevere suggerimenti, idee o segnalazioni di bachi. - If you found a bug, you can see if it's already known here (english): - Se trovi un baco, puoi vedere se è già conosciuto qui (in inglese): - - - Your email address is optional, but we may want to contact you. - Il tuo indirizzo di posta elettronica è opzionale, ma potremmo volerti contattare. - - Send us feedback! Mandaci un commento! @@ -152,10 +140,6 @@ Modifica schemi - Game Options - Opzioni di Gioco - - Game scheme will auto-select a weapon Lo schema di gioco sceglierà automaticamente un'arma @@ -172,7 +156,7 @@ GameUIConfig Guest - + Ospite @@ -230,6 +214,56 @@ Per favore controlla l'installazione! + + Usage + command-line + Utilizzo + + + OPTION + command-line + OPZIONI + + + CONNECTSTRING + command-line + STRINGACONNESSIONE + + + Options + command-line + Opzioni + + + Display this help + command-line + Visualizza questo messaggio di help + + + Custom path for configuration data and user data + command-line + Percorso personalizzato per la configurazione e i dati utente + + + Custom path to the game data folder + command-line + Percorso personalizzato per i dati del gioco + + + Hedgewars can use a %1 (e.g. "%2") to connect on start. + command-line + Hedgewars può usare un %1 (per esempio "%2") per connettersi all'avvio. + + + Malformed option argument: %1 + command-line + Argomento %1 errato + + + Unknown option argument: %1 + command-line + Opzione %1 sconosciuta + HWAskQuitDialog @@ -407,16 +441,17 @@ Guest - + Ospite Room password - + Password stanza The room is protected with password. Please, enter the password: - + Questa stanza è protetta da password. +Per piacere, inserisci la password: @@ -429,6 +464,24 @@ Cannot open demofile %1 Impossibile aprire il file demo %1 + + A Fatal ERROR occured! - The game engine had to stop. + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%1' button in the main menu! + +Last two engine messages: +%2 + ERRORE non recuperabile! Il motore di gioco si è dovuto arrestare. + +Ci dispiace molto per l'inconveniente :( + +Se continua a succedere, per piacere clicca il bottone '%1' nel menu principale! + +Ultimi due messaggi del motore: +%2 + HWMapContainer @@ -537,10 +590,6 @@ Mappa: - Theme: - Tema: - - Load drawn map Carica mappa disegnata @@ -560,6 +609,14 @@ Theme: %1 Tema: %1 + + Random perlin + Rumore casuale + + + Style: + Stile: + HWNetServersModel @@ -603,10 +660,6 @@ %1 *** %2 è entrato nella stanza - %1 *** %2 has joined - %1 *** %2 è entrato - - %1 *** %2 has left (%3) %1 *** %2 ha lasciato (%3) @@ -626,6 +679,10 @@ The server is too old. Disconnecting now. Il server è troppo datato. Si verrà immediatamente disconessi. + + Server authentication error + Errore di autenticazione server + HWPasswordDialog @@ -686,13 +743,6 @@ - KB - - SDL_ttf returned error while rendering text, most propably it is related to the bug in freetype2. It's recommended to update your freetype lib. - SDL_ttf ha restituito un errore durante il rendering del testo, probabilmente relativo ad un bug della libreria freetype2. Si raccomanda di aggiornare le proprie librerie freetype. - - - KeyBinder Category @@ -702,19 +752,6 @@ LibavInteraction - Duration: %1m %2s - - Durata: %1m %2s - - - Video: %1x%2, - Video: %1x%2, - - - %1 fps, - %1 fps, - - Audio: Audio: @@ -724,15 +761,15 @@ Duration: %1m %2s - + Durata: %1m %2s Video: %1x%2 - + Video: %1x%2 %1 fps - + %1 fps @@ -822,6 +859,10 @@ This page requires an internet connection. Questa pagina richiede una connessione a Internet. + + Open packages directory + Apri la cartella dei pacchetti + PageDrawMap @@ -863,15 +904,19 @@ Polyline - + Polilinea Rectangle - + Rettangolo Ellipse - + Ellisse + + + Optimize + Ottimizza @@ -931,9 +976,12 @@ Ranking Classifica - + The best shot award was won by <b>%1</b> with <b>%2</b> pts. - Il premio per il miglior colpo è stato vinto da <b>%1</b> con <b>%2</b> punti. + + Il premio per il miglior colpo è stato vinto da <b>%1</b> con <b>%2</b> punti. + + The best killer is <b>%1</b> with <b>%2</b> kills in a turn. @@ -987,9 +1035,9 @@ (%1 %2) - - - + + (%1 %2) + (%1 %2) @@ -1080,10 +1128,6 @@ PageNetGame - Control - Controllo - - Edit game preferences Modifica preferenze @@ -1296,37 +1340,9 @@ PageRoomsList - Create - Crea - - - Join - Entra - - Admin features Opzioni amministrative - - Room Name: - Nome stanza: - - - Rules: - Regole: - - - Weapons: - Armi: - - - Search: - Cerca: - - - Clear - Cancella - %1 players online @@ -1351,10 +1367,6 @@ Stato della stanza - Clear filters - Rimuovi filtri - - Open server administration page Apri pagina di amministrazione del server @@ -1483,19 +1495,19 @@ None (Default) - + Nessuno (Default) Wrap (World wraps) - + Avvolgi (il mondo avvolge) Bounce (Edges reflect) - + Rimbalza (i bordi si riflettono) Sea (Edges connect to sea) - + Mare (i bordi si connettono al mare) @@ -1593,26 +1605,12 @@ caricamento - Date: %1 - - Data: %1 - - - - Size: %1 - - Dimensione: %1 - - - Date: %1 - Data: %1 - {1?} + Data: %1 Size: %1 - Dimensione: %1 - {1?} + Dimensione: %1 @@ -1658,10 +1656,6 @@ Rimuovi amico - Update - Aggiorna - - Restrict Unregistered Players Join Impedisci la partecipazione di giocatori non registrati @@ -1750,35 +1744,35 @@ Team - + Squadra Enable team tags by default - + Abilita i tag della squadra in automatico Hog - + Riccio Enable hedgehog tags by default - + Abilita i tag dei ricci in automatico Health - + Vita Enable health tags by default - + Abilita i tag della vita in automatico Translucent - + Semitrasparente Enable translucent tags by default - + Abilita i tag semitrasparenti in automatico @@ -1800,18 +1794,6 @@ Comunità - Any - Qualsiasi - - - In lobby - In lobby - - - In progress - In corso - - Disabled Disabilitato @@ -1950,10 +1932,6 @@ Porta del server: - Version - Versione - - Initial sound volume Volume sonoro iniziale @@ -2014,10 +1992,6 @@ Esplosivi - Tip: - Suggerimento: - - Quality Qualità @@ -2058,10 +2032,6 @@ % Tempo regalo - This program is distributed under the GNU General Public License v2 - Questo programma è distribuito con licenza GNU General Public License v2 - - There are videos that are currently being processed. Exiting now will abort them. Do you really want to quit? @@ -2167,15 +2137,19 @@ Tip: %1 - + Consiglio: %1 Displayed tags above hogs and translucent tags - + Visualizza i tag sopra i ricci e i tag semitrasparenti World Edge - + Bordi del mondo + + + Script parameter + Parametro dello script @@ -2186,7 +2160,7 @@ hedgehog %1 - Riccio %1 + riccio %1 anonymous @@ -2199,10 +2173,6 @@ Hedgewars %1 Hedgewars %1 - - -r%1 (%2) - -r%1 (%2) - QMessageBox @@ -2265,40 +2235,6 @@ Tutte le associazioni di file sono state impostate - Main - Error - Main - Errore - - - Cannot create directory %1 - Impossibile creare la directory %1 - - - Failed to open data directory: -%1 - -Please check your installation! - Impossibile creare la directory dati: -%1 - -Per favore controlla l'installazione! - - - TCP - Error - TCP - Errore - - - Unable to start the server: %1. - Impossibile avviare il server: %1. - - - Unable to run engine at - Impossibile avviare il motore a - - - Error code: %1 - Codice di errore: %1 - - Video upload - Error Caricamento video - Errore @@ -2444,10 +2380,6 @@ Hedgewars - Avviso - Hedgewars - Hedgewars - - Not all players are ready Non tutti i giocatori sono pronti @@ -2462,7 +2394,7 @@ QObject No description available - Nessuna descrizione disponibile + Nessuna descrizione disponibile @@ -2604,7 +2536,7 @@ set password - + imposta la password @@ -2655,7 +2587,11 @@ Script - + Script + + + Random Perlin + Rumore casuale @@ -2700,8 +2636,8 @@ nuovo - copy of - copia di + copy of %1 + copia di %1 @@ -2716,6 +2652,20 @@ Impossibile eseguire il motore a %1 Codice di errore: %2 + + The game engine died unexpectedly! +(exit code %1) + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%2' button in the main menu! + Il motore del gioco è morto inaspettatamente! +(codice di uscita %1) + +Ci dispiace molto per l'inconveniente :( + +Se questo continua a succedere, per piacere clicca il bottone '%2' nel menu principale! + TeamSelWidget @@ -2725,13 +2675,6 @@ - TeamShowWidget - - %1's team - Squadra di %1 - - - ThemePrompt Cancel @@ -2777,10 +2720,6 @@ cambia - find hedgehog - trova riccio - - ammo menu menu delle armi @@ -2916,6 +2855,14 @@ hedgehog info informazioni riccio + + autocam / find hedgehog + camera automatica / trova riccio + + + speed up replay + aumenta velocità replay + binds (categories) @@ -2963,10 +2910,6 @@ Imposta il timer di granate e armi a tempo: - Move the camera to the active hog: - Muovi la camera verso il riccio attivo: - - Move the cursor or camera without using the mouse: Muovi il cursore o la camera senza usare il mouse: @@ -3006,6 +2949,14 @@ Hedgehog movement Movimento riccio + + Toggle automatic camera / refocus on active hedgehog: + Togli camera automatica / riposiziona sul riccio attivo: + + + Demo replay: + Vizualizza demo: + binds (keys) @@ -3330,123 +3281,179 @@ server Not room master - Non proprietario della stanza + Non proprietario della stanza Corrupted hedgehogs info - Informazioni ricci corrotte + Informazioni ricci corrotte too many teams - troppe squadre + troppe squadre too many hedgehogs - troppi ricci + troppi ricci There's already a team with same name in the list - C'è già una quadra collo stesso nome in lista + C'è già una quadra con lo stesso nome nella lista round in progress - turno in corso + turno in corso restricted - proibito + proibito REMOVE_TEAM: no such team - CANCELLA_SQUADRA: squadra non presente + CANCELLA_SQUADRA: squadra non presente Not team owner! - Non proprietario della squadra! + Non proprietario della squadra! Less than two clans! - Meno di due clan! + Meno di due clan! Room with such name already exists - Esiste già una stanza con questo nome + Esiste già una stanza con questo nome Nickname already chosen - Nome già scelto + Nickname già in uso Illegal nickname - Nome non valido + Nickname non valido Protocol already known - Protocollo già conosciuto + Protocollo già conosciuto Bad number - Numero non valido + Numero non valido Nickname is already in use - Nome già in uso + Nickname già in uso Authentication failed - Autenticazione fallita + Autenticazione fallita 60 seconds cooldown after kick - 60 secondi di raffreddamento prima dell'espulsione + 60 secondi di raffreddamento prima dell'espulsione kicked - espulso + espulso Ping timeout - Scadenza ping + Scadenza ping bye - ciao + ciao Illegal room name - Nome stanza non valido + Nome stanza non valido No such room - Stanza non esistente + Stanza non esistente Joining restricted - Ingresso riservato + Ingresso riservato Registered users only - Solo utenti registrati + Solo utenti registrati You are banned in this room - Sei stato espulso dalla stanza + Sei stato espulso dalla stanza Empty config entry - Configurazione vuota + Configurazione vuota Restricted - + Riservato No checker rights - + Nessun diritto di modifica Room version incompatible to your hedgewars version - + Stanza non compatibile con la tua versione di hedgewars + + + You already have voted + Hai già votato + + + Voting closed + Votazioni chiuse + + + New voting started + Nuova votazione avviata + + + Voting expired + Votazione scaduta + + + kick + espelli + + + map + mappa + + + pause + pausa + + + Reconnected too fast + Riconnessione troppo veloce + + + Warning! Chat flood protection activated + Attenzione! Protezione eccessivo numero messaggi attivata + + + Excess flood + Eccessivo numero messaggi + + + Game messages flood detected - 1 + Rilevato numero messaggi di gioco eccessivo - 1 + + + Game messages flood detected - 2 + Rilevato numero messaggi di gioco eccessivo - 2 + + + Warning! Joins flood protection activated + Attenzione! Protezione congiunta eccessivo numero messaggi attivata + + + There's no voting going on + Non ci sono votazioni in questo momento diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/hedgewars_ja.ts --- a/share/hedgewars/Data/Locale/hedgewars_ja.ts Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/hedgewars_ja.ts Tue Nov 10 20:43:13 2015 +0100 @@ -23,7 +23,11 @@ copy of - 模写 + 模写 + + + copy of %1 + @@ -205,6 +209,56 @@ Please check your installation! + + Usage + command-line + + + + OPTION + command-line + + + + CONNECTSTRING + command-line + + + + Options + command-line + + + + Display this help + command-line + + + + Custom path for configuration data and user data + command-line + + + + Custom path to the game data folder + command-line + + + + Hedgewars can use a %1 (e.g. "%2") to connect on start. + command-line + + + + Malformed option argument: %1 + command-line + + + + Unknown option argument: %1 + command-line + + HWAskQuitDialog @@ -394,6 +448,17 @@ Cannot open demofile %1 デモファイル%1を開くことが出来なかった + + A Fatal ERROR occured! - The game engine had to stop. + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%1' button in the main menu! + +Last two engine messages: +%2 + + HWMapContainer @@ -521,6 +586,14 @@ Theme: %1 + + Random perlin + + + + Style: + + HWNetServersModel @@ -587,6 +660,10 @@ The server is too old. Disconnecting now. + + Server authentication error + + HWPasswordDialog @@ -767,6 +844,10 @@ This page requires an internet connection. + + Open packages directory + + PageDrawMap @@ -818,6 +899,10 @@ Ellipse + + Optimize + + PageEditTeam @@ -876,9 +961,11 @@ Ranking - + The best shot award was won by <b>%1</b> with <b>%2</b> pts. - + + + The best killer is <b>%1</b> with <b>%2</b> kills in a turn. @@ -2057,6 +2144,10 @@ World Edge + + Script parameter + + QLineEdit @@ -2500,6 +2591,10 @@ Script + + Random Perlin + + SeedPrompt @@ -2544,7 +2639,11 @@ copy of - 模写 + 模写 + + + copy of %1 + @@ -2558,6 +2657,15 @@ Error code: %2 + + The game engine died unexpectedly! +(exit code %1) + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%2' button in the main menu! + + TeamSelWidget @@ -2617,7 +2725,7 @@ find hedgehog - 針鼠を見つける + 針鼠を見つける ammo menu @@ -2751,6 +2859,14 @@ hedgehog info + + autocam / find hedgehog + + + + speed up replay + + binds (categories) @@ -2798,10 +2914,6 @@ - Move the camera to the active hog: - - - Move the cursor or camera without using the mouse: @@ -2841,6 +2953,14 @@ Hedgehog movement + + Toggle automatic camera / refocus on active hedgehog: + + + + Demo replay: + + binds (keys) @@ -3283,5 +3403,61 @@ Empty config entry + + You already have voted + + + + Voting closed + + + + New voting started + + + + Voting expired + + + + kick + + + + map + + + + pause + ポーズ + + + Reconnected too fast + + + + Warning! Chat flood protection activated + + + + Excess flood + + + + Game messages flood detected - 1 + + + + Game messages flood detected - 2 + + + + Warning! Joins flood protection activated + + + + There's no voting going on + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/hedgewars_ko.ts --- a/share/hedgewars/Data/Locale/hedgewars_ko.ts Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/hedgewars_ko.ts Tue Nov 10 20:43:13 2015 +0100 @@ -22,7 +22,7 @@ - copy of + copy of %1 @@ -205,6 +205,56 @@ Please check your installation! + + Usage + command-line + + + + OPTION + command-line + + + + CONNECTSTRING + command-line + + + + Options + command-line + + + + Display this help + command-line + + + + Custom path for configuration data and user data + command-line + + + + Custom path to the game data folder + command-line + + + + Hedgewars can use a %1 (e.g. "%2") to connect on start. + command-line + + + + Malformed option argument: %1 + command-line + + + + Unknown option argument: %1 + command-line + + HWAskQuitDialog @@ -394,6 +444,17 @@ Cannot open demofile %1 + + A Fatal ERROR occured! - The game engine had to stop. + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%1' button in the main menu! + +Last two engine messages: +%2 + + HWMapContainer @@ -521,6 +582,14 @@ Theme: %1 + + Random perlin + + + + Style: + + HWNetServersModel @@ -583,6 +652,10 @@ The server is too old. Disconnecting now. + + Server authentication error + + HWPasswordDialog @@ -756,6 +829,10 @@ This page requires an internet connection. + + Open packages directory + + PageDrawMap @@ -807,6 +884,10 @@ Ellipse + + Optimize + + PageEditTeam @@ -865,9 +946,11 @@ Ranking - + The best shot award was won by <b>%1</b> with <b>%2</b> pts. - + + + The best killer is <b>%1</b> with <b>%2</b> kills in a turn. @@ -2022,6 +2105,10 @@ World Edge + + Script parameter + + QLineEdit @@ -2457,6 +2544,10 @@ Script + + Random Perlin + + SeedPrompt @@ -2500,7 +2591,7 @@ - copy of + copy of %1 @@ -2515,6 +2606,15 @@ Error code: %2 + + The game engine died unexpectedly! +(exit code %1) + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%2' button in the main menu! + + TeamSelWidget @@ -2573,10 +2673,6 @@ - find hedgehog - - - ammo menu @@ -2708,6 +2804,14 @@ hedgehog info + + autocam / find hedgehog + + + + speed up replay + + binds (categories) @@ -2755,10 +2859,6 @@ - Move the camera to the active hog: - - - Move the cursor or camera without using the mouse: @@ -2798,6 +2898,14 @@ Hedgehog movement + + Toggle automatic camera / refocus on active hedgehog: + + + + Demo replay: + + binds (keys) @@ -3240,5 +3348,61 @@ Empty config entry + + You already have voted + + + + Voting closed + + + + New voting started + + + + Voting expired + + + + kick + + + + map + + + + pause + + + + Reconnected too fast + + + + Warning! Chat flood protection activated + + + + Excess flood + + + + Game messages flood detected - 1 + + + + Game messages flood detected - 2 + + + + Warning! Joins flood protection activated + + + + There's no voting going on + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/hedgewars_lt.ts --- a/share/hedgewars/Data/Locale/hedgewars_lt.ts Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/hedgewars_lt.ts Tue Nov 10 20:43:13 2015 +0100 @@ -4,7 +4,7 @@ About - + Unknown Compiler @@ -20,76 +20,76 @@ AmmoSchemeModel - + new - - copy of + + copy of %1 BanDialog - + permanent - - - IP - - - - - Nick - - - - - IP/Nick - - - - Reason + + IP + Nick + + + + + IP/Nick + + + + + Reason + + + + Duration - + Ok - + Cancel - + you know why - + Warning - + Please, specify %1 - + nickname @@ -97,7 +97,7 @@ DataManager - + Use Default @@ -196,8 +196,8 @@ HWApplication - - + + %1 minutes @@ -206,7 +206,7 @@ - + %1 hour @@ -215,18 +215,18 @@ - - - - %1 hours - - - - - - - + + + %1 hours + + + + + + + + %1 day @@ -235,9 +235,9 @@ - - - + + + %1 days @@ -246,7 +246,7 @@ - + Scheme '%1' not supported @@ -256,7 +256,67 @@ - + + Usage + command-line + + + + + OPTION + command-line + + + + + CONNECTSTRING + command-line + + + + + Options + command-line + + + + + Display this help + command-line + + + + + Custom path for configuration data and user data + command-line + + + + + Custom path to the game data folder + command-line + + + + + Hedgewars can use a %1 (e.g. "%2") to connect on start. + command-line + + + + + Malformed option argument: %1 + command-line + + + + + Unknown option argument: %1 + command-line + + + + Failed to open data directory: %1 @@ -275,67 +335,67 @@ HWChatWidget - + %1 has joined - + %1 has left - + %1 has left (%2) - + %1 has been removed from your ignore list - + %1 has been added to your ignore list - + %1 has been removed from your friends list - + %1 has been added to your friends list - + Stylesheet imported from %1 - + Enter %1 if you want to use the current StyleSheet in future, enter %2 to reset! - + Couldn't read %1 - + StyleSheet discarded - + StyleSheet saved to %1 - + Failed to save StyleSheet to %1 @@ -455,34 +515,34 @@ - + Cannot save record to file %1 - - Hedgewars Demo File - File Types - - - + Hedgewars Demo File + File Types + + + + Hedgewars Save File File Types - + Demo name - + Demo name: - + This page requires an internet connection. @@ -490,13 +550,25 @@ HWGame - - + + A Fatal ERROR occured! - The game engine had to stop. + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%1' button in the main menu! + +Last two engine messages: +%2 + + + + + en.txt lt.txt - + Cannot open demofile %1 @@ -504,158 +576,168 @@ HWMapContainer - + Map type: - - Image map - - - - Mission map + Image map - Hand-drawn + Mission map - Randomly generated + Hand-drawn + Randomly generated + + + + Random maze - + + Random perlin + + + + Random - + Map preview: - + Load map drawing - + Edit map drawing - - All - - - - - Small - - - - Medium + All - Large + Small - Cavern + Medium + Large + + + + + Cavern + + + + Wacky - - Large tunnels - - - - - Small islands - - - - Medium islands + Large tunnels + Small islands + + + + + Medium islands + + + + Large islands - + Map size: - + Maze style: - + + Style: + + + + Mission: - + Map: - - + + Theme: %1 - + Load drawn map - + Drawn Maps - + All files - + Small tunnels - + Medium tunnels - + Seed @@ -681,53 +763,58 @@ HWNewNet - + User quit - - Remote host has closed connection - - - - The host was not found. Please check the host name and port settings. + Remote host has closed connection + The host was not found. Please check the host name and port settings. + + + + Connection refused - + The server is too old. Disconnecting now. - + + Server authentication error + + + + Room destroyed - + You got kicked - - + + %1 *** %2 has joined the room - + %1 *** %2 has left - + %1 *** %2 has left (%3) @@ -841,7 +928,7 @@ MapModel - + No description available. @@ -935,12 +1022,17 @@ PageDataDownload - + + Open packages directory + + + + Loading, please wait. - + This page requires an internet connection. @@ -979,33 +1071,38 @@ - Load + Optimize + Load + + + + Save - + Load drawn map - - + + Drawn Maps - - + + All files - + Save drawn map @@ -1091,13 +1188,17 @@ Save - - + + The best shot award was won by <b>%1</b> with <b>%2</b> pts. - + + + + + - + The best killer is <b>%1</b> with <b>%2</b> kills in a turn. @@ -1106,7 +1207,7 @@ - + A total of <b>%1</b> hedgehog(s) were killed during this round. @@ -1115,7 +1216,7 @@ - + (%1 kill) @@ -1124,7 +1225,7 @@ - + (%1 %2) @@ -1133,7 +1234,7 @@ - + <b>%1</b> thought it's good to shoot his own hedgehogs with <b>%2</b> pts. @@ -1142,7 +1243,7 @@ - + <b>%1</b> killed <b>%2</b> of his own hedgehogs. @@ -1151,7 +1252,7 @@ - + <b>%1</b> was scared and skipped turn <b>%2</b> times. @@ -1179,72 +1280,72 @@ PageMain - + Play a game on a single computer - + Play a game across a network - + Play local network game - + Play a game across a local area network - + Play official network game - + Play a game on an official server - + Read about who is behind the Hedgewars Project - - Feedback - - - + Feedback + + + + Leave a feedback here reporting issues, suggesting features or just saying how you like Hedgewars - - Downloadable Content - - - + Downloadable Content + + + + Access the user created content downloadable from our website - + Exit game - + Manage videos recorded from game - + Edit game preferences @@ -1528,37 +1629,37 @@ PageRoomsList - + Search for a room: - + Create room - + Join room - + Room state - + Admin features - + Open server administration page - + %1 players online @@ -1705,37 +1806,37 @@ - + None (Default) - - Wrap (World wraps) - - - - Bounce (Edges reflect) + Wrap (World wraps) + Bounce (Edges reflect) + + + + Sea (Edges connect to sea) - + Copy - + New - + Delete @@ -1822,17 +1923,17 @@ PageVideos - + Name - + Size - + %1 bytes @@ -1841,27 +1942,27 @@ - + (in progress...) - - Date: %1 - - - + Date: %1 + + + + Size: %1 - + encoding - + uploading @@ -1869,44 +1970,44 @@ QAction - + Info - + Kick - + Ban - + Follow - - + + Ignore - - + + Add friend - + Unignore - + Remove friend @@ -1926,12 +2027,12 @@ - + Show games in lobby - + Show games in-progress @@ -2203,17 +2304,17 @@ - + Playing teams - + Videos - + Description @@ -2221,12 +2322,12 @@ QLabel - + Revision - + This program is distributed under the %1 @@ -2281,12 +2382,13 @@ - + This development build is 'work in progress' and may not be compatible with other versions of the game, while some features might be broken or incomplete! - + + Tip: %1 @@ -2441,7 +2543,12 @@ - + + Script parameter + + + + Scheme Name: @@ -2574,7 +2681,7 @@ - + Cannot delete default scheme '%1'! @@ -2599,19 +2706,19 @@ - + Not all players are ready - + Are you sure you want to start this game? Not all players are ready. - + Hedgewars - Error @@ -2637,28 +2744,28 @@ - + Hedgewars - Success - + All file associations have been set - + File association failed. - + Error - + Cannot use the ammo '%1'! @@ -2726,55 +2833,55 @@ - + Room Name - Error - + Please select room from the list - + Room Name - Are you sure? - + The game you are trying to join has started. Do you still want to join the room? - + Schemes - Warning - + Schemes - Are you sure? - + Do you really want to delete the game scheme '%1'? - - - - Videos - Are you sure? - - - + + + Videos - Are you sure? + + + + Do you really want to delete the video '%1'? - + Do you really want to remove %1 file(s)? @@ -2783,25 +2890,25 @@ - + Do you really want to cancel uploading %1? - - - + + + File error - + Cannot open '%1' for writing - - + + Cannot open '%1' for reading @@ -2832,12 +2939,12 @@ - + Hedgewars - Warning - + Hedgewars - Information @@ -2845,8 +2952,8 @@ QObject - - + + No description available @@ -2865,7 +2972,7 @@ - + Cancel @@ -2943,8 +3050,8 @@ - - + + Delete @@ -2969,44 +3076,44 @@ - + Open videos directory - + Open the video directory in your system - + Play - + Play this video - + Delete this video - - - + + + Upload to YouTube - + Upload this video to your Youtube account - + Cancel uploading @@ -3093,6 +3200,11 @@ + Random Perlin + + + + Hand-drawn @@ -3151,28 +3263,38 @@ - copy of + copy of %1 TCPBase - + Unable to start server at %1. - + Unable to run engine at %1 Error code: %2 + + + The game engine died unexpectedly! +(exit code %1) + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%2' button in the main menu! + + TeamSelWidget - + At least two teams are required to play! @@ -3333,7 +3455,7 @@ - find hedgehog + autocam / find hedgehog @@ -3403,11 +3525,16 @@ + speed up replay + + + + hedgehog info - + record @@ -3474,7 +3601,7 @@ - Move the camera to the active hog: + Toggle automatic camera / refocus on active hedgehog: @@ -3514,11 +3641,16 @@ + Demo replay: + + + + Toggle labels above hedgehogs: - + Record video: @@ -3526,44 +3658,44 @@ binds (keys) - + Axis - - + + (Up) - - + + (Down) - + Hat - + (Left) - + (Right) - + Button - + Keyboard @@ -3926,152 +4058,222 @@ server - + Restricted - - Not room master - - - - - Corrupted hedgehogs info - - - - - too many teams - - - - - too many hedgehogs - - - - - There's already a team with same name in the list - - - - - round in progress - - - - - restricted - - - - - REMOVE_TEAM: no such team - - - - - Not team owner! - - - - Less than two clans! + Not room master - Illegal room name + Corrupted hedgehogs info - Room with such name already exists + too many teams - Nickname already chosen + too many hedgehogs - Illegal nickname + There's already a team with same name in the list - Protocol already known + round in progress - Bad number + restricted - Nickname is already in use + REMOVE_TEAM: no such team - No checker rights + Not team owner! + + + + + Less than two clans! + + + + + You already have voted + + + + + Voting closed + + + + + New voting started + + + + + Voting expired + + + + + kick + + + + + map + + + + + pause - Authentication failed + Illegal room name - 60 seconds cooldown after kick + Room with such name already exists - kicked + Nickname already chosen - Ping timeout + Illegal nickname - bye + Protocol already known - No such room + Bad number - Room version incompatible to your hedgewars version + Nickname is already in use - Joining restricted + No checker rights - Registered users only + Authentication failed - You are banned in this room + 60 seconds cooldown after kick + kicked + + + + + Reconnected too fast + + + + + Ping timeout + + + + + bye + + + + + No such room + + + + + Room version incompatible to your hedgewars version + + + + + Joining restricted + + + + + Registered users only + + + + + You are banned in this room + + + + + Warning! Chat flood protection activated + + + + + Excess flood + + + + + Game messages flood detected - 1 + + + + + Game messages flood detected - 2 + + + + + Warning! Joins flood protection activated + + + + + There's no voting going on + + + + Empty config entry diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/hedgewars_ms.ts --- a/share/hedgewars/Data/Locale/hedgewars_ms.ts Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/hedgewars_ms.ts Tue Nov 10 20:43:13 2015 +0100 @@ -4,7 +4,7 @@ About - + Unknown Compiler @@ -20,76 +20,76 @@ AmmoSchemeModel - + new - - copy of + + copy of %1 BanDialog - + permanent - - - IP - - - - - Nick - - - - - IP/Nick - - - - Reason + + IP + Nick + + + + + IP/Nick + + + + + Reason + + + + Duration - + Ok - + Cancel - + you know why - + Warning - + Please, specify %1 - + nickname @@ -97,7 +97,7 @@ DataManager - + Use Default @@ -194,47 +194,47 @@ HWApplication - - + + %1 minutes - + %1 hour - - - - %1 hours - - - - - + + + %1 hours + + + + + + %1 day - - - + + + %1 days - + Scheme '%1' not supported @@ -244,7 +244,67 @@ - + + Usage + command-line + + + + + OPTION + command-line + + + + + CONNECTSTRING + command-line + + + + + Options + command-line + + + + + Display this help + command-line + + + + + Custom path for configuration data and user data + command-line + + + + + Custom path to the game data folder + command-line + + + + + Hedgewars can use a %1 (e.g. "%2") to connect on start. + command-line + + + + + Malformed option argument: %1 + command-line + + + + + Unknown option argument: %1 + command-line + + + + Failed to open data directory: %1 @@ -263,67 +323,67 @@ HWChatWidget - + %1 has joined - + %1 has left - + %1 has left (%2) - + %1 has been removed from your ignore list - + %1 has been added to your ignore list - + %1 has been removed from your friends list - + %1 has been added to your friends list - + Stylesheet imported from %1 - + Enter %1 if you want to use the current StyleSheet in future, enter %2 to reset! - + Couldn't read %1 - + StyleSheet discarded - + StyleSheet saved to %1 - + Failed to save StyleSheet to %1 @@ -443,34 +503,34 @@ - + Cannot save record to file %1 - - Hedgewars Demo File - File Types - - - + Hedgewars Demo File + File Types + + + + Hedgewars Save File File Types - + Demo name - + Demo name: - + This page requires an internet connection. @@ -478,13 +538,25 @@ HWGame - - + + A Fatal ERROR occured! - The game engine had to stop. + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%1' button in the main menu! + +Last two engine messages: +%2 + + + + + en.txt ms.txt - + Cannot open demofile %1 @@ -492,158 +564,168 @@ HWMapContainer - + Map type: - - Image map - - - - Mission map + Image map - Hand-drawn + Mission map - Randomly generated + Hand-drawn + Randomly generated + + + + Random maze - + + Random perlin + + + + Random - + Map preview: - + Load map drawing - + Edit map drawing - - All - - - - - Small - - - - Medium + All - Large + Small - Cavern + Medium + Large + + + + + Cavern + + + + Wacky - - Large tunnels - - - - - Small islands - - - - Medium islands + Large tunnels + Small islands + + + + + Medium islands + + + + Large islands - + Map size: - + Maze style: - + + Style: + + + + Mission: - + Map: - - + + Theme: %1 - + Load drawn map - + Drawn Maps - + All files - + Small tunnels - + Medium tunnels - + Seed @@ -674,53 +756,58 @@ - + User quit - - Remote host has closed connection - - - - The host was not found. Please check the host name and port settings. + Remote host has closed connection + The host was not found. Please check the host name and port settings. + + + + Connection refused - + The server is too old. Disconnecting now. - + You got kicked - + + Server authentication error + + + + %1 *** %2 has left - + %1 *** %2 has left (%3) - - + + %1 *** %2 has joined the room - + Room destroyed @@ -829,7 +916,7 @@ MapModel - + No description available. @@ -923,12 +1010,17 @@ PageDataDownload - + + Open packages directory + + + + Loading, please wait. - + This page requires an internet connection. @@ -967,33 +1059,38 @@ - Load + Optimize + Load + + + + Save - + Load drawn map - - + + Drawn Maps - - + + All files - + Save drawn map @@ -1079,55 +1176,57 @@ Save - - + + The best shot award was won by <b>%1</b> with <b>%2</b> pts. - + + + - + The best killer is <b>%1</b> with <b>%2</b> kills in a turn. - + A total of <b>%1</b> hedgehog(s) were killed during this round. - + (%1 kill) - + (%1 %2) - + <b>%1</b> thought it's good to shoot his own hedgehogs with <b>%2</b> pts. - + <b>%1</b> killed <b>%2</b> of his own hedgehogs. - + <b>%1</b> was scared and skipped turn <b>%2</b> times. @@ -1153,72 +1252,72 @@ PageMain - + Play a game on a single computer - + Play a game across a network - + Play local network game - + Play a game across a local area network - + Play official network game - + Play a game on an official server - + Read about who is behind the Hedgewars Project - - Feedback - - - + Feedback + + + + Leave a feedback here reporting issues, suggesting features or just saying how you like Hedgewars - - Downloadable Content - - - + Downloadable Content + + + + Access the user created content downloadable from our website - + Exit game - + Manage videos recorded from game - + Edit game preferences @@ -1502,37 +1601,37 @@ PageRoomsList - + Search for a room: - + Create room - + Join room - + Room state - + Admin features - + Open server administration page - + %1 players online @@ -1677,37 +1776,37 @@ - + None (Default) - - Wrap (World wraps) - - - - Bounce (Edges reflect) + Wrap (World wraps) + Bounce (Edges reflect) + + + + Sea (Edges connect to sea) - + Copy - + New - + Delete @@ -1794,44 +1893,44 @@ PageVideos - + Name - + Size - + %1 bytes - + (in progress...) - - Date: %1 - - - + Date: %1 + + + + Size: %1 - + encoding - + uploading @@ -1854,54 +1953,54 @@ - + Info - + Kick - + Ban - + Follow - - + + Ignore - - + + Add friend - + Unignore - + Remove friend - + Show games in lobby - + Show games in-progress @@ -2173,17 +2272,17 @@ - + Videos - + Description - + Playing teams @@ -2288,12 +2387,13 @@ - + This development build is 'work in progress' and may not be compatible with other versions of the game, while some features might be broken or incomplete! - + + Tip: %1 @@ -2453,7 +2553,12 @@ - + + Script parameter + + + + Scheme Name: @@ -2483,12 +2588,12 @@ - + Revision - + This program is distributed under the %1 @@ -2544,7 +2649,7 @@ - + Cannot delete default scheme '%1'! @@ -2569,19 +2674,19 @@ - + Not all players are ready - + Are you sure you want to start this game? Not all players are ready. - + Hedgewars - Error @@ -2607,18 +2712,18 @@ - + Hedgewars - Success - + All file associations have been set - + File association failed. @@ -2686,90 +2791,90 @@ - + Room Name - Error - + Please select room from the list - + Room Name - Are you sure? - + The game you are trying to join has started. Do you still want to join the room? - + Schemes - Warning - + Schemes - Are you sure? - + Do you really want to delete the game scheme '%1'? - - - - Videos - Are you sure? - - - + + + Videos - Are you sure? + + + + Do you really want to delete the video '%1'? - + Do you really want to remove %1 file(s)? - + Do you really want to cancel uploading %1? - - - + + + File error - + Cannot open '%1' for writing - - + + Cannot open '%1' for reading - + Error - + Cannot use the ammo '%1'! @@ -2800,12 +2905,12 @@ - + Hedgewars - Warning - + Hedgewars - Information @@ -2813,8 +2918,8 @@ QObject - - + + No description available @@ -2838,7 +2943,7 @@ - + Cancel @@ -2916,8 +3021,8 @@ - - + + Delete @@ -2937,44 +3042,44 @@ - + Open videos directory - + Open the video directory in your system - + Play - + Play this video - + Delete this video - - - + + + Upload to YouTube - + Upload this video to your Youtube account - + Cancel uploading @@ -3061,6 +3166,11 @@ + Random Perlin + + + + Hand-drawn @@ -3119,28 +3229,38 @@ - copy of + copy of %1 TCPBase - + Unable to start server at %1. - + Unable to run engine at %1 Error code: %2 + + + The game engine died unexpectedly! +(exit code %1) + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%2' button in the main menu! + + TeamSelWidget - + At least two teams are required to play! @@ -3301,7 +3421,7 @@ - find hedgehog + autocam / find hedgehog @@ -3371,11 +3491,16 @@ + speed up replay + + + + hedgehog info - + record @@ -3442,7 +3567,7 @@ - Move the camera to the active hog: + Toggle automatic camera / refocus on active hedgehog: @@ -3482,11 +3607,16 @@ + Demo replay: + + + + Toggle labels above hedgehogs: - + Record video: @@ -3849,44 +3979,44 @@ - + Keyboard - + Axis - - + + (Up) - - + + (Down) - + Hat - + (Left) - + (Right) - + Button @@ -3894,152 +4024,222 @@ server - + Restricted - - Not room master - - - - - Corrupted hedgehogs info - - - - - too many teams - - - - - too many hedgehogs - - - - - There's already a team with same name in the list - - - - - round in progress - - - - - restricted - - - - - REMOVE_TEAM: no such team - - - - - Not team owner! - - - - Less than two clans! + Not room master - Illegal room name + Corrupted hedgehogs info - Room with such name already exists + too many teams - Nickname already chosen + too many hedgehogs - Illegal nickname + There's already a team with same name in the list - Protocol already known + round in progress - Bad number + restricted - Nickname is already in use + REMOVE_TEAM: no such team - No checker rights + Not team owner! + + + + + Less than two clans! + + + + + You already have voted + + + + + Voting closed + + + + + New voting started + + + + + Voting expired + + + + + kick + + + + + map + + + + + pause - Authentication failed + Illegal room name - 60 seconds cooldown after kick + Room with such name already exists - kicked + Nickname already chosen - Ping timeout + Illegal nickname - bye + Protocol already known - No such room + Bad number - Room version incompatible to your hedgewars version + Nickname is already in use - Joining restricted + No checker rights - Registered users only + Authentication failed - You are banned in this room + 60 seconds cooldown after kick + kicked + + + + + Reconnected too fast + + + + + Ping timeout + + + + + bye + + + + + No such room + + + + + Room version incompatible to your hedgewars version + + + + + Joining restricted + + + + + Registered users only + + + + + You are banned in this room + + + + + Warning! Chat flood protection activated + + + + + Excess flood + + + + + Game messages flood detected - 1 + + + + + Game messages flood detected - 2 + + + + + Warning! Joins flood protection activated + + + + + There's no voting going on + + + + Empty config entry diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/hedgewars_nl.ts --- a/share/hedgewars/Data/Locale/hedgewars_nl.ts Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/hedgewars_nl.ts Tue Nov 10 20:43:13 2015 +0100 @@ -22,7 +22,7 @@ - copy of + copy of %1 @@ -211,6 +211,56 @@ Please check your installation! + + Usage + command-line + + + + OPTION + command-line + + + + CONNECTSTRING + command-line + + + + Options + command-line + + + + Display this help + command-line + + + + Custom path for configuration data and user data + command-line + + + + Custom path to the game data folder + command-line + + + + Hedgewars can use a %1 (e.g. "%2") to connect on start. + command-line + + + + Malformed option argument: %1 + command-line + + + + Unknown option argument: %1 + command-line + + HWAskQuitDialog @@ -400,6 +450,17 @@ Cannot open demofile %1 + + A Fatal ERROR occured! - The game engine had to stop. + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%1' button in the main menu! + +Last two engine messages: +%2 + + HWMapContainer @@ -527,6 +588,14 @@ Theme: %1 + + Random perlin + + + + Style: + + HWNetServersModel @@ -589,6 +658,10 @@ The server is too old. Disconnecting now. + + Server authentication error + + HWPasswordDialog @@ -762,6 +835,10 @@ This page requires an internet connection. + + Open packages directory + + PageDrawMap @@ -813,6 +890,10 @@ Ellipse + + Optimize + + PageEditTeam @@ -871,9 +952,12 @@ Ranking - + The best shot award was won by <b>%1</b> with <b>%2</b> pts. - + + + + The best killer is <b>%1</b> with <b>%2</b> kills in a turn. @@ -2037,6 +2121,10 @@ World Edge + + Script parameter + + QLineEdit @@ -2473,6 +2561,10 @@ Script + + Random Perlin + + SeedPrompt @@ -2516,7 +2608,7 @@ - copy of + copy of %1 @@ -2531,6 +2623,15 @@ Error code: %2 + + The game engine died unexpectedly! +(exit code %1) + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%2' button in the main menu! + + TeamSelWidget @@ -2589,10 +2690,6 @@ - find hedgehog - - - ammo menu @@ -2724,6 +2821,14 @@ hedgehog info + + autocam / find hedgehog + + + + speed up replay + + binds (categories) @@ -2771,10 +2876,6 @@ - Move the camera to the active hog: - - - Move the cursor or camera without using the mouse: @@ -2814,6 +2915,14 @@ Hedgehog movement + + Toggle automatic camera / refocus on active hedgehog: + + + + Demo replay: + + binds (keys) @@ -3256,5 +3365,61 @@ Empty config entry + + You already have voted + + + + Voting closed + + + + New voting started + + + + Voting expired + + + + kick + + + + map + + + + pause + + + + Reconnected too fast + + + + Warning! Chat flood protection activated + + + + Excess flood + + + + Game messages flood detected - 1 + + + + Game messages flood detected - 2 + + + + Warning! Joins flood protection activated + + + + There's no voting going on + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/hedgewars_pl.ts --- a/share/hedgewars/Data/Locale/hedgewars_pl.ts Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/hedgewars_pl.ts Tue Nov 10 20:43:13 2015 +0100 @@ -23,7 +23,11 @@ copy of - kopia + kopia + + + copy of %1 + @@ -224,6 +228,56 @@ Sprawdź poprawność instalacji! + + Usage + command-line + + + + OPTION + command-line + + + + CONNECTSTRING + command-line + + + + Options + command-line + + + + Display this help + command-line + + + + Custom path for configuration data and user data + command-line + + + + Custom path to the game data folder + command-line + + + + Hedgewars can use a %1 (e.g. "%2") to connect on start. + command-line + + + + Malformed option argument: %1 + command-line + + + + Unknown option argument: %1 + command-line + + HWAskQuitDialog @@ -423,6 +477,17 @@ Cannot open demofile %1 Nie można wczytać dema z pliku %1 + + A Fatal ERROR occured! - The game engine had to stop. + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%1' button in the main menu! + +Last two engine messages: +%2 + + HWMapContainer @@ -550,6 +615,14 @@ Theme: %1 Motyw: %1 + + Random perlin + + + + Style: + + HWNetServersModel @@ -616,6 +689,10 @@ The server is too old. Disconnecting now. Stara wersja serwera. Nastąpi rozłączenie. + + Server authentication error + + HWPasswordDialog @@ -812,6 +889,10 @@ This page requires an internet connection. Ta strona wymaga połączenia z internetem. + + Open packages directory + + PageDrawMap @@ -863,6 +944,10 @@ Ellipse + + Optimize + + PageEditTeam @@ -921,9 +1006,13 @@ Ranking Ranking - + The best shot award was won by <b>%1</b> with <b>%2</b> pts. - Największe obrażenia (<b>%2</b> pkt.) zadał <b>%1</b>. + + Największe obrażenia (<b>%2</b> pkt.) zadał <b>%1</b>. + + + The best killer is <b>%1</b> with <b>%2</b> kills in a turn. @@ -2172,6 +2261,10 @@ World Edge + + Script parameter + + QLineEdit @@ -2649,6 +2742,10 @@ Script + + Random Perlin + + SeedPrompt @@ -2693,7 +2790,11 @@ copy of - kopia + kopia + + + copy of %1 + @@ -2708,6 +2809,15 @@ Nie można uruchomić silnika na %1 Kod błędu: %2 + + The game engine died unexpectedly! +(exit code %1) + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%2' button in the main menu! + + TeamSelWidget @@ -2770,7 +2880,7 @@ find hedgehog - znajdź jeża + znajdź jeża ammo menu @@ -2908,6 +3018,14 @@ hedgehog info informacje o jeżu + + autocam / find hedgehog + + + + speed up replay + + binds (categories) @@ -2956,7 +3074,7 @@ Move the camera to the active hog: - Ustaw kamerę na aktywnym jeżu: + Ustaw kamerę na aktywnym jeżu: Move the cursor or camera without using the mouse: @@ -2998,6 +3116,14 @@ Hedgehog movement Poruszanie się jeżem + + Toggle automatic camera / refocus on active hedgehog: + + + + Demo replay: + + binds (keys) @@ -3440,5 +3566,61 @@ Empty config entry + + You already have voted + + + + Voting closed + + + + New voting started + + + + Voting expired + + + + kick + + + + map + + + + pause + pauza + + + Reconnected too fast + + + + Warning! Chat flood protection activated + + + + Excess flood + + + + Game messages flood detected - 1 + + + + Game messages flood detected - 2 + + + + Warning! Joins flood protection activated + + + + There's no voting going on + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/hedgewars_pt_BR.ts --- a/share/hedgewars/Data/Locale/hedgewars_pt_BR.ts Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/hedgewars_pt_BR.ts Tue Nov 10 20:43:13 2015 +0100 @@ -23,7 +23,11 @@ copy of - cópia de + cópia de + + + copy of %1 + @@ -214,6 +218,56 @@ Por favor, confira sua instalação! + + Usage + command-line + + + + OPTION + command-line + + + + CONNECTSTRING + command-line + + + + Options + command-line + + + + Display this help + command-line + + + + Custom path for configuration data and user data + command-line + + + + Custom path to the game data folder + command-line + + + + Hedgewars can use a %1 (e.g. "%2") to connect on start. + command-line + + + + Malformed option argument: %1 + command-line + + + + Unknown option argument: %1 + command-line + + HWAskQuitDialog @@ -413,6 +467,17 @@ Cannot open demofile %1 Falha ao abrir o arquivo de demonstração %1 + + A Fatal ERROR occured! - The game engine had to stop. + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%1' button in the main menu! + +Last two engine messages: +%2 + + HWMapContainer @@ -541,6 +606,14 @@ Theme: %1 Tema: %1 + + Random perlin + + + + Style: + + HWNetServersModel @@ -607,6 +680,10 @@ The server is too old. Disconnecting now. O servidor está muito velho. Desconectando agora. + + Server authentication error + + HWPasswordDialog @@ -803,6 +880,10 @@ This page requires an internet connection. Esta página exige uma conexão à Internet. + + Open packages directory + + PageDrawMap @@ -854,6 +935,10 @@ Ellipse + + Optimize + + PageEditTeam @@ -912,9 +997,12 @@ Ranking Colocação - + The best shot award was won by <b>%1</b> with <b>%2</b> pts. - O prêmio de melhor atirador foi para <b>%1</b> com <b>%2</b> pts. + + O prêmio de melhor atirador foi para <b>%1</b> com <b>%2</b> pts. + + The best killer is <b>%1</b> with <b>%2</b> kills in a turn. @@ -2150,6 +2238,10 @@ World Edge + + Script parameter + + QLineEdit @@ -2600,6 +2692,10 @@ Script + + Random Perlin + + SeedPrompt @@ -2644,7 +2740,11 @@ copy of - cópia de + cópia de + + + copy of %1 + @@ -2659,6 +2759,15 @@ Não foi capaz de executar o motor em %1 Código de erro: %2 + + The game engine died unexpectedly! +(exit code %1) + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%2' button in the main menu! + + TeamSelWidget @@ -2721,7 +2830,7 @@ find hedgehog - encontrar ouriço + encontrar ouriço ammo menu @@ -2859,6 +2968,14 @@ hedgehog info informações do ouriço + + autocam / find hedgehog + + + + speed up replay + + binds (categories) @@ -2907,7 +3024,7 @@ Move the camera to the active hog: - Mover a câmera para o ouriço ativo: + Mover a câmera para o ouriço ativo: Move the cursor or camera without using the mouse: @@ -2949,6 +3066,14 @@ Hedgehog movement Movimento do ouriço + + Toggle automatic camera / refocus on active hedgehog: + + + + Demo replay: + + binds (keys) @@ -3393,5 +3518,61 @@ Empty config entry + + You already have voted + + + + Voting closed + + + + New voting started + + + + Voting expired + + + + kick + + + + map + + + + pause + pausa + + + Reconnected too fast + + + + Warning! Chat flood protection activated + + + + Excess flood + + + + Game messages flood detected - 1 + + + + Game messages flood detected - 2 + + + + Warning! Joins flood protection activated + + + + There's no voting going on + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/hedgewars_pt_PT.ts --- a/share/hedgewars/Data/Locale/hedgewars_pt_PT.ts Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/hedgewars_pt_PT.ts Tue Nov 10 20:43:13 2015 +0100 @@ -23,7 +23,11 @@ copy of - cópia de + cópia de + + + copy of %1 + @@ -218,6 +222,56 @@ Por favor verifica a tua instalação! + + Usage + command-line + + + + OPTION + command-line + + + + CONNECTSTRING + command-line + + + + Options + command-line + + + + Display this help + command-line + + + + Custom path for configuration data and user data + command-line + + + + Custom path to the game data folder + command-line + + + + Hedgewars can use a %1 (e.g. "%2") to connect on start. + command-line + + + + Malformed option argument: %1 + command-line + + + + Unknown option argument: %1 + command-line + + HWAskQuitDialog @@ -417,6 +471,17 @@ Cannot open demofile %1 Não foi possível abrir o ficheiro %1 + + A Fatal ERROR occured! - The game engine had to stop. + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%1' button in the main menu! + +Last two engine messages: +%2 + + HWMapContainer @@ -548,6 +613,14 @@ Theme: %1 Tema: %1 + + Random perlin + + + + Style: + + HWNetServersModel @@ -614,6 +687,10 @@ The server is too old. Disconnecting now. O servidor é demasiado antigo. Desconectado. + + Server authentication error + + HWPasswordDialog @@ -811,6 +888,10 @@ This page requires an internet connection. Esta página requer ligação à internet. + + Open packages directory + + PageDrawMap @@ -862,6 +943,10 @@ Ellipse + + Optimize + + PageEditTeam @@ -920,9 +1005,12 @@ Ranking Ranking - + The best shot award was won by <b>%1</b> with <b>%2</b> pts. - O título de melhor tiro foi para <b>%1</b> com <b>%2</b> pontos de dano. + + O título de melhor tiro foi para <b>%1</b> com <b>%2</b> pontos de dano. + + The best killer is <b>%1</b> with <b>%2</b> kills in a turn. @@ -2122,6 +2210,10 @@ World Edge + + Script parameter + + QLineEdit @@ -2604,6 +2696,10 @@ Script + + Random Perlin + + SeedPrompt @@ -2648,7 +2744,11 @@ copy of - copia de + copia de + + + copy of %1 + @@ -2663,6 +2763,15 @@ Não foi possível iniciar o motor de jogo em %1 Código de erro:: %2 + + The game engine died unexpectedly! +(exit code %1) + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%2' button in the main menu! + + TeamSelWidget @@ -2729,7 +2838,7 @@ find hedgehog - encontrar ouriço + encontrar ouriço ammo menu @@ -2863,6 +2972,14 @@ hedgehog info informação do ouriço + + autocam / find hedgehog + + + + speed up replay + + binds (categories) @@ -2911,7 +3028,7 @@ Move the camera to the active hog: - Mover a câmara para o ouriço correntemente activo: + Mover a câmara para o ouriço correntemente activo: Move the cursor or camera without using the mouse: @@ -2953,6 +3070,14 @@ Hedgehog movement Movimentar ouriço + + Toggle automatic camera / refocus on active hedgehog: + + + + Demo replay: + + binds (keys) @@ -3395,5 +3520,61 @@ Room version incompatible to your hedgewars version + + You already have voted + + + + Voting closed + + + + New voting started + + + + Voting expired + + + + kick + + + + map + + + + pause + pausa + + + Reconnected too fast + + + + Warning! Chat flood protection activated + + + + Excess flood + + + + Game messages flood detected - 1 + + + + Game messages flood detected - 2 + + + + Warning! Joins flood protection activated + + + + There's no voting going on + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/hedgewars_ro.ts --- a/share/hedgewars/Data/Locale/hedgewars_ro.ts Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/hedgewars_ro.ts Tue Nov 10 20:43:13 2015 +0100 @@ -22,7 +22,7 @@ new - copy of + copy of %1 @@ -217,6 +217,56 @@ Please check your installation! + + Usage + command-line + + + + OPTION + command-line + + + + CONNECTSTRING + command-line + + + + Options + command-line + + + + Display this help + command-line + + + + Custom path for configuration data and user data + command-line + + + + Custom path to the game data folder + command-line + + + + Hedgewars can use a %1 (e.g. "%2") to connect on start. + command-line + + + + Malformed option argument: %1 + command-line + + + + Unknown option argument: %1 + command-line + + HWAskQuitDialog @@ -406,6 +456,17 @@ Cannot open demofile %1 Cannot open demofile %1 + + A Fatal ERROR occured! - The game engine had to stop. + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%1' button in the main menu! + +Last two engine messages: +%2 + + HWMapContainer @@ -533,6 +594,14 @@ Theme: %1 + + Random perlin + + + + Style: + + HWNetServersModel @@ -599,6 +668,10 @@ The server is too old. Disconnecting now. + + Server authentication error + + HWPasswordDialog @@ -779,6 +852,10 @@ This page requires an internet connection. + + Open packages directory + + PageDrawMap @@ -830,6 +907,10 @@ Ellipse + + Optimize + + PageEditTeam @@ -888,9 +969,13 @@ Ranking Ranking - + The best shot award was won by <b>%1</b> with <b>%2</b> pts. - The best shot award was won by <b>%1</b> with <b>%2</b> pts. + + The best shot award was won by <b>%1</b> with <b>%2</b> pts. + + + The best killer is <b>%1</b> with <b>%2</b> kills in a turn. @@ -2087,6 +2172,10 @@ World Edge + + Script parameter + + QLineEdit @@ -2533,6 +2622,10 @@ Script + + Random Perlin + + SeedPrompt @@ -2576,7 +2669,7 @@ new - copy of + copy of %1 @@ -2591,6 +2684,15 @@ Error code: %2 + + The game engine died unexpectedly! +(exit code %1) + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%2' button in the main menu! + + TeamSelWidget @@ -2650,7 +2752,7 @@ find hedgehog - find hedgehog + find hedgehog ammo menu @@ -2784,6 +2886,14 @@ hedgehog info + + autocam / find hedgehog + + + + speed up replay + + binds (categories) @@ -2832,7 +2942,7 @@ Move the camera to the active hog: - Move the camera to the active hog: + Move the camera to the active hog: Move the cursor or camera without using the mouse: @@ -2874,6 +2984,14 @@ Hedgehog movement + + Toggle automatic camera / refocus on active hedgehog: + + + + Demo replay: + + binds (keys) @@ -3316,5 +3434,61 @@ Empty config entry + + You already have voted + + + + Voting closed + + + + New voting started + + + + Voting expired + + + + kick + + + + map + + + + pause + pause + + + Reconnected too fast + + + + Warning! Chat flood protection activated + + + + Excess flood + + + + Game messages flood detected - 1 + + + + Game messages flood detected - 2 + + + + Warning! Joins flood protection activated + + + + There's no voting going on + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/hedgewars_ru.ts --- a/share/hedgewars/Data/Locale/hedgewars_ru.ts Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/hedgewars_ru.ts Tue Nov 10 20:43:13 2015 +0100 @@ -23,7 +23,11 @@ copy of - копия + копия + + + copy of %1 + копия %1 @@ -161,7 +165,7 @@ GameUIConfig Guest - + Гость @@ -224,6 +228,56 @@ Пожалуйста, проверьте установку приложения! + + Usage + command-line + + + + OPTION + command-line + + + + CONNECTSTRING + command-line + + + + Options + command-line + + + + Display this help + command-line + + + + Custom path for configuration data and user data + command-line + + + + Custom path to the game data folder + command-line + + + + Hedgewars can use a %1 (e.g. "%2") to connect on start. + command-line + + + + Malformed option argument: %1 + command-line + + + + Unknown option argument: %1 + command-line + + HWAskQuitDialog @@ -339,7 +393,7 @@ Hedgewars - Nick registered - + Hedgewars - Имя пользователя зарегистрировано This nick is registered, and you haven't specified a password. @@ -347,39 +401,45 @@ If this nick isn't yours, please register your own nick at www.hedgewars.org Password: - + Указанное имя пользователя зарегистрирована, и вы не указали пароль + +Если это имя пользователя не принадлежит вам, пожалуйста, зарегистрируйте другое имя на www.hedgewars.org + +Пароль: Your nickname is not registered. To prevent someone else from using it, please register it at www.hedgewars.org - + Ваше имя пользователя не зарегистрировано. +Чтобы никто другой не воспользовался им, +зарегистрируйте его на www.hedgewars.org Your password wasn't saved either. - + Ваш пароль не был сохранён. Hedgewars - Empty nickname - + Hedgewars - Пустое имя пользователя Hedgewars - Wrong password - + Hedgewars - Неверный пароль You entered a wrong password. - + Вы ввели неверный пароль. Try Again - + Попробуйте снова Hedgewars - Connection error - + Hedgewars - Ошибка соединения You reconnected too fast. @@ -389,20 +449,21 @@ This page requires an internet connection. - + Для этой страницы нужно соединение с интернетом. Guest - + Гость Room password - + Пароль комнаты The room is protected with password. Please, enter the password: - + Эта комната защищена паролем. +Пожалуйста, введите пароль: @@ -415,6 +476,17 @@ Cannot open demofile %1 Не могу открыть демо %1 + + A Fatal ERROR occured! - The game engine had to stop. + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%1' button in the main menu! + +Last two engine messages: +%2 + + HWMapContainer @@ -488,11 +560,11 @@ Load map drawing - Загрузить рисованную карту + Загрузить Edit map drawing - Редактировать рисованную карту + Редактировать Small islands @@ -542,6 +614,14 @@ Theme: %1 Тема: %1 + + Random perlin + Случайная перлиновская + + + Style: + Стиль: + HWNetServersModel @@ -608,19 +688,26 @@ The server is too old. Disconnecting now. Слишком старый сервер. Отсоединяюсь. + + Server authentication error + Ошибка аутентификации сервера + HWPasswordDialog Login - + Имя пользователя To connect to the server, please log in. If you don't have an account on www.hedgewars.org, just enter your nickname. - + Для входа на сервер укажите имя пользователя. + +Если у вас нет учётной записи на www.hedgewars.org, +введите своё имя пользователя. Nickname: @@ -703,15 +790,15 @@ Duration: %1m %2s - + Длительность: %1мин %2сек Video: %1x%2 - + Видео: %1x%2 %1 fps - + %1 кадров/сек @@ -799,7 +886,11 @@ This page requires an internet connection. - + Для этой страницы нужно соединение с интернетом. + + + Open packages directory + Открыть папку с пакетами @@ -842,15 +933,19 @@ Polyline - + Ломаная Rectangle - + Прямоугольник Ellipse - + Эллипс + + + Optimize + Оптимизировать @@ -910,9 +1005,13 @@ Ranking Рейтинг - + The best shot award was won by <b>%1</b> with <b>%2</b> pts. - Приз за лучший выстрел получает <b>%1</b> с <b>%2</b> пунктами урона. + + Приз за лучший выстрел получает <b>%1</b> с <b>%2</b> пунктом урона. + Приз за лучший выстрел получает <b>%1</b> с <b>%2</b> пунктами урона. + Приз за лучший выстрел получает <b>%1</b> с <b>%2</b> пунктами урона. + The best killer is <b>%1</b> with <b>%2</b> kills in a turn. @@ -964,18 +1063,16 @@ Play again - + Играть заново Save - Сохранить + Сохранить (%1 %2) - - @@ -997,7 +1094,7 @@ PageMain Downloadable Content - + Скачиваемые дополнения Play a game on a single computer @@ -1013,11 +1110,11 @@ Leave a feedback here reporting issues, suggesting features or just saying how you like Hedgewars - + Оставьте отзыв, упомянув проблемы, предложив новые возможности или просто рассказав, что вам нравится Hedgewars Access the user created content downloadable from our website - + Доступ к скачиваемым с нашего сайта дополнениям, созданным пользователями Exit game @@ -1237,7 +1334,7 @@ Game audio - + Звук в игре Frontend audio @@ -1245,7 +1342,7 @@ Account - + Учётная запись Proxy settings @@ -1470,19 +1567,19 @@ None (Default) - + Отсутствует (по умолчанию) Wrap (World wraps) - + Замыкание Bounce (Edges reflect) - + Отражение Sea (Edges connect to sea) - + Море (края соединены с морем) @@ -1592,11 +1689,11 @@ Date: %1 - Дата: %1 {1?} + Дата: %1 Size: %1 - Размер: %1 {1?} + Размер: %1 @@ -1651,11 +1748,11 @@ Show games in lobby - + Показывать неначавшиеся игры Show games in-progress - Показать текущие игры + Показывать текущие игры @@ -1714,7 +1811,7 @@ In-game sound effects - + Внутриигровые звуковые эффекты Music @@ -1722,7 +1819,7 @@ In-game music - + Внутриигровая музыка Frontend sound effects @@ -1734,35 +1831,35 @@ Team - + Команда Enable team tags by default - + Включить ярлыки команд по умолчанию Hog - + Ёж Enable hedgehog tags by default - + Включить ярлыки ежей по умолчанию Health - + Здоровье Enable health tags by default - + Включить ярлыки уровня здоровья по умолчанию Translucent - + Прозрачность Enable translucent tags by default - + Включить прозрачность ярлыков по умолчанию @@ -2159,7 +2256,11 @@ World Edge - + Край мира + + + Script parameter + Параметр скрипта @@ -2326,8 +2427,6 @@ Do you really want to remove %1 file(s)? - - @@ -2413,7 +2512,7 @@ QObject No description available - Описание отсутствует + Описание отсутствует @@ -2500,7 +2599,7 @@ Restore default coding parameters - + Восстановить параметры кодирования Open the video directory in your system @@ -2508,19 +2607,19 @@ Play this video - + Играть видео Delete this video - + Удалить видео Upload this video to your Youtube account - + Отправить на YouTube Reset - + Сбросить Set the default server port for Hedgewars @@ -2555,7 +2654,7 @@ set password - + указать пароль @@ -2606,7 +2705,11 @@ Script - + Скрипт + + + Random Perlin + Случайная перлиновская @@ -2652,7 +2755,11 @@ copy of - копия + копия + + + copy of %1 + копия %1 @@ -2666,6 +2773,15 @@ Error code: %2 + + The game engine died unexpectedly! +(exit code %1) + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%2' button in the main menu! + + TeamSelWidget @@ -2788,7 +2904,7 @@ find hedgehog - найти ёжика + найти ёжика ammo menu @@ -2866,6 +2982,14 @@ hedgehog info информация о еже + + autocam / find hedgehog + + + + speed up replay + ускорить проигрывание + binds (categories) @@ -2914,7 +3038,7 @@ Move the camera to the active hog: - Передвижение камеры на активного ежа: + Передвижение камеры на активного ежа: Move the cursor or camera without using the mouse: @@ -2956,6 +3080,14 @@ Hedgehog movement Движение ежа + + Toggle automatic camera / refocus on active hedgehog: + + + + Demo replay: + + binds (keys) @@ -3279,10 +3411,6 @@ server - Restricted - - - Not room master @@ -3292,15 +3420,15 @@ too many teams - + слишком много команд too many hedgehogs - + слишком много ежей There's already a team with same name in the list - + В списке уже есть команда с таким названием round in progress @@ -3308,7 +3436,7 @@ restricted - + ограничено REMOVE_TEAM: no such team @@ -3364,7 +3492,7 @@ kicked - + выкинут Ping timeout @@ -3372,23 +3500,19 @@ bye - + пока No such room - - - - Room version incompatible to your hedgewars version - + Нет такой комнаты Joining restricted - + Вход ограничен Registered users only - + Только для зарегистрированных игроков You are banned in this room @@ -3398,5 +3522,69 @@ Empty config entry + + Restricted + Ограничено + + + Room version incompatible to your hedgewars version + + + + You already have voted + + + + Voting closed + + + + New voting started + + + + Voting expired + + + + kick + выкинуть + + + map + карта + + + pause + пауза + + + Reconnected too fast + + + + Warning! Chat flood protection activated + + + + Excess flood + + + + Game messages flood detected - 1 + + + + Game messages flood detected - 2 + + + + Warning! Joins flood protection activated + + + + There's no voting going on + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/hedgewars_sk.ts --- a/share/hedgewars/Data/Locale/hedgewars_sk.ts Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/hedgewars_sk.ts Tue Nov 10 20:43:13 2015 +0100 @@ -23,7 +23,11 @@ copy of - kópia z + kópia z + + + copy of %1 + @@ -224,6 +228,56 @@ Skontrolujte, prosím, inštaláciu! + + Usage + command-line + + + + OPTION + command-line + + + + CONNECTSTRING + command-line + + + + Options + command-line + + + + Display this help + command-line + + + + Custom path for configuration data and user data + command-line + + + + Custom path to the game data folder + command-line + + + + Hedgewars can use a %1 (e.g. "%2") to connect on start. + command-line + + + + Malformed option argument: %1 + command-line + + + + Unknown option argument: %1 + command-line + + HWAskQuitDialog @@ -413,6 +467,17 @@ Cannot open demofile %1 Nie je možné otvoriť demosúbor %1 + + A Fatal ERROR occured! - The game engine had to stop. + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%1' button in the main menu! + +Last two engine messages: +%2 + + HWMapContainer @@ -540,6 +605,14 @@ Theme: %1 + + Random perlin + + + + Style: + + HWNetServersModel @@ -606,6 +679,10 @@ The server is too old. Disconnecting now. Server je príliš zastaraný. Odpojím sa. + + Server authentication error + + HWPasswordDialog @@ -799,6 +876,10 @@ This page requires an internet connection. + + Open packages directory + + PageDrawMap @@ -850,6 +931,10 @@ Ellipse + + Optimize + + PageEditTeam @@ -908,9 +993,13 @@ Ranking Rebríček - + The best shot award was won by <b>%1</b> with <b>%2</b> pts. - Ocenenie za najlepší zásah vyhral(a) <b>%1</b> so ziskom <b>%2</b> bodov. + + Ocenenie za najlepší zásah vyhral(a) <b>%1</b> so ziskom <b>%2</b> bodov. + + + The best killer is <b>%1</b> with <b>%2</b> kills in a turn. @@ -2143,6 +2232,10 @@ World Edge + + Script parameter + + QLineEdit @@ -2615,6 +2708,10 @@ Script + + Random Perlin + + SeedPrompt @@ -2659,7 +2756,11 @@ copy of - kópia z + kópia z + + + copy of %1 + @@ -2673,6 +2774,15 @@ Error code: %2 + + The game engine died unexpectedly! +(exit code %1) + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%2' button in the main menu! + + TeamSelWidget @@ -2728,7 +2838,7 @@ find hedgehog - nájsť ježka + nájsť ježka ammo menu @@ -2866,6 +2976,14 @@ hedgehog info + + autocam / find hedgehog + + + + speed up replay + + binds (categories) @@ -2914,7 +3032,7 @@ Move the camera to the active hog: - Presunie kameru na aktívneho ježka: + Presunie kameru na aktívneho ježka: Move the cursor or camera without using the mouse: @@ -2956,6 +3074,14 @@ Hedgehog movement + + Toggle automatic camera / refocus on active hedgehog: + + + + Demo replay: + + binds (keys) @@ -3398,5 +3524,61 @@ Empty config entry + + You already have voted + + + + Voting closed + + + + New voting started + + + + Voting expired + + + + kick + + + + map + + + + pause + pauza + + + Reconnected too fast + + + + Warning! Chat flood protection activated + + + + Excess flood + + + + Game messages flood detected - 1 + + + + Game messages flood detected - 2 + + + + Warning! Joins flood protection activated + + + + There's no voting going on + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/hedgewars_sv.ts --- a/share/hedgewars/Data/Locale/hedgewars_sv.ts Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/hedgewars_sv.ts Tue Nov 10 20:43:13 2015 +0100 @@ -23,7 +23,11 @@ copy of - kopia av + kopia av + + + copy of %1 + @@ -215,6 +219,56 @@ Please check your installation! + + Usage + command-line + + + + OPTION + command-line + + + + CONNECTSTRING + command-line + + + + Options + command-line + + + + Display this help + command-line + + + + Custom path for configuration data and user data + command-line + + + + Custom path to the game data folder + command-line + + + + Hedgewars can use a %1 (e.g. "%2") to connect on start. + command-line + + + + Malformed option argument: %1 + command-line + + + + Unknown option argument: %1 + command-line + + HWAskQuitDialog @@ -404,6 +458,17 @@ Cannot open demofile %1 Kan inte öppna demofil %1 + + A Fatal ERROR occured! - The game engine had to stop. + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%1' button in the main menu! + +Last two engine messages: +%2 + + HWMapContainer @@ -531,6 +596,14 @@ Theme: %1 + + Random perlin + + + + Style: + + HWNetServersModel @@ -597,6 +670,10 @@ The server is too old. Disconnecting now. + + Server authentication error + + HWPasswordDialog @@ -777,6 +854,10 @@ This page requires an internet connection. + + Open packages directory + + PageDrawMap @@ -828,6 +909,10 @@ Ellipse + + Optimize + + PageEditTeam @@ -886,9 +971,12 @@ Ranking Rankning - + The best shot award was won by <b>%1</b> with <b>%2</b> pts. - Bästa skott-priset vanns av <b>%1</b> med <b>%2</b> poäng. + + Bästa skott-priset vanns av <b>%1</b> med <b>%2</b> poäng. + + The best killer is <b>%1</b> with <b>%2</b> kills in a turn. @@ -2108,6 +2196,10 @@ World Edge + + Script parameter + + QLineEdit @@ -2553,6 +2645,10 @@ Script + + Random Perlin + + SeedPrompt @@ -2597,7 +2693,11 @@ copy of - kopia av + kopia av + + + copy of %1 + @@ -2611,6 +2711,15 @@ Error code: %2 + + The game engine died unexpectedly! +(exit code %1) + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%2' button in the main menu! + + TeamSelWidget @@ -2666,7 +2775,7 @@ find hedgehog - hitta igelkott + hitta igelkott ammo menu @@ -2804,6 +2913,14 @@ hedgehog info + + autocam / find hedgehog + + + + speed up replay + + binds (categories) @@ -2852,7 +2969,7 @@ Move the camera to the active hog: - Flytta kameran till aktiv igelkotte: + Flytta kameran till aktiv igelkotte: Move the cursor or camera without using the mouse: @@ -2894,6 +3011,14 @@ Hedgehog movement + + Toggle automatic camera / refocus on active hedgehog: + + + + Demo replay: + + binds (keys) @@ -3336,5 +3461,61 @@ Empty config entry + + You already have voted + + + + Voting closed + + + + New voting started + + + + Voting expired + + + + kick + + + + map + + + + pause + pausa + + + Reconnected too fast + + + + Warning! Chat flood protection activated + + + + Excess flood + + + + Game messages flood detected - 1 + + + + Game messages flood detected - 2 + + + + Warning! Joins flood protection activated + + + + There's no voting going on + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/hedgewars_tr_TR.ts --- a/share/hedgewars/Data/Locale/hedgewars_tr_TR.ts Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/hedgewars_tr_TR.ts Tue Nov 10 20:43:13 2015 +0100 @@ -5,14 +5,14 @@ About Unknown Compiler - + Bilinmeyen Derleyici AbstractPage Go back - + Geri Dön @@ -23,6 +23,10 @@ copy of + kopya + + + copy of %1 @@ -30,77 +34,89 @@ BanDialog IP - IP + IP Nick - + Takma Ad IP/Nick - + IP Reason - + Sebep Duration - + Süre Ok - + Tamam Cancel - İptal + İptal you know why - + biliyor musunuz Warning - + Uyarı Please, specify %1 - + Lütfen %1 belirtin nickname - + takmaad permanent - + kalıcı DataManager Use Default - + Varsayılanı Kullan FeedbackDialog View - + Göster Cancel - İptal + İptal Send Feedback - + Geribildirim Gönder + + + Please give us feedback! + Lütfen bize geribildirim gönder! We are always happy about suggestions, ideas, or bug reports. - + Her zaman yeni öneri, fikir ve hata raporlarından mutlu oluyoruz. + + + If you found a bug, you can see if it's already known here (english): + Eğer bir hata bulduysan, burada olup olmadığını görebilirsin (İngilizce): + + + Your email address is optional, but we may want to contact you. + E-posta adresi isteğe bağlıdır, ancak iletişime geçmek isteyebiliriz. Send us feedback! @@ -119,12 +135,12 @@ FreqSpinBox Never - + Asla Every %1 turn - - + + Her %1 turda @@ -140,15 +156,15 @@ Game scheme will auto-select a weapon - + Oyun planı otomatik bir silah seçecek Map - Harita + Harita Game options - + Oyun seçenekleri @@ -162,47 +178,100 @@ HWApplication %1 minutes - - + + %1 dakika %1 hour - - + + %1 saat %1 hours - - + + %1 saat %1 day - - + + %1 gün %1 days - - + + %1 gün Scheme '%1' not supported - + '%1' planı desteklenmiyor Cannot create directory %1 - %1 dizini oluşturulamadı + %1 dizini oluşturulamadı Failed to open data directory: %1 Please check your installation! + Veri dizini açılamadı: +%1 + +Lütfen kurulumunuzu denetleyin! + + + Usage + command-line + + + + OPTION + command-line + + + + CONNECTSTRING + command-line + + + + Options + command-line + + + + Display this help + command-line + + + + Custom path for configuration data and user data + command-line + + + + Custom path to the game data folder + command-line + + + + Hedgewars can use a %1 (e.g. "%2") to connect on start. + command-line + + + + Malformed option argument: %1 + command-line + + + + Unknown option argument: %1 + command-line @@ -210,50 +279,54 @@ HWAskQuitDialog Do you really want to quit? - + Gerçekten çıkmak istiyor musunuz? HWChatWidget %1 has been removed from your ignore list - - - - %1 has been added to your ignore list - + %1 yoksayma listenizden kaldırıldı + + + %1 has been added toINCOMPLETE your ignore list + %1 yoksayma listenize eklendi %1 has been removed from your friends list - + %1 arkadaş listenizden kaldırıldı %1 has been added to your friends list - + %1 arkadaş listenize eklendi Stylesheet imported from %1 - + %1 biçembelgesi aktarıldı Enter %1 if you want to use the current StyleSheet in future, enter %2 to reset! - + Geçerli BiçemBelgesini ileride kullanmak için %1, sıfırlamak için %3 girin! Couldn't read %1 - + %1 okunamadı StyleSheet discarded - + BiçemBelgesi silindi StyleSheet saved to %1 - + BiçemBelgesi %1 konumuna kaydedildi Failed to save StyleSheet to %1 - + BiçemBelgesi %1 konumuna kaydedilemedi + + + %1 has been added to your ignore list + %1 yoksayma listenize eklendi %1 has joined @@ -276,50 +349,50 @@ DefaultTeam - + VarsayılanTakım Hedgewars Demo File File Types - + Hedgewars Gösteri Dosyası Hedgewars Save File File Types - + Hedgewars Kayıt Dosyası Demo name - + Gösteri adı Demo name: - + Gösteri adı: Game aborted - + Oyun sonlandı Nickname - + Takma ad No nickname supplied. - + Takma ad girilmedi. Someone already uses your nickname %1 on the server. Please pick another nickname: - + Sunucuda başka biri %1 takma adını kullanıyor. Başka bir isim girin: %1's Team - + %1 Oyuncusunun Takımı Hedgewars - Nick registered - + Hedgewars - Takma ad kayıtlı This nick is registered, and you haven't specified a password. @@ -327,48 +400,53 @@ If this nick isn't yours, please register your own nick at www.hedgewars.org Password: - + Bu takma ad kayıtlı ve bir parola belirtmedin. + +Bu takma ad senin değilse, lütfen kendi takma adını www.hedgewars.org adresinden kaydet. + +Parola: Your nickname is not registered. To prevent someone else from using it, please register it at www.hedgewars.org - + Takma adın kayıtlı değil. +Başkasının kullanmaması için lütfen, +www.hedgewars.org sitesinden kaydet. Your password wasn't saved either. - + + +Parolan da kaydedilmedi. Hedgewars - Empty nickname - + Hedgewars - Boş takma ad Hedgewars - Wrong password - + Hedgewars - Hatalı parola You entered a wrong password. - + Hatalı parola girdin. Try Again - + Tekrar Dene Hedgewars - Connection error - + Hedgewars - Bağlantı hatası You reconnected too fast. Please wait a few seconds and try again. - - - - This page requires an internet connection. - + Çok hızlı yeniden bağlandın. +Birkaç saniye bekle ve yeniden dene. Guest @@ -383,6 +461,10 @@ Please, enter the password: + + This page requires an internet connection. + + HWGame @@ -394,6 +476,17 @@ Cannot open demofile %1 Gösteri dosyası açılamadı %1 + + A Fatal ERROR occured! - The game engine had to stop. + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%1' button in the main menu! + +Last two engine messages: +%2 + + HWMapContainer @@ -423,98 +516,110 @@ Small tunnels - + Küçük tüneller Medium tunnels - + Orta tüneller Seed - + Besleme Map type: - + Harita türü: Image map - + Resim haritası Mission map - + Görev haritası Hand-drawn - + El çizimi Randomly generated - + Rastgele oluşturulmuş Random maze - + Rastgele labirent Random - Rastgele + Rastgele Map preview: - + Harita önizleme: Load map drawing - + Yerel harita çizimi Edit map drawing - + Harita çizimini düzenle Small islands - + Küçük adalar Medium islands - + Orta adalar Large islands - + Büyük adalar Map size: - + Harita boyutu: Maze style: - + Labirent biçemi: Mission: - + Görev: Map: - + Harita: + + + Theme: + Tema: Load drawn map - + Çizili harita yükle Drawn Maps - + Çizili Haritalar All files - + Tüm dosyalar Large tunnels + Büyük tüneller + + + Random perlin + + + + Style: @@ -553,7 +658,7 @@ Quit reason: - Çıkma sebebi: + Çıkma sebebi: You got kicked @@ -561,26 +666,34 @@ %1 *** %2 has joined the room - + %1 *** %2 odaya katıldı + + + %1 *** %2 has joined + %1 *** %2 katıldı %1 *** %2 has left - + %1 *** %2 ayrıldı %1 *** %2 has left (%3) - + %1 *** %2 ayrıldı (%3) User quit - + Kullanıcı çıktı Remote host has closed connection - + Uzak sunucu bağlantıyı kapattı The server is too old. Disconnecting now. + Sunucu çok eski. Bağlantı kesiliyor. + + + Server authentication error @@ -588,55 +701,58 @@ HWPasswordDialog Login - + Oturum aç To connect to the server, please log in. If you don't have an account on www.hedgewars.org, just enter your nickname. - + Sunucuya bağlanmak için lütfen oturum aç. + +Eğer www.hedgewars.org adresinde bir hesabın yoksa, +sadece takma adını gir. Nickname: - + Takma ad: Password: - + Parola: HWUploadVideoDialog Upload video - + Video yükle Upload - + Yükle HatButton Change hat (%1) - + Şapkayı değiştir (%1) HatPrompt Cancel - İptal + İptal Use selected hat - + Seçili şapkayı kullan Search for a hat: - + Şapka ara: @@ -650,18 +766,32 @@ KeyBinder Category - + Kategori LibavInteraction + Duration: %1m %2s + + Süre: %1d %2s + + + + Video: %1x%2, + Video: %1x%2, + + + %1 fps, + %1 fps, + + Audio: - + Ses: unknown - + bilinmiyor Duration: %1m %2s @@ -680,70 +810,70 @@ MapModel No description available. - + Kullanılabilir açıklama yok. PageAdmin Clear Accounts Cache - + Hesap Belleğini Temizle Fetch data - + Veri getir Server message for latest version: - + Son sürüm için sunucu iletisi: Server message for previous versions: - + Önceki sürümler için sunucu iletisi: Latest version protocol number: - + En son sürüm protokol numarası: MOTD preview: - + MOTD önizleme: Set data - + Veri ayarla General - Genel + Genel Bans - + Engellemeler IP/Nick - + IP/Takma Ad Expiration - + Dolum Reason - + Sebep Refresh - + Yenile Add - + Ekle Remove - + Kaldır @@ -756,6 +886,10 @@ PageDataDownload + Open packages directory + + + Loading, please wait. @@ -768,39 +902,39 @@ PageDrawMap Undo - + Geri al Clear - + Temizle Load - Yükle + Yükle Save - + Kaydet Load drawn map - + Çizili harita yükle Save drawn map - + Çizili haritayı kaydet Drawn Maps - + Çizili Haritalar All files - + Tüm dosyalar Eraser - + Silgi Polyline @@ -814,6 +948,10 @@ Ellipse + + Optimize + + PageEditTeam @@ -823,93 +961,95 @@ Select an action to choose a custom key bind for this team - + Bu takıma özel tuş ataması için bir eylem seçin Use my default - + Varsayılanı kullan Reset all binds - + Tüm atamaları sıfırla Custom Controls - + Özel Denetimler Hat - + Şapka Name - + İsim This hedgehog's name - + Bu kirpinin adı Randomize this hedgehog's name - + Kirpi adını rastgele ata Random Team - + Rastgele Takım PageGameStats Details - + Ayrıntılar Health graph - + Sağlık Grafiği Ranking - - - + Sıralama + + The best shot award was won by <b>%1</b> with <b>%2</b> pts. - + + En iyi atış ödülü: <b>%2</b> puanla <b>%1</b> + The best killer is <b>%1</b> with <b>%2</b> kills in a turn. - - + + En iyi öldürücü: <b>%1</b> bir turda <b>%2</b> öldürme. A total of <b>%1</b> hedgehog(s) were killed during this round. - - + + Bu turda toplam <b>%1</b> kirpi öldürüldü. (%1 kill) - - + + (%1 öldürme) <b>%1</b> thought it's good to shoot his own hedgehogs with <b>%2</b> pts. - - + + <b>%1</b> kendi kirpilerini <b>%2</b> puanla vurmanın güzel olduğunu düşündü <b>%1</b> killed <b>%2</b> of his own hedgehogs. - - + + <b>%1</b> kendi <b>%2</b> kirpisini öldürdü <b>%1</b> was scared and skipped turn <b>%2</b> times. - - + + <b>%1</b> korktu ve <b>%2</b> kez turu pas geçti. @@ -918,7 +1058,7 @@ Save - + Kaydet (%1 %2) @@ -931,73 +1071,73 @@ PageInGame In game... - + Oyunda... PageInfo Open the snapshot folder - + Ekran görüntü klasörünü aç PageMain Downloadable Content - + İndirilebilir İçerik Play a game on a single computer - + Tek bir bilgisayarda oyna Play a game across a network - + Ağ üzerinde oyna Read about who is behind the Hedgewars Project - + Hedgewars Projesinin arkasında kimlerin olduğunu göster Leave a feedback here reporting issues, suggesting features or just saying how you like Hedgewars - + Sorunları bildirme, özellik önerme veya Hedgewars oyununu ne kadar sevdiğini söylemek için geri bildirim bırak Access the user created content downloadable from our website - + Websitemizdeki kullanıcılar tarafından oluşturulmuş indirilebilir içeriğe bak Exit game - + Oyundan çık Manage videos recorded from game - + Oyunda kayıtlı videolarını yönet Edit game preferences - + Oyun tercihlerini düzenle Play a game across a local area network - + Yerel ağda bir oyun oyna Play a game on an official server - + Resmi bir sunucuda oyun oyna Feedback - + Geri Bildirim Play local network game - + Yerel ağ oyunu oyna Play official network game - + Resmi ağ oyunu oyna @@ -1008,42 +1148,42 @@ Edit game preferences - + Oyun tercihlerini düzenle PageNetGame Control - Kontrol + Denetim Edit game preferences - + Oyun tercihlerini düzenle Start - Başla + Başla Update - Güncelle + Güncelle Room controls - + Oda denetimleri PageNetServer + Insert your address here + Adresi buraya girin + + Click here for details - - Insert your address here - - PageOptions @@ -1057,163 +1197,163 @@ Delete team - + Takımı sil You can't edit teams from team selection. Go back to main menu to add, edit or delete teams. - + Takım seçiminden takımları düzenleyemezsiniz. Takım eklemek, düzenlemek ve silmek için ana menüye dönün. New scheme - + Yeni plan Edit scheme - + Planı düzenle Delete scheme - + Planı sil New weapon set - + Yeni silah seti Edit weapon set - + Silah setini düzenle Delete weapon set - + Silah setini sil Advanced - Gelişmiş + Gelişmiş Reset to default colors - + Varsayılan renklere sıfırla Proxy host - + Vekil sunucusu Proxy port - + Vekil portu Proxy login - + Vekil kullanıcı adı Proxy password - + Vekil parolası No proxy - + Vekil sunucu yok Socks5 proxy - + Socks5 vekil sunucusu HTTP proxy - + HTTP vekil sunucusu System proxy settings - + Sistem vekil ayarları Select an action to change what key controls it - + Denetimi kullanan tuşu değiştirmek için bir eylem seçin Reset to default - + Varsayılana sıfırla Reset all binds - + Tüm atamaları sıfırla Game - + Oyun Graphics - + Grafik Audio - + Ses Controls - + Denetimler Video Recording - + Video Kaydı Network - + Teams - Takımlar + Takımlar Schemes - + Planlar Weapons - Silahlar + Silahlar Frontend - + Ön Uç Custom colors - + Özel renkler Game audio - + Oyun sesi Frontend audio - + Ön uç sesi Account - + Hesap Proxy settings - + Vekil sunucu ayarları Miscellaneous - + Çeşitli Updates - + Güncellemeler Check for updates - + Güncellemeleri Denetle Video recording options - + Video kayıt seçenekleri @@ -1241,31 +1381,43 @@ Admin features Yönetici görevleri + + Rules: + Kurallar: + + + Weapons: + Silahlar: + %1 players online - - + + %1 oyuncu çevrimiçi Search for a room: - + Bir oda ara: Create room - + Oda oluştur Join room - + Odaya katıl Room state - + Oda durumu + + + Clear filters + Süzgeçleri temizle Open server administration page - + Sunucu yönetim sayfasını aç @@ -1276,7 +1428,7 @@ Teams will start on opposite sides of the terrain, two team colours max! - Takımlar bölgenin faklı taraflarında başlarlar, en fazla iki takım rengi! + Takımlar bölgenin farklı taraflarında başlarlar, en fazla iki takım rengi! Land can not be destroyed! @@ -1296,7 +1448,7 @@ Gain 80% of the damage you do back in health - Verdiğin hasarın %%80'ini sağlık olarak kazan + Verdiğin hasarın %80'ini sağlık olarak kazan Share your opponents pain, share their damage @@ -1324,63 +1476,63 @@ Order of play is random instead of in room order. - + Oda sırası yerine oynama sırası rastgeledir. Play with a King. If he dies, your side dies. - + Bir Kralla oyna. O ölürse takımın ölür. Take turns placing your hedgehogs before the start of play. - + Oyuna başlamadan önce kirpileri sırayla yerleştir. Ammo is shared between all teams that share a colour. - + Aynı rengi paylaşan tüm takımlar cephaneyi paylaşır. Disable girders when generating random maps. - + Rastgele haritalar oluştururken kirişleri devre dışı bırak. Disable land objects when generating random maps. - + Rastgele haritalar oluştururken zemin nesnelerini devre dışı bırak. AI respawns on death. - + Yapay zeka, öldükten sonra yeniden doğar. All (living) hedgehogs are fully restored at the end of turn - + Tüm (yaşayan) kirpiler tur sonunda eski haline gelir Attacking does not end your turn. - + Saldırmak sıranı bitirmez. Weapons are reset to starting values each turn. - + Silahlar her turda başlangıç değerlerine sıfırlanır. Each hedgehog has its own ammo. It does not share with the team. - + Her kirpinin kendi cephanesi olur. Takımla paylaşmaz. You will not have to worry about wind anymore. - + Artık rüzgarı dert etmen gerekmiyor. Wind will affect almost everything. - + Rüzgar neredeyse her şeyi etkiler. Copy - + Kopyala Teams in each clan take successive turns sharing their turn time. - + Her klandaki takımlar kendi sıralarındaki zamanı paylaşarak değişirler. Add an indestructible border around the terrain @@ -1388,7 +1540,7 @@ Add an indestructible border along the bottom - + Alta yok edilemez bir sınır ekle None (Default) @@ -1411,7 +1563,7 @@ PageSelectWeapon Default - Öntanımlı + Varsayılan Delete @@ -1419,94 +1571,108 @@ New - Yeni + Yeni Copy - + Kopyala PageSinglePlayer Play a quick game against the computer with random settings - + Rastgele ayarlarla bilgisayara karşı hızlı bir oyun oyna Play a hotseat game against your friends, or AI teams - + Arkadaşlarınla veya Yapay Zeka takımlarıyla ayarlanmış bir oyun oyna Campaign Mode - + Mücadele Kipi Practice your skills in a range of training missions - + Yeteneklerini çeşitli eğitim görevleri ile geliştir Watch recorded demos - + Kayıtlı gösterileri izle Load a previously saved game - + Önceden kayıtlı bir oyun yükle PageTraining No description available - + Kullanılabilir açıklama yok Select a mission! - + Bir görev seç! Pick the mission or training to play - + Oynamak üzere bir görev veya eğitim seç Start fighting - + Dövüşe başla PageVideos Name - + İsim Size - + Boyut %1 bytes - - + + %1 bayt (in progress...) - + (yapım aşamasında...) encoding - + kodlanıyor uploading - + yükleniyor + + + Date: %1 + + Tarih: %1 + + + + Size: %1 + + Boyut: %1 + Date: %1 - + Tarih: %1 + {1?} Size: %1 - + Boyut: %1 + {1?} @@ -1533,23 +1699,23 @@ Follow - + Takip Et Ignore - + Yoksay Add friend - + Arkadaş ekle Unignore - + Yoksaymayı kapat Remove friend - + Arkadaş kaldır Update @@ -1557,15 +1723,15 @@ Restrict Unregistered Players Join - + Kayıtsız Oyuncuların Katılmasını Kısıtla Show games in lobby - + Lobideki oyunları göster Show games in-progress - + Süren oyunları göster @@ -1588,59 +1754,59 @@ Check for updates at startup - + Başlangıçta güncellemeleri denetle Show ammo menu tooltips - + Cephane menüsü araç ipuçlarını göster Save password - + Parolayı kaydet Save account name and password - + Hesap adı ve parolasını kaydet Video is private - + Video özel Record audio - + Sesi kaydet Use game resolution - + Oyun çözünürlüğünü kullan Visual effects - + Görsel efektler Sound - + Ses In-game sound effects - + Oyun ses efektleri Music - + Müzik In-game music - + Oyun içi müzik Frontend sound effects - + Ön uç ses efektleri Frontend music - + Ön uç müziği Team @@ -1683,75 +1849,79 @@ Level - Bilgisayar + Seviye (System default) - + (Sistem varsayılanı) Community - + Topluluk + + + Any + Herhangi Disabled - + Kapalı Red/Cyan - + Kırmızı/Camgöbeği Cyan/Red - + Camgöbeği/Kırmızı Red/Blue - + Kırmızı/Mavi Blue/Red - + Mavi/Kırmızı Red/Green - + Kırmızı/Yeşil Green/Red - + Yeşil/Kırmızı Side-by-side - + Yan yana Top-Bottom - + Üst-Alt Red/Cyan grayscale - + Kırmızı/Camgöbeği gri Cyan/Red grayscale - + Camgöbeği/Kırmızı gri Red/Blue grayscale - + Kırmızı/Mavi gri Blue/Red grayscale - + Mavi/Kırmızı gri Red/Green grayscale - + Kırmızı/Yeşil gri Green/Red grayscale - + Yeşil/Kırmızı gri @@ -1782,15 +1952,15 @@ Team Settings - + Takım ayarları Videos - + Videolar Description - + Açıklama @@ -1865,177 +2035,183 @@ % Dud Mines - + Sahte Mayın % Name - + İsim Type - + Tür Grave - + Mezar taşı Flag - + Bayrak Voice - + Ses Locale - + Dil Explosives - + Patlayıcılar + + + Tip: + İpucu: Quality - + Kalite % Health Crates - + Sağlık Sandık %'si Health in Crates - + Sandıklardaki Sağlık Sudden Death Water Rise - + Ani Ölüm Su Yükselmesi Sudden Death Health Decrease - + Ani Ölüm Sağlık Azaltması % Rope Length - + Halat Uzunluk %'si Stereo rendering - + Stereo hazırlama Style - + Biçem Scheme - + Plan % Get Away Time - + Uzakta Zamanı %'si There are videos that are currently being processed. Exiting now will abort them. Do you really want to quit? - + Şu anda işlenen videolar var. +Çıkmak bu işlemi sonlandıracak. +Gerçekten çıkmak istiyor musunuz? Please provide either the YouTube account name or the email address associated with the Google Account. - + Lütfen YouTube hesap adını veya Google Hesabınız ile ilişkilendirmiş e-posta adresini gir. Account name (or email): - + Hesap adı (veya e-posta): Password: - + Parola: Video title: - + Video başlığı: Video description: - + Video açıklaması: Tags (comma separated): - + Etiketler (virgülle ayrılmış): Description - + Açıklama Nickname - + Takma ad Format - + Biçim Audio codec - + Ses kodlayıcı Video codec - + Video kodlayıcı Framerate - + Kare oranı Bitrate (Kbps) - + Bit oranı (Kbps) This development build is 'work in progress' and may not be compatible with other versions of the game, while some features might be broken or incomplete! - + Bu geliştirme derlemesi 'yapım aşamasındadır' ve oyunun diğer sürümleri ile uyumlu olmayabilir; bazı özellikler bozuk veya tamamlanmamış olabilir! Fullscreen - Tam ekran + Tam ekran Fullscreen Resolution - + Tam Ekran Çözünürlüğü Windowed Resolution - + Pencere Çözünürlüğü Your Email - + E-postanız Summary - + Özet Send system information - + Sistem bilgisi gönder Type the security code: - + Güvenlik kodunu yaz: Revision - + Gözden Geçirme This program is distributed under the %1 - + Bu program %1 altında dağıtılmaktadır This setting will be effective at next restart. - + Bu ayar bir sonraki başlatmada etkin olacaktır. Tip: %1 @@ -2049,6 +2225,10 @@ World Edge + + Script parameter + + QLineEdit @@ -2058,11 +2238,11 @@ hedgehog %1 - + kirpi %1 anonymous - + anonim @@ -2071,6 +2251,10 @@ Hedgewars %1 Hedgewars %1 + + -r%1 (%2) + -r%1 (%2) + QMessageBox @@ -2084,227 +2268,255 @@ File association failed. - + Dosya ilişkilendirme başarısız. Error while authenticating at google.com: - + Google.com ile kimlik açma başarısız Login or password is incorrect - + Kullanıcı adı veya parolası yanlış Error while sending metadata to youtube.com: - + Youtube.com üst verisi gönderilirken hata Teams - Are you sure? - + Takımlar - Emin misin? Do you really want to delete the team '%1'? - + '%1' takımını gerçekten silmek istiyor musun? Cannot delete default scheme '%1'! - + Varsayılan '%1' planı silinemez Please select a record from the list - + Lütfen listeden bir kayıt seç Unable to start server - + Sunucu başlatılamadı Hedgewars - Error - + Hedgewars - Hata Hedgewars - Success - + Hedgewars - Başarılı All file associations have been set - + Tüm dosya ilişkilendirmeleri ayarlandı Cannot create directory %1 %1 dizini oluşturulamadı + Failed to open data directory: +%1 + +Please check your installation! + Veri dizini açılamadı: +%1 + +Lütfen kurulumunuzu denetleyin! + + + TCP - Error + TCP - Hata + + Unable to start the server: %1. Sunucu başlatılamadı: %1. + Unable to run engine at + Motor şurada başlatılamadı: + + + Error code: %1 + Hata kodu: %1 + + Video upload - Error - + Video yükleme - Hata Netgame - Error - + Ağ oyunu - Hata Please select a server from the list - + Lütfen listeden bir sunucu seç Please enter room name - Lütfen oda ismini girin + Lütfen oda ismini gir Record Play - Error - + Oyunu Kaydet - Hata Please select record from the list - Lütfen listeden kaydı seçin + Lütfen listeden kaydı seç Cannot rename to - + Adlandırma başarısız: Cannot delete file - + Dosya silinemedi: Room Name - Error - + Oda Adı - Hata Please select room from the list - Lütfen listeden bir oda seçin + Lütfen listeden bir oda seçin Room Name - Are you sure? - + Oda Adı - Emin misiniz? The game you are trying to join has started. Do you still want to join the room? - + Katılmaya çalıştığınız oyun başlamış. +Hala odaya katılmak istiyor musunuz? Schemes - Warning - + Planlar - Uyarı Schemes - Are you sure? - + Planlar - Emin misiniz? Do you really want to delete the game scheme '%1'? - + Gerçekten '%1' oyun planını silmek istiyor musunuz? Videos - Are you sure? - + Videolar - Emin misiniz? Do you really want to delete the video '%1'? - + Gerçekten '%1' videosunu silmek istiyor musunuz? Do you really want to remove %1 file(s)? - - + + Gerçekten %1 dosyayı kaldırmak istiyor musunuz? Do you really want to cancel uploading %1? - + Gerçekten %1 yüklemesini iptal etmek istiyor musunuz? File error - + Dosya hatası Cannot open '%1' for writing - + '%1' yazmak için açılamıyor Cannot open '%1' for reading - + '%1' okumak için açılamıyor Cannot use the ammo '%1'! - + '%1' cephanesi kullanılamıyor! Weapons - Warning - + Silahlar - Uyarı Cannot overwrite default weapon set '%1'! - + Varsayılan '%1' silah setinin üzerine yazılamaz! Cannot delete default weapon set '%1'! - + Varsayılan '%1' silah seti silinemez! Weapons - Are you sure? - + Silahlar - Emin misiniz? Do you really want to delete the weapon set '%1'? - + Gerçekten '%1' silah setini silmek istiyor musunuz? Hedgewars - Nick not registered - + Hedgewars - Takma ad kayıtlı değil System Information Preview - + Sistem Bilgi Önizlemesi Failed to generate captcha - + Captcha oluşturulamadı Failed to download captcha - + Captcha indirilemedi Please fill out all fields. Email is optional. - + Lütfen tüm alanları doldurun. E-posta isteğe bağlıdır. Hedgewars - Warning - + Hedgewars - Uyarı Hedgewars - Information - + Hedgewars - Bilgi + + + Hedgewars + Hedgewars Not all players are ready - + Tüm oyuncular hazır değil Are you sure you want to start this game? Not all players are ready. - + Oyunu başlatmak istiyor musunuz? +Tüm oyuncular hazır değil. QObject No description available - + Kullanılabilir açıklama yok QPushButton default - öntanımlı + varsayılan OK @@ -2356,86 +2568,90 @@ Associate file extensions - + Dosya uzantılarını ilişkilendir More info - + Daha fazla bilgi Set default options - + Varsayılan seçenekleri ayarla Open videos directory - + Video dizinini aç Play - + Oynat Upload to YouTube - + YouTube'a Yükle Cancel uploading - + Yüklemeyi iptal et Restore default coding parameters - + Varsayılan kodlama parametrelerini geri al Open the video directory in your system - + Sistemindeki video dizinini aç Play this video - + Bu videoyu oynat Delete this video - + Bu videoyu sil Upload this video to your Youtube account - + Bu videoyu Youtube hesabıma yükle Reset - + Sıfırla Set the default server port for Hedgewars - + Hedgewars için öntanımlı sunucu portu Invite your friends to your server in just 1 click! - + Sadece 1 tık ile arkadaşlarını sunucuna davet et! + + + Click to copy your unique server URL in your clipboard. Send this link to your friends ands and they will be able to join you. + Benzersiz sunucu adresini panoya kopyalamak için tıkla. Bu bağlantıyı arkadaşlarına gönder ve sana katılmalarını sağla. + + + Start private server + Özel sunucuyu başlat Click to copy your unique server URL to your clipboard. Send this link to your friends and they will be able to join you. - - Start private server - - RoomNamePrompt Enter a name for your room. - + Oda için bir ad gir. Cancel - İptal + İptal Create room - + Oda oluştur set password @@ -2446,96 +2662,104 @@ RoomsListModel In progress - + Sürüyor Room Name - + Oda Adı C - + K T - + T Owner - + Sahip Map - Harita + Harita Rules - + Kurallar Weapons - Silahlar + Silahlar Random Map - + Rastgele Harita Random Maze - + Rastgele Labirent Hand-drawn - + El Çizimi Script + + Random Perlin + + SeedPrompt The map seed is the basis for all random values generated by the game. - + Harita beslemesi, oyun tarafından oluşturulan tüm rastgele değerler için bir tabandır. Cancel - İptal + İptal Set seed - + Besleme ayarla Close - + Kapat SelWeaponWidget Weapon set - + Silah seti Probabilities - + Olasılıklar Ammo in boxes - + Kutulardaki cephane Delays - + Gecikmeler new - yeni + yeni copy of + kopya + + + copy of %1 @@ -2543,11 +2767,21 @@ TCPBase Unable to start server at %1. - + %1 içinde sunucu başlatılamıyor Unable to run engine at %1 Error code: %2 + %1 içinde motor çalıştırılamıyor +Hata kodu: %2 + + + The game engine died unexpectedly! +(exit code %1) + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%2' button in the main menu! @@ -2555,22 +2789,29 @@ TeamSelWidget At least two teams are required to play! - + Oynamak için en az iki takım gerekli! + + + + TeamShowWidget + + %1's team + %1 takımı ThemePrompt Cancel - İptal + İptal Search for a theme: - + Tema arayın: Use selected theme - + Seçili temayı kullan @@ -2609,7 +2850,7 @@ find hedgehog - kirpi bul + kirpi bul ammo menu @@ -2697,7 +2938,7 @@ change mode - modu değiştir + kipi değiştir capture @@ -2709,38 +2950,46 @@ long jump - + uzun zıplama high jump - + yüksek zıplama zoom in - + yakınlaştırma zoom out - + uzaklaştırma reset zoom - + yakınlaştırmayı sıfırla slot 10 - slot 10 + slot 10 mute audio - + sesi kapat record - + kaydet hedgehog info + kirpi bilgisi + + + autocam / find hedgehog + + + + speed up replay @@ -2748,89 +2997,97 @@ binds (categories) Movement - + Hareket Weapons - Silahlar + Silahlar Camera - + Kamera Miscellaneous - + Çeşitli binds (descriptions) Traverse gaps and obstacles by jumping: - + Boşluklardan ve engellerden zıplayarak kaçın: Fire your selected weapon or trigger an utility item: - + Seçili silahını ateşle veya bir yardımcı öge tetikle: Pick a weapon or a target location under the cursor: - + Bir silah seç veya imleç altında konum işaretle Switch your currently active hog (if possible): - + Geçerli kirpiyi değiştir (mümkünse): Pick a weapon or utility item: - + Bir silah veya yardımcı öge al: Set the timer on bombs and timed weapons: - + Bombalarda ve zamanlı silahlarda zamanlayıcıyı ayarla: Move the camera to the active hog: - + Kamerayı etkin kirpiye götür: Move the cursor or camera without using the mouse: - + Kamera veya imleci fare kullanmadan hareket ettir Modify the camera's zoom level: - + Kamera yakınlaştırma seviyesini değiştir: Talk to your team or all participants: - + Takımla veya tüm katılanlarla konuş Pause, continue or leave your game: - + Oyunu beklet, devam et veya oyundan ayrıl Modify the game's volume while playing: - + Oynarken oyunun sesini değiştir: Toggle fullscreen mode: - + Tam ekran kipini değiştir: Take a screenshot: - + Ekran görüntüsü al: Toggle labels above hedgehogs: - + Kirpilerin üzerindeki etiketleri aç/kapat Record video: - + Video kaydet: Hedgehog movement + Kirpi hareketi + + + Toggle automatic camera / refocus on active hedgehog: + + + + Demo replay: @@ -2838,35 +3095,35 @@ binds (keys) Axis - + Eksen (Up) - + (Yukarı) (Down) - + (Aşağı) Hat - + Şapka (Left) - + (Sol) (Right) - + (Sağ) Button - + Düğme Keyboard - + Klavye Delete @@ -2874,385 +3131,433 @@ Mouse: Left button - + Fare: Sol düğme Mouse: Middle button - + Fare: Orta düğme Mouse: Right button - + Fare: Sağ düğme Mouse: Wheel up - + Fare: Tekerlek yukarı Mouse: Wheel down - + Fare: Tekerlek aşağı Backspace - + Backspace Tab - + Sekme Clear - + Temizle Return - + Enter Pause - + Pause Escape - + Escape Space - + Boşluk Numpad 0 - + Nümerik 0 Numpad 1 - + Nümerik 1 Numpad 2 - + Nümerik 2 Numpad 3 - + Nümerik 3 Numpad 4 - + Nümerik 4 Numpad 5 - + Nümerik 5 Numpad 6 - + Nümerik 6 Numpad 7 - + Nümerik 7 Numpad 8 - + Nümerik 8 Numpad 9 - + Nümerik 9 Numpad . - + Nümerik . Numpad / - + Nümerik / Numpad * - + Nümerik * Numpad - - + Nümerik - Numpad + - + Nümerik + Enter - + Enter Equals - + Eşittir Up - + Yukarı Down - + Aşağı Right - + Sağ Left - + Sol Insert - + Ekle Home - + Ev End - + Son Page up - + Sayfa yukarı Page down - + Sayfa aşağı Num lock - + Nümerik kilit Caps lock - + Büyük harf Scroll lock - + Kaydırma kilidi Right shift - + Sağ üst karakter Left shift - + Sol üst karakter Right ctrl - + Sağ kontrol Left ctrl - + Sol kontrol Right alt - + Sağ alt Left alt - + Sol alt Right meta - + Sağ meta Left meta - + Sol meta A button - + A düğmesi B button - + B düğmesi X button - + X düğmesi Y button - + Y düğmesi LB button - + LB düğmesi RB button - + RB düğmesi Back button - + Geri düğmesi Start button - + Start düğmesi Left stick - + Sol çubuk Right stick - + Sağ çubuk Left stick (Right) - + Sol çubuk (Sağ) Left stick (Left) - + Sol çubuk (Sol) Left stick (Down) - + Sol çubuk (Aşağı) Left stick (Up) - + Sol çubuk (Yukarı) Left trigger - + Sol tetik Right trigger - + Sağ tetik Right stick (Down) - + Sağ çubuk (Aşağı) Right stick (Up) - + Sağ çubuk (Yukarı) Right stick (Right) - + Sağ çubuk (Sağ) Right stick (Left) - + Sağ çubuk (Sol) DPad - + DPad server - Restricted - - - Not room master - + Oda uzmanı değil Corrupted hedgehogs info - + Bozuk kirpi bilgisi too many teams - + çok fazla takım too many hedgehogs - + çok fazla kirpi There's already a team with same name in the list - + Listede aynı isimde başka bir takım var round in progress - + tur sürüyor restricted - + kısıtlı REMOVE_TEAM: no such team - + REMOVE_TEAM: böyle bir takım yok Not team owner! - + Takım sahibi değil! Less than two clans! - - - - Illegal room name - + İki klandan daha az! Room with such name already exists - + Oda adı zaten mevcut Nickname already chosen - + Takma ad zaten seçilmiş Illegal nickname - + Geçersiz takma ad Protocol already known - + Protokol zaten biliniyor Bad number - + Hatalı sayı Nickname is already in use - + Takma ad zaten kullanımda No checker rights - + Denetim hakları yok Authentication failed - + Kimlik doğrulama başarısız 60 seconds cooldown after kick - + Kovulduktan sonra 60 saniye sakinleşme kicked - + kovuldu Ping timeout - + Ping zaman aşımı bye - + hoşça kal + + + Illegal room name + Geçersiz oda adı No such room + Böyle bir oda yok + + + Joining restricted + Katılma kısıtlı + + + Registered users only + Sadece kayıtlı kullanıcılar + + + You are banned in this room + Bu odadan engellendiniz + + + Empty config entry + Boş yapılandırma girdisi + + + You already have voted + + + + Voting closed + + + + New voting started + + + + Voting expired + + + + kick + + + + map + + + + pause + duraklat + + + Restricted + + + + Reconnected too fast @@ -3260,19 +3565,27 @@ - Joining restricted + Warning! Chat flood protection activated - Registered users only + Excess flood + + + + Game messages flood detected - 1 - You are banned in this room + Game messages flood detected - 2 - Empty config entry + Warning! Joins flood protection activated + + + + There's no voting going on diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/hedgewars_uk.ts --- a/share/hedgewars/Data/Locale/hedgewars_uk.ts Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/hedgewars_uk.ts Tue Nov 10 20:43:13 2015 +0100 @@ -5,14 +5,14 @@ About Unknown Compiler - + Невідомий компілятор AbstractPage Go back - + Назад @@ -23,96 +23,100 @@ copy of - копія + копія + + + copy of %1 + BanDialog IP - IP + IP Nick - + Нік IP/Nick - + IP/Нік Reason - + Причина Duration - + Тривалість Ok - + Гаразд Cancel - Скасувати + Скасувати you know why - + ви знаєте чому Warning - + Увага Please, specify %1 - + Будь ласка, вкажіть %1 nickname - + ім'я permanent - + постійний DataManager Use Default - + Використати типове FeedbackDialog View - + Вигляд Cancel - Скасувати + Скасувати Send Feedback - + Надіслати відгук We are always happy about suggestions, ideas, or bug reports. - + Ми завжди раді пропозиціям, ідеям, або повідомленням про помилки. Send us feedback! - + Надішліть нам відгук! If you found a bug, you can see if it's already been reported here: - + Якщо ви знайшли помилку, ви можете побачити, чи про неї вже повідомлялося, тут: Your email address is optional, but necessary if you want us to get back at you. - + Ваша електронна адреса не є обов'язковою, але потрібною, якщо ви хочете, щоб ми з вами зв'язались. @@ -146,79 +150,132 @@ Game scheme will auto-select a weapon - + Схема гри вибере зброю Map - Мапа + Карта Game options - + Параметри гри GameUIConfig Guest - + Гість HWApplication %1 minutes - - + + %1 хвилин %1 hour - - + + %1 година %1 hours - - + + %1 годин %1 day - - + + %1 день %1 days - - + + %1 днів Scheme '%1' not supported - + Схема '%1' не підтримується Cannot create directory %1 - Не можу створити директорію %1 + Не можу створити директорію %1 Failed to open data directory: %1 Please check your installation! + Не вдалось відкрити теку з даними: +%1 + +Перевірте інсталяцію! + + + Usage + command-line + + + + OPTION + command-line + + + + CONNECTSTRING + command-line + + + + Options + command-line + + + + Display this help + command-line + + + + Custom path for configuration data and user data + command-line + + + + Custom path to the game data folder + command-line + + + + Hedgewars can use a %1 (e.g. "%2") to connect on start. + command-line + + + + Malformed option argument: %1 + command-line + + + + Unknown option argument: %1 + command-line @@ -226,62 +283,62 @@ HWAskQuitDialog Do you really want to quit? - + Дійсно бажаєте вийти? HWChatWidget %1 has been removed from your ignore list - + %1 був видалений зі списку ігнорування %1 has been added to your ignore list - + %1 був доданий до списку ігнорування %1 has been removed from your friends list - + %1 був видалений зі списку друзів %1 has been added to your friends list - + %1 був доданий до списку друзів Stylesheet imported from %1 - + Стиль імпортовано з %1 Enter %1 if you want to use the current StyleSheet in future, enter %2 to reset! - + Введіть %1 щоб використовувати поточний стиль, введіть %2 щоб скинути параметри! Couldn't read %1 - + Неможливо прочитати %1 StyleSheet discarded - + Стиль відхилено StyleSheet saved to %1 - + Стиль збережено до %1 Failed to save StyleSheet to %1 - + Не вдалось зберегти стиль %1 %1 has joined - + %1 приєднався %1 has left - + %1 пішов %1 has left (%2) - + %1 пішов (%2) @@ -306,36 +363,37 @@ Demo name - + Назва демонстрації Demo name: - + Назва демонстрації: Game aborted - + Гра перервана Nickname - Ім'я + Ім'я No nickname supplied. - + Нікнейм не вказаний. Someone already uses your nickname %1 on the server. Please pick another nickname: - + Хтось вже використовує ім'я %1 на сервері. +Виберіть інше ім'я: %1's Team - + Команда %1 Hedgewars - Nick registered - + Hedgewars - Ім'я зареєстроване This nick is registered, and you haven't specified a password. @@ -343,61 +401,71 @@ If this nick isn't yours, please register your own nick at www.hedgewars.org Password: - + Цей нік зареєстрований а ви не вказали пароль. + +Якщо нік не ваш, зареєструйте ваш власний нік на www.hedgewars.org + +Пароль: Your nickname is not registered. To prevent someone else from using it, please register it at www.hedgewars.org - + Ваш нікнейм не зареєстрований. +Щоб ніхто інший ним не користувався, +зареєструйте його на www.hedgewars.org Your password wasn't saved either. - + + +Ваш пароль не був збережений. Hedgewars - Empty nickname - + Hedgewars - Порожнє ім'я Hedgewars - Wrong password - + Hedgewars - Невірний пароль You entered a wrong password. - + Ви вказали невірний пароль. Try Again - + Спробуйте знову Hedgewars - Connection error - + Hedgewars - Помилка з'єднання You reconnected too fast. Please wait a few seconds and try again. - + Ви перепід'єднались надто швидко. +Зачекайте кілька секунд і спробуйте знов. This page requires an internet connection. - + Сторінка потребує з'єднання з інтернетом. Guest - + Гість Room password - + Пароль кімнати The room is protected with password. Please, enter the password: - + Кімната захищена паролем. +Будь ласка, введіть пароль: @@ -410,6 +478,17 @@ Cannot open demofile %1 Не можу відкрити демо %1 + + A Fatal ERROR occured! - The game engine had to stop. + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%1' button in the main menu! + +Last two engine messages: +%2 + + HWMapContainer @@ -447,94 +526,102 @@ Seed - Перемішати + Висів Map type: - + Тип карти: Image map - + Картинка Mission map - + Карта місії Hand-drawn - + Намальована вручну Randomly generated - + Згенерована Random maze - + Випадковий лабіринт Random - Випадково + Випадкова Map preview: - + Огляд карти: Load map drawing - + Завантажити карту Edit map drawing - + Редагувати карту Small islands - + Малі острови Medium islands - + Середні острови Large islands - + Великі острови Map size: - + Розмір карти: Maze style: - + Стиль лабіринту: Mission: - + Місія: Map: - + Карта: Load drawn map - Завантажити намальовану мапу + Завантажити намальовану карту Drawn Maps - + Намальовані карти All files - + Всі файли Large tunnels - + Великі тунелі: Theme: %1 + Тема: %1 + + + Random perlin + + + + Style: @@ -593,14 +680,18 @@ User quit - + Користувач вийшов Remote host has closed connection - + Віддалений комп'ютер закрив з'єднання The server is too old. Disconnecting now. + Сервер застарів. Від'єднуюсь. + + + Server authentication error @@ -608,55 +699,58 @@ HWPasswordDialog Login - + Логін To connect to the server, please log in. If you don't have an account on www.hedgewars.org, just enter your nickname. - + Щоб з'єднатись із серверов, увійдіть. + +Якщо у вас немає акаунта на www.hedgewars.org, +просто вкажіть ваше ім'я. Nickname: - + Ім'я: Password: - + Пароль: HWUploadVideoDialog Upload video - + Надіслати відео Upload - + Надсилання HatButton Change hat (%1) - + Змінити капелюх (%1) HatPrompt Cancel - Скасувати + Скасувати Use selected hat - + Використати вибраний капелюх Search for a hat: - + Шукати капелюх: @@ -670,37 +764,37 @@ KeyBinder Category - + Категорія LibavInteraction Audio: - + Аудіо: unknown - + невідомо Duration: %1m %2s - + Тривалість: %1хв %2с Video: %1x%2 - + Відео: %1x%2 %1 fps - + %1 fps MapModel No description available. - + Опис відсутній. @@ -735,35 +829,35 @@ General - Основні + Основні Bans - + Бани IP/Nick - + IP/Нік Expiration - + Закінчення Reason - + Причина Refresh - + Оновити Add - + Додати Remove - + Видалити @@ -777,10 +871,14 @@ PageDataDownload Loading, please wait. - + Завантажується, зачекайте. This page requires an internet connection. + Ця сторінка потребує з'єднання з інтернетом. + + + Open packages directory @@ -804,34 +902,38 @@ Load drawn map - Завантажити намальовану мапу + Завантажити намальовану карту Save drawn map - Зберегти намальовану мапу + Зберегти намальовану карту Drawn Maps - + Намальовані карти All files - + Всі файли Eraser - + Гумка Polyline - + Ламана лінія Rectangle - + Прямокутник Ellipse + Еліпс + + + Optimize @@ -843,39 +945,39 @@ Select an action to choose a custom key bind for this team - + Виберіть дію для зміни гарячої кнопки для цієї команди Use my default - + Використати типове Reset all binds - + Скинути всі прив'язки Custom Controls - + Власне керування Hat - Капелюх + Капелюх Name - Назва + Назва This hedgehog's name - + Ім'я цього їжака Randomize this hedgehog's name - + Згенерувати випадкове ім'я їжака Random Team - Випадкова Команда + Випадкова Команда @@ -892,9 +994,13 @@ Ranking Позиції - + The best shot award was won by <b>%1</b> with <b>%2</b> pts. - Нагороду за кращий постріл отримує <b>%1</b> з <b>%2</b> пунктами нанесених втрат. + + Нагороду за кращий постріл отримує <b>%1</b> з <b>%2</b> пунктами нанесених втрат. + + + The best killer is <b>%1</b> with <b>%2</b> kills in a turn. @@ -946,16 +1052,16 @@ Play again - + Зіграти знову Save - Зберегти + Зберегти (%1 %2) - - + + (%1 %2) @@ -965,73 +1071,73 @@ PageInGame In game... - + В грі... PageInfo Open the snapshot folder - + Відкрити теку зі знімками PageMain Downloadable Content - + Завантажуваний контент Play a game on a single computer - + Грати гру на одному комп'ютері Play a game across a network - + Грати гру по мережі Read about who is behind the Hedgewars Project - + Дізнатись хто стоїть за проектом Hedgewars Leave a feedback here reporting issues, suggesting features or just saying how you like Hedgewars - + Залиште тут відгук, пропозицію, повідомте про помилку, або просто поділіться враженнями про Hedgewars Access the user created content downloadable from our website - + Отримати контент, створений користувачами Exit game - + Вийти з гри Manage videos recorded from game - + Керувати відеозаписами ігор Edit game preferences - + Змінити параметри гри Play a game across a local area network - + Грати гру по локальній мережі Play a game on an official server - + Грати гру на офіційному сайті Feedback - + Відгук Play local network game - + Грати локальну мережну гру Play official network game - + Грати офіційну мережну гру @@ -1042,7 +1148,7 @@ Edit game preferences - + Змінити параметри гри @@ -1053,30 +1159,30 @@ Edit game preferences - + Змінити параметри гри Start - Старт + Старт Update - Оновити + Оновити Room controls - + Керування кімнатою PageNetServer Click here for details - + Клацніть тут за деталями Insert your address here - + Вкажіть вашу адресу тут @@ -1123,131 +1229,131 @@ Advanced - Розширені + Розширені Reset to default colors - + Скинути кольори до типових Proxy host - + Хост проксі Proxy port - + Порт проксі Proxy login - + Логін проксі Proxy password - + Пароль проксі No proxy - + Без проксі Socks5 proxy - + Socks5 проксі HTTP proxy - + HTTP проксі System proxy settings - + Системні параметри проксі Select an action to change what key controls it - + Виберіть дію для зміни кнопки, що контролює дію Reset to default - + Скинути до типового Reset all binds - + Скинути всі прив'язки Game - + Гра Graphics - + Графіка Audio - + Аудіо Controls - + Керування Video Recording - + Запис відео Network - + Мережа Teams - Команди + Команди Schemes - + Схеми Weapons - Зброя + Зброя Frontend - + Фронтенд Custom colors - + Власні кольори Game audio - + Аудіо гри Frontend audio - + Аудіо фронтенду Account - + Акаунт Proxy settings - + Параметри проксі Miscellaneous - + Різне Updates - + Оновлення Check for updates - + Перевірити на оновлення Video recording options - + Параметри запису відео @@ -1305,23 +1411,23 @@ Search for a room: - + Шукати кімнату: Create room - + Створити кімнату Join room - + Приєднатись до кімнати Room state - + Стан кімнати Open server administration page - + Відкрити сторінку адміністрування сервера @@ -1332,7 +1438,7 @@ Teams will start on opposite sides of the terrain, two team colours max! - Команди почнуть гру на протилежних кінцях мапи, команди максимум двох кольорів! + Команди почнуть гру на протилежних кінцях карти, команди максимум двох кольорів! Land can not be destroyed! @@ -1400,7 +1506,7 @@ Disable land objects when generating random maps. - Вимкнути декорації при генеруванні випадкової мапи + Вимкнути декорації при генеруванні випадкової карти AI respawns on death. @@ -1444,23 +1550,23 @@ Add an indestructible border along the bottom - + Додати невразливу межу знизу None (Default) - + Немає (Типово) Wrap (World wraps) - + Перенос (на інший край) Bounce (Edges reflect) - + Відбиття (краї пружні) Sea (Edges connect to sea) - + Море (краї з'єднані з морем) @@ -1486,85 +1592,85 @@ PageSinglePlayer Play a quick game against the computer with random settings - + Грати швидку гру проти комп'ютера з випадковими параметрами Play a hotseat game against your friends, or AI teams - + Грати гарячу гру проти друзів, або комп'ютера Campaign Mode - + Режим кампанії Practice your skills in a range of training missions - + Відточіть навики в тренувальних місіях Watch recorded demos - + Переглянути записані демо Load a previously saved game - + Завантажити збережену гру PageTraining No description available - + Опис відсутній Select a mission! - + Виберіть місію! Pick the mission or training to play - + Виберіть місію або навчання для гри Start fighting - + Розпочати бій PageVideos Name - Назва + Назва Size - + Розмір %1 bytes - - + + %1 байт (in progress...) - + (в процесі...) encoding - + кодування uploading - + надсилання Date: %1 - + Дата: %1 Size: %1 - + Розмір: %1 @@ -1615,15 +1721,15 @@ Restrict Unregistered Players Join - + Заборонити вхід незареєстрованих гравців Show games in lobby - + Показувати ігри в вестибюлі Show games in-progress - + Показувати триваючі ігри @@ -1654,83 +1760,83 @@ Save password - + Зберегти пароль Save account name and password - + Зберегти ім'я і пароль Video is private - + Відео є приватним Record audio - + Звук Use game resolution - + Як у грі Visual effects - + Візуальні ефекти Sound - + Звук In-game sound effects - + Звукові ефекти в грі Music - + Музика In-game music - + Музика в грі Frontend sound effects - + Звукові ефети фронтенду Frontend music - + Музика фронтенду Team - + Команда Enable team tags by default - + Ввімкнути теги команд Hog - + Іжак Enable hedgehog tags by default - + Ввімкнути теги їжаків Health - + Здоров'я Enable health tags by default - + Ввімкнути теги здоров'я Translucent - + Напівпрозорість Enable translucent tags by default - + Ввімкнути напівпрозорі теги @@ -1801,27 +1907,27 @@ Red/Cyan grayscale - Черв./Блак. відтінки сірого + Черв./Блак. сіра гама Cyan/Red grayscale - Блак./Черв. відтінки сірого + Блак./Черв. сіра гама Red/Blue grayscale - Черв./Синій відтінки сірого + Черв./Синій сіра гама Blue/Red grayscale - Синій/Черв. відтінки сірого + Синій/Черв. сіра гама Red/Green grayscale - Черв./Зел. відтінки сірого + Черв./Зел. сіра гама Green/Red grayscale - Зел./Черв. відтінки сірого + Зел./Черв. сіра гама @@ -1856,11 +1962,11 @@ Videos - + Відео Description - + Опис @@ -2013,114 +2119,120 @@ There are videos that are currently being processed. Exiting now will abort them. Do you really want to quit? - + Зараз триває обробка відео. +Якщо зараз вийти це скасує обробку. +Дійсно вийти? Please provide either the YouTube account name or the email address associated with the Google Account. - + Вкажіть ім'я акаунта на YouTube або електронну адресу акаунта на Google. Account name (or email): - + Ім'я акаунта (або е-мейл): Password: - + Пароль: Video title: - + Заголовок відео: Video description: - + Опис відео: Tags (comma separated): - + Теги (через кому): Description - + Опис Nickname - Ім'я + Ім'я Format - + Формат Audio codec - + Кодек звуку Video codec - + Кодек відео Framerate - + Частота кадрів Bitrate (Kbps) - + Бітрейт (Kbps) This development build is 'work in progress' and may not be compatible with other versions of the game, while some features might be broken or incomplete! - + Ця збірка знаходиться в розробці і може бути несумісна з іншими версіями гри. Також певні функції можуть бути зламані або недороблені. Fullscreen - Повний екран + Повний екран Fullscreen Resolution - + Повноекранне розширення Windowed Resolution - + Розширення вікна Your Email - + Ваша пошта Summary - + Звіт Send system information - + Відіслати системні дані Type the security code: - + Введіть код безпеки: Revision - + Ревізія This program is distributed under the %1 - + Ця програма поширюється згідно з %1 This setting will be effective at next restart. - + Цей параметр застосується після перезапуску. Tip: %1 - + Порада: %1 Displayed tags above hogs and translucent tags - + Показувати теги над їжаками і напівпрозорі теги World Edge + Край світу + + + Script parameter @@ -2132,11 +2244,11 @@ hedgehog %1 - + їжак %1 anonymous - + анонімус @@ -2163,48 +2275,50 @@ Error while authenticating at google.com: - + Помилка авторизації на google.com: + Login or password is incorrect - + Логін або пароль невірні Error while sending metadata to youtube.com: - + Помилка відсилання метаданих на youtube.com: + Teams - Are you sure? - + Команди - Ви впевнені? Do you really want to delete the team '%1'? - + Ви дійсно хочете видалити команду '%1'? Cannot delete default scheme '%1'! - + Неможливо видалити типову схему '%1'! Please select a record from the list - + Виберіть запис зі списку Unable to start server - + Помилка запуску сервера Hedgewars - Error - + Hedgewars - Помилка Hedgewars - Success - + Hedgewars - Успіх All file associations have been set - + Файлові асоціації встановлено Cannot create directory %1 @@ -2216,165 +2330,166 @@ Video upload - Error - + Надсилання відео - Помилка Netgame - Error - + Мережна гра - Помилка Please select a server from the list - + Виберіть сервер зі списку Please enter room name - Введіть назву кімнати + Введіть назву кімнати Record Play - Error - + Відтворення запису - Помилка Please select record from the list - Выберіть запис зі списку + Виберіть запис зі списку Cannot rename to - + Неможливо перейменувати на Cannot delete file - + Неможливо видалити файл Room Name - Error - + Назва кімнати - Помилка Please select room from the list - Виберіть кімнату зі списку + Виберіть кімнату зі списку Room Name - Are you sure? - + Назва кімнати - Ви впевнені? The game you are trying to join has started. Do you still want to join the room? - Гра, до якої ви хочети при'єднатись вже почалась. + Гра, до якої ви хочети при'єднатись вже почалась. Ви все ще хочете ввійти в кімнату? Schemes - Warning - + Схеми - Увага Schemes - Are you sure? - + Схеми - Ви впевнені? Do you really want to delete the game scheme '%1'? - + Ви дійсно хочете видалити схему гри '%1'? Videos - Are you sure? - + Відео - Ви впевнені? Do you really want to delete the video '%1'? - + Ви дійсно хочете видалити відео '%1'? Do you really want to remove %1 file(s)? - - - - + + Ви дійсно хочете видалити '%1' файл? + Ви дійсно хочете видалити '%1' файли? + Ви дійсно хочете видалити '%1' файлів? Do you really want to cancel uploading %1? - + Ви дійсно хочете скасувати відсилання %1? File error - Помилка файлу + Помилка файлу Cannot open '%1' for writing - + Неможливо відкрити '%1' для запису Cannot open '%1' for reading - + Неможливо відкрити '%1' для читання Cannot use the ammo '%1'! - + Не можу використати боєприпаси '%1'! Weapons - Warning - + Зброя - Увага Cannot overwrite default weapon set '%1'! - + Неможливо перевизначити типовий набір зброї '%1'! Cannot delete default weapon set '%1'! - + Неможливо видалити типовий набір зброї '%1'! Weapons - Are you sure? - + Зброя - Ви впевнені? Do you really want to delete the weapon set '%1'? - + Ви дійсно хочете видалити набір зброї '%1'? Hedgewars - Nick not registered - + Hedgewars - Ім'я не зареєстроване System Information Preview - + Перегляд системної інформації Failed to generate captcha - + Не вдалось згенерувати капчу Failed to download captcha - + Не вдалось завантажити капчу Please fill out all fields. Email is optional. - + Заповніть всі поля, е-мейл не обов'язковий. Hedgewars - Warning - + Hedgewars - Увага Hedgewars - Information - + Hedgewars - Інформація Not all players are ready - + Не всі гравці готові Are you sure you want to start this game? Not all players are ready. - + Ви дійсно хочете розпочати цю гру? +Не всі гравці готові. QObject No description available - + Опис відсутній @@ -2437,136 +2552,140 @@ More info - + Більше інформації Set default options - + Задати типові налаштування Open videos directory - + Відкрити теку з відео Play - + Відтворити Upload to YouTube - + Надіслати на YouTube Cancel uploading - + Скасувати надсилання Restore default coding parameters - + Відновити типові параметри кодування Open the video directory in your system - + Відкрити теку з відеозаписами у вашій системі Play this video - + Відтворити це відео Delete this video - + Видалити це відео Upload this video to your Youtube account - + Відіслати це відео на ваш акаунт Youtube Reset - + Скинути Set the default server port for Hedgewars - + Задати типовий порт сервера для Hedgewars Invite your friends to your server in just 1 click! - + Запросіть друзів на ваш сервер одним кліком! Click to copy your unique server URL to your clipboard. Send this link to your friends and they will be able to join you. - + Клацніть щоб скопіювати унікальний URL сервера в буфер. Надішліть це посилання друзям, і вони зможуть приєднатися до вас. Start private server - + Запутити приватний сервер RoomNamePrompt Enter a name for your room. - + Вкажіть назву вашої кімнати. Cancel - Скасувати + Скасувати Create room - + Створити кімнату set password - + задати пароль RoomsListModel In progress - В процесі + В процесі Room Name - Назва Кімнати + Назва Кімнати C - Кл + Кл T - Км + Км Owner - Власник + Власник Map - Мапа + Карта Rules - Правила + Правила Weapons - Зброя + Зброя Random Map - Випадкова Мапа + Випадкова Карта Random Maze - Випадковий лабіринт + Випадковий лабіринт Hand-drawn - + Намальована вручну Script + Скрипт + + + Random Perlin @@ -2574,19 +2693,19 @@ SeedPrompt The map seed is the basis for all random values generated by the game. - + Висів карти є основою для всіх випадкових величин, згенерованих грою. Cancel - Скасувати + Скасувати Set seed - + Вказати висів Close - + Закрити @@ -2613,18 +2732,32 @@ copy of - копія + копія + + + copy of %1 + TCPBase Unable to start server at %1. - + Неможливо запустити сервер на %1. Unable to run engine at %1 Error code: %2 + Неможливо запустити двигун на %1 +Код помилки: %2 + + + The game engine died unexpectedly! +(exit code %1) + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%2' button in the main menu! @@ -2632,22 +2765,22 @@ TeamSelWidget At least two teams are required to play! - + Щоб грати потрібно хоча б дві команди! ThemePrompt Cancel - Скасувати + Скасувати Search for a theme: - + Шукати тему: Use selected theme - + Використати вибрану тему @@ -2686,7 +2819,7 @@ find hedgehog - знайти їжачка + знайти їжачка ammo menu @@ -2810,14 +2943,22 @@ mute audio - + вимкнути звук record - + запис hedgehog info + про їжака + + + autocam / find hedgehog + + + + speed up replay @@ -2825,19 +2966,19 @@ binds (categories) Movement - + Переміщення Weapons - Зброя + Зброя Camera - + Камера Miscellaneous - + Різне @@ -2868,7 +3009,7 @@ Move the camera to the active hog: - Перемістити камеру до активного їжака: + Перемістити камеру до активного їжака: Move the cursor or camera without using the mouse: @@ -2904,10 +3045,18 @@ Record video: - + Записати відео: Hedgehog movement + Рух їжака + + + Toggle automatic camera / refocus on active hedgehog: + + + + Demo replay: @@ -2971,7 +3120,7 @@ Backspace - + Backspace Tab @@ -2999,63 +3148,63 @@ Numpad 0 - + Numpad 0 Numpad 1 - + Numpad 1 Numpad 2 - + Numpad 2 Numpad 3 - + Numpad 3 Numpad 4 - + Numpad 4 Numpad 5 - + Numpad 5 Numpad 6 - + Numpad 6 Numpad 7 - + Numpad 7 Numpad 8 - + Numpad 8 Numpad 9 - + Numpad 9 Numpad . - + Numpad . Numpad / - + Numpad / Numpad * - + Numpad * Numpad - - + Numpad - Numpad + - + Numpad + Enter @@ -3103,7 +3252,7 @@ Num lock - + Num lock Caps lock @@ -3203,11 +3352,11 @@ Left trigger - + Лівий перемикач Right trigger - + Правий перемикач Right stick (Down) @@ -3234,122 +3383,178 @@ server Restricted - + Обмежено Not room master - + Не власник кімнати Corrupted hedgehogs info - + Пошкоджені дані їжака too many teams - + забагато команд too many hedgehogs - + забагато їжаків There's already a team with same name in the list - + Команда з такою назвою вже є у списку round in progress - + раунд триває restricted - + обмежено REMOVE_TEAM: no such team - + REMOVE_TEAM: немає такої команди Not team owner! - + Не власник команди! Less than two clans! - + Менше двох кланів! Illegal room name - + неприпустима назва кімнати Room with such name already exists - + Кімната з такою назвою вже існує Nickname already chosen - + Нікнейм вже вибрано Illegal nickname - + недопустимий нікнейм Protocol already known - + Протокол вже відомий Bad number - + Погане число Nickname is already in use - + Нікнейм вже використовується No checker rights - + Немає прав контролера Authentication failed - + Помилка авторизації 60 seconds cooldown after kick - + 60 секунд очікування після копняка kicked - + копнутий Ping timeout - + Час відклику bye - + бувай No such room - + Немає такої кімнати Room version incompatible to your hedgewars version - + Версія кімнати несумісна з версією вашої гри Joining restricted - + Вхід обмежено Registered users only - + Лише для зареєстрованих користувачів You are banned in this room - + Ви заблоковані в цій кімнаті Empty config entry + Порожній конфігураційний запис + + + You already have voted + + + + Voting closed + + + + New voting started + + + + Voting expired + + + + kick + + + + map + + + + pause + пауза + + + Reconnected too fast + + + + Warning! Chat flood protection activated + + + + Excess flood + + + + Game messages flood detected - 1 + + + + Game messages flood detected - 2 + + + + Warning! Joins flood protection activated + + + + There's no voting going on diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/hedgewars_zh_CN.ts --- a/share/hedgewars/Data/Locale/hedgewars_zh_CN.ts Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/hedgewars_zh_CN.ts Tue Nov 10 20:43:13 2015 +0100 @@ -4,7 +4,7 @@ About - + Unknown Compiler @@ -20,76 +20,76 @@ AmmoSchemeModel - + new - - copy of + + copy of %1 BanDialog - + permanent - - - IP - IP - - - - Nick - - - - - IP/Nick - - - - Reason - + + IP + IP + Nick + + + + + IP/Nick + + + + + Reason + + + + Duration - + Ok - + Cancel 取消 - + you know why - + Warning - + Please, specify %1 - + nickname @@ -97,7 +97,7 @@ DataManager - + Use Default @@ -194,47 +194,47 @@ HWApplication - - + + %1 minutes - + %1 hour - - - - %1 hours - - - - - + + + %1 hours + + + + + + %1 day - - - + + + %1 days - + Scheme '%1' not supported @@ -244,7 +244,67 @@ - + + Usage + command-line + + + + + OPTION + command-line + + + + + CONNECTSTRING + command-line + + + + + Options + command-line + + + + + Display this help + command-line + + + + + Custom path for configuration data and user data + command-line + + + + + Custom path to the game data folder + command-line + + + + + Hedgewars can use a %1 (e.g. "%2") to connect on start. + command-line + + + + + Malformed option argument: %1 + command-line + + + + + Unknown option argument: %1 + command-line + + + + Failed to open data directory: %1 @@ -263,67 +323,67 @@ HWChatWidget - + %1 has joined - + %1 has left - + %1 has left (%2) - + %1 has been removed from your ignore list - + %1 has been added to your ignore list - + %1 has been removed from your friends list - + %1 has been added to your friends list - + Stylesheet imported from %1 - + Enter %1 if you want to use the current StyleSheet in future, enter %2 to reset! - + Couldn't read %1 - + StyleSheet discarded - + StyleSheet saved to %1 - + Failed to save StyleSheet to %1 @@ -442,35 +502,35 @@ - + Hedgewars Demo File File Types - + Hedgewars Save File File Types - + Demo name - + Demo name: - + This page requires an internet connection. - + Cannot save record to file %1 无法录入文件 %1 @@ -478,13 +538,25 @@ HWGame - - + + A Fatal ERROR occured! - The game engine had to stop. + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%1' button in the main menu! + +Last two engine messages: +%2 + + + + + en.txt zh_CN.txt - + Cannot open demofile %1 DEMO %1 打不开 @@ -492,158 +564,168 @@ HWMapContainer - + Small tunnels - + Medium tunnels - + Seed - + Map type: - - Image map - - - - Mission map + Image map - Hand-drawn + Mission map - Randomly generated + Hand-drawn + Randomly generated + + + + Random maze - + + Random perlin + + + + Random - + Map preview: - + Load map drawing - + Edit map drawing - - All - 全部 - - - - Small - 小型 - - - Medium - 中型 + All + 全部 - Large - 大型 + Small + 小型 - Cavern - 洞穴 + Medium + 中型 + Large + 大型 + + + + Cavern + 洞穴 + + + Wacky 曲折 - - Large tunnels - - - - - Small islands - - - - Medium islands + Large tunnels + Small islands + + + + + Medium islands + + + + Large islands - + Map size: - + Maze style: - + + Style: + + + + Mission: - + Map: - - + + Theme: %1 - + Load drawn map - + Drawn Maps - + All files @@ -669,43 +751,48 @@ HWNewNet - + User quit - - Remote host has closed connection - - - - The host was not found. Please check the host name and port settings. - 错误没找到这个主机。请检查主机名和端口设置。 + Remote host has closed connection + + The host was not found. Please check the host name and port settings. + 错误没找到这个主机。请检查主机名和端口设置。 + + + Connection refused 连接被拒绝 - + The server is too old. Disconnecting now. - + + Server authentication error + + + + %1 *** %2 has left - + %1 *** %2 has left (%3) - - + + %1 *** %2 has joined the room @@ -715,12 +802,12 @@ 退出原因: - + Room destroyed 房间损坏 - + You got kicked 被踢出 @@ -836,7 +923,7 @@ MapModel - + No description available. @@ -930,12 +1017,17 @@ PageDataDownload - + + Open packages directory + + + + Loading, please wait. - + This page requires an internet connection. @@ -974,33 +1066,38 @@ - Load - 读取 + Optimize + + Load + 读取 + + + Save 保存 - + Load drawn map - - + + Drawn Maps - - + + All files - + Save drawn map @@ -1086,55 +1183,57 @@ Save 保存 - - + + The best shot award was won by <b>%1</b> with <b>%2</b> pts. - + + + - + The best killer is <b>%1</b> with <b>%2</b> kills in a turn. - + A total of <b>%1</b> hedgehog(s) were killed during this round. - + (%1 kill) - + (%1 %2) - + <b>%1</b> thought it's good to shoot his own hedgehogs with <b>%2</b> pts. - + <b>%1</b> killed <b>%2</b> of his own hedgehogs. - + <b>%1</b> was scared and skipped turn <b>%2</b> times. @@ -1160,72 +1259,72 @@ PageMain - + Play a game on a single computer - + Play a game across a network - + Play local network game - + Play a game across a local area network - + Play official network game - + Play a game on an official server - + Read about who is behind the Hedgewars Project - - Feedback - - - + Feedback + + + + Leave a feedback here reporting issues, suggesting features or just saying how you like Hedgewars - - Downloadable Content - - - + Downloadable Content + + + + Access the user created content downloadable from our website - + Exit game - + Manage videos recorded from game - + Edit game preferences @@ -1513,27 +1612,27 @@ PageRoomsList - + Search for a room: - + Create room - + Join room - + Room state - + Open server administration page @@ -1546,14 +1645,14 @@ 加入 - + %1 players online - + Admin features 管理员功能 @@ -1696,37 +1795,37 @@ - + None (Default) - - Wrap (World wraps) - - - - Bounce (Edges reflect) + Wrap (World wraps) + Bounce (Edges reflect) + + + + Sea (Edges connect to sea) - + Copy - + New 新游戏 - + Delete 删除 @@ -1813,44 +1912,44 @@ PageVideos - + Name - + Size - + %1 bytes - + (in progress...) - - Date: %1 - - - + Date: %1 + + + + Size: %1 - + encoding - + uploading @@ -1858,7 +1957,7 @@ QAction - + Kick @@ -1882,49 +1981,49 @@ - + Info 信息 - + Ban 屏蔽 - + Follow - - + + Ignore - - + + Add friend - + Unignore - + Remove friend - + Show games in lobby - + Show games in-progress @@ -2181,7 +2280,7 @@ 城堡模式 - + Playing teams 玩家队伍 @@ -2201,12 +2300,12 @@ 基本设置 - + Videos - + Description @@ -2269,12 +2368,12 @@ FPS 上限 - + Revision - + This program is distributed under the %1 @@ -2388,7 +2487,12 @@ - + + Script parameter + + + + Scheme Name: 设置名称: @@ -2485,12 +2589,13 @@ - + This development build is 'work in progress' and may not be compatible with other versions of the game, while some features might be broken or incomplete! - + + Tip: %1 @@ -2560,12 +2665,12 @@ QMessageBox - + Error 错误 - + Cannot use the ammo '%1'! @@ -2581,7 +2686,7 @@ - + Cannot delete default scheme '%1'! @@ -2606,19 +2711,19 @@ 服务器连接丢失 - + Not all players are ready - + Are you sure you want to start this game? Not all players are ready. - + Hedgewars - Error @@ -2644,18 +2749,18 @@ - + Hedgewars - Success - + All file associations have been set - + File association failed. @@ -2723,80 +2828,80 @@ - + Room Name - Error - + Please select room from the list - + Room Name - Are you sure? - + The game you are trying to join has started. Do you still want to join the room? - + Schemes - Warning - + Schemes - Are you sure? - + Do you really want to delete the game scheme '%1'? - - - - Videos - Are you sure? - - - + + + Videos - Are you sure? + + + + Do you really want to delete the video '%1'? - + Do you really want to remove %1 file(s)? - + Do you really want to cancel uploading %1? - - - + + + File error - + Cannot open '%1' for writing - - + + Cannot open '%1' for reading @@ -2827,12 +2932,12 @@ - + Hedgewars - Warning - + Hedgewars - Information @@ -2840,8 +2945,8 @@ QObject - - + + No description available @@ -2932,14 +3037,14 @@ - + Cancel 取消 - - + + Delete 删除 @@ -2964,44 +3069,44 @@ - + Open videos directory - + Open the video directory in your system - + Play - + Play this video - + Delete this video - - - + + + Upload to YouTube - + Upload this video to your Youtube account - + Cancel uploading @@ -3088,6 +3193,11 @@ + Random Perlin + + + + Hand-drawn @@ -3146,28 +3256,38 @@ - copy of + copy of %1 TCPBase - + Unable to start server at %1. - + Unable to run engine at %1 Error code: %2 + + + The game engine died unexpectedly! +(exit code %1) + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%2' button in the main menu! + + TeamSelWidget - + At least two teams are required to play! @@ -3302,6 +3422,11 @@ 定时5秒 + + autocam / find hedgehog + + + zoom in @@ -3328,11 +3453,16 @@ + speed up replay + + + + hedgehog info - + record @@ -3342,9 +3472,8 @@ 退出 - find hedgehog - 找到 刺猬 + 找到 刺猬 @@ -3469,7 +3598,7 @@ - Move the camera to the active hog: + Toggle automatic camera / refocus on active hedgehog: @@ -3509,11 +3638,16 @@ + Demo replay: + + + + Toggle labels above hedgehogs: - + Record video: @@ -3876,44 +4010,44 @@ - + Keyboard - + Axis - - + + (Up) - - + + (Down) - + Hat - + (Left) - + (Right) - + Button @@ -3921,152 +4055,222 @@ server - + Restricted - - Not room master - - - - - Corrupted hedgehogs info - - - - - too many teams - - - - - too many hedgehogs - - - - - There's already a team with same name in the list - - - - - round in progress - - - - - restricted - - - - - REMOVE_TEAM: no such team - - - - - Not team owner! - - - - Less than two clans! + Not room master - Illegal room name + Corrupted hedgehogs info - Room with such name already exists + too many teams - Nickname already chosen + too many hedgehogs - Illegal nickname + There's already a team with same name in the list - Protocol already known + round in progress - Bad number + restricted - Nickname is already in use + REMOVE_TEAM: no such team - No checker rights - + Not team owner! + + + + + Less than two clans! + + + + + You already have voted + + + + + Voting closed + + + + + New voting started + + + + + Voting expired + + + + + kick + + + + + map + + + + + pause + 暂停 - Authentication failed + Illegal room name - 60 seconds cooldown after kick + Room with such name already exists - kicked + Nickname already chosen - Ping timeout + Illegal nickname - bye + Protocol already known - No such room + Bad number - Room version incompatible to your hedgewars version + Nickname is already in use - Joining restricted + No checker rights - Registered users only + Authentication failed - You are banned in this room + 60 seconds cooldown after kick + kicked + + + + + Reconnected too fast + + + + + Ping timeout + + + + + bye + + + + + No such room + + + + + Room version incompatible to your hedgewars version + + + + + Joining restricted + + + + + Registered users only + + + + + You are banned in this room + + + + + Warning! Chat flood protection activated + + + + + Excess flood + + + + + Game messages flood detected - 1 + + + + + Game messages flood detected - 2 + + + + + Warning! Joins flood protection activated + + + + + There's no voting going on + + + + Empty config entry diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/hedgewars_zh_TW.ts --- a/share/hedgewars/Data/Locale/hedgewars_zh_TW.ts Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/hedgewars_zh_TW.ts Tue Nov 10 20:43:13 2015 +0100 @@ -22,7 +22,7 @@ - copy of + copy of %1 @@ -205,6 +205,56 @@ Please check your installation! + + Usage + command-line + + + + OPTION + command-line + + + + CONNECTSTRING + command-line + + + + Options + command-line + + + + Display this help + command-line + + + + Custom path for configuration data and user data + command-line + + + + Custom path to the game data folder + command-line + + + + Hedgewars can use a %1 (e.g. "%2") to connect on start. + command-line + + + + Malformed option argument: %1 + command-line + + + + Unknown option argument: %1 + command-line + + HWAskQuitDialog @@ -394,6 +444,17 @@ Cannot open demofile %1 DEMO %1 打不開 + + A Fatal ERROR occured! - The game engine had to stop. + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%1' button in the main menu! + +Last two engine messages: +%2 + + HWMapContainer @@ -521,6 +582,14 @@ Theme: %1 + + Random perlin + + + + Style: + + HWNetServersModel @@ -587,6 +656,10 @@ The server is too old. Disconnecting now. + + Server authentication error + + HWPasswordDialog @@ -767,6 +840,10 @@ This page requires an internet connection. + + Open packages directory + + PageDrawMap @@ -818,6 +895,10 @@ Ellipse + + Optimize + + PageEditTeam @@ -876,9 +957,11 @@ Ranking - + The best shot award was won by <b>%1</b> with <b>%2</b> pts. - + + + The best killer is <b>%1</b> with <b>%2</b> kills in a turn. @@ -2061,6 +2144,10 @@ World Edge + + Script parameter + + QLineEdit @@ -2504,6 +2591,10 @@ Script + + Random Perlin + + SeedPrompt @@ -2547,7 +2638,7 @@ - copy of + copy of %1 @@ -2562,6 +2653,15 @@ Error code: %2 + + The game engine died unexpectedly! +(exit code %1) + +We are very sorry for the inconvenience :( + +If this keeps happening, please click the '%2' button in the main menu! + + TeamSelWidget @@ -2677,7 +2777,7 @@ find hedgehog - 尋找刺蝟 + 尋找刺蝟 ammo menu @@ -2755,6 +2855,14 @@ hedgehog info + + autocam / find hedgehog + + + + speed up replay + + binds (categories) @@ -2803,7 +2911,7 @@ Move the camera to the active hog: - 移動鏡頭到選中刺蝟: + 移動鏡頭到選中刺蝟: Move the cursor or camera without using the mouse: @@ -2845,6 +2953,14 @@ Hedgehog movement + + Toggle automatic camera / refocus on active hedgehog: + + + + Demo replay: + + binds (keys) @@ -3287,5 +3403,61 @@ Empty config entry + + You already have voted + + + + Voting closed + + + + New voting started + + + + Voting expired + + + + kick + + + + map + + + + pause + 暫停 + + + Reconnected too fast + + + + Warning! Chat flood protection activated + + + + Excess flood + + + + Game messages flood detected - 1 + + + + Game messages flood detected - 2 + + + + Warning! Joins flood protection activated + + + + There's no voting going on + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/it.lua --- a/share/hedgewars/Data/Locale/it.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/it.lua Tue Nov 10 20:43:13 2015 +0100 @@ -1,29 +1,43 @@ locale = { + ["!!!"] = "!!!", + ["???"] = "???", ["..."] = "...", [":("] = ":(", - ["!!!"] = "!!!", ["011101000"] = "011101000", ["011101001"] = "011101001", +-- ["+1 to a Bottom Feeder for killing anyone"] = "", -- Mutant +-- ["+1 to a Mutant for killing anyone"] = "", -- Mutant +-- ["-1 to anyone for a suicide"] = "", -- Mutant +-- ["+2 for becoming a Mutant"] = "", -- Mutant ["30 minutes later..."] = "30 minuti più tardi...", ["About a month ago, a cyborg came and told us that you're the cannibals!"] = "Circa un mese fa, è arrivato un cyborg e ci ha detto che siete voi i cannibali!", ["Accuracy Bonus!"] = "Bonus Precisione!", ["Ace"] = "Asso", ["Achievement Unlocked"] = "Archivio Sbloccato", ["A Classic Fairytale"] = "Una favola classica", - ["???"] = "???", ["Actually, you aren't worthy of life! Take this..."] = "In realtà, non siete degni di vivere! Prendete questo...", ["A cy-what?"] = "Un cy-cosa?", +-- ["Advanced Repositioning Mode"] = "", -- Construction_Mode ["Adventurous"] = "Avventuroso", +-- ["a frenetic Hedgewars mini-game"] = "", -- Frenzy ["Africa"] = "Africa", -- ["After Leaks A Lot betrayed his tribe, he joined the cannibals..."] = "", -- A_Classic_Fairytale:first_blood -- ["After the shock caused by the enemy spy, Leaks A Lot and Dense Cloud went hunting to relax."] = "", -- A_Classic_Fairytale:shadow ["Again with the 'cannibals' thing!"] = "Ancora colla storia dei 'cannibali'!", +-- ["Aggressively removes enemy hedgehogs."] = "", -- Construction_Mode ["a Hedgewars challenge"] = "una sfida Hedgewars", ["a Hedgewars mini-game"] = "un mini-gioco di Hedgewars", +-- ["a Hedgewars tag game"] = "", -- Mutant +-- ["AHHh, home sweet home. Made it in %d seconds."] = "", -- ClimbHome ["Aiming Practice"] = "Pratica la tua mira", +-- ["Air Attack"] = "", -- Construction_Mode -- ["A leap in a leap"] = "", -- A_Classic_Fairytale:first_blood ["A little gift from the cyborgs"] = "Un piccolo regalo dai cyborg", ["All gone...everything!"] = "E' finito... tutto!", +-- ["Allows free teleportation between other nodes."] = "", -- Construction_Mode +-- ["Allows placement of girders, rubber-bands, mines, sticky mines and barrels."] = "", -- Construction_Mode +-- ["Allows placement of structures."] = "", -- Construction_Mode +-- ["Allows the placement of weapons, utiliites, and health crates."] = "", -- Construction_Mode ["All right, we just need to get to the other side of the island!"] = "Va bene, dobbiamo solo raggiungere l'altro lato dell'isola!", ["All walls touched!"] = "Tutti i muri toccati!", ["Ammo Depleted!"] = "Munizioni scarse!", @@ -38,8 +52,11 @@ ["And so they discovered that cyborgs weren't invulnerable..."] = "E così scoprirono che i cyborg non erano invulnerabili...", -- ["And where's all the weed?"] = "", -- A_Classic_Fairytale:dragon ["And you believed me? Oh, god, that's cute!"] = "E mi credi? Oddio, che bello!", - ["Anno 1032: [The explosion will make a strong push ~ wide range, wont affect hogs close to the target]"] = "Anno 1032: [L'esplosione genererà un forte colpo a lungo raggio, non influierà sui ricci vicini all'obiettivo]", + +-- ["Anno 1032: [The explosion will make a strong push ~ Wide range, wont affect hogs close to the target]"] = "", -- Continental_supplies ["Antarctica"] = "Antartico", +-- ["Antarctic summer: - Will give you one girder/mudball and two sineguns/portals every fourth turn."] = "", -- Continental_supplies +-- ["Area"] = "", -- Continental_supplies ["Are we there yet?"] = "Siamo già lì?", ["Are you accusing me of something?"] = "Mi stai accusando di qualcosa?", ["Are you saying that many of us have died for your entertainment?"] = "Stai dicendo che molti di noi sono morti per il tuo divertimento?", @@ -59,27 +76,35 @@ ["[Backspace]"] = "[Cancella]", -- ["Backstab"] = "", -- A_Classic_Fairytale:backstab -- ["Bad Team"] = "", -- User_Mission_-_The_Great_Escape +-- ["Ballgun"] = "", -- Construction_Mode ["Bamboo Thicket"] = "Boschetto di Bambù", ["Barrel Eater!"] = "Mangiatore di Barili!", ["Barrel Launcher"] = "Lanciatore di Barili", +-- ["Barrel Placement Mode"] = "", -- Construction_Mode +-- ["Baseball Bat"] = "", -- Construction_Mode ["Baseballbat"] = "Mazza da baseball", ["Bat balls at your enemies and|push them into the sea!"] = "Lancia delle palline ai tuoi nemici|e spingili in acqua!", ["Bat your opponents through the|baskets and out of the map!"] = "Manda (colpendoli) i tuoi nemici|in acqua attraverso i canestri laterali!", +-- ["Bazooka"] = "", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 ["Bazooka Training"] = "Addestramento sull'utilizzo del Bazooka", -- ["Beep Loopers"] = "", -- A_Classic_Fairytale:queen ["Best laps per team: "] = "Tempo migliore per squadra: ", ["Best Team Times: "] = "Tempi della squadra migliore: ", ["Beware, though! If you are slow, you die!"] = "Attenzione, comunque! Se siete lenti, morirete!", +-- ["Bio-Filter"] = "", -- Construction_Mode ["Biomechanic Team"] = "Squadra biomeccanica", +-- ["Birdy"] = "", -- Construction_Mode -- ["Blender"] = "", -- A_Classic_Fairytale:family -- ["Bloodpie"] = "", -- A_Classic_Fairytale:backstab -- ["Bloodrocutor"] = "", -- A_Classic_Fairytale:shadow -- ["Bloodsucker"] = "", -- A_Classic_Fairytale:shadow ["Bloody Rookies"] = "Reclute Sanguinose", +-- ["Blowtorch"] = "", -- Construction_Mode, Frenzy +-- ["Blue Team"] = "", -- User_Mission_-_Dangerous_Ducklings -- ["Bone Jackson"] = "", -- A_Classic_Fairytale:backstab -- ["Bonely"] = "", -- A_Classic_Fairytale:shadow + ["BOOM!"] = "KABOOM!", ["Boom!"] = "Kaboom!", - ["BOOM!"] = "KABOOM!", ["Boss defeated!"] = "Boss sconfitto!", ["Boss Slayer!"] = "Boss Uccisore!", -- ["Brain Blower"] = "", -- A_Classic_Fairytale:journey @@ -89,6 +114,7 @@ -- ["Brain Teaser"] = "", -- A_Classic_Fairytale:backstab -- ["Brutal Lily"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil ["Brutus"] = "Bruto", +-- ["Build a fortress and destroy your enemy."] = "", -- Construction_Mode ["Build a track and race."] = "Costruisci una pista e corri.", ["Bullseye"] = "Bersaglio", -- A_Classic_Fairytale:dragon ["But it proved to be no easy task!"] = "Ma si è dimostrato essere un compito non facile!", @@ -99,6 +125,7 @@ ["But why would they help us?"] = "Ma perché dovrebbero aiutarci?", ["But you're cannibals. It's what you do."] = "Ma voi siete cannibali. E' quello che fate.", ["But you said you'd let her go!"] = "Avete detto che l'avreste lasciata andare!", +-- ["Cake"] = "", -- Construction_Mode -- ["Call me Beep! Well, 'cause I'm such a nice...person!"] = "", -- A_Classic_Fairytale:family ["Cannibals"] = "Cannibali", ["Cannibal Sentry"] = "Sentinella cannibale", @@ -108,8 +135,15 @@ -- ["Carol"] = "", -- A_Classic_Fairytale:family ["CHALLENGE COMPLETE"] = "SFIDA COMPLETATA", ["Change Weapon"] = "Cambia Arma", +-- ["changing range from %i%% to %i%% with period of %i msec"] = "", -- Gravity ["Choose your side! If you want to join the strange man, walk up to him.|Otherwise, walk away from him. If you decide to att...nevermind..."] = "Scegli da che parte vuoi stare! Se vuoi stare con quell'uomo strano, vai con lui.|Altrimenti, allontanatene. Se decidi di attacc... niente...", +-- ["Cleaver"] = "", -- Construction_Mode +-- ["Cleaver Placement Mode"] = "", -- Construction_Mode +-- ["Climber"] = "", -- ClimbHome +-- ["Climb Home"] = "", -- ClimbHome +-- ["Clowns"] = "", -- User_Mission_-_Nobody_Laugh ["Clumsy"] = "Goffo", +-- ["Cluster Bomb"] = "", -- Construction_Mode -- ["Cluster Bomb MASTER!"] = "", -- Basic_Training_-_Cluster_Bomb ["Cluster Bomb Training"] = "Addestramento bomba a grappolo", ["Codename: Teamwork"] = "Nome in Codice: Lavoro di Squadra", @@ -124,17 +158,24 @@ ["Complete the track as fast as you can!"] = "Completa la pista più veloce che puoi!", -- ["COMPLETION TIME"] = "", -- User_Mission_-_Rope_Knock_Challenge ["Configuration accepted."] = "Configurazione accettata", + ["Congratulations!"] = "Complimenti!", ["Congratulations"] = "Complimenti", - ["Congratulations!"] = "Complimenti!", -- ["Congratulations! You needed only half of time|to eliminate all targets."] = "", -- Basic_Training_-_Cluster_Bomb -- ["Congratulations! You've completed the Rope tutorial! |- Tutorial ends in 10 seconds!"] = "", -- Basic_Training_-_Rope ["Congratulations! You've eliminated all targets|within the allowed time frame."] = "Complimenti! Hai distrutto tutti gli obiettivi|entro il tempo previsto.", +-- ["CONSTRUCTION MODE"] = "", -- Construction_Mode +-- ["Construction Station"] = "", -- Construction_Mode -- ["Continental supplies"] = "", -- Continental_supplies ["Control pillars to score points."] = "Ottieni il controllo dei pilastri per guadagnare punti.", +-- ["Core"] = "", -- Construction_Mode -- ["Corporationals"] = "", -- A_Classic_Fairytale:queen -- ["Corpsemonger"] = "", -- A_Classic_Fairytale:shadow ["Corpse Thrower"] = "Lanciatore di cadaveri", +-- ["Cost"] = "", -- Construction_Mode +-- ["Crate Placement Tool"] = "", -- Construction_Mode -- ["Crates Left:"] = "", -- User_Mission_-_RCPlane_Challenge +-- ["Cricket time: [Drop a fireable mine! ~ Will work if fired close to your hog & far away from enemy ~ 1 sec]"] = "", -- Continental_supplies +-- ["Current setting is "] = "", -- Gravity ["Cybernetic Empire"] = "Impero Cibernetico", ["Cyborg. It's what the aliens call themselves."] = "Cyborg. E' come gli alieni chiamano loro stessi.", -- ["Dahmer"] = "", -- A_Classic_Fairytale:backstab @@ -142,15 +183,19 @@ ["DAMMIT, ROOKIE! GET OFF MY HEAD!"] = "MALEDIZIONE, RECLUTA! VIA DALLA MIA TESTA!", ["Dangerous Ducklings"] = "Anatroccoli Pericolosi", ["Deadweight"] = "Peso morto", - ["Defeat the cannibals"] = "Sconfiggi i cannibali", - ["Defeat the cannibals!|"] = "Sconfiggi i cannibali!|", +-- ["Decrease"] = "", -- Continental_supplies -- ["Defeat the cannibals!|Grenade hint: set the timer with [1-5], aim with [Up]/[Down] and hold [Space] to set power"] = "", -- A_Classic_Fairytale:shadow + ["Defeat the cannibals!|"] = "Sconfiggi i cannibali!|", + ["Defeat the cannibals"] = "Sconfiggi i cannibali", ["Defeat the cyborgs!"] = "Sconfiggi i cyborg!", +-- ["Defend your core from the enemy."] = "", -- Construction_Mode -- ["Defend yourself!|Hint: You can get tips on using weapons by moving your mouse over them in the weapon selection menu"] = "", -- A_Classic_Fairytale:shadow +-- ["Dematerializes weapons and equipment carried by enemy hedgehogs."] = "", -- Construction_Mode ["Demolition is fun!"] = "Demolire è divertente!", -- ["Dense Cloud"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united -- ["Dense Cloud must have already told them everything..."] = "", -- A_Classic_Fairytale:shadow ["Depleted Kamikaze!"] = "Kamikaze Esaurito!", +-- ["Desert Eagle"] = "", -- Construction_Mode, A_Space_Adventure:death02 -- ["Destroy him, Leaks A Lot! He is responsible for the deaths of many of us!"] = "", -- A_Classic_Fairytale:first_blood ["Destroy invaders to score points."] = "Distruggi gli invasori per guadagnare dei punti.", -- ["Destroy the targets!|Hint: Select the Shoryuken and hit [Space]|P.S. You can use it mid-air."] = "", -- A_Classic_Fairytale:first_blood @@ -164,14 +209,17 @@ ["Do not laugh, inexperienced one, for he speaks the truth!"] = "Non ridere, pivello, perché lui dice la verità!", -- ["Do not let his words fool you, young one! He will stab you in the back as soon as you turn away!"] = "", -- A_Classic_Fairytale:first_blood -- ["Do the deed"] = "", -- A_Classic_Fairytale:first_blood + ["DOUBLE KILL"] = "DOPPIA UCCISIONE", ["Double Kill!"] = "Doppia Uccisione!", - ["DOUBLE KILL"] = "DOPPIA UCCISIONE", ["Do you have any idea how valuable grass is?"] = "Hai una pallida idea di quanto vale l'erba?", ["Do you think you're some kind of god?"] = "Pensi di essere un qualche dio?", -- ["Dragon's Lair"] = "", -- A_Classic_Fairytale:dragon +-- ["Drill Rocket"] = "", -- Construction_Mode -- ["Drills"] = "", -- A_Classic_Fairytale:backstab +-- ["Drill Strike"] = "", -- Construction_Mode ["Drone Hunter!"] = "Cacciatore di Droni!", --- ["Drop a bomb: [drop some heroic wind that will turn into a bomb on impact]"] = "", -- Continental_supplies +-- ["Drop a bomb: [Drop some heroic wind that will turn into a bomb on impact]"] = "", -- Continental_supplies + ["Drowner"] = "Affogato", -- ["Dude, all the plants are gone!"] = "", -- A_Classic_Fairytale:family -- ["Dude, can you see Ramon and Spiky?"] = "", -- A_Classic_Fairytale:journey @@ -181,11 +229,15 @@ ["Dude, where are we?"] = "Ehi, dove siamo?", -- ["Dude, wow! I just had the weirdest high!"] = "", -- A_Classic_Fairytale:backstab ["Duration"] = "Durata", --- ["Dust storm: [Deals 20 damage to all enemies in the circle]"] = "", -- Continental_supplies +-- ["Dust storm: [Deals 15 damage to all enemies in the circle]"] = "", -- Continental_supplies + +-- ["Dynamite"] = "", -- Construction_Mode +-- ["Each turn is only ONE SECOND!"] = "", -- Frenzy ["Each turn you get 1-3 random weapons"] = "In ogni turno hai da 1 a 3 armi casuali", ["Each turn you get one random weapon"] = "In ogno turno hai una sola arma casuale", +-- ["Eagle Eye: [Blink to the impact ~ One shot]"] = "", -- Continental_supplies + ["Eagle Eye"] = "Occhio di falco", --- ["Eagle Eye: [Blink to the impact ~ one shot]"] = "", -- Continental_supplies -- ["Ear Sniffer"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:epil -- ["Elderbot"] = "", -- A_Classic_Fairytale:family -- ["Elimate your captor."] = "", -- User_Mission_-_The_Great_Escape @@ -208,8 +260,9 @@ -- ["Every single time!"] = "", -- A_Classic_Fairytale:dragon -- ["Everything looks OK..."] = "", -- A_Classic_Fairytale:enemy -- ["Exactly, man! That was my dream."] = "", -- A_Classic_Fairytale:backstab +-- ["Extra Damage"] = "", -- Construction_Mode +-- ["Extra Time"] = "", -- Construction_Mode -- ["Eye Chewer"] = "", -- A_Classic_Fairytale:journey --- ["INSANITY"] = "", -- Mutant -- ["Family Reunion"] = "", -- A_Classic_Fairytale:family ["Fastest lap: "] = "Giro migliore: ", ["Feeble Resistance"] = "Resistenza Finale", @@ -219,24 +272,29 @@ -- ["Femur Lover"] = "", -- A_Classic_Fairytale:shadow -- ["Fierce Competition!"] = "", -- Space_Invasion -- ["Fiery Water"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united +-- ["Filthy Blue"] = "", -- User_Mission_-_Dangerous_Ducklings -- ["Find your tribe!|Cross the lake!"] = "", -- A_Classic_Fairytale:dragon -- ["Finish your training|Hint: Animations can be skipped with the [Precise] key."] = "", -- A_Classic_Fairytale:first_blood --- ["Fire a mine: [Does what it says ~ Cant be dropped close to an enemy ~ 1 sec]"] = "", -- Continental_supplies + ["Fire"] = "Fuoco", ["First aid kits?!"] = "Kit di pronto soccorso?!", +-- ["FIRST BLOOD MUTATES"] = "", -- Mutant ["First Blood"] = "Primo sangue", --- ["FIRST BLOOD MUTATES"] = "", -- Mutant ["First Steps"] = "Primi passi", ["Flag captured!"] = "Bandiera catturata!", ["Flag respawned!"] = "Bandiera restituita!", ["Flag returned!"] = "Bandiera recuperata!", ["Flags, and their home base will be placed where each team ends their first turn."] = "Le bandiere saranno piazzate nel luogo in cui le squadre finiscono il loro primo turno.", ["Flamer"] = "Incendiario", +-- ["Flamethrower"] = "", -- Construction_Mode -- ["Flaming Worm"] = "", -- A_Classic_Fairytale:backstab --- ["Flare: [fire up some bombs depending on hogs depending on hogs in the circle"] = "", -- Continental_supplies + -- ["Flesh for Brainz"] = "", -- A_Classic_Fairytale:journey +-- ["Flying Saucer"] = "", -- Construction_Mode, Frenzy -- ["For improved features/stability, play 0.9.18+"] = "", -- WxW -- ["Free Dense Cloud and continue the mission!"] = "", -- A_Classic_Fairytale:journey +-- ["Freezer"] = "", -- Construction_Mode +-- ["FRENZY"] = "", -- Frenzy ["Friendly Fire!"] = "Fuoco Amico!", ["fuel extended!"] = "carburante aggiuntivo!", ["GAME BEGUN!!!"] = "IL GIOCO E' INIZIATO!!!", @@ -246,6 +304,9 @@ -- ["Game? Was this a game to you?!"] = "", -- A_Classic_Fairytale:enemy -- ["GasBomb"] = "", -- Continental_supplies -- ["Gas Gargler"] = "", -- A_Classic_Fairytale:queen +-- ["General information"] = "", -- Continental_supplies +-- ["Generates power."] = "", -- Construction_Mode +-- ["Generator"] = "", -- Construction_Mode -- ["Get Dense Cloud out of the pit!"] = "", -- A_Classic_Fairytale:journey ["Get on over there and take him out!"] = "Vai fuori da qui ed eliminalo!", -- ["Get on the head of the mole"] = "", -- A_Classic_Fairytale:first_blood @@ -256,6 +317,8 @@ -- ["Get your teammates out of their natural prison and save the princess!|Hint: Drilling holes should solve everything.|Hint: It might be a good idea to place a girder before starting to drill. Just saying.|Hint: All your hedgehogs need to be above the marked height!|Hint: Leaks A Lot needs to get really close to the princess!"] = "", -- A_Classic_Fairytale:family ["GG!"] = "GG!", -- ["Gimme Bones"] = "", -- A_Classic_Fairytale:backstab +-- ["Girder"] = "", -- Construction_Mode +-- ["Girder Placement Mode"] = "", -- Construction_Mode -- ["Glark"] = "", -- A_Classic_Fairytale:shadow ["Goal"] = "Goal", ["GO! GO! GO!"] = "VAI! VAI! VAI!", @@ -272,12 +335,16 @@ -- ["Go surf!"] = "", -- WxW ["GOTCHA!"] = "COLPITO!!", ["Grab Mines/Explosives"] = "Afferra Mine/Esplosivi", +-- ["Grants nearby hogs life-regeneration."] = "", -- Construction_Mode +-- ["Gravity"] = "", -- Gravity -- ["Great choice, Steve! Mind if I call you that?"] = "", -- A_Classic_Fairytale:shadow -- ["Great work! Now hit it with your Baseball Bat! |Tip: You can change weapon with 'Right Click'!"] = "", -- Basic_Training_-_Rope -- ["Great! You will be contacted soon for assistance."] = "", -- A_Classic_Fairytale:shadow --- ["Green lipstick bullet: [Is poisonous]"] = "", -- Continental_supplies + +-- ["Green lipstick bullet: [Poisonous, deals no damage]"] = "", -- Continental_supplies +-- ["Greetings, cloudy one!"] = "", -- A_Classic_Fairytale:shadow ["Greetings, "] = "Saluti, ", --- ["Greetings, cloudy one!"] = "", -- A_Classic_Fairytale:shadow +-- ["Grenade"] = "", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 -- ["Grenade Training"] = "", -- Basic_Training_-_Grenade -- ["Grenadiers"] = "", -- Basic_Training_-_Grenade -- ["Guys, do you think there's more of them?"] = "", -- A_Classic_Fairytale:backstab @@ -285,6 +352,7 @@ ["Haha!"] = "Ahah!", ["Hahahaha!"] = "Ahahahah!", ["Haha, now THAT would be something!"] = "Haha, allora questa pioggia ha DAVVERO qualcosa di strano!", +-- ["Hammer"] = "", -- Construction_Mode, Continental_supplies ["Hannibal"] = "Annibale", [" Hapless Hogs left!"] = "Ricci Sfortunati rimanenti!", ["Hapless Hogs"] = "Ricci Sfortunati", @@ -292,15 +360,19 @@ -- ["Hatless Jerry"] = "", -- A_Classic_Fairytale:queen -- ["Have no illusions, your tribe is dead, indifferent of your choice."] = "", -- A_Classic_Fairytale:shadow -- ["Have we ever attacked you first?"] = "", -- A_Classic_Fairytale:enemy +-- ["Healing Station"] = "", -- Construction_Mode +-- ["Health Crate Placement Mode"] = "", -- Construction_Mode ["Health crates extend your time."] = "Le casse salute estendono il tuo tempo", -- ["Heavy Cannfantry"] = "", -- A_Classic_Fairytale:united ["Heavy"] = "Pesante", -- ["Hedge-cogs"] = "", -- A_Classic_Fairytale:enemy --- ["Hedgehog projectile: [fire your hog like a Sticky Bomb]"] = "", -- Continental_supplies +-- ["Hedgehog projectile: [Fire your hog like a Sticky Bomb]"] = "", -- Continental_supplies + ["Hedgewars-Basketball"] = "Hedgewars-Pallacanestro", ["Hedgewars-Knockball"] = "Hedgewars-Knockball", ["Hedgibal Lecter"] = "Riccibal Lecter", ["Heh, it's not that bad."] = "Beh, alla fine non piove così forte.", +-- ["Hellish Handgrenade"] = "", -- Construction_Mode ["Hello again, "] = "Salve di nuovo, ", -- ["Help me, Leaks!"] = "", -- A_Classic_Fairytale:journey ["Help me, please!!!"] = "Aiutami, per favore!!!", @@ -332,6 +404,7 @@ ["Hogminator"] = "Ricc-minator", ["Hogs in sight!"] = "Ricci in vista!", ["HOLY SHYTE!"] = "SANTA POLENTA!", +-- ["Homing Bee"] = "", -- Construction_Mode -- ["Honest Lee"] = "", -- A_Classic_Fairytale:enemy ["Hooray!"] = "Hurrà!!!", -- ["Hostage Situation"] = "", -- A_Classic_Fairytale:family @@ -387,6 +460,7 @@ ["I'm not sure about that!"] = "Non sono sicuro di quello!", -- ["Impressive...you are still dry as the corpse of a hawk after a week in the desert..."] = "", -- A_Classic_Fairytale:first_blood ["I'm so scared!"] = "Ho tanta paura!", +-- ["Increase"] = "", -- Continental_supplies ["Incredible..."] = "Incredibile...", ["I need to find the others!"] = "Devo trovare gli altri!", -- ["I need to get to the other side of this island, fast!"] = "", -- A_Classic_Fairytale:journey @@ -395,12 +469,14 @@ ["I need to warn the others."] = "Devo avvisare gli altri.", -- ["In fact, you are the only one that's been acting strangely."] = "", -- A_Classic_Fairytale:backstab -- ["In order to get to the other side, you need to collect the crates first.|"] = "", -- A_Classic_Fairytale:dragon +-- ["INSANITY"] = "", -- Mutant ["Instructor"] = "Istruttore", ["Interesting idea, haha!"] = "Idea interessante, ahah!", -- ["Interesting! Last time you said you killed a cannibal!"] = "", -- A_Classic_Fairytale:backstab -- ["In the meantime, take these and return to your \"friend\"!"] = "", -- A_Classic_Fairytale:shadow ["invaders destroyed"] = "invasori distrutti", ["Invasion"] = "Invasione", +-- ["Invulnerable"] = "", -- Construction_Mode ["I saw it with my own eyes!"] = "L'ho visto coi miei occhi!", ["I see..."] = "Capisco...", -- ["I see you have already taken the leap of faith."] = "", -- A_Classic_Fairytale:first_blood @@ -415,8 +491,8 @@ -- ["It is called 'Hogs of Steel'."] = "", -- A_Classic_Fairytale:enemy ["It is time to practice your fighting skills."] = "E' ora di mettere in pratica le vostre abilità di combattimento.", ["It must be a childhood trauma..."] = "Dev'essere un trauma infantile...", +-- ["It must be the aliens' deed."] = "", -- A_Classic_Fairytale:backstab ["It must be the aliens!"] = "Devono essere gli alieni!", --- ["It must be the aliens' deed."] = "", -- A_Classic_Fairytale:backstab -- ["It must be the cyborgs again!"] = "", -- A_Classic_Fairytale:enemy -- ["I told you, I just found them."] = "", -- A_Classic_Fairytale:backstab ["It's a good thing SUDDEN DEATH is 99 turns away..."] = "Almeno il SUDDEN DEATH arriverà tra 99 turni...", @@ -443,6 +519,7 @@ -- ["Just kidding, none of you have died!"] = "", -- A_Classic_Fairytale:enemy -- ["Just on a walk."] = "", -- A_Classic_Fairytale:united -- ["Just wait till I get my hands on that trauma! ARGH!"] = "", -- A_Classic_Fairytale:family +-- ["Kamikaze"] = "", -- Construction_Mode ["Kamikaze Expert!"] = "Kamikaze Esperto!", ["Keep it up!"] = "Mantienilo al sicuro!", ["Kerguelen"] = "Kerguelen", @@ -452,6 +529,8 @@ -- ["Kill the aliens!"] = "", -- A_Classic_Fairytale:dragon -- ["Kill the cannibal!"] = "", -- A_Classic_Fairytale:first_blood -- ["Kill the traitor...or spare his life!|Kill him or press [Precise]!"] = "", -- A_Classic_Fairytale:backstab +-- ["Land Sprayer"] = "", -- Construction_Mode +-- ["Laser Sight"] = "", -- Construction_Mode ["Last Target!"] = "Ultimo Obiettivo!", -- ["Leader"] = "", -- A_Classic_Fairytale:enemy -- ["Leaderbot"] = "", -- A_Classic_Fairytale:queen @@ -461,6 +540,7 @@ -- ["Leaks A Lot must survive!"] = "", -- A_Classic_Fairytale:journey -- ["Led Heart"] = "", -- A_Classic_Fairytale:queen -- ["Lee"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen +-- ["left shift"] = "", -- Continental_supplies ["[Left Shift]"] = "Shift Sinistro", -- ["Let a Continent provide your weapons!"] = "", -- Continental_supplies -- ["Let me test your skills a little, will you?"] = "", -- A_Classic_Fairytale:journey @@ -471,41 +551,56 @@ -- ["Let them have a taste of my fury!"] = "", -- A_Classic_Fairytale:backstab -- ["Let us help, too!"] = "", -- A_Classic_Fairytale:backstab -- ["Light Cannfantry"] = "", -- A_Classic_Fairytale:united +-- ["Limburger"] = "", -- Construction_Mode ["Listen up, maggot!!"] = "Recluta, Attenzione!!", -- ["Little did they know that this hunt will mark them forever..."] = "", -- A_Classic_Fairytale:shadow ["Lively Lifeguard"] = "Bagnino Vivace", --- ["Lonely Cries: [Rise the water if no hog is in the circle and deal 1 damage to all hogs]"] = "", -- Continental_supplies + +-- ["Lonely Cries: [Rise the water if no hog is in the circle and deal 7 damage to all enemy hogs]"] = "", -- Continental_supplies +-- ["Lonely Hog"] = "", -- ClimbHome -- ["Look, I had no choice!"] = "", -- A_Classic_Fairytale:backstab -- ["Look out! There's more of them!"] = "", -- A_Classic_Fairytale:backstab -- ["Look out! We're surrounded by cannibals!"] = "", -- A_Classic_Fairytale:enemy -- ["Looks like the whole world is falling apart!"] = "", -- A_Classic_Fairytale:enemy +-- ["Low Gravity"] = "", -- Construction_Mode, Frenzy -- ["Luckily, I've managed to snatch some of them."] = "", -- A_Classic_Fairytale:united -- ["LUDICROUS KILL"] = "", -- Mutant +-- ["Made it!"] = "", -- ClimbHome +-- ["- Massive weapon bonus on first turn"] = "", -- Continental_supplies -- ["May the spirits aid you in all your quests!"] = "", -- A_Classic_Fairytale:backstab -- ["Medicine: [Fire some exploding medicine that will heal all hogs effected by the explosion]"] = "", -- Continental_supplies -- ["MEGA KILL"] = "", -- Mutant -- ["Meiwes"] = "", -- A_Classic_Fairytale:backstab -- ["Mindy"] = "", -- A_Classic_Fairytale:united +-- ["Mine"] = "", -- Construction_Mode, Frenzy ["Mine Deployer"] = "Posatore di Mine", ["Mine Eater!"] = "Mangiatore di Mine!", +-- ["Mine Placement Mode"] = "", -- Construction_Mode ["|- Mines Time:"] = "|- Timer delle mine:", +-- ["Mine Strike"] = "", -- Construction_Mode ["MISSION FAILED"] = "MISSIONE FALLITA", ["MISSION SUCCESSFUL"] = "MISSIONE COMPLETATA CON SUCCESSO", ["MISSION SUCCESS"] = "MISSIONE COMPLETATA", +-- ["Molotov Cocktail"] = "", -- Construction_Mode ["Molotov"] = "Molotov", -- ["MONSTER KILL"] = "", -- Mutant -- ["More Natives"] = "", -- A_Classic_Fairytale:epil +-- ["Mortar"] = "", -- Construction_Mode, A_Space_Adventure:death02 ["Movement: [Up], [Down], [Left], [Right]"] = "Movimenti: [Su], [Giù], [Sinistra], [Destra]", +-- ["Mudball"] = "", -- Construction_Mode ["Multi-shot!"] = "Colpi multipli!", -- ["Muriel"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen -- ["Muscle Dissolver"] = "", -- A_Classic_Fairytale:shadow -- ["-------"] = "", -- Mutant +-- ["Mutant"] = "", -- Mutant -- ["Nade Boy"] = "", -- Basic_Training_-_Grenade -- ["Name"] = "", -- A_Classic_Fairytale:queen ["Nameless Heroes"] = "Eroi Senza Nome", -- ["Nancy Screw"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:queen +-- ["Napalm"] = "", -- Construction_Mode -- ["Napalm rocket: [Fire a bomb with napalm!]"] = "", -- Continental_supplies -- ["Natives"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:first_blood, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united +-- ["Naughty Ninja"] = "", -- User_Mission_-_Dangerous_Ducklings ["New Barrels Per Turn"] = "Nuovi Barili ad Ogni Turno", ["NEW CLAN RECORD: "] = "NUOVO RECORD DEL CLAN: ", ["NEW fastest lap: "] = "Nuovo giro migliore: ", @@ -516,6 +611,7 @@ -- ["Nice work, "] = "", -- A_Classic_Fairytale:dragon -- ["Nice work!"] = "", -- A_Classic_Fairytale:enemy -- ["Nilarian"] = "", -- A_Classic_Fairytale:queen +-- ["Nobody Laugh"] = "", -- User_Mission_-_Nobody_Laugh -- ["No, I came back to help you out..."] = "", -- A_Classic_Fairytale:shadow -- ["No...I wonder where they disappeared?!"] = "", -- A_Classic_Fairytale:journey -- ["Nom-Nom"] = "", -- A_Classic_Fairytale:journey @@ -523,6 +619,7 @@ -- ["Nope. It was one fast mole, that's for sure."] = "", -- A_Classic_Fairytale:shadow -- ["No! Please, help me!"] = "", -- A_Classic_Fairytale:journey -- ["NORMAL"] = "", -- Continental_supplies +-- ["Normal players can only score points by killing the mutant."] = "", -- Mutant -- ["North America"] = "", -- Continental_supplies -- ["Not all hogs are born equal."] = "", -- Highlander ["NOT ENOUGH WAYPOINTS"] = "NON CI SONO ABBASTANZA PUNTI!", @@ -535,6 +632,7 @@ -- ["No. Where did he come from?"] = "", -- A_Classic_Fairytale:shadow -- ["Now how do I get on the other side?!"] = "", -- A_Classic_Fairytale:dragon -- ["No. You and the rest of the tribe are safer there!"] = "", -- A_Classic_Fairytale:backstab +-- ["Object Placement Tool"] = "", -- Construction_Mode -- ["Obliterate them!|Hint: You might want to take cover..."] = "", -- A_Classic_Fairytale:shadow -- ["Obstacle course"] = "", -- A_Classic_Fairytale:dragon -- ["Of course I have to save her. What did I expect?!"] = "", -- A_Classic_Fairytale:family @@ -551,21 +649,29 @@ -- ["Once upon a time, on an island with great natural resources, lived two tribes in heated conflict..."] = "", -- A_Classic_Fairytale:first_blood -- ["ONE HOG PER TEAM! KILLING EXCESS HEDGES"] = "", -- Mutant -- ["One tribe was peaceful, spending their time hunting and training, enjoying the small pleasures of life..."] = "", -- A_Classic_Fairytale:first_blood +-- ["on Skip"] = "", -- Continental_supplies -- ["Oops...I dropped them."] = "", -- A_Classic_Fairytale:united -- ["Open that crate and we will continue!"] = "", -- A_Classic_Fairytale:first_blood ["Operation Diver"] = "Operazione Sub", ["Opposing Team: "] = "Squadra Nemica: ", +-- ["or 'g=50, g2=150, period=4000' for gravity changing|from 50 to 150 and back with period of 4000 msec"] = "", -- Gravity -- ["Orlando Boom!"] = "", -- A_Classic_Fairytale:queen +-- ["Other kills don't give you points."] = "", -- Mutant -- ["Ouch!"] = "", -- User_Mission_-_Rope_Knock_Challenge -- ["Our tribe, our beautiful island!"] = "", -- A_Classic_Fairytale:enemy -- ["Parachute"] = "", -- Continental_supplies ["Pathetic Hog #%d"] = "Riccio Patetico #%d", ["Pathetic Resistance"] = "Resistenza Patetica", +-- ["Penguin roar: [Deal 15 damage + 15% of your hogs health to all hogs around you and get 2/3 back]"] = "", -- Continental_supplies -- ["Perfect! Now try to get the next crate without hurting yourself!"] = "", -- A_Classic_Fairytale:first_blood ["Per-Hog Ammo"] = "Munizioni per Riccio", --- ["- Per team weapons|- 9 weaponschemes|- Unique new weapons| |Select continent first round with the Weapon Menu or by ([switch/tab]=Increase,[precise/left shift]=Decrease) on Skip|Some weapons have a second option. Find them with [switch/tab]"] = "", -- Continental_supplies +-- ["Personal Portal Device"] = "", -- Construction_Mode + +-- ["Per team weapons"] = "", -- Continental_supplies -- ["Pfew! That was close!"] = "", -- A_Classic_Fairytale:shadow --- ["Piñata bullet: [Contains some sweet candy!]"] = "Proiettile pentolaccia: [Contiene alcune caramelle deliziose!]", -- Continental_supplies +-- ["Piano Strike"] = "", -- Construction_Mode +-- ["Pickhammer"] = "", -- Construction_Mode + -- ["Pings left:"] = "", -- Space_Invasion ["Place more waypoints using the 'Air Attack' weapon."] = "Piazza più punti usando l'Attacco Aereo", -- ["Planes Used:"] = "", -- User_Mission_-_RCPlane_Challenge @@ -575,15 +681,19 @@ -- ["Please place the way-point in the open, within the map boundaries."] = "", -- Racer -- ["Please, stop releasing your \"smoke signals\"!"] = "", -- A_Classic_Fairytale:shadow -- ["Point Blank Combo!"] = "", -- Space_Invasion +-- ["POINTS"] = "", -- Mutant ["points"] = "punti", ["Poison"] = "Veleno", +-- ["Population"] = "", -- Continental_supplies -- ["Portal hint: one goes to the destination, and one is the entrance.|"] = "", -- A_Classic_Fairytale:dragon -- ["Portal mission"] = "", -- portal ["Power Remaining"] = "Potenza Rimasta", ["Prepare yourself"] = "Preparati", +-- ["presice"] = "", -- Continental_supplies -- ["Press [Enter] to accept this configuration."] = "", -- WxW -- ["Press [Left] or [Right] to move around, [Enter] to jump"] = "", -- A_Classic_Fairytale:first_blood ["Press [Precise] to skip intro"] = "Premi [Mirino di Precisione] per saltare l'intro", +-- ["Prestigious Pilot"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Private Novak"] = "", -- Basic_Training_-_Cluster_Bomb -- ["Protect yourselves!|Grenade hint: set the timer with [1-5], aim with [Up]/[Down] and hold [Space] to set power"] = "", -- A_Classic_Fairytale:shadow ["Race complexity limit reached."] = "Raggiunto il limite di complessità della corsa.", @@ -592,25 +702,39 @@ -- ["Radar Ping"] = "", -- Space_Invasion -- ["Raging Buffalo"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united -- ["Ramon"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow +-- ["random in range from %i%% to %i%% with period of %i msec"] = "", -- Gravity +-- ["RC Plane"] = "", -- Construction_Mode -- ["RC PLANE TRAINING"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Really?! You thought you could harm me with your little toys?"] = "", -- A_Classic_Fairytale:shadow +-- ["Reflector Shield"] = "", -- Construction_Mode +-- ["Reflects enemy projectiles."] = "", -- Construction_Mode -- ["Regurgitator"] = "", -- A_Classic_Fairytale:backstab -- ["Reinforcements"] = "", -- A_Classic_Fairytale:backstab -- ["Remember: The rope only bend around objects, |if it doesn't hit anything it's always stright!"] = "", -- Basic_Training_-_Rope -- ["Remember this, pathetic animal: when the day comes, you will regret your blind loyalty!"] = "", -- A_Classic_Fairytale:shadow +-- ["REMOVED"] = "", -- Continental_supplies +-- ["Respawner"] = "", -- Construction_Mode +-- ["Resurrector"] = "", -- Construction_Mode +-- ["Resurrects dead hedgehogs."] = "", -- Construction_Mode [" - Return the enemy flag to your base to score | - First team to 3 captures wins | - You may only score when your flag is in your base | - Hogs will drop the flag if killed, or drowned | - Dropped flags may be returned or recaptured | - Hogs respawn when killed"] = " - Riporta la bandiera nemica alla tua base per guadagnare un punto| - La prima squadra a catturarne 3 vince! | - Puoi guadagnare punti solo quando la tua bandiera si trova nella tua base! | - I ricci lasceranno cadere la bandiera se uccisi o caduti in acqua! | - Le bandiere cadute possono essere restituite o ricatturate! | - I ricci risorgono dalla morte!", -- ["Return to Leaks A Lot! If you get stuck, press [Precise] to try again!"] = "", -- A_Classic_Fairytale:shadow -- ["Righteous Beard"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:first_blood, A_Classic_Fairytale:queen, A_Classic_Fairytale:united +-- ["Rope"] = "", -- Construction_Mode -- ["ROPE-KNOCKING"] = "", -- User_Mission_-_Rope_Knock_Challenge +-- ["Rope to safety"] = "", -- ClimbHome -- ["Rope Training"] = "", -- Basic_Training_-_Rope -- ["Rot Molester"] = "", -- A_Classic_Fairytale:shadow ["Round Limit:"] = "Limite del Round: ", ["Round Limit"] = "Limite del Round", ["Rounds Complete: "] = "Round Completati: ", ["Rounds Complete"] = "Round Completati", +-- ["Rubber Band"] = "", -- Construction_Mode +-- ["Rubber Placement Mode"] = "", -- Construction_Mode +-- ["RULES"] = "", -- Frenzy, Mutant ["RULES OF THE GAME [Press ESC to view]"] = "REGOLE DEL GIOCO (Premi ESC per visualizzarle)", -- ["Rusty Joe"] = "", -- A_Classic_Fairytale:queen --- ["Sabotage: [Sabotage all hogs in the circle and deal ~10 dmg]"] = "", -- Continental_supplies +-- ["Sabotage/Flare: [Sabotage all hogs in the circle and deal ~1 dmg OR Fire a cluster up into the air]"] = "", -- Continental_supplies + -- ["Salivaslurper"] = "", -- A_Classic_Fairytale:united -- ["Salvation"] = "", -- A_Classic_Fairytale:family -- ["Salvation was one step closer now..."] = "", -- A_Classic_Fairytale:dragon @@ -622,7 +746,7 @@ -- ["Scalp Muncher"] = "", -- A_Classic_Fairytale:backstab -- ["Score"] = "", -- Mutant ["SCORE"] = "PUNTEGGIO", --- ["Scream from a Walrus: [Deal 20 damage + 10% of your hogs health to all hogs around you and get half back]"] = "", -- Continental_supplies + ["sec"] = "sec", -- ["Seduction"] = "", -- Continental_supplies -- ["Seems like every time you take a \"walk\", the enemy find us!"] = "", -- A_Classic_Fairytale:backstab @@ -630,8 +754,11 @@ ["See ya!"] = "Ci vediamo!", -- ["Segmentation Paul"] = "", -- A_Classic_Fairytale:dragon -- ["Select continent!"] = "", -- Continental_supplies +-- ["Select continent first round with the Weapon Menu or by"] = "", -- Continental_supplies -- ["Select difficulty: [Left] - easier or [Right] - harder"] = "", -- A_Classic_Fairytale:first_blood ["selected!"] = "selezionato!", +-- ["Set period to negative value for random gravity"] = "", -- Gravity +-- ["Setup:|'g=150', where 150 is 150% of normal gravity"] = "", -- Gravity -- ["... share your beauty with the world every morning, my princess!"] = "", -- A_Classic_Fairytale:journey -- ["She's behind that tall thingy."] = "", -- A_Classic_Fairytale:family ["Shield boosted! +30 power"] = "Scudo ricaricato! Potenza +30", @@ -642,16 +769,21 @@ ["Shield OFF:"] = "Scudo OFF:", ["Shield ON:"] = "Scudo ON:", ["Shield Seeker!"] = "Cercatore di Scudi!", +-- ["Shoryuken"] = "", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 -- ["Shotgun"] = "", ["Shotgun Team"] = "Squadra Shotgun", ["Shotgun Training"] = "Addestramento sull'utilizzo del Fucile a Pompa", ["shots remaining."] = "colpi rimasti.", ["Silly"] = "Stupido", +-- ["SineGun"] = "", -- Construction_Mode ["Sinky"] = "Affondato", -- ["Sirius Lee"] = "", -- A_Classic_Fairytale:enemy ["%s is out and Team %d|scored a penalty!| |Score:"] = "%s è fuori dal campo e la squadra %d|prende una penalità!| |Punteggio:", ["%s is out and Team %d|scored a point!| |Score:"] = "%s è fuori dal campo e la squadra %d|guadagna un punto!| |Puntuación:", -- ["Slippery"] = "", -- A_Classic_Fairytale:journey +-- ["Slot"] = "", -- Frenzy +-- ["Slot keys save time! (F1-F10 by default)"] = "", -- Frenzy +-- ["SLOTS"] = "", -- Frenzy -- ["Smith 0.97"] = "", -- A_Classic_Fairytale:enemy -- ["Smith 0.98"] = "", -- A_Classic_Fairytale:enemy -- ["Smith 0.99a"] = "", -- A_Classic_Fairytale:enemy @@ -663,6 +795,7 @@ ["Sniper Training"] = "Addestramento sull'utilizzo del Fucile di Precisione", ["Sniperz"] = "Cecchini", -- ["So humiliating..."] = "", -- A_Classic_Fairytale:first_blood +-- ["Some weapons have a second option. Find them with"] = "", -- Continental_supplies -- ["South America"] = "", -- Continental_supplies -- ["So? What will it be?"] = "", -- A_Classic_Fairytale:shadow -- ["Spawn the crate, and attack!"] = "", -- WxW @@ -671,6 +804,8 @@ -- ["Spleenlover"] = "", -- A_Classic_Fairytale:united ["Sponge"] = "Spugna", ["Spooky Tree"] = "Albero Stregato", +-- ["Sprite Placement Mode"] = "", -- Construction_Mode +-- ["Sprite Testing Mode"] = "", -- Construction_Mode ["s|"] = "s|", ["s"] = "s", ["STATUS UPDATE"] = "STATUS AGGIORNATO", @@ -678,20 +813,36 @@ -- ["Step By Step"] = "", -- A_Classic_Fairytale:first_blood -- ["Steve"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen -- ["Sticky Mine"] = "", -- Continental_supplies +-- ["Sticky Mine Placement Mode"] = "", -- Construction_Mode -- ["Stronglings"] = "", -- A_Classic_Fairytale:shadow --- ["Structure"] = "", -- Continental_supplies + +-- ["Structure Placement Mode"] = "", -- Construction_Mode +-- ["Structure Placement Tool"] = "", -- Construction_Mode +-- ["Sundaland"] = "", -- Continental_supplies -- ["Super Weapons"] = "", -- WxW +-- ["Support Station"] = "", -- Construction_Mode -- ["Surf Before Crate"] = "", -- WxW -- ["Surfer! +15 points!"] = "", -- Space_Invasion -- ["Surfer!"] = "", -- WxW -- ["Survive!|Hint: Cinematics can be skipped with the [Precise] key."] = "", -- A_Classic_Fairytale:shadow -- ["Swing, Leaks A Lot, on the wings of the wind!"] = "", -- A_Classic_Fairytale:first_blood +-- ["switch"] = "", -- Continental_supplies ["Switched to "] = "Cambiato in", +-- ["Switch Hog"] = "", -- Construction_Mode -- ["Syntax Errol"] = "", -- A_Classic_Fairytale:dragon +-- ["tab"] = "", -- Continental_supplies +-- ["Tagging Mode"] = "", -- Construction_Mode -- ["Talk about mixed signals..."] = "", -- A_Classic_Fairytale:dragon +-- ["Tardis"] = "", -- Construction_Mode +-- ["Target Placement Mode"] = "", -- Construction_Mode ["Team %d: "] = "Squadra %d: ", ["Team Scores"] = "Punteggi della Squadra", +-- ["Teleporation Node"] = "", -- Construction_Mode +-- ["Teleportation Mode"] = "", -- Construction_Mode +-- ["Teleportation Node"] = "", -- Construction_Mode +-- ["Teleport"] = "", -- Construction_Mode, Frenzy -- ["Teleport hint: just use the mouse to select the destination!"] = "", -- A_Classic_Fairytale:dragon +-- ["Teleport Unsuccessful. Please teleport within a clan teleporter's sphere of influence."] = "", -- Construction_Mode ["Thanks!"] = "Grazie!", ["Thank you, my hero!"] = "Grazie, mio eroe!", -- ["Thank you, oh, thank you, Leaks A Lot!"] = "", -- A_Classic_Fairytale:journey @@ -708,6 +859,7 @@ ["That was pointless."] = "Era senza senso.", -- ["The answer is...entertaintment. You'll see what I mean."] = "", -- A_Classic_Fairytale:backstab -- ["The anti-portal zone is all over the floor, and I have nothing to kill him...Droping something could hurt him enough to kill him..."] = "", -- portal +-- ["The Bottom Feeder can score points by killing anyone."] = "", -- Mutant -- ["The Bull's Eye"] = "", -- A_Classic_Fairytale:first_blood -- ["The caves are well hidden, they won't find us there!"] = "", -- A_Classic_Fairytale:united -- ["The Crate Frenzy"] = "", -- A_Classic_Fairytale:first_blood @@ -717,20 +869,26 @@ -- ["The Enemy Of My Enemy"] = "", -- A_Classic_Fairytale:enemy -- ["The First Blood"] = "", -- A_Classic_Fairytale:first_blood -- ["The First Encounter"] = "", -- A_Classic_Fairytale:shadow +-- ["The first player to kill someone becomes the Mutant."] = "", -- Mutant ["The flag will respawn next round."] = "La bandiera verrà restituita alla fine del turno.", -- ["The food bites back"] = "", -- A_Classic_Fairytale:backstab -- ["The giant umbrella from the last crate should help break the fall."] = "", -- A_Classic_Fairytale:first_blood -- ["The Great Escape"] = "", -- User_Mission_-_The_Great_Escape +-- ["The Great Hog in the sky sees your sadness and grants you a boon."] = "", -- Construction_Mode -- ["The guardian"] = "", -- A_Classic_Fairytale:shadow -- ["The Individualist"] = "", -- A_Classic_Fairytale:shadow -- ["Their buildings were very primitive back then, even for an uncivilised island."] = "", -- A_Classic_Fairytale:united -- ["The Journey Back"] = "", -- A_Classic_Fairytale:journey -- ["The Leap of Faith"] = "", -- A_Classic_Fairytale:first_blood -- ["The Moonwalk"] = "", -- A_Classic_Fairytale:journey +-- ["The Mutant has super-weapons and a lot of health."] = "", -- Mutant +-- ["The Mutant loses health quickly if he doesn't keep scoring kills."] = "", -- Mutant ["The Nameless One"] = "Il Senzanome", -- ["The next one is pretty hard! |Tip: You have to do multiple swings!"] = "", -- Basic_Training_-_Rope -- ["Then how do they keep appearing?"] = "", -- A_Classic_Fairytale:shadow -- ["The other one were all cannibals, spending their time eating the organs of fellow hedgehogs..."] = "", -- A_Classic_Fairytale:first_blood +-- ["The player with least points (or most deaths) becomes the Bottom Feeder."] = "", -- Mutant +-- ["There are a variety of structures available to aid you."] = "", -- Construction_Mode -- ["There must be a spy among us!"] = "", -- A_Classic_Fairytale:backstab -- ["There's more of them? When did they become so hungry?"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united -- ["There's nothing more satisfying for me than seeing you share your beauty with the world every morning, my princess!"] = "", -- A_Classic_Fairytale:journey @@ -786,7 +944,7 @@ -- ["To the caves..."] = "", -- A_Classic_Fairytale:united ["Toxic Team"] = "Team Velenoso", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork ["TRACK COMPLETED"] = "PISTA COMPLETATA", - ["TRACK FAILED!"] = "PISTA FALLITA!", + ["training"] = "addestramento", ["Traitors"] = "Traditori", ["Tribe"] = "Tribù", @@ -803,6 +961,7 @@ -- ["ULTRA KILL"] = "", -- Mutant -- ["Under Construction"] = "", -- A_Classic_Fairytale:shadow -- ["Unexpected Igor"] = "", -- A_Classic_Fairytale:dragon +-- ["Unique new weapons"] = "", -- Continental_supplies -- ["Unit 0x0007"] = "", -- A_Classic_Fairytale:family -- ["Unit 334a$7%;.*"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united ["Unit 3378"] = "Unità 3378", @@ -817,11 +976,14 @@ -- ["Use it wisely!"] = "", -- A_Classic_Fairytale:dragon -- ["Use it with precaution!"] = "", -- A_Classic_Fairytale:first_blood ["User Challenge"] = "Sfida Utente", - +-- ["Use the air-attack weapons and the arrow keys to select structures."] = "", -- Construction_Mode -- ["Use the portal gun to get to the next crate, then use the new gun to get to the final destination!|"] = "", -- A_Classic_Fairytale:dragon -- ["Use the rope to get on the head of the mole, young one!"] = "", -- A_Classic_Fairytale:first_blood -- ["Use the rope to knock your enemies to their doom."] = "", -- User_Mission_-_Rope_Knock_Challenge +-- ["Use your ready time to think."] = "", -- Frenzy ["Use your rope to get from start to finish as fast as you can!"] = "Usa la tua corda per raggiungere il traguardo il più velocemente possibile!", +-- ["Utility Crate Placement Mode"] = "", -- Construction_Mode +-- ["Vampirism"] = "", -- Construction_Mode -- ["Vedgies"] = "", -- A_Classic_Fairytale:journey -- ["Vegan Jack"] = "", -- A_Classic_Fairytale:enemy -- ["Victory!"] = "", -- Basic_Training_-_Rope @@ -833,10 +995,14 @@ -- ["Wannabe Flyboys"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Wannabe Shoppsta"] = "", -- User_Mission_-_Rope_Knock_Challenge -- ["Watch your steps, young one!"] = "", -- A_Classic_Fairytale:first_blood +-- ["Watermelon Bomb"] = "", -- Construction_Mode ["Waypoint placed."] = "Punto piazzato.", ["Way-Points Remaining"] = "Punti Da Piazzare Rimasti", -- ["Weaklings"] = "", -- A_Classic_Fairytale:shadow -- ["We all know what happens when you get frightened..."] = "", -- A_Classic_Fairytale:first_blood +-- ["Weapon Crate Placement Mode"] = "", -- Construction_Mode +-- ["Weapon Filter"] = "", -- Construction_Mode +-- ["weaponschemes"] = "", -- Continental_supplies ["Weapons Reset"] = "Armi Azzerate", -- ["Weapons reset."] = "", -- Highlander -- ["We are indeed."] = "", -- A_Classic_Fairytale:backstab @@ -882,16 +1048,14 @@ -- ["Where are all these crates coming from?!"] = "", -- A_Classic_Fairytale:shadow ["Where are they?!"] = "Dove sono loro?!", ["Where did that alien run?"] = "Dov'è corso quell'alieno?", +-- ["Where did you get the exploding apples and the magic bow that shoots many arrows?"] = "", -- A_Classic_Fairytale:shadow ["Where did you get the exploding apples?"] = "Dove avete preso le mele explosive?", --- ["Where did you get the exploding apples and the magic bow that shoots many arrows?"] = "", -- A_Classic_Fairytale:shadow -- ["Where did you get the magic bow that shoots many arrows?"] = "", -- A_Classic_Fairytale:shadow -- ["Where did you get the weapons in the forest, Dense Cloud?"] = "", -- A_Classic_Fairytale:backstab ["Where do you get that?!"] = "Dove avete preso quello?!", ["Where have you been?!"] = "Dove siete stati?!", ["Where have you been?"] = "Dove siete stati?", - ["? Why?"] = "? Perché?", - ["Why "] = "Perché ", - ["! Why?!"] = "! Perché?!", +-- ["Whip"] = "", -- Construction_Mode ["Why are you doing this?"] = "Perché stai facendo questo?", ["Why are you helping us, uhm...?"] = "Perché ci stai aiutando, mmm...?", -- ["Why can't he just let her go?!"] = "", -- A_Classic_Fairytale:family @@ -899,10 +1063,15 @@ ["Why do you not like me?"] = "Perché non ti piaccio?", -- ["Why do you want to take over our island?"] = "", -- A_Classic_Fairytale:enemy ["Why me?!"] = "Perché io?!", + ["! Why?!"] = "! Perché?!", + ["? Why?"] = "? Perché?", + ["Why "] = "Perché ", -- ["Why would they do this?"] = "", -- A_Classic_Fairytale:backstab -- ["- Will Get 1-3 random weapons"] = "", -- Continental_supplies --- ["- Will refresh Parachute each turn."] = "", -- Continental_supplies --- ["- Will refresh portalgun each turn."] = "", -- Continental_supplies +-- ["- Will give you an airstrike every fifth turn."] = "", -- Continental_supplies +-- ["- Will give you a parachute every second turn."] = "", -- Continental_supplies + + ["Will this ever end?"] = "Finirà mai?", ["WINNER IS "] = "IL VINCITORE E' ", ["WINNING TIME: "] = "TEMPO VINCENTE: ", @@ -921,6 +1090,7 @@ ["Yes!"] = "Sì!", ["Yes, yeees! You are now ready to enter the real world!"] = "S^, sìì! Ora siete pronti per entrare nel mondo reale!", ["Yo, dude, we're here, too!"] = "Ehi, tu, ci siamo anche noi, qui!", +-- ["You are far from home, and the water is rising, climb up as high as you can!"] = "", -- ClimbHome -- ["You are given the chance to turn your life around..."] = "", -- A_Classic_Fairytale:shadow -- ["You are playing with our lives here!"] = "", -- A_Classic_Fairytale:enemy ["! You bastards!"] = "! Bastardi!", @@ -931,7 +1101,6 @@ -- ["You'd better watch your steps..."] = "", -- A_Classic_Fairytale:journey ["You did not make it in time, try again!"] = "Non hai fatto in tempo, prova ancora!", -- ["You have 7 turns until the next wave arrives.|Make sure the arriving cannibals are greeted appropriately!|If the hog dies, the cause is lost.|Hint: you might want to use some mines..."] = "", -- A_Classic_Fairytale:backstab - ["You have "] = "Hai ", -- ["You have been giving us out to the enemy, haven't you!"] = "", -- A_Classic_Fairytale:backstab -- ["You have been respawned, at your last checkpoint!"] = "", -- Basic_Training_-_Rope -- ["You have been respawned, be more carefull next time!"] = "", -- Basic_Training_-_Rope @@ -939,6 +1108,7 @@ -- ["You have failed to complete your task, young one!"] = "", -- A_Classic_Fairytale:journey -- ["You have failed to save the tribe!"] = "", -- A_Classic_Fairytale:backstab -- ["You have finally figured it out!"] = "", -- A_Classic_Fairytale:enemy + ["You have "] = "Hai ", -- ["You have kidnapped our whole tribe!"] = "", -- A_Classic_Fairytale:enemy -- ["You have killed an innocent hedgehog!"] = "", -- A_Classic_Fairytale:backstab -- ["You have proven yourself worthy to see our most ancient secret!"] = "", -- A_Classic_Fairytale:first_blood @@ -953,6 +1123,8 @@ -- ["You know what? I don't even regret anything!"] = "", -- A_Classic_Fairytale:backstab -- ["You'll see what I mean!"] = "", -- A_Classic_Fairytale:enemy ["You may only attack from a rope!"] = "Puoi attaccare solo da una corda!", +-- ["You may only spawn 5 crates per turn."] = "", -- Construction_Mode +-- ["You may only use 1 Extra Time per turn."] = "", -- Construction_Mode -- ["You meatbags are pretty slow, you know!"] = "", -- A_Classic_Fairytale:enemy -- ["You might want to find a way to instantly kill arriving cannibals!"] = "", -- A_Classic_Fairytale:backstab -- ["Young one, you are telling us that they can instantly change location without a shaman?"] = "", -- A_Classic_Fairytale:united @@ -973,6 +1145,7 @@ ["You've failed. Try again."] = "Hai fallito. Prova di nuovo.", ["You've reached the goal!| |Time: "] = "Hai raggiunto il traguardo!| |Tempo: ", ["You will be avenged!"] = "Sarai vendicato!", +-- ["- You will recieve 2-4 weapons on each kill! (Even on own hogs)"] = "", -- Continental_supplies ["You won't believe what happened to me!"] = "Non crederete a quello che mi è successo!", -- ["Yuck! I bet they'll keep worshipping her even after I save the village!"] = "", -- A_Classic_Fairytale:family ["Zealandia"] = "Zealandia", diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/ko.lua --- a/share/hedgewars/Data/Locale/ko.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/ko.lua Tue Nov 10 20:43:13 2015 +0100 @@ -4,6 +4,10 @@ -- ["..."] = "", -- ["011101000"] = "", -- A_Classic_Fairytale:dragon -- ["011101001"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:family, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united +-- ["+1 to a Bottom Feeder for killing anyone"] = "", -- Mutant +-- ["+1 to a Mutant for killing anyone"] = "", -- Mutant +-- ["-1 to anyone for a suicide"] = "", -- Mutant +-- ["+2 for becoming a Mutant"] = "", -- Mutant -- ["30 minutes later..."] = "", -- A_Classic_Fairytale:shadow -- ["About a month ago, a cyborg came and told us that you're the cannibals!"] = "", -- A_Classic_Fairytale:enemy -- ["Accuracy Bonus!"] = "", @@ -13,17 +17,27 @@ -- ["???"] = "", -- A_Classic_Fairytale:backstab -- ["Actually, you aren't worthy of life! Take this..."] = "", -- A_Classic_Fairytale:shadow -- ["A cy-what?"] = "", -- A_Classic_Fairytale:enemy +-- ["Advanced Repositioning Mode"] = "", -- Construction_Mode -- ["Adventurous"] = "", -- A_Classic_Fairytale:journey +-- ["a frenetic Hedgewars mini-game"] = "", -- Frenzy -- ["Africa"] = "", -- Continental_supplies -- ["After Leaks A Lot betrayed his tribe, he joined the cannibals..."] = "", -- A_Classic_Fairytale:first_blood -- ["After the shock caused by the enemy spy, Leaks A Lot and Dense Cloud went hunting to relax."] = "", -- A_Classic_Fairytale:shadow -- ["Again with the 'cannibals' thing!"] = "", -- A_Classic_Fairytale:enemy +-- ["Aggressively removes enemy hedgehogs."] = "", -- Construction_Mode -- ["a Hedgewars challenge"] = "", -- User_Mission_-_RCPlane_Challenge, User_Mission_-_Rope_Knock_Challenge -- ["a Hedgewars mini-game"] = "", -- Space_Invasion, The_Specialists +-- ["a Hedgewars tag game"] = "", -- Mutant +-- ["AHHh, home sweet home. Made it in %d seconds."] = "", -- ClimbHome -- ["Aiming Practice"] = "", --Bazooka, Shotgun, SniperRifle +-- ["Air Attack"] = "", -- Construction_Mode -- ["A leap in a leap"] = "", -- A_Classic_Fairytale:first_blood -- ["A little gift from the cyborgs"] = "", -- A_Classic_Fairytale:shadow -- ["All gone...everything!"] = "", -- A_Classic_Fairytale:enemy +-- ["Allows free teleportation between other nodes."] = "", -- Construction_Mode +-- ["Allows placement of girders, rubber-bands, mines, sticky mines and barrels."] = "", -- Construction_Mode +-- ["Allows placement of structures."] = "", -- Construction_Mode +-- ["Allows the placement of weapons, utiliites, and health crates."] = "", -- Construction_Mode -- ["All right, we just need to get to the other side of the island!"] = "", -- A_Classic_Fairytale:journey -- ["All walls touched!"] = "", -- WxW -- ["Ammo"] = "", @@ -38,8 +52,11 @@ -- ["And so they discovered that cyborgs weren't invulnerable..."] = "", -- A_Classic_Fairytale:journey -- ["And where's all the weed?"] = "", -- A_Classic_Fairytale:dragon -- ["And you believed me? Oh, god, that's cute!"] = "", -- A_Classic_Fairytale:journey --- ["Anno 1032: [The explosion will make a strong push ~ wide range, wont affect hogs close to the target]"] = "", -- Continental_supplies +-- ["Anno 1032: [The explosion will make a strong push ~ Wide range, wont affect hogs close to the target]"] = "", -- Continental_supplies + -- ["Antarctica"] = "", -- Continental_supplies +-- ["Antarctic summer: - Will give you one girder/mudball and two sineguns/portals every fourth turn."] = "", -- Continental_supplies +-- ["Area"] = "", -- Continental_supplies -- ["Are we there yet?"] = "", -- A_Classic_Fairytale:shadow -- ["Are you accusing me of something?"] = "", -- A_Classic_Fairytale:backstab -- ["Are you saying that many of us have died for your entertainment?"] = "", -- A_Classic_Fairytale:enemy @@ -59,27 +76,35 @@ -- ["[Backspace]"] = "", -- ["Backstab"] = "", -- A_Classic_Fairytale:backstab -- ["Bad Team"] = "", -- User_Mission_-_The_Great_Escape +-- ["Ballgun"] = "", -- Construction_Mode -- ["Bamboo Thicket"] = "", -- ["Barrel Eater!"] = "", -- ["Barrel Launcher"] = "", +-- ["Barrel Placement Mode"] = "", -- Construction_Mode +-- ["Baseball Bat"] = "", -- Construction_Mode -- ["Baseballbat"] = "", -- Continental_supplies -- ["Bat balls at your enemies and|push them into the sea!"] = "", -- ["Bat your opponents through the|baskets and out of the map!"] = "", +-- ["Bazooka"] = "", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 -- ["Bazooka Training"] = "", -- ["Beep Loopers"] = "", -- A_Classic_Fairytale:queen -- ["Best laps per team: "] = "", -- ["Best Team Times: "] = "", -- ["Beware, though! If you are slow, you die!"] = "", -- A_Classic_Fairytale:dragon +-- ["Bio-Filter"] = "", -- Construction_Mode -- ["Biomechanic Team"] = "", -- A_Classic_Fairytale:family +-- ["Birdy"] = "", -- Construction_Mode -- ["Blender"] = "", -- A_Classic_Fairytale:family -- ["Bloodpie"] = "", -- A_Classic_Fairytale:backstab -- ["Bloodrocutor"] = "", -- A_Classic_Fairytale:shadow -- ["Bloodsucker"] = "", -- A_Classic_Fairytale:shadow -- ["Bloody Rookies"] = "", -- 01#Boot_Camp, User_Mission_-_Dangerous_Ducklings, User_Mission_-_Diver, User_Mission_-_Spooky_Tree +-- ["Blowtorch"] = "", -- Construction_Mode, Frenzy +-- ["Blue Team"] = "", -- User_Mission_-_Dangerous_Ducklings -- ["Bone Jackson"] = "", -- A_Classic_Fairytale:backstab -- ["Bonely"] = "", -- A_Classic_Fairytale:shadow +-- ["BOOM!"] = "", -- ["Boom!"] = "", --- ["BOOM!"] = "", -- ["Boss defeated!"] = "", -- ["Boss Slayer!"] = "", -- ["Brain Blower"] = "", -- A_Classic_Fairytale:journey @@ -89,6 +114,7 @@ -- ["Brain Teaser"] = "", -- A_Classic_Fairytale:backstab -- ["Brutal Lily"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil -- ["Brutus"] = "", -- A_Classic_Fairytale:backstab +-- ["Build a fortress and destroy your enemy."] = "", -- Construction_Mode -- ["Build a track and race."] = "", -- ["Bullseye"] = "", -- A_Classic_Fairytale:dragon -- ["But it proved to be no easy task!"] = "", -- A_Classic_Fairytale:dragon @@ -99,6 +125,7 @@ -- ["But why would they help us?"] = "", -- A_Classic_Fairytale:backstab -- ["But you're cannibals. It's what you do."] = "", -- A_Classic_Fairytale:enemy -- ["But you said you'd let her go!"] = "", -- A_Classic_Fairytale:journey +-- ["Cake"] = "", -- Construction_Mode -- ["Call me Beep! Well, 'cause I'm such a nice...person!"] = "", -- A_Classic_Fairytale:family -- ["Cannibals"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:first_blood -- ["Cannibal Sentry"] = "", -- A_Classic_Fairytale:journey @@ -108,8 +135,15 @@ -- ["Carol"] = "", -- A_Classic_Fairytale:family -- ["CHALLENGE COMPLETE"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Change Weapon"] = "", +-- ["changing range from %i%% to %i%% with period of %i msec"] = "", -- Gravity -- ["Choose your side! If you want to join the strange man, walk up to him.|Otherwise, walk away from him. If you decide to att...nevermind..."] = "", -- A_Classic_Fairytale:shadow +-- ["Cleaver"] = "", -- Construction_Mode +-- ["Cleaver Placement Mode"] = "", -- Construction_Mode +-- ["Climber"] = "", -- ClimbHome +-- ["Climb Home"] = "", -- ClimbHome +-- ["Clowns"] = "", -- User_Mission_-_Nobody_Laugh -- ["Clumsy"] = "", +-- ["Cluster Bomb"] = "", -- Construction_Mode -- ["Cluster Bomb MASTER!"] = "", -- Basic_Training_-_Cluster_Bomb -- ["Cluster Bomb Training"] = "", -- Basic_Training_-_Cluster_Bomb -- ["Codename: Teamwork"] = "", @@ -129,12 +163,19 @@ -- ["Congratulations! You needed only half of time|to eliminate all targets."] = "", -- Basic_Training_-_Cluster_Bomb -- ["Congratulations! You've completed the Rope tutorial! |- Tutorial ends in 10 seconds!"] = "", -- Basic_Training_-_Rope -- ["Congratulations! You've eliminated all targets|within the allowed time frame."] = "", --Bazooka, Shotgun, SniperRifle +-- ["CONSTRUCTION MODE"] = "", -- Construction_Mode +-- ["Construction Station"] = "", -- Construction_Mode -- ["Continental supplies"] = "", -- Continental_supplies -- ["Control pillars to score points."] = "", +-- ["Core"] = "", -- Construction_Mode -- ["Corporationals"] = "", -- A_Classic_Fairytale:queen -- ["Corpsemonger"] = "", -- A_Classic_Fairytale:shadow -- ["Corpse Thrower"] = "", -- A_Classic_Fairytale:epil +-- ["Cost"] = "", -- Construction_Mode +-- ["Crate Placement Tool"] = "", -- Construction_Mode -- ["Crates Left:"] = "", -- User_Mission_-_RCPlane_Challenge +-- ["Cricket time: [Drop a fireable mine! ~ Will work if fired close to your hog & far away from enemy ~ 1 sec]"] = "", -- Continental_supplies +-- ["Current setting is "] = "", -- Gravity -- ["Cybernetic Empire"] = "", -- ["Cyborg. It's what the aliens call themselves."] = "", -- A_Classic_Fairytale:enemy -- ["Dahmer"] = "", -- A_Classic_Fairytale:backstab @@ -142,15 +183,19 @@ -- ["DAMMIT, ROOKIE! GET OFF MY HEAD!"] = "", -- ["Dangerous Ducklings"] = "", -- ["Deadweight"] = "", +-- ["Decrease"] = "", -- Continental_supplies -- ["Defeat the cannibals"] = "", -- A_Classic_Fairytale:backstab -- ["Defeat the cannibals!|"] = "", -- A_Classic_Fairytale:united -- ["Defeat the cannibals!|Grenade hint: set the timer with [1-5], aim with [Up]/[Down] and hold [Space] to set power"] = "", -- A_Classic_Fairytale:shadow -- ["Defeat the cyborgs!"] = "", -- A_Classic_Fairytale:enemy +-- ["Defend your core from the enemy."] = "", -- Construction_Mode -- ["Defend yourself!|Hint: You can get tips on using weapons by moving your mouse over them in the weapon selection menu"] = "", -- A_Classic_Fairytale:shadow +-- ["Dematerializes weapons and equipment carried by enemy hedgehogs."] = "", -- Construction_Mode -- ["Demolition is fun!"] = "", -- ["Dense Cloud"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united -- ["Dense Cloud must have already told them everything..."] = "", -- A_Classic_Fairytale:shadow -- ["Depleted Kamikaze!"] = "", +-- ["Desert Eagle"] = "", -- Construction_Mode, A_Space_Adventure:death02 -- ["Destroy him, Leaks A Lot! He is responsible for the deaths of many of us!"] = "", -- A_Classic_Fairytale:first_blood -- ["Destroy invaders to score points."] = "", -- ["Destroy the targets!|Hint: Select the Shoryuken and hit [Space]|P.S. You can use it mid-air."] = "", -- A_Classic_Fairytale:first_blood @@ -169,9 +214,12 @@ -- ["Do you have any idea how valuable grass is?"] = "", -- A_Classic_Fairytale:enemy -- ["Do you think you're some kind of god?"] = "", -- A_Classic_Fairytale:enemy -- ["Dragon's Lair"] = "", -- A_Classic_Fairytale:dragon +-- ["Drill Rocket"] = "", -- Construction_Mode -- ["Drills"] = "", -- A_Classic_Fairytale:backstab +-- ["Drill Strike"] = "", -- Construction_Mode -- ["Drone Hunter!"] = "", --- ["Drop a bomb: [drop some heroic wind that will turn into a bomb on impact]"] = "", -- Continental_supplies +-- ["Drop a bomb: [Drop some heroic wind that will turn into a bomb on impact]"] = "", -- Continental_supplies + -- ["Drowner"] = "", -- ["Dude, all the plants are gone!"] = "", -- A_Classic_Fairytale:family -- ["Dude, can you see Ramon and Spiky?"] = "", -- A_Classic_Fairytale:journey @@ -181,11 +229,15 @@ -- ["Dude, where are we?"] = "", -- A_Classic_Fairytale:backstab -- ["Dude, wow! I just had the weirdest high!"] = "", -- A_Classic_Fairytale:backstab -- ["Duration"] = "", -- Continental_supplies --- ["Dust storm: [Deals 20 damage to all enemies in the circle]"] = "", -- Continental_supplies +-- ["Dust storm: [Deals 15 damage to all enemies in the circle]"] = "", -- Continental_supplies + +-- ["Dynamite"] = "", -- Construction_Mode +-- ["Each turn is only ONE SECOND!"] = "", -- Frenzy -- ["Each turn you get 1-3 random weapons"] = "", -- ["Each turn you get one random weapon"] = "", -- ["Eagle Eye"] = "", -- A_Classic_Fairytale:backstab --- ["Eagle Eye: [Blink to the impact ~ one shot]"] = "", -- Continental_supplies +-- ["Eagle Eye: [Blink to the impact ~ One shot]"] = "", -- Continental_supplies + -- ["Ear Sniffer"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:epil -- ["Elderbot"] = "", -- A_Classic_Fairytale:family -- ["Elimate your captor."] = "", -- User_Mission_-_The_Great_Escape @@ -208,8 +260,9 @@ -- ["Every single time!"] = "", -- A_Classic_Fairytale:dragon -- ["Everything looks OK..."] = "", -- A_Classic_Fairytale:enemy -- ["Exactly, man! That was my dream."] = "", -- A_Classic_Fairytale:backstab +-- ["Extra Damage"] = "", -- Construction_Mode +-- ["Extra Time"] = "", -- Construction_Mode -- ["Eye Chewer"] = "", -- A_Classic_Fairytale:journey --- ["INSANITY"] = "", -- Mutant -- ["Family Reunion"] = "", -- A_Classic_Fairytale:family -- ["Fastest lap: "] = "", -- ["Feeble Resistance"] = "", @@ -219,10 +272,11 @@ -- ["Femur Lover"] = "", -- A_Classic_Fairytale:shadow -- ["Fierce Competition!"] = "", -- Space_Invasion -- ["Fiery Water"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united +-- ["Filthy Blue"] = "", -- User_Mission_-_Dangerous_Ducklings -- ["Find your tribe!|Cross the lake!"] = "", -- A_Classic_Fairytale:dragon -- ["Finish your training|Hint: Animations can be skipped with the [Precise] key."] = "", -- A_Classic_Fairytale:first_blood -- ["Fire"] = "", --- ["Fire a mine: [Does what it says ~ Cant be dropped close to an enemy ~ 1 sec]"] = "", -- Continental_supplies + -- ["First aid kits?!"] = "", -- A_Classic_Fairytale:united -- ["First Blood"] = "", -- A_Classic_Fairytale:first_blood -- ["FIRST BLOOD MUTATES"] = "", -- Mutant @@ -232,11 +286,15 @@ -- ["Flag returned!"] = "", -- ["Flags, and their home base will be placed where each team ends their first turn."] = "", -- ["Flamer"] = "", +-- ["Flamethrower"] = "", -- Construction_Mode -- ["Flaming Worm"] = "", -- A_Classic_Fairytale:backstab --- ["Flare: [fire up some bombs depending on hogs depending on hogs in the circle"] = "", -- Continental_supplies + -- ["Flesh for Brainz"] = "", -- A_Classic_Fairytale:journey +-- ["Flying Saucer"] = "", -- Construction_Mode, Frenzy -- ["For improved features/stability, play 0.9.18+"] = "", -- WxW -- ["Free Dense Cloud and continue the mission!"] = "", -- A_Classic_Fairytale:journey +-- ["Freezer"] = "", -- Construction_Mode +-- ["FRENZY"] = "", -- Frenzy -- ["Friendly Fire!"] = "", -- ["fuel extended!"] = "", -- ["GAME BEGUN!!!"] = "", @@ -246,6 +304,9 @@ -- ["Game? Was this a game to you?!"] = "", -- A_Classic_Fairytale:enemy -- ["GasBomb"] = "", -- Continental_supplies -- ["Gas Gargler"] = "", -- A_Classic_Fairytale:queen +-- ["General information"] = "", -- Continental_supplies +-- ["Generates power."] = "", -- Construction_Mode +-- ["Generator"] = "", -- Construction_Mode -- ["Get Dense Cloud out of the pit!"] = "", -- A_Classic_Fairytale:journey -- ["Get on over there and take him out!"] = "", -- ["Get on the head of the mole"] = "", -- A_Classic_Fairytale:first_blood @@ -256,6 +317,8 @@ -- ["Get your teammates out of their natural prison and save the princess!|Hint: Drilling holes should solve everything.|Hint: It might be a good idea to place a girder before starting to drill. Just saying.|Hint: All your hedgehogs need to be above the marked height!|Hint: Leaks A Lot needs to get really close to the princess!"] = "", -- A_Classic_Fairytale:family -- ["GG!"] = "", -- User_Mission_-_Rope_Knock_Challenge -- ["Gimme Bones"] = "", -- A_Classic_Fairytale:backstab +-- ["Girder"] = "", -- Construction_Mode +-- ["Girder Placement Mode"] = "", -- Construction_Mode -- ["Glark"] = "", -- A_Classic_Fairytale:shadow -- ["Goal"] = "", -- ["GO! GO! GO!"] = "", @@ -272,12 +335,16 @@ -- ["Go surf!"] = "", -- WxW -- ["GOTCHA!"] = "", -- ["Grab Mines/Explosives"] = "", +-- ["Grants nearby hogs life-regeneration."] = "", -- Construction_Mode +-- ["Gravity"] = "", -- Gravity -- ["Great choice, Steve! Mind if I call you that?"] = "", -- A_Classic_Fairytale:shadow -- ["Great work! Now hit it with your Baseball Bat! |Tip: You can change weapon with 'Right Click'!"] = "", -- Basic_Training_-_Rope -- ["Great! You will be contacted soon for assistance."] = "", -- A_Classic_Fairytale:shadow --- ["Green lipstick bullet: [Is poisonous]"] = "", -- Continental_supplies + +-- ["Green lipstick bullet: [Poisonous, deals no damage]"] = "", -- Continental_supplies -- ["Greetings, "] = "", -- A_Classic_Fairytale:dragon -- ["Greetings, cloudy one!"] = "", -- A_Classic_Fairytale:shadow +-- ["Grenade"] = "", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 -- ["Grenade Training"] = "", -- Basic_Training_-_Grenade -- ["Grenadiers"] = "", -- Basic_Training_-_Grenade -- ["Guys, do you think there's more of them?"] = "", -- A_Classic_Fairytale:backstab @@ -285,23 +352,27 @@ -- ["Haha!"] = "", -- A_Classic_Fairytale:united -- ["Hahahaha!"] = "", -- ["Haha, now THAT would be something!"] = "", +-- ["Hammer"] = "", -- Construction_Mode, Continental_supplies -- ["Hannibal"] = "", -- A_Classic_Fairytale:epil -- ["Hapless Hogs"] = "", -- [" Hapless Hogs left!"] = "", - -- [" HAS MUTATED"] = "", -- Mutant -- ["Hatless Jerry"] = "", -- A_Classic_Fairytale:queen -- ["Have no illusions, your tribe is dead, indifferent of your choice."] = "", -- A_Classic_Fairytale:shadow -- ["Have we ever attacked you first?"] = "", -- A_Classic_Fairytale:enemy +-- ["Healing Station"] = "", -- Construction_Mode +-- ["Health Crate Placement Mode"] = "", -- Construction_Mode -- ["Health crates extend your time."] = "", -- ["Heavy"] = "", -- ["Heavy Cannfantry"] = "", -- A_Classic_Fairytale:united -- ["Hedge-cogs"] = "", -- A_Classic_Fairytale:enemy --- ["Hedgehog projectile: [fire your hog like a Sticky Bomb]"] = "", -- Continental_supplies +-- ["Hedgehog projectile: [Fire your hog like a Sticky Bomb]"] = "", -- Continental_supplies + -- ["Hedgewars-Basketball"] = "", -- ["Hedgewars-Knockball"] = "", -- ["Hedgibal Lecter"] = "", -- A_Classic_Fairytale:backstab -- ["Heh, it's not that bad."] = "", +-- ["Hellish Handgrenade"] = "", -- Construction_Mode -- ["Hello again, "] = "", -- A_Classic_Fairytale:family -- ["Help me, Leaks!"] = "", -- A_Classic_Fairytale:journey -- ["Help me, please!!!"] = "", -- A_Classic_Fairytale:journey @@ -333,6 +404,7 @@ -- ["Hogminator"] = "", -- A_Classic_Fairytale:family -- ["Hogs in sight!"] = "", -- Continental_supplies -- ["HOLY SHYTE!"] = "", -- Mutant +-- ["Homing Bee"] = "", -- Construction_Mode -- ["Honest Lee"] = "", -- A_Classic_Fairytale:enemy -- ["Hooray!"] = "", -- ["Hostage Situation"] = "", -- A_Classic_Fairytale:family @@ -366,7 +438,6 @@ -- ["If you get stuck, use your Desert Eagle or restart the mission!|"] = "", -- A_Classic_Fairytale:journey -- ["If you know what I mean..."] = "", -- A_Classic_Fairytale:shadow -- ["If you say so..."] = "", -- A_Classic_Fairytale:shadow - -- ["I guess you'll have to kill them."] = "", -- A_Classic_Fairytale:dragon -- ["I have come to make you an offering..."] = "", -- A_Classic_Fairytale:shadow -- ["I have no idea where that mole disappeared...Can you see it?"] = "", -- A_Classic_Fairytale:shadow @@ -389,6 +460,7 @@ -- ["I'm not sure about that!"] = "", -- A_Classic_Fairytale:united -- ["Impressive...you are still dry as the corpse of a hawk after a week in the desert..."] = "", -- A_Classic_Fairytale:first_blood -- ["I'm so scared!"] = "", -- A_Classic_Fairytale:united +-- ["Increase"] = "", -- Continental_supplies -- ["Incredible..."] = "", -- A_Classic_Fairytale:shadow -- ["I need to find the others!"] = "", -- A_Classic_Fairytale:backstab -- ["I need to get to the other side of this island, fast!"] = "", -- A_Classic_Fairytale:journey @@ -397,12 +469,14 @@ -- ["I need to warn the others."] = "", -- A_Classic_Fairytale:backstab -- ["In fact, you are the only one that's been acting strangely."] = "", -- A_Classic_Fairytale:backstab -- ["In order to get to the other side, you need to collect the crates first.|"] = "", -- A_Classic_Fairytale:dragon +-- ["INSANITY"] = "", -- Mutant -- ["Instructor"] = "", -- 01#Boot_Camp, User_Mission_-_Dangerous_Ducklings -- ["Interesting idea, haha!"] = "", -- A_Classic_Fairytale:enemy -- ["Interesting! Last time you said you killed a cannibal!"] = "", -- A_Classic_Fairytale:backstab -- ["In the meantime, take these and return to your \"friend\"!"] = "", -- A_Classic_Fairytale:shadow -- ["invaders destroyed"] = "", -- ["Invasion"] = "", -- A_Classic_Fairytale:united +-- ["Invulnerable"] = "", -- Construction_Mode -- ["I saw it with my own eyes!"] = "", -- A_Classic_Fairytale:shadow -- ["I see..."] = "", -- A_Classic_Fairytale:shadow -- ["I see you have already taken the leap of faith."] = "", -- A_Classic_Fairytale:first_blood @@ -445,6 +519,7 @@ -- ["Just kidding, none of you have died!"] = "", -- A_Classic_Fairytale:enemy -- ["Just on a walk."] = "", -- A_Classic_Fairytale:united -- ["Just wait till I get my hands on that trauma! ARGH!"] = "", -- A_Classic_Fairytale:family +-- ["Kamikaze"] = "", -- Construction_Mode -- ["Kamikaze Expert!"] = "", -- ["Keep it up!"] = "", -- ["Kerguelen"] = "", -- Continental_supplies @@ -454,6 +529,8 @@ -- ["Kill the aliens!"] = "", -- A_Classic_Fairytale:dragon -- ["Kill the cannibal!"] = "", -- A_Classic_Fairytale:first_blood -- ["Kill the traitor...or spare his life!|Kill him or press [Precise]!"] = "", -- A_Classic_Fairytale:backstab +-- ["Land Sprayer"] = "", -- Construction_Mode +-- ["Laser Sight"] = "", -- Construction_Mode -- ["Last Target!"] = "", -- ["Leader"] = "", -- A_Classic_Fairytale:enemy -- ["Leaderbot"] = "", -- A_Classic_Fairytale:queen @@ -464,6 +541,7 @@ -- ["Led Heart"] = "", -- A_Classic_Fairytale:queen -- ["Lee"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen -- ["[Left Shift]"] = "", +-- ["left shift"] = "", -- Continental_supplies -- ["Let a Continent provide your weapons!"] = "", -- Continental_supplies -- ["Let me test your skills a little, will you?"] = "", -- A_Classic_Fairytale:journey -- ["Let's go home!"] = "", -- A_Classic_Fairytale:journey @@ -473,41 +551,56 @@ -- ["Let them have a taste of my fury!"] = "", -- A_Classic_Fairytale:backstab -- ["Let us help, too!"] = "", -- A_Classic_Fairytale:backstab -- ["Light Cannfantry"] = "", -- A_Classic_Fairytale:united +-- ["Limburger"] = "", -- Construction_Mode -- ["Listen up, maggot!!"] = "", -- ["Little did they know that this hunt will mark them forever..."] = "", -- A_Classic_Fairytale:shadow -- ["Lively Lifeguard"] = "", --- ["Lonely Cries: [Rise the water if no hog is in the circle and deal 1 damage to all hogs]"] = "", -- Continental_supplies + +-- ["Lonely Cries: [Rise the water if no hog is in the circle and deal 7 damage to all enemy hogs]"] = "", -- Continental_supplies +-- ["Lonely Hog"] = "", -- ClimbHome -- ["Look, I had no choice!"] = "", -- A_Classic_Fairytale:backstab -- ["Look out! There's more of them!"] = "", -- A_Classic_Fairytale:backstab -- ["Look out! We're surrounded by cannibals!"] = "", -- A_Classic_Fairytale:enemy -- ["Looks like the whole world is falling apart!"] = "", -- A_Classic_Fairytale:enemy +-- ["Low Gravity"] = "", -- Construction_Mode, Frenzy -- ["Luckily, I've managed to snatch some of them."] = "", -- A_Classic_Fairytale:united -- ["LUDICROUS KILL"] = "", -- Mutant +-- ["Made it!"] = "", -- ClimbHome +-- ["- Massive weapon bonus on first turn"] = "", -- Continental_supplies -- ["May the spirits aid you in all your quests!"] = "", -- A_Classic_Fairytale:backstab -- ["Medicine: [Fire some exploding medicine that will heal all hogs effected by the explosion]"] = "", -- Continental_supplies -- ["MEGA KILL"] = "", -- Mutant -- ["Meiwes"] = "", -- A_Classic_Fairytale:backstab -- ["Mindy"] = "", -- A_Classic_Fairytale:united +-- ["Mine"] = "", -- Construction_Mode, Frenzy -- ["Mine Deployer"] = "", -- ["Mine Eater!"] = "", +-- ["Mine Placement Mode"] = "", -- Construction_Mode -- ["|- Mines Time:"] = "", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork +-- ["Mine Strike"] = "", -- Construction_Mode -- ["MISSION FAILED"] = "", -- User_Mission_-_Dangerous_Ducklings, User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork -- ["MISSION SUCCESS"] = "", -- ["MISSION SUCCESSFUL"] = "", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork +-- ["Molotov Cocktail"] = "", -- Construction_Mode -- ["Molotov"] = "", -- Continental_supplies -- ["MONSTER KILL"] = "", -- Mutant -- ["More Natives"] = "", -- A_Classic_Fairytale:epil +-- ["Mortar"] = "", -- Construction_Mode, A_Space_Adventure:death02 -- ["Movement: [Up], [Down], [Left], [Right]"] = "", +-- ["Mudball"] = "", -- Construction_Mode -- ["Multi-shot!"] = "", -- ["Muriel"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen -- ["Muscle Dissolver"] = "", -- A_Classic_Fairytale:shadow -- ["-------"] = "", -- Mutant +-- ["Mutant"] = "", -- Mutant -- ["Nade Boy"] = "", -- Basic_Training_-_Grenade -- ["Name"] = "", -- A_Classic_Fairytale:queen -- ["Nameless Heroes"] = "", -- ["Nancy Screw"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:queen +-- ["Napalm"] = "", -- Construction_Mode -- ["Napalm rocket: [Fire a bomb with napalm!]"] = "", -- Continental_supplies -- ["Natives"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:first_blood, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united +-- ["Naughty Ninja"] = "", -- User_Mission_-_Dangerous_Ducklings -- ["New Barrels Per Turn"] = "", -- ["NEW CLAN RECORD: "] = "", -- ["NEW fastest lap: "] = "", @@ -518,6 +611,7 @@ -- ["Nice work, "] = "", -- A_Classic_Fairytale:dragon -- ["Nice work!"] = "", -- A_Classic_Fairytale:enemy -- ["Nilarian"] = "", -- A_Classic_Fairytale:queen +-- ["Nobody Laugh"] = "", -- User_Mission_-_Nobody_Laugh -- ["No, I came back to help you out..."] = "", -- A_Classic_Fairytale:shadow -- ["No...I wonder where they disappeared?!"] = "", -- A_Classic_Fairytale:journey -- ["Nom-Nom"] = "", -- A_Classic_Fairytale:journey @@ -525,6 +619,7 @@ -- ["Nope. It was one fast mole, that's for sure."] = "", -- A_Classic_Fairytale:shadow -- ["No! Please, help me!"] = "", -- A_Classic_Fairytale:journey -- ["NORMAL"] = "", -- Continental_supplies +-- ["Normal players can only score points by killing the mutant."] = "", -- Mutant -- ["North America"] = "", -- Continental_supplies -- ["Not all hogs are born equal."] = "", -- Highlander -- ["NOT ENOUGH WAYPOINTS"] = "", @@ -537,6 +632,7 @@ -- ["No. Where did he come from?"] = "", -- A_Classic_Fairytale:shadow -- ["Now how do I get on the other side?!"] = "", -- A_Classic_Fairytale:dragon -- ["No. You and the rest of the tribe are safer there!"] = "", -- A_Classic_Fairytale:backstab +-- ["Object Placement Tool"] = "", -- Construction_Mode -- ["Obliterate them!|Hint: You might want to take cover..."] = "", -- A_Classic_Fairytale:shadow -- ["Obstacle course"] = "", -- A_Classic_Fairytale:dragon -- ["Of course I have to save her. What did I expect?!"] = "", -- A_Classic_Fairytale:family @@ -553,24 +649,30 @@ -- ["Once upon a time, on an island with great natural resources, lived two tribes in heated conflict..."] = "", -- A_Classic_Fairytale:first_blood -- ["ONE HOG PER TEAM! KILLING EXCESS HEDGES"] = "", -- Mutant -- ["One tribe was peaceful, spending their time hunting and training, enjoying the small pleasures of life..."] = "", -- A_Classic_Fairytale:first_blood +-- ["on Skip"] = "", -- Continental_supplies -- ["Oops...I dropped them."] = "", -- A_Classic_Fairytale:united -- ["Open that crate and we will continue!"] = "", -- A_Classic_Fairytale:first_blood -- ["Operation Diver"] = "", -- ["Opposing Team: "] = "", +-- ["or 'g=50, g2=150, period=4000' for gravity changing|from 50 to 150 and back with period of 4000 msec"] = "", -- Gravity -- ["Orlando Boom!"] = "", -- A_Classic_Fairytale:queen +-- ["Other kills don't give you points."] = "", -- Mutant -- ["Ouch!"] = "", -- User_Mission_-_Rope_Knock_Challenge -- ["Our tribe, our beautiful island!"] = "", -- A_Classic_Fairytale:enemy -- ["Parachute"] = "", -- Continental_supplies -- ["Pathetic Hog #%d"] = "", -- ["Pathetic Resistance"] = "", -- User_Mission_-_Bamboo_Thicket, User_Mission_-_Newton_and_the_Hammock +-- ["Penguin roar: [Deal 15 damage + 15% of your hogs health to all hogs around you and get 2/3 back]"] = "", -- Continental_supplies -- ["Perfect! Now try to get the next crate without hurting yourself!"] = "", -- A_Classic_Fairytale:first_blood -- ["Per-Hog Ammo"] = "", --- ["- Per team weapons|- 9 weaponschemes|- Unique new weapons| |Select continent first round with the Weapon Menu or by ([switch/tab]=Increase,[precise/left shift]=Decrease) on Skip|Some weapons have a second option. Find them with [switch/tab]"] = "", -- Continental_supplies +-- ["Personal Portal Device"] = "", -- Construction_Mode +-- ["Per team weapons"] = "", -- Continental_supplies -- ["Pfew! That was close!"] = "", -- A_Classic_Fairytale:shadow --- ["Piñata bullet: [Contains some sweet candy!]"] = "", -- Continental_supplies +-- ["Piano Strike"] = "", -- Construction_Mode +-- ["Pickhammer"] = "", -- Construction_Mode + -- ["Pings left:"] = "", -- Space_Invasion - -- ["Place more waypoints using the 'Air Attack' weapon."] = "", -- ["Planes Used:"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Planes Used"] = "", -- User_Mission_-_RCPlane_Challenge @@ -580,14 +682,18 @@ -- ["Please, stop releasing your \"smoke signals\"!"] = "", -- A_Classic_Fairytale:shadow -- ["Point Blank Combo!"] = "", -- Space_Invasion -- ["points"] = "", -- Control, CTF_Blizzard, Basic_Training_-_Bazooka, Basic_Training_-_Shotgun, Basic_Training_-_Sniper_Rifle +-- ["POINTS"] = "", -- Mutant -- ["Poison"] = "", +-- ["Population"] = "", -- Continental_supplies -- ["Portal hint: one goes to the destination, and one is the entrance.|"] = "", -- A_Classic_Fairytale:dragon -- ["Portal mission"] = "", -- portal -- ["Power Remaining"] = "", -- ["Prepare yourself"] = "", +-- ["presice"] = "", -- Continental_supplies -- ["Press [Enter] to accept this configuration."] = "", -- WxW -- ["Press [Left] or [Right] to move around, [Enter] to jump"] = "", -- A_Classic_Fairytale:first_blood -- ["Press [Precise] to skip intro"] = "", +-- ["Prestigious Pilot"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Private Novak"] = "", -- Basic_Training_-_Cluster_Bomb -- ["Protect yourselves!|Grenade hint: set the timer with [1-5], aim with [Up]/[Down] and hold [Space] to set power"] = "", -- A_Classic_Fairytale:shadow -- ["Race complexity limit reached."] = "", @@ -596,26 +702,40 @@ -- ["Radar Ping"] = "", -- Space_Invasion -- ["Raging Buffalo"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united -- ["Ramon"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow +-- ["random in range from %i%% to %i%% with period of %i msec"] = "", -- Gravity +-- ["RC Plane"] = "", -- Construction_Mode -- ["RC PLANE TRAINING"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Really?! You thought you could harm me with your little toys?"] = "", -- A_Classic_Fairytale:shadow +-- ["Reflector Shield"] = "", -- Construction_Mode +-- ["Reflects enemy projectiles."] = "", -- Construction_Mode -- ["Regurgitator"] = "", -- A_Classic_Fairytale:backstab -- ["Reinforcements"] = "", -- A_Classic_Fairytale:backstab -- ["Remember: The rope only bend around objects, |if it doesn't hit anything it's always stright!"] = "", -- Basic_Training_-_Rope -- ["Remember this, pathetic animal: when the day comes, you will regret your blind loyalty!"] = "", -- A_Classic_Fairytale:shadow +-- ["REMOVED"] = "", -- Continental_supplies +-- ["Respawner"] = "", -- Construction_Mode +-- ["Resurrector"] = "", -- Construction_Mode +-- ["Resurrects dead hedgehogs."] = "", -- Construction_Mode -- [" - Return the enemy flag to your base to score | - First team to 3 captures wins | - You may only score when your flag is in your base | - Hogs will drop the flag if killed, or drowned | - Dropped flags may be returned or recaptured | - Hogs respawn when killed"] = "", -- ["Return to Leaks A Lot! If you get stuck, press [Precise] to try again!"] = "", -- A_Classic_Fairytale:shadow -- ["Righteous Beard"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:first_blood, A_Classic_Fairytale:queen, A_Classic_Fairytale:united +-- ["Rope"] = "", -- Construction_Mode -- ["ROPE-KNOCKING"] = "", -- User_Mission_-_Rope_Knock_Challenge +-- ["Rope to safety"] = "", -- ClimbHome -- ["Rope Training"] = "", -- Basic_Training_-_Rope -- ["Rot Molester"] = "", -- A_Classic_Fairytale:shadow -- ["Round Limit:"] = "", -- ["Round Limit"] = "", -- ["Rounds Complete: "] = "", -- ["Rounds Complete"] = "", +-- ["Rubber Band"] = "", -- Construction_Mode +-- ["Rubber Placement Mode"] = "", -- Construction_Mode +-- ["RULES"] = "", -- Frenzy, Mutant -- ["RULES OF THE GAME [Press ESC to view]"] = "", -- ["Rusty Joe"] = "", -- A_Classic_Fairytale:queen -- ["s|"] = "", --- ["Sabotage: [Sabotage all hogs in the circle and deal ~10 dmg]"] = "", -- Continental_supplies +-- ["Sabotage/Flare: [Sabotage all hogs in the circle and deal ~1 dmg OR Fire a cluster up into the air]"] = "", -- Continental_supplies + -- ["Salivaslurper"] = "", -- A_Classic_Fairytale:united -- ["Salvation"] = "", -- A_Classic_Fairytale:family -- ["Salvation was one step closer now..."] = "", -- A_Classic_Fairytale:dragon @@ -627,7 +747,7 @@ -- ["Scalp Muncher"] = "", -- A_Classic_Fairytale:backstab -- ["SCORE"] = "", -- ["Score"] = "", -- Mutant --- ["Scream from a Walrus: [Deal 20 damage + 10% of your hogs health to all hogs around you and get half back]"] = "", -- Continental_supplies + -- ["sec"] = "", -- CTF_Blizzard, TrophyRace, Basic_Training_-_Bazooka, Basic_Training_-_Shotgun, Basic_Training_-_Sniper_Rifle, User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork, Capture_the_Flag -- ["Seduction"] = "", -- Continental_supplies -- ["Seems like every time you take a \"walk\", the enemy find us!"] = "", -- A_Classic_Fairytale:backstab @@ -635,8 +755,11 @@ -- ["See ya!"] = "", -- ["Segmentation Paul"] = "", -- A_Classic_Fairytale:dragon -- ["Select continent!"] = "", -- Continental_supplies +-- ["Select continent first round with the Weapon Menu or by"] = "", -- Continental_supplies -- ["Select difficulty: [Left] - easier or [Right] - harder"] = "", -- A_Classic_Fairytale:first_blood -- ["selected!"] = "", +-- ["Set period to negative value for random gravity"] = "", -- Gravity +-- ["Setup:|'g=150', where 150 is 150% of normal gravity"] = "", -- Gravity -- ["s"] = "", -- GaudyRacer, Space_Invasion -- ["... share your beauty with the world every morning, my princess!"] = "", -- A_Classic_Fairytale:journey -- ["She's behind that tall thingy."] = "", -- A_Classic_Fairytale:family @@ -648,16 +771,21 @@ -- ["Shield OFF:"] = "", -- ["Shield ON:"] = "", -- ["Shield Seeker!"] = "", +-- ["Shoryuken"] = "", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 -- ["Shotgun"] = "", -- Continental_supplies -- ["Shotgun Team"] = "", -- ["Shotgun Training"] = "", -- ["shots remaining."] = "", -- ["Silly"] = "", +-- ["SineGun"] = "", -- Construction_Mode -- ["Sinky"] = "", -- ["Sirius Lee"] = "", -- A_Classic_Fairytale:enemy -- ["%s is out and Team %d|scored a penalty!| |Score:"] = "", -- Basketball, Knockball -- ["%s is out and Team %d|scored a point!| |Score:"] = "", -- Basketball, Knockball -- ["Slippery"] = "", -- A_Classic_Fairytale:journey +-- ["Slot"] = "", -- Frenzy +-- ["Slot keys save time! (F1-F10 by default)"] = "", -- Frenzy +-- ["SLOTS"] = "", -- Frenzy -- ["Smith 0.97"] = "", -- A_Classic_Fairytale:enemy -- ["Smith 0.98"] = "", -- A_Classic_Fairytale:enemy -- ["Smith 0.99a"] = "", -- A_Classic_Fairytale:enemy @@ -669,6 +797,7 @@ -- ["Sniper Training"] = "", -- ["Sniperz"] = "", -- ["So humiliating..."] = "", -- A_Classic_Fairytale:first_blood +-- ["Some weapons have a second option. Find them with"] = "", -- Continental_supplies -- ["South America"] = "", -- Continental_supplies -- ["So? What will it be?"] = "", -- A_Classic_Fairytale:shadow -- ["Spawn the crate, and attack!"] = "", -- WxW @@ -677,25 +806,43 @@ -- ["Spleenlover"] = "", -- A_Classic_Fairytale:united -- ["Sponge"] = "", -- ["Spooky Tree"] = "", +-- ["Sprite Placement Mode"] = "", -- Construction_Mode +-- ["Sprite Testing Mode"] = "", -- Construction_Mode -- ["STATUS UPDATE"] = "", -- GaudyRacer, Space_Invasion -- ["Steel Eye"] = "", -- A_Classic_Fairytale:queen -- ["Step By Step"] = "", -- A_Classic_Fairytale:first_blood -- ["Steve"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen -- ["Sticky Mine"] = "", -- Continental_supplies +-- ["Sticky Mine Placement Mode"] = "", -- Construction_Mode -- ["Stronglings"] = "", -- A_Classic_Fairytale:shadow --- ["Structure"] = "", -- Continental_supplies + +-- ["Structure Placement Mode"] = "", -- Construction_Mode +-- ["Structure Placement Tool"] = "", -- Construction_Mode +-- ["Sundaland"] = "", -- Continental_supplies -- ["Super Weapons"] = "", -- WxW +-- ["Support Station"] = "", -- Construction_Mode -- ["Surf Before Crate"] = "", -- WxW -- ["Surfer! +15 points!"] = "", -- Space_Invasion -- ["Surfer!"] = "", -- WxW -- ["Survive!|Hint: Cinematics can be skipped with the [Precise] key."] = "", -- A_Classic_Fairytale:shadow -- ["Swing, Leaks A Lot, on the wings of the wind!"] = "", -- A_Classic_Fairytale:first_blood +-- ["switch"] = "", -- Continental_supplies -- ["Switched to "] = "", +-- ["Switch Hog"] = "", -- Construction_Mode -- ["Syntax Errol"] = "", -- A_Classic_Fairytale:dragon +-- ["tab"] = "", -- Continental_supplies +-- ["Tagging Mode"] = "", -- Construction_Mode -- ["Talk about mixed signals..."] = "", -- A_Classic_Fairytale:dragon +-- ["Tardis"] = "", -- Construction_Mode +-- ["Target Placement Mode"] = "", -- Construction_Mode -- ["Team %d: "] = "", -- ["Team Scores"] = "", -- Control, Space_Invasion +-- ["Teleporation Node"] = "", -- Construction_Mode +-- ["Teleportation Mode"] = "", -- Construction_Mode +-- ["Teleportation Node"] = "", -- Construction_Mode +-- ["Teleport"] = "", -- Construction_Mode, Frenzy -- ["Teleport hint: just use the mouse to select the destination!"] = "", -- A_Classic_Fairytale:dragon +-- ["Teleport Unsuccessful. Please teleport within a clan teleporter's sphere of influence."] = "", -- Construction_Mode -- ["Thanks!"] = "", -- A_Classic_Fairytale:family -- ["Thank you, my hero!"] = "", -- A_Classic_Fairytale:family -- ["Thank you, oh, thank you, Leaks A Lot!"] = "", -- A_Classic_Fairytale:journey @@ -712,6 +859,7 @@ -- ["That was pointless."] = "", -- ["The answer is...entertaintment. You'll see what I mean."] = "", -- A_Classic_Fairytale:backstab -- ["The anti-portal zone is all over the floor, and I have nothing to kill him...Droping something could hurt him enough to kill him..."] = "", -- portal +-- ["The Bottom Feeder can score points by killing anyone."] = "", -- Mutant -- ["The Bull's Eye"] = "", -- A_Classic_Fairytale:first_blood -- ["The caves are well hidden, they won't find us there!"] = "", -- A_Classic_Fairytale:united -- ["The Crate Frenzy"] = "", -- A_Classic_Fairytale:first_blood @@ -721,20 +869,26 @@ -- ["The Enemy Of My Enemy"] = "", -- A_Classic_Fairytale:enemy -- ["The First Blood"] = "", -- A_Classic_Fairytale:first_blood -- ["The First Encounter"] = "", -- A_Classic_Fairytale:shadow +-- ["The first player to kill someone becomes the Mutant."] = "", -- Mutant -- ["The flag will respawn next round."] = "", -- ["The food bites back"] = "", -- A_Classic_Fairytale:backstab -- ["The giant umbrella from the last crate should help break the fall."] = "", -- A_Classic_Fairytale:first_blood -- ["The Great Escape"] = "", -- User_Mission_-_The_Great_Escape +-- ["The Great Hog in the sky sees your sadness and grants you a boon."] = "", -- Construction_Mode -- ["The guardian"] = "", -- A_Classic_Fairytale:shadow -- ["The Individualist"] = "", -- A_Classic_Fairytale:shadow -- ["Their buildings were very primitive back then, even for an uncivilised island."] = "", -- A_Classic_Fairytale:united -- ["The Journey Back"] = "", -- A_Classic_Fairytale:journey -- ["The Leap of Faith"] = "", -- A_Classic_Fairytale:first_blood -- ["The Moonwalk"] = "", -- A_Classic_Fairytale:journey +-- ["The Mutant has super-weapons and a lot of health."] = "", -- Mutant +-- ["The Mutant loses health quickly if he doesn't keep scoring kills."] = "", -- Mutant -- ["The Nameless One"] = "", -- ["The next one is pretty hard! |Tip: You have to do multiple swings!"] = "", -- Basic_Training_-_Rope -- ["Then how do they keep appearing?"] = "", -- A_Classic_Fairytale:shadow -- ["The other one were all cannibals, spending their time eating the organs of fellow hedgehogs..."] = "", -- A_Classic_Fairytale:first_blood +-- ["The player with least points (or most deaths) becomes the Bottom Feeder."] = "", -- Mutant +-- ["There are a variety of structures available to aid you."] = "", -- Construction_Mode -- ["There must be a spy among us!"] = "", -- A_Classic_Fairytale:backstab -- ["There's more of them? When did they become so hungry?"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united -- ["There's nothing more satisfying for me than seeing you share your beauty with the world every morning, my princess!"] = "", -- A_Classic_Fairytale:journey @@ -790,7 +944,7 @@ -- ["To the caves..."] = "", -- A_Classic_Fairytale:united -- ["Toxic Team"] = "", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork -- ["TRACK COMPLETED"] = "", --- ["TRACK FAILED!"] = "", + -- ["training"] = "", -- portal -- ["Traitors"] = "", -- A_Classic_Fairytale:epil -- ["Tribe"] = "", -- A_Classic_Fairytale:backstab @@ -807,6 +961,7 @@ -- ["ULTRA KILL"] = "", -- Mutant -- ["Under Construction"] = "", -- A_Classic_Fairytale:shadow -- ["Unexpected Igor"] = "", -- A_Classic_Fairytale:dragon +-- ["Unique new weapons"] = "", -- Continental_supplies -- ["Unit"] = "", -- ["Unit 0x0007"] = "", -- A_Classic_Fairytale:family -- ["Unit 334a$7%;.*"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united @@ -821,11 +976,14 @@ -- ["Use it wisely!"] = "", -- A_Classic_Fairytale:dragon -- ["Use it with precaution!"] = "", -- A_Classic_Fairytale:first_blood -- ["User Challenge"] = "", - +-- ["Use the air-attack weapons and the arrow keys to select structures."] = "", -- Construction_Mode -- ["Use the portal gun to get to the next crate, then use the new gun to get to the final destination!|"] = "", -- A_Classic_Fairytale:dragon -- ["Use the rope to get on the head of the mole, young one!"] = "", -- A_Classic_Fairytale:first_blood -- ["Use the rope to knock your enemies to their doom."] = "", -- User_Mission_-_Rope_Knock_Challenge +-- ["Use your ready time to think."] = "", -- Frenzy -- ["Use your rope to get from start to finish as fast as you can!"] = "", +-- ["Utility Crate Placement Mode"] = "", -- Construction_Mode +-- ["Vampirism"] = "", -- Construction_Mode -- ["Vedgies"] = "", -- A_Classic_Fairytale:journey -- ["Vegan Jack"] = "", -- A_Classic_Fairytale:enemy -- ["Victory!"] = "", -- Basic_Training_-_Rope @@ -837,10 +995,14 @@ -- ["Wannabe Flyboys"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Wannabe Shoppsta"] = "", -- User_Mission_-_Rope_Knock_Challenge -- ["Watch your steps, young one!"] = "", -- A_Classic_Fairytale:first_blood +-- ["Watermelon Bomb"] = "", -- Construction_Mode -- ["Waypoint placed."] = "", -- ["Way-Points Remaining"] = "", -- ["Weaklings"] = "", -- A_Classic_Fairytale:shadow -- ["We all know what happens when you get frightened..."] = "", -- A_Classic_Fairytale:first_blood +-- ["Weapon Crate Placement Mode"] = "", -- Construction_Mode +-- ["Weapon Filter"] = "", -- Construction_Mode +-- ["weaponschemes"] = "", -- Continental_supplies -- ["Weapons Reset"] = "", -- ["Weapons reset."] = "", -- Highlander -- ["We are indeed."] = "", -- A_Classic_Fairytale:backstab @@ -893,6 +1055,7 @@ -- ["Where do you get that?!"] = "", -- A_Classic_Fairytale:enemy -- ["Where have you been?!"] = "", -- A_Classic_Fairytale:backstab -- ["Where have you been?"] = "", -- A_Classic_Fairytale:united +-- ["Whip"] = "", -- Construction_Mode -- ["? Why?"] = "", -- A_Classic_Fairytale:backstab -- ["Why "] = "", -- A_Classic_Fairytale:backstab -- ["! Why?!"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united @@ -905,8 +1068,10 @@ -- ["Why me?!"] = "", -- A_Classic_Fairytale:backstab -- ["Why would they do this?"] = "", -- A_Classic_Fairytale:backstab -- ["- Will Get 1-3 random weapons"] = "", -- Continental_supplies --- ["- Will refresh Parachute each turn."] = "", -- Continental_supplies --- ["- Will refresh portalgun each turn."] = "", -- Continental_supplies +-- ["- Will give you an airstrike every fifth turn."] = "", -- Continental_supplies +-- ["- Will give you a parachute every second turn."] = "", -- Continental_supplies + + -- ["Will this ever end?"] = "", -- ["WINNER IS "] = "", -- Mutant -- ["WINNING TIME: "] = "", @@ -925,6 +1090,7 @@ -- ["Yes!"] = "", -- A_Classic_Fairytale:enemy -- ["Yes, yeees! You are now ready to enter the real world!"] = "", -- A_Classic_Fairytale:first_blood -- ["Yo, dude, we're here, too!"] = "", -- A_Classic_Fairytale:family +-- ["You are far from home, and the water is rising, climb up as high as you can!"] = "", -- ClimbHome -- ["You are given the chance to turn your life around..."] = "", -- A_Classic_Fairytale:shadow -- ["You are playing with our lives here!"] = "", -- A_Classic_Fairytale:enemy -- ["! You bastards!"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united @@ -957,6 +1123,8 @@ -- ["You know what? I don't even regret anything!"] = "", -- A_Classic_Fairytale:backstab -- ["You'll see what I mean!"] = "", -- A_Classic_Fairytale:enemy -- ["You may only attack from a rope!"] = "", -- WxW +-- ["You may only spawn 5 crates per turn."] = "", -- Construction_Mode +-- ["You may only use 1 Extra Time per turn."] = "", -- Construction_Mode -- ["You meatbags are pretty slow, you know!"] = "", -- A_Classic_Fairytale:enemy -- ["You might want to find a way to instantly kill arriving cannibals!"] = "", -- A_Classic_Fairytale:backstab -- ["Young one, you are telling us that they can instantly change location without a shaman?"] = "", -- A_Classic_Fairytale:united @@ -977,6 +1145,7 @@ -- ["You've failed. Try again."] = "", -- ["You've reached the goal!| |Time: "] = "", -- ["You will be avenged!"] = "", -- A_Classic_Fairytale:shadow +-- ["- You will recieve 2-4 weapons on each kill! (Even on own hogs)"] = "", -- Continental_supplies -- ["You won't believe what happened to me!"] = "", -- A_Classic_Fairytale:backstab -- ["Yuck! I bet they'll keep worshipping her even after I save the village!"] = "", -- A_Classic_Fairytale:family -- ["Zealandia"] = "", -- Continental_supplies diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/lt.lua --- a/share/hedgewars/Data/Locale/lt.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/lt.lua Tue Nov 10 20:43:13 2015 +0100 @@ -4,6 +4,10 @@ ["..."] = "...", -- ["011101000"] = "", -- A_Classic_Fairytale:dragon -- ["011101001"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:family, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united +-- ["+1 to a Bottom Feeder for killing anyone"] = "", -- Mutant +-- ["+1 to a Mutant for killing anyone"] = "", -- Mutant +-- ["-1 to anyone for a suicide"] = "", -- Mutant +-- ["+2 for becoming a Mutant"] = "", -- Mutant -- ["30 minutes later..."] = "", -- A_Classic_Fairytale:shadow -- ["About a month ago, a cyborg came and told us that you're the cannibals!"] = "", -- A_Classic_Fairytale:enemy ["Accuracy Bonus!"] = "Taiklumo Bonusas!", @@ -13,17 +17,27 @@ -- ["???"] = "", -- A_Classic_Fairytale:backstab -- ["Actually, you aren't worthy of life! Take this..."] = "", -- A_Classic_Fairytale:shadow -- ["A cy-what?"] = "", -- A_Classic_Fairytale:enemy +-- ["Advanced Repositioning Mode"] = "", -- Construction_Mode -- ["Adventurous"] = "", -- A_Classic_Fairytale:journey +-- ["a frenetic Hedgewars mini-game"] = "", -- Frenzy -- ["Africa"] = "", -- Continental_supplies -- ["After Leaks A Lot betrayed his tribe, he joined the cannibals..."] = "", -- A_Classic_Fairytale:first_blood -- ["After the shock caused by the enemy spy, Leaks A Lot and Dense Cloud went hunting to relax."] = "", -- A_Classic_Fairytale:shadow -- ["Again with the 'cannibals' thing!"] = "", -- A_Classic_Fairytale:enemy +-- ["Aggressively removes enemy hedgehogs."] = "", -- Construction_Mode -- ["a Hedgewars challenge"] = "", -- User_Mission_-_RCPlane_Challenge, User_Mission_-_Rope_Knock_Challenge ["a Hedgewars mini-game"] = "Eþiu karu mini þaidimas", -- Space_Invasion, The_Specialists +-- ["a Hedgewars tag game"] = "", -- Mutant +-- ["AHHh, home sweet home. Made it in %d seconds."] = "", -- ClimbHome ["Aiming Practice"] = "Taiklumo Treniruotë", --Bazooka, Shotgun, SniperRifle +-- ["Air Attack"] = "", -- Construction_Mode -- ["A leap in a leap"] = "", -- A_Classic_Fairytale:first_blood -- ["A little gift from the cyborgs"] = "", -- A_Classic_Fairytale:shadow -- ["All gone...everything!"] = "", -- A_Classic_Fairytale:enemy +-- ["Allows free teleportation between other nodes."] = "", -- Construction_Mode +-- ["Allows placement of girders, rubber-bands, mines, sticky mines and barrels."] = "", -- Construction_Mode +-- ["Allows placement of structures."] = "", -- Construction_Mode +-- ["Allows the placement of weapons, utiliites, and health crates."] = "", -- Construction_Mode -- ["All right, we just need to get to the other side of the island!"] = "", -- A_Classic_Fairytale:journey -- ["All walls touched!"] = "", -- WxW ["Ammo Depleted!"] = "Nusodrintojo Kulkos!", @@ -38,8 +52,11 @@ -- ["And so they discovered that cyborgs weren't invulnerable..."] = "", -- A_Classic_Fairytale:journey -- ["And where's all the weed?"] = "", -- A_Classic_Fairytale:dragon -- ["And you believed me? Oh, god, that's cute!"] = "", -- A_Classic_Fairytale:journey --- ["Anno 1032: [The explosion will make a strong push ~ wide range, wont affect hogs close to the target]"] = "", -- Continental_supplies +-- ["Anno 1032: [The explosion will make a strong push ~ Wide range, wont affect hogs close to the target]"] = "", -- Continental_supplies + -- ["Antarctica"] = "", -- Continental_supplies +-- ["Antarctic summer: - Will give you one girder/mudball and two sineguns/portals every fourth turn."] = "", -- Continental_supplies +-- ["Area"] = "", -- Continental_supplies -- ["Are we there yet?"] = "", -- A_Classic_Fairytale:shadow -- ["Are you accusing me of something?"] = "", -- A_Classic_Fairytale:backstab -- ["Are you saying that many of us have died for your entertainment?"] = "", -- A_Classic_Fairytale:enemy @@ -59,27 +76,35 @@ -- ["[Backspace]"] = "", -- ["Backstab"] = "", -- A_Classic_Fairytale:backstab -- ["Bad Team"] = "", -- User_Mission_-_The_Great_Escape +-- ["Ballgun"] = "", -- Construction_Mode -- ["Bamboo Thicket"] = "", -- ["Barrel Eater!"] = "", -- ["Barrel Launcher"] = "", +-- ["Barrel Placement Mode"] = "", -- Construction_Mode +-- ["Baseball Bat"] = "", -- Construction_Mode -- ["Baseballbat"] = "", -- Continental_supplies ["Bat balls at your enemies and|push them into the sea!"] = "Dauþk is kamuoliu i savo prieðus|ir nustumk juos i jûra!", ["Bat your opponents through the|baskets and out of the map!"] = "Dauþk savo obonentus pro kaðes|ir ið þemëlapio!", +-- ["Bazooka"] = "", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 ["Bazooka Training"] = "Bazukos Treniruotë", -- ["Beep Loopers"] = "", -- A_Classic_Fairytale:queen ["Best laps per team: "] = "Geriausi ratai per komanda: ", ["Best Team Times: "] = "Geriausios komandos laikai: ", -- ["Beware, though! If you are slow, you die!"] = "", -- A_Classic_Fairytale:dragon +-- ["Bio-Filter"] = "", -- Construction_Mode -- ["Biomechanic Team"] = "", -- A_Classic_Fairytale:family +-- ["Birdy"] = "", -- Construction_Mode -- ["Blender"] = "", -- A_Classic_Fairytale:family -- ["Bloodpie"] = "", -- A_Classic_Fairytale:backstab -- ["Bloodrocutor"] = "", -- A_Classic_Fairytale:shadow -- ["Bloodsucker"] = "", -- A_Classic_Fairytale:shadow ["Bloody Rookies"] = "Prakeikti Eiliniai", -- 01#Boot_Camp, User_Mission_-_Dangerous_Ducklings, User_Mission_-_Diver, User_Mission_-_Spooky_Tree +-- ["Blowtorch"] = "", -- Construction_Mode, Frenzy +-- ["Blue Team"] = "", -- User_Mission_-_Dangerous_Ducklings -- ["Bone Jackson"] = "", -- A_Classic_Fairytale:backstab -- ["Bonely"] = "", -- A_Classic_Fairytale:shadow + ["BOOM!"] = "BOOM!", ["Boom!"] = "Boom!", - ["BOOM!"] = "BOOM!", ["Boss defeated!"] = "Bosas Nugalëtas!", ["Boss Slayer!"] = "Bosu Þudikas!", -- ["Brain Blower"] = "", -- A_Classic_Fairytale:journey @@ -89,6 +114,7 @@ -- ["Brain Teaser"] = "", -- A_Classic_Fairytale:backstab -- ["Brutal Lily"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil -- ["Brutus"] = "", -- A_Classic_Fairytale:backstab +-- ["Build a fortress and destroy your enemy."] = "", -- Construction_Mode -- ["Build a track and race."] = "", -- ["Bullseye"] = "", -- A_Classic_Fairytale:dragon -- ["But it proved to be no easy task!"] = "", -- A_Classic_Fairytale:dragon @@ -99,6 +125,7 @@ -- ["But why would they help us?"] = "", -- A_Classic_Fairytale:backstab -- ["But you're cannibals. It's what you do."] = "", -- A_Classic_Fairytale:enemy -- ["But you said you'd let her go!"] = "", -- A_Classic_Fairytale:journey +-- ["Cake"] = "", -- Construction_Mode -- ["Call me Beep! Well, 'cause I'm such a nice...person!"] = "", -- A_Classic_Fairytale:family -- ["Cannibals"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:first_blood -- ["Cannibal Sentry"] = "", -- A_Classic_Fairytale:journey @@ -108,8 +135,15 @@ -- ["Carol"] = "", -- A_Classic_Fairytale:family -- ["CHALLENGE COMPLETE"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Change Weapon"] = "", +-- ["changing range from %i%% to %i%% with period of %i msec"] = "", -- Gravity -- ["Choose your side! If you want to join the strange man, walk up to him.|Otherwise, walk away from him. If you decide to att...nevermind..."] = "", -- A_Classic_Fairytale:shadow +-- ["Cleaver"] = "", -- Construction_Mode +-- ["Cleaver Placement Mode"] = "", -- Construction_Mode +-- ["Climber"] = "", -- ClimbHome +-- ["Climb Home"] = "", -- ClimbHome +-- ["Clowns"] = "", -- User_Mission_-_Nobody_Laugh ["Clumsy"] = "Durnelis", +-- ["Cluster Bomb"] = "", -- Construction_Mode -- ["Cluster Bomb MASTER!"] = "", -- Basic_Training_-_Cluster_Bomb -- ["Cluster Bomb Training"] = "", -- Basic_Training_-_Cluster_Bomb ["Codename: Teamwork"] = "Kodas: Komandinis Darbas", @@ -129,12 +163,19 @@ -- ["Congratulations! You needed only half of time|to eliminate all targets."] = "", -- Basic_Training_-_Cluster_Bomb -- ["Congratulations! You've completed the Rope tutorial! |- Tutorial ends in 10 seconds!"] = "", -- Basic_Training_-_Rope ["Congratulations! You've eliminated all targets|within the allowed time frame."] = "Sveikinu! Tu pradanginai visus taikinius|per leista laika.", --Bazooka, Shotgun, SniperRifle +-- ["CONSTRUCTION MODE"] = "", -- Construction_Mode +-- ["Construction Station"] = "", -- Construction_Mode -- ["Continental supplies"] = "", -- Continental_supplies ["Control pillars to score points."] = "Valdyk stulpus ir gausi taðku.", +-- ["Core"] = "", -- Construction_Mode -- ["Corporationals"] = "", -- A_Classic_Fairytale:queen -- ["Corpsemonger"] = "", -- A_Classic_Fairytale:shadow -- ["Corpse Thrower"] = "", -- A_Classic_Fairytale:epil +-- ["Cost"] = "", -- Construction_Mode +-- ["Crate Placement Tool"] = "", -- Construction_Mode -- ["Crates Left:"] = "", -- User_Mission_-_RCPlane_Challenge +-- ["Cricket time: [Drop a fireable mine! ~ Will work if fired close to your hog & far away from enemy ~ 1 sec]"] = "", -- Continental_supplies +-- ["Current setting is "] = "", -- Gravity ["Cybernetic Empire"] = "Kibernetinë Karalystë", -- ["Cyborg. It's what the aliens call themselves."] = "", -- A_Classic_Fairytale:enemy -- ["Dahmer"] = "", -- A_Classic_Fairytale:backstab @@ -142,15 +183,19 @@ ["DAMMIT, ROOKIE!"] = "PO VELNIU EILINI!", ["Dangerous Ducklings"] = "Pavojingos Antis", ["Deadweight"] = "Dedveitas", +-- ["Decrease"] = "", -- Continental_supplies -- ["Defeat the cannibals"] = "", -- A_Classic_Fairytale:backstab -- ["Defeat the cannibals!|"] = "", -- A_Classic_Fairytale:united -- ["Defeat the cannibals!|Grenade hint: set the timer with [1-5], aim with [Up]/[Down] and hold [Space] to set power"] = "", -- A_Classic_Fairytale:shadow -- ["Defeat the cyborgs!"] = "", -- A_Classic_Fairytale:enemy +-- ["Defend your core from the enemy."] = "", -- Construction_Mode -- ["Defend yourself!|Hint: You can get tips on using weapons by moving your mouse over them in the weapon selection menu"] = "", -- A_Classic_Fairytale:shadow +-- ["Dematerializes weapons and equipment carried by enemy hedgehogs."] = "", -- Construction_Mode -- ["Demolition is fun!"] = "", -- ["Dense Cloud"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united -- ["Dense Cloud must have already told them everything..."] = "", -- A_Classic_Fairytale:shadow ["Depleted Kamikaze!"] = "Nusodrintojo Kamikaze!", +-- ["Desert Eagle"] = "", -- Construction_Mode, A_Space_Adventure:death02 -- ["Destroy him, Leaks A Lot! He is responsible for the deaths of many of us!"] = "", -- A_Classic_Fairytale:first_blood ["Destroy invaders to score points."] = "Sunaikink Isiverþëjus Ir Gauk Taðku.", -- ["Destroy the targets!|Hint: Select the Shoryuken and hit [Space]|P.S. You can use it mid-air."] = "", -- A_Classic_Fairytale:first_blood @@ -169,9 +214,12 @@ -- ["Do you have any idea how valuable grass is?"] = "", -- A_Classic_Fairytale:enemy -- ["Do you think you're some kind of god?"] = "", -- A_Classic_Fairytale:enemy -- ["Dragon's Lair"] = "", -- A_Classic_Fairytale:dragon +-- ["Drill Rocket"] = "", -- Construction_Mode -- ["Drills"] = "", -- A_Classic_Fairytale:backstab +-- ["Drill Strike"] = "", -- Construction_Mode ["Drone Hunter!"] = "Drone Medþiotojas!", --- ["Drop a bomb: [drop some heroic wind that will turn into a bomb on impact]"] = "", -- Continental_supplies +-- ["Drop a bomb: [Drop some heroic wind that will turn into a bomb on impact]"] = "", -- Continental_supplies + ["Drowner"] = "Skendëjas", -- ["Dude, all the plants are gone!"] = "", -- A_Classic_Fairytale:family -- ["Dude, can you see Ramon and Spiky?"] = "", -- A_Classic_Fairytale:journey @@ -181,11 +229,15 @@ -- ["Dude, where are we?"] = "", -- A_Classic_Fairytale:backstab -- ["Dude, wow! I just had the weirdest high!"] = "", -- A_Classic_Fairytale:backstab -- ["Duration"] = "", -- Continental_supplies --- ["Dust storm: [Deals 20 damage to all enemies in the circle]"] = "", -- Continental_supplies +-- ["Dust storm: [Deals 15 damage to all enemies in the circle]"] = "", -- Continental_supplies + +-- ["Dynamite"] = "", -- Construction_Mode +-- ["Each turn is only ONE SECOND!"] = "", -- Frenzy ["Each turn you get 1-3 random weapons"] = "Kekviena Eile Gausi 1-3 Atsitiktiniu Ginklu", ["Each turn you get one random weapon"] = "Kekviena Eile Gausi Po Viena Atsitiktini Ginkla", -- ["Eagle Eye"] = "", -- A_Classic_Fairytale:backstab --- ["Eagle Eye: [Blink to the impact ~ one shot]"] = "", -- Continental_supplies +-- ["Eagle Eye: [Blink to the impact ~ One shot]"] = "", -- Continental_supplies + -- ["Ear Sniffer"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:epil -- ["Elderbot"] = "", -- A_Classic_Fairytale:family -- ["Elimate your captor."] = "", -- User_Mission_-_The_Great_Escape @@ -208,8 +260,9 @@ -- ["Every single time!"] = "", -- A_Classic_Fairytale:dragon -- ["Everything looks OK..."] = "", -- A_Classic_Fairytale:enemy -- ["Exactly, man! That was my dream."] = "", -- A_Classic_Fairytale:backstab +-- ["Extra Damage"] = "", -- Construction_Mode +-- ["Extra Time"] = "", -- Construction_Mode -- ["Eye Chewer"] = "", -- A_Classic_Fairytale:journey --- ["INSANITY"] = "", -- Mutant -- ["Family Reunion"] = "", -- A_Classic_Fairytale:family ["Fastest lap: "] = "Greièiausias Ratas: ", ["Feeble Resistance"] = "Silpnaus Atsparumo Tvirtovë", @@ -219,9 +272,10 @@ -- ["Femur Lover"] = "", -- A_Classic_Fairytale:shadow -- ["Fierce Competition!"] = "", -- Space_Invasion -- ["Fiery Water"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united +-- ["Filthy Blue"] = "", -- User_Mission_-_Dangerous_Ducklings -- ["Find your tribe!|Cross the lake!"] = "", -- A_Classic_Fairytale:dragon -- ["Finish your training|Hint: Animations can be skipped with the [Precise] key."] = "", -- A_Classic_Fairytale:first_blood --- ["Fire a mine: [Does what it says ~ Cant be dropped close to an enemy ~ 1 sec]"] = "", -- Continental_supplies + ["Fire"] = "Ugnis", -- ["First aid kits?!"] = "", -- A_Classic_Fairytale:united -- ["First Blood"] = "", -- A_Classic_Fairytale:first_blood @@ -232,11 +286,15 @@ ["Flag returned!"] = "Vëliava Sugraþinta!", ["Flags, and their home base will be placed where each team ends their first turn."] = "Vëliavos, Ir Ju Bazës Bus Padëtos Kur Kekviena Komanda Pabaigs Ëjima.", -- ["Flamer"] = "", +-- ["Flamethrower"] = "", -- Construction_Mode -- ["Flaming Worm"] = "", -- A_Classic_Fairytale:backstab --- ["Flare: [fire up some bombs depending on hogs depending on hogs in the circle"] = "", -- Continental_supplies + -- ["Flesh for Brainz"] = "", -- A_Classic_Fairytale:journey +-- ["Flying Saucer"] = "", -- Construction_Mode, Frenzy -- ["For improved features/stability, play 0.9.18+"] = "", -- WxW -- ["Free Dense Cloud and continue the mission!"] = "", -- A_Classic_Fairytale:journey +-- ["Freezer"] = "", -- Construction_Mode +-- ["FRENZY"] = "", -- Frenzy -- ["Friendly Fire!"] = "", -- ["fuel extended!"] = "", ["GAME BEGUN!!!"] = "Þaidimas Prasidëjo!!!", @@ -246,6 +304,9 @@ -- ["Game? Was this a game to you?!"] = "", -- A_Classic_Fairytale:enemy -- ["GasBomb"] = "", -- Continental_supplies -- ["Gas Gargler"] = "", -- A_Classic_Fairytale:queen +-- ["General information"] = "", -- Continental_supplies +-- ["Generates power."] = "", -- Construction_Mode +-- ["Generator"] = "", -- Construction_Mode -- ["Get Dense Cloud out of the pit!"] = "", -- A_Classic_Fairytale:journey ["Get on over there and take him out!"] = "Nueik Ten Ir Nudauþk Ji!", -- ["Get on the head of the mole"] = "", -- A_Classic_Fairytale:first_blood @@ -256,6 +317,8 @@ -- ["Get your teammates out of their natural prison and save the princess!|Hint: Drilling holes should solve everything.|Hint: It might be a good idea to place a girder before starting to drill. Just saying.|Hint: All your hedgehogs need to be above the marked height!|Hint: Leaks A Lot needs to get really close to the princess!"] = "", -- A_Classic_Fairytale:family -- ["GG!"] = "", -- User_Mission_-_Rope_Knock_Challenge -- ["Gimme Bones"] = "", -- A_Classic_Fairytale:backstab +-- ["Girder"] = "", -- Construction_Mode +-- ["Girder Placement Mode"] = "", -- Construction_Mode -- ["Glark"] = "", -- A_Classic_Fairytale:shadow ["Goal"] = "Ðaunu!", ["GO! GO! GO!"] = "Bëk! Bëk! Bëk!", @@ -272,12 +335,16 @@ -- ["Go surf!"] = "", -- WxW ["GOTCHA!"] = "Prigavau!", -- ["Grab Mines/Explosives"] = "", +-- ["Grants nearby hogs life-regeneration."] = "", -- Construction_Mode +-- ["Gravity"] = "", -- Gravity -- ["Great choice, Steve! Mind if I call you that?"] = "", -- A_Classic_Fairytale:shadow -- ["Great work! Now hit it with your Baseball Bat! |Tip: You can change weapon with 'Right Click'!"] = "", -- Basic_Training_-_Rope -- ["Great! You will be contacted soon for assistance."] = "", -- A_Classic_Fairytale:shadow --- ["Green lipstick bullet: [Is poisonous]"] = "", -- Continental_supplies + +-- ["Green lipstick bullet: [Poisonous, deals no damage]"] = "", -- Continental_supplies -- ["Greetings, "] = "", -- A_Classic_Fairytale:dragon -- ["Greetings, cloudy one!"] = "", -- A_Classic_Fairytale:shadow +-- ["Grenade"] = "", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 -- ["Grenade Training"] = "", -- Basic_Training_-_Grenade -- ["Grenadiers"] = "", -- Basic_Training_-_Grenade -- ["Guys, do you think there's more of them?"] = "", -- A_Classic_Fairytale:backstab @@ -285,23 +352,27 @@ -- ["Haha!"] = "", -- A_Classic_Fairytale:united ["Hahahaha!"] = "Hahahaha!", ["Haha, now THAT would be something!"] = "Haha, na tai jau butu kaþkas!", +-- ["Hammer"] = "", -- Construction_Mode, Continental_supplies -- ["Hannibal"] = "", -- A_Classic_Fairytale:epil [" Hapless Hogs left!"] = " Nelaimingu Eþiu Liko!", ["Hapless Hogs"] = "Nelaimingi Eþiai", - -- [" HAS MUTATED"] = "", -- Mutant -- ["Hatless Jerry"] = "", -- A_Classic_Fairytale:queen -- ["Have no illusions, your tribe is dead, indifferent of your choice."] = "", -- A_Classic_Fairytale:shadow -- ["Have we ever attacked you first?"] = "", -- A_Classic_Fairytale:enemy +-- ["Healing Station"] = "", -- Construction_Mode +-- ["Health Crate Placement Mode"] = "", -- Construction_Mode -- ["Health crates extend your time."] = "", -- ["Heavy Cannfantry"] = "", -- A_Classic_Fairytale:united ["Heavy"] = "Sunku", -- ["Hedge-cogs"] = "", -- A_Classic_Fairytale:enemy --- ["Hedgehog projectile: [fire your hog like a Sticky Bomb]"] = "", -- Continental_supplies +-- ["Hedgehog projectile: [Fire your hog like a Sticky Bomb]"] = "", -- Continental_supplies + ["Hedgewars-Basketball"] = "Eþiukaru-Krepðinis", ["Hedgewars-Knockball"] = "Eþiukaru-Trenktaskamuolys", -- ["Hedgibal Lecter"] = "", -- A_Classic_Fairytale:backstab ["Heh, it's not that bad."] = "Heh,nëra taip blogai.", +-- ["Hellish Handgrenade"] = "", -- Construction_Mode -- ["Hello again, "] = "", -- A_Classic_Fairytale:family -- ["Help me, Leaks!"] = "", -- A_Classic_Fairytale:journey -- ["Help me, please!!!"] = "", -- A_Classic_Fairytale:journey @@ -333,6 +404,7 @@ -- ["Hogminator"] = "", -- A_Classic_Fairytale:family -- ["Hogs in sight!"] = "", -- Continental_supplies -- ["HOLY SHYTE!"] = "", -- Mutant +-- ["Homing Bee"] = "", -- Construction_Mode -- ["Honest Lee"] = "", -- A_Classic_Fairytale:enemy ["Hooray!"] = "Hurah!", -- ["Hostage Situation"] = "", -- A_Classic_Fairytale:family @@ -366,7 +438,6 @@ -- ["If you get stuck, use your Desert Eagle or restart the mission!|"] = "", -- A_Classic_Fairytale:journey -- ["If you know what I mean..."] = "", -- A_Classic_Fairytale:shadow -- ["If you say so..."] = "", -- A_Classic_Fairytale:shadow - -- ["I guess you'll have to kill them."] = "", -- A_Classic_Fairytale:dragon -- ["I have come to make you an offering..."] = "", -- A_Classic_Fairytale:shadow -- ["I have no idea where that mole disappeared...Can you see it?"] = "", -- A_Classic_Fairytale:shadow @@ -389,6 +460,7 @@ -- ["I'm not sure about that!"] = "", -- A_Classic_Fairytale:united -- ["Impressive...you are still dry as the corpse of a hawk after a week in the desert..."] = "", -- A_Classic_Fairytale:first_blood -- ["I'm so scared!"] = "", -- A_Classic_Fairytale:united +-- ["Increase"] = "", -- Continental_supplies -- ["Incredible..."] = "", -- A_Classic_Fairytale:shadow -- ["I need to find the others!"] = "", -- A_Classic_Fairytale:backstab -- ["I need to get to the other side of this island, fast!"] = "", -- A_Classic_Fairytale:journey @@ -397,12 +469,14 @@ -- ["I need to warn the others."] = "", -- A_Classic_Fairytale:backstab -- ["In fact, you are the only one that's been acting strangely."] = "", -- A_Classic_Fairytale:backstab -- ["In order to get to the other side, you need to collect the crates first.|"] = "", -- A_Classic_Fairytale:dragon +-- ["INSANITY"] = "", -- Mutant ["Instructor"] = "Instruktorius", -- 01#Boot_Camp, User_Mission_-_Dangerous_Ducklings -- ["Interesting idea, haha!"] = "", -- A_Classic_Fairytale:enemy -- ["Interesting! Last time you said you killed a cannibal!"] = "", -- A_Classic_Fairytale:backstab -- ["In the meantime, take these and return to your \"friend\"!"] = "", -- A_Classic_Fairytale:shadow ["invaders destroyed"] = "isiverþëjai sunaikinti", -- ["Invasion"] = "", -- A_Classic_Fairytale:united +-- ["Invulnerable"] = "", -- Construction_Mode -- ["I saw it with my own eyes!"] = "", -- A_Classic_Fairytale:shadow -- ["I see..."] = "", -- A_Classic_Fairytale:shadow -- ["I see you have already taken the leap of faith."] = "", -- A_Classic_Fairytale:first_blood @@ -445,6 +519,7 @@ -- ["Just kidding, none of you have died!"] = "", -- A_Classic_Fairytale:enemy -- ["Just on a walk."] = "", -- A_Classic_Fairytale:united -- ["Just wait till I get my hands on that trauma! ARGH!"] = "", -- A_Classic_Fairytale:family +-- ["Kamikaze"] = "", -- Construction_Mode ["Kamikaze Expert!"] = "Kamikazes Ekspertas!", -- ["Keep it up!"] = "", -- ["Kerguelen"] = "", -- Continental_supplies @@ -454,6 +529,8 @@ -- ["Kill the aliens!"] = "", -- A_Classic_Fairytale:dragon -- ["Kill the cannibal!"] = "", -- A_Classic_Fairytale:first_blood -- ["Kill the traitor...or spare his life!|Kill him or press [Precise]!"] = "", -- A_Classic_Fairytale:backstab +-- ["Land Sprayer"] = "", -- Construction_Mode +-- ["Laser Sight"] = "", -- Construction_Mode -- ["Last Target!"] = "", -- ["Leader"] = "", -- A_Classic_Fairytale:enemy -- ["Leaderbot"] = "", -- A_Classic_Fairytale:queen @@ -463,6 +540,7 @@ -- ["Leaks A Lot must survive!"] = "", -- A_Classic_Fairytale:journey -- ["Led Heart"] = "", -- A_Classic_Fairytale:queen -- ["Lee"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen +-- ["left shift"] = "", -- Continental_supplies ["[Left Shift]"] = "[Kairis Shiftas"], -- ["Let a Continent provide your weapons!"] = "", -- Continental_supplies -- ["Let me test your skills a little, will you?"] = "", -- A_Classic_Fairytale:journey @@ -473,41 +551,56 @@ -- ["Let them have a taste of my fury!"] = "", -- A_Classic_Fairytale:backstab -- ["Let us help, too!"] = "", -- A_Classic_Fairytale:backstab -- ["Light Cannfantry"] = "", -- A_Classic_Fairytale:united +-- ["Limburger"] = "", -- Construction_Mode ["Listen up, maggot!!"] = "Paklausyk eilini!!", -- ["Little did they know that this hunt will mark them forever..."] = "", -- A_Classic_Fairytale:shadow -- ["Lively Lifeguard"] = "", --- ["Lonely Cries: [Rise the water if no hog is in the circle and deal 1 damage to all hogs]"] = "", -- Continental_supplies + +-- ["Lonely Cries: [Rise the water if no hog is in the circle and deal 7 damage to all enemy hogs]"] = "", -- Continental_supplies +-- ["Lonely Hog"] = "", -- ClimbHome -- ["Look, I had no choice!"] = "", -- A_Classic_Fairytale:backstab -- ["Look out! There's more of them!"] = "", -- A_Classic_Fairytale:backstab -- ["Look out! We're surrounded by cannibals!"] = "", -- A_Classic_Fairytale:enemy -- ["Looks like the whole world is falling apart!"] = "", -- A_Classic_Fairytale:enemy +-- ["Low Gravity"] = "", -- Construction_Mode, Frenzy -- ["Luckily, I've managed to snatch some of them."] = "", -- A_Classic_Fairytale:united -- ["LUDICROUS KILL"] = "", -- Mutant +-- ["Made it!"] = "", -- ClimbHome +-- ["- Massive weapon bonus on first turn"] = "", -- Continental_supplies -- ["May the spirits aid you in all your quests!"] = "", -- A_Classic_Fairytale:backstab -- ["Medicine: [Fire some exploding medicine that will heal all hogs effected by the explosion]"] = "", -- Continental_supplies -- ["MEGA KILL"] = "", -- Mutant -- ["Meiwes"] = "", -- A_Classic_Fairytale:backstab -- ["Mindy"] = "", -- A_Classic_Fairytale:united +-- ["Mine"] = "", -- Construction_Mode, Frenzy -- ["Mine Deployer"] = "", -- ["Mine Eater!"] = "", +-- ["Mine Placement Mode"] = "", -- Construction_Mode ["|- Mines Time:"] = "|- Minu Laikas:", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork +-- ["Mine Strike"] = "", -- Construction_Mode ["MISSION FAILED"] = "Misija Nepavyko", -- User_Mission_-_Dangerous_Ducklings, User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork ["MISSION SUCCESSFUL"] = "Misija Buvo Ivykdita", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork ["MISSION SUCCESS"] = "Misija Pavyko", +-- ["Molotov Cocktail"] = "", -- Construction_Mode -- ["Molotov"] = "", -- Continental_supplies -- ["MONSTER KILL"] = "", -- Mutant -- ["More Natives"] = "", -- A_Classic_Fairytale:epil +-- ["Mortar"] = "", -- Construction_Mode, A_Space_Adventure:death02 ["Movement: [Up], [Down], [Left], [Right]"] = "Judëjimas: [I Virðu, [I Apaèia], [I Kaire], [I Deðine]"], +-- ["Mudball"] = "", -- Construction_Mode ["Multi-shot!"] = "Dvigubas-Ðuvis!", -- ["Muriel"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen -- ["Muscle Dissolver"] = "", -- A_Classic_Fairytale:shadow -- ["-------"] = "", -- Mutant +-- ["Mutant"] = "", -- Mutant -- ["Nade Boy"] = "", -- Basic_Training_-_Grenade -- ["Name"] = "", -- A_Classic_Fairytale:queen ["Nameless Heroes"] = "Bevardþiai Herojiai", -- ["Nancy Screw"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:queen +-- ["Napalm"] = "", -- Construction_Mode -- ["Napalm rocket: [Fire a bomb with napalm!]"] = "", -- Continental_supplies -- ["Natives"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:first_blood, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united +-- ["Naughty Ninja"] = "", -- User_Mission_-_Dangerous_Ducklings -- ["New Barrels Per Turn"] = "", ["NEW CLAN RECORD: "] = "Naujas Klano Rekordas: ", ["NEW fastest lap: "] = "Naujas Greièiausias Ratas: ", @@ -518,6 +611,7 @@ -- ["Nice work, "] = "", -- A_Classic_Fairytale:dragon -- ["Nice work!"] = "", -- A_Classic_Fairytale:enemy -- ["Nilarian"] = "", -- A_Classic_Fairytale:queen +-- ["Nobody Laugh"] = "", -- User_Mission_-_Nobody_Laugh -- ["No, I came back to help you out..."] = "", -- A_Classic_Fairytale:shadow -- ["No...I wonder where they disappeared?!"] = "", -- A_Classic_Fairytale:journey -- ["Nom-Nom"] = "", -- A_Classic_Fairytale:journey @@ -525,6 +619,7 @@ -- ["Nope. It was one fast mole, that's for sure."] = "", -- A_Classic_Fairytale:shadow -- ["No! Please, help me!"] = "", -- A_Classic_Fairytale:journey -- ["NORMAL"] = "", -- Continental_supplies +-- ["Normal players can only score points by killing the mutant."] = "", -- Mutant -- ["North America"] = "", -- Continental_supplies -- ["Not all hogs are born equal."] = "", -- Highlander ["NOT ENOUGH WAYPOINTS"] = "Neuþtenka Kelio Taðku", @@ -537,6 +632,7 @@ -- ["No. Where did he come from?"] = "", -- A_Classic_Fairytale:shadow -- ["Now how do I get on the other side?!"] = "", -- A_Classic_Fairytale:dragon -- ["No. You and the rest of the tribe are safer there!"] = "", -- A_Classic_Fairytale:backstab +-- ["Object Placement Tool"] = "", -- Construction_Mode -- ["Obliterate them!|Hint: You might want to take cover..."] = "", -- A_Classic_Fairytale:shadow -- ["Obstacle course"] = "", -- A_Classic_Fairytale:dragon -- ["Of course I have to save her. What did I expect?!"] = "", -- A_Classic_Fairytale:family @@ -553,24 +649,30 @@ -- ["Once upon a time, on an island with great natural resources, lived two tribes in heated conflict..."] = "", -- A_Classic_Fairytale:first_blood -- ["ONE HOG PER TEAM! KILLING EXCESS HEDGES"] = "", -- Mutant -- ["One tribe was peaceful, spending their time hunting and training, enjoying the small pleasures of life..."] = "", -- A_Classic_Fairytale:first_blood +-- ["on Skip"] = "", -- Continental_supplies -- ["Oops...I dropped them."] = "", -- A_Classic_Fairytale:united -- ["Open that crate and we will continue!"] = "", -- A_Classic_Fairytale:first_blood ["Operation Diver"] = "Operacijos Vairuotojas", ["Opposing Team: "] = "Pasiprieðinanti Komanda: ", +-- ["or 'g=50, g2=150, period=4000' for gravity changing|from 50 to 150 and back with period of 4000 msec"] = "", -- Gravity -- ["Orlando Boom!"] = "", -- A_Classic_Fairytale:queen +-- ["Other kills don't give you points."] = "", -- Mutant -- ["Ouch!"] = "", -- User_Mission_-_Rope_Knock_Challenge -- ["Our tribe, our beautiful island!"] = "", -- A_Classic_Fairytale:enemy -- ["Parachute"] = "", -- Continental_supplies ["Pathetic Hog #%d"] = "Niekam Tikes Eþys #%d", -- ["Pathetic Resistance"] = "", -- User_Mission_-_Bamboo_Thicket, User_Mission_-_Newton_and_the_Hammock +-- ["Penguin roar: [Deal 15 damage + 15% of your hogs health to all hogs around you and get 2/3 back]"] = "", -- Continental_supplies -- ["Perfect! Now try to get the next crate without hurting yourself!"] = "", -- A_Classic_Fairytale:first_blood ["Per-Hog Ammo"] = "Kulkos Per-Eþy", --- ["- Per team weapons|- 9 weaponschemes|- Unique new weapons| |Select continent first round with the Weapon Menu or by ([switch/tab]=Increase,[precise/left shift]=Decrease) on Skip|Some weapons have a second option. Find them with [switch/tab]"] = "", -- Continental_supplies +-- ["Personal Portal Device"] = "", -- Construction_Mode +-- ["Per team weapons"] = "", -- Continental_supplies -- ["Pfew! That was close!"] = "", -- A_Classic_Fairytale:shadow --- ["Piñata bullet: [Contains some sweet candy!]"] = "", -- Continental_supplies +-- ["Piano Strike"] = "", -- Construction_Mode +-- ["Pickhammer"] = "", -- Construction_Mode + -- ["Pings left:"] = "", -- Space_Invasion - -- ["Place more waypoints using the 'Air Attack' weapon."] = "", -- ["Planes Used:"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Planes Used"] = "", -- User_Mission_-_RCPlane_Challenge @@ -579,15 +681,19 @@ -- ["Please place the way-point in the open, within the map boundaries."] = "", -- Racer -- ["Please, stop releasing your \"smoke signals\"!"] = "", -- A_Classic_Fairytale:shadow -- ["Point Blank Combo!"] = "", -- Space_Invasion +-- ["POINTS"] = "", -- Mutant ["points"] = "taðkai", -- Control, CTF_Blizzard, Basic_Training_-_Bazooka, Basic_Training_-_Shotgun, Basic_Training_-_Sniper_Rifle ["Poison"] = "Nuodai", +-- ["Population"] = "", -- Continental_supplies -- ["Portal hint: one goes to the destination, and one is the entrance.|"] = "", -- A_Classic_Fairytale:dragon -- ["Portal mission"] = "", -- portal ["Power Remaining"] = "Jëgos Liko", -- ["Prepare yourself"] = "", +-- ["presice"] = "", -- Continental_supplies -- ["Press [Enter] to accept this configuration."] = "", -- WxW -- ["Press [Left] or [Right] to move around, [Enter] to jump"] = "", -- A_Classic_Fairytale:first_blood ["Press [Precise] to skip intro"] = "Spausk [TaikluNusitaikima kad baigtum iëjima"], +-- ["Prestigious Pilot"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Private Novak"] = "", -- Basic_Training_-_Cluster_Bomb -- ["Protect yourselves!|Grenade hint: set the timer with [1-5], aim with [Up]/[Down] and hold [Space] to set power"] = "", -- A_Classic_Fairytale:shadow ["Race complexity limit reached."] = "Lenktyniu Sudëtingumo Limitas Pasiektas.", @@ -596,25 +702,39 @@ -- ["Radar Ping"] = "", -- Space_Invasion -- ["Raging Buffalo"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united -- ["Ramon"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow +-- ["random in range from %i%% to %i%% with period of %i msec"] = "", -- Gravity +-- ["RC Plane"] = "", -- Construction_Mode -- ["RC PLANE TRAINING"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Really?! You thought you could harm me with your little toys?"] = "", -- A_Classic_Fairytale:shadow +-- ["Reflector Shield"] = "", -- Construction_Mode +-- ["Reflects enemy projectiles."] = "", -- Construction_Mode -- ["Regurgitator"] = "", -- A_Classic_Fairytale:backstab -- ["Reinforcements"] = "", -- A_Classic_Fairytale:backstab -- ["Remember: The rope only bend around objects, |if it doesn't hit anything it's always stright!"] = "", -- Basic_Training_-_Rope -- ["Remember this, pathetic animal: when the day comes, you will regret your blind loyalty!"] = "", -- A_Classic_Fairytale:shadow +-- ["REMOVED"] = "", -- Continental_supplies +-- ["Respawner"] = "", -- Construction_Mode +-- ["Resurrector"] = "", -- Construction_Mode +-- ["Resurrects dead hedgehogs."] = "", -- Construction_Mode [" - Return the enemy flag to your base to score | - First team to 3 captures wins | - You may only score when your flag is in your base | - Hogs will drop the flag if killed, or drowned | - Dropped flags may be returned or recaptured | - Hogs respawn when killed"] = " - Graþink prieðu vëliava i savo baze ir gausi taðku | - Pirma komanda su 3 vëliavom laimi | - Taðkus gausi tik tada kaip tavo vëliava bazëje | - Eþiai pames vëliava jeigu mirs, arba paskes | - Pamestos vëliavos gali buti graþintos arba pavogtos | - Eþiai atsikelia kaip nuþudyti", -- ["Return to Leaks A Lot! If you get stuck, press [Precise] to try again!"] = "", -- A_Classic_Fairytale:shadow -- ["Righteous Beard"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:first_blood, A_Classic_Fairytale:queen, A_Classic_Fairytale:united +-- ["Rope"] = "", -- Construction_Mode -- ["ROPE-KNOCKING"] = "", -- User_Mission_-_Rope_Knock_Challenge +-- ["Rope to safety"] = "", -- ClimbHome -- ["Rope Training"] = "", -- Basic_Training_-_Rope -- ["Rot Molester"] = "", -- A_Classic_Fairytale:shadow -- ["Round Limit:"] = "", ["Round Limit"] = "Raundu Limitas", -- ["Rounds Complete: "] = "", ["Rounds Complete"] = "Raundai Ivykditi", +-- ["Rubber Band"] = "", -- Construction_Mode +-- ["Rubber Placement Mode"] = "", -- Construction_Mode +-- ["RULES"] = "", -- Frenzy, Mutant ["RULES OF THE GAME [Press ESC to view]"] = "ÞAIDIMO TAISYKLES [Spausk ESC Kad Parodytu"], -- ["Rusty Joe"] = "", -- A_Classic_Fairytale:queen --- ["Sabotage: [Sabotage all hogs in the circle and deal ~10 dmg]"] = "", -- Continental_supplies +-- ["Sabotage/Flare: [Sabotage all hogs in the circle and deal ~1 dmg OR Fire a cluster up into the air]"] = "", -- Continental_supplies + -- ["Salivaslurper"] = "", -- A_Classic_Fairytale:united -- ["Salvation"] = "", -- A_Classic_Fairytale:family -- ["Salvation was one step closer now..."] = "", -- A_Classic_Fairytale:dragon @@ -626,7 +746,7 @@ -- ["Scalp Muncher"] = "", -- A_Classic_Fairytale:backstab -- ["Score"] = "", -- Mutant ["SCORE"] = "Taðkai", --- ["Scream from a Walrus: [Deal 20 damage + 10% of your hogs health to all hogs around you and get half back]"] = "", -- Continental_supplies + ["sec"] = "sek", -- CTF_Blizzard, TrophyRace, Basic_Training_-_Bazooka, Basic_Training_-_Shotgun, Basic_Training_-_Sniper_Rifle, User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork, Capture_the_Flag -- ["Seduction"] = "", -- Continental_supplies -- ["Seems like every time you take a \"walk\", the enemy find us!"] = "", -- A_Classic_Fairytale:backstab @@ -634,8 +754,11 @@ ["See ya!"] = "Iki!", -- ["Segmentation Paul"] = "", -- A_Classic_Fairytale:dragon -- ["Select continent!"] = "", -- Continental_supplies +-- ["Select continent first round with the Weapon Menu or by"] = "", -- Continental_supplies -- ["Select difficulty: [Left] - easier or [Right] - harder"] = "", -- A_Classic_Fairytale:first_blood -- ["selected!"] = "", +-- ["Set period to negative value for random gravity"] = "", -- Gravity +-- ["Setup:|'g=150', where 150 is 150% of normal gravity"] = "", -- Gravity -- ["... share your beauty with the world every morning, my princess!"] = "", -- A_Classic_Fairytale:journey -- ["She's behind that tall thingy."] = "", -- A_Classic_Fairytale:family ["Shield boosted! +30 power"] = "Skydas Pagerintas! +30 jëga", @@ -646,16 +769,21 @@ ["Shield OFF:"] = "Skydas Iðjungtas:", ["Shield ON:"] = "Skydas Ijungtas:", ["Shield Seeker!"] = "Skydo Ieðkotojas!", +-- ["Shoryuken"] = "", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 -- ["Shotgun"] = "", -- Continental_supplies ["Shotgun Team"] = "Ðratinio Ðautuvo Komanda", ["Shotgun Training"] = "Ðratinio Ðautuvo Treniruotë", -- ["shots remaining."] = "", ["Silly"] = "Durnelis", +-- ["SineGun"] = "", -- Construction_Mode ["Sinky"] = "Paskenduolis", -- ["Sirius Lee"] = "", -- A_Classic_Fairytale:enemy ["%s is out and Team %d|scored a penalty!| |Score:"] = "%s Iðkrito ir komanda %d|gavo bausme!| |Score:", -- Basketball, Knockball ["%s is out and Team %d|scored a point!| |Score:"] = "%s Iðkrito ir komanda %d|gavo taðka!| |Score:", -- Basketball, Knockball -- ["Slippery"] = "", -- A_Classic_Fairytale:journey +-- ["Slot"] = "", -- Frenzy +-- ["Slot keys save time! (F1-F10 by default)"] = "", -- Frenzy +-- ["SLOTS"] = "", -- Frenzy -- ["Smith 0.97"] = "", -- A_Classic_Fairytale:enemy -- ["Smith 0.98"] = "", -- A_Classic_Fairytale:enemy -- ["Smith 0.99a"] = "", -- A_Classic_Fairytale:enemy @@ -667,6 +795,7 @@ ["Sniper Training"] = "Snaiperio Treniruotë", ["Sniperz"] = "Snaiperiai", -- ["So humiliating..."] = "", -- A_Classic_Fairytale:first_blood +-- ["Some weapons have a second option. Find them with"] = "", -- Continental_supplies -- ["South America"] = "", -- Continental_supplies -- ["So? What will it be?"] = "", -- A_Classic_Fairytale:shadow -- ["Spawn the crate, and attack!"] = "", -- WxW @@ -675,6 +804,8 @@ -- ["Spleenlover"] = "", -- A_Classic_Fairytale:united ["Sponge"] = "Kempinë", ["Spooky Tree"] = "Baisusis Medis", +-- ["Sprite Placement Mode"] = "", -- Construction_Mode +-- ["Sprite Testing Mode"] = "", -- Construction_Mode ["s|"] = "s|", ["s"] = "s", -- GaudyRacer, Space_Invasion ["STATUS UPDATE"] = "Bûsenos Atnaujinimas", -- GaudyRacer, Space_Invasion @@ -682,20 +813,36 @@ -- ["Step By Step"] = "", -- A_Classic_Fairytale:first_blood -- ["Steve"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen -- ["Sticky Mine"] = "", -- Continental_supplies +-- ["Sticky Mine Placement Mode"] = "", -- Construction_Mode -- ["Stronglings"] = "", -- A_Classic_Fairytale:shadow --- ["Structure"] = "", -- Continental_supplies + +-- ["Structure Placement Mode"] = "", -- Construction_Mode +-- ["Structure Placement Tool"] = "", -- Construction_Mode +-- ["Sundaland"] = "", -- Continental_supplies -- ["Super Weapons"] = "", -- WxW +-- ["Support Station"] = "", -- Construction_Mode -- ["Surf Before Crate"] = "", -- WxW -- ["Surfer! +15 points!"] = "", -- Space_Invasion -- ["Surfer!"] = "", -- WxW -- ["Survive!|Hint: Cinematics can be skipped with the [Precise] key."] = "", -- A_Classic_Fairytale:shadow -- ["Swing, Leaks A Lot, on the wings of the wind!"] = "", -- A_Classic_Fairytale:first_blood +-- ["switch"] = "", -- Continental_supplies ["Switched to "] = "Pakeistas i ", +-- ["Switch Hog"] = "", -- Construction_Mode -- ["Syntax Errol"] = "", -- A_Classic_Fairytale:dragon +-- ["tab"] = "", -- Continental_supplies +-- ["Tagging Mode"] = "", -- Construction_Mode -- ["Talk about mixed signals..."] = "", -- A_Classic_Fairytale:dragon +-- ["Tardis"] = "", -- Construction_Mode +-- ["Target Placement Mode"] = "", -- Construction_Mode ["Team %d: "] = "Komanda %d: ", ["Team Scores"] = "Komandos Taðkai", -- Control, Space_Invasion +-- ["Teleporation Node"] = "", -- Construction_Mode +-- ["Teleportation Mode"] = "", -- Construction_Mode +-- ["Teleportation Node"] = "", -- Construction_Mode +-- ["Teleport"] = "", -- Construction_Mode, Frenzy -- ["Teleport hint: just use the mouse to select the destination!"] = "", -- A_Classic_Fairytale:dragon +-- ["Teleport Unsuccessful. Please teleport within a clan teleporter's sphere of influence."] = "", -- Construction_Mode -- ["Thanks!"] = "", -- A_Classic_Fairytale:family -- ["Thank you, my hero!"] = "", -- A_Classic_Fairytale:family -- ["Thank you, oh, thank you, Leaks A Lot!"] = "", -- A_Classic_Fairytale:journey @@ -712,6 +859,7 @@ ["That was pointless."] = "Tai Buvo Beprasmiðka.", -- ["The answer is...entertaintment. You'll see what I mean."] = "", -- A_Classic_Fairytale:backstab -- ["The anti-portal zone is all over the floor, and I have nothing to kill him...Droping something could hurt him enough to kill him..."] = "", -- portal +-- ["The Bottom Feeder can score points by killing anyone."] = "", -- Mutant -- ["The Bull's Eye"] = "", -- A_Classic_Fairytale:first_blood -- ["The caves are well hidden, they won't find us there!"] = "", -- A_Classic_Fairytale:united -- ["The Crate Frenzy"] = "", -- A_Classic_Fairytale:first_blood @@ -721,20 +869,26 @@ -- ["The Enemy Of My Enemy"] = "", -- A_Classic_Fairytale:enemy -- ["The First Blood"] = "", -- A_Classic_Fairytale:first_blood -- ["The First Encounter"] = "", -- A_Classic_Fairytale:shadow +-- ["The first player to kill someone becomes the Mutant."] = "", -- Mutant ["The flag will respawn next round."] = "Vëliava atsigaus kita raunda.", -- ["The food bites back"] = "", -- A_Classic_Fairytale:backstab -- ["The giant umbrella from the last crate should help break the fall."] = "", -- A_Classic_Fairytale:first_blood -- ["The Great Escape"] = "", -- User_Mission_-_The_Great_Escape +-- ["The Great Hog in the sky sees your sadness and grants you a boon."] = "", -- Construction_Mode -- ["The guardian"] = "", -- A_Classic_Fairytale:shadow -- ["The Individualist"] = "", -- A_Classic_Fairytale:shadow -- ["Their buildings were very primitive back then, even for an uncivilised island."] = "", -- A_Classic_Fairytale:united -- ["The Journey Back"] = "", -- A_Classic_Fairytale:journey -- ["The Leap of Faith"] = "", -- A_Classic_Fairytale:first_blood -- ["The Moonwalk"] = "", -- A_Classic_Fairytale:journey +-- ["The Mutant has super-weapons and a lot of health."] = "", -- Mutant +-- ["The Mutant loses health quickly if he doesn't keep scoring kills."] = "", -- Mutant ["The Nameless One"] = "Bevardis", -- ["The next one is pretty hard! |Tip: You have to do multiple swings!"] = "", -- Basic_Training_-_Rope -- ["Then how do they keep appearing?"] = "", -- A_Classic_Fairytale:shadow -- ["The other one were all cannibals, spending their time eating the organs of fellow hedgehogs..."] = "", -- A_Classic_Fairytale:first_blood +-- ["The player with least points (or most deaths) becomes the Bottom Feeder."] = "", -- Mutant +-- ["There are a variety of structures available to aid you."] = "", -- Construction_Mode -- ["There must be a spy among us!"] = "", -- A_Classic_Fairytale:backstab -- ["There's more of them? When did they become so hungry?"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united -- ["There's nothing more satisfying for me than seeing you share your beauty with the world every morning, my princess!"] = "", -- A_Classic_Fairytale:journey @@ -790,7 +944,7 @@ -- ["To the caves..."] = "", -- A_Classic_Fairytale:united ["Toxic Team"] = "Toksinë Komanda", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork ["TRACK COMPLETED"] = "Trasa Ivykdita", --- ["TRACK FAILED!"] = "", + -- ["training"] = "", -- portal -- ["Traitors"] = "", -- A_Classic_Fairytale:epil -- ["Tribe"] = "", -- A_Classic_Fairytale:backstab @@ -807,6 +961,7 @@ -- ["ULTRA KILL"] = "", -- Mutant -- ["Under Construction"] = "", -- A_Classic_Fairytale:shadow -- ["Unexpected Igor"] = "", -- A_Classic_Fairytale:dragon +-- ["Unique new weapons"] = "", -- Continental_supplies -- ["Unit"] = "", -- ["Unit 0x0007"] = "", -- A_Classic_Fairytale:family -- ["Unit 334a$7%;.*"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united @@ -821,11 +976,14 @@ -- ["Use it wisely!"] = "", -- A_Classic_Fairytale:dragon -- ["Use it with precaution!"] = "", -- A_Classic_Fairytale:first_blood ["User Challenge"] = "Vartotojo Iðukis", - +-- ["Use the air-attack weapons and the arrow keys to select structures."] = "", -- Construction_Mode -- ["Use the portal gun to get to the next crate, then use the new gun to get to the final destination!|"] = "", -- A_Classic_Fairytale:dragon -- ["Use the rope to get on the head of the mole, young one!"] = "", -- A_Classic_Fairytale:first_blood -- ["Use the rope to knock your enemies to their doom."] = "", -- User_Mission_-_Rope_Knock_Challenge +-- ["Use your ready time to think."] = "", -- Frenzy ["Use your rope to get from start to finish as fast as you can!"] = "Naudok virve kad nusigautum nuo starto iki finiðo taip greitai kaip gali!", +-- ["Utility Crate Placement Mode"] = "", -- Construction_Mode +-- ["Vampirism"] = "", -- Construction_Mode -- ["Vedgies"] = "", -- A_Classic_Fairytale:journey -- ["Vegan Jack"] = "", -- A_Classic_Fairytale:enemy -- ["Victory!"] = "", -- Basic_Training_-_Rope @@ -837,10 +995,14 @@ -- ["Wannabe Flyboys"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Wannabe Shoppsta"] = "", -- User_Mission_-_Rope_Knock_Challenge -- ["Watch your steps, young one!"] = "", -- A_Classic_Fairytale:first_blood +-- ["Watermelon Bomb"] = "", -- Construction_Mode ["Waypoint placed."] = "Kelio Taðkas Pasiektas.", -- ["Way-Points Remaining"] = "", -- ["Weaklings"] = "", -- A_Classic_Fairytale:shadow -- ["We all know what happens when you get frightened..."] = "", -- A_Classic_Fairytale:first_blood +-- ["Weapon Crate Placement Mode"] = "", -- Construction_Mode +-- ["Weapon Filter"] = "", -- Construction_Mode +-- ["weaponschemes"] = "", -- Continental_supplies ["Weapons Reset"] = "Ginklai Atgaivinti", -- ["Weapons reset."] = "", -- Highlander -- ["We are indeed."] = "", -- A_Classic_Fairytale:backstab @@ -893,6 +1055,7 @@ -- ["Where do you get that?!"] = "", -- A_Classic_Fairytale:enemy -- ["Where have you been?!"] = "", -- A_Classic_Fairytale:backstab -- ["Where have you been?"] = "", -- A_Classic_Fairytale:united +-- ["Whip"] = "", -- Construction_Mode -- ["? Why?"] = "", -- A_Classic_Fairytale:backstab -- ["Why "] = "", -- A_Classic_Fairytale:backstab -- ["! Why?!"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united @@ -905,8 +1068,10 @@ -- ["Why me?!"] = "", -- A_Classic_Fairytale:backstab -- ["Why would they do this?"] = "", -- A_Classic_Fairytale:backstab -- ["- Will Get 1-3 random weapons"] = "", -- Continental_supplies --- ["- Will refresh Parachute each turn."] = "", -- Continental_supplies --- ["- Will refresh portalgun each turn."] = "", -- Continental_supplies +-- ["- Will give you an airstrike every fifth turn."] = "", -- Continental_supplies +-- ["- Will give you a parachute every second turn."] = "", -- Continental_supplies + + -- ["Will this ever end?"] = "", -- ["WINNER IS "] = "", -- Mutant ["WINNING TIME: "] = "Laimëjimo Laikas: ", @@ -925,6 +1090,7 @@ -- ["Yes!"] = "", -- A_Classic_Fairytale:enemy -- ["Yes, yeees! You are now ready to enter the real world!"] = "", -- A_Classic_Fairytale:first_blood -- ["Yo, dude, we're here, too!"] = "", -- A_Classic_Fairytale:family +-- ["You are far from home, and the water is rising, climb up as high as you can!"] = "", -- ClimbHome -- ["You are given the chance to turn your life around..."] = "", -- A_Classic_Fairytale:shadow -- ["You are playing with our lives here!"] = "", -- A_Classic_Fairytale:enemy -- ["! You bastards!"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united @@ -957,6 +1123,8 @@ -- ["You know what? I don't even regret anything!"] = "", -- A_Classic_Fairytale:backstab -- ["You'll see what I mean!"] = "", -- A_Classic_Fairytale:enemy -- ["You may only attack from a rope!"] = "", -- WxW +-- ["You may only spawn 5 crates per turn."] = "", -- Construction_Mode +-- ["You may only use 1 Extra Time per turn."] = "", -- Construction_Mode -- ["You meatbags are pretty slow, you know!"] = "", -- A_Classic_Fairytale:enemy -- ["You might want to find a way to instantly kill arriving cannibals!"] = "", -- A_Classic_Fairytale:backstab -- ["Young one, you are telling us that they can instantly change location without a shaman?"] = "", -- A_Classic_Fairytale:united @@ -977,6 +1145,7 @@ ["You've failed. Try again."] = "Tau nepavyko. Bandyk vël.", ["You've reached the goal!| |Time: "] = "Tu pasiekiai taikini!| |Laikas: ", -- ["You will be avenged!"] = "", -- A_Classic_Fairytale:shadow +-- ["- You will recieve 2-4 weapons on each kill! (Even on own hogs)"] = "", -- Continental_supplies -- ["You won't believe what happened to me!"] = "", -- A_Classic_Fairytale:backstab -- ["Yuck! I bet they'll keep worshipping her even after I save the village!"] = "", -- A_Classic_Fairytale:family -- ["Zealandia"] = "", -- Continental_supplies diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/lt.txt --- a/share/hedgewars/Data/Locale/lt.txt Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/lt.txt Tue Nov 10 20:43:13 2015 +0100 @@ -1,65 +1,68 @@ ; Lietuviškai 00:00=Granata -00:01=Klasterinė Granata +00:01=Klasterinė granata 00:02=Bazuka -00:03=Sekanti Bitė -00:04=Šratinis Šautuvas -00:05=Kasimo iranga (Žemyn) -00:06=Praleisti Eile +00:03=Sekanti bitė +00:04=Šratinis šautuvas +00:05=Kasimo įranga (žemyn) +00:06=Praleisti eilę 00:07=Virvė 00:08=Mina 00:09=Pistoletas 00:10=Dinamitas -00:11=Beisbolo Lazda +00:11=Beisbolo lazda 00:12=Shoryukenas -00:13=sekundė +00:13=Sekundė 00:14=Parašiutas -00:15=Oro Ataka -00:16=Minų Streikas -00:17=Kasimo Iranga (I Šonus) +00:15=Oro ataka +00:16=Minų smūgis +00:17=Kasimo įranga (į šonus) 00:18=Konstrukcija 00:19=Teleportacija -00:20=Pakeisti Ežy -00:21=Klasterinis Sviedinys +00:20=Pakeisti ežį +00:21=Klasterinis sviedinys 00:22=Botagas 00:23=Kamikadzė 00:24=Tortas 00:25=Suviliojimas -00:26=Arbūzo Bomba -00:27=Pragariška Rankinė Granata -00:28=Besikasanti Raketa -00:29=Kamuoliu Ginklas +00:26=Arbūzo bomba +00:27=Pragariška rankinė granata +00:28=Besikasanti raketa +00:29=Kamuolių ginklas 00:30=Napalmas -00:31=RBV Lektuvelis -00:32=Maža Gravitacija -00:33=Ekstra Žala +00:31=RBV Lėktuvėlis +00:32=Maža gravitacija +00:33=Papildoma žala 00:34=Nemirtingas -00:35=Ekstra Laikas +00:35=Papildomas laikas 00:36=Lazeris -00:37=Vampirismas +00:37=Vampyrizmas 00:38=Snaiperis -00:39=Skrendanti Lėkštė -00:40=Molotovo Kokteilis +00:39=Skrendanti lėkštė +00:40=Molotovo kokteilis 00:41=Paukštelis -00:42=Teleportuojantis Prietaisas -00:43=Piano Streikas -00:44=Senas Sūris +00:42=Teleportuojantis prietaisas +00:43=Pianino smūgis +00:44=Senas sūris 00:45=Sinuso Ginklas (Betoje) 00:46=Ugniasvaidis -00:47=Limpanti Mina +00:47=Limpanti mina 00:48=Kūjis 00:49=Atgaivinimas -00:50=Besikasanciu Raketu Streikas -00:51=Purvo Kamuolys -00:52=Joks Ginklas Nepasirinktas +00:50=Besikasančių raketų smūgis +00:51=Purvo kamuolys +00:52=Nepasirinktas joks ginklas 00:53=TARDIS ; 00:54=Struktūra -00:54=Žemės Purškimas +00:54=Žemės purškimas +00:55=Šaldymo kamera +00:56=Cleaver +00:57=Trintukas 01:00=Kaukimės! 01:01=Lygiosios -01:02=%1 Laimejo! +01:02=%1 Laimėjo! 01:03=Garsas %1% 01:04=Sustabdyta 01:05=Tikrai išeiti (Y/Esc)? @@ -67,166 +70,168 @@ 01:07=%1 Liko 01:08=Degalai 01:09=Kraunasi... -01:10=Naudojant šita iranki nepabaigs jusu eilės! -01:11=Sitas Ginklas Arba Irankis Dar Negali Buti Panaudotas! +01:10=Naudojant šį įrankį jūsų eilė nepasibaigs! +01:11=Šitas ginklas arba įrankis dar negali būti panaudotas! 01:12=Paskutinis raundas iki maro! -01:13=%1 raundu iki maro! +01:13=%1 raundų iki maro! 01:14=Pasiruošk, %1! 01:15=Nežymus 01:16=Žemas 01:17=Normalus 01:18=Aukštas 01:19=Ekstremalus -01:20=%1 Atsokti +01:20=%1 Atšokti +01:21=Garsas išjungtas +01:22=AFK režimas ; Event messages ; Hog (%1) died -02:00=%1 spirė i kibira! -02:00=%1 pamatė šviesa! -02:00=%1 nematė kad taip nutiks! +02:00=%1 spyrė į kibirą! +02:00=%1 pamatė šviesą! +02:00=%1 negalvojo, kad taip nutiks! 02:00=%1 mojuoja ate! -02:00=%1 nuėjo i geresne vietele! -02:00=%1 sutiko savo kurėja! +02:00=%1 nuėjo į geresnę vietelę! +02:00=%1 sutiko savo kūrėją! 02:00=%1 nebegali išsilaikyti! 02:00=%1 atliko savo pareigas! 02:00=%1 pasiaukoja! -02:00=%1 baige savo karjera! +02:00=%1 baigė savo karjerą! 02:00=%1 krito kaip musė! -02:00=%1 uzsivertė! +02:00=%1 užsivertė! 02:00=%1 sako ate! 02:00=%1 bus prisimintas! -02:00=%1 turejo išeiti! -02:00=%1 paliko žmona ir vaikus -02:00=%1 paleido savo paskutine bazuka -02:00=%1 metė savo paskutine granata -02:00=%1 iškepe paskutini savo torta -02:00=%1 paleido paskutine virve -02:00=%1 pakvietė paskutini savo oro streika -02:00=%1 paskutini karta uztaise savo šratini šautuva -02:00=%1 mete paskutini savo arbūza -02:00=%1 ištrauke paskutini savo pistoleta -02:00=%1 gavo daugiau negu galejo pakelt -02:00=%1 pamiršo kad nera nemirtingas -02:00=%1 išėjo žaisti geresni žaidima -02:00=%1 supykes paliko gyvenima +02:00=%1 turėjo išeiti! +02:00=%1 paliko žmoną ir vaikus +02:00=%1 paleido savo paskutinę bazuką +02:00=%1 metė savo paskutinę granatą +02:00=%1 iškepė paskutinį savo tortą +02:00=%1 paleido paskutinę virvę +02:00=%1 pakvietė paskutinį savo oro smūgį +02:00=%1 paskutinį kartą užtaisė savo šratinį šautuvą +02:00=%1 metė paskutinį savo arbūzą +02:00=%1 ištraukė paskutinį savo pistoletą +02:00=%1 gavo daugiau negu galėjo pakelti +02:00=%1 pamiršo, kad nėra nemirtingas +02:00=%1 išėjo žaisti geresnį žaidimą +02:00=%1 supykęs paliko gyvenimą 02:00=%1 Susivaro 02:00=vargšas %1... -02:00=%1 verčiau žaistu wormux -02:00=%1 blokavo šuvius su juo veidu -02:00=%1 vaidino heroju -02:00=%1 rado savo vieta Valhalloj +02:00=%1 verčiau žaistų wormux +02:00=%1 blokavo šūvius savo veidu +02:00=%1 vaidino didvyrį +02:00=%1 rado savo vietą Valhalloj 02:00=%1 išėjo iš pastato -02:00=%1 eina dinozauru keliu -02:00=%1 pritraukia ežius arčiau ekstinkcijos -02:00=%1 atnešė ašara mano akiai -02:00=%1 ira ex-ežys -02:00=%1 stumia dūra -02:00=%1 gimes mirti +02:00=%1 eina dinozaurų keliu +02:00=%1 pritraukia ežius arčiau išnykimo +02:00=%1 atnešė ašarą mano akiai +02:00=%1 yra ex-ežys +02:00=%1 stumia dūrą +02:00=%1 gimęs mirti 02:00=Sakykit ate %1 -02:00=Paskutini karta matote %1 -02:00=%1 sutiko paskutini kilima -02:00=Rukyk juos jei turi ju, %1 -02:00=%1 pajaucia ka reiškia Susivaryti Iki Nulio +02:00=Paskutinį kartą matote %1 +02:00=%1 sutiko paskutinį kilimą +02:00=Rukyk juos jei turi jų, %1 +02:00=%1 pajaučia, ką reiškia susivaryti iki nulio 02:00=%1 išejo 02:00=%1 nebėra -02:00=%1 pradingo +02:00=%1 dingo 02:00=%1 nepaaiškinamai mirė -02:00=Atsiprašome %1 tau laikas išeiti -02:00=%1 žiuri i žaidima iš dangaus -02:00=Ate %1, mes taves beveik nežinojom! -02:00=%1 galvojo kad kulkos neskauda -02:00=%1 butu panaudojes ekstra givybe -02:00=Ar cia ira daktaras? +02:00=Atsiprašome %1, tau laikas išeiti +02:00=%1 žiuri į žaidimą iš dangaus +02:00=Ate %1, mes tavęs beveik nežinojom! +02:00=%1 galvojo, kad kulkos neskauda +02:00=%1 būtų panaudojęs papildomą gyvybę +02:00=Ar čia yra daktaras? ; Hog (%1) Drowned -02:01=%1 žaidžia submarina! -02:01=%1 mimikuoja titanika! +02:01=%1 žaidžia povandeninį laivą! +02:01=%1 mėgdžioja titaniką! 02:01=%1 plaukia kaip akmuo! -02:01=%1 pluduriuoja kaip plyta! +02:01=%1 plūduriuoja kaip plyta! 02:01=%1 apžiuri gilumas 02:01=%1 nemėgo vandens 02:01=%1 taškosi -02:01=%1 pamiršo gelbijimosi rata -02:01=%1 tikrai galejo mokintis kaip plaukti +02:01=%1 pamiršo gelbėjimosi ratą +02:01=%1 tikrai galėjo mokytis plaukti 02:01=%1 paliko savo plafkes namie -02:01=%1 ira nublokštas -02:01=%1 ira vienas šlapias ežys -02:01=%1 pamirso atsinešti savo gelbijimosi kostiuma +02:01=%1 yra nublokštas +02:01=%1 yra vienas šlapias ežys +02:01=%1 pamirso atsinešti savo gelbėjimosi kostiumą 02:01=%1 gaudo žuvis 02:01=%1 miega su žuvimis -02:01=%1 galvoja kad vandens psihikos užknisa šitame žaidime +02:01=%1 galvoja, kad vandens fizika užknisa šitame žaidime 02:01=%1 užsimanė gerti -02:01=Jūra pasijėmė %1 +02:01=Jūra paėmė %1 02:01=%1 dingo jūroj -02:01=%1 galejo atsinešti nardimo iranga -02:01=%1 ira palaidotas jūroje -02:01=%1 turi skendimo jausma -02:01=%1 praktikuoja savo plaukimo teknika +02:01=%1 galejo atsinešti nardymo įrangą +02:01=%1 palaidotas jūroje +02:01=%1 turi skendimo jausmą +02:01=%1 praktikuoja savo plaukimo tekniką 02:01=%1 eina ieškoti titaniko -02:01=%1 nera Jėzus +02:01=%1 nėra Jėzus 02:01=%1 ieško Nemo 02:01=%1 neria ant galvos -02:01=Turi pamastyti kiek ten daug ežiu -02:01=%1 padidina jūra -02:01=%1 nebuvo itrauktas i Navy -02:01=%1 mimikuoja mirusia žuvi -02:01=Bent jau nenuėjai žemyn tuoletu, %1 -02:01=Sonikas nemokėjo plaukti nemokėjo ir %1 +02:01=Turi pamąstyti, kiek ten daug ežių +02:01=%1 padidina jūrą +02:01=%1 nebuvo įtrauktas į jūrų laivyną +02:01=%1 mėgdžioja mirusią žuvį +02:01=Bent jau nebuvai nuleistas į klozetą, %1 +02:01=Sonikas nemokėjo plaukti, nemokėjo ir %1 02:01=%1 nori žaisti delfinus -02:01=%1 nuejo i Aquaria -02:01=%1 rado prarasta atlantijos miesta -02:01=Tavo šuniuko stylius galėtu panaudoti šiek tiek daugiau praktikos, %1 -02:01=%1 galėjo atsinešti laiva +02:01=%1 nuėjo į Aquaria +02:01=%1 rado prarastą atlantidos miestą +02:01=Tavo šuniuko stiliui reikia šiek tiek daugiau praktikos, %1 +02:01=%1 galėjo atsinešti laivą 02:01=%1 nepatinka vandens sportas -02:01=%1 visada pucia burbulus +02:01=%1 visada pučia burbulus 02:01=%1 užkliuvo už dumblio -02:01=%1 galvoja kad druskinas vanduo ira gerai odai -02:01=%1 gavo druskino vandens i žaisdas +02:01=%1 galvoja, kad sūrus vanduo yra gerai odai +02:01=%1 gavo sūraus vandens į žaizdas 02:01=%1 ėjo lenta 02:01=%1 nusiprausė -02:01=%1 ira šlapias šlapias šlapias +02:01=%1 yra šlapias šlapias šlapias 02:01=%1 nugurguliavo -02:01=Ir sakei kad nereikia plafkiu %1 +02:01=Ir sakei, kad nereikia plafkiu %1 ; Round starts 02:02=Kaunamės! -02:02=Užsitaise ir pasiruoše! +02:02=Užsitaisę ir pasiruošę! 02:02=Pasiruoškite karui! -02:02=Kas pasiruošes veiksmui! -02:02=Pradedam ši vakarėli +02:02=Kas pasiruošęs veiksmui! +02:02=Pradedam šį vakarėlį 02:02=Paskutinis stovintis ežys laimi 02:02=Varom! 02:02=Išsitaškom! 02:02=Judam! 02:02=Tai prasideda... -02:02=Tai kažko tikrai didelis startas -02:02=Sveiki atvyke i ežiu karus -02:02=Sveiki atvyke i karo lauka -02:02=Sutraiškikit savo priešus! +02:02=Tai pradžia kažko tikrai didelio +02:02=Sveiki atvykę į ežių karus +02:02=Sveiki atvykę į karo lauką +02:02=Sutraiškykite savo priešus! 02:02=Tegul geriausias ežys laimi 02:02=Pergalė arba Mirtis -02:02=Laimėtojas gaus torta +02:02=Laimėtojas gaus tortą 02:02=Pralošimas nėra pasirinkimas 02:02=VAROOOOOM! -02:02=Ežiu karai, pristatyta jums nuo Hedgewars.org +02:02=Ežių karus jums suteikia Hedgewars.org 02:02=GL HF -02:02=Džiaukis kad tau nereikės kovoti prieš Tiyuri -02:02=Džiaukis kad tau nereikės kovoti prieš unC0Rr -02:02=Džiaukis kad tau nereikės kovoti prieš Nemo -02:02=Džiaukis kad tau nereikės kovoti prieš Smaxx -02:02=Džiaukis kad tau nereikės kovoti prieš Uncharted -02:02=Parodyk ka sugebi! -02:02=Pralaimėtojai viska išvalo! -02:02=Pradėkime šia amžiaus kova -02:02=Pradėkime šia legendine kova -02:02=Pradėkime šia nuožmia kova -02:02=Pradėkime šia metu kova -02:02=Pradėkime šia mėnesio kova -02:02=Pradėkime šia savaitės kova -02:02=Pradėkime šia dienos kova -02:02=Pradėkime šia valandos kova -02:02=Išspausk save iki limito! -02:02=Nugalėk prieša! +02:02=Džiaukis, kad tau nereikės kovoti prieš Tiyuri +02:02=Džiaukis, kad tau nereikės kovoti prieš unC0Rr +02:02=Džiaukis, kad tau nereikės kovoti prieš Nemo +02:02=Džiaukis, kad tau nereikės kovoti prieš Smaxx +02:02=Džiaukis, kad tau nereikės kovoti prieš Uncharted +02:02=Parodyk ką sugebi! +02:02=Pralaimėtojai viską išvalo! +02:02=Pradėkime šią amžiaus kovą +02:02=Pradėkime šią legendinę kovą +02:02=Pradėkime šią nuožmią kovą +02:02=Pradėkime šią metų kovą +02:02=Pradėkime šią mėnesio kovą +02:02=Pradėkime šią savaitės kovą +02:02=Pradėkime šią dienos kovą +02:02=Pradėkime šią valandos kovą +02:02=Išspausk save iki ribos! +02:02=Nugalėk priešą! 02:02=Sėkmės 02:02=Pasilinksmink 02:02=Kaukis geroje kovoje @@ -234,14 +239,14 @@ 02:02=Kaukis su garbe 02:02=Nepasiduok 02:02=Niekada nepasiduok -02:02=Išdrapstik ir sutraiškyk! -02:02=Pradėkime šia beprotiška kova! -02:02=Tikiuosi kad tu pasiruošes pavargti! +02:02=Išdrabstyk ir sutraiškyk! +02:02=Pradėkime šią beprotišką kovą! +02:02=Tikiuosi, kad tu pasiruošęs pavargti! 02:02=Varom Varom Varom! 02:02=Judam ežiai! 02:02=Pristatyk jiem tai! 02:02=Nebijok! -02:02=Buk drasus ir laimėk +02:02=Būk drąsus ir laimėk ; Round ends (win; unused atm) 02:03=... @@ -253,273 +258,273 @@ 02:05=Atskrenda pagalba! 02:05=Medikas! 02:05=Pagalba iš dangaus! -02:05=Givybės dėžė tau -02:05=Gera givybė... Dėžės formoi! +02:05=Gyvybės dėžė tau +02:05=Gera gyvybė... Dėžės formoj! 02:05=Woho! 02:05=Nauji lipdukai! 02:05=Štai tai tau padės geriau jaustis -02:05=Givybės šaltinis! -02:05=Tai turėtu pagelbėti! +02:05=Gyvybės šaltinis! +02:05=Tai turėtų pagelbėti! 02:05=Čiupk tai 02:05=Sveikas užkandis 02:05=Vaistai skausmui 02:05=Gerk tik: Tiek kiek gali surasti! -02:05=Siuntinis jums +02:05=Siuntinys jums 02:05=Yay! ; New ammo crate -02:06=Daugiau ginklu! +02:06=Daugiau ginklų! 02:06=Pastiprinimas! 02:06=Užsitaisom ir pasiruošiam! -02:06=Idomu koks ten ginklas? +02:06=Įdomu koks ten ginklas? 02:06=Dėžės! -02:06=Kas galėtu buti viduje? -02:06=Kalėdos ateina anksti ežiu karuose +02:06=Kas galėtų būti viduje? +02:06=Kalėdos ateina anksti ežių karuose 02:06=Dovana! 02:06=Specialus Pristatymas! -02:06=Buvo sunku pranešti pro apsauga.. -02:06=Naikinantis ginklai iš dangaus -02:06=Sprogstancios medziagos viduje -02:06=Pajimk tai arba susprogdink tavo pasirinkimas -02:06=Jega! +02:06=Buvo sunku pranešti pro apsaugą... +02:06=Naikinantys ginklai iš dangaus +02:06=Viduje sprogstančios medžiagos +02:06=Paimk tai arba susprogdink - tavo pasirinkimas +02:06=Jėga! 02:06=Mmmmm Kulkos 02:06=Dėžė! 02:06=Oro Paštas! -02:06=Kad ir kas bebutu šitoje dežėje tai ne pica -02:06=Pajimk tai! +02:06=Kad ir kas bebūtų, šitoje dėžėje tai ne pica +02:06=Paimk tai! 02:06=Ginklai Ginklai Ginklai -02:06=Neleisk Priešui To Pajimti! -02:06=Blizgantis Nauji Žaislai! -02:06=Paslaptinga Dėžė! +02:06=Neleisk priešui šito paimti! +02:06=Blizgantys nauji žaislai! +02:06=Paslaptinga dėžė! ; New utility crate -02:07=Irankiu Laikas! -02:07=Tai Gali Praversti... -02:07=Naudingi Irankiai! -02:07=Išnaudok Šia Dėže -02:07=Atsargiai Žemiau -02:07=Dar Daugiau Naudingu Irankiu! -02:07=Irankiai tau! -02:07=Tai Turėtu Buti Gera! -02:07=Naudok Tai Išmintingai -02:07=Ooo Sunki Dėžė -02:07=Tau Gali Šito Prireikti +02:07=Įrankių metas! +02:07=Tai gali praversti... +02:07=Naudingi įrankiai! +02:07=Išnaudok šią dėžę +02:07=Atsargiai apačioje +02:07=Dar daugiau naudingų įrankių! +02:07=Įrankiai tau! +02:07=Tai turėtu būti geras! +02:07=Naudok tai išmintingai +02:07=Ooo sunki dėžė +02:07=Tau gali šito prireikti ; Hog (%1) skips his turn -02:08=%1 ira toks nuobodus... +02:08=%1 yra toks nuobodus... 02:08=%1 net nesumirksėjo -02:08=%1 ira vienas tingus ežys -02:08=%1 ira tusčiagalvis -02:08=%1 pasidave -02:08=Tu miegi tu praloši, %1 -02:08=%1 gedingai praleidžia eile -02:08=%1 ira tikrai tingus -02:08=%1 reikėtu daugiau motivacijos -02:08=%1 ira pacifistas +02:08=%1 yra vienas tingus ežys +02:08=%1 yra tuščiagalvis +02:08=%1 pasidavė +02:08=Tu miegi - tu praloši, %1 +02:08=%1 gėdingai praleidžia eilę +02:08=%1 yra tikrai tingus +02:08=%1 reikėtų daugiau motyvacijos +02:08=%1 yra pacifistas 02:08=%1 atsiduso 02:08=%1 pailsi 02:08=%1 atostogauja 02:08=%1 netiki savo galimybėmis -02:08=%1 nusprendė apsoluciai nieko nedaryti +02:08=%1 nusprendė visiškai nieko nedaryti 02:08=%1 leidžia priešui susinaikinti pačiam -02:08=%1 butu niekam tikes vakarėliuose +02:08=%1 būtų niekam tikęs vakarėliuose 02:08=%1 pasislepė -02:08=%1 praleido savo šansa -02:08=%1 nusprendė kad geriausias dalykas kuri jis gali daryti ira niekas -02:08=%1 ira bailys -02:08=Puck Puck Puck, %1 ira visčiukas -02:08=%1 atrodo truputi geltonas -02:08=%1 ira didelis bailys! +02:08=%1 praleido savo šansą +02:08=%1 nusprendė, kad geriausias dalykas kurį jis gali daryti, yra niekas +02:08=%1 yra bailys +02:08=Puck Puck Puck, %1 yra viščiukas +02:08=%1 atrodo truputį geltonas +02:08=%1 yra didelis bailys! 02:08=%1 laukia maro -02:08=%1 ira ne kovojimo tipo -02:08=%1 pergalvoja savo prasme gyvenime +02:08=%1 nėra kovotojo tipo +02:08=%1 pergalvoja savo prasmę gyvenime 02:08=%1 ir taip niekada nešaudė taikliai -02:08=%1 nenorėjo eiti i armija pirmoje vietoje -02:08=Baik švaistyti musu laika, %1 -02:08=Aš nusiviliau tavimi, %1 -02:08=Nagi tu gali geriau %1 -02:08=%1 palužo -02:08=%1 turi ka veikti ir be kovojimo +02:08=%1 niekada net nenorėjo eiti į kariuomenę +02:08=Baik švaistyti mūsų laiką, %1 +02:08=Aš nusivyliau tavimi, %1 +02:08=Nagi, tu gali geriau %1 +02:08=%1 palūžo +02:08=%1 turi ką veikti ir be kovojimo 02:08=%1 persigando 02:08=%1 užmigo ; Hog (%1) hurts himself only -02:09=%1 turėtu treniruoti taikluma! -02:09=%1 nekenčia saves -02:09=%1 stovi netoje pusėje! +02:09=%1 turėtų treniruoti taiklumą! +02:09=%1 nekenčia savęs +02:09=%1 stovi ne toje pusėje! 02:09=%1 pasielgė kaip emo -02:09=%1 netaip laikė ginkla +02:09=%1 netaip laikė ginklą 02:09=%1 mėgsta save žaloti 02:09=%1 leidžia priešui mėgautis jo faillu -02:09=%1 neprižiuri saves +02:09=%1 neprižiūri savęs 02:09=%1 susivarė 02:09=%1 susimovė -02:09=Nekoks šuvis, %1 -02:09=%1 galėtu buti atsargesnis su pavojingais ginklais -02:09=%1 turėtu pakeisti karjera -02:09=Blogiausias. Šuvis. Gyvenime! -02:09=Ne ne ne %1, šauk i PRIEŠA! -02:09=%1 turėtu naikinti tik prieša -02:09=%1 artėja prie savizudybės +02:09=Nekoks šūvis, %1 +02:09=%1 galėtų būti atsargesnis su pavojingais ginklais +02:09=%1 turėtų pakeisti karjerą +02:09=Blogiausias. Šūvis. Gyvenime! +02:09=Ne ne ne %1, šauk į PRIEŠĄ! +02:09=%1 turėtų naikinti tik priešą +02:09=%1 artėja prie savižudybės 02:09=%1 padeda priešui 02:09=Tai buvo kvaila %1 -02:09=%1 Palauk KA?? +02:09=%1 Palauk KĄ?? 02:09=%1 susimaišė 02:09=%1 sužaloja save -02:09=%1 myli žeminti save -02:09=%1 ira durnelis! +02:09=%1 mėgsta žeminti save +02:09=%1 yra durnelis! 02:09=%1 neatsargus -02:09=%1 parodo priešui ka sugeba -02:09=%1 sumaišė ataka su šuoliu +02:09=%1 parodo priešui ką sugeba +02:09=%1 sumaišė ataką su šuoliu 02:09=Nesijaudink %1, Nikas Ninuostabus 02:09=%1 taip pasielgė specialiai 02:09=Aš niekam nesakysiu jeigu tu nesakysi, %1 02:09=Kaip gėdinga! -02:09=Aš tikras kad niekas to nematė %1 -02:09=%1 turėjo perskaityti manuala +02:09=Aš tikras, kad niekas to nematė %1 +02:09=%1 turėjo perskaityti manualą 02:09=%1 ginklas tikrai sugedo ; Hog shot an home run (using the bat and another hog) -02:10=Koks smugis! +02:10=Koks smūgis! 02:10=Tai Paukštis Tai Lėktuvas... 02:10=Šitas iškrito! ; Hog (%1) has to leave (team is gone) -02:11=%1 turi eiti i lova! -02:11=%1 atrodo per daug užsijėmes kad galėtu žaisti +02:11=%1 turi eiti į lovą! +02:11=%1 atrodo per daug užsiėmęs, kad galėtų žaisti 02:11=išsigando! 02:11=%1 turi eiti ; Weapon Categories -03:00=Granata Su Laikmačiu -03:01=Granata Su Laikmačiu -03:02=Balistinis Ginklas -03:03=Vadovautas Ginklas -03:04=Ginklas (Keleta Šuviu) -03:05=Kasimosi Irankis +03:00=Granata su laikmačiu +03:01=Granata su laikmačiu +03:02=Balistinis ginklas +03:03=Valdomas ginklas +03:04=Ginklas (keli šūviai) +03:05=Kasimosi įrankis 03:06=Veiksmas -03:07=Transporto Priemonė -03:08=Artumo Bomba -03:09=Ginklas (Keleta Šuviu) +03:07=Transporto priemonė +03:08=Artumo bomba +03:09=Ginklas (keli šūviai) 03:10=BOOM! 03:11=Bonk! -03:12=Kovos Menai -03:13=UNUSED -03:14=Transporto Priemonė -03:15=Aviacinė Ataka -03:16=Aviacinė Ataka -03:17=Kasimosi Irankis -03:18=Naudingas Irankis -03:19=Transporto Priemonė +03:12=Kovos menai +03:13=NENAUDOJAMAS +03:14=Transporto priemonė +03:15=Oro ataka +03:16=Oro Ataka +03:17=Kasimosi įrankis +03:18=Naudingas įrankis +03:19=Transporto priemonė 03:20=Veiksmas -03:21=Balistinis Ginklas -03:22=Vadink Mane Indiana! +03:21=Balistinis ginklas +03:22=Vadink mane Indiana! 03:23=(Tikrai) Kovos Menai 03:24=Tortas NĖRA melas! 03:25=Kostiumas -03:26=Sultinga Granata -03:27=Liepsnojanti Granata -03:28=Balistinis Ginklas -03:29=Balistinis Ginklas -03:30=Aviacinė Ataka -03:31=Pulteliu Valdoma Bomba -03:32=Laikinas Efektas -03:33=Laikinas Efektas -03:34=Laikinas Efektas -03:35=Laikinas Efektas -03:36=Laikinas Efektas -03:37=Laikinas Efektas -03:38=Ginklas (Keleta Šuviu) -03:39=Transporto Priemonė +03:26=Sultinga granata +03:27=Liepsnojanti granata +03:28=Balistinis ginklas +03:29=Balistinis ginklas +03:30=Oro ataka +03:31=Pulteliu valdoma bomba +03:32=Laikinas efektas +03:33=Laikinas efektas +03:34=Laikinas efektas +03:35=Laikinas efektas +03:36=Laikinas efektas +03:37=Laikinas efektas +03:38=Ginklas (keli šūviai) +03:39=Transporto priemonė 03:40=Deginanti Granata 03:41=Paukščiukas 03:42=Dimensijos... ; the misspelled "Beethoven" is intentional (-> to beat) -03:43=Atliekant Mirtina Nata -03:44=Geriausias Prieš: 1923 -03:45=Mokslo Galia +03:43=Atliekant Mirtiną sonatą +03:44=Geriausias iki: 1923 +03:45=Mokslo galia 03:46=Karšta Karšta Karšta! -03:47=Prilipdyk Jas Kur Nors Naudingai! -03:48=Kūjio laikas! -03:49=Daro ka ir galvoji -03:50=Kurmio Fanas -03:51=Rastas Ant Žemės -03:52=UNUSED +03:47=Prilipdyk jas kur nors naudingai! +03:48=Kūjo laikas! +03:49=Daro ką ir galvoji +03:50=Kurmio fanas +03:51=Rastas ant žemės +03:52=NENAUDOJAMAS 03:53=Tipas 40 -;03:54=Pastatyk Ka Nors +;03:54=Pastatyk ką nors ; Weapon Descriptions (use | as line breaks) -04:00=Atakuok savo priešus su paprasta granata.|Ji sprogs kaip jos laikmatis pasieks nuli.|1-5: Nustatyk granatos laikmati|Ataka: Laikyk kad mestum stipriau -04:01=Atakuok savo priešus naudodamas klasterine granata.|Ji pasiskirstis i mažesnes bombas kaip jos|laikmatis pasieks nuli.|1-5: Nustato granatos laikmati|Ataka: Laikyk kad mestum stipriau -04:02=Atakuok savo priešus paleisdamas balistini objekta|kuris gali buti valdomas vėjo.|Ataka: Laikyk kad šautum stipriau -04:03=Paleisk sprogstančia bite kuri seks prieša|arba pasirinkta taikini. Nešauk su pilna jėga|nes tai gadina taikluma.|Pelė: Pasirink taikini|Ataka: Laikyk kad šautum stipriau -04:04=Atakuok savo priešus naudodamas šratini šautuva.|Ačiu jo pasiskirstimui tau nereikia nusitaikity tiesiai i prieša|kad padarytum žalos.|Ataka: Šauna (Keleta Kartu) -04:05=Judėk po žeme naudok kasimo iranga|kad galėtum nusileisti i tuneli arba i kita vietove.|Ataka: Pradėti ir nustoti kasima -04:06=Nusibodo? Nėra Kaip Pulti? Taupai Kulkas?|Jokiu Problemu! Tiesiog praleisk savo eile, baily!|Ataka: Praleidžia tavo eile be veiksmo -04:07=Nuvaryk toli ir greitai|su virve. Numesk ežius i vandeni|arba numesk ant ju granata arba panašius ginklus.|Ataka: Šauk arba atleisk virve|Ilgas Šuolis: Meta granatas arba panašius ginklus -04:08=Laikyk savo priešus kuo toliau numesdamas|mina siauruose praėjimuose arba prie ju kojiu. Tik|buk tikras kad pabėgsi kad pats jos neaktyvuotum!|Ataka: Meta mina tau prie kojiu -04:09=Neesi tikras apie savo taikluma? Naudok pistoleta|su keturiais šuviais.|Ataka: Šauti (Keleta Kartu) -04:10=Stipri ataka visada pasirinkimas. Numesk ši|klasikini sprogmeni priešui prie kojiu ir atsitrauk.|Ataka: Mesk dinamita prie savo kojiu -04:11=Atsikratyk priešo ežiu nudauždamas juos|per vietove i vandeni. Arba|Nudaužk keleta minu savo draugams|Ataka: Daužia viska prieš tave -04:12=Prieik arti priešininko ir paleisk šia|beveik mirtina kovos menu teknika.|Ataka: Padaryk nuostabuji shoryukena. -04:13=UNUSED -04:14=Bijai Aukščiu? Geriau griebk parašiuta.|Jis išsiskleis|kaip busi arti žemės|išsaugok savo eži ir saugiai nusileisk.|Ataka: Išskleidžia parašiuta|Ilgas Šuolis: Meta granatas arba panašius ginklus -04:15=Pakviesk oro streika|kuris paleis linija bombu.|I Kaire/I Dešine: Atakos pusė|Pelė: Pasirink savo taikini -04:16=Iškviesk lėktuva kuris išmes|minu i parinkta vietove.|I Kaire/I Dešine: Atakos pusė|Pelė: Pasirink savo taikini -04:17=Reikia apsaugos? Naudok šia kasimo iranga|kad pasidarytum tuneli kuris tave|pridengs.|Ataka: Pradėk arba nustok kasti -04:18=Reikia apsaugos ar nori pereiti nepereinama vietove?|Padėk keleta platformu ir iveik kliūtis|I Kaire/I Dešine: Pasirink platforma|Pelė: Padėk platforma -04:19=Panaudota teisingu momentu ji gali išgelbėti tavo ežy|tai teleportacija|naudok išmintingai.|Pelė: Pasirink kur teleportuotis -04:20=Leidžia tau pasikeisti ežy|Ataka: Ijunk ežiu keitimasi -04:21=Šauk sviedini kuris sprogs i daugiau bombu|kaip ka nors palies.|Ataka: Šauna pilna jėga -04:22=Netik Indianui Džonsui! Botagas|ira naudingas ginklas dauguma situacijiu. Ipač|kaip norėtum numesti ka nors nuo kalno.|Ataka: Daužk viska priešais tave -04:23=Jeigu neturi ka prarasti,tai gali praversti.|Paaukok ežy leisdamas ji i priešus.|Ataka: Paleisk mirtna ataka -04:24=Su Gimtadieniu! Paleisk ši torta, leisk jam nueiti|arti tavo priešu ir duok jiems sprogstanti vakarėli|tortas praeina visas vietoves tik ant jo ira laikmatis taigi paskubėk.|Ataka: Pradėk torta arba leisk jam nutupti ir sprogti -04:25=Naudok ši kostiuma kad priviliotum priešo ežius ir jie pašoktu iki taves|taip tu gali juos ivilioti i duobes ar kur tik nori.|Ataka: Naudok ši kostiuma ir bandyk suvilioti kita ežy -04:26=Mesk ši sultinga arbūza i savo priešus.|Kaip laikas pasibaigs jis išsiskirstis i arbūzo skiltelias.|1-5: Nustatyk bombos laika|Ataka: Laikyk kad mestum stipriau -04:27=Leisk savo priešams degti pragaro liepsnoje|naudojant šia pragariška granata. Don't get too close to|the explosion as smaller fires might last longer.|Attack: Hold to shoot with more power -04:28=Kaip paleisi šia raketa i žeme|ji pradės kastis ir susprogs|ji sprogsta po kiek laiko arba kaip nebera zemės|Ataka: Laikyk kad šautum stipriau -04:29=Tai ne vaiku žaislas! Kamuoliu ginklas|išauna tona spalvotu kamuoliuku kurie sprogsta.|Ataka: Šauna pilna galia|I Viršu/I Apačua: Nuolatinis nusitaikimas -04:30=Pakviesk napalma.Jis išdegins viska kas tik trugdys|ir padarys daug žalos|tik atsargiai ugnis reguoja i vėji.|I Kaire/I Dešine: Atakos pusė|Pelė: Pasirink savo taikini -04:31=RBV Lėktuvėlis ira puikus ginklas rinkti dėžėms|pulti tolimus ežius.Gali numesti bombu|ir i juos atsitrenkti.|Ataka: Paleisti lėktuva arba mesti bombas|Ilgas Šuolis: Paleidžia dramatine muzika|I Kaire/I Dešine: Valdyk lėktuvėli -04:32=Maža gravitacija ira efektyviau negu dieta! Šok|aukščiau ir toliau arba leisk savo priešam skristi dar toliau.|Ataka: Aktyvuoti +04:00=Pulk savo priešus su paprasta granata.|Ji sprogs kai jos laikmatis pasieks nulį.|1-5: Nustatyk granatos laikmatį|Ataka: Laikyk, kad mestum stipriau +04:01=Pulk savo priešus naudodamas klasterinę granatą.|Ji pasiskirstys į mažesnes bombas kai jos|laikmatis pasieks nulį.|1-5: Nustato granatos laikmatį|Ataka: Laikyk, kad mestum stipriau +04:02=Pulk savo priešus paleisdamas balistinį objektą,|kuris gali būti valdomas vėjo.|Ataka: Laikyk, kad šautum stipriau +04:03=Paleisk sprogstančią bitę, kuri seks priešą|arba pasirinktą taikinį. Nešauk su pilna jėga,|nes tai gadina taiklumą.|Pelė: Pasirink taikini|Ataka: Laikyk, kad šautum stipriau +04:04=Pulk savo priešus naudodamas šratinį šautuvą.|Dėl jo pasiskirstymo tau nereikia nusitaikiti tiesiai į priešą,|kad padarytum žalos.|Ataka: Šauna (Keleta kartų) +04:05=Judėk po žeme, naudok kasimo įrangą,|kad galėtum nusileisti į tunelį arba į kitą vietovę.|Ataka: Pradėti ir nustoti kasimą +04:06=Nusibodo? Nėra Kaip Pulti? Taupai kulkas?|Jokių problemų! Tiesiog praleisk savo eilę, baily!|Ataka: Praleidžia tavo eilę be veiksmo +04:07=Nuvaryk toli ir greitai|su virve. Numesk ežius į vandenį|arba numesk ant jų granatą arba panašius ginklus.|Ataka: Šauk arba atleisk virvę|Ilgas Šuolis: Meta granatas arba panašius ginklus +04:08=Laikyk savo priešus kuo toliau, numesdamas|miną siauruose praėjimuose arba prie jų kojų. Tik|būk tikras, kad pabėgsi pats jos neaktyvavęs!|Ataka: Meta miną tau prie kojų +04:09=Nesi tikras dėl savo taiklumo? Naudok pistoletą|su keturiais šūviais.|Ataka: Šauti (keleta kartų) +04:10=Stipri ataka visada pasirinkimas. Numesk šį|klasikinį sprogmenį priešui prie kojų ir atsitrauk.|Ataka: Mesk dinamitą prie savo kojų +04:11=Atsikratyk priešo ežiais, nudauždamas juos|per vietovę į vandenį. Arba|Nudaužk keletą minų savo draugams|Ataka: Daužia viską prieš tave +04:12=Prieik arti prie priešininko ir panaudok šią|beveik mirtiną kovos menų techniką.|Ataka: Padaryk nuostabųjį shoryukena. +04:13=NENAUDOJAMAS +04:14=Bijai aukščio? Geriau griebk parašiutą.|Jis išsiskleis|kai būsi arti žemės|išsaugok savo ežį ir saugiai nusileisk.|Ataka: Išskleidžia parašiutą|Ilgas Šuolis: Meta granatas arba panašius ginklus +04:15=Pakviesk oro smūgį,|kuris paleis eilę bombu.|Į kairę/Į dešinę: Atakos pusė|Pelė: Pasirink savo taikinį +04:16=Iškviesk lėktuvą, kuris išmes|minų į parinktą vietovę.|Į kairę/Į dešinę: Atakos pusė|Pelė: Pasirink savo taikinį +04:17=Reikia apsaugos? Naudok šią kasimo įrangą,|kad pasidarytum tunelį, kuris tave|pridengs.|Ataka: Pradėk arba nustok kasti +04:18=Reikia apsaugos ar nori pereiti nepereinama vietovę?|Padėk keletą platformų ir įveik kliūtis|Į kairę/Į dešinę: Pasirink platformą|Pelė: Padėk platformą +04:19=Panaudota teisingu momentu, ji gali išgelbėti tavo ežį|tai teleportacija|naudok išmintingai.|Pelė: Pasirink kur teleportuotis +04:20=Leidžia tau pasikeisti ežį|Ataka: Įjunk ežių keitimąsi +04:21=Šauk sviedinį, kuris sprogs į daugiau bombų|kai ką nors palies.|Ataka: Šauna pilna jėga +04:22=Netik Indianui Džonsui! Botagas|yra naudingas ginklas daugumoje situacijų. Ypač|kai norėtum numesti ką nors nuo kalno.|Ataka: Daužk viską priešais tave +04:23=Jeigu neturi ką prarasti, tai gali praversti.|Paaukok ežį leisdamas jį į priešus.|Ataka: Paleisk mirtną ataką +04:24=Su Gimtadieniu! Paleisk šį tortą, leisk jam nueiti|arti tavo priešų ir duok jiems sprogstantį vakarėlį|tortas praeina visas vietoves tik ant jo yra laikmatis, taigi paskubėk.|Ataka: Detonuok tortą arba leisk jam nutūpti ir sprogti +04:25=Naudok šį kostiumą, kad priviliotum priešo ežius ir jie pašoktu iki taves|taip tu gali juos įvilioti į duobes ar kur tik nori.|Ataka: Naudok šį kostiumą ir bandyk suvilioti kitą ežį +04:26=Mesk šį sultingą arbūzą į savo priešus.|Kai laikas pasibaigs, jis išsiskirstys į arbūzo skilteles.|1-5: Nustatyk bombos laiką|Ataka: Laikyk, kad mestum stipriau +04:27=Leisk savo priešams degti pragaro liepsnoje|naudojant šią pragarišką granatą. Nebūk per arti|sprogimo, nes mažos liepsnelės ilgiau liepsnos.|Ataka: Laikyk, kad mestum stipriau +04:28=Kai paleisi šią raketą į žemę|ji pradės kastis ir susprogs|ji sprogsta po kiek laiko arba kai nebėra žemės|Ataka: Laikyk, kad šautum stipriau +04:29=Tai ne vaikų žaislas! Kamuolių ginklas|iššauna daug spalvotų kamuoliukų, kurie sprogsta.|Ataka: Šauna pilna galia|Į viršų/Į apačią: Nuolatinis nusitaikymas +04:30=Pakviesk napalmą. Jis išdegins viską, kas tik trugdys|ir padarys daug žalos|tik atsargiai - ugnis reguoja į vėją.|Į kairę/Į dešinę: Atakos pusė|Pelė: Pasirink savo taikinį +04:31=RBV Lėktuvėlis yra puikus ginklas rinkti dėžėms|pulti tolimus ežius. Gali numesti bombų|ir i juos atsitrenkti.|Ataka: Paleisti lėktuvą arba mesti bombas|Ilgas Šuolis: Paleidžia dramatinę muziką|Į kairę/Į dešinę: Valdyk lėktuvėlį +04:32=Maža gravitacija yra efektyviau nei dieta! Šok|aukščiau ir toliau arba leisk savo priešams skristi dar toliau.|Ataka: Aktyvuoti 04:33=Kartais tau reikia pagalbos padaryti daugiau žalos.|Ataka: Aktyvuoti -04:34=Negalite manes paliesti!|Ataka: Aktyvuoti -04:35=Kartais laikas bėga per daug greitai.Pačiupk ekstra|sekundžiu kad pabaigtum savo ataka.|Ataka: Aktyvuoti -04:36=Na, kartais tu tiesiog blogas taiklume.Gauk modernios pagalbos.|Ataka: Aktyvuoti -04:37=Nebijok dienos šviesos. Tai galios tik viena eile|bet aktyvuos pasigydima nuo žalios kokia padarai|kitiem ežiam.|Ataka: Aktyvuoti -04:38=Snaiperis gali buti pats pavojingiausias ginklas|visame tavo arsenale, gaila kad jis niekam tikes iš arti.|Taigi iš kuo toliau šauni tuo daugiau žalos padarai|Ataka: Šauna (Keleta Kartu) -04:39=Skrisk i kitas žemėlapio vietas.|Skraidanti lėkštė gali nunešti tave kur tik pageidauji|tik ja sunku ivaldyti.|Ataka: Aktivuok|I viršu/I Kaire/I Dešine: Spaudinėk lėtai|Ilgas šuolis: Mes granatas arba panašius ginklus -04:40=Padegink vietove |su buteliu pripildytu degančiu skysčiu.|Ataka: Laikyk kad mestum stipriau -04:41=Tai kažkas keistesnio už skrendančias lėkštes tai valdomas paukštis.|Paukščiukas nešioja tavo ežy po žemėlapi|ir meta kiaušinius ant tavo priešu!|Ataka: Aktyvuoja ir meta kiaušinius|I Viršu/I Kaire/I Dešine: Valdyk paukšti -04:42=Šitas nešiojimas teleportacijos irankis|gali teleportuoti ir tave ir tavo priešus per visa žemėlapi|ir leidžia tau imesti i ji visokius ginklus|Naudok ji išmintingai|IR LAIMĖSI!|Ataka: Šauk Portala|Jungiklis: Rinkis portalo spalvas -04:43=Mesk milziniska pienina ant savo priešu galvu!|Bet atsargiai|Tai gali kainuoti tau tavo gyvibe|Pelė: Pasirink taikini |F1-F9: Grok Pianu -04:44=Tai ne tik suris, tai tikrai senas suris!|Jis nepadarys daug žalos|bet kaip laikmatis pasieks nuli jis |užnuodis visus kurie pajaučia kvapa!|1-5: Nustatyk granatos laikmati|Ataka: Laikyk kad mestum stipriau -04:45=Visos tos psyhikos klasės pagaliau atsimokėjo|Paleisk smarkia vėjo banga|i savo priešus.|Atsargiai, šitas ginklas nejuokauja. (Šitas Ginklas Dar Nebaigtas)|Ataka: Šauna -04:46=Apdenk savo priešus ugnies apvalkalu.|Karštoka!|Ataka: Aktivuok|I Viršu/I apačia: Nenustok taikitis |Kaire/Dešinė: Perstatyk spjovimo galia -04:47=Dvigubai idomiau Su dviem lipniom minom!|Padaryk grandine reakcija arba apsigink save (arba abu!)|Ataka: Laikyti kad mestum stipriau (dvigubai) -04:48=Kūjis netik viniui ikalti bet ir|daužti ežiui per galva|nujima priešininko gyvibe ir dar numuša ji i žeme.|Ataka: Aktivuoti -04:49=Atgaivink Savo Draugus!|Bet atsargiai tai atgaivina ir tavo priešus.|Ataka: Laikyk paspaudes ataka kad atgaivintum lėtai|I Viršu: Pagreitina atgaivinima +04:34=Negalite manęs paliesti!|Ataka: Aktyvuoti +04:35=Kartais laikas bėga per daug greitai. Gauk papildomų|sekundžių, kad pabaigtum savo ataką.|Ataka: Aktyvuoti +04:36=Na, kartais tu tiesiog netaiklus. Gauk modernios pagalbos.|Ataka: Aktyvuoti +04:37=Nebijok dienos šviesos. Tai galios tik viena ėjimą,|bet aktyvuos pasigydimą nuo žalos kokią padarai|kitiems ežiams.|Ataka: Aktyvuoti +04:38=Snaiperis gali buti pats pavojingiausias ginklas|visame tavo arsenale, gaila kad jis niekam tikęs iš arti.|Taigi iš kuo toliau šauni tuo daugiau žalos padarai|Ataka: Šauna (Keleta Kartu) +04:39=Skrisk į kitas žemėlapio vietas.|Skraidanti lėkštė gali nunešti tave kur tik pageidauji|tik ją sunku įvaldyti.|Ataka: Aktyvuok|Į viršų/Į kairę/Į dešinę: Spaudinėk lėtai|Ilgas šuolis: Mes granatas arba panašius ginklus +04:40=Padegink vietovę|su buteliu, pripildytu degančiu skysčiu.|Ataka: Laikyk, kad mestum stipriau +04:41=Tai kažkas keistesnio už skrendančias lėkštes, tai - valdomas paukštis.|Paukščiukas nešioja tavo ežį po žemėlapį|ir meta kiaušinius ant tavo priešu!|Ataka: Aktyvuoja ir meta kiaušinius|Į viršų/Į kairę/Į dešinę: Valdyk paukštį +04:42=Šitas nešiojimas teleportacijos įrankis|gali teleportuoti ir tave, ir tavo priešus per visa žemėlapį|ir leidžia tau įmesti į jį visokius ginklus|Naudok jį išmintingai|IR LAIMĖSI!|Ataka: Šauk Portalą|Jungiklis: Rinkis portalo spalvas +04:43=Mesk milžinišką pianiną ant savo priešų galvų!|Bet atsargiai|Tai gali kainuoti tau tavo gyvybę|Pelė: Pasirink taikini |F1-F9: Grok Pianinu +04:44=Tai ne tik sūris, tai tikrai senas sūris!|Jis nepadarys daug žalos|bet kai laikmatis pasieks nulį, jis |užnuodys visus, kurie pajaučia kvapą!|1-5: Nustatyk granatos laikmatį|Ataka: Laikyk, kad mestum stipriau +04:45=Visos tos fizikos pamokos pagaliau atsipirko|Paleisk smarkią vėjo bangą|į savo priešus.|Atsargiai, šitas ginklas nejuokauja. (Šitas ginklas dar nebaigtas)|Ataka: Šauna +04:46=Apdenk savo priešus ugnies apvalkalu.|Karštoka!|Ataka: Aktyvuok|Į viršų/Į apačią: Nenustok taikytis |Kairė/Dešinė: Perstatyk spjovimo galią +04:47=Dvigubai įdomiau Su dviem lipniom minom!|Padaryk grandininę reakcija arba apsigink save (arba abu!)|Ataka: Laikyk, kad mestum stipriau (dvigubai) +04:48=Kūjis ne tik viniai įkalti, bet ir|daužti ežiui per galvą|nuima priešininko gyvybę ir dar numuša jį į žemę.|Ataka: Aktyvuoti +04:49=Atgaivink savo draugus!|Bet atsargiai, tai atgaivina ir tavo priešus.|Ataka: Laikyk paspaudęs ataką, kad atgaivintum lėtai|Į viršu: Pagreitina atgaivinimą ; Game goal strings 05:00=Žaidimo režimai 05:01=Taikomos šios taisyklės -05:02=Fortai: Gink savo forta; nugalėk savo priešus! -05:03=Maža gravitacija: Žėk kur eini! -05:04=Nemirtingumas: Ežiai ira (beveik) nemirtingi -05:05=Vampirizmas: Ežiai bus pagyditi su žala kuria jie padaro +05:02=Fortai: Gink savo fortą; nugalėk savo priešus! +05:03=Maža gravitacija: Žiūrėk kur eini! +05:04=Nemirtingumas: Ežiai yra (beveik) nemirtingi +05:05=Vampirizmas: Ežiai bus pagydyti su žala, kurią jie padaro 05:06=Karma: Priešo ežiai nukentės taip pat kaip ir tavo -05:07=Apgink Karali: Neleisk savo karaliui mirti!|Padėk karali: Pasirink apginta startavimo pozicija savo karaliui -05:08=Padėk Ežius: Padėk savo ežius prieš žaidima -05:09=Artilerija: Ežiai negali vaiksčioti -05:10=Nesunaikinoma Vietovė: Daugiausia ginklu nesunaikins vietovės +05:07=Apgink Karalių: Neleisk savo karaliui mirti!|Padėk karaliui: Pasirink apginta pradžios poziciją savo karaliui +05:08=Padėk ežius: Padėk savo ežius prieš žaidimą +05:09=Artilerija: Ežiai negali vaikščioti +05:10=Nesunaikinoma Vietovė: Dauguma ginklų nesunaikins vietovės 05:11=Pasidalintos Kulkos: Visos komandos tomis pačiomis spalvomis pasidalina kulkomis -05:12=Minu Laikmačiai: Minos detonuosis po %1 second(s) -05:13=Minu Laikmačiai: Minos detonuosis iškart -05:14=Minu Laikmačiai: Minos detonuosis po 0 - 5 sekundžiu +05:12=Minų Laikmačiai: Minos detonuosis po %1 sekundės(-žių) +05:13=Minu Laikmačiai: Minos detonuosis iš karto +05:14=Minu Laikmačiai: Minos detonuosis po 0 - 5 sekundžių 05:15=Žalos Modifikatorius: Visi ginklai darys %1% žalos -05:16=Visu ežiu gyvibės atsitato kaip baigi eile +05:16=Visų ežių gyvybės atsistato kai baigi eilę 05:17=AI Ežiai atsikelia po mirties -05:18=Nesibaigiančios Atakos -05:19=Ginklai atstatyti kaip baigi eile -05:20=Ginklai nesidalinami tarp ežiu -05:21=Komandinis Režimas: Komandos klane visi juda po eile|Pasidalintas laikas: Komandos klane pasidalina laiku \ No newline at end of file +05:18=Nesibaigiančios atakos +05:19=Ginklai atstatomi, kai baigi eilę +05:20=Ginklai nesidalinami tarp ežių +05:21=Komandinis Režimas: Komandos klane visi juda po eilę|Pasidalintas laikas: Komandos klane pasidalina laiku \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/missions_de.txt --- a/share/hedgewars/Data/Locale/missions_de.txt Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/missions_de.txt Tue Nov 10 20:43:13 2015 +0100 @@ -1,23 +1,29 @@ -Basic_Training_-_Bazooka.name=Training: Bazooka - Grundlagen +Basic_Training_-_Bazooka.name=Grundlagentraining: Bazooka Basic_Training_-_Bazooka.desc="Nutze den Wind zu deinem Vorteil aus!" -Basic_Training_-_Grenade.name=Training: Granate - Grundlagen +Basic_Training_-_Grenade.name=Grundlagentraining: Granate Basic_Training_-_Grenade.desc="Vergiss nicht: Stift ziehen UND werfen!" -Basic_Training_-_Shotgun.name=Training: Schrotflinte - Grundlagen +Basic_Training_-_Shotgun.name=Grundlagentraining: Schrotflinte Basic_Training_-_Shotgun.desc="Zuerst schießen, dann fragen!" -Basic_Training_-_Sniper_Rifle.name=Training: Scharfschützengewehr - Grundlagen -Basic_Training_-_Sniper_Rifle.desc="Boom, headshot!" +Basic_Training_-_Sniper_Rifle.name=Grundlagentraining: Scharfschützengewehr +Basic_Training_-_Sniper_Rifle.desc="Peng, Kopfschuss!" + +Basic_Training_-_Cluster_Bomb.name=Grundlagentraining: Splittergranate +Basic_Training_-_Cluster_Bomb.desc="Jemand braucht eine heiße Dusche!" -User_Mission_-_Dangerous_Ducklings.name=Mission: Dangerous Ducklings -User_Mission_-_Dangerous_Ducklings.desc="Nun gut, Rekrut! Es ist Zeit, dass du das im Grundlagentraining gelernte in die Tag umsetzt!" +Basic_Training_-_Rope.name=Grundlagentraining: Seil +Basic_Training_-_Rope.desc="Raus da und schwing!" + +User_Mission_-_Dangerous_Ducklings.name=Mission: Gefährliche Entchen +User_Mission_-_Dangerous_Ducklings.desc="Nun gut, Rekrut! Es ist Zeit, dass du das im Grundlagentraining Gelernte in die Tag umsetzt!" User_Mission_-_Diver.name=Mission: Taucher -User_Mission_-_Diver.desc="Diese amphibische Angriffstrategie ist schwieriger als sie aussieht." +User_Mission_-_Diver.desc="Diese amphibische Angriffstrategie ist schwieriger, als sie aussieht." User_Mission_-_Teamwork.name=Mission: Teamwork -User_Mission_-_Teamwork.desc="Ab und zu... tut Liebe weh." +User_Mission_-_Teamwork.desc="Ab und zu … tut Liebe weh." User_Mission_-_Spooky_Tree.name=Mission: Spukiger Baum User_Mission_-_Spooky_Tree.desc="Viele Kisten hier draußen. Ich hoffe jedenfalls, dass dieser Vogel hier nicht hungrig wird." @@ -25,8 +31,57 @@ User_Mission_-_Bamboo_Thicket.name=Mission: Bambusdickicht User_Mission_-_Bamboo_Thicket.desc="Tod von oben." -User_Mission_-_That_Sinking_Feeling.name=Mission: That Sinking Feeling -User_Mission_-_That_Sinking_Feeling.desc="Hier steht einen das Wasser ganz schön schnell bis zu Hals. Viele sind hieran gescheitert. Kannst du alle Igel retten?" +User_Mission_-_That_Sinking_Feeling.name=Mission: Land unter +User_Mission_-_That_Sinking_Feeling.desc="Hier steht einen das Wasser ganz schön schnell bis zum Halse. Viele sind hieran gescheitert. Kannst du alle Igel retten?" User_Mission_-_Newton_and_the_Hammock.name=Mission: Newton und die Hängematte -User_Mission_-_Newton_and_the_Hammock.desc="Nicht vergessen Igelinge: Die Geschwindigkeit eines Körpers bleibt konstant, es sei denn es wirkt eine äußere Kraft wird auf ihn ein!" +User_Mission_-_Newton_and_the_Hammock.desc="Nicht vergessen, Igelinge: Die Geschwindigkeit eines Körpers bleibt konstant, es sei denn, es wirkt eine äußere Kraft auf ihn ein!" + +User_Mission_-_The_Great_Escape.name=Mission: Gesprengte Ketten +User_Mission_-_The_Great_Escape.desc="Glaubst du, dass du mich einsperren könnest?" + +User_Mission_-_Rope_Knock_Challenge.name=Herausforderung: Seilschubsen +User_Mission_-_Rope_Knock_Challenge.desc="Sieh! Hinter dir!" + +User_Mission_-_Nobody_Laugh.name=Mission: Niemand darf lachen +User_Mission_-_Nobody_Laugh.desc="Das ist kein Witz!" + +User_Mission_-_RCPlane_Challenge.name=Herausforderung: Funkflugzeug +User_Mission_-_RCPlane_Challenge.desc="Bist wohl ziemlich eingebildet, was, Flieger?" + +portal.name=Mission: Knifflige Portalherausforderung +portal.desc="Benutze das Portalgerät, um dich schnell und weit zu bewegen; benutze es zum Töten; benutze es mit Vorsicht!" + +Target_Practice_-_Bazooka_easy.name=Zielübung: Bazooka (einfach) +Target_Practice_-_Bazooka_easy.desc="Nun gut, Soldat: Zerstör einfach die Zielscheiben so schnell, wie du kannst!" + +Target_Practice_-_Bazooka_hard.name=Zielübung: Bazooka (schwer) +Target_Practice_-_Bazooka_hard.desc="Kannst du die Zielscheiben treffen, auch wenn sie sehr weit weg sind?" + +Target_Practice_-_Cluster_Bomb.name=Zielübung: Splittergranate +Target_Practice_-_Cluster_Bomb.desc="Jemand braucht eine heiße Dusche!" + +Target_Practice_-_Shotgun.name=Zielübung: Schrotflinte +Target_Practice_-_Shotgun.desc="Erst schießen, dann fragen!" + +Target_Practice_-_Homing_Bee.name=Zielübung: Zielsuchende Biene +Target_Practice_-_Homing_Bee.desc="Die zielsuchende Biene zu benutzen ist kniffliger, als es aussieht!" + +Target_Practice_-_Grenade_easy.name=Zielübung: Granate (einfach) +Target_Practice_-_Grenade_easy.desc="Eine Aufwärmübung für den aufstrebenden Grenadier." + +Target_Practice_-_Grenade_hard.name=Zielübung: Granate (schwer) +Target_Practice_-_Grenade_hard.desc="Das ist nichts für Grünschnäbel! Wir werden die Zielscheiben an ein paar wirklich knifflige Stellen platzieren." + +ClimbHome.name=Herausforderung: Nach Hause klettern +ClimbHome.desc="Du bist weit von Zuhause weg und das Wasser steigt ständig. Klettere so hoch, wie du kannst!" + +Challenge_-_Speed_Shoppa_-_Hedgelove.name=Herausforderung: Seilliebe +Challenge_-_Speed_Shoppa_-_Hedgelove.desc="Zeig deine Liebe zum Seilschwingen, sammle ein paar wenige Kisten auf dieser kleinen Karte ein." + +Challenge_-_Speed_Shoppa_-_Ropes.name=Herausforderung: Seile und Kisten +Challenge_-_Speed_Shoppa_-_Ropes.desc="Nimm dein Seil, und sammle alle Kisten auf dieser mittelgroßen Karte ein." + +Challenge_-_Speed_Shoppa_-_ShoppaKing.name=Herausforderung: Der Kunde ist König +Challenge_-_Speed_Shoppa_-_ShoppaKing.desc="Zeig, dass du dem Titel eines Königs würdig bist und sammle alle Kisten so schnell wie möglich mit deinem Seil auf dieser großen Karte ein." + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/missions_el.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Locale/missions_el.txt Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,53 @@ +Basic_Training_-_Bazooka.name=Βασική Εκπαίδευση Μπαζούκα +Basic_Training_-_Bazooka.desc="Το κλειδί είναι να χρησιμοποιήσεις τον άνεμο προς όφελός σου!" + +Basic_Training_-_Grenade.name=Βασική Εκπαίδευση Χειροβομβίδας +Basic_Training_-_Grenade.desc="Θυμίσου, τραβάς την περόνη ΚΑΙ πετάς!" + +Basic_Training_-_Cluster_Bomb.name=Βασική Εκπαίδευση Βόμβας Θραυσμάτων +Basic_Training_-_Cluster_Bomb.desc="Κάποιος χρειάζεται ένα καυτό ντουζ!" + +Basic_Training_-_Shotgun.name=Βασική Εκπαίδευση Καραμπίνας +Basic_Training_-_Shotgun.desc="Πυροβόλα πρώτα, ρώτα μετά!" + +Basic_Training_-_Sniper_Rifle.name=Βασική Εκπαίδευση Ελεύθερου Σκοπευτή +Basic_Training_-_Sniper_Rifle.desc="Μπαμ, χτύπημα στο κεφάλι!" + +Basic_Training_-_Rope.name=Βασική Εκπαίδευση Σκοινιού +Basic_Training_-_Rope.desc="Τράβα εκεί έξω και κουνίσου!" + +User_Mission_-_Dangerous_Ducklings.name=Αποστολή: Επικίνδυνα Παπιά +User_Mission_-_Dangerous_Ducklings.desc="Λοιπόν, στραβάδι! Καιρός να θέσουμε ό,τι μάθαμε στη Βασική Εκπαίδευση σε εφαρμογή!" + +User_Mission_-_Diver.name=Αποστολή: Δύτης +User_Mission_-_Diver.desc="Αυτή η 'αμφίβια εισβολή' είναι πιο δύσκολη απ'ότι φαίνεται..." + +User_Mission_-_Teamwork.name=Αποστολή: Ομαδική Δουλειά +User_Mission_-_Teamwork.desc="Μερικές φορές, η αγάπη πονάει." + +User_Mission_-_Spooky_Tree.name=Αποστολή: Τρομακτικό Δέντρο +User_Mission_-_Spooky_Tree.desc="Πολλά κιβώτια εκεί έξω. Ελπίζω αυτό το πτηνό να μην αισθάνεται πεινασμένο." + +User_Mission_-_Bamboo_Thicket.name=Αποστολή: Θάμνος από Bamboo +User_Mission_-_Bamboo_Thicket.desc="Ο θάνατος έρχεται από κάτω." + +User_Mission_-_That_Sinking_Feeling.name=Αποστολή: Αυτό το Αίσθημα ότι Βουλιάζεις +User_Mission_-_That_Sinking_Feeling.desc="Η στάθμη του νερού ανεβαίνει απότομα και ο χρόνος είναι περιορισμένος. Πολλοί προσπάθησαν και απέτυχαν. Μπορείς να τους σώσεις όλους;" + +User_Mission_-_Newton_and_the_Hammock.name=Αποστολή: ο Νεύτωνας και η Αιώρα +User_Mission_-_Newton_and_the_Hammock.desc="Θυμηθείτε σκαντζοχοίρια: Η ταχύτητα ενός σώματος παραμένει σταθερή εκτός εάν ασκηθεί στο σώμα κάποια εξωτερική δύναμη!" + +User_Mission_-_The_Great_Escape.name=Αποστολή: Η Μεγάλη Απόδραση +User_Mission_-_The_Great_Escape.desc="Νομίζεις ότι μπορείς να με φυλακίσεις!;" + +User_Mission_-_Rope_Knock_Challenge.name=Πρόκληση: Χτύπημα με Σκοινί +User_Mission_-_Rope_Knock_Challenge.desc="Κοίτα πίσω σου!" + +User_Mission_-_Nobody_Laugh.name=Αποστολή: Μη Γελάσει Κανείς +User_Mission_-_Nobody_Laugh.desc="Αυτό δεν είναι αστείο." + +User_Mission_-_RCPlane_Challenge.name=Πρόκληση: Τηλεκατευθυνόμενο Αεροπλάνο +User_Mission_-_RCPlane_Challenge.desc="Νοιώθεις πολύ σίγουρος, ε, πιλότε;" + +portal.name=Αποστολή: Σπαζοκεφαλιά με Πύλες(Portals) +portal.desc="Χρησιμοποίησε την πύλη για να μετακινηθείς γρήγορα και μακριά, χρησιμοποιησέ την για να σκοτώσεις, χρησιμοποιησέ την με προσοχή!" diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/missions_en.txt --- a/share/hedgewars/Data/Locale/missions_en.txt Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/missions_en.txt Tue Nov 10 20:43:13 2015 +0100 @@ -1,53 +1,83 @@ -Basic_Training_-_Bazooka.name=Basic Bazooka Training -Basic_Training_-_Bazooka.desc="Using the wind to your advantage is key!" - -Basic_Training_-_Grenade.name=Basic Grenade Training -Basic_Training_-_Grenade.desc="Remember, you pull the pin out AND throw!" - -Basic_Training_-_Cluster_Bomb.name=Basic Cluster Bomb Training -Basic_Training_-_Cluster_Bomb.desc="Someone needs hot shower!" - -Basic_Training_-_Shotgun.name=Basic Shotgun Training -Basic_Training_-_Shotgun.desc="Shoot first, ask questions later!" - -Basic_Training_-_Sniper_Rifle.name=Basic Sniper Rifle Training -Basic_Training_-_Sniper_Rifle.desc="Boom, headshot!" - -Basic_Training_-_Rope.name=Basic Rope Training -Basic_Training_-_Rope.desc="Get out there and swing!" - -User_Mission_-_Dangerous_Ducklings.name=Mission: Dangerous Ducklings -User_Mission_-_Dangerous_Ducklings.desc="Alright, rookie! Time to put what we learned in Basic Training into practice!" - -User_Mission_-_Diver.name=Mission: Diver -User_Mission_-_Diver.desc="This 'amphibious assault' thing is harder than it looks..." - -User_Mission_-_Teamwork.name=Mission: Teamwork -User_Mission_-_Teamwork.desc="Sometimes, love hurts." - -User_Mission_-_Spooky_Tree.name=Mission: Spooky Tree -User_Mission_-_Spooky_Tree.desc="Lots of crates out here. I sure hope that bird ain't feeling hungry." - -User_Mission_-_Bamboo_Thicket.name=Mission: Bamboo Thicket -User_Mission_-_Bamboo_Thicket.desc="Death comes from above." - -User_Mission_-_That_Sinking_Feeling.name=Mission: That Sinking Feeling -User_Mission_-_That_Sinking_Feeling.desc="The water is rising rapidly and time is limited. Many have tried and failed. Can you save them all?" - -User_Mission_-_Newton_and_the_Hammock.name=Mission: Newton and the Hammock -User_Mission_-_Newton_and_the_Hammock.desc="Remember hoglets: The velocity of a body remains constant unless the body is acted upon by an external force!" - -User_Mission_-_The_Great_Escape.name=Mission: The Great Escape -User_Mission_-_The_Great_Escape.desc="You think you can cage me!?" - -User_Mission_-_Rope_Knock_Challenge.name=Challenge: Rope Knocking -User_Mission_-_Rope_Knock_Challenge.desc="Look behind you!" - -User_Mission_-_Nobody_Laugh.name=Mission: Nobody Laugh -User_Mission_-_Nobody_Laugh.desc="This ain't no joke." - -User_Mission_-_RCPlane_Challenge.name=Challenge: RC Plane -User_Mission_-_RCPlane_Challenge.desc="Feeling pretty confident, eh, flyboy?" - -portal.name=Mission: Portal Mind Challenge -portal.desc="Use the portal to move fast and far, use it to kill, use it with caution!" +Basic_Training_-_Bazooka.name=Basic Bazooka Training +Basic_Training_-_Bazooka.desc="Using the wind to your advantage is key!" + +Basic_Training_-_Grenade.name=Basic Grenade Training +Basic_Training_-_Grenade.desc="Remember, you pull the pin out AND throw!" + +Basic_Training_-_Cluster_Bomb.name=Basic Cluster Bomb Training +Basic_Training_-_Cluster_Bomb.desc="Someone needs hot shower!" + +Basic_Training_-_Shotgun.name=Basic Shotgun Training +Basic_Training_-_Shotgun.desc="Shoot first, ask questions later!" + +Basic_Training_-_Sniper_Rifle.name=Basic Sniper Rifle Training +Basic_Training_-_Sniper_Rifle.desc="Boom, headshot!" + +Basic_Training_-_Rope.name=Basic Rope Training +Basic_Training_-_Rope.desc="Get out there and swing!" + +User_Mission_-_Dangerous_Ducklings.name=Mission: Dangerous Ducklings +User_Mission_-_Dangerous_Ducklings.desc="Alright, rookie! Time to put what we learned in Basic Training into practice!" + +User_Mission_-_Diver.name=Mission: Diver +User_Mission_-_Diver.desc="This 'amphibious assault' thing is harder than it looks..." + +User_Mission_-_Teamwork.name=Mission: Teamwork +User_Mission_-_Teamwork.desc="Sometimes, love hurts." + +User_Mission_-_Spooky_Tree.name=Mission: Spooky Tree +User_Mission_-_Spooky_Tree.desc="Lots of crates out here. I sure hope that bird ain't feeling hungry." + +User_Mission_-_Bamboo_Thicket.name=Mission: Bamboo Thicket +User_Mission_-_Bamboo_Thicket.desc="Death comes from above." + +User_Mission_-_That_Sinking_Feeling.name=Mission: That Sinking Feeling +User_Mission_-_That_Sinking_Feeling.desc="The water is rising rapidly and time is limited. Many have tried and failed. Can you save them all?" + +User_Mission_-_Newton_and_the_Hammock.name=Mission: Newton and the Hammock +User_Mission_-_Newton_and_the_Hammock.desc="Remember hoglets: The velocity of a body remains constant unless the body is acted upon by an external force!" + +User_Mission_-_The_Great_Escape.name=Mission: The Great Escape +User_Mission_-_The_Great_Escape.desc="You think you can cage me!?" + +User_Mission_-_Rope_Knock_Challenge.name=Challenge: Rope Knocking +User_Mission_-_Rope_Knock_Challenge.desc="Look behind you!" + +User_Mission_-_Nobody_Laugh.name=Mission: Nobody Laugh +User_Mission_-_Nobody_Laugh.desc="This ain't no joke." + +User_Mission_-_RCPlane_Challenge.name=Challenge: RC Plane +User_Mission_-_RCPlane_Challenge.desc="Feeling pretty confident, eh, flyboy?" + +portal.name=Mission: Portal Mind Challenge +portal.desc="Use the portal to move fast and far, use it to kill, use it with caution!" + +Target_Practice_-_Bazooka_easy.name=Target Practice: Bazooka (easy) +Target_Practice_-_Bazooka_easy.desc="Alright, soldier, blow those targets up as fast as you can!" + +Target_Practice_-_Bazooka_hard.name=Target Practice: Bazooka (hard) +Target_Practice_-_Bazooka_hard.desc="Can you hit the targets even when they are very far away?" + +Target_Practice_-_Cluster_Bomb.name=Target Practice: Cluster Bomb +Target_Practice_-_Cluster_Bomb.desc="Someone needs hot shower!" + +Target_Practice_-_Shotgun.name=Target Practice: Shotgun +Target_Practice_-_Shotgun.desc="Shoot first, ask questions later!" + +Target_Practice_-_Homing_Bee.name=Target Practice: Homing Bee +Target_Practice_-_Homing_Bee.desc="Using the homing bee is trickier than it seems." + +Target_Practice_-_Grenade_easy.name=Target Practice: Grenade (easy) +Target_Practice_-_Grenade_easy.desc="A warm-up training for the aspiring grenadier." + +Target_Practice_-_Grenade_hard.name=Target Practice: Grenade (hard) +Target_Practice_-_Grenade_hard.desc="This is nothing for greenhorns! We will place the targets at some really tricky positions." + +Challenge_-_Speed_Shoppa_-_Hedgelove.name=Challenge: Shoppa Love +Challenge_-_Speed_Shoppa_-_Hedgelove.desc="Show your love to rope and collect a few crates on a small map." + +Challenge_-_Speed_Shoppa_-_Ropes.name=Challenge: Ropes and Crates +Challenge_-_Speed_Shoppa_-_Ropes.desc="Take your rope and collect all crates on this medium-sized map." + +Challenge_-_Speed_Shoppa_-_ShoppaKing.name=Challenge: The Customer is King +Challenge_-_Speed_Shoppa_-_ShoppaKing.desc="Show you're worthy of a true king and collect all crates as fast as possible on this large map." \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/missions_it.txt --- a/share/hedgewars/Data/Locale/missions_it.txt Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/missions_it.txt Tue Nov 10 20:43:13 2015 +0100 @@ -43,5 +43,41 @@ User_Mission_-_Rope_Knock_Challenge.name=Sfida: a colpi di corda User_Mission_-_Rope_Knock_Challenge.desc="Guarda sempre dietro di te!" +User_Mission_-_Nobody_Laugh.name=Missione: Nessuno ride +User_Mission_-_Nobody_Laugh.desc="Questo non è un gioco." + User_Mission_-_RCPlane_Challenge.name=Sfida: aereo radiocomandato -User_Mission_-_RCPlane_Challenge.desc="Ti senti abbastanza sicuro, eh, aviatore?" \ No newline at end of file +User_Mission_-_RCPlane_Challenge.desc="Ti senti abbastanza sicuro, eh, aviatore?" + +portal.name=Missione: Sfida il portale della mente +portal.desc="Usa il portale per muoverti velocemente e lontano, usalo per uccidere, ma usalo con cauzione!" + +Target_Practice_-_Bazooka_easy.name=Tiro al Bersaglio: Bazooka (facile) +Target_Practice_-_Bazooka_easy.desc="Ok, soldati, fate saltare questi bersagli più in fretta che potete!" + +Target_Practice_-_Bazooka_hard.name=Tiro al Bersaglio: Bazooka (difficile) +Target_Practice_-_Bazooka_hard.desc="Puoi colpire i bersagli anche quando sono molto lontani?" + +Target_Practice_-_Cluster_Bomb.name=Tiro al Bersaglio: Bomba Cluster +Target_Practice_-_Cluster_Bomb.desc="A qualcuno serve una doccia calda!" + +Target_Practice_-_Shotgun.name=Tiro al Bersaglio: Shotgun +Target_Practice_-_Shotgun.desc="Prima spara, poi fai le domande!" + +Target_Practice_-_Homing_Bee.name=Tiro al Bersaglio: Ape a ricerca +Target_Practice_-_Homing_Bee.desc="Usare l'ape a ricerca è più complicato di quello che sembra." + +Target_Practice_-_Grenade_easy.name=Tiro al Bersagio: Granata (facile) +Target_Practice_-_Grenade_easy.desc="Un training di riscaldamento per aspiranti granatieri." + +Target_Practice_-_Grenade_hard.name=Tiro al Bersagio: Granata (difficile) +Target_Practice_-_Grenade_hard.desc="Questo non è per novellini! Piazzeremo i bersagli in posti veramente difficili." + +Challenge_-_Speed_Shoppa_-_Hedgelove.name=Sfida: Amo Shoppa +Challenge_-_Speed_Shoppa_-_Hedgelove.desc="Fai vedere il tuo amore e colleziona alcune casse in una mappa piccola." + +Challenge_-_Speed_Shoppa_-_Ropes.name=Sfida: Funi e Casse +Challenge_-_Speed_Shoppa_-_Ropes.desc="Prendi la tua fune e colleziona tutte le casse in questa mappa media." + +Challenge_-_Speed_Shoppa_-_ShoppaKing.name=Sfida: Il Cliente è il Re +Challenge_-_Speed_Shoppa_-_ShoppaKing.desc="Fai vedere che sei degno di un vero re e colleziona tutte le casse più in fretta che puoi in questa mappa grande." diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/missions_pt.txt --- a/share/hedgewars/Data/Locale/missions_pt.txt Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/missions_pt.txt Tue Nov 10 20:43:13 2015 +0100 @@ -1,50 +1,50 @@ -Basic_Training_-_Bazooka.name=Treino Básico com Bazuca -Basic_Training_-_Bazooka.desc="Saber utilizar o vento para tua vantagem é a chave!" - -Basic_Training_-_Grenade.name=Treino Básico com Granada -Basic_Training_-_Grenade.desc="Lembra-te, tens de retirar a cavilha E ATIRAR!" - -Basic_Training_-_Cluster_Bomb.name=Treino Básico com Bomba de Fragmentos -Basic_Training_-_Cluster_Bomb.desc="Alguem está a precisar de um duche bem quente!" - -Basic_Training_-_Shotgun.name=Treino Básico com Caçadeira -Basic_Training_-_Shotgun.desc="Dispara primeiro, questiona depois!" - -Basic_Training_-_Sniper_Rifle.name=Treino Básico com Sniper -Basic_Training_-_Sniper_Rifle.desc="Boom, headshot!" - -Basic_Training_-_Rope.name=Treino Básico com Corda -Basic_Training_-_Rope.desc="Get out there and swing!" - -User_Mission_-_Dangerous_Ducklings.name=Missão: Dangerous Ducklings -User_Mission_-_Dangerous_Ducklings.desc="Alright, rookie! Time to put what we learned in Basic Training into practice!" - -User_Mission_-_Diver.name=Missão: Diver -User_Mission_-_Diver.desc="Esta coisa do 'assalto anfíbio' é mais difícil do que parece..." - -User_Mission_-_Teamwork.name=Missão: Teamwork -User_Mission_-_Teamwork.desc="Por vezes, o amor doi." - -User_Mission_-_Spooky_Tree.name=Missão: Spooky Tree -User_Mission_-_Spooky_Tree.desc="Imensas caixas por todo o lado. Só espero que este pássaro não se esteja a sentir com fome." - -User_Mission_-_Bamboo_Thicket.name=Missão: Bamboo Thicket -User_Mission_-_Bamboo_Thicket.desc="Death comes from above." - -User_Mission_-_That_Sinking_Feeling.name=Missão: That Sinking Feeling -User_Mission_-_That_Sinking_Feeling.desc="A água está a subir rapidamente e o tempo é limitado. Muitos tentaram e falharam. Consegues salvá-los todos?" - -User_Mission_-_Newton_and_the_Hammock.name=Missão: Newton and the Hammock -User_Mission_-_Newton_and_the_Hammock.desc="Remember hoglets: The velocity of a body remains constant unless the body is acted upon by an external force!" - -User_Mission_-_The_Great_Escape.name=Missão: The Great Escape -User_Mission_-_The_Great_Escape.desc="Pensas que me consegues enjaular!?" - -User_Mission_-_Rope_Knock_Challenge.name=Desafio: Rope Knocking -User_Mission_-_Rope_Knock_Challenge.desc="Look behind you!" - -User_Mission_-_RCPlane_Challenge.name=Desafio: Avião Telecomandado -User_Mission_-_RCPlane_Challenge.desc="Feeling pretty confident, eh, flyboy?" - -portal.name=Missão: Treino com Portais -portal.desc="Use the portal to move fast and far, use it to kill, use it with caution!" +Basic_Training_-_Bazooka.name=Treino Básico com Bazuca +Basic_Training_-_Bazooka.desc="Saber utilizar o vento para tua vantagem é a chave!" + +Basic_Training_-_Grenade.name=Treino Básico com Granada +Basic_Training_-_Grenade.desc="Lembra-te, tens de retirar a cavilha E ATIRAR!" + +Basic_Training_-_Cluster_Bomb.name=Treino Básico com Bomba de Fragmentos +Basic_Training_-_Cluster_Bomb.desc="Alguem está a precisar de um duche bem quente!" + +Basic_Training_-_Shotgun.name=Treino Básico com Caçadeira +Basic_Training_-_Shotgun.desc="Dispara primeiro, questiona depois!" + +Basic_Training_-_Sniper_Rifle.name=Treino Básico com Sniper +Basic_Training_-_Sniper_Rifle.desc="Boom, headshot!" + +Basic_Training_-_Rope.name=Treino Básico com Corda +Basic_Training_-_Rope.desc="Get out there and swing!" + +User_Mission_-_Dangerous_Ducklings.name=Missão: Dangerous Ducklings +User_Mission_-_Dangerous_Ducklings.desc="Alright, rookie! Time to put what we learned in Basic Training into practice!" + +User_Mission_-_Diver.name=Missão: Diver +User_Mission_-_Diver.desc="Esta coisa do 'assalto anfíbio' é mais difícil do que parece..." + +User_Mission_-_Teamwork.name=Missão: Teamwork +User_Mission_-_Teamwork.desc="Por vezes, o amor doi." + +User_Mission_-_Spooky_Tree.name=Missão: Spooky Tree +User_Mission_-_Spooky_Tree.desc="Imensas caixas por todo o lado. Só espero que este pássaro não se esteja a sentir com fome." + +User_Mission_-_Bamboo_Thicket.name=Missão: Bamboo Thicket +User_Mission_-_Bamboo_Thicket.desc="Death comes from above." + +User_Mission_-_That_Sinking_Feeling.name=Missão: That Sinking Feeling +User_Mission_-_That_Sinking_Feeling.desc="A água está a subir rapidamente e o tempo é limitado. Muitos tentaram e falharam. Consegues salvá-los todos?" + +User_Mission_-_Newton_and_the_Hammock.name=Missão: Newton and the Hammock +User_Mission_-_Newton_and_the_Hammock.desc="Remember hoglets: The velocity of a body remains constant unless the body is acted upon by an external force!" + +User_Mission_-_The_Great_Escape.name=Missão: The Great Escape +User_Mission_-_The_Great_Escape.desc="Pensas que me consegues enjaular!?" + +User_Mission_-_Rope_Knock_Challenge.name=Desafio: Rope Knocking +User_Mission_-_Rope_Knock_Challenge.desc="Look behind you!" + +User_Mission_-_RCPlane_Challenge.name=Desafio: Avião Telecomandado +User_Mission_-_RCPlane_Challenge.desc="Feeling pretty confident, eh, flyboy?" + +portal.name=Missão: Treino com Portais +portal.desc="Use the portal to move fast and far, use it to kill, use it with caution!" diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/missions_pt_BR.txt --- a/share/hedgewars/Data/Locale/missions_pt_BR.txt Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/missions_pt_BR.txt Tue Nov 10 20:43:13 2015 +0100 @@ -1,53 +1,53 @@ -Basic_Training_-_Bazooka.name=Treino básico de bazuca -Basic_Training_-_Bazooka.desc="O segredo é usar o vento ao seu favor!" - -Basic_Training_-_Grenade.name=Treino básico de granada -Basic_Training_-_Grenade.desc="Lembre, você tira o pino E arremessa!" - -Basic_Training_-_Cluster_Bomb.name=Treino básico de bomba de estilhaço -Basic_Training_-_Cluster_Bomb.desc="Alguém está precisando de um banho quente!" - -Basic_Training_-_Shotgun.name=Treino básico de escopeta -Basic_Training_-_Shotgun.desc="Atire primeiro, pergunte depois!" - -Basic_Training_-_Sniper_Rifle.name=Treino básico de Rifle Sniper -Basic_Training_-_Sniper_Rifle.desc="Bum! Na cabeça!" - -Basic_Training_-_Rope.name=Treino básico de corda -Basic_Training_-_Rope.desc="Saia daí e balance!" - -User_Mission_-_Dangerous_Ducklings.name=Missão: Patinhos perigosos -User_Mission_-_Dangerous_Ducklings.desc="Certo, recruta! Hora de colocar em prática o que aprendeu nos Treinos Básicos!" - -User_Mission_-_Diver.name=Missão: Mergulhador -User_Mission_-_Diver.desc="Essa coisa de 'investida anfíbio' é mais difícil do que parece..." - -User_Mission_-_Teamwork.name=Missão: Trabalho em equipe -User_Mission_-_Teamwork.desc="Às vezes, o amor doi." - -User_Mission_-_Spooky_Tree.name=Missão: Árvore medonha -User_Mission_-_Spooky_Tree.desc="Muitas caixas por aqui. Só espero que aquele pássaro não esteja com fome." - -User_Mission_-_Bamboo_Thicket.name=Missão: Floresta de bambus -User_Mission_-_Bamboo_Thicket.desc="A morte vem de cima." - -User_Mission_-_That_Sinking_Feeling.name=Missão: Aquela sensação de afundar -User_Mission_-_That_Sinking_Feeling.desc="A água está subindo rapidamente e o tempo é contado. Muitos tentaram, muitos falharam. Consegue salvar todos?" - -User_Mission_-_Newton_and_the_Hammock.name=Missão: Newton e a rede -User_Mission_-_Newton_and_the_Hammock.desc="Lembrem-se, ouriçozinhos: A velocidade de um corpo permanece constante a menos que aja sobre ele uma força externa!" - -User_Mission_-_The_Great_Escape.name=Missão: A grande fuga -User_Mission_-_The_Great_Escape.desc="Está pensando que consegue me prender!?" - -User_Mission_-_Rope_Knock_Challenge.name=Challenge: Corda que doi -User_Mission_-_Rope_Knock_Challenge.desc="Atrás de você!" - -User_Mission_-_Nobody_Laugh.name=Missão: Ninguém ri -User_Mission_-_Nobody_Laugh.desc="Isso não é piada." - -User_Mission_-_RCPlane_Challenge.name=Desafio: Aeromodelo -User_Mission_-_RCPlane_Challenge.desc="Está bem confiante, né, aviador?" - -portal.name=Missão: Desafio dos portais -portal.desc="Use o portal para se mover rápido e para longe, use-o para matar, use-o com cuidado!" +Basic_Training_-_Bazooka.name=Treino básico de bazuca +Basic_Training_-_Bazooka.desc="O segredo é usar o vento ao seu favor!" + +Basic_Training_-_Grenade.name=Treino básico de granada +Basic_Training_-_Grenade.desc="Lembre, você tira o pino E arremessa!" + +Basic_Training_-_Cluster_Bomb.name=Treino básico de bomba de estilhaço +Basic_Training_-_Cluster_Bomb.desc="Alguém está precisando de um banho quente!" + +Basic_Training_-_Shotgun.name=Treino básico de escopeta +Basic_Training_-_Shotgun.desc="Atire primeiro, pergunte depois!" + +Basic_Training_-_Sniper_Rifle.name=Treino básico de Rifle Sniper +Basic_Training_-_Sniper_Rifle.desc="Bum! Na cabeça!" + +Basic_Training_-_Rope.name=Treino básico de corda +Basic_Training_-_Rope.desc="Saia daí e balance!" + +User_Mission_-_Dangerous_Ducklings.name=Missão: Patinhos perigosos +User_Mission_-_Dangerous_Ducklings.desc="Certo, recruta! Hora de colocar em prática o que aprendeu nos Treinos Básicos!" + +User_Mission_-_Diver.name=Missão: Mergulhador +User_Mission_-_Diver.desc="Essa coisa de 'investida anfíbio' é mais difícil do que parece..." + +User_Mission_-_Teamwork.name=Missão: Trabalho em equipe +User_Mission_-_Teamwork.desc="Às vezes, o amor doi." + +User_Mission_-_Spooky_Tree.name=Missão: Árvore medonha +User_Mission_-_Spooky_Tree.desc="Muitas caixas por aqui. Só espero que aquele pássaro não esteja com fome." + +User_Mission_-_Bamboo_Thicket.name=Missão: Floresta de bambus +User_Mission_-_Bamboo_Thicket.desc="A morte vem de cima." + +User_Mission_-_That_Sinking_Feeling.name=Missão: Aquela sensação de afundar +User_Mission_-_That_Sinking_Feeling.desc="A água está subindo rapidamente e o tempo é contado. Muitos tentaram, muitos falharam. Consegue salvar todos?" + +User_Mission_-_Newton_and_the_Hammock.name=Missão: Newton e a rede +User_Mission_-_Newton_and_the_Hammock.desc="Lembrem-se, ouriçozinhos: A velocidade de um corpo permanece constante a menos que aja sobre ele uma força externa!" + +User_Mission_-_The_Great_Escape.name=Missão: A grande fuga +User_Mission_-_The_Great_Escape.desc="Está pensando que consegue me prender!?" + +User_Mission_-_Rope_Knock_Challenge.name=Challenge: Corda que doi +User_Mission_-_Rope_Knock_Challenge.desc="Atrás de você!" + +User_Mission_-_Nobody_Laugh.name=Missão: Ninguém ri +User_Mission_-_Nobody_Laugh.desc="Isso não é piada." + +User_Mission_-_RCPlane_Challenge.name=Desafio: Aeromodelo +User_Mission_-_RCPlane_Challenge.desc="Está bem confiante, né, aviador?" + +portal.name=Missão: Desafio dos portais +portal.desc="Use o portal para se mover rápido e para longe, use-o para matar, use-o com cuidado!" diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/missions_ru.txt --- a/share/hedgewars/Data/Locale/missions_ru.txt Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/missions_ru.txt Tue Nov 10 20:43:13 2015 +0100 @@ -4,17 +4,23 @@ Basic_Training_-_Grenade.name=Базовое упражнение с гранатой Basic_Training_-_Grenade.desc="Запомни: выдерни чеку и бросай!" +Basic_Training_-_Cluster_Bomb.name=Базовое упражнение с касcетной бомбой +Basic_Training_-_Cluster_Bomb.desc="Кому-то нужен горячий душ!" + Basic_Training_-_Shotgun.name=Базовое упражнение с ружьём Basic_Training_-_Shotgun.desc="Стреляй, все вопросы потом!" Basic_Training_-_Sniper_Rifle.name=Базовое упражнение со снайперской винтовкой Basic_Training_-_Sniper_Rifle.desc="БАХ, в яблочко!" -User_Mission_-_Dangerous_Ducklings.name=Миссия: Dangerous Ducklings +Basic_Training_-_Rope.name=Базовое упражнение с верёвкой +Basic_Training_-_Rope.desc="Раскачивайся и цепляйся!" + +User_Mission_-_Dangerous_Ducklings.name=Миссия: Опасные Утята User_Mission_-_Dangerous_Ducklings.desc="Ну что, новобранцы! Пора на практике проверить, чему вы научились на базовых упражнениях!" User_Mission_-_Diver.name=Миссия: Ныряльщик -User_Mission_-_Diver.desc="This 'amphibious assault' thing is harder than it looks..." +User_Mission_-_Diver.desc="'Морской десант' это сложнее, чем кажется..." User_Mission_-_Teamwork.name=Миссия: Командная работа User_Mission_-_Teamwork.desc="Иногда любовь ранит." @@ -22,11 +28,56 @@ User_Mission_-_Spooky_Tree.name=Миссия: Зловещее дерево User_Mission_-_Spooky_Tree.desc="Здесь много ящиков. Конечно, я уверен, что эта птица не голодна." -User_Mission_-_Bamboo_Thicket.name=Миссия: Bamboo Thicket +User_Mission_-_Bamboo_Thicket.name=Миссия: Заросли Бамбука User_Mission_-_Bamboo_Thicket.desc="Смерть приходит сверху." -User_Mission_-_That_Sinking_Feeling.name=Миссия: That Sinking Feeling +User_Mission_-_That_Sinking_Feeling.name=Миссия: Дед Мазай и Ёжики User_Mission_-_That_Sinking_Feeling.desc="Вода быстро поднимается, а время ограничено. Многие пытались без успеха. Сможешь ли ты спасти всех?" User_Mission_-_Newton_and_the_Hammock.name=Миссия: Ньютон и гамак User_Mission_-_Newton_and_the_Hammock.desc="Ежата, запомните: Скорость тела остаётся постоянной, пока к нему не применяется внешняя сила!" + +User_Mission_-_The_Great_Escape.name=Миссия: Великий Побег +User_Mission_-_The_Great_Escape.desc="Вы думаете, клетка меня остановит!?" + +User_Mission_-_Rope_Knock_Challenge.name=Испытание: Толчок Верёвкой +User_Mission_-_Rope_Knock_Challenge.desc="Оглянись!" + +User_Mission_-_Nobody_Laugh.name=Миссия: Никто не смеётся +User_Mission_-_Nobody_Laugh.desc="Это не шутка ли." + +User_Mission_-_RCPlane_Challenge.name=Испытание: Радиоуправляемый самолёт +User_Mission_-_RCPlane_Challenge.desc="Чувствешь себя довольно уверенно, а, пилотишко?" + +portal.name=Миссия: Портальная головоломка +portal.desc="Используй портал для перемещения, используй его для убийства, используй его с осторожностью!" + +Target_Practice_-_Bazooka_easy.name=Учебная Стрельба: Базука (легко) +Target_Practice_-_Bazooka_easy.desc="Хорошо, солдат, взорви эти цели так быстро, как сможешь!" + +Target_Practice_-_Bazooka_hard.name=Учебная Стрельба: Базука (сложно) +Target_Practice_-_Bazooka_hard.desc="Сможешь ли ты попасть в цели даже если они далеко?" + +Target_Practice_-_Cluster_Bomb.name=Учебная Стрельба: Касcетная бомба +Target_Practice_-_Cluster_Bomb.desc="Кому-то нужен горячий душ!" + +Target_Practice_-_Shotgun.name=Учебная Стрельба: Дробовик +Target_Practice_-_Shotgun.desc="Сначала стреляй, потом спрашивай!" + +Target_Practice_-_Homing_Bee.name=Учебная Стрельба: Пчёлка +Target_Practice_-_Homing_Bee.desc="Использование пчёлки сложнее, чем может показаться на первый взгляд." + +Target_Practice_-_Grenade_easy.name=Учебная Стрельба: Граната (легко) +Target_Practice_-_Grenade_easy.desc="Разминочная тренировка для чистолюбивого гренадера." + +Target_Practice_-_Grenade_hard.name=Учебная Стрельба: Граната (сложно) +Target_Practice_-_Grenade_hard.desc="Это точно не для молокососов! Мы поместили цели в действительно труднодоступные места." + +Challenge_-_Speed_Shoppa_-_Hedgelove.name=Испытание: Shoppa Love +Challenge_-_Speed_Shoppa_-_Hedgelove.desc="Покажите вашу любовь к верёвке и соберите несколько ящиков на маленькой карте." + +Challenge_-_Speed_Shoppa_-_Ropes.name=Испытание: Верёвки и Ящики +Challenge_-_Speed_Shoppa_-_Ropes.desc="Возьмите вашу верёвку и соберите все ящики на этой средних размеров карте." + +Challenge_-_Speed_Shoppa_-_ShoppaKing.name=Испытание: Покупатель это Король +Challenge_-_Speed_Shoppa_-_ShoppaKing.desc="Докажите, что вы настоящий король и соберите все ящики на этой огромной карте так быстро, как сможете." \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/missions_tr.txt --- a/share/hedgewars/Data/Locale/missions_tr.txt Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/missions_tr.txt Tue Nov 10 20:43:13 2015 +0100 @@ -1,50 +1,50 @@ -Basic_Training_-_Bazooka.name=Temel Roketatar Eğitimi -Basic_Training_-_Bazooka.desc="Rüzgarı yararına kullanmak bir anahtar!" - -Basic_Training_-_Grenade.name=Temel Bomba Eğitimi -Basic_Training_-_Grenade.desc="Unutma, pimi çek VE at!" - -Basic_Training_-_Cluster_Bomb.name=Temel Parça Tesirli Bomba Eğitimi -Basic_Training_-_Cluster_Bomb.desc="Birinin sıcak duşa ihtiyacı var!" - -Basic_Training_-_Shotgun.name=Temel Tüfek Eğitimi -Basic_Training_-_Shotgun.desc="Önce atış yap, soruları sonra sor!" - -Basic_Training_-_Sniper_Rifle.name=Temel Keskin Nişancı Tüfeği Eğitimi -Basic_Training_-_Sniper_Rifle.desc="Bum, kafadan!" - -Basic_Training_-_Rope.name=Temel Halat Eğitimi -Basic_Training_-_Rope.desc="Ordan çık ve sallan!" - -User_Mission_-_Dangerous_Ducklings.name=Görev: Tehlikeli Ördek Yavruları -User_Mission_-_Dangerous_Ducklings.desc="Peki acemi! Şimdi Temel Eğitimde öğrendiklerini uygulamanın zamanı!" - -User_Mission_-_Diver.name=Görev: Dalıcı -User_Mission_-_Diver.desc="Bu 'iki yönlü saldırı' göründüğünden daha zor..." - -User_Mission_-_Teamwork.name=Görev: Takım Çalışması -User_Mission_-_Teamwork.desc="Bazen, aşk acıtır." - -User_Mission_-_Spooky_Tree.name=Görev: Korkak Ağaç -User_Mission_-_Spooky_Tree.desc="Burada çok fazla kasa var. Eminim bu kuş aç değildir." - -User_Mission_-_Bamboo_Thicket.name=Görev: Bambu Ormanı -User_Mission_-_Bamboo_Thicket.desc="Ölüm yukardan gelir." - -User_Mission_-_That_Sinking_Feeling.name=Görev: Batıyormuş Hissi -User_Mission_-_That_Sinking_Feeling.desc="Su hızlıca yükseliyor ve zaman kısıtlı. Çoğu denedi ve kaybetti. Hepsini kurtarabilecek misin?" - -User_Mission_-_Newton_and_the_Hammock.name=Görev: Newton ve Hamak -User_Mission_-_Newton_and_the_Hammock.desc="Kirpişleri unutma: Bir vücudun hızı harici bir kuvvetle itilmedikçe sabit kalır!" - -User_Mission_-_The_Great_Escape.name=Görev: Büyük Kaçış -User_Mission_-_The_Great_Escape.desc="Beni hapsedebileceğini mi sanıyorsun!?" - -User_Mission_-_Rope_Knock_Challenge.name=Mücadele: Halat Vuruşu -User_Mission_-_Rope_Knock_Challenge.desc="Arkana bak!" - -User_Mission_-_RCPlane_Challenge.name=Mücadele: RC Uçağı -User_Mission_-_RCPlane_Challenge.desc="Çok emin görünüyorsun değil mi, uçan çocuk?" - -portal.name= Görev: Portal eğitim görevi -portal.desc="Hızlı ve uzak yerlere hareket için portalı kullan, öldürmek için kullan, dikkatli kullan!" +Basic_Training_-_Bazooka.name=Temel Roketatar Eğitimi +Basic_Training_-_Bazooka.desc="Rüzgarı yararına kullanmak bir anahtar!" + +Basic_Training_-_Grenade.name=Temel Bomba Eğitimi +Basic_Training_-_Grenade.desc="Unutma, pimi çek VE at!" + +Basic_Training_-_Cluster_Bomb.name=Temel Parça Tesirli Bomba Eğitimi +Basic_Training_-_Cluster_Bomb.desc="Birinin sıcak duşa ihtiyacı var!" + +Basic_Training_-_Shotgun.name=Temel Tüfek Eğitimi +Basic_Training_-_Shotgun.desc="Önce atış yap, soruları sonra sor!" + +Basic_Training_-_Sniper_Rifle.name=Temel Keskin Nişancı Tüfeği Eğitimi +Basic_Training_-_Sniper_Rifle.desc="Bum, kafadan!" + +Basic_Training_-_Rope.name=Temel Halat Eğitimi +Basic_Training_-_Rope.desc="Ordan çık ve sallan!" + +User_Mission_-_Dangerous_Ducklings.name=Görev: Tehlikeli Ördek Yavruları +User_Mission_-_Dangerous_Ducklings.desc="Peki acemi! Şimdi Temel Eğitimde öğrendiklerini uygulamanın zamanı!" + +User_Mission_-_Diver.name=Görev: Dalıcı +User_Mission_-_Diver.desc="Bu 'iki yönlü saldırı' göründüğünden daha zor..." + +User_Mission_-_Teamwork.name=Görev: Takım Çalışması +User_Mission_-_Teamwork.desc="Bazen, aşk acıtır." + +User_Mission_-_Spooky_Tree.name=Görev: Korkak Ağaç +User_Mission_-_Spooky_Tree.desc="Burada çok fazla kasa var. Eminim bu kuş aç değildir." + +User_Mission_-_Bamboo_Thicket.name=Görev: Bambu Ormanı +User_Mission_-_Bamboo_Thicket.desc="Ölüm yukardan gelir." + +User_Mission_-_That_Sinking_Feeling.name=Görev: Batıyormuş Hissi +User_Mission_-_That_Sinking_Feeling.desc="Su hızlıca yükseliyor ve zaman kısıtlı. Çoğu denedi ve kaybetti. Hepsini kurtarabilecek misin?" + +User_Mission_-_Newton_and_the_Hammock.name=Görev: Newton ve Hamak +User_Mission_-_Newton_and_the_Hammock.desc="Kirpişleri unutma: Bir vücudun hızı harici bir kuvvetle itilmedikçe sabit kalır!" + +User_Mission_-_The_Great_Escape.name=Görev: Büyük Kaçış +User_Mission_-_The_Great_Escape.desc="Beni hapsedebileceğini mi sanıyorsun!?" + +User_Mission_-_Rope_Knock_Challenge.name=Mücadele: Halat Vuruşu +User_Mission_-_Rope_Knock_Challenge.desc="Arkana bak!" + +User_Mission_-_RCPlane_Challenge.name=Mücadele: RC Uçağı +User_Mission_-_RCPlane_Challenge.desc="Çok emin görünüyorsun değil mi, uçan çocuk?" + +portal.name= Görev: Portal eğitim görevi +portal.desc="Hızlı ve uzak yerlere hareket için portalı kullan, öldürmek için kullan, dikkatli kullan!" diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/missions_uk.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Locale/missions_uk.txt Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,53 @@ +Basic_Training_-_Bazooka.name=Базове тренування з Базукою +Basic_Training_-_Bazooka.desc="Слідкування за вітром є ключем до перемоги!" + +Basic_Training_-_Grenade.name=Базове тренування з Гранатою +Basic_Training_-_Grenade.desc="Пам'ятай, висмикуєш чеку І кидаєш!" + +Basic_Training_-_Cluster_Bomb.name=Базове тренування з Кластерною бомбою +Basic_Training_-_Cluster_Bomb.desc="Хтось потребує гарячий душ!" + +Basic_Training_-_Shotgun.name=Базове тренування з Рушницею +Basic_Training_-_Shotgun.desc="Спершу стріляй, потім питай!" + +Basic_Training_-_Sniper_Rifle.name=Базове тренування зі Снайперською гвинтівкою +Basic_Training_-_Sniper_Rifle.desc="Бах, точно в голову!" + +Basic_Training_-_Rope.name=Базове тренування з Мотузкою +Basic_Training_-_Rope.desc="Розхитуйтся і вилазь!" + +User_Mission_-_Dangerous_Ducklings.name=Місія: Небезпечні каченята +User_Mission_-_Dangerous_Ducklings.desc="Гаразд, новачок! Час застосувати отримані в Базових тренуваннях уміння на практиці!" + +User_Mission_-_Diver.name=Місія: Водолаз +User_Mission_-_Diver.desc="Ця 'десантна атака' є складнішою ніж здається..." + +User_Mission_-_Teamwork.name=Місія: Командна гра +User_Mission_-_Teamwork.desc="Інколи, любов підступна." + +User_Mission_-_Spooky_Tree.name=Місія: Моторошне дерево +User_Mission_-_Spooky_Tree.desc="Тут багато ящиків. Я сподіваюсь цей птах не зголодніє." + +User_Mission_-_Bamboo_Thicket.name=Місія: Бамбукові зарослі +User_Mission_-_Bamboo_Thicket.desc="Смерть приходить зверху." + +User_Mission_-_That_Sinking_Feeling.name=Місія: Це погане відчуття +User_Mission_-_That_Sinking_Feeling.desc="Вода піднімається і часу обмаль. Багато хто спробував і не зміг. Ти можеш їх врятувати?" + +User_Mission_-_Newton_and_the_Hammock.name=Місія: Ньютон і Гамак +User_Mission_-_Newton_and_the_Hammock.desc="Пам'ятайте: Швидкість тіла залишається постійною, якщо тіло не знаходиться під впливом зовнішньої сили!" + +User_Mission_-_The_Great_Escape.name=Місія: Велика втеча +User_Mission_-_The_Great_Escape.desc="Ти думаєш що можеш ув'язнити мене!?" + +User_Mission_-_Rope_Knock_Challenge.name=Виклик: Стук мотузки +User_Mission_-_Rope_Knock_Challenge.desc="Дивись позаду!" + +User_Mission_-_Nobody_Laugh.name=Місія: Ніхто не сміється +User_Mission_-_Nobody_Laugh.desc="Це не жарт." + +User_Mission_-_RCPlane_Challenge.name=Виклик: Радіо-керований літак +User_Mission_-_RCPlane_Challenge.desc="Почуваєшся впевнено, льотчик, га?" + +portal.name=Місія: Виклик Розумного порталу +portal.desc="Скористайся порталом щоб рухатись швидко і далеко, використовуй щоб вбивати, використовуй обережно!" diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/pl.lua --- a/share/hedgewars/Data/Locale/pl.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/pl.lua Tue Nov 10 20:43:13 2015 +0100 @@ -4,6 +4,10 @@ ["..."] = "...", -- ["011101000"] = "", -- A_Classic_Fairytale:dragon -- ["011101001"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:family, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united +-- ["+1 to a Bottom Feeder for killing anyone"] = "", -- Mutant +-- ["+1 to a Mutant for killing anyone"] = "", -- Mutant +-- ["-1 to anyone for a suicide"] = "", -- Mutant +-- ["+2 for becoming a Mutant"] = "", -- Mutant -- ["30 minutes later..."] = "", -- A_Classic_Fairytale:shadow -- ["About a month ago, a cyborg came and told us that you're the cannibals!"] = "", -- A_Classic_Fairytale:enemy ["Accuracy Bonus!"] = "Bonus za celność", @@ -13,17 +17,27 @@ -- ["???"] = "", -- A_Classic_Fairytale:backstab -- ["Actually, you aren't worthy of life! Take this..."] = "", -- A_Classic_Fairytale:shadow -- ["A cy-what?"] = "", -- A_Classic_Fairytale:enemy +-- ["Advanced Repositioning Mode"] = "", -- Construction_Mode -- ["Adventurous"] = "", -- A_Classic_Fairytale:journey +-- ["a frenetic Hedgewars mini-game"] = "", -- Frenzy -- ["Africa"] = "", -- Continental_supplies -- ["After Leaks A Lot betrayed his tribe, he joined the cannibals..."] = "", -- A_Classic_Fairytale:first_blood -- ["After the shock caused by the enemy spy, Leaks A Lot and Dense Cloud went hunting to relax."] = "", -- A_Classic_Fairytale:shadow -- ["Again with the 'cannibals' thing!"] = "", -- A_Classic_Fairytale:enemy +-- ["Aggressively removes enemy hedgehogs."] = "", -- Construction_Mode -- ["a Hedgewars challenge"] = "", -- User_Mission_-_RCPlane_Challenge, User_Mission_-_Rope_Knock_Challenge ["a Hedgewars mini-game"] = "Mini gra", -- Space_Invasion, The_Specialists +-- ["a Hedgewars tag game"] = "", -- Mutant +-- ["AHHh, home sweet home. Made it in %d seconds."] = "", -- ClimbHome ["Aiming Practice"] = "Potrenuj celność", +-- ["Air Attack"] = "", -- Construction_Mode -- ["A leap in a leap"] = "", -- A_Classic_Fairytale:first_blood -- ["A little gift from the cyborgs"] = "", -- A_Classic_Fairytale:shadow -- ["All gone...everything!"] = "", -- A_Classic_Fairytale:enemy +-- ["Allows free teleportation between other nodes."] = "", -- Construction_Mode +-- ["Allows placement of girders, rubber-bands, mines, sticky mines and barrels."] = "", -- Construction_Mode +-- ["Allows placement of structures."] = "", -- Construction_Mode +-- ["Allows the placement of weapons, utiliites, and health crates."] = "", -- Construction_Mode -- ["All right, we just need to get to the other side of the island!"] = "", -- A_Classic_Fairytale:journey -- ["All walls touched!"] = "", -- WxW ["Ammo"] = "Amunicja", @@ -38,8 +52,11 @@ -- ["And so they discovered that cyborgs weren't invulnerable..."] = "", -- A_Classic_Fairytale:journey -- ["And where's all the weed?"] = "", -- A_Classic_Fairytale:dragon -- ["And you believed me? Oh, god, that's cute!"] = "", -- A_Classic_Fairytale:journey --- ["Anno 1032: [The explosion will make a strong push ~ wide range, wont affect hogs close to the target]"] = "", -- Continental_supplies +-- ["Anno 1032: [The explosion will make a strong push ~ Wide range, wont affect hogs close to the target]"] = "", -- Continental_supplies + -- ["Antarctica"] = "", -- Continental_supplies +-- ["Antarctic summer: - Will give you one girder/mudball and two sineguns/portals every fourth turn."] = "", -- Continental_supplies +-- ["Area"] = "", -- Continental_supplies -- ["Are we there yet?"] = "", -- A_Classic_Fairytale:shadow -- ["Are you accusing me of something?"] = "", -- A_Classic_Fairytale:backstab -- ["Are you saying that many of us have died for your entertainment?"] = "", -- A_Classic_Fairytale:enemy @@ -59,27 +76,35 @@ -- ["[Backspace]"] = "", -- ["Backstab"] = "", -- A_Classic_Fairytale:backstab -- ["Bad Team"] = "", -- User_Mission_-_The_Great_Escape +-- ["Ballgun"] = "", -- Construction_Mode -- ["Bamboo Thicket"] = "", ["Barrel Eater!"] = "Pożeracz Beczek!", ["Barrel Launcher"] = "Wyrzutnia Beczek", +-- ["Barrel Placement Mode"] = "", -- Construction_Mode +-- ["Baseball Bat"] = "", -- Construction_Mode -- ["Baseballbat"] = "", -- Continental_supplies ["Bat balls at your enemies and|push them into the sea!"] = "Uderzaj piłkami w swoich przeciwników|i strącaj ich do wody!", ["Bat your opponents through the|baskets and out of the map!"] = "Uderzaj swoich przeciwników|wyrzucając przez kosz, poza mapę!", +-- ["Bazooka"] = "", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 ["Bazooka Training"] = "Trening bazooki", -- ["Beep Loopers"] = "", -- A_Classic_Fairytale:queen ["Best laps per team: "] = "Najszybsze okrążenie drużyny: ", ["Best Team Times: "] = "Najlepszy czas zespołów", -- ["Beware, though! If you are slow, you die!"] = "", -- A_Classic_Fairytale:dragon +-- ["Bio-Filter"] = "", -- Construction_Mode -- ["Biomechanic Team"] = "", -- A_Classic_Fairytale:family +-- ["Birdy"] = "", -- Construction_Mode -- ["Blender"] = "", -- A_Classic_Fairytale:family -- ["Bloodpie"] = "", -- A_Classic_Fairytale:backstab -- ["Bloodrocutor"] = "", -- A_Classic_Fairytale:shadow -- ["Bloodsucker"] = "", -- A_Classic_Fairytale:shadow ["Bloody Rookies"] = "Żółtodzioby", +-- ["Blowtorch"] = "", -- Construction_Mode, Frenzy +-- ["Blue Team"] = "", -- User_Mission_-_Dangerous_Ducklings -- ["Bone Jackson"] = "", -- A_Classic_Fairytale:backstab -- ["Bonely"] = "", -- A_Classic_Fairytale:shadow + ["BOOM!"] = "BUM!", ["Boom!"] = "BUM!", - ["BOOM!"] = "BUM!", ["Boss defeated!"] = "Boss pokonany!", ["Boss Slayer!"] = "Pogromca bossów", -- ["Brain Blower"] = "", -- A_Classic_Fairytale:journey @@ -89,6 +114,7 @@ -- ["Brain Teaser"] = "", -- A_Classic_Fairytale:backstab -- ["Brutal Lily"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil -- ["Brutus"] = "", -- A_Classic_Fairytale:backstab +-- ["Build a fortress and destroy your enemy."] = "", -- Construction_Mode ["Build a track and race."] = "Zbuduj trasę i ścigaj się.", -- ["Bullseye"] = "", -- A_Classic_Fairytale:dragon -- ["But it proved to be no easy task!"] = "", -- A_Classic_Fairytale:dragon @@ -99,6 +125,7 @@ -- ["But why would they help us?"] = "", -- A_Classic_Fairytale:backstab -- ["But you're cannibals. It's what you do."] = "", -- A_Classic_Fairytale:enemy -- ["But you said you'd let her go!"] = "", -- A_Classic_Fairytale:journey +-- ["Cake"] = "", -- Construction_Mode -- ["Call me Beep! Well, 'cause I'm such a nice...person!"] = "", -- A_Classic_Fairytale:family -- ["Cannibals"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:first_blood -- ["Cannibal Sentry"] = "", -- A_Classic_Fairytale:journey @@ -108,8 +135,15 @@ -- ["Carol"] = "", -- A_Classic_Fairytale:family -- ["CHALLENGE COMPLETE"] = "", -- User_Mission_-_RCPlane_Challenge ["Change Weapon"] = "Zmień broń", +-- ["changing range from %i%% to %i%% with period of %i msec"] = "", -- Gravity -- ["Choose your side! If you want to join the strange man, walk up to him.|Otherwise, walk away from him. If you decide to att...nevermind..."] = "", -- A_Classic_Fairytale:shadow +-- ["Cleaver"] = "", -- Construction_Mode +-- ["Cleaver Placement Mode"] = "", -- Construction_Mode +-- ["Climber"] = "", -- ClimbHome +-- ["Climb Home"] = "", -- ClimbHome +-- ["Clowns"] = "", -- User_Mission_-_Nobody_Laugh ["Clumsy"] = "Fajtłapa", +-- ["Cluster Bomb"] = "", -- Construction_Mode -- ["Cluster Bomb MASTER!"] = "", -- Basic_Training_-_Cluster_Bomb -- ["Cluster Bomb Training"] = "", -- Basic_Training_-_Cluster_Bomb ["Codename: Teamwork"] = "Kryptonim: Praca zespołowa", @@ -129,12 +163,19 @@ -- ["Congratulations! You needed only half of time|to eliminate all targets."] = "", -- Basic_Training_-_Cluster_Bomb -- ["Congratulations! You've completed the Rope tutorial! |- Tutorial ends in 10 seconds!"] = "", -- Basic_Training_-_Rope ["Congratulations! You've eliminated all targets|within the allowed time frame."] = "Gratulacje! Zniszczyłeś wszystkie cele przed upłynięciem czasu.", +-- ["CONSTRUCTION MODE"] = "", -- Construction_Mode +-- ["Construction Station"] = "", -- Construction_Mode -- ["Continental supplies"] = "", -- Continental_supplies ["Control pillars to score points."] = "Kontroluj filary by zdobyć punkty", +-- ["Core"] = "", -- Construction_Mode -- ["Corporationals"] = "", -- A_Classic_Fairytale:queen -- ["Corpsemonger"] = "", -- A_Classic_Fairytale:shadow -- ["Corpse Thrower"] = "", -- A_Classic_Fairytale:epil +-- ["Cost"] = "", -- Construction_Mode +-- ["Crate Placement Tool"] = "", -- Construction_Mode -- ["Crates Left:"] = "", -- User_Mission_-_RCPlane_Challenge +-- ["Cricket time: [Drop a fireable mine! ~ Will work if fired close to your hog & far away from enemy ~ 1 sec]"] = "", -- Continental_supplies +-- ["Current setting is "] = "", -- Gravity ["Cybernetic Empire"] = "Cybernetyczne Imperium", -- ["Cyborg. It's what the aliens call themselves."] = "", -- A_Classic_Fairytale:enemy -- ["Dahmer"] = "", -- A_Classic_Fairytale:backstab @@ -142,15 +183,19 @@ ["DAMMIT, ROOKIE!"] = "Żółtodziobie!", ["Dangerous Ducklings"] = "Niebezpieczne Kaczory", -- ["Deadweight"] = "", +-- ["Decrease"] = "", -- Continental_supplies -- ["Defeat the cannibals"] = "", -- A_Classic_Fairytale:backstab -- ["Defeat the cannibals!|"] = "", -- A_Classic_Fairytale:united -- ["Defeat the cannibals!|Grenade hint: set the timer with [1-5], aim with [Up]/[Down] and hold [Space] to set power"] = "", -- A_Classic_Fairytale:shadow -- ["Defeat the cyborgs!"] = "", -- A_Classic_Fairytale:enemy +-- ["Defend your core from the enemy."] = "", -- Construction_Mode -- ["Defend yourself!|Hint: You can get tips on using weapons by moving your mouse over them in the weapon selection menu"] = "", -- A_Classic_Fairytale:shadow +-- ["Dematerializes weapons and equipment carried by enemy hedgehogs."] = "", -- Construction_Mode ["Demolition is fun!"] = "Rozwałka jest fajna!", -- ["Dense Cloud"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united -- ["Dense Cloud must have already told them everything..."] = "", -- A_Classic_Fairytale:shadow -- ["Depleted Kamikaze!"] = "", +-- ["Desert Eagle"] = "", -- Construction_Mode, A_Space_Adventure:death02 -- ["Destroy him, Leaks A Lot! He is responsible for the deaths of many of us!"] = "", -- A_Classic_Fairytale:first_blood ["Destroy invaders to score points."] = "Zabijaj najeźdźców by zdobyć punkty.", -- ["Destroy the targets!|Hint: Select the Shoryuken and hit [Space]|P.S. You can use it mid-air."] = "", -- A_Classic_Fairytale:first_blood @@ -169,9 +214,12 @@ -- ["Do you have any idea how valuable grass is?"] = "", -- A_Classic_Fairytale:enemy -- ["Do you think you're some kind of god?"] = "", -- A_Classic_Fairytale:enemy -- ["Dragon's Lair"] = "", -- A_Classic_Fairytale:dragon +-- ["Drill Rocket"] = "", -- Construction_Mode -- ["Drills"] = "", -- A_Classic_Fairytale:backstab +-- ["Drill Strike"] = "", -- Construction_Mode ["Drone Hunter!"] = "Łowca dronów", --- ["Drop a bomb: [drop some heroic wind that will turn into a bomb on impact]"] = "", -- Continental_supplies +-- ["Drop a bomb: [Drop some heroic wind that will turn into a bomb on impact]"] = "", -- Continental_supplies + -- ["Drowner"] = "", -- ["Dude, all the plants are gone!"] = "", -- A_Classic_Fairytale:family -- ["Dude, can you see Ramon and Spiky?"] = "", -- A_Classic_Fairytale:journey @@ -181,11 +229,15 @@ -- ["Dude, where are we?"] = "", -- A_Classic_Fairytale:backstab -- ["Dude, wow! I just had the weirdest high!"] = "", -- A_Classic_Fairytale:backstab -- ["Duration"] = "", -- Continental_supplies --- ["Dust storm: [Deals 20 damage to all enemies in the circle]"] = "", -- Continental_supplies +-- ["Dust storm: [Deals 15 damage to all enemies in the circle]"] = "", -- Continental_supplies + +-- ["Dynamite"] = "", -- Construction_Mode +-- ["Each turn is only ONE SECOND!"] = "", -- Frenzy ["Each turn you get 1-3 random weapons"] = "Z każdą turą dostaniesz 1-3 bronie", ["Each turn you get one random weapon"] = "Z każdą turą dostaniesz losową broń", -- ["Eagle Eye"] = "", -- A_Classic_Fairytale:backstab --- ["Eagle Eye: [Blink to the impact ~ one shot]"] = "", -- Continental_supplies +-- ["Eagle Eye: [Blink to the impact ~ One shot]"] = "", -- Continental_supplies + -- ["Ear Sniffer"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:epil -- ["Elderbot"] = "", -- A_Classic_Fairytale:family -- ["Elimate your captor."] = "", -- User_Mission_-_The_Great_Escape @@ -208,8 +260,9 @@ -- ["Every single time!"] = "", -- A_Classic_Fairytale:dragon -- ["Everything looks OK..."] = "", -- A_Classic_Fairytale:enemy -- ["Exactly, man! That was my dream."] = "", -- A_Classic_Fairytale:backstab +-- ["Extra Damage"] = "", -- Construction_Mode +-- ["Extra Time"] = "", -- Construction_Mode -- ["Eye Chewer"] = "", -- A_Classic_Fairytale:journey --- ["INSANITY"] = "", -- Mutant -- ["Family Reunion"] = "", -- A_Classic_Fairytale:family ["Fastest lap: "] = "Najszybsze okrążenie: ", ["Feeble Resistance"] = "Ruch Oporu", @@ -219,9 +272,10 @@ -- ["Femur Lover"] = "", -- A_Classic_Fairytale:shadow -- ["Fierce Competition!"] = "", -- Space_Invasion -- ["Fiery Water"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united +-- ["Filthy Blue"] = "", -- User_Mission_-_Dangerous_Ducklings -- ["Find your tribe!|Cross the lake!"] = "", -- A_Classic_Fairytale:dragon -- ["Finish your training|Hint: Animations can be skipped with the [Precise] key."] = "", -- A_Classic_Fairytale:first_blood --- ["Fire a mine: [Does what it says ~ Cant be dropped close to an enemy ~ 1 sec]"] = "", -- Continental_supplies + ["Fire"] = "Ogień", -- ["First aid kits?!"] = "", -- A_Classic_Fairytale:united -- ["First Blood"] = "", -- A_Classic_Fairytale:first_blood @@ -232,11 +286,15 @@ ["Flag returned!"] = "Flaga odzyskana!", ["Flags, and their home base will be placed where each team ends their first turn."] = "Flagi i baza zostaną umieszczone tam gdzie zespół zakończy swą pierwszą turę.", -- ["Flamer"] = "", +-- ["Flamethrower"] = "", -- Construction_Mode -- ["Flaming Worm"] = "", -- A_Classic_Fairytale:backstab --- ["Flare: [fire up some bombs depending on hogs depending on hogs in the circle"] = "", -- Continental_supplies + -- ["Flesh for Brainz"] = "", -- A_Classic_Fairytale:journey +-- ["Flying Saucer"] = "", -- Construction_Mode, Frenzy -- ["For improved features/stability, play 0.9.18+"] = "", -- WxW -- ["Free Dense Cloud and continue the mission!"] = "", -- A_Classic_Fairytale:journey +-- ["Freezer"] = "", -- Construction_Mode +-- ["FRENZY"] = "", -- Frenzy -- ["Friendly Fire!"] = "", ["fuel extended!"] = "zdobyto paliwo", ["GAME BEGUN!!!"] = "GRA ROZPOCZĘTA!!!", @@ -246,6 +304,9 @@ -- ["Game? Was this a game to you?!"] = "", -- A_Classic_Fairytale:enemy -- ["GasBomb"] = "", -- Continental_supplies -- ["Gas Gargler"] = "", -- A_Classic_Fairytale:queen +-- ["General information"] = "", -- Continental_supplies +-- ["Generates power."] = "", -- Construction_Mode +-- ["Generator"] = "", -- Construction_Mode -- ["Get Dense Cloud out of the pit!"] = "", -- A_Classic_Fairytale:journey ["Get on over there and take him out!"] = "Dostań się tam i go wykończ!", -- ["Get on the head of the mole"] = "", -- A_Classic_Fairytale:first_blood @@ -256,6 +317,8 @@ -- ["Get your teammates out of their natural prison and save the princess!|Hint: Drilling holes should solve everything.|Hint: It might be a good idea to place a girder before starting to drill. Just saying.|Hint: All your hedgehogs need to be above the marked height!|Hint: Leaks A Lot needs to get really close to the princess!"] = "", -- A_Classic_Fairytale:family -- ["GG!"] = "", -- User_Mission_-_Rope_Knock_Challenge -- ["Gimme Bones"] = "", -- A_Classic_Fairytale:backstab +-- ["Girder"] = "", -- Construction_Mode +-- ["Girder Placement Mode"] = "", -- Construction_Mode -- ["Glark"] = "", -- A_Classic_Fairytale:shadow ["Goal"] = "Gol", ["GO! GO! GO!"] = "RUCHY! RUCHY! RUCHY!", @@ -272,12 +335,16 @@ -- ["Go surf!"] = "", -- WxW ["GOTCHA!"] = "MAM CIĘ!", ["Grab Mines/Explosives"] = "Chwyć miny/beczki", +-- ["Grants nearby hogs life-regeneration."] = "", -- Construction_Mode +-- ["Gravity"] = "", -- Gravity -- ["Great choice, Steve! Mind if I call you that?"] = "", -- A_Classic_Fairytale:shadow -- ["Great work! Now hit it with your Baseball Bat! |Tip: You can change weapon with 'Right Click'!"] = "", -- Basic_Training_-_Rope -- ["Great! You will be contacted soon for assistance."] = "", -- A_Classic_Fairytale:shadow --- ["Green lipstick bullet: [Is poisonous]"] = "", -- Continental_supplies + +-- ["Green lipstick bullet: [Poisonous, deals no damage]"] = "", -- Continental_supplies -- ["Greetings, "] = "", -- A_Classic_Fairytale:dragon -- ["Greetings, cloudy one!"] = "", -- A_Classic_Fairytale:shadow +-- ["Grenade"] = "", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 -- ["Grenade Training"] = "", -- Basic_Training_-_Grenade -- ["Grenadiers"] = "", -- Basic_Training_-_Grenade -- ["Guys, do you think there's more of them?"] = "", -- A_Classic_Fairytale:backstab @@ -285,23 +352,27 @@ -- ["Haha!"] = "", -- A_Classic_Fairytale:united ["Hahahaha!"] = "Hahahaha!", ["Haha, now THAT would be something!"] = "Haha, to było by COŚ", +-- ["Hammer"] = "", -- Construction_Mode, Continental_supplies -- ["Hannibal"] = "", -- A_Classic_Fairytale:epil [" Hapless Hogs left!"] = " Nieszczęsne Jeże pozostały", ["Hapless Hogs"] = "Nieszczęsne Jeże", - -- [" HAS MUTATED"] = "", -- Mutant -- ["Hatless Jerry"] = "", -- A_Classic_Fairytale:queen -- ["Have no illusions, your tribe is dead, indifferent of your choice."] = "", -- A_Classic_Fairytale:shadow -- ["Have we ever attacked you first?"] = "", -- A_Classic_Fairytale:enemy +-- ["Healing Station"] = "", -- Construction_Mode +-- ["Health Crate Placement Mode"] = "", -- Construction_Mode ["Health crates extend your time."] = "Apteczki dodają czas.", -- ["Heavy"] = "", -- ["Heavy Cannfantry"] = "", -- A_Classic_Fairytale:united -- ["Hedge-cogs"] = "", -- A_Classic_Fairytale:enemy --- ["Hedgehog projectile: [fire your hog like a Sticky Bomb]"] = "", -- Continental_supplies +-- ["Hedgehog projectile: [Fire your hog like a Sticky Bomb]"] = "", -- Continental_supplies + ["Hedgewars-Basketball"] = "Hedgewars-Koszykówka", ["Hedgewars-Knockball"] = "Hedgewars-Knockball", -- ["Hedgibal Lecter"] = "", -- A_Classic_Fairytale:backstab ["Heh, it's not that bad."] = "Heh, nie jest aż tak źle.", +-- ["Hellish Handgrenade"] = "", -- Construction_Mode -- ["Hello again, "] = "", -- A_Classic_Fairytale:family -- ["Help me, Leaks!"] = "", -- A_Classic_Fairytale:journey -- ["Help me, please!!!"] = "", -- A_Classic_Fairytale:journey @@ -333,6 +404,7 @@ -- ["Hogminator"] = "", -- A_Classic_Fairytale:family -- ["Hogs in sight!"] = "", -- Continental_supplies -- ["HOLY SHYTE!"] = "", -- Mutant +-- ["Homing Bee"] = "", -- Construction_Mode -- ["Honest Lee"] = "", -- A_Classic_Fairytale:enemy ["Hooray!"] = "Hurraaa!", -- ["Hostage Situation"] = "", -- A_Classic_Fairytale:family @@ -366,7 +438,6 @@ -- ["If you get stuck, use your Desert Eagle or restart the mission!|"] = "", -- A_Classic_Fairytale:journey -- ["If you know what I mean..."] = "", -- A_Classic_Fairytale:shadow -- ["If you say so..."] = "", -- A_Classic_Fairytale:shadow - -- ["I guess you'll have to kill them."] = "", -- A_Classic_Fairytale:dragon -- ["I have come to make you an offering..."] = "", -- A_Classic_Fairytale:shadow -- ["I have no idea where that mole disappeared...Can you see it?"] = "", -- A_Classic_Fairytale:shadow @@ -389,6 +460,7 @@ -- ["I'm not sure about that!"] = "", -- A_Classic_Fairytale:united -- ["Impressive...you are still dry as the corpse of a hawk after a week in the desert..."] = "", -- A_Classic_Fairytale:first_blood -- ["I'm so scared!"] = "", -- A_Classic_Fairytale:united +-- ["Increase"] = "", -- Continental_supplies -- ["Incredible..."] = "", -- A_Classic_Fairytale:shadow -- ["I need to find the others!"] = "", -- A_Classic_Fairytale:backstab -- ["I need to get to the other side of this island, fast!"] = "", -- A_Classic_Fairytale:journey @@ -397,12 +469,14 @@ -- ["I need to warn the others."] = "", -- A_Classic_Fairytale:backstab -- ["In fact, you are the only one that's been acting strangely."] = "", -- A_Classic_Fairytale:backstab -- ["In order to get to the other side, you need to collect the crates first.|"] = "", -- A_Classic_Fairytale:dragon +-- ["INSANITY"] = "", -- Mutant ["Instructor"] = "Instruktor", -- ["Interesting idea, haha!"] = "", -- A_Classic_Fairytale:enemy -- ["Interesting! Last time you said you killed a cannibal!"] = "", -- A_Classic_Fairytale:backstab -- ["In the meantime, take these and return to your \"friend\"!"] = "", -- A_Classic_Fairytale:shadow ["invaders destroyed"] = "najeźdźców zniszczonych", -- ["Invasion"] = "", -- A_Classic_Fairytale:united +-- ["Invulnerable"] = "", -- Construction_Mode -- ["I saw it with my own eyes!"] = "", -- A_Classic_Fairytale:shadow -- ["I see..."] = "", -- A_Classic_Fairytale:shadow -- ["I see you have already taken the leap of faith."] = "", -- A_Classic_Fairytale:first_blood @@ -445,6 +519,7 @@ -- ["Just kidding, none of you have died!"] = "", -- A_Classic_Fairytale:enemy -- ["Just on a walk."] = "", -- A_Classic_Fairytale:united -- ["Just wait till I get my hands on that trauma! ARGH!"] = "", -- A_Classic_Fairytale:family +-- ["Kamikaze"] = "", -- Construction_Mode -- ["Kamikaze Expert!"] = "", ["Keep it up!"] = "Tak trzymaj!", -- ["Kerguelen"] = "", -- Continental_supplies @@ -454,6 +529,8 @@ -- ["Kill the aliens!"] = "", -- A_Classic_Fairytale:dragon -- ["Kill the cannibal!"] = "", -- A_Classic_Fairytale:first_blood -- ["Kill the traitor...or spare his life!|Kill him or press [Precise]!"] = "", -- A_Classic_Fairytale:backstab +-- ["Land Sprayer"] = "", -- Construction_Mode +-- ["Laser Sight"] = "", -- Construction_Mode ["Last Target!"] = "Ostatni cel!", -- ["Leader"] = "", -- A_Classic_Fairytale:enemy -- ["Leaderbot"] = "", -- A_Classic_Fairytale:queen @@ -463,6 +540,7 @@ -- ["Leaks A Lot must survive!"] = "", -- A_Classic_Fairytale:journey -- ["Led Heart"] = "", -- A_Classic_Fairytale:queen -- ["Lee"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen +-- ["left shift"] = "", -- Continental_supplies ["[Left Shift]"] = "[Lewy Shift]", -- ["Let a Continent provide your weapons!"] = "", -- Continental_supplies -- ["Let me test your skills a little, will you?"] = "", -- A_Classic_Fairytale:journey @@ -473,41 +551,56 @@ -- ["Let them have a taste of my fury!"] = "", -- A_Classic_Fairytale:backstab -- ["Let us help, too!"] = "", -- A_Classic_Fairytale:backstab -- ["Light Cannfantry"] = "", -- A_Classic_Fairytale:united +-- ["Limburger"] = "", -- Construction_Mode ["Listen up, maggot!!"] = "Słuchaj mnie, gnido!", -- ["Little did they know that this hunt will mark them forever..."] = "", -- A_Classic_Fairytale:shadow ["Lively Lifeguard"] = "Ratownik!", --- ["Lonely Cries: [Rise the water if no hog is in the circle and deal 1 damage to all hogs]"] = "", -- Continental_supplies + +-- ["Lonely Cries: [Rise the water if no hog is in the circle and deal 7 damage to all enemy hogs]"] = "", -- Continental_supplies +-- ["Lonely Hog"] = "", -- ClimbHome -- ["Look, I had no choice!"] = "", -- A_Classic_Fairytale:backstab -- ["Look out! There's more of them!"] = "", -- A_Classic_Fairytale:backstab -- ["Look out! We're surrounded by cannibals!"] = "", -- A_Classic_Fairytale:enemy -- ["Looks like the whole world is falling apart!"] = "", -- A_Classic_Fairytale:enemy +-- ["Low Gravity"] = "", -- Construction_Mode, Frenzy -- ["Luckily, I've managed to snatch some of them."] = "", -- A_Classic_Fairytale:united -- ["LUDICROUS KILL"] = "", -- Mutant +-- ["Made it!"] = "", -- ClimbHome +-- ["- Massive weapon bonus on first turn"] = "", -- Continental_supplies -- ["May the spirits aid you in all your quests!"] = "", -- A_Classic_Fairytale:backstab -- ["Medicine: [Fire some exploding medicine that will heal all hogs effected by the explosion]"] = "", -- Continental_supplies -- ["MEGA KILL"] = "", -- Mutant -- ["Meiwes"] = "", -- A_Classic_Fairytale:backstab -- ["Mindy"] = "", -- A_Classic_Fairytale:united +-- ["Mine"] = "", -- Construction_Mode, Frenzy -- ["Mine Deployer"] = "", ["Mine Eater!"] = "Pożeracz min!", +-- ["Mine Placement Mode"] = "", -- Construction_Mode ["|- Mines Time:"] = "|- Czas detonacji min:", +-- ["Mine Strike"] = "", -- Construction_Mode ["MISSION FAILED"] = "MISJA ZAKOŃCZONA NIEPOWODZENIEM", ["MISSION SUCCESSFUL"] = "MISJA POWIODŁA SIĘ", ["MISSION SUCCESS"] = "MISJA ZAKOŃCZONA SUKCESEM", +-- ["Molotov Cocktail"] = "", -- Construction_Mode -- ["Molotov"] = "", -- Continental_supplies -- ["MONSTER KILL"] = "", -- Mutant -- ["More Natives"] = "", -- A_Classic_Fairytale:epil +-- ["Mortar"] = "", -- Construction_Mode, A_Space_Adventure:death02 ["Movement: [Up], [Down], [Left], [Right]"] = "Poruszanie się: [Góra], [Dół], [Lewo], [Prawo]", +-- ["Mudball"] = "", -- Construction_Mode ["Multi-shot!"] = "Wielokrotny strzał", -- ["Muriel"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen -- ["Muscle Dissolver"] = "", -- A_Classic_Fairytale:shadow -- ["-------"] = "", -- Mutant +-- ["Mutant"] = "", -- Mutant -- ["Nade Boy"] = "", -- Basic_Training_-_Grenade -- ["Name"] = "", -- A_Classic_Fairytale:queen ["Nameless Heroes"] = "Bezimienni Bohaterowie", -- ["Nancy Screw"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:queen +-- ["Napalm"] = "", -- Construction_Mode -- ["Napalm rocket: [Fire a bomb with napalm!]"] = "", -- Continental_supplies -- ["Natives"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:first_blood, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united +-- ["Naughty Ninja"] = "", -- User_Mission_-_Dangerous_Ducklings ["New Barrels Per Turn"] = "Ilość beczek dodanych co turę", ["NEW CLAN RECORD: "] = "NOWY REKORD ZESPOŁU: ", ["NEW fastest lap: "] = "NOWE najszybsze okrążenie: ", @@ -518,6 +611,7 @@ -- ["Nice work, "] = "", -- A_Classic_Fairytale:dragon -- ["Nice work!"] = "", -- A_Classic_Fairytale:enemy -- ["Nilarian"] = "", -- A_Classic_Fairytale:queen +-- ["Nobody Laugh"] = "", -- User_Mission_-_Nobody_Laugh -- ["No, I came back to help you out..."] = "", -- A_Classic_Fairytale:shadow -- ["No...I wonder where they disappeared?!"] = "", -- A_Classic_Fairytale:journey -- ["Nom-Nom"] = "", -- A_Classic_Fairytale:journey @@ -525,6 +619,7 @@ -- ["Nope. It was one fast mole, that's for sure."] = "", -- A_Classic_Fairytale:shadow -- ["No! Please, help me!"] = "", -- A_Classic_Fairytale:journey -- ["NORMAL"] = "", -- Continental_supplies +-- ["Normal players can only score points by killing the mutant."] = "", -- Mutant -- ["North America"] = "", -- Continental_supplies ["Not all hogs are born equal."] = "Nie wszystkie jeże rodzą się równe.", -- Highlander ["NOT ENOUGH WAYPOINTS"] = "ZA MAŁO PUNKTÓW KONTROLNYCH", @@ -537,6 +632,7 @@ -- ["No. Where did he come from?"] = "", -- A_Classic_Fairytale:shadow -- ["Now how do I get on the other side?!"] = "", -- A_Classic_Fairytale:dragon -- ["No. You and the rest of the tribe are safer there!"] = "", -- A_Classic_Fairytale:backstab +-- ["Object Placement Tool"] = "", -- Construction_Mode -- ["Obliterate them!|Hint: You might want to take cover..."] = "", -- A_Classic_Fairytale:shadow -- ["Obstacle course"] = "", -- A_Classic_Fairytale:dragon -- ["Of course I have to save her. What did I expect?!"] = "", -- A_Classic_Fairytale:family @@ -553,24 +649,30 @@ -- ["Once upon a time, on an island with great natural resources, lived two tribes in heated conflict..."] = "", -- A_Classic_Fairytale:first_blood -- ["ONE HOG PER TEAM! KILLING EXCESS HEDGES"] = "", -- Mutant -- ["One tribe was peaceful, spending their time hunting and training, enjoying the small pleasures of life..."] = "", -- A_Classic_Fairytale:first_blood +-- ["on Skip"] = "", -- Continental_supplies -- ["Oops...I dropped them."] = "", -- A_Classic_Fairytale:united -- ["Open that crate and we will continue!"] = "", -- A_Classic_Fairytale:first_blood ["Operation Diver"] = "Operacja Nurek", ["Opposing Team: "] = "Przeciwna drużyna", +-- ["or 'g=50, g2=150, period=4000' for gravity changing|from 50 to 150 and back with period of 4000 msec"] = "", -- Gravity -- ["Orlando Boom!"] = "", -- A_Classic_Fairytale:queen +-- ["Other kills don't give you points."] = "", -- Mutant -- ["Ouch!"] = "", -- User_Mission_-_Rope_Knock_Challenge -- ["Our tribe, our beautiful island!"] = "", -- A_Classic_Fairytale:enemy -- ["Parachute"] = "", -- Continental_supplies ["Pathetic Hog #%d"] = "Żałosny Jeż #%d", -- ["Pathetic Resistance"] = "", -- User_Mission_-_Bamboo_Thicket, User_Mission_-_Newton_and_the_Hammock +-- ["Penguin roar: [Deal 15 damage + 15% of your hogs health to all hogs around you and get 2/3 back]"] = "", -- Continental_supplies -- ["Perfect! Now try to get the next crate without hurting yourself!"] = "", -- A_Classic_Fairytale:first_blood ["Per-Hog Ammo"] = "Oddzielna amunicja dla jeży", --- ["- Per team weapons|- 9 weaponschemes|- Unique new weapons| |Select continent first round with the Weapon Menu or by ([switch/tab]=Increase,[precise/left shift]=Decrease) on Skip|Some weapons have a second option. Find them with [switch/tab]"] = "", -- Continental_supplies +-- ["Personal Portal Device"] = "", -- Construction_Mode +-- ["Per team weapons"] = "", -- Continental_supplies -- ["Pfew! That was close!"] = "", -- A_Classic_Fairytale:shadow --- ["Piñata bullet: [Contains some sweet candy!]"] = "", -- Continental_supplies +-- ["Piano Strike"] = "", -- Construction_Mode +-- ["Pickhammer"] = "", -- Construction_Mode + -- ["Pings left:"] = "", -- Space_Invasion - ["Place more waypoints using the 'Air Attack' weapon."] = "Postaw więcej punktów orientacyjnych używając [Nalotu]", -- ["Planes Used:"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Planes Used"] = "", -- User_Mission_-_RCPlane_Challenge @@ -579,15 +681,19 @@ -- ["Please place the way-point in the open, within the map boundaries."] = "", -- Racer -- ["Please, stop releasing your \"smoke signals\"!"] = "", -- A_Classic_Fairytale:shadow -- ["Point Blank Combo!"] = "", -- Space_Invasion +-- ["POINTS"] = "", -- Mutant ["points"] = "punkty", -- Control, CTF_Blizzard, Basic_Training_-_Bazooka, Basic_Training_-_Shotgun, Basic_Training_-_Sniper_Rifle ["Poison"] = "Truciciel", +-- ["Population"] = "", -- Continental_supplies -- ["Portal hint: one goes to the destination, and one is the entrance.|"] = "", -- A_Classic_Fairytale:dragon -- ["Portal mission"] = "", -- portal ["Power Remaining"] = "pkt. energii pozostało", ["Prepare yourself"] = "Przygotuj się", +-- ["presice"] = "", -- Continental_supplies -- ["Press [Enter] to accept this configuration."] = "", -- WxW -- ["Press [Left] or [Right] to move around, [Enter] to jump"] = "", -- A_Classic_Fairytale:first_blood ["Press [Precise] to skip intro"] = "Naciśnij [Precyzyjne celowanie] by pominąć intro", +-- ["Prestigious Pilot"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Private Novak"] = "", -- Basic_Training_-_Cluster_Bomb -- ["Protect yourselves!|Grenade hint: set the timer with [1-5], aim with [Up]/[Down] and hold [Space] to set power"] = "", -- A_Classic_Fairytale:shadow ["Race complexity limit reached."] = "Osiągnięto limit złożoności trasy.", @@ -596,25 +702,39 @@ -- ["Radar Ping"] = "", -- Space_Invasion -- ["Raging Buffalo"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united -- ["Ramon"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow +-- ["random in range from %i%% to %i%% with period of %i msec"] = "", -- Gravity +-- ["RC Plane"] = "", -- Construction_Mode -- ["RC PLANE TRAINING"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Really?! You thought you could harm me with your little toys?"] = "", -- A_Classic_Fairytale:shadow +-- ["Reflector Shield"] = "", -- Construction_Mode +-- ["Reflects enemy projectiles."] = "", -- Construction_Mode -- ["Regurgitator"] = "", -- A_Classic_Fairytale:backstab -- ["Reinforcements"] = "", -- A_Classic_Fairytale:backstab -- ["Remember: The rope only bend around objects, |if it doesn't hit anything it's always stright!"] = "", -- Basic_Training_-_Rope -- ["Remember this, pathetic animal: when the day comes, you will regret your blind loyalty!"] = "", -- A_Classic_Fairytale:shadow +-- ["REMOVED"] = "", -- Continental_supplies +-- ["Respawner"] = "", -- Construction_Mode +-- ["Resurrector"] = "", -- Construction_Mode +-- ["Resurrects dead hedgehogs."] = "", -- Construction_Mode [" - Return the enemy flag to your base to score | - First team to 3 captures wins | - You may only score when your flag is in your base | - Hogs will drop the flag if killed, or drowned | - Dropped flags may be returned or recaptured | - Hogs respawn when killed"] = " - Przynieś flagę wroga do swojej bazy by zdobyć punkt | - Pierwszy kto zrobi to 3 razy, wygrywa | - Punkt zdobywasz tylko gdy twoja flaga znajduje się w bazie | - Jeże upuszczą flagę gdy zostaną zabite bądź utopione | - Upuszczona flaga może być przywrócona lub przechwycona ponownie | - Jeże odradzają się po śmierci", -- ["Return to Leaks A Lot! If you get stuck, press [Precise] to try again!"] = "", -- A_Classic_Fairytale:shadow -- ["Righteous Beard"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:first_blood, A_Classic_Fairytale:queen, A_Classic_Fairytale:united +-- ["Rope"] = "", -- Construction_Mode -- ["ROPE-KNOCKING"] = "", -- User_Mission_-_Rope_Knock_Challenge +-- ["Rope to safety"] = "", -- ClimbHome -- ["Rope Training"] = "", -- Basic_Training_-_Rope -- ["Rot Molester"] = "", -- A_Classic_Fairytale:shadow ["Round Limit:"] = "Ilość rund:", ["Round Limit"] = "Ilość rund", ["Rounds Complete"] = "Koniec", ["Rounds Complete: "] = "Ukończono rund: ", +-- ["Rubber Band"] = "", -- Construction_Mode +-- ["Rubber Placement Mode"] = "", -- Construction_Mode +-- ["RULES"] = "", -- Frenzy, Mutant ["RULES OF THE GAME [Press ESC to view]"] = "ZASADY GRY [Naciśnij ESC by zobaczyć]", -- ["Rusty Joe"] = "", -- A_Classic_Fairytale:queen --- ["Sabotage: [Sabotage all hogs in the circle and deal ~10 dmg]"] = "", -- Continental_supplies +-- ["Sabotage/Flare: [Sabotage all hogs in the circle and deal ~1 dmg OR Fire a cluster up into the air]"] = "", -- Continental_supplies + -- ["Salivaslurper"] = "", -- A_Classic_Fairytale:united -- ["Salvation"] = "", -- A_Classic_Fairytale:family -- ["Salvation was one step closer now..."] = "", -- A_Classic_Fairytale:dragon @@ -626,7 +746,7 @@ -- ["Scalp Muncher"] = "", -- A_Classic_Fairytale:backstab -- ["Score"] = "", -- Mutant ["SCORE"] = "PUNKTY", --- ["Scream from a Walrus: [Deal 20 damage + 10% of your hogs health to all hogs around you and get half back]"] = "", -- Continental_supplies + ["sec"] = "sek", -- ["Seduction"] = "", -- Continental_supplies -- ["Seems like every time you take a \"walk\", the enemy find us!"] = "", -- A_Classic_Fairytale:backstab @@ -634,8 +754,11 @@ ["See ya!"] = "Do zobaczenia!", -- ["Segmentation Paul"] = "", -- A_Classic_Fairytale:dragon -- ["Select continent!"] = "", -- Continental_supplies +-- ["Select continent first round with the Weapon Menu or by"] = "", -- Continental_supplies -- ["Select difficulty: [Left] - easier or [Right] - harder"] = "", -- A_Classic_Fairytale:first_blood ["selected!"] = "wybrany!", +-- ["Set period to negative value for random gravity"] = "", -- Gravity +-- ["Setup:|'g=150', where 150 is 150% of normal gravity"] = "", -- Gravity -- ["... share your beauty with the world every morning, my princess!"] = "", -- A_Classic_Fairytale:journey -- ["She's behind that tall thingy."] = "", -- A_Classic_Fairytale:family ["Shield boosted! +30 power"] = "Osłona ulepszona: +30 energii", @@ -646,16 +769,21 @@ ["Shield OFF:"] = "Osłona WYŁĄCZONA:", ["Shield ON:"] = "Osłona WŁĄCZONA:", ["Shield Seeker!"] = "Zdobywca osłon!", +-- ["Shoryuken"] = "", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 -- ["Shotgun"] = "", -- Continental_supplies ["Shotgun Team"] = "Strzelcy", ["Shotgun Training"] = "Trening strzelecki", ["shots remaining."] = "strzałów pozostało.", ["Silly"] = "Głuptas", +-- ["SineGun"] = "", -- Construction_Mode -- ["Sinky"] = "", -- ["Sirius Lee"] = "", -- A_Classic_Fairytale:enemy ["%s is out and Team %d|scored a penalty!| |Score:"] = "%s utonął i drużyna %d|dostała punkt karny!| |Punktacja:", ["%s is out and Team %d|scored a point!| |Score:"] = "%s utonął i drużyna %d|zdobyła punkt!| |Punktacja:", -- ["Slippery"] = "", -- A_Classic_Fairytale:journey +-- ["Slot"] = "", -- Frenzy +-- ["Slot keys save time! (F1-F10 by default)"] = "", -- Frenzy +-- ["SLOTS"] = "", -- Frenzy -- ["Smith 0.97"] = "", -- A_Classic_Fairytale:enemy -- ["Smith 0.98"] = "", -- A_Classic_Fairytale:enemy -- ["Smith 0.99a"] = "", -- A_Classic_Fairytale:enemy @@ -667,6 +795,7 @@ ["Sniper Training"] = "Trening Snajperski", ["Sniperz"] = "Snajperzy", -- ["So humiliating..."] = "", -- A_Classic_Fairytale:first_blood +-- ["Some weapons have a second option. Find them with"] = "", -- Continental_supplies -- ["South America"] = "", -- Continental_supplies -- ["So? What will it be?"] = "", -- A_Classic_Fairytale:shadow -- ["Spawn the crate, and attack!"] = "", -- WxW @@ -675,6 +804,8 @@ -- ["Spleenlover"] = "", -- A_Classic_Fairytale:united ["Sponge"] = "Gąbka", ["Spooky Tree"] = "Straszne drzewo", +-- ["Sprite Placement Mode"] = "", -- Construction_Mode +-- ["Sprite Testing Mode"] = "", -- Construction_Mode ["s|"] = "s|", ["s"] = "s", -- GaudyRacer, Space_Invasion ["STATUS UPDATE"] = "WYNIKI", -- GaudyRacer, Space_Invasion @@ -682,20 +813,36 @@ -- ["Step By Step"] = "", -- A_Classic_Fairytale:first_blood -- ["Steve"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen -- ["Sticky Mine"] = "", -- Continental_supplies +-- ["Sticky Mine Placement Mode"] = "", -- Construction_Mode -- ["Stronglings"] = "", -- A_Classic_Fairytale:shadow --- ["Structure"] = "", -- Continental_supplies + +-- ["Structure Placement Mode"] = "", -- Construction_Mode +-- ["Structure Placement Tool"] = "", -- Construction_Mode +-- ["Sundaland"] = "", -- Continental_supplies -- ["Super Weapons"] = "", -- WxW +-- ["Support Station"] = "", -- Construction_Mode -- ["Surf Before Crate"] = "", -- WxW -- ["Surfer! +15 points!"] = "", -- Space_Invasion -- ["Surfer!"] = "", -- WxW -- ["Survive!|Hint: Cinematics can be skipped with the [Precise] key."] = "", -- A_Classic_Fairytale:shadow -- ["Swing, Leaks A Lot, on the wings of the wind!"] = "", -- A_Classic_Fairytale:first_blood +-- ["switch"] = "", -- Continental_supplies ["Switched to "] = "Przełączono na ", +-- ["Switch Hog"] = "", -- Construction_Mode -- ["Syntax Errol"] = "", -- A_Classic_Fairytale:dragon +-- ["tab"] = "", -- Continental_supplies +-- ["Tagging Mode"] = "", -- Construction_Mode -- ["Talk about mixed signals..."] = "", -- A_Classic_Fairytale:dragon +-- ["Tardis"] = "", -- Construction_Mode +-- ["Target Placement Mode"] = "", -- Construction_Mode ["Team %d: "] = "Drużyna %d: ", ["Team Scores"] = "Punktacja(?)", -- Control, Space_Invasion +-- ["Teleporation Node"] = "", -- Construction_Mode +-- ["Teleportation Mode"] = "", -- Construction_Mode +-- ["Teleportation Node"] = "", -- Construction_Mode +-- ["Teleport"] = "", -- Construction_Mode, Frenzy -- ["Teleport hint: just use the mouse to select the destination!"] = "", -- A_Classic_Fairytale:dragon +-- ["Teleport Unsuccessful. Please teleport within a clan teleporter's sphere of influence."] = "", -- Construction_Mode -- ["Thanks!"] = "", -- A_Classic_Fairytale:family -- ["Thank you, my hero!"] = "", -- A_Classic_Fairytale:family -- ["Thank you, oh, thank you, Leaks A Lot!"] = "", -- A_Classic_Fairytale:journey @@ -712,6 +859,7 @@ ["That was pointless."] = "To było bezcelowe", -- ["The answer is...entertaintment. You'll see what I mean."] = "", -- A_Classic_Fairytale:backstab -- ["The anti-portal zone is all over the floor, and I have nothing to kill him...Droping something could hurt him enough to kill him..."] = "", -- portal +-- ["The Bottom Feeder can score points by killing anyone."] = "", -- Mutant -- ["The Bull's Eye"] = "", -- A_Classic_Fairytale:first_blood -- ["The caves are well hidden, they won't find us there!"] = "", -- A_Classic_Fairytale:united -- ["The Crate Frenzy"] = "", -- A_Classic_Fairytale:first_blood @@ -721,20 +869,26 @@ -- ["The Enemy Of My Enemy"] = "", -- A_Classic_Fairytale:enemy -- ["The First Blood"] = "", -- A_Classic_Fairytale:first_blood -- ["The First Encounter"] = "", -- A_Classic_Fairytale:shadow +-- ["The first player to kill someone becomes the Mutant."] = "", -- Mutant ["The flag will respawn next round."] = "Flaga pojawi się ponownie przy następnej rundzie.", -- ["The food bites back"] = "", -- A_Classic_Fairytale:backstab -- ["The giant umbrella from the last crate should help break the fall."] = "", -- A_Classic_Fairytale:first_blood -- ["The Great Escape"] = "", -- User_Mission_-_The_Great_Escape +-- ["The Great Hog in the sky sees your sadness and grants you a boon."] = "", -- Construction_Mode -- ["The guardian"] = "", -- A_Classic_Fairytale:shadow -- ["The Individualist"] = "", -- A_Classic_Fairytale:shadow -- ["Their buildings were very primitive back then, even for an uncivilised island."] = "", -- A_Classic_Fairytale:united -- ["The Journey Back"] = "", -- A_Classic_Fairytale:journey -- ["The Leap of Faith"] = "", -- A_Classic_Fairytale:first_blood -- ["The Moonwalk"] = "", -- A_Classic_Fairytale:journey +-- ["The Mutant has super-weapons and a lot of health."] = "", -- Mutant +-- ["The Mutant loses health quickly if he doesn't keep scoring kills."] = "", -- Mutant ["The Nameless One"] = "Bezimienny", -- ["The next one is pretty hard! |Tip: You have to do multiple swings!"] = "", -- Basic_Training_-_Rope -- ["Then how do they keep appearing?"] = "", -- A_Classic_Fairytale:shadow -- ["The other one were all cannibals, spending their time eating the organs of fellow hedgehogs..."] = "", -- A_Classic_Fairytale:first_blood +-- ["The player with least points (or most deaths) becomes the Bottom Feeder."] = "", -- Mutant +-- ["There are a variety of structures available to aid you."] = "", -- Construction_Mode -- ["There must be a spy among us!"] = "", -- A_Classic_Fairytale:backstab -- ["There's more of them? When did they become so hungry?"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united -- ["There's nothing more satisfying for me than seeing you share your beauty with the world every morning, my princess!"] = "", -- A_Classic_Fairytale:journey @@ -790,7 +944,7 @@ -- ["To the caves..."] = "", -- A_Classic_Fairytale:united ["Toxic Team"] = "Toksyczny zespół", ["TRACK COMPLETED"] = "UKOŃCZONO TRASĘ", - ["TRACK FAILED!"] = "TRASA NIEUKOŃCZONA!", + -- ["training"] = "", -- portal -- ["Traitors"] = "", -- A_Classic_Fairytale:epil -- ["Tribe"] = "", -- A_Classic_Fairytale:backstab @@ -807,6 +961,7 @@ -- ["ULTRA KILL"] = "", -- Mutant -- ["Under Construction"] = "", -- A_Classic_Fairytale:shadow -- ["Unexpected Igor"] = "", -- A_Classic_Fairytale:dragon +-- ["Unique new weapons"] = "", -- Continental_supplies -- ["Unit 0x0007"] = "", -- A_Classic_Fairytale:family -- ["Unit 334a$7%;.*"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united ["Unit 3378"] = "Jednostka 3378", @@ -821,11 +976,14 @@ -- ["Use it wisely!"] = "", -- A_Classic_Fairytale:dragon -- ["Use it with precaution!"] = "", -- A_Classic_Fairytale:first_blood -- ["User Challenge"] = "", - +-- ["Use the air-attack weapons and the arrow keys to select structures."] = "", -- Construction_Mode -- ["Use the portal gun to get to the next crate, then use the new gun to get to the final destination!|"] = "", -- A_Classic_Fairytale:dragon -- ["Use the rope to get on the head of the mole, young one!"] = "", -- A_Classic_Fairytale:first_blood -- ["Use the rope to knock your enemies to their doom."] = "", -- User_Mission_-_Rope_Knock_Challenge +-- ["Use your ready time to think."] = "", -- Frenzy ["Use your rope to get from start to finish as fast as you can!"] = "Użyj liny by jak najszybciej dotrzeć od startu do mety", +-- ["Utility Crate Placement Mode"] = "", -- Construction_Mode +-- ["Vampirism"] = "", -- Construction_Mode -- ["Vedgies"] = "", -- A_Classic_Fairytale:journey -- ["Vegan Jack"] = "", -- A_Classic_Fairytale:enemy -- ["Victory!"] = "", -- Basic_Training_-_Rope @@ -837,10 +995,14 @@ -- ["Wannabe Flyboys"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Wannabe Shoppsta"] = "", -- User_Mission_-_Rope_Knock_Challenge -- ["Watch your steps, young one!"] = "", -- A_Classic_Fairytale:first_blood +-- ["Watermelon Bomb"] = "", -- Construction_Mode ["Waypoint placed."] = "Postawiono punkt kontrolny", ["Way-Points Remaining"] = "Pozostało punktów: ", -- ["Weaklings"] = "", -- A_Classic_Fairytale:shadow -- ["We all know what happens when you get frightened..."] = "", -- A_Classic_Fairytale:first_blood +-- ["Weapon Crate Placement Mode"] = "", -- Construction_Mode +-- ["Weapon Filter"] = "", -- Construction_Mode +-- ["weaponschemes"] = "", -- Continental_supplies ["Weapons Reset"] = "Bronie odnawiają się", ["Weapons reset."] = "Bronie odnawiają się.", -- Highlander -- ["We are indeed."] = "", -- A_Classic_Fairytale:backstab @@ -893,6 +1055,7 @@ -- ["Where do you get that?!"] = "", -- A_Classic_Fairytale:enemy -- ["Where have you been?!"] = "", -- A_Classic_Fairytale:backstab -- ["Where have you been?"] = "", -- A_Classic_Fairytale:united +-- ["Whip"] = "", -- Construction_Mode -- ["? Why?"] = "", -- A_Classic_Fairytale:backstab -- ["Why "] = "", -- A_Classic_Fairytale:backstab -- ["! Why?!"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united @@ -905,8 +1068,10 @@ -- ["Why me?!"] = "", -- A_Classic_Fairytale:backstab -- ["Why would they do this?"] = "", -- A_Classic_Fairytale:backstab -- ["- Will Get 1-3 random weapons"] = "", -- Continental_supplies --- ["- Will refresh Parachute each turn."] = "", -- Continental_supplies --- ["- Will refresh portalgun each turn."] = "", -- Continental_supplies +-- ["- Will give you an airstrike every fifth turn."] = "", -- Continental_supplies +-- ["- Will give you a parachute every second turn."] = "", -- Continental_supplies + + ["Will this ever end?"] = "Co to się kiedyś skończy?", -- ["WINNER IS "] = "", -- Mutant ["WINNING TIME: "] = "ZWYCIĘSKI CZAS: ", @@ -925,6 +1090,7 @@ -- ["Yes!"] = "", -- A_Classic_Fairytale:enemy -- ["Yes, yeees! You are now ready to enter the real world!"] = "", -- A_Classic_Fairytale:first_blood -- ["Yo, dude, we're here, too!"] = "", -- A_Classic_Fairytale:family +-- ["You are far from home, and the water is rising, climb up as high as you can!"] = "", -- ClimbHome -- ["You are given the chance to turn your life around..."] = "", -- A_Classic_Fairytale:shadow -- ["You are playing with our lives here!"] = "", -- A_Classic_Fairytale:enemy -- ["! You bastards!"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united @@ -957,6 +1123,8 @@ -- ["You know what? I don't even regret anything!"] = "", -- A_Classic_Fairytale:backstab -- ["You'll see what I mean!"] = "", -- A_Classic_Fairytale:enemy -- ["You may only attack from a rope!"] = "", -- WxW +-- ["You may only spawn 5 crates per turn."] = "", -- Construction_Mode +-- ["You may only use 1 Extra Time per turn."] = "", -- Construction_Mode -- ["You meatbags are pretty slow, you know!"] = "", -- A_Classic_Fairytale:enemy -- ["You might want to find a way to instantly kill arriving cannibals!"] = "", -- A_Classic_Fairytale:backstab -- ["Young one, you are telling us that they can instantly change location without a shaman?"] = "", -- A_Classic_Fairytale:united @@ -977,6 +1145,7 @@ ["You've failed. Try again."] = "Przegrałeś. Spróbuj jeszcze raz", ["You've reached the goal!| |Time: "] = "Dotarłeś do celu!| |Czas: ", -- ["You will be avenged!"] = "", -- A_Classic_Fairytale:shadow +-- ["- You will recieve 2-4 weapons on each kill! (Even on own hogs)"] = "", -- Continental_supplies -- ["You won't believe what happened to me!"] = "", -- A_Classic_Fairytale:backstab -- ["Yuck! I bet they'll keep worshipping her even after I save the village!"] = "", -- A_Classic_Fairytale:family -- ["Zealandia"] = "", -- Continental_supplies diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/pl.txt --- a/share/hedgewars/Data/Locale/pl.txt Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/pl.txt Tue Nov 10 20:43:13 2015 +0100 @@ -58,6 +58,7 @@ 00:54=Miotacz błota 00:55=Zamrażarka 00:56=Tasak +00:57=Guma 01:00=Walczmy! 01:01=Remis @@ -81,6 +82,9 @@ 01:19=Ekstremalne 01:20=%1 odbicie 01:21=Dźwięk wyciszony +01:22=Tryb AFK +01:23=Automatyczne wyłączanie kamery +01:24=Automatyczne włączanie kamery ; Event messages ; Hog (%1) died @@ -544,6 +548,7 @@ 03:54=Narzędzie 03:55=Przełammy lody! 03:56=Nie przytnij sobie igieł! +03:57=Narzędzie ; Weapon Descriptions (use | as line breaks) 04:00=Atakuj przeciwników zwykłym granatem.|Wybuchnie kiedy zapalnik skończy odliczanie.|1-5: Ustawia zapalnik|Atak: Przytrzymaj by rzucić z większą siłą @@ -604,6 +609,7 @@ 04:54=Wystrzel strumień kleistej mazi.|Buduj mosty, zasypuj wrogów, zatykaj tunele.|Uważaj by nie zasypać samego siebie! 04:55=Epoka lodowcowa powraca!!|Zamroź jeże, uczyń podłoże śliskim lub zapobiegnij|utonięciu zamrażając wodę.|Atak: Strzał 04:56=Rzuć w przeciwnika dwoma tasakami i zablokuj mu |drogę lub użyj ich do wspinaczki! Jednak uważaj! |Te tasaki są naprawdę ostre!|Atak: Przytrzymaj by rzucić z większą siłą (dwukrotnie) +04:57=Budowanie elastyczny pasek wykonany z gumy,|z których jeże i inne rzeczy|odbijają się bez obrażeń upadku.|Lewo/Prawo: Zmiana orientacji pasek gumy|Kursor: Umieść pasek gumy w aktualnej pozycji ; Game goal strings 05:00=Ustawienia gry diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/pt_BR.lua --- a/share/hedgewars/Data/Locale/pt_BR.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/pt_BR.lua Tue Nov 10 20:43:13 2015 +0100 @@ -4,26 +4,40 @@ -- ["..."] = "", -- ["011101000"] = "", -- A_Classic_Fairytale:dragon -- ["011101001"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:family, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united +-- ["+1 to a Bottom Feeder for killing anyone"] = "", -- Mutant +-- ["+1 to a Mutant for killing anyone"] = "", -- Mutant +-- ["-1 to anyone for a suicide"] = "", -- Mutant +-- ["+2 for becoming a Mutant"] = "", -- Mutant ["30 minutes later..."] = "30 minutos mais tarde...", -- A_Classic_Fairytale:shadow ["About a month ago, a cyborg came and told us that you're the cannibals!"] = "Há cerca de um mês, um ciborgue veio e nos contou que vocês são os canibais!", -- A_Classic_Fairytale:enemy ["Accuracy Bonus!"] = "Bônus por acurácia", ["Ace"] = "Ás", -- User_Mission_-_RCPlane_Challenge, User_Mission_-_Rope_Knock_Challenge ["Achievement Unlocked"] = "Conquista alcançada", -- User_Mission_-_Bamboo_Thicket, User_Mission_-_That_Sinking_Feeling, Tumbler +-- ["???"] = "", -- A_Classic_Fairytale:backstab ["A Classic Fairytale"] = "Um conto de fadas clássico", -- A_Classic_Fairytale:first_blood --- ["???"] = "", -- A_Classic_Fairytale:backstab ["Actually, you aren't worthy of life! Take this..."] = "Na verdade, você não merece viver! Tome isso...", -- A_Classic_Fairytale:shadow ["A cy-what?"] = "Um cib... o quê?", -- A_Classic_Fairytale:enemy +-- ["Advanced Repositioning Mode"] = "", -- Construction_Mode -- ["Adventurous"] = "", -- A_Classic_Fairytale:journey +-- ["a frenetic Hedgewars mini-game"] = "", -- Frenzy ["Africa"] = "África", -- Continental_supplies ["After Leaks A Lot betrayed his tribe, he joined the cannibals..."] = "Depois que Vaza Demais traiu sua tribo, ele se juntou aos canibais...", -- A_Classic_Fairytale:first_blood -- ["After the shock caused by the enemy spy, Leaks A Lot and Dense Cloud went hunting to relax."] = "", -- A_Classic_Fairytale:shadow -- ["Again with the 'cannibals' thing!"] = "", -- A_Classic_Fairytale:enemy +-- ["Aggressively removes enemy hedgehogs."] = "", -- Construction_Mode ["a Hedgewars challenge"] = "um desafio Hedgewars", -- User_Mission_-_RCPlane_Challenge, User_Mission_-_Rope_Knock_Challenge ["a Hedgewars mini-game"] = "um mini-jogo Hedgewars", -- Space_Invasion, The_Specialists +-- ["a Hedgewars tag game"] = "", -- Mutant +-- ["AHHh, home sweet home. Made it in %d seconds."] = "", -- ClimbHome ["Aiming Practice"] = "Pratique a sua pontaria", --Bazooka, Shotgun, SniperRifle +-- ["Air Attack"] = "", -- Construction_Mode -- ["A leap in a leap"] = "", -- A_Classic_Fairytale:first_blood ["A little gift from the cyborgs"] = "Um pequeno presente dos ciborgues", -- A_Classic_Fairytale:shadow -- ["All gone...everything!"] = "", -- A_Classic_Fairytale:enemy +-- ["Allows free teleportation between other nodes."] = "", -- Construction_Mode +-- ["Allows placement of girders, rubber-bands, mines, sticky mines and barrels."] = "", -- Construction_Mode +-- ["Allows placement of structures."] = "", -- Construction_Mode +-- ["Allows the placement of weapons, utiliites, and health crates."] = "", -- Construction_Mode -- ["All right, we just need to get to the other side of the island!"] = "", -- A_Classic_Fairytale:journey -- ["All walls touched!"] = "", -- WxW -- ["Ammo"] = "", @@ -38,8 +52,11 @@ -- ["And so they discovered that cyborgs weren't invulnerable..."] = "", -- A_Classic_Fairytale:journey -- ["And where's all the weed?"] = "", -- A_Classic_Fairytale:dragon -- ["And you believed me? Oh, god, that's cute!"] = "", -- A_Classic_Fairytale:journey --- ["Anno 1032: [The explosion will make a strong push ~ wide range, wont affect hogs close to the target]"] = "", -- Continental_supplies +-- ["Anno 1032: [The explosion will make a strong push ~ Wide range, wont affect hogs close to the target]"] = "", -- Continental_supplies + -- ["Antarctica"] = "", -- Continental_supplies +-- ["Antarctic summer: - Will give you one girder/mudball and two sineguns/portals every fourth turn."] = "", -- Continental_supplies +-- ["Area"] = "", -- Continental_supplies -- ["Are we there yet?"] = "", -- A_Classic_Fairytale:shadow -- ["Are you accusing me of something?"] = "", -- A_Classic_Fairytale:backstab -- ["Are you saying that many of us have died for your entertainment?"] = "", -- A_Classic_Fairytale:enemy @@ -59,27 +76,35 @@ -- ["[Backspace]"] = "", -- ["Backstab"] = "", -- A_Classic_Fairytale:backstab -- ["Bad Team"] = "", -- User_Mission_-_The_Great_Escape +-- ["Ballgun"] = "", -- Construction_Mode -- ["Bamboo Thicket"] = "", -- ["Barrel Eater!"] = "", -- ["Barrel Launcher"] = "", +-- ["Barrel Placement Mode"] = "", -- Construction_Mode +-- ["Baseball Bat"] = "", -- Construction_Mode -- ["Baseballbat"] = "", -- Continental_supplies ["Bat balls at your enemies and|push them into the sea!"] = "Rebata as bolas em direção ao seus|e derrube-os no mar!", ["Bat your opponents through the|baskets and out of the map!"] = "Rebata seus oponentes para|fora do mapa através dos cestos!", +-- ["Bazooka"] = "", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 ["Bazooka Training"] = "Treino com a Bazuca", -- ["Beep Loopers"] = "", -- A_Classic_Fairytale:queen ["Best laps per team: "] = "Melhor volta por equipe: ", -- ["Best Team Times: "] = "", -- ["Beware, though! If you are slow, you die!"] = "", -- A_Classic_Fairytale:dragon +-- ["Bio-Filter"] = "", -- Construction_Mode -- ["Biomechanic Team"] = "", -- A_Classic_Fairytale:family +-- ["Birdy"] = "", -- Construction_Mode -- ["Blender"] = "", -- A_Classic_Fairytale:family -- ["Bloodpie"] = "", -- A_Classic_Fairytale:backstab -- ["Bloodrocutor"] = "", -- A_Classic_Fairytale:shadow -- ["Bloodsucker"] = "", -- A_Classic_Fairytale:shadow -- ["Bloody Rookies"] = "", -- 01#Boot_Camp, User_Mission_-_Dangerous_Ducklings, User_Mission_-_Diver, User_Mission_-_Spooky_Tree +-- ["Blowtorch"] = "", -- Construction_Mode, Frenzy +-- ["Blue Team"] = "", -- User_Mission_-_Dangerous_Ducklings -- ["Bone Jackson"] = "", -- A_Classic_Fairytale:backstab -- ["Bonely"] = "", -- A_Classic_Fairytale:shadow +-- ["BOOM!"] = "", -- ["Boom!"] = "", --- ["BOOM!"] = "", -- ["Boss defeated!"] = "", -- ["Boss Slayer!"] = "", -- ["Brain Blower"] = "", -- A_Classic_Fairytale:journey @@ -89,6 +114,7 @@ -- ["Brain Teaser"] = "", -- A_Classic_Fairytale:backstab -- ["Brutal Lily"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil -- ["Brutus"] = "", -- A_Classic_Fairytale:backstab +-- ["Build a fortress and destroy your enemy."] = "", -- Construction_Mode -- ["Build a track and race."] = "", -- ["Bullseye"] = "", -- A_Classic_Fairytale:dragon -- ["But it proved to be no easy task!"] = "", -- A_Classic_Fairytale:dragon @@ -99,6 +125,7 @@ -- ["But why would they help us?"] = "", -- A_Classic_Fairytale:backstab -- ["But you're cannibals. It's what you do."] = "", -- A_Classic_Fairytale:enemy -- ["But you said you'd let her go!"] = "", -- A_Classic_Fairytale:journey +-- ["Cake"] = "", -- Construction_Mode -- ["Call me Beep! Well, 'cause I'm such a nice...person!"] = "", -- A_Classic_Fairytale:family ["Cannibals"] = "Canibais", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:first_blood -- ["Cannibal Sentry"] = "", -- A_Classic_Fairytale:journey @@ -108,8 +135,15 @@ -- ["Carol"] = "", -- A_Classic_Fairytale:family -- ["CHALLENGE COMPLETE"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Change Weapon"] = "", +-- ["changing range from %i%% to %i%% with period of %i msec"] = "", -- Gravity -- ["Choose your side! If you want to join the strange man, walk up to him.|Otherwise, walk away from him. If you decide to att...nevermind..."] = "", -- A_Classic_Fairytale:shadow +-- ["Cleaver"] = "", -- Construction_Mode +-- ["Cleaver Placement Mode"] = "", -- Construction_Mode +-- ["Climber"] = "", -- ClimbHome +-- ["Climb Home"] = "", -- ClimbHome +-- ["Clowns"] = "", -- User_Mission_-_Nobody_Laugh -- ["Clumsy"] = "", +-- ["Cluster Bomb"] = "", -- Construction_Mode -- ["Cluster Bomb MASTER!"] = "", -- Basic_Training_-_Cluster_Bomb -- ["Cluster Bomb Training"] = "", -- Basic_Training_-_Cluster_Bomb -- ["Codename: Teamwork"] = "", @@ -129,12 +163,19 @@ -- ["Congratulations! You needed only half of time|to eliminate all targets."] = "", -- Basic_Training_-_Cluster_Bomb -- ["Congratulations! You've completed the Rope tutorial! |- Tutorial ends in 10 seconds!"] = "", -- Basic_Training_-_Rope ["Congratulations! You've eliminated all targets|within the allowed time frame."] = "Parabéns! Você eliminou todos os alvos|dentro do tempo limite.", --Bazooka, Shotgun, SniperRifle +-- ["CONSTRUCTION MODE"] = "", -- Construction_Mode +-- ["Construction Station"] = "", -- Construction_Mode -- ["Continental supplies"] = "", -- Continental_supplies -- ["Control pillars to score points."] = "", +-- ["Core"] = "", -- Construction_Mode -- ["Corporationals"] = "", -- A_Classic_Fairytale:queen -- ["Corpsemonger"] = "", -- A_Classic_Fairytale:shadow -- ["Corpse Thrower"] = "", -- A_Classic_Fairytale:epil +-- ["Cost"] = "", -- Construction_Mode +-- ["Crate Placement Tool"] = "", -- Construction_Mode -- ["Crates Left:"] = "", -- User_Mission_-_RCPlane_Challenge +-- ["Cricket time: [Drop a fireable mine! ~ Will work if fired close to your hog & far away from enemy ~ 1 sec]"] = "", -- Continental_supplies +-- ["Current setting is "] = "", -- Gravity -- ["Cybernetic Empire"] = "", -- ["Cyborg. It's what the aliens call themselves."] = "", -- A_Classic_Fairytale:enemy -- ["Dahmer"] = "", -- A_Classic_Fairytale:backstab @@ -142,15 +183,19 @@ -- ["DAMMIT, ROOKIE! GET OFF MY HEAD!"] = "", -- ["Dangerous Ducklings"] = "", -- ["Deadweight"] = "", +-- ["Decrease"] = "", -- Continental_supplies -- ["Defeat the cannibals"] = "", -- A_Classic_Fairytale:backstab -- ["Defeat the cannibals!|"] = "", -- A_Classic_Fairytale:united -- ["Defeat the cannibals!|Grenade hint: set the timer with [1-5], aim with [Up]/[Down] and hold [Space] to set power"] = "", -- A_Classic_Fairytale:shadow -- ["Defeat the cyborgs!"] = "", -- A_Classic_Fairytale:enemy +-- ["Defend your core from the enemy."] = "", -- Construction_Mode -- ["Defend yourself!|Hint: You can get tips on using weapons by moving your mouse over them in the weapon selection menu"] = "", -- A_Classic_Fairytale:shadow +-- ["Dematerializes weapons and equipment carried by enemy hedgehogs."] = "", -- Construction_Mode -- ["Demolition is fun!"] = "", -- ["Dense Cloud"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united -- ["Dense Cloud must have already told them everything..."] = "", -- A_Classic_Fairytale:shadow -- ["Depleted Kamikaze!"] = "", +-- ["Desert Eagle"] = "", -- Construction_Mode, A_Space_Adventure:death02 ["Destroy him, Leaks A Lot! He is responsible for the deaths of many of us!"] = "Destrua-o, Vaza Demais! Ele é responsável pelas mortes de muitos de nós!", -- A_Classic_Fairytale:first_blood ["Destroy invaders to score points."] = "Destrua os invasores para conseguir pontos.", ["Destroy the targets!|Hint: Select the Shoryuken and hit [Space]|P.S. You can use it mid-air."] = "Destrua os alvos!|Dica: Selecione o Shoryuken e aperte [Espaço]|Obs.: Você pode usá-lo em pleno ar.", -- A_Classic_Fairytale:first_blood @@ -169,9 +214,12 @@ -- ["Do you have any idea how valuable grass is?"] = "", -- A_Classic_Fairytale:enemy -- ["Do you think you're some kind of god?"] = "", -- A_Classic_Fairytale:enemy -- ["Dragon's Lair"] = "", -- A_Classic_Fairytale:dragon +-- ["Drill Rocket"] = "", -- Construction_Mode -- ["Drills"] = "", -- A_Classic_Fairytale:backstab +-- ["Drill Strike"] = "", -- Construction_Mode -- ["Drone Hunter!"] = "", --- ["Drop a bomb: [drop some heroic wind that will turn into a bomb on impact]"] = "", -- Continental_supplies +-- ["Drop a bomb: [Drop some heroic wind that will turn into a bomb on impact]"] = "", -- Continental_supplies + -- ["Drowner"] = "", -- ["Dude, all the plants are gone!"] = "", -- A_Classic_Fairytale:family -- ["Dude, can you see Ramon and Spiky?"] = "", -- A_Classic_Fairytale:journey @@ -181,11 +229,15 @@ -- ["Dude, where are we?"] = "", -- A_Classic_Fairytale:backstab -- ["Dude, wow! I just had the weirdest high!"] = "", -- A_Classic_Fairytale:backstab -- ["Duration"] = "", -- Continental_supplies --- ["Dust storm: [Deals 20 damage to all enemies in the circle]"] = "", -- Continental_supplies +-- ["Dust storm: [Deals 15 damage to all enemies in the circle]"] = "", -- Continental_supplies + +-- ["Dynamite"] = "", -- Construction_Mode +-- ["Each turn is only ONE SECOND!"] = "", -- Frenzy -- ["Each turn you get 1-3 random weapons"] = "", -- ["Each turn you get one random weapon"] = "", -- ["Eagle Eye"] = "", -- A_Classic_Fairytale:backstab --- ["Eagle Eye: [Blink to the impact ~ one shot]"] = "", -- Continental_supplies +-- ["Eagle Eye: [Blink to the impact ~ One shot]"] = "", -- Continental_supplies + -- ["Ear Sniffer"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:epil -- ["Elderbot"] = "", -- A_Classic_Fairytale:family -- ["Elimate your captor."] = "", -- User_Mission_-_The_Great_Escape @@ -208,8 +260,9 @@ -- ["Every single time!"] = "", -- A_Classic_Fairytale:dragon -- ["Everything looks OK..."] = "", -- A_Classic_Fairytale:enemy -- ["Exactly, man! That was my dream."] = "", -- A_Classic_Fairytale:backstab +-- ["Extra Damage"] = "", -- Construction_Mode +-- ["Extra Time"] = "", -- Construction_Mode -- ["Eye Chewer"] = "", -- A_Classic_Fairytale:journey --- ["INSANITY"] = "", -- Mutant -- ["Family Reunion"] = "", -- A_Classic_Fairytale:family ["Fastest lap: "] = "Volta mais rápida: ", -- ["Feeble Resistance"] = "", @@ -219,24 +272,29 @@ -- ["Femur Lover"] = "", -- A_Classic_Fairytale:shadow -- ["Fierce Competition!"] = "", -- Space_Invasion -- ["Fiery Water"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united +-- ["Filthy Blue"] = "", -- User_Mission_-_Dangerous_Ducklings -- ["Find your tribe!|Cross the lake!"] = "", -- A_Classic_Fairytale:dragon -- ["Finish your training|Hint: Animations can be skipped with the [Precise] key."] = "", -- A_Classic_Fairytale:first_blood -- ["Fire"] = "", --- ["Fire a mine: [Does what it says ~ Cant be dropped close to an enemy ~ 1 sec]"] = "", -- Continental_supplies + -- ["First aid kits?!"] = "", -- A_Classic_Fairytale:united +-- ["FIRST BLOOD MUTATES"] = "", -- Mutant ["First Blood"] = "Primeiro sangue", -- A_Classic_Fairytale:first_blood --- ["FIRST BLOOD MUTATES"] = "", -- Mutant ["First Steps"] = "Primeiros passos", -- A_Classic_Fairytale:first_blood ["Flag captured!"] = "Bandeira capturada!", -- ["Flag respawned!"] = "", -- ["Flag returned!"] = "", -- ["Flags, and their home base will be placed where each team ends their first turn."] = "", -- ["Flamer"] = "", +-- ["Flamethrower"] = "", -- Construction_Mode -- ["Flaming Worm"] = "", -- A_Classic_Fairytale:backstab --- ["Flare: [fire up some bombs depending on hogs depending on hogs in the circle"] = "", -- Continental_supplies + -- ["Flesh for Brainz"] = "", -- A_Classic_Fairytale:journey +-- ["Flying Saucer"] = "", -- Construction_Mode, Frenzy -- ["For improved features/stability, play 0.9.18+"] = "", -- WxW -- ["Free Dense Cloud and continue the mission!"] = "", -- A_Classic_Fairytale:journey +-- ["Freezer"] = "", -- Construction_Mode +-- ["FRENZY"] = "", -- Frenzy -- ["Friendly Fire!"] = "", -- ["fuel extended!"] = "", -- ["GAME BEGUN!!!"] = "", @@ -246,6 +304,9 @@ -- ["Game? Was this a game to you?!"] = "", -- A_Classic_Fairytale:enemy -- ["GasBomb"] = "", -- Continental_supplies -- ["Gas Gargler"] = "", -- A_Classic_Fairytale:queen +-- ["General information"] = "", -- Continental_supplies +-- ["Generates power."] = "", -- Construction_Mode +-- ["Generator"] = "", -- Construction_Mode -- ["Get Dense Cloud out of the pit!"] = "", -- A_Classic_Fairytale:journey -- ["Get on over there and take him out!"] = "", -- ["Get on the head of the mole"] = "", -- A_Classic_Fairytale:first_blood @@ -256,6 +317,8 @@ -- ["Get your teammates out of their natural prison and save the princess!|Hint: Drilling holes should solve everything.|Hint: It might be a good idea to place a girder before starting to drill. Just saying.|Hint: All your hedgehogs need to be above the marked height!|Hint: Leaks A Lot needs to get really close to the princess!"] = "", -- A_Classic_Fairytale:family -- ["GG!"] = "", -- User_Mission_-_Rope_Knock_Challenge -- ["Gimme Bones"] = "", -- A_Classic_Fairytale:backstab +-- ["Girder"] = "", -- Construction_Mode +-- ["Girder Placement Mode"] = "", -- Construction_Mode -- ["Glark"] = "", -- A_Classic_Fairytale:shadow -- ["Goal"] = "", -- ["GO! GO! GO!"] = "", @@ -272,12 +335,16 @@ -- ["Go surf!"] = "", -- WxW -- ["GOTCHA!"] = "", -- ["Grab Mines/Explosives"] = "", +-- ["Grants nearby hogs life-regeneration."] = "", -- Construction_Mode +-- ["Gravity"] = "", -- Gravity -- ["Great choice, Steve! Mind if I call you that?"] = "", -- A_Classic_Fairytale:shadow -- ["Great work! Now hit it with your Baseball Bat! |Tip: You can change weapon with 'Right Click'!"] = "", -- Basic_Training_-_Rope -- ["Great! You will be contacted soon for assistance."] = "", -- A_Classic_Fairytale:shadow --- ["Green lipstick bullet: [Is poisonous]"] = "", -- Continental_supplies + +-- ["Green lipstick bullet: [Poisonous, deals no damage]"] = "", -- Continental_supplies -- ["Greetings, "] = "", -- A_Classic_Fairytale:dragon -- ["Greetings, cloudy one!"] = "", -- A_Classic_Fairytale:shadow +-- ["Grenade"] = "", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 -- ["Grenade Training"] = "", -- Basic_Training_-_Grenade -- ["Grenadiers"] = "", -- Basic_Training_-_Grenade -- ["Guys, do you think there's more of them?"] = "", -- A_Classic_Fairytale:backstab @@ -285,23 +352,27 @@ -- ["Haha!"] = "", -- A_Classic_Fairytale:united -- ["Hahahaha!"] = "", -- ["Haha, now THAT would be something!"] = "", +-- ["Hammer"] = "", -- Construction_Mode, Continental_supplies -- ["Hannibal"] = "", -- A_Classic_Fairytale:epil -- ["Hapless Hogs"] = "", -- [" Hapless Hogs left!"] = "", - -- [" HAS MUTATED"] = "", -- Mutant -- ["Hatless Jerry"] = "", -- A_Classic_Fairytale:queen -- ["Have no illusions, your tribe is dead, indifferent of your choice."] = "", -- A_Classic_Fairytale:shadow -- ["Have we ever attacked you first?"] = "", -- A_Classic_Fairytale:enemy +-- ["Healing Station"] = "", -- Construction_Mode +-- ["Health Crate Placement Mode"] = "", -- Construction_Mode -- ["Health crates extend your time."] = "", -- ["Heavy"] = "", -- ["Heavy Cannfantry"] = "", -- A_Classic_Fairytale:united -- ["Hedge-cogs"] = "", -- A_Classic_Fairytale:enemy --- ["Hedgehog projectile: [fire your hog like a Sticky Bomb]"] = "", -- Continental_supplies +-- ["Hedgehog projectile: [Fire your hog like a Sticky Bomb]"] = "", -- Continental_supplies + ["Hedgewars-Basketball"] = "Hedgewars-Basketball", ["Hedgewars-Knockball"] = "Hedgewars-Knockball", -- ["Hedgibal Lecter"] = "", -- A_Classic_Fairytale:backstab -- ["Heh, it's not that bad."] = "", +-- ["Hellish Handgrenade"] = "", -- Construction_Mode -- ["Hello again, "] = "", -- A_Classic_Fairytale:family -- ["Help me, Leaks!"] = "", -- A_Classic_Fairytale:journey -- ["Help me, please!!!"] = "", -- A_Classic_Fairytale:journey @@ -333,6 +404,7 @@ -- ["Hogminator"] = "", -- A_Classic_Fairytale:family -- ["Hogs in sight!"] = "", -- Continental_supplies -- ["HOLY SHYTE!"] = "", -- Mutant +-- ["Homing Bee"] = "", -- Construction_Mode -- ["Honest Lee"] = "", -- A_Classic_Fairytale:enemy -- ["Hooray!"] = "", -- ["Hostage Situation"] = "", -- A_Classic_Fairytale:family @@ -366,7 +438,6 @@ -- ["If you get stuck, use your Desert Eagle or restart the mission!|"] = "", -- A_Classic_Fairytale:journey -- ["If you know what I mean..."] = "", -- A_Classic_Fairytale:shadow -- ["If you say so..."] = "", -- A_Classic_Fairytale:shadow - -- ["I guess you'll have to kill them."] = "", -- A_Classic_Fairytale:dragon -- ["I have come to make you an offering..."] = "", -- A_Classic_Fairytale:shadow -- ["I have no idea where that mole disappeared...Can you see it?"] = "", -- A_Classic_Fairytale:shadow @@ -389,6 +460,7 @@ -- ["I'm not sure about that!"] = "", -- A_Classic_Fairytale:united -- ["Impressive...you are still dry as the corpse of a hawk after a week in the desert..."] = "", -- A_Classic_Fairytale:first_blood -- ["I'm so scared!"] = "", -- A_Classic_Fairytale:united +-- ["Increase"] = "", -- Continental_supplies -- ["Incredible..."] = "", -- A_Classic_Fairytale:shadow -- ["I need to find the others!"] = "", -- A_Classic_Fairytale:backstab -- ["I need to get to the other side of this island, fast!"] = "", -- A_Classic_Fairytale:journey @@ -397,12 +469,14 @@ -- ["I need to warn the others."] = "", -- A_Classic_Fairytale:backstab -- ["In fact, you are the only one that's been acting strangely."] = "", -- A_Classic_Fairytale:backstab -- ["In order to get to the other side, you need to collect the crates first.|"] = "", -- A_Classic_Fairytale:dragon +-- ["INSANITY"] = "", -- Mutant -- ["Instructor"] = "", -- 01#Boot_Camp, User_Mission_-_Dangerous_Ducklings -- ["Interesting idea, haha!"] = "", -- A_Classic_Fairytale:enemy -- ["Interesting! Last time you said you killed a cannibal!"] = "", -- A_Classic_Fairytale:backstab -- ["In the meantime, take these and return to your \"friend\"!"] = "", -- A_Classic_Fairytale:shadow -- ["invaders destroyed"] = "", -- ["Invasion"] = "", -- A_Classic_Fairytale:united +-- ["Invulnerable"] = "", -- Construction_Mode -- ["I saw it with my own eyes!"] = "", -- A_Classic_Fairytale:shadow -- ["I see..."] = "", -- A_Classic_Fairytale:shadow -- ["I see you have already taken the leap of faith."] = "", -- A_Classic_Fairytale:first_blood @@ -445,6 +519,7 @@ -- ["Just kidding, none of you have died!"] = "", -- A_Classic_Fairytale:enemy -- ["Just on a walk."] = "", -- A_Classic_Fairytale:united -- ["Just wait till I get my hands on that trauma! ARGH!"] = "", -- A_Classic_Fairytale:family +-- ["Kamikaze"] = "", -- Construction_Mode -- ["Kamikaze Expert!"] = "", -- ["Keep it up!"] = "", -- ["Kerguelen"] = "", -- Continental_supplies @@ -454,6 +529,8 @@ -- ["Kill the aliens!"] = "", -- A_Classic_Fairytale:dragon -- ["Kill the cannibal!"] = "", -- A_Classic_Fairytale:first_blood -- ["Kill the traitor...or spare his life!|Kill him or press [Precise]!"] = "", -- A_Classic_Fairytale:backstab +-- ["Land Sprayer"] = "", -- Construction_Mode +-- ["Laser Sight"] = "", -- Construction_Mode -- ["Last Target!"] = "", -- ["Leader"] = "", -- A_Classic_Fairytale:enemy -- ["Leaderbot"] = "", -- A_Classic_Fairytale:queen @@ -464,6 +541,7 @@ -- ["Led Heart"] = "", -- A_Classic_Fairytale:queen -- ["Lee"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen -- ["[Left Shift]"] = "", +-- ["left shift"] = "", -- Continental_supplies -- ["Let a Continent provide your weapons!"] = "", -- Continental_supplies -- ["Let me test your skills a little, will you?"] = "", -- A_Classic_Fairytale:journey -- ["Let's go home!"] = "", -- A_Classic_Fairytale:journey @@ -473,41 +551,56 @@ -- ["Let them have a taste of my fury!"] = "", -- A_Classic_Fairytale:backstab -- ["Let us help, too!"] = "", -- A_Classic_Fairytale:backstab -- ["Light Cannfantry"] = "", -- A_Classic_Fairytale:united +-- ["Limburger"] = "", -- Construction_Mode -- ["Listen up, maggot!!"] = "", -- ["Little did they know that this hunt will mark them forever..."] = "", -- A_Classic_Fairytale:shadow -- ["Lively Lifeguard"] = "", --- ["Lonely Cries: [Rise the water if no hog is in the circle and deal 1 damage to all hogs]"] = "", -- Continental_supplies + +-- ["Lonely Cries: [Rise the water if no hog is in the circle and deal 7 damage to all enemy hogs]"] = "", -- Continental_supplies +-- ["Lonely Hog"] = "", -- ClimbHome -- ["Look, I had no choice!"] = "", -- A_Classic_Fairytale:backstab -- ["Look out! There's more of them!"] = "", -- A_Classic_Fairytale:backstab -- ["Look out! We're surrounded by cannibals!"] = "", -- A_Classic_Fairytale:enemy -- ["Looks like the whole world is falling apart!"] = "", -- A_Classic_Fairytale:enemy +-- ["Low Gravity"] = "", -- Construction_Mode, Frenzy -- ["Luckily, I've managed to snatch some of them."] = "", -- A_Classic_Fairytale:united -- ["LUDICROUS KILL"] = "", -- Mutant +-- ["Made it!"] = "", -- ClimbHome +-- ["- Massive weapon bonus on first turn"] = "", -- Continental_supplies -- ["May the spirits aid you in all your quests!"] = "", -- A_Classic_Fairytale:backstab -- ["Medicine: [Fire some exploding medicine that will heal all hogs effected by the explosion]"] = "", -- Continental_supplies -- ["MEGA KILL"] = "", -- Mutant -- ["Meiwes"] = "", -- A_Classic_Fairytale:backstab -- ["Mindy"] = "", -- A_Classic_Fairytale:united +-- ["Mine"] = "", -- Construction_Mode, Frenzy -- ["Mine Deployer"] = "", -- ["Mine Eater!"] = "", +-- ["Mine Placement Mode"] = "", -- Construction_Mode -- ["|- Mines Time:"] = "", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork +-- ["Mine Strike"] = "", -- Construction_Mode -- ["MISSION FAILED"] = "", -- User_Mission_-_Dangerous_Ducklings, User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork -- ["MISSION SUCCESS"] = "", -- ["MISSION SUCCESSFUL"] = "", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork +-- ["Molotov Cocktail"] = "", -- Construction_Mode -- ["Molotov"] = "", -- Continental_supplies -- ["MONSTER KILL"] = "", -- Mutant -- ["More Natives"] = "", -- A_Classic_Fairytale:epil +-- ["Mortar"] = "", -- Construction_Mode, A_Space_Adventure:death02 -- ["Movement: [Up], [Down], [Left], [Right]"] = "", +-- ["Mudball"] = "", -- Construction_Mode -- ["Multi-shot!"] = "", -- ["Muriel"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen -- ["Muscle Dissolver"] = "", -- A_Classic_Fairytale:shadow -- ["-------"] = "", -- Mutant +-- ["Mutant"] = "", -- Mutant -- ["Nade Boy"] = "", -- Basic_Training_-_Grenade -- ["Name"] = "", -- A_Classic_Fairytale:queen -- ["Nameless Heroes"] = "", -- ["Nancy Screw"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:queen +-- ["Napalm"] = "", -- Construction_Mode -- ["Napalm rocket: [Fire a bomb with napalm!]"] = "", -- Continental_supplies -- ["Natives"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:first_blood, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united +-- ["Naughty Ninja"] = "", -- User_Mission_-_Dangerous_Ducklings -- ["New Barrels Per Turn"] = "", -- ["NEW CLAN RECORD: "] = "", ["NEW fastest lap: "] = "NOVA volta mais rápida: ", @@ -518,6 +611,7 @@ -- ["Nice work, "] = "", -- A_Classic_Fairytale:dragon -- ["Nice work!"] = "", -- A_Classic_Fairytale:enemy -- ["Nilarian"] = "", -- A_Classic_Fairytale:queen +-- ["Nobody Laugh"] = "", -- User_Mission_-_Nobody_Laugh -- ["No, I came back to help you out..."] = "", -- A_Classic_Fairytale:shadow -- ["No...I wonder where they disappeared?!"] = "", -- A_Classic_Fairytale:journey -- ["Nom-Nom"] = "", -- A_Classic_Fairytale:journey @@ -525,6 +619,7 @@ -- ["Nope. It was one fast mole, that's for sure."] = "", -- A_Classic_Fairytale:shadow -- ["No! Please, help me!"] = "", -- A_Classic_Fairytale:journey -- ["NORMAL"] = "", -- Continental_supplies +-- ["Normal players can only score points by killing the mutant."] = "", -- Mutant -- ["North America"] = "", -- Continental_supplies -- ["Not all hogs are born equal."] = "", -- Highlander -- ["NOT ENOUGH WAYPOINTS"] = "", @@ -537,6 +632,7 @@ -- ["No. Where did he come from?"] = "", -- A_Classic_Fairytale:shadow -- ["Now how do I get on the other side?!"] = "", -- A_Classic_Fairytale:dragon -- ["No. You and the rest of the tribe are safer there!"] = "", -- A_Classic_Fairytale:backstab +-- ["Object Placement Tool"] = "", -- Construction_Mode -- ["Obliterate them!|Hint: You might want to take cover..."] = "", -- A_Classic_Fairytale:shadow -- ["Obstacle course"] = "", -- A_Classic_Fairytale:dragon -- ["Of course I have to save her. What did I expect?!"] = "", -- A_Classic_Fairytale:family @@ -553,24 +649,30 @@ ["Once upon a time, on an island with great natural resources, lived two tribes in heated conflict..."] = "Era uma vez, em uma ilha com ótimos recursos naturais, duas tribos que viviam em intenso conflito...", -- A_Classic_Fairytale:first_blood -- ["ONE HOG PER TEAM! KILLING EXCESS HEDGES"] = "", -- Mutant -- ["One tribe was peaceful, spending their time hunting and training, enjoying the small pleasures of life..."] = "", -- A_Classic_Fairytale:first_blood +-- ["on Skip"] = "", -- Continental_supplies -- ["Oops...I dropped them."] = "", -- A_Classic_Fairytale:united -- ["Open that crate and we will continue!"] = "", -- A_Classic_Fairytale:first_blood -- ["Operation Diver"] = "", -- ["Opposing Team: "] = "", +-- ["or 'g=50, g2=150, period=4000' for gravity changing|from 50 to 150 and back with period of 4000 msec"] = "", -- Gravity -- ["Orlando Boom!"] = "", -- A_Classic_Fairytale:queen +-- ["Other kills don't give you points."] = "", -- Mutant -- ["Ouch!"] = "", -- User_Mission_-_Rope_Knock_Challenge -- ["Our tribe, our beautiful island!"] = "", -- A_Classic_Fairytale:enemy -- ["Parachute"] = "", -- Continental_supplies -- ["Pathetic Hog #%d"] = "", -- ["Pathetic Resistance"] = "", -- User_Mission_-_Bamboo_Thicket, User_Mission_-_Newton_and_the_Hammock +-- ["Penguin roar: [Deal 15 damage + 15% of your hogs health to all hogs around you and get 2/3 back]"] = "", -- Continental_supplies -- ["Perfect! Now try to get the next crate without hurting yourself!"] = "", -- A_Classic_Fairytale:first_blood -- ["Per-Hog Ammo"] = "", --- ["- Per team weapons|- 9 weaponschemes|- Unique new weapons| |Select continent first round with the Weapon Menu or by ([switch/tab]=Increase,[precise/left shift]=Decrease) on Skip|Some weapons have a second option. Find them with [switch/tab]"] = "", -- Continental_supplies +-- ["Personal Portal Device"] = "", -- Construction_Mode +-- ["Per team weapons"] = "", -- Continental_supplies -- ["Pfew! That was close!"] = "", -- A_Classic_Fairytale:shadow --- ["Piñata bullet: [Contains some sweet candy!]"] = "", -- Continental_supplies +-- ["Piano Strike"] = "", -- Construction_Mode +-- ["Pickhammer"] = "", -- Construction_Mode + -- ["Pings left:"] = "", -- Space_Invasion - -- ["Place more waypoints using the 'Air Attack' weapon."] = "", -- ["Planes Used:"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Planes Used"] = "", -- User_Mission_-_RCPlane_Challenge @@ -580,14 +682,18 @@ -- ["Please, stop releasing your \"smoke signals\"!"] = "", -- A_Classic_Fairytale:shadow -- ["Point Blank Combo!"] = "", -- Space_Invasion -- ["points"] = "", -- Control, CTF_Blizzard, Basic_Training_-_Bazooka, Basic_Training_-_Shotgun, Basic_Training_-_Sniper_Rifle +-- ["POINTS"] = "", -- Mutant -- ["Poison"] = "", +-- ["Population"] = "", -- Continental_supplies -- ["Portal hint: one goes to the destination, and one is the entrance.|"] = "", -- A_Classic_Fairytale:dragon -- ["Portal mission"] = "", -- portal -- ["Power Remaining"] = "", -- ["Prepare yourself"] = "", +-- ["presice"] = "", -- Continental_supplies -- ["Press [Enter] to accept this configuration."] = "", -- WxW -- ["Press [Left] or [Right] to move around, [Enter] to jump"] = "", -- A_Classic_Fairytale:first_blood -- ["Press [Precise] to skip intro"] = "", +-- ["Prestigious Pilot"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Private Novak"] = "", -- Basic_Training_-_Cluster_Bomb -- ["Protect yourselves!|Grenade hint: set the timer with [1-5], aim with [Up]/[Down] and hold [Space] to set power"] = "", -- A_Classic_Fairytale:shadow -- ["Race complexity limit reached."] = "", @@ -596,26 +702,40 @@ -- ["Radar Ping"] = "", -- Space_Invasion -- ["Raging Buffalo"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united -- ["Ramon"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow +-- ["random in range from %i%% to %i%% with period of %i msec"] = "", -- Gravity +-- ["RC Plane"] = "", -- Construction_Mode -- ["RC PLANE TRAINING"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Really?! You thought you could harm me with your little toys?"] = "", -- A_Classic_Fairytale:shadow +-- ["Reflector Shield"] = "", -- Construction_Mode +-- ["Reflects enemy projectiles."] = "", -- Construction_Mode -- ["Regurgitator"] = "", -- A_Classic_Fairytale:backstab -- ["Reinforcements"] = "", -- A_Classic_Fairytale:backstab -- ["Remember: The rope only bend around objects, |if it doesn't hit anything it's always stright!"] = "", -- Basic_Training_-_Rope -- ["Remember this, pathetic animal: when the day comes, you will regret your blind loyalty!"] = "", -- A_Classic_Fairytale:shadow +-- ["REMOVED"] = "", -- Continental_supplies +-- ["Respawner"] = "", -- Construction_Mode +-- ["Resurrector"] = "", -- Construction_Mode +-- ["Resurrects dead hedgehogs."] = "", -- Construction_Mode -- [" - Return the enemy flag to your base to score | - First team to 3 captures wins | - You may only score when your flag is in your base | - Hogs will drop the flag if killed, or drowned | - Dropped flags may be returned or recaptured | - Hogs respawn when killed"] = "", -- ["Return to Leaks A Lot! If you get stuck, press [Precise] to try again!"] = "", -- A_Classic_Fairytale:shadow -- ["Righteous Beard"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:first_blood, A_Classic_Fairytale:queen, A_Classic_Fairytale:united +-- ["Rope"] = "", -- Construction_Mode -- ["ROPE-KNOCKING"] = "", -- User_Mission_-_Rope_Knock_Challenge +-- ["Rope to safety"] = "", -- ClimbHome -- ["Rope Training"] = "", -- Basic_Training_-_Rope -- ["Rot Molester"] = "", -- A_Classic_Fairytale:shadow -- ["Round Limit:"] = "", -- ["Round Limit"] = "", -- ["Rounds Complete: "] = "", -- ["Rounds Complete"] = "", +-- ["Rubber Band"] = "", -- Construction_Mode +-- ["Rubber Placement Mode"] = "", -- Construction_Mode +-- ["RULES"] = "", -- Frenzy, Mutant -- ["RULES OF THE GAME [Press ESC to view]"] = "", -- ["Rusty Joe"] = "", -- A_Classic_Fairytale:queen -- ["s|"] = "", --- ["Sabotage: [Sabotage all hogs in the circle and deal ~10 dmg]"] = "", -- Continental_supplies +-- ["Sabotage/Flare: [Sabotage all hogs in the circle and deal ~1 dmg OR Fire a cluster up into the air]"] = "", -- Continental_supplies + -- ["Salivaslurper"] = "", -- A_Classic_Fairytale:united -- ["Salvation"] = "", -- A_Classic_Fairytale:family -- ["Salvation was one step closer now..."] = "", -- A_Classic_Fairytale:dragon @@ -627,7 +747,7 @@ -- ["Scalp Muncher"] = "", -- A_Classic_Fairytale:backstab -- ["SCORE"] = "", -- ["Score"] = "", -- Mutant --- ["Scream from a Walrus: [Deal 20 damage + 10% of your hogs health to all hogs around you and get half back]"] = "", -- Continental_supplies + -- ["sec"] = "", -- CTF_Blizzard, TrophyRace, Basic_Training_-_Bazooka, Basic_Training_-_Shotgun, Basic_Training_-_Sniper_Rifle, User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork, Capture_the_Flag -- ["Seduction"] = "", -- Continental_supplies -- ["Seems like every time you take a \"walk\", the enemy find us!"] = "", -- A_Classic_Fairytale:backstab @@ -635,8 +755,11 @@ -- ["See ya!"] = "", -- ["Segmentation Paul"] = "", -- A_Classic_Fairytale:dragon -- ["Select continent!"] = "", -- Continental_supplies +-- ["Select continent first round with the Weapon Menu or by"] = "", -- Continental_supplies -- ["Select difficulty: [Left] - easier or [Right] - harder"] = "", -- A_Classic_Fairytale:first_blood -- ["selected!"] = "", +-- ["Set period to negative value for random gravity"] = "", -- Gravity +-- ["Setup:|'g=150', where 150 is 150% of normal gravity"] = "", -- Gravity -- ["s"] = "", -- GaudyRacer, Space_Invasion -- ["... share your beauty with the world every morning, my princess!"] = "", -- A_Classic_Fairytale:journey -- ["She's behind that tall thingy."] = "", -- A_Classic_Fairytale:family @@ -648,16 +771,21 @@ -- ["Shield OFF:"] = "", -- ["Shield ON:"] = "", -- ["Shield Seeker!"] = "", +-- ["Shoryuken"] = "", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 -- ["Shotgun"] = "", -- Continental_supplies ["Shotgun Team"] = "Carabineiros", ["Shotgun Training"] = "Treino com a Escopeta", -- ["shots remaining."] = "", -- ["Silly"] = "", +-- ["SineGun"] = "", -- Construction_Mode -- ["Sinky"] = "", -- ["Sirius Lee"] = "", -- A_Classic_Fairytale:enemy ["%s is out and Team %d|scored a penalty!| |Score:"] = "%s está fora e a Equipe %d|sofreu uma penalidade!| |Pontuação:", -- Basketball, Knockball ["%s is out and Team %d|scored a point!| |Score:"] = "%s está fora e a Equipe %d|marcou um ponto!| |Pontuação:", -- Basketball, Knockball -- ["Slippery"] = "", -- A_Classic_Fairytale:journey +-- ["Slot"] = "", -- Frenzy +-- ["Slot keys save time! (F1-F10 by default)"] = "", -- Frenzy +-- ["SLOTS"] = "", -- Frenzy -- ["Smith 0.97"] = "", -- A_Classic_Fairytale:enemy -- ["Smith 0.98"] = "", -- A_Classic_Fairytale:enemy -- ["Smith 0.99a"] = "", -- A_Classic_Fairytale:enemy @@ -669,6 +797,7 @@ ["Sniper Training"] = "Treino com o Rifle Sniper", ["Sniperz"] = "Franco-Atiradores", -- ["So humiliating..."] = "", -- A_Classic_Fairytale:first_blood +-- ["Some weapons have a second option. Find them with"] = "", -- Continental_supplies -- ["South America"] = "", -- Continental_supplies -- ["So? What will it be?"] = "", -- A_Classic_Fairytale:shadow -- ["Spawn the crate, and attack!"] = "", -- WxW @@ -677,25 +806,43 @@ -- ["Spleenlover"] = "", -- A_Classic_Fairytale:united -- ["Sponge"] = "", -- ["Spooky Tree"] = "", +-- ["Sprite Placement Mode"] = "", -- Construction_Mode +-- ["Sprite Testing Mode"] = "", -- Construction_Mode -- ["STATUS UPDATE"] = "", -- GaudyRacer, Space_Invasion -- ["Steel Eye"] = "", -- A_Classic_Fairytale:queen -- ["Step By Step"] = "", -- A_Classic_Fairytale:first_blood -- ["Steve"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen -- ["Sticky Mine"] = "", -- Continental_supplies +-- ["Sticky Mine Placement Mode"] = "", -- Construction_Mode -- ["Stronglings"] = "", -- A_Classic_Fairytale:shadow --- ["Structure"] = "", -- Continental_supplies + +-- ["Structure Placement Mode"] = "", -- Construction_Mode +-- ["Structure Placement Tool"] = "", -- Construction_Mode +-- ["Sundaland"] = "", -- Continental_supplies -- ["Super Weapons"] = "", -- WxW +-- ["Support Station"] = "", -- Construction_Mode -- ["Surf Before Crate"] = "", -- WxW -- ["Surfer! +15 points!"] = "", -- Space_Invasion -- ["Surfer!"] = "", -- WxW -- ["Survive!|Hint: Cinematics can be skipped with the [Precise] key."] = "", -- A_Classic_Fairytale:shadow -- ["Swing, Leaks A Lot, on the wings of the wind!"] = "", -- A_Classic_Fairytale:first_blood +-- ["switch"] = "", -- Continental_supplies -- ["Switched to "] = "", +-- ["Switch Hog"] = "", -- Construction_Mode -- ["Syntax Errol"] = "", -- A_Classic_Fairytale:dragon +-- ["tab"] = "", -- Continental_supplies +-- ["Tagging Mode"] = "", -- Construction_Mode -- ["Talk about mixed signals..."] = "", -- A_Classic_Fairytale:dragon +-- ["Tardis"] = "", -- Construction_Mode +-- ["Target Placement Mode"] = "", -- Construction_Mode ["Team %d: "] = "Equipe %d: ", -- ["Team Scores"] = "", -- Control, Space_Invasion +-- ["Teleporation Node"] = "", -- Construction_Mode +-- ["Teleportation Mode"] = "", -- Construction_Mode +-- ["Teleportation Node"] = "", -- Construction_Mode +-- ["Teleport"] = "", -- Construction_Mode, Frenzy -- ["Teleport hint: just use the mouse to select the destination!"] = "", -- A_Classic_Fairytale:dragon +-- ["Teleport Unsuccessful. Please teleport within a clan teleporter's sphere of influence."] = "", -- Construction_Mode -- ["Thanks!"] = "", -- A_Classic_Fairytale:family -- ["Thank you, my hero!"] = "", -- A_Classic_Fairytale:family -- ["Thank you, oh, thank you, Leaks A Lot!"] = "", -- A_Classic_Fairytale:journey @@ -712,6 +859,7 @@ -- ["That was pointless."] = "", -- ["The answer is...entertaintment. You'll see what I mean."] = "", -- A_Classic_Fairytale:backstab -- ["The anti-portal zone is all over the floor, and I have nothing to kill him...Droping something could hurt him enough to kill him..."] = "", -- portal +-- ["The Bottom Feeder can score points by killing anyone."] = "", -- Mutant -- ["The Bull's Eye"] = "", -- A_Classic_Fairytale:first_blood -- ["The caves are well hidden, they won't find us there!"] = "", -- A_Classic_Fairytale:united -- ["The Crate Frenzy"] = "", -- A_Classic_Fairytale:first_blood @@ -721,20 +869,26 @@ -- ["The Enemy Of My Enemy"] = "", -- A_Classic_Fairytale:enemy -- ["The First Blood"] = "", -- A_Classic_Fairytale:first_blood -- ["The First Encounter"] = "", -- A_Classic_Fairytale:shadow +-- ["The first player to kill someone becomes the Mutant."] = "", -- Mutant -- ["The flag will respawn next round."] = "", -- ["The food bites back"] = "", -- A_Classic_Fairytale:backstab -- ["The giant umbrella from the last crate should help break the fall."] = "", -- A_Classic_Fairytale:first_blood -- ["The Great Escape"] = "", -- User_Mission_-_The_Great_Escape +-- ["The Great Hog in the sky sees your sadness and grants you a boon."] = "", -- Construction_Mode -- ["The guardian"] = "", -- A_Classic_Fairytale:shadow -- ["The Individualist"] = "", -- A_Classic_Fairytale:shadow -- ["Their buildings were very primitive back then, even for an uncivilised island."] = "", -- A_Classic_Fairytale:united -- ["The Journey Back"] = "", -- A_Classic_Fairytale:journey -- ["The Leap of Faith"] = "", -- A_Classic_Fairytale:first_blood -- ["The Moonwalk"] = "", -- A_Classic_Fairytale:journey +-- ["The Mutant has super-weapons and a lot of health."] = "", -- Mutant +-- ["The Mutant loses health quickly if he doesn't keep scoring kills."] = "", -- Mutant -- ["The Nameless One"] = "", -- ["The next one is pretty hard! |Tip: You have to do multiple swings!"] = "", -- Basic_Training_-_Rope -- ["Then how do they keep appearing?"] = "", -- A_Classic_Fairytale:shadow -- ["The other one were all cannibals, spending their time eating the organs of fellow hedgehogs..."] = "", -- A_Classic_Fairytale:first_blood +-- ["The player with least points (or most deaths) becomes the Bottom Feeder."] = "", -- Mutant +-- ["There are a variety of structures available to aid you."] = "", -- Construction_Mode -- ["There must be a spy among us!"] = "", -- A_Classic_Fairytale:backstab -- ["There's more of them? When did they become so hungry?"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united -- ["There's nothing more satisfying for me than seeing you share your beauty with the world every morning, my princess!"] = "", -- A_Classic_Fairytale:journey @@ -790,7 +944,7 @@ -- ["To the caves..."] = "", -- A_Classic_Fairytale:united -- ["Toxic Team"] = "", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork -- ["TRACK COMPLETED"] = "", --- ["TRACK FAILED!"] = "", + -- ["training"] = "", -- portal -- ["Traitors"] = "", -- A_Classic_Fairytale:epil -- ["Tribe"] = "", -- A_Classic_Fairytale:backstab @@ -807,6 +961,7 @@ -- ["ULTRA KILL"] = "", -- Mutant -- ["Under Construction"] = "", -- A_Classic_Fairytale:shadow -- ["Unexpected Igor"] = "", -- A_Classic_Fairytale:dragon +-- ["Unique new weapons"] = "", -- Continental_supplies -- ["Unit"] = "", -- ["Unit 0x0007"] = "", -- A_Classic_Fairytale:family -- ["Unit 334a$7%;.*"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united @@ -821,11 +976,14 @@ -- ["Use it wisely!"] = "", -- A_Classic_Fairytale:dragon -- ["Use it with precaution!"] = "", -- A_Classic_Fairytale:first_blood -- ["User Challenge"] = "", - +-- ["Use the air-attack weapons and the arrow keys to select structures."] = "", -- Construction_Mode -- ["Use the portal gun to get to the next crate, then use the new gun to get to the final destination!|"] = "", -- A_Classic_Fairytale:dragon -- ["Use the rope to get on the head of the mole, young one!"] = "", -- A_Classic_Fairytale:first_blood -- ["Use the rope to knock your enemies to their doom."] = "", -- User_Mission_-_Rope_Knock_Challenge +-- ["Use your ready time to think."] = "", -- Frenzy ["Use your rope to get from start to finish as fast as you can!"] = "Use sua corda para ir do início ao fim o mais rápido que você puder!", +-- ["Utility Crate Placement Mode"] = "", -- Construction_Mode +-- ["Vampirism"] = "", -- Construction_Mode -- ["Vedgies"] = "", -- A_Classic_Fairytale:journey -- ["Vegan Jack"] = "", -- A_Classic_Fairytale:enemy -- ["Victory!"] = "", -- Basic_Training_-_Rope @@ -837,10 +995,14 @@ -- ["Wannabe Flyboys"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Wannabe Shoppsta"] = "", -- User_Mission_-_Rope_Knock_Challenge -- ["Watch your steps, young one!"] = "", -- A_Classic_Fairytale:first_blood +-- ["Watermelon Bomb"] = "", -- Construction_Mode -- ["Waypoint placed."] = "", -- ["Way-Points Remaining"] = "", -- ["Weaklings"] = "", -- A_Classic_Fairytale:shadow -- ["We all know what happens when you get frightened..."] = "", -- A_Classic_Fairytale:first_blood +-- ["Weapon Crate Placement Mode"] = "", -- Construction_Mode +-- ["Weapon Filter"] = "", -- Construction_Mode +-- ["weaponschemes"] = "", -- Continental_supplies -- ["Weapons Reset"] = "", -- ["Weapons reset."] = "", -- Highlander -- ["We are indeed."] = "", -- A_Classic_Fairytale:backstab @@ -893,6 +1055,7 @@ -- ["Where do you get that?!"] = "", -- A_Classic_Fairytale:enemy -- ["Where have you been?!"] = "", -- A_Classic_Fairytale:backstab -- ["Where have you been?"] = "", -- A_Classic_Fairytale:united +-- ["Whip"] = "", -- Construction_Mode -- ["? Why?"] = "", -- A_Classic_Fairytale:backstab -- ["Why "] = "", -- A_Classic_Fairytale:backstab -- ["! Why?!"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united @@ -905,8 +1068,10 @@ -- ["Why me?!"] = "", -- A_Classic_Fairytale:backstab -- ["Why would they do this?"] = "", -- A_Classic_Fairytale:backstab -- ["- Will Get 1-3 random weapons"] = "", -- Continental_supplies --- ["- Will refresh Parachute each turn."] = "", -- Continental_supplies --- ["- Will refresh portalgun each turn."] = "", -- Continental_supplies +-- ["- Will give you an airstrike every fifth turn."] = "", -- Continental_supplies +-- ["- Will give you a parachute every second turn."] = "", -- Continental_supplies + + -- ["Will this ever end?"] = "", -- ["WINNER IS "] = "", -- Mutant -- ["WINNING TIME: "] = "", @@ -925,6 +1090,7 @@ -- ["Yes!"] = "", -- A_Classic_Fairytale:enemy -- ["Yes, yeees! You are now ready to enter the real world!"] = "", -- A_Classic_Fairytale:first_blood -- ["Yo, dude, we're here, too!"] = "", -- A_Classic_Fairytale:family +-- ["You are far from home, and the water is rising, climb up as high as you can!"] = "", -- ClimbHome -- ["You are given the chance to turn your life around..."] = "", -- A_Classic_Fairytale:shadow -- ["You are playing with our lives here!"] = "", -- A_Classic_Fairytale:enemy -- ["! You bastards!"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united @@ -957,6 +1123,8 @@ -- ["You know what? I don't even regret anything!"] = "", -- A_Classic_Fairytale:backstab -- ["You'll see what I mean!"] = "", -- A_Classic_Fairytale:enemy -- ["You may only attack from a rope!"] = "", -- WxW +-- ["You may only spawn 5 crates per turn."] = "", -- Construction_Mode +-- ["You may only use 1 Extra Time per turn."] = "", -- Construction_Mode -- ["You meatbags are pretty slow, you know!"] = "", -- A_Classic_Fairytale:enemy -- ["You might want to find a way to instantly kill arriving cannibals!"] = "", -- A_Classic_Fairytale:backstab -- ["Young one, you are telling us that they can instantly change location without a shaman?"] = "", -- A_Classic_Fairytale:united @@ -977,6 +1145,7 @@ -- ["You've failed. Try again."] = "", ["You've reached the goal!| |Time: "] = "Você alcançou o objetivo!| |Tempo: ", -- ["You will be avenged!"] = "", -- A_Classic_Fairytale:shadow +-- ["- You will recieve 2-4 weapons on each kill! (Even on own hogs)"] = "", -- Continental_supplies -- ["You won't believe what happened to me!"] = "", -- A_Classic_Fairytale:backstab -- ["Yuck! I bet they'll keep worshipping her even after I save the village!"] = "", -- A_Classic_Fairytale:family -- ["Zealandia"] = "", -- Continental_supplies diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/pt_PT.lua --- a/share/hedgewars/Data/Locale/pt_PT.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/pt_PT.lua Tue Nov 10 20:43:13 2015 +0100 @@ -4,6 +4,10 @@ ["..."] = "...", ["011101000"] = "011101000", -- A_Classic_Fairytale:dragon ["011101001"] = "011101001", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:family, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united +-- ["+1 to a Bottom Feeder for killing anyone"] = "", -- Mutant +-- ["+1 to a Mutant for killing anyone"] = "", -- Mutant +-- ["-1 to anyone for a suicide"] = "", -- Mutant +-- ["+2 for becoming a Mutant"] = "", -- Mutant ["30 minutes later..."] = "30 minutos depois...", -- A_Classic_Fairytale:shadow ["About a month ago, a cyborg came and told us that you're the cannibals!"] = "À volta de um mês atrás, apareceu um cyborg e disse-nos que voces é que eram os cabinais!", -- A_Classic_Fairytale:enemy ["Accuracy Bonus!"] = "Bónus de Precisão!", @@ -13,17 +17,27 @@ ["A Classic Fairytale"] = "Um Clássico Conto de Fadas", -- A_Classic_Fairytale:first_blood ["Actually, you aren't worthy of life! Take this..."] = "Pensando melhor, não mereçes viver! Toma isto...", -- A_Classic_Fairytale:shadow ["A cy-what?"] = "Um cy-quê?", -- A_Classic_Fairytale:enemy +-- ["Advanced Repositioning Mode"] = "", -- Construction_Mode ["Adventurous"] = "Aventureiro", -- A_Classic_Fairytale:journey +-- ["a frenetic Hedgewars mini-game"] = "", -- Frenzy ["Africa"] = "África", -- Continental_supplies ["After Leaks A Lot betrayed his tribe, he joined the cannibals..."] = "Depois do Leaks A Lot ter traído a sua tribo, ele juntou-se aos canibais...", -- A_Classic_Fairytale:first_blood ["After the shock caused by the enemy spy, Leaks A Lot and Dense Cloud went hunting to relax."] = "Depois do choque causado pelo espião inimigo, Leaks A Lot e Nuvem Densa foram caçar para relaxar.", -- A_Classic_Fairytale:shadow ["Again with the 'cannibals' thing!"] = "Outra vez com a cena dos 'canibais'!", -- A_Classic_Fairytale:enemy +-- ["Aggressively removes enemy hedgehogs."] = "", -- Construction_Mode ["a Hedgewars challenge"] = "um desafio Hedgewars", -- User_Mission_-_RCPlane_Challenge, User_Mission_-_Rope_Knock_Challenge ["a Hedgewars mini-game"] = "um mini-jogo Hedgewars", -- Space_Invasion, The_Specialists +-- ["a Hedgewars tag game"] = "", -- Mutant +-- ["AHHh, home sweet home. Made it in %d seconds."] = "", -- ClimbHome ["Aiming Practice"] = "Pratica a tua pontaria", --Bazooka, Shotgun, SniperRifle +-- ["Air Attack"] = "", -- Construction_Mode -- ["A leap in a leap"] = "Um salto num salto", -- A_Classic_Fairytale:first_blood ["A little gift from the cyborgs"] = "Um pequeno presente dos cyborgs", -- A_Classic_Fairytale:shadow ["All gone...everything!"] = "Foi-se...tudo!", -- A_Classic_Fairytale:enemy +-- ["Allows free teleportation between other nodes."] = "", -- Construction_Mode +-- ["Allows placement of girders, rubber-bands, mines, sticky mines and barrels."] = "", -- Construction_Mode +-- ["Allows placement of structures."] = "", -- Construction_Mode +-- ["Allows the placement of weapons, utiliites, and health crates."] = "", -- Construction_Mode ["All right, we just need to get to the other side of the island!"] = "Ok, so precisamos de chegar ao outro lado da ilha!", -- A_Classic_Fairytale:journey ["All walls touched!"] = "Todas as paredes alcançadas!", -- WxW -- ["Ammo Depleted!"] = "Munições Esgotadas!", @@ -38,8 +52,11 @@ ["And so they discovered that cyborgs weren't invulnerable..."] = "E então descobriram que os cyborgs não eram invulneráveis...", -- A_Classic_Fairytale:journey ["And where's all the weed?"] = "E onde está a erva toda?", -- A_Classic_Fairytale:dragon ["And you believed me? Oh, god, that's cute!"] = "E tu acreditaste em mim? Ai meu deus, tão fofo!", -- A_Classic_Fairytale:journey --- ["Anno 1032: [The explosion will make a strong push ~ wide range, wont affect hogs close to the target]"] = "", -- Continental_supplies +-- ["Anno 1032: [The explosion will make a strong push ~ Wide range, wont affect hogs close to the target]"] = "", -- Continental_supplies + ["Antarctica"] = "Antártica", -- Continental_supplies +-- ["Antarctic summer: - Will give you one girder/mudball and two sineguns/portals every fourth turn."] = "", -- Continental_supplies +-- ["Area"] = "", -- Continental_supplies ["Are we there yet?"] = "Já chegámos?", -- A_Classic_Fairytale:shadow -- ["Are you accusing me of something?"] = "Estás a acusar-me de alguma coisa?", -- A_Classic_Fairytale:backstab -- ["Are you saying that many of us have died for your entertainment?"] = "Estás a tentar dizer-me que estas quantidade de nós morreu para o teu entertenimento?", -- A_Classic_Fairytale:enemy @@ -59,27 +76,35 @@ ["[Backspace]"] = "[Retrocesso (backspace)]", -- ["Backstab"] = "", -- A_Classic_Fairytale:backstab -- ["Bad Team"] = "", -- User_Mission_-_The_Great_Escape +-- ["Ballgun"] = "", -- Construction_Mode -- ["Bamboo Thicket"] = "", -- ["Barrel Eater!"] = "", -- ["Barrel Launcher"] = "", +-- ["Barrel Placement Mode"] = "", -- Construction_Mode +-- ["Baseball Bat"] = "", -- Construction_Mode -- ["Baseballbat"] = "", -- Continental_supplies ["Bat balls at your enemies and|push them into the sea!"] = "Bate bolas contra os teus|enimigos e empurra-os ao mar!", ["Bat your opponents through the|baskets and out of the map!"] = "Bate os teus adversarios|fora do mapa acertando com eles no cesto!", +-- ["Bazooka"] = "", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 ["Bazooka Training"] = "Treino com Bazuca", -- ["Beep Loopers"] = "", -- A_Classic_Fairytale:queen ["Best laps per team: "] = "Melhores voltas por equipa: ", -- ["Best Team Times: "] = "", -- ["Beware, though! If you are slow, you die!"] = "", -- A_Classic_Fairytale:dragon +-- ["Bio-Filter"] = "", -- Construction_Mode -- ["Biomechanic Team"] = "", -- A_Classic_Fairytale:family +-- ["Birdy"] = "", -- Construction_Mode -- ["Blender"] = "", -- A_Classic_Fairytale:family -- ["Bloodpie"] = "", -- A_Classic_Fairytale:backstab -- ["Bloodrocutor"] = "", -- A_Classic_Fairytale:shadow -- ["Bloodsucker"] = "", -- A_Classic_Fairytale:shadow -- ["Bloody Rookies"] = "", -- 01#Boot_Camp, User_Mission_-_Dangerous_Ducklings, User_Mission_-_Diver, User_Mission_-_Spooky_Tree +-- ["Blowtorch"] = "", -- Construction_Mode, Frenzy +-- ["Blue Team"] = "", -- User_Mission_-_Dangerous_Ducklings -- ["Bone Jackson"] = "", -- A_Classic_Fairytale:backstab -- ["Bonely"] = "", -- A_Classic_Fairytale:shadow + ["BOOM!"] = "BOOM!", ["Boom!"] = "Boom!", - ["BOOM!"] = "BOOM!", ["Boss defeated!"] = "Boss derrotado!", -- ["Boss Slayer!"] = "", -- ["Brain Blower"] = "", -- A_Classic_Fairytale:journey @@ -89,6 +114,7 @@ -- ["Brain Teaser"] = "", -- A_Classic_Fairytale:backstab -- ["Brutal Lily"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil -- ["Brutus"] = "", -- A_Classic_Fairytale:backstab +-- ["Build a fortress and destroy your enemy."] = "", -- Construction_Mode -- ["Build a track and race."] = "Constroi uma pista e compete numa corrida.", -- ["Bullseye"] = "Em cheio", -- A_Classic_Fairytale:dragon -- ["But it proved to be no easy task!"] = "", -- A_Classic_Fairytale:dragon @@ -99,6 +125,7 @@ -- ["But why would they help us?"] = "Mas porque nos ajudariam eles?", -- A_Classic_Fairytale:backstab -- ["But you're cannibals. It's what you do."] = "Mas voçês são canibais. É o que (voçês)fazem.", -- A_Classic_Fairytale:enemy -- ["But you said you'd let her go!"] = "Mas disseste que a deixarias ir!", -- A_Classic_Fairytale:journey +-- ["Cake"] = "", -- Construction_Mode -- ["Call me Beep! Well, 'cause I'm such a nice...person!"] = "Trata-me por Beep! Bem, porque eu sou um---a pessoa tão simpática!", -- A_Classic_Fairytale:family ["Cannibals"] = "Canibais", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:first_blood -- ["Cannibal Sentry"] = "", -- A_Classic_Fairytale:journey @@ -108,8 +135,15 @@ ["Carol"] = "Carol", -- A_Classic_Fairytale:family ["CHALLENGE COMPLETE"] = "DESAFIO COMPLETO", -- User_Mission_-_RCPlane_Challenge ["Change Weapon"] = "Trocar Arma", +-- ["changing range from %i%% to %i%% with period of %i msec"] = "", -- Gravity ["Choose your side! If you want to join the strange man, walk up to him.|Otherwise, walk away from him. If you decide to att...nevermind..."] = "Escolhe o teu lado! Se quiseres juntar-te ao homem estranho, aproxima-te dele! Caso contrario, afastate dele. Se decidires atac...esquece...", -- A_Classic_Fairytale:shadow +-- ["Cleaver"] = "", -- Construction_Mode +-- ["Cleaver Placement Mode"] = "", -- Construction_Mode +-- ["Climber"] = "", -- ClimbHome +-- ["Climb Home"] = "", -- ClimbHome +-- ["Clowns"] = "", -- User_Mission_-_Nobody_Laugh ["Clumsy"] = "Desastrado", +-- ["Cluster Bomb"] = "", -- Construction_Mode ["Cluster Bomb MASTER!"] = "MESTRE da Bomba de Fragmentos!", -- Basic_Training_-_Cluster_Bomb ["Cluster Bomb Training"] = "Treino com Bomba de Fragmentos!", -- Basic_Training_-_Cluster_Bomb -- ["Codename: Teamwork"] = "Nome de código: Trabalho em Equipa", @@ -129,12 +163,19 @@ -- ["Congratulations! You needed only half of time|to eliminate all targets."] = "", -- Basic_Training_-_Cluster_Bomb -- ["Congratulations! You've completed the Rope tutorial! |- Tutorial ends in 10 seconds!"] = "", -- Basic_Training_-_Rope ["Congratulations! You've eliminated all targets|within the allowed time frame."] = "Parabéns! Eliminaste todos os alvos|dentro do tempo limite.", --Bazooka, Shotgun, SniperRifle +-- ["CONSTRUCTION MODE"] = "", -- Construction_Mode +-- ["Construction Station"] = "", -- Construction_Mode -- ["Continental supplies"] = "", -- Continental_supplies -- ["Control pillars to score points."] = "", +-- ["Core"] = "", -- Construction_Mode -- ["Corporationals"] = "", -- A_Classic_Fairytale:queen -- ["Corpsemonger"] = "", -- A_Classic_Fairytale:shadow -- ["Corpse Thrower"] = "", -- A_Classic_Fairytale:epil +-- ["Cost"] = "", -- Construction_Mode +-- ["Crate Placement Tool"] = "", -- Construction_Mode -- ["Crates Left:"] = "", -- User_Mission_-_RCPlane_Challenge +-- ["Cricket time: [Drop a fireable mine! ~ Will work if fired close to your hog & far away from enemy ~ 1 sec]"] = "", -- Continental_supplies +-- ["Current setting is "] = "", -- Gravity ["Cybernetic Empire"] = "Império Cibernético", -- ["Cyborg. It's what the aliens call themselves."] = "Cyborg. É o que os extra terrestres se chamam a eles mesmos(errrr)\autointitulam", -- A_Classic_Fairytale:enemy -- ["Dahmer"] = "", -- A_Classic_Fairytale:backstab @@ -142,15 +183,19 @@ -- ["DAMMIT, ROOKIE! GET OFF MY HEAD!"] = "", ["Dangerous Ducklings"] = "Patinhos perigosos", -- ["Deadweight"] = "", +-- ["Decrease"] = "", -- Continental_supplies -- ["Defeat the cannibals"] = "", -- A_Classic_Fairytale:backstab -- ["Defeat the cannibals!|"] = "", -- A_Classic_Fairytale:united -- ["Defeat the cannibals!|Grenade hint: set the timer with [1-5], aim with [Up]/[Down] and hold [Space] to set power"] = "", -- A_Classic_Fairytale:shadow -- ["Defeat the cyborgs!"] = "", -- A_Classic_Fairytale:enemy +-- ["Defend your core from the enemy."] = "", -- Construction_Mode -- ["Defend yourself!|Hint: You can get tips on using weapons by moving your mouse over them in the weapon selection menu"] = "", -- A_Classic_Fairytale:shadow +-- ["Dematerializes weapons and equipment carried by enemy hedgehogs."] = "", -- Construction_Mode ["Demolition is fun!"] = "Demolir é divertido!", + ["Dense Cloud must have already told them everything..."] = "O Nuvem Densa já lhes deve ter dito tudo...", -- A_Classic_Fairytale:shadow ["Dense Cloud"] = "Nuvem Densa", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united - ["Dense Cloud must have already told them everything..."] = "O Nuvem Densa já lhes deve ter dito tudo...", -- A_Classic_Fairytale:shadow -- ["Depleted Kamikaze!"] = "", +-- ["Desert Eagle"] = "", -- Construction_Mode, A_Space_Adventure:death02 -- ["Destroy him, Leaks A Lot! He is responsible for the deaths of many of us!"] = "", -- A_Classic_Fairytale:first_blood -- ["Destroy invaders to score points."] = "", -- ["Destroy the targets!|Hint: Select the Shoryuken and hit [Space]|P.S. You can use it mid-air."] = "", -- A_Classic_Fairytale:first_blood @@ -169,9 +214,12 @@ -- ["Do you have any idea how valuable grass is?"] = "Tnes alguma ideia do quão aliosa esta erva é?", -- A_Classic_Fairytale:enemy -- ["Do you think you're some kind of god?"] = "Pensas que és\Axas-te algum tipo de deus?", -- A_Classic_Fairytale:enemy -- ["Dragon's Lair"] = "", -- A_Classic_Fairytale:dragon +-- ["Drill Rocket"] = "", -- Construction_Mode -- ["Drills"] = "", -- A_Classic_Fairytale:backstab +-- ["Drill Strike"] = "", -- Construction_Mode -- ["Drone Hunter!"] = "", --- ["Drop a bomb: [drop some heroic wind that will turn into a bomb on impact]"] = "Larga uma bomba: [lança algum horoico vento que se ]", -- Continental_supplies +-- ["Drop a bomb: [Drop some heroic wind that will turn into a bomb on impact]"] = "", -- Continental_supplies + -- ["Drowner"] = "", -- ["Dude, all the plants are gone!"] = "Bacano, os planetas desapareceram todos!", -- A_Classic_Fairytale:family -- ["Dude, can you see Ramon and Spiky?"] = "Bacano, consegues ver o Ramon e o Spiky?", -- A_Classic_Fairytale:journey @@ -181,11 +229,15 @@ -- ["Dude, where are we?"] = "Bacano, onde estamos?", -- A_Classic_Fairytale:backstab -- ["Dude, wow! I just had the weirdest high!"] = "Bacano, wow! Acabei de ter o 'high' mais esquesito de sempre.", -- A_Classic_Fairytale:backstab ["Duration"] = "Duração", -- Continental_supplies --- ["Dust storm: [Deals 20 damage to all enemies in the circle]"] = "Tempestade de areia: [Causa 20 pontos de dano a toros os inimigos dentro no circulo]", -- Continental_supplies +-- ["Dust storm: [Deals 15 damage to all enemies in the circle]"] = "", -- Continental_supplies + +-- ["Dynamite"] = "", -- Construction_Mode +-- ["Each turn is only ONE SECOND!"] = "", -- Frenzy -- ["Each turn you get 1-3 random weapons"] = "Todos os turnos recebes 1-3 armas aleatórias", -- ["Each turn you get one random weapon"] = "Todos os turnos recebes uma arma aleatória", -- ["Eagle Eye"] = "", -- A_Classic_Fairytale:backstab --- ["Eagle Eye: [Blink to the impact ~ one shot]"] = "", -- Continental_supplies +-- ["Eagle Eye: [Blink to the impact ~ One shot]"] = "", -- Continental_supplies + -- ["Ear Sniffer"] = "Snifa ouvidos\orelhas", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:epil -- ["Elderbot"] = "", -- A_Classic_Fairytale:family -- ["Elimate your captor."] = "Elimina o teu raptor.", -- User_Mission_-_The_Great_Escape @@ -208,8 +260,9 @@ -- ["Every single time!"] = "", -- A_Classic_Fairytale:dragon -- ["Everything looks OK..."] = "", -- A_Classic_Fairytale:enemy -- ["Exactly, man! That was my dream."] = "Exactamente, homem! Esse era o meu sonho.", -- A_Classic_Fairytale:backstab +-- ["Extra Damage"] = "", -- Construction_Mode +-- ["Extra Time"] = "", -- Construction_Mode -- ["Eye Chewer"] = "", -- A_Classic_Fairytale:journey --- ["INSANITY"] = "", -- Mutant -- ["Family Reunion"] = "", -- A_Classic_Fairytale:family ["Fastest lap: "] = "Volta mais rápida: ", -- ["Feeble Resistance"] = "", @@ -219,10 +272,11 @@ -- ["Femur Lover"] = "", -- A_Classic_Fairytale:shadow -- ["Fierce Competition!"] = "", -- Space_Invasion ["Fiery Water"] = "Água Flamejante", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united +-- ["Filthy Blue"] = "", -- User_Mission_-_Dangerous_Ducklings ["Find your tribe!|Cross the lake!"] = "Encontra a tua tribo|Atravessa o lago!", -- A_Classic_Fairytale:dragon -- ["Finish your training|Hint: Animations can be skipped with the [Precise] key."] = "Acaba o teu treino|Ajuda: As animações podem ser saltadas com a tecla [Precisão].", -- A_Classic_Fairytale:first_blood + ["Fire"] = "Fogo", --- ["Fire a mine: [Does what it says ~ Cant be dropped close to an enemy ~ 1 sec]"] = "", -- Continental_supplies ["First aid kits?!"] = "Kits de primeiros socorros?!", -- A_Classic_Fairytale:united -- ["First Blood"] = "", -- A_Classic_Fairytale:first_blood -- ["FIRST BLOOD MUTATES"] = "", -- Mutant @@ -232,11 +286,15 @@ ["Flag returned!"] = "Bandeira devolvida!", -- ["Flags, and their home base will be placed where each team ends their first turn."] = "", -- ["Flamer"] = "Azeiteiro", +-- ["Flamethrower"] = "", -- Construction_Mode -- ["Flaming Worm"] = "Minhoca Flamejante", -- A_Classic_Fairytale:backstab --- ["Flare: [fire up some bombs depending on hogs depending on hogs in the circle"] = "", -- Continental_supplies + -- ["Flesh for Brainz"] = "", -- A_Classic_Fairytale:journey +-- ["Flying Saucer"] = "", -- Construction_Mode, Frenzy ["For improved features/stability, play 0.9.18+"] = "Para mais funcionalidades e maior estabilidade, joga 0.9.18+", -- WxW ["Free Dense Cloud and continue the mission!"] = "Liberta o Nuvem Densa e continua a tua missão!", -- A_Classic_Fairytale:journey +-- ["Freezer"] = "", -- Construction_Mode +-- ["FRENZY"] = "", -- Frenzy -- ["Friendly Fire!"] = "Fogo amigável!", -- ["fuel extended!"] = "combustivel aumentado!", -- ["GAME BEGUN!!!"] = "O JOGO COMEÇOU!!!", @@ -246,6 +304,9 @@ ["Game? Was this a game to you?!"] = "Jogo? Isto foi um jogo para ti?!", -- A_Classic_Fairytale:enemy -- ["GasBomb"] = "", -- Continental_supplies -- ["Gas Gargler"] = "", -- A_Classic_Fairytale:queen +-- ["General information"] = "", -- Continental_supplies +-- ["Generates power."] = "", -- Construction_Mode +-- ["Generator"] = "", -- Construction_Mode -- ["Get Dense Cloud out of the pit!"] = "Tira o Nuvem Densa do precipicio(?)", -- A_Classic_Fairytale:journey ["Get on over there and take him out!"] = "Chega-te aqui e acaba com ele!", -- ["Get on the head of the mole"] = "", -- A_Classic_Fairytale:first_blood @@ -256,6 +317,8 @@ -- ["Get your teammates out of their natural prison and save the princess!|Hint: Drilling holes should solve everything.|Hint: It might be a good idea to place a girder before starting to drill. Just saying.|Hint: All your hedgehogs need to be above the marked height!|Hint: Leaks A Lot needs to get really close to the princess!"] = "", -- A_Classic_Fairytale:family ["GG!"] = "GG! (Excelente jogo!)", -- User_Mission_-_Rope_Knock_Challenge -- ["Gimme Bones"] = "", -- A_Classic_Fairytale:backstab +-- ["Girder"] = "", -- Construction_Mode +-- ["Girder Placement Mode"] = "", -- Construction_Mode -- ["Glark"] = "", -- A_Classic_Fairytale:shadow -- ["Goal"] = "Objectivo\Fim", ["GO! GO! GO!"] = "GO! GO! GO!", @@ -272,12 +335,16 @@ -- ["Go surf!"] = "Vai 'surfar'!", -- WxW -- ["GOTCHA!"] = "APANHEI-TE!", -- ["Grab Mines/Explosives"] = "Agarra Minas/Explosivos", +-- ["Grants nearby hogs life-regeneration."] = "", -- Construction_Mode +-- ["Gravity"] = "", -- Gravity -- ["Great choice, Steve! Mind if I call you that?"] = "Excelente escolha, Steve! Importas-te que te chame\trate assim?", -- A_Classic_Fairytale:shadow -- ["Great work! Now hit it with your Baseball Bat! |Tip: You can change weapon with 'Right Click'!"] = Bom trabalho! Agora dá-lhe com o teu bastão de basebal! [Ajuada: Podes trocar de arma com o 'Click Direito'!]"", -- Basic_Training_-_Rope -- ["Great! You will be contacted soon for assistance."] = "", -- A_Classic_Fairytale:shadow --- ["Green lipstick bullet: [Is poisonous]"] = "Batom bala verde: [É venenoso]", -- Continental_supplies + +-- ["Green lipstick bullet: [Poisonous, deals no damage]"] = "", -- Continental_supplies -- ["Greetings, "] = "", -- A_Classic_Fairytale:dragon -- ["Greetings, cloudy one!"] = "", -- A_Classic_Fairytale:shadow +-- ["Grenade"] = "", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 -- ["Grenade Training"] = "Treino com Granadas", -- Basic_Training_-_Grenade -- ["Grenadiers"] = "", -- Basic_Training_-_Grenade -- ["Guys, do you think there's more of them?"] = "Pessoal, axam que ainda há mais?\ha mais deles?", -- A_Classic_Fairytale:backstab @@ -285,22 +352,27 @@ ["Haha!"] = "Haha!", -- A_Classic_Fairytale:united ["Hahahaha!"] = "Hahahaha!", -- ["Haha, now THAT would be something!"] = "Haha, agora ISSO seria espetacular!\é que era!", +-- ["Hammer"] = "", -- Construction_Mode, Continental_supplies -- ["Hannibal"] = "Hannibal", -- A_Classic_Fairytale:epil +-- [" Hapless Hogs left!"] = " Ouriços Desafortunados restantes!", -- ["Hapless Hogs"] = "Ouriços Desafortunados", --- [" Hapless Hogs left!"] = " Ouriços Desafortunados restantes!", -- [" HAS MUTATED"] = " MUTOU", -- Mutant -- ["Hatless Jerry"] = "", -- A_Classic_Fairytale:queen -- ["Have no illusions, your tribe is dead, indifferent of your choice."] = "Não tenhas ilusoes, a tua tribo está morta, indiferentes à tua escolha.", -- A_Classic_Fairytale:shadow -- ["Have we ever attacked you first?"] = "Alguma vez te atacamos primeiro?", -- A_Classic_Fairytale:enemy +-- ["Healing Station"] = "", -- Construction_Mode +-- ["Health Crate Placement Mode"] = "", -- Construction_Mode ["Health crates extend your time."] = "As caixas de vida prolongam o teu tempo.", -- ["Heavy"] = "", -- ["Heavy Cannfantry"] = "", -- A_Classic_Fairytale:united -- ["Hedge-cogs"] = "Engrenagens-ouriço", -- A_Classic_Fairytale:enemy --- ["Hedgehog projectile: [fire your hog like a Sticky Bomb]"] = "", -- Continental_supplies +-- ["Hedgehog projectile: [Fire your hog like a Sticky Bomb]"] = "", -- Continental_supplies + ["Hedgewars-Basketball"] = "Hedgewars-Basquetebol", ["Hedgewars-Knockball"] = "Hedgewars-Knockball", -- ["Hedgibal Lecter"] = "Hedgibal Lecter", -- A_Classic_Fairytale:backstab -- ["Heh, it's not that bad."] = "Heh, não é assim tão mau.\Podia ser pior.", +-- ["Hellish Handgrenade"] = "", -- Construction_Mode ["Hello again, "] = "Olá novamente, ", -- A_Classic_Fairytale:family ["Help me, Leaks!"] = "Ajuda-me, Leaks!", -- A_Classic_Fairytale:journey ["Help me, please!!!"] = "Ajuda-me, por favor!!!", -- A_Classic_Fairytale:journey @@ -332,6 +404,7 @@ -- ["Hogminator"] = "", -- A_Classic_Fairytale:family -- ["Hogs in sight!"] = "", -- Continental_supplies -- ["HOLY SHYTE!"] = "", -- Mutant +-- ["Homing Bee"] = "", -- Construction_Mode -- ["Honest Lee"] = "", -- A_Classic_Fairytale:enemy ["Hooray!"] = "Hurra!", -- ["Hostage Situation"] = "", -- A_Classic_Fairytale:family @@ -387,6 +460,7 @@ ["I'm not sure about that!"] = "Não tenho a certeza quanto a isso!", -- A_Classic_Fairytale:united ["Impressive...you are still dry as the corpse of a hawk after a week in the desert..."] = "Impressionante...ainda estás seco tal e qual um cadáver de um falcão depois de uma semana no deserto...", -- A_Classic_Fairytale:first_blood ["I'm so scared!"] = "Tenho tanto medo!", -- A_Classic_Fairytale:united +-- ["Increase"] = "", -- Continental_supplies ["Incredible..."] = "Incrível...", -- A_Classic_Fairytale:shadow ["I need to find the others!"] = "Preciso de encontrar os outros!", -- A_Classic_Fairytale:backstab ["I need to get to the other side of this island, fast!"] = "Preciso de chegar ao outro lado da ilha, rápido!", -- A_Classic_Fairytale:journey @@ -395,12 +469,14 @@ ["I need to warn the others."] = "Preciso de avisar os outros.", -- A_Classic_Fairytale:backstab ["In fact, you are the only one that's been acting strangely."] = "Na realidade, és o único que se tem comportado de forma estranha.", -- A_Classic_Fairytale:backstab ["In order to get to the other side, you need to collect the crates first.|"] = "De forma a conseguir chegar ao outro lado, tens primeiro de obter todas as caixas.", -- A_Classic_Fairytale:dragon +-- ["INSANITY"] = "", -- Mutant ["Instructor"] = "Instrutor", -- 01#Boot_Camp, User_Mission_-_Dangerous_Ducklings ["Interesting idea, haha!"] = "Interessante ideia, haha!", -- A_Classic_Fairytale:enemy ["Interesting! Last time you said you killed a cannibal!"] = "Interessante! Da ultima vez disseste que tinhas morto um canibal!", -- A_Classic_Fairytale:backstab -- ["In the meantime, take these and return to your \"friend\"!"] = "Entretanto, pega\toma isto e volta para o teu \"amigo\"!", -- A_Classic_Fairytale:shadow ["invaders destroyed"] = "invasores destruidos", ["Invasion"] = "Invasão", -- A_Classic_Fairytale:united +-- ["Invulnerable"] = "", -- Construction_Mode ["I saw it with my own eyes!"] = "Eu vi-o com os meus próprios olhos!", -- A_Classic_Fairytale:shadow ["I see..."] = "Estou a ver...", -- A_Classic_Fairytale:shadow -- ["I see you have already taken the leap of faith."] = "Vejo que ja deste um salto de fé", -- A_Classic_Fairytale:first_blood @@ -415,8 +491,8 @@ -- ["It is called 'Hogs of Steel'."] = "É chamado 'Hogs of Steel'.", -- A_Classic_Fairytale:enemy ["It is time to practice your fighting skills."] = "Está na hora de praticar os habilidades em combate.", -- A_Classic_Fairytale:first_blood ["It must be a childhood trauma..."] = "Deve ser um trauma de criança...", -- A_Classic_Fairytale:family + ["It must be the aliens' deed."] = "Devem ser obra dos alienígenas!", -- A_Classic_Fairytale:backstab ["It must be the aliens!"] = "Devem ser os alienígenas!", -- A_Classic_Fairytale:backstab - ["It must be the aliens' deed."] = "Devem ser obra dos alienígenas!", -- A_Classic_Fairytale:backstab ["It must be the cyborgs again!"] = "Devem ser os cyborgs novamente!", -- A_Classic_Fairytale:enemy -- ["I told you, I just found them."] = "Eu disse-te que os tinha acabado de encontrar.\que simplesmente os encontrei.", -- A_Classic_Fairytale:backstab ["It's a good thing SUDDEN DEATH is 99 turns away..."] = "Ainda bem que ainda faltam 99 turnos para MORTE SÚBITA...", @@ -443,6 +519,7 @@ ["Just kidding, none of you have died!"] = "Estou só a brincar, nenhum de vocês morreu!", -- A_Classic_Fairytale:enemy -- ["Just on a walk."] = "Só a passear\dar um passeio.", -- A_Classic_Fairytale:united ["Just wait till I get my hands on that trauma! ARGH!"] = "Espera até eu pôr as mãos naquele trauma! ARGH!", -- A_Classic_Fairytale:family +-- ["Kamikaze"] = "", -- Construction_Mode ["Kamikaze Expert!"] = "Kamikaze profissional!", ["Keep it up!"] = "Continua assim!", ["Kerguelen"] = "", -- Continental_supplies @@ -452,15 +529,18 @@ ["Kill the aliens!"] = "Mata os alienígenas!", -- A_Classic_Fairytale:dragon ["Kill the cannibal!"] = "Destrói o canibal!", -- A_Classic_Fairytale:first_blood -- ["Kill the traitor...or spare his life!|Kill him or press [Precise]!"] = "Acaba com o traídor...ou poupa a sua vida!|Mata-o ou pressiona [Precisão]!", -- A_Classic_Fairytale:backstab +-- ["Land Sprayer"] = "", -- Construction_Mode +-- ["Laser Sight"] = "", -- Construction_Mode -- ["Last Target!"] = "Ultimo Alvo!", +-- ["Leaderbot"] = "", -- A_Classic_Fairytale:queen -- ["Leader"] = "Lider", -- A_Classic_Fairytale:enemy --- ["Leaderbot"] = "", -- A_Classic_Fairytale:queen - ["Leaks A Lot"] = "Leaks A Lot", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:first_blood, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united -- ["Leaks A Lot, depressed for killing his loved one, failed to save the village..."] = "O Leaks A Lot, deprimido por ter morto a sua amada, não conseguiu salvar a aldeia...", -- A_Classic_Fairytale:journey ["Leaks A Lot gave his life for his tribe! He should have survived!"] = "Leaks A Lot deu a sua vida pela tribo! Ele devia ter sobrevivido!", -- A_Classic_Fairytale:first_blood + ["Leaks A Lot"] = "Leaks A Lot", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:first_blood, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united ["Leaks A Lot must survive!"] = "Leaks A Lot tem de sobreviver!", -- A_Classic_Fairytale:journey -- ["Led Heart"] = "", -- A_Classic_Fairytale:queen ["Lee"] = "Lee", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen +-- ["left shift"] = "", -- Continental_supplies ["[Left Shift]"] = "[Shift Esquerdo]", ["Let a Continent provide your weapons!"] = "Deixa um Continente fornecer-vos armamento!", -- Continental_supplies -- ["Let me test your skills a little, will you?"] = "Pemite-me testar as tuas habilidades um pouco\por um bocadinho.<, ok?>", -- A_Classic_Fairytale:journey @@ -471,41 +551,56 @@ -- ["Let them have a taste of my fury!"] = "Deixa-os provar a minha fúria!", -- A_Classic_Fairytale:backstab ["Let us help, too!"] = "Deixa-nos ajudar também!", -- A_Classic_Fairytale:backstab -- ["Light Cannfantry"] = "", -- A_Classic_Fairytale:united +-- ["Limburger"] = "", -- Construction_Mode ["Listen up, maggot!!"] = "Ouvem bem, verme!!", -- ["Little did they know that this hunt will mark them forever..."] = "Nunca eles imaginariam que esta caça os marcaria para sempre...", -- A_Classic_Fairytale:shadow -- ["Lively Lifeguard"] = "", --- ["Lonely Cries: [Rise the water if no hog is in the circle and deal 1 damage to all hogs]"] = "Choros Solitarios: [Aumente o nível da água]", -- Continental_supplies + +-- ["Lonely Cries: [Rise the water if no hog is in the circle and deal 7 damage to all enemy hogs]"] = "", -- Continental_supplies +-- ["Lonely Hog"] = "", -- ClimbHome ["Look, I had no choice!"] = "Olha, eu não tive escolha!", -- A_Classic_Fairytale:backstab -- ["Look out! There's more of them!"] = "Cuidado! Existem mais!", -- A_Classic_Fairytale:backstab -- ["Look out! We're surrounded by cannibals!"] = "Cuidado! Estamos rodeados de cabinais!", -- A_Classic_Fairytale:enemy -- ["Looks like the whole world is falling apart!"] = "", -- A_Classic_Fairytale:enemy +-- ["Low Gravity"] = "", -- Construction_Mode, Frenzy -- ["Luckily, I've managed to snatch some of them."] = "Por sorte, consegui alguns deles.", -- A_Classic_Fairytale:united ["LUDICROUS KILL"] = "LUDICROUS KILL", -- Mutant +-- ["Made it!"] = "", -- ClimbHome +-- ["- Massive weapon bonus on first turn"] = "", -- Continental_supplies -- ["May the spirits aid you in all your quests!"] = "", -- A_Classic_Fairytale:backstab -- ["Medicine: [Fire some exploding medicine that will heal all hogs effected by the explosion]"] = "", -- Continental_supplies ["MEGA KILL"] = "MEGA KILL", -- Mutant -- ["Meiwes"] = "", -- A_Classic_Fairytale:backstab -- ["Mindy"] = "", -- A_Classic_Fairytale:united +-- ["Mine"] = "", -- Construction_Mode, Frenzy -- ["Mine Deployer"] = "", -- ["Mine Eater!"] = "", +-- ["Mine Placement Mode"] = "", -- Construction_Mode ["|- Mines Time:"] = "|- Tempo das minas:", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork +-- ["Mine Strike"] = "", -- Construction_Mode ["MISSION FAILED"] = "MISSÃO FALHADA", -- User_Mission_-_Dangerous_Ducklings, User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork ["MISSION SUCCESSFUL"] = "MISSÃO COMPLETA", -- User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork ["MISSION SUCCESS"] = "MISSÃO COMPLETA", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork +-- ["Molotov Cocktail"] = "", -- Construction_Mode ["Molotov"] = "", -- Continental_supplies ["MONSTER KILL"] = "MONSTER KILL", -- Mutant ["More Natives"] = "Mais Nativos", -- A_Classic_Fairytale:epil +-- ["Mortar"] = "", -- Construction_Mode, A_Space_Adventure:death02 ["Movement: [Up], [Down], [Left], [Right]"] = "Movimento: [Cima], [Baixo], [Esquerda], [Direita]", +-- ["Mudball"] = "", -- Construction_Mode -- ["Multi-shot!"] = "Multiplo-tiro!", -- ["Muriel"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen -- ["Muscle Dissolver"] = "", -- A_Classic_Fairytale:shadow ["-------"] = "-------", -- Mutant +-- ["Mutant"] = "", -- Mutant -- ["Nade Boy"] = "", -- Basic_Training_-_Grenade +-- ["Nameless Heroes"] = "", ["Name"] = "Nome", -- A_Classic_Fairytale:queen --- ["Nameless Heroes"] = "", -- ["Nancy Screw"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:queen +-- ["Napalm"] = "", -- Construction_Mode -- ["Napalm rocket: [Fire a bomb with napalm!]"] = "", -- Continental_supplies -- ["Natives"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:first_blood, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united +-- ["Naughty Ninja"] = "", -- User_Mission_-_Dangerous_Ducklings -- ["New Barrels Per Turn"] = "", -- ["NEW CLAN RECORD: "] = "", ["NEW fastest lap: "] = "NOVA volta recorde: ", @@ -516,6 +611,7 @@ ["Nice work, "] = "Bom trabalho, ", -- A_Classic_Fairytale:dragon ["Nice work!"] = "Bom trabalho!", -- A_Classic_Fairytale:enemy -- ["Nilarian"] = "", -- A_Classic_Fairytale:queen +-- ["Nobody Laugh"] = "", -- User_Mission_-_Nobody_Laugh ["No, I came back to help you out..."] = "Não, voltei para te ajudar...", -- A_Classic_Fairytale:shadow -- ["No...I wonder where they disappeared?!"] = "Não... Pegunto-me para onde desapareceram?!", -- A_Classic_Fairytale:journey -- ["Nom-Nom"] = "", -- A_Classic_Fairytale:journey @@ -523,6 +619,7 @@ -- ["Nope. It was one fast mole, that's for sure."] = "Não. Mas foi uma toupeira muito rápida de certeza.", -- A_Classic_Fairytale:shadow ["No! Please, help me!"] = "Não! Por favor, ajuda-me!", -- A_Classic_Fairytale:journey ["NORMAL"] = "NORMAL", -- Continental_supplies +-- ["Normal players can only score points by killing the mutant."] = "", -- Mutant ["North America"] = "América do Norte", -- Continental_supplies -- ["Not all hogs are born equal."] = "Nem todos os ouriços nascem iguais\da mesma maneira.", -- Highlander -- ["NOT ENOUGH WAYPOINTS"] = "", @@ -535,12 +632,13 @@ ["No. Where did he come from?"] = "Não. De onde raio é que ele apareceu?", -- A_Classic_Fairytale:shadow ["Now how do I get on the other side?!"] = "Agora, como chego ao outro lado?!", -- A_Classic_Fairytale:dragon -- ["No. You and the rest of the tribe are safer there!"] = "", -- A_Classic_Fairytale:backstab +-- ["Object Placement Tool"] = "", -- Construction_Mode -- ["Obliterate them!|Hint: You might want to take cover..."] = "", -- A_Classic_Fairytale:shadow ["Obstacle course"] = "Pista de obstáculos", -- A_Classic_Fairytale:dragon ["Of course I have to save her. What did I expect?!"] = "Claro que tenho de a salvar. Estavas à espera do quê?!", -- A_Classic_Fairytale:family -- ["OH, COME ON!"] = "OH, VÁ LÁ!", -- A_Classic_Fairytale:journey + ["Oh, my! This is even more entertaining than I've expected!"] = "Uau! Isto é mais interessante do que eu esperava!", -- A_Classic_Fairytale:backstab ["Oh, my!"] = "Uau!", -- A_Classic_Fairytale:first_blood - ["Oh, my! This is even more entertaining than I've expected!"] = "Uau! Isto é mais interessante do que eu esperava!", -- A_Classic_Fairytale:backstab ["Oh no! Just try again!"] = "Oh não! Tenta novamente!", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork -- ["Oh no, not "] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united ["Oh no! Time's up! Just try again."] = "Oh não! Terminou o tempo! Tenta novamente.", --Bazooka, Shotgun, SniperRifle @@ -551,21 +649,29 @@ -- ["Once upon a time, on an island with great natural resources, lived two tribes in heated conflict..."] = "Era uma vez, numa ilha de grandes recursos naturais, viviam duas tribos com um profundo conflituo...", -- A_Classic_Fairytale:first_blood ["ONE HOG PER TEAM! KILLING EXCESS HEDGES"] = "UM OURIÇO POR EQUIPA! A REMOVER OS OURIÇOS EM EXCESSO", -- Mutant -- ["One tribe was peaceful, spending their time hunting and training, enjoying the small pleasures of life..."] = "", -- A_Classic_Fairytale:first_blood +-- ["on Skip"] = "", -- Continental_supplies ["Oops...I dropped them."] = "Oops...deixei-os cair.", -- A_Classic_Fairytale:united ["Open that crate and we will continue!"] = "Abre a caixa e podemos prosseguir!", -- A_Classic_Fairytale:first_blood ["Operation Diver"] = "Operação Mergulho", ["Opposing Team: "] = "Equipa adversária", +-- ["or 'g=50, g2=150, period=4000' for gravity changing|from 50 to 150 and back with period of 4000 msec"] = "", -- Gravity -- ["Orlando Boom!"] = "", -- A_Classic_Fairytale:queen +-- ["Other kills don't give you points."] = "", -- Mutant ["Ouch!"] = "Ouch!", -- User_Mission_-_Rope_Knock_Challenge ["Our tribe, our beautiful island!"] = "A nossa tribo, a nossa bela ilha!", -- A_Classic_Fairytale:enemy ["Parachute"] = "Pára-quedas", -- Continental_supplies ["Pathetic Hog #%d"] = "Ouriço patético #%d", -- ["Pathetic Resistance"] = "Pátetica Resistencia", -- User_Mission_-_Bamboo_Thicket, User_Mission_-_Newton_and_the_Hammock +-- ["Penguin roar: [Deal 15 damage + 15% of your hogs health to all hogs around you and get 2/3 back]"] = "", -- Continental_supplies ["Perfect! Now try to get the next crate without hurting yourself!"] = "Perfeito! Agora tenta obter a proxima caixa sem te aleijares!", -- A_Classic_Fairytale:first_blood -- ["Per-Hog Ammo"] = "Armamento por-Ouriço", --- ["- Per team weapons|- 9 weaponschemes|- Unique new weapons| |Select continent first round with the Weapon Menu or by ([switch/tab]=Increase,[precise/left shift]=Decrease) on Skip|Some weapons have a second option. Find them with [switch/tab]"] = "", -- Continental_supplies +-- ["Personal Portal Device"] = "", -- Construction_Mode + +-- ["Per team weapons"] = "", -- Continental_supplies ["Pfew! That was close!"] = "Ufa! Foi por um triz.", -- A_Classic_Fairytale:shadow --- ["Piñata bullet: [Contains some sweet candy!]"] = "Bala pinhata: [Contem goluzeimas\doces!]", -- Continental_supplies +-- ["Piano Strike"] = "", -- Construction_Mode +-- ["Pickhammer"] = "", -- Construction_Mode + -- ["Pings left:"] = "", -- Space_Invasion -- ["Place more waypoints using the 'Air Attack' weapon."] = "", -- ["Planes Used:"] = "", -- User_Mission_-_RCPlane_Challenge @@ -576,14 +682,18 @@ -- ["Please, stop releasing your \"smoke signals\"!"] = "", -- A_Classic_Fairytale:shadow -- ["Point Blank Combo!"] = "", -- Space_Invasion -- ["points"] = "", -- Control, Space_Invasion +-- ["POINTS"] = "", -- Mutant ["Poison"] = "Poison", +-- ["Population"] = "", -- Continental_supplies -- ["Portal hint: one goes to the destination, and one is the entrance.|"] = "", -- A_Classic_Fairytale:dragon -- ["Portal mission"] = "", -- portal ["Power Remaining"] = "Energia Restante", ["Prepare yourself"] = "Prepara-te!", +-- ["presice"] = "", -- Continental_supplies ["Press [Enter] to accept this configuration."] = "Pressiona [Enter] para aceitar esta configuração.", -- WxW ["Press [Left] or [Right] to move around, [Enter] to jump"] = "Pressiona [Esquerda] ou [Direita] para te moveres, [Enter] para saltar", -- A_Classic_Fairytale:first_blood -- ["Press [Precise] to skip intro"] = "Pressiona [] para saltar a introdução", +-- ["Prestigious Pilot"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Private Novak"] = "", -- Basic_Training_-_Cluster_Bomb -- ["Protect yourselves!|Grenade hint: set the timer with [1-5], aim with [Up]/[Down] and hold [Space] to set power"] = "", -- A_Classic_Fairytale:shadow -- ["Race complexity limit reached."] = "", @@ -592,26 +702,40 @@ -- ["Radar Ping"] = "", -- Space_Invasion -- ["Raging Buffalo"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united -- ["Ramon"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow +-- ["random in range from %i%% to %i%% with period of %i msec"] = "", -- Gravity +-- ["RC Plane"] = "", -- Construction_Mode -- ["RC PLANE TRAINING"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Really?! You thought you could harm me with your little toys?"] = "A SÉRIO?! Pensavas que me podias fazer mal com os teus pequenos brinquedos?", -- A_Classic_Fairytale:shadow +-- ["Reflector Shield"] = "", -- Construction_Mode +-- ["Reflects enemy projectiles."] = "", -- Construction_Mode -- ["Regurgitator"] = "", -- A_Classic_Fairytale:backstab -- ["Reinforcements"] = "", -- A_Classic_Fairytale:backstab -- ["Remember: The rope only bend around objects, |if it doesn't hit anything it's always stright!"] = "", -- Basic_Training_-_Rope -- ["Remember this, pathetic animal: when the day comes, you will regret your blind loyalty!"] = "", -- A_Classic_Fairytale:shadow +-- ["REMOVED"] = "", -- Continental_supplies +-- ["Respawner"] = "", -- Construction_Mode +-- ["Resurrector"] = "", -- Construction_Mode +-- ["Resurrects dead hedgehogs."] = "", -- Construction_Mode [" - Return the enemy flag to your base to score | - First team to 3 captures wins | - You may only score when your flag is in your base | - Hogs will drop the flag if killed, or drowned | - Dropped flags may be returned or recaptured | - Hogs respawn when killed"] = " - Traz a bandeira inimiga para tua base | - A primeira equipa a captura-la 3 vezes ganha | - Apenas podes marcar quando a tua bandeira está na tua base | - Os ouriços largam a bandeira se morrerem ou se afogarem | - As bandeiras abandonadas podem ser devolvidas ou recapturadas | - Os ouriços mortos ressuscitam", -- ["Return to Leaks A Lot! If you get stuck, press [Precise] to try again!"] = "", -- A_Classic_Fairytale:shadow -- ["Righteous Beard"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:first_blood, A_Classic_Fairytale:queen, A_Classic_Fairytale:united +-- ["Rope"] = "", -- Construction_Mode -- ["ROPE-KNOCKING"] = "", -- User_Mission_-_Rope_Knock_Challenge +-- ["Rope to safety"] = "", -- ClimbHome -- ["Rope Training"] = "", -- Basic_Training_-_Rope -- ["Rot Molester"] = "", -- A_Classic_Fairytale:shadow -- ["Round Limit:"] = "", -- ["Round Limit"] = "", -- ["Rounds Complete: "] = "Rondas Completas: ", -- ["Rounds Complete"] = "Rondas Completas", +-- ["Rubber Band"] = "", -- Construction_Mode +-- ["Rubber Placement Mode"] = "", -- Construction_Mode +-- ["RULES"] = "", -- Frenzy, Mutant ["RULES OF THE GAME [Press ESC to view]"] = "REGRAS DE JOGO [Pressiona ESC para as visualizar]", -- ["Rusty Joe"] = "Joe Emferrujado", -- A_Classic_Fairytale:queen -- ["s|"] = "", --- ["Sabotage: [Sabotage all hogs in the circle and deal ~10 dmg]"] = "", -- Continental_supplies +-- ["Sabotage/Flare: [Sabotage all hogs in the circle and deal ~1 dmg OR Fire a cluster up into the air]"] = "", -- Continental_supplies + -- ["Salivaslurper"] = "", -- A_Classic_Fairytale:united -- ["Salvation"] = "Salvação", -- A_Classic_Fairytale:family -- ["Salvation was one step closer now..."] = "", -- A_Classic_Fairytale:dragon @@ -621,18 +745,21 @@ -- ["Save the princess! All your hogs must survive!|Hint: Kill the cyborgs first! Use the ammo very carefully!|Hint: You might want to spare a girder for cover!"] = "", -- A_Classic_Fairytale:family -- ["Save the princess by collecting the crate in under 12 turns!"] = "", -- A_Classic_Fairytale:journey -- ["Scalp Muncher"] = "", -- A_Classic_Fairytale:backstab + ["SCORE"] = "RESULTADO", ["Score"] = "Resultado", -- Mutant - ["SCORE"] = "RESULTADO", --- ["Scream from a Walrus: [Deal 20 damage + 10% of your hogs health to all hogs around you and get half back]"] = "", -- Continental_supplies + ["sec"] = "seg", -- CTF_Blizzard, TrophyRace, Basic_Training_-_Bazooka, Basic_Training_-_Shotgun, Basic_Training_-_Sniper_Rifle, User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork, Capture_the_Flag ["Seduction"] = "Sedução", -- Continental_supplies -- ["Seems like every time you take a \"walk\", the enemy find us!"] = "", -- A_Classic_Fairytale:backstab -- ["See that crate farther on the right?"] = "", -- A_Classic_Fairytale:first_blood ["See ya!"] = "Chau!", -- ["Segmentation Paul"] = "", -- A_Classic_Fairytale:dragon +-- ["Select continent first round with the Weapon Menu or by"] = "", -- Continental_supplies ["Select continent!"] = "Seleciona o continente!", -- Continental_supplies -- ["Select difficulty: [Left] - easier or [Right] - harder"] = "Seleciona a dificuldade: [Esquerda] - facil ou [Direita] - dificil", -- A_Classic_Fairytale:first_blood ["selected!"] = "seleccionado!", +-- ["Set period to negative value for random gravity"] = "", -- Gravity +-- ["Setup:|'g=150', where 150 is 150% of normal gravity"] = "", -- Gravity ["... share your beauty with the world every morning, my princess!"] = "... partilha a tua beleza com o mundo todas as manhãs, minha princesa!", -- A_Classic_Fairytale:journey ["She's behind that tall thingy."] = "Ela está atráz daquela coisa alta.", -- A_Classic_Fairytale:family -- ["Shield boosted! +30 power"] = "Escudo reparado\aumentado! +30 energia (-unconfirmed)", @@ -643,16 +770,21 @@ ["Shield OFF:"] = "Escudo DESLIGADO:", ["Shield ON:"] = "Escudo LIGADO:", -- ["Shield Seeker!"] = "", +-- ["Shoryuken"] = "", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 ["Shotgun"] = "Caçadeira", -- Continental_supplies ["Shotgun Team"] = "Caçadores", ["Shotgun Training"] = "Treino com Caçadeira", -- ["shots remaining."] = "tiros restantes.", -- ["Silly"] = "", +-- ["SineGun"] = "", -- Construction_Mode -- ["Sinky"] = "", -- ["Sirius Lee"] = "", -- A_Classic_Fairytale:enemy ["%s is out and Team %d|scored a penalty!| |Score:"] = "%s está fora e a equipa %d|perde um ponto!| |Pontuação:", -- Basketball, Knockball ["%s is out and Team %d|scored a point!| |Score:"] = "%s está fora e a equipa %d|soma um ponto!| |Pontuação:", -- Basketball, Knockball -- ["Slippery"] = "Escorregadio", -- A_Classic_Fairytale:journey +-- ["Slot"] = "", -- Frenzy +-- ["Slot keys save time! (F1-F10 by default)"] = "", -- Frenzy +-- ["SLOTS"] = "", -- Frenzy -- ["Smith 0.97"] = "", -- A_Classic_Fairytale:enemy -- ["Smith 0.98"] = "", -- A_Classic_Fairytale:enemy -- ["Smith 0.99a"] = "", -- A_Classic_Fairytale:enemy @@ -664,6 +796,7 @@ ["Sniper Training"] = "Treino com Sniper", ["Sniperz"] = "Sniperz", ["So humiliating..."] = "Tão humilhante...", -- A_Classic_Fairytale:first_blood +-- ["Some weapons have a second option. Find them with"] = "", -- Continental_supplies ["South America"] = "América do Sul", -- Continental_supplies ["So? What will it be?"] = "Então? O que vai ser?", -- A_Classic_Fairytale:shadow -- ["Spawn the crate, and attack!"] = "Faz aparecer a caixa, e ataca!", -- WxW @@ -672,26 +805,44 @@ -- ["Spleenlover"] = "", -- A_Classic_Fairytale:united -- ["Sponge"] = "Esponja", -- ["Spooky Tree"] = "", +-- ["Sprite Placement Mode"] = "", -- Construction_Mode +-- ["Sprite Testing Mode"] = "", -- Construction_Mode ["s"] = "s", -- GaudyRacer, Space_Invasion -- ["STATUS UPDATE"] = "", -- GaudyRacer, Space_Invasion -- ["Steel Eye"] = "Olho de Ferro", -- A_Classic_Fairytale:queen -- ["Step By Step"] = "Passo a Passo", -- A_Classic_Fairytale:first_blood ["Steve"] = "Steve", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen -- ["Sticky Mine"] = "", -- Continental_supplies +-- ["Sticky Mine Placement Mode"] = "", -- Construction_Mode -- ["Stronglings"] = "", -- A_Classic_Fairytale:shadow - ["Structure"] = "Estrutura", -- Continental_supplies + +-- ["Structure Placement Mode"] = "", -- Construction_Mode +-- ["Structure Placement Tool"] = "", -- Construction_Mode +-- ["Sundaland"] = "", -- Continental_supplies -- ["Super Weapons"] = "", -- WxW +-- ["Support Station"] = "", -- Construction_Mode -- ["Surf Before Crate"] = "", -- WxW -- ["Surfer! +15 points!"] = "", -- Space_Invasion -- ["Surfer!"] = "", -- WxW -- ["Survive!|Hint: Cinematics can be skipped with the [Precise] key."] = "", -- A_Classic_Fairytale:shadow -- ["Swing, Leaks A Lot, on the wings of the wind!"] = "", -- A_Classic_Fairytale:first_blood +-- ["switch"] = "", -- Continental_supplies -- ["Switched to "] = "", +-- ["Switch Hog"] = "", -- Construction_Mode -- ["Syntax Errol"] = "", -- A_Classic_Fairytale:dragon +-- ["tab"] = "", -- Continental_supplies +-- ["Tagging Mode"] = "", -- Construction_Mode -- ["Talk about mixed signals..."] = "", -- A_Classic_Fairytale:dragon +-- ["Tardis"] = "", -- Construction_Mode +-- ["Target Placement Mode"] = "", -- Construction_Mode ["Team %d: "] = "Equipa %d: ", -- ["Team Scores"] = "Pontuações Equipa", -- Control, Space_Invasion +-- ["Teleporation Node"] = "", -- Construction_Mode +-- ["Teleportation Mode"] = "", -- Construction_Mode +-- ["Teleportation Node"] = "", -- Construction_Mode +-- ["Teleport"] = "", -- Construction_Mode, Frenzy -- ["Teleport hint: just use the mouse to select the destination!"] = "Ajuda com o Teleporte: usa o rato para selecionar o teu destino!", -- A_Classic_Fairytale:dragon +-- ["Teleport Unsuccessful. Please teleport within a clan teleporter's sphere of influence."] = "", -- Construction_Mode ["Thanks!"] = "Obrigada!", -- A_Classic_Fairytale:family ["Thank you, my hero!"] = "Obrigada, meu herói!", -- A_Classic_Fairytale:family ["Thank you, oh, thank you, Leaks A Lot!"] = "Obrigada, oh, obrigada, Leaks A Lot!", -- A_Classic_Fairytale:journey @@ -708,6 +859,7 @@ ["That was pointless."] = "Isso foi completamente desnecessario.", -- ["The answer is...entertaintment. You'll see what I mean."] = "A resposta é...entertenimento. Já vais perceber ao que me refiro\quero dizer.", -- A_Classic_Fairytale:backstab -- ["The anti-portal zone is all over the floor, and I have nothing to kill him...Droping something could hurt him enough to kill him..."] = "", -- portal +-- ["The Bottom Feeder can score points by killing anyone."] = "", -- Mutant -- ["The Bull's Eye"] = "", -- A_Classic_Fairytale:first_blood -- ["The caves are well hidden, they won't find us there!"] = "", -- A_Classic_Fairytale:united -- ["The Crate Frenzy"] = "", -- A_Classic_Fairytale:first_blood @@ -717,20 +869,26 @@ -- ["The Enemy Of My Enemy"] = "", -- A_Classic_Fairytale:enemy -- ["The First Blood"] = "", -- A_Classic_Fairytale:first_blood -- ["The First Encounter"] = "", -- A_Classic_Fairytale:shadow +-- ["The first player to kill someone becomes the Mutant."] = "", -- Mutant ["The flag will respawn next round."] = "A bandeira ira reaparecer no próximo turno.", -- ["The food bites back"] = "", -- A_Classic_Fairytale:backstab -- ["The giant umbrella from the last crate should help break the fall."] = "O guarda-chuva gigante que estava na ultima caixa deve ajudar a amparar a tua queda.", -- A_Classic_Fairytale:first_blood -- ["The Great Escape"] = "", -- User_Mission_-_The_Great_Escape +-- ["The Great Hog in the sky sees your sadness and grants you a boon."] = "", -- Construction_Mode -- ["The guardian"] = "O guardião", -- A_Classic_Fairytale:shadow -- ["The Individualist"] = "O Individualista", -- A_Classic_Fairytale:shadow -- ["Their buildings were very primitive back then, even for an uncivilised island."] = "", -- A_Classic_Fairytale:united -- ["The Journey Back"] = "", -- A_Classic_Fairytale:journey -- ["The Leap of Faith"] = "", -- A_Classic_Fairytale:first_blood -- ["The Moonwalk"] = "", -- A_Classic_Fairytale:journey +-- ["The Mutant has super-weapons and a lot of health."] = "", -- Mutant +-- ["The Mutant loses health quickly if he doesn't keep scoring kills."] = "", -- Mutant -- ["The Nameless One"] = "", -- ["The next one is pretty hard! |Tip: You have to do multiple swings!"] = "", -- Basic_Training_-_Rope -- ["Then how do they keep appearing?"] = "", -- A_Classic_Fairytale:shadow -- ["The other one were all cannibals, spending their time eating the organs of fellow hedgehogs..."] = "", -- A_Classic_Fairytale:first_blood +-- ["The player with least points (or most deaths) becomes the Bottom Feeder."] = "", -- Mutant +-- ["There are a variety of structures available to aid you."] = "", -- Construction_Mode -- ["There must be a spy among us!"] = "", -- A_Classic_Fairytale:backstab -- ["There's more of them? When did they become so hungry?"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united -- ["There's nothing more satisfying for me than seeing you share your beauty with the world every morning, my princess!"] = "", -- A_Classic_Fairytale:journey @@ -786,7 +944,7 @@ -- ["To the caves..."] = "", -- A_Classic_Fairytale:united -- ["Toxic Team"] = "", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork -- ["TRACK COMPLETED"] = "PISTA COMPLETA", --- ["TRACK FAILED!"] = "PISTA", + ["training"] = "treino", -- portal ["Traitores"] = "Traidores", -- A_Classic_Fairytale:epil ["Tribe"] = "Tribo", -- A_Classic_Fairytale:backstab @@ -803,6 +961,7 @@ ["ULTRA KILL"] = "ULTRA KILL", -- Mutant ["Under Construction"] = "Em Construção", -- A_Classic_Fairytale:shadow -- ["Unexpected Igor"] = "", -- A_Classic_Fairytale:dragon +-- ["Unique new weapons"] = "", -- Continental_supplies ["Unit 0x0007"] = "Unidade 0x0007", -- A_Classic_Fairytale:family ["Unit 334a$7%;.*"] = "Unidade 334a$7%;.*", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united ["Unit 3378"] = "Unidade 3378", @@ -817,14 +976,18 @@ -- ["Use it wisely!"] = "Usa com moderação\sábiamente", -- A_Classic_Fairytale:dragon -- ["Use it with precaution!"] = "Usa com cuidado!", -- A_Classic_Fairytale:first_blood -- ["User Challenge"] = "", +-- ["Use the air-attack weapons and the arrow keys to select structures."] = "", -- Construction_Mode -- ["Use the portal gun to get to the next crate, then use the new gun to get to the final destination!|"] = "", -- A_Classic_Fairytale:dragon -- ["Use the rope to get on the head of the mole, young one!"] = "Usa a corda para chegar à cabeça da toupeira, jovem!", -- A_Classic_Fairytale:first_blood ["Use the rope to knock your enemies to their doom."] = "Usa a corda para empurrar os teus inimigos para o seu fim.", -- User_Mission_-_Rope_Knock_Challenge +-- ["Use your ready time to think."] = "", -- Frenzy ["Use your rope to get from start to finish as fast as you can!"] = "Utilizando a corda, percorre o percurso do inicio ao fim o mais rápido que conseguires!", +-- ["Utility Crate Placement Mode"] = "", -- Construction_Mode +-- ["Vampirism"] = "", -- Construction_Mode ["Vedgies"] = "Vegetais", -- A_Classic_Fairytale:journey ["Vegan Jack"] = "Jack Vegetariano", -- A_Classic_Fairytale:enemy + ["Victory for the "] = "Vitória para a", -- CTF_Blizzard, Capture_the_Flag ["Victory!"] = "Vitória!", -- Basic_Training_-_Rope - ["Victory for the "] = "Vitória para a", -- CTF_Blizzard, Capture_the_Flag ["Violence is not the answer to your problems!"] = "Violência não é a resposta para os teus problemas!", -- A_Classic_Fairytale:first_blood -- ["Walls Left"] = "Faltam $1 paredes", -- WxW ["Walls Required"] = "Paredes Necessárias", -- WxW @@ -832,10 +995,14 @@ -- ["Wannabe Flyboys"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Wannabe Shoppsta"] = "", -- User_Mission_-_Rope_Knock_Challenge -- ["Watch your steps, young one!"] = "Cuidado onde pões os pés, jovem!", -- A_Classic_Fairytale:first_blood +-- ["Watermelon Bomb"] = "", -- Construction_Mode -- ["Waypoint placed."] = "Waypoint colocado.", -- ["Way-Points Remaining"] = "", -- ["Weaklings"] = "Fracotes", -- A_Classic_Fairytale:shadow -- ["We all know what happens when you get frightened..."] = "Todos sabemos o que acontece quando te sentes assustado...", -- A_Classic_Fairytale:first_blood +-- ["Weapon Crate Placement Mode"] = "", -- Construction_Mode +-- ["Weapon Filter"] = "", -- Construction_Mode +-- ["weaponschemes"] = "", -- Continental_supplies -- ["Weapons Reset"] = "", -- ["Weapons reset."] = "", -- Highlander ["We are indeed."] = "Somos mesmo.", -- A_Classic_Fairytale:backstab @@ -876,21 +1043,19 @@ -- ["What is this place?"] = "O que é este sitio?\Que (raio de) sitio é este?", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy ["What shall we do with the traitor?"] = "O que fazemos com o traidor?", -- A_Classic_Fairytale:backstab -- ["WHAT?! You're the ones attacking us!"] = "O QUÊ?! Voces é que nos atacaram\estão a atacar!", -- A_Classic_Fairytale:enemy + ["When I find it..."] = "Quando o encontrar...", -- A_Classic_Fairytale:dragon ["When?"] = "Quando?", -- A_Classic_Fairytale:enemy - ["When I find it..."] = "Quando o encontrar...", -- A_Classic_Fairytale:dragon ["Where are all these crates coming from?!"] = "De onde vêm todas estas caixas?!", -- A_Classic_Fairytale:shadow ["Where are they?!"] = "Onde estão eles?!", -- A_Classic_Fairytale:backstab ["Where did that alien run?"] = "Para onde fugiu aquele alienígena?", -- A_Classic_Fairytale:dragon + ["Where did you get the exploding apples and the magic bow that shoots many arrows?"] = "Onde arranjaste as maçãs explosivas e o arco mágico que dispara muitas flechas?", -- A_Classic_Fairytale:shadow ["Where did you get the exploding apples?"] = "Onde arranjaste as maçãs explosivas?", -- A_Classic_Fairytale:shadow - ["Where did you get the exploding apples and the magic bow that shoots many arrows?"] = "Onde arranjaste as maçãs explosivas e o arco mágico que dispara muitas flechas?", -- A_Classic_Fairytale:shadow ["Where did you get the magic bow that shoots many arrows?"] = "Onde arranjaste o arco mágico que dispara muitas flechas?", -- A_Classic_Fairytale:shadow -- ["Where did you get the weapons in the forest, Dense Cloud?"] = "Onde arranjaste as armas na floresta, Nuvem Densa?", -- A_Classic_Fairytale:backstab ["Where do you get that?!"] = "Onde arranjaste isso?!", -- A_Classic_Fairytale:enemy ["Where have you been?!"] = "Onde estiveste?!", -- A_Classic_Fairytale:backstab ["Where have you been?"] = "Onde estiveste?", -- A_Classic_Fairytale:united - ["? Why?"] = "? Por quê?", -- A_Classic_Fairytale:backstab - ["Why "] = "Por quê ", -- A_Classic_Fairytale:backstab - ["! Why?!"] = "! Por quê?!", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united +-- ["Whip"] = "", -- Construction_Mode ["Why are you doing this?"] = "Porque estás a fazer isto?", -- A_Classic_Fairytale:journey ["Why are you helping us, uhm...?"] = "Porque nos estás a ajudar, uhm...?", -- A_Classic_Fairytale:family ["Why can't he just let her go?!"] = "Porque não podemos simplesmente deixá-la ir?!", -- A_Classic_Fairytale:family @@ -898,10 +1063,15 @@ ["Why do you not like me?"] = "Porque não gostas de mim?", -- A_Classic_Fairytale:shadow ["Why do you want to take over our island?"] = "Porque querem apoderar-se da nossa ilha?", -- A_Classic_Fairytale:enemy ["Why me?!"] = "Por quê eu?!", -- A_Classic_Fairytale:backstab + ["? Why?"] = "? Por quê?", -- A_Classic_Fairytale:backstab + ["Why "] = "Por quê ", -- A_Classic_Fairytale:backstab + ["! Why?!"] = "! Por quê?!", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united ["Why would they do this?"] = "Porque fariam eles isto?", -- A_Classic_Fairytale:backstab -- ["- Will Get 1-3 random weapons"] = "", -- Continental_supplies --- ["- Will refresh Parachute each turn."] = "", -- Continental_supplies --- ["- Will refresh portalgun each turn."] = "", -- Continental_supplies +-- ["- Will give you an airstrike every fifth turn."] = "", -- Continental_supplies +-- ["- Will give you a parachute every second turn."] = "", -- Continental_supplies + + -- ["Will this ever end?"] = "Será que isto alguma vez vai acabar?", ["WINNER IS "] = "O VENCEDOR É ", -- Mutant ["WINNING TIME: "] = "TEMPO VENCEDOR: ", @@ -920,6 +1090,7 @@ ["Yes!"] = "Sim!", -- A_Classic_Fairytale:enemy -- ["Yes, yeees! You are now ready to enter the real world!"] = "Sim, SIM! Estás agora pronto para entrar no mundo real!", -- A_Classic_Fairytale:first_blood -- ["Yo, dude, we're here, too!"] = "Yo, bacano, também estamos aqui!\chagámos, também!", -- A_Classic_Fairytale:family +-- ["You are far from home, and the water is rising, climb up as high as you can!"] = "", -- ClimbHome ["You are given the chance to turn your life around..."] = "Foi-te oferecida uma oportunidade para mudar a tua vida...", -- A_Classic_Fairytale:shadow -- ["You are playing with our lives here!"] = "Estas a bincar com as nossas vidas com isto!", -- A_Classic_Fairytale:enemy -- ["! You bastards!"] = "! Seus bastardos!", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united @@ -930,7 +1101,6 @@ -- ["You'd better watch your steps..."] = "É melhor teres cuidado onde pôes os pés...", -- A_Classic_Fairytale:journey -- ["You did not make it in time, try again!"] = "Não chegaste a tempo, tenta novamente!", -- Basic_Training_-_Rope -- ["You have 7 turns until the next wave arrives.|Make sure the arriving cannibals are greeted appropriately!|If the hog dies, the cause is lost.|Hint: you might want to use some mines..."] = "", -- A_Classic_Fairytale:backstab --- ["You have "] = "Tens ", -- A_Classic_Fairytale:dragon -- ["You have been giving us out to the enemy, haven't you!"] = "", -- A_Classic_Fairytale:backstab -- ["You have been respawned, at your last checkpoint!"] = "", -- Basic_Training_-_Rope -- ["You have been respawned, be more carefull next time!"] = "", -- Basic_Training_-_Rope @@ -943,6 +1113,7 @@ -- ["You have proven yourself worthy to see our most ancient secret!"] = "", -- A_Classic_Fairytale:first_blood -- ["You have proven yourselves worthy!"] = "", -- A_Classic_Fairytale:enemy ["You have SCORED!!"] = "Marcaste!!", +-- ["You have "] = "Tens ", -- A_Classic_Fairytale:dragon ["You have to destroy 12 targets in 180 seconds"] = "Tens de destruir 12 alvos em 180 segundos", -- Basic_Training_-_Cluster_Bomb -- ["You have won the game by proving true cooperative skills!"] = "Ganhaste o jogo demonstrando a tua excelente habilidade em cooperar!", -- A_Classic_Fairytale:enemy ["You just appeared out of thin air!"] = "Simplesmente apareceste do nada!", -- A_Classic_Fairytale:backstab @@ -952,6 +1123,8 @@ -- ["You know what? I don't even regret anything!"] = "Sabes que mais? Nem me arrependo de nada disto!", -- A_Classic_Fairytale:backstab -- ["You'll see what I mean!"] = "Já vais perceber o que quero dizer!", -- A_Classic_Fairytale:enemy ["You may only attack from a rope!"] = "Só podes atacar da corda!", -- WxW +-- ["You may only spawn 5 crates per turn."] = "", -- Construction_Mode +-- ["You may only use 1 Extra Time per turn."] = "", -- Construction_Mode ["You meatbags are pretty slow, you know!"] = "Voçês sacos de carne são muito lentos, sabiam?", -- A_Classic_Fairytale:enemy -- ["You might want to find a way to instantly kill arriving cannibals!"] = "", -- A_Classic_Fairytale:backstab -- ["Young one, you are telling us that they can instantly change location without a shaman?"] = "", -- A_Classic_Fairytale:united @@ -972,6 +1145,7 @@ ["You've failed. Try again."] = "Falhaste. Tenta novamente.", ["You've reached the goal!| |Time: "] = "Chegaste ao fim!| |Tempo: ", ["You will be avenged!"] = "Serás vingado!", -- A_Classic_Fairytale:shadow +-- ["- You will recieve 2-4 weapons on each kill! (Even on own hogs)"] = "", -- Continental_supplies ["You won't believe what happened to me!"] = "Não vais acreditar no que se passou comigo!", -- A_Classic_Fairytale:backstab -- ["Yuck! I bet they'll keep worshipping her even after I save the village!"] = "Yuck! Aposto que eles vão continuar a venerala mesmo depois de eu ter salvo a aldeia deles~~~~~~", -- A_Classic_Fairytale:family -- ["Zealandia"] = "", -- Continental_supplies diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/ru.lua --- a/share/hedgewars/Data/Locale/ru.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/ru.lua Tue Nov 10 20:43:13 2015 +0100 @@ -4,28 +4,46 @@ -- ["..."] = "", -- ["011101000"] = "", -- A_Classic_Fairytale:dragon -- ["011101001"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:family, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united + ["+1 to a Bottom Feeder for killing anyone"] = "+1 Аутсайдеру за убийство", -- Mutant + ["+1 to a Mutant for killing anyone"] = "+1 Мутанту за убийство", -- Mutant + ["-1 to anyone for a suicide"] = "-1 за самоубийство", -- Mutant + ["+2 for becoming a Mutant"] = "+2 за то, что стал Мутантом", -- Mutant -- ["30 minutes later..."] = "", -- A_Classic_Fairytale:shadow -- ["About a month ago, a cyborg came and told us that you're the cannibals!"] = "", -- A_Classic_Fairytale:enemy - ["Accuracy Bonus!"] = "Бонус за аккуратность!", --- ["Ace"] = "", -- User_Mission_-_RCPlane_Challenge, User_Mission_-_Rope_Knock_Challenge --- ["Achievement Unlocked"] = "", -- User_Mission_-_Bamboo_Thicket, User_Mission_-_That_Sinking_Feeling, Tumbler + ["Above-average pilot"] = "Пилот выше среднего", -- User_Mission_-_RCPlane_Challenge + ["Accuracy Bonus!"] = "Бонус за точность!", + ["Accuracy bonus: +%d points"] = "Бонус за точность: +%d очков", -- Basic_Training_-_Sniper_Rifle + ["Ace"] = "Ас", -- User_Mission_-_RCPlane_Challenge, User_Mission_-_Rope_Knock_Challenge + ["Achievement obtained: Lively Lifeguard"] = "Достижение получено: Живучий Спасатель", -- User_Mission_-_That_Sinking_Feeling + ["Achievement Unlocked"] = "Достижение Разблокировано", -- User_Mission_-_Bamboo_Thicket, User_Mission_-_That_Sinking_Feeling, Tumbler -- ["A Classic Fairytale"] = "", -- A_Classic_Fairytale:first_blood -- ["???"] = "", -- A_Classic_Fairytale:backstab -- ["Actually, you aren't worthy of life! Take this..."] = "", -- A_Classic_Fairytale:shadow -- ["A cy-what?"] = "", -- A_Classic_Fairytale:enemy +-- ["Advanced Repositioning Mode"] = "", -- Construction_Mode -- ["Adventurous"] = "", -- A_Classic_Fairytale:journey +-- ["a frenetic Hedgewars mini-game"] = "", -- Frenzy -- ["Africa"] = "", -- Continental_supplies -- ["After Leaks A Lot betrayed his tribe, he joined the cannibals..."] = "", -- A_Classic_Fairytale:first_blood -- ["After the shock caused by the enemy spy, Leaks A Lot and Dense Cloud went hunting to relax."] = "", -- A_Classic_Fairytale:shadow -- ["Again with the 'cannibals' thing!"] = "", -- A_Classic_Fairytale:enemy --- ["a Hedgewars challenge"] = "", -- User_Mission_-_RCPlane_Challenge, User_Mission_-_Rope_Knock_Challenge + ["Aggressively removes enemy hedgehogs."] = "Агрессивно уничтожает вражеских ежей.", -- Construction_Mode + ["a Hedgewars challenge"] = "Hedgewars испытание", -- User_Mission_-_RCPlane_Challenge, User_Mission_-_Rope_Knock_Challenge ["a Hedgewars mini-game"] = "Мини-игра в Hedgewars", -- Space_Invasion, The_Specialists + ["a Hedgewars tag game"] = "Ролевая игра в Hedgewars", -- Mutant +-- ["AHHh, home sweet home. Made it in %d seconds."] = "", -- ClimbHome ["Aiming Practice"] = "Упражнение на точность", --Bazooka, Shotgun, SniperRifle + ["Aiming practice"] = "Упражнение на точность", -- TargetPractice + ["Air Attack"] = "Воздушная атака", -- Construction_Mode -- ["A leap in a leap"] = "", -- A_Classic_Fairytale:first_blood -- ["A little gift from the cyborgs"] = "", -- A_Classic_Fairytale:shadow -- ["All gone...everything!"] = "", -- A_Classic_Fairytale:enemy + ["Allows free teleportation between other nodes."] = "Позволяет телепортироваться между другими узлами.", -- Construction_Mode + ["Allows placement of girders, rubber-bands, mines, sticky mines and barrels."] = "Позволяет размещать балки, батуты, мины, мины-липучки и бочки.", -- Construction_Mode +-- ["Allows placement of structures."] = "", -- Construction_Mode + ["Allows the placement of weapons, utiliites, and health crates."] = "Позволяет размещать ящики с оружием, утилитами и аптечки.", -- Construction_Mode -- ["All right, we just need to get to the other side of the island!"] = "", -- A_Classic_Fairytale:journey --- ["All walls touched!"] = "", -- WxW + ["All walls touched!"] = "Все стены тронуты!", -- WxW -- ["Ammo"] = "", -- ["Ammo Depleted!"] = "", -- ["ammo extended!"] = "", @@ -38,50 +56,68 @@ -- ["And so they discovered that cyborgs weren't invulnerable..."] = "", -- A_Classic_Fairytale:journey -- ["And where's all the weed?"] = "", -- A_Classic_Fairytale:dragon -- ["And you believed me? Oh, god, that's cute!"] = "", -- A_Classic_Fairytale:journey --- ["Anno 1032: [The explosion will make a strong push ~ wide range, wont affect hogs close to the target]"] = "", -- Continental_supplies +-- ["Anno 1032: [The explosion will make a strong push ~ Wide range, wont affect hogs close to the target]"] = "", -- Continental_supplies + -- ["Antarctica"] = "", -- Continental_supplies +-- ["Antarctic summer: - Will give you one girder/mudball and two sineguns/portals every fourth turn."] = "", -- Continental_supplies +-- ["Area"] = "", -- Continental_supplies -- ["Are we there yet?"] = "", -- A_Classic_Fairytale:shadow -- ["Are you accusing me of something?"] = "", -- A_Classic_Fairytale:backstab -- ["Are you saying that many of us have died for your entertainment?"] = "", -- A_Classic_Fairytale:enemy -- ["Artur Detour"] = "", -- A_Classic_Fairytale:queen -- ["As a reward for your performance, here's some new technology!"] = "", -- A_Classic_Fairytale:dragon --- ["a shoppa minigame"] = "", -- WxW + ["a shoppa minigame"] = "shoppa мини-игра", -- WxW -- ["Asia"] = "", -- Continental_supplies -- ["Assault Team"] = "", -- A_Classic_Fairytale:backstab -- ["As the ammo is sparse, you might want to reuse ropes while mid-air.|"] = "", -- A_Classic_Fairytale:dragon -- ["As the challenge was completed, Leaks A Lot set foot on the ground..."] = "", -- A_Classic_Fairytale:first_blood -- ["As you can see, there is no way to get on the other side!"] = "", -- A_Classic_Fairytale:dragon --- ["Attack From Rope"] = "", -- WxW + ["Attack From Rope"] = "Атака с верёвки", -- WxW -- ["Australia"] = "", -- Continental_supplies --- ["Available points remaining: "] = "", + ["Available points remaining: "] = "Осталось точек для размещения: ", + ["Average pilot"] = "Средний Пилот", -- User_Mission_-_RCPlane_Challenge -- ["Back Breaker"] = "", -- A_Classic_Fairytale:backstab -- ["Back in the village, after telling the villagers about the threat..."] = "", -- A_Classic_Fairytale:united -- ["[Backspace]"] = "", -- ["Backstab"] = "", -- A_Classic_Fairytale:backstab --- ["Bad Team"] = "", -- User_Mission_-_The_Great_Escape --- ["Bamboo Thicket"] = "", + ["Bad Guy"] = "Плохой", -- User_Mission_-_The_Great_Escape + ["badmad"] = "Злодеи", -- portal + ["Bad Team"] = "Злодеи", -- User_Mission_-_The_Great_Escape + ["Ballgun"] = "Шаромёт", -- Construction_Mode + ["Bamboo Thicket"] = "Заросли Бамбука", -- User_Mission_-_Bamboo_Thicket -- ["Barrel Eater!"] = "", -- ["Barrel Launcher"] = "", + ["Barrel Placement Mode"] = "Режим Размещения Бочек", -- Construction_Mode + ["Baseball Bat"] = "Бейсбольная бита", -- Construction_Mode -- ["Baseballbat"] = "", -- Continental_supplies --- ["Bat balls at your enemies and|push them into the sea!"] = "", --- ["Bat your opponents through the|baskets and out of the map!"] = "", - ["Bazooka Training"] = "Упражнение с базукой", + ["Bat balls at your enemies and|push them into the sea!"] = "Сбей своих соберников|бейсбольными мячами в воду!", + ["Bat your opponents through the|baskets and out of the map!"] = "Выбей своих соберников через корзину в воду!", + ["Bazooka"] = "Базука", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 + ["Bazooka Training"] = "Тренировка с базукой", -- ["Beep Loopers"] = "", -- A_Classic_Fairytale:queen + ["Beginner"] = "Новичок", -- User_Mission_-_RCPlane_Challenge + ["Below-average pilot"] = "Пилот ниже среднего", -- User_Mission_-_RCPlane_Challenge -- ["Best laps per team: "] = "", --- ["Best Team Times: "] = "", + ["Best Team Times: "] = "ЛУЧШЕЕ ВРЕМЯ КОМАНДЫ: ", -- ["Beware, though! If you are slow, you die!"] = "", -- A_Classic_Fairytale:dragon + ["Bio-Filter"] = "Био-Фильтр", -- Construction_Mode -- ["Biomechanic Team"] = "", -- A_Classic_Fairytale:family + ["Birdy"] = "Птичка", -- Construction_Mode -- ["Blender"] = "", -- A_Classic_Fairytale:family -- ["Bloodpie"] = "", -- A_Classic_Fairytale:backstab -- ["Bloodrocutor"] = "", -- A_Classic_Fairytale:shadow -- ["Bloodsucker"] = "", -- A_Classic_Fairytale:shadow --- ["Bloody Rookies"] = "", -- 01#Boot_Camp, User_Mission_-_Dangerous_Ducklings, User_Mission_-_Diver, User_Mission_-_Spooky_Tree + ["Bloody Rookies"] = "Новобранцы", -- 01#Boot_Camp, User_Mission_-_Dangerous_Ducklings, User_Mission_-_Diver, User_Mission_-_Spooky_Tree + ["Blowtorch"] = "Бур", -- Construction_Mode, Frenzy + ["Blue Team"] = "Синяя Команда", -- User_Mission_-_Dangerous_Ducklings + ["Bobo"] = "Бобо", -- User_Mission_-_Nobody_Laugh -- ["Bone Jackson"] = "", -- A_Classic_Fairytale:backstab -- ["Bonely"] = "", -- A_Classic_Fairytale:shadow ["BOOM!"] = "БАБАХ!", ["Boom!"] = "Бум!", -- ["Boss defeated!"] = "", -- ["Boss Slayer!"] = "", + ["BOTTOM FEEDER"] = "АУТСАЙДЕР", -- Mutant -- ["Brain Blower"] = "", -- A_Classic_Fairytale:journey -- ["Brainiac"] = "", -- A_Classic_Fairytale:epil, A_Classic_Fairytale:first_blood, A_Classic_Fairytale:shadow -- ["Brainila"] = "", -- A_Classic_Fairytale:united @@ -89,7 +125,8 @@ -- ["Brain Teaser"] = "", -- A_Classic_Fairytale:backstab -- ["Brutal Lily"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil -- ["Brutus"] = "", -- A_Classic_Fairytale:backstab --- ["Build a track and race."] = "", + ["Build a fortress and destroy your enemy."] = "Постройте крепость и уничтожьте своего врага.", -- Construction_Mode + ["Build a track and race."] = "Постройте трек и гоняйте!", -- ["Bullseye"] = "", -- A_Classic_Fairytale:dragon -- ["But it proved to be no easy task!"] = "", -- A_Classic_Fairytale:dragon -- ["But that's impossible!"] = "", -- A_Classic_Fairytale:backstab @@ -99,80 +136,122 @@ -- ["But why would they help us?"] = "", -- A_Classic_Fairytale:backstab -- ["But you're cannibals. It's what you do."] = "", -- A_Classic_Fairytale:enemy -- ["But you said you'd let her go!"] = "", -- A_Classic_Fairytale:journey +-- ["C-1"] = "", -- portal +-- ["C-2"] = "", -- portal + ["Cake"] = "Торт", -- Construction_Mode -- ["Call me Beep! Well, 'cause I'm such a nice...person!"] = "", -- A_Classic_Fairytale:family -- ["Cannibals"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:first_blood -- ["Cannibal Sentry"] = "", -- A_Classic_Fairytale:journey -- ["Cannibals?! You're the cannibals!"] = "", -- A_Classic_Fairytale:enemy ["CAPTURE THE FLAG"] = "ЗАХВАТ ФЛАГА", --- ["Careless"] = "", + ["Careless"] = "Беспечный", -- ["Carol"] = "", -- A_Classic_Fairytale:family --- ["CHALLENGE COMPLETE"] = "", -- User_Mission_-_RCPlane_Challenge + ["Challenge"] = "Испытание", -- SpeedShoppa + ["CHALLENGE COMPLETE"] = "МИССИЯ ПРОЙДЕНА", -- User_Mission_-_RCPlane_Challenge + ["Challenge completed!"] = "Испытание пройдено!", -- SpeedShoppa + ["Challenge failed!"] = "Испытание провалено!", -- SpeedShoppa ["Change Weapon"] = "Сменить оружие", +-- ["changing range from %i%% to %i%% with period of %i msec"] = "", -- Gravity + ["Cheater"] = "Читер", -- User_Mission_-_RCPlane_Challenge -- ["Choose your side! If you want to join the strange man, walk up to him.|Otherwise, walk away from him. If you decide to att...nevermind..."] = "", -- A_Classic_Fairytale:shadow --- ["Clumsy"] = "", --- ["Cluster Bomb MASTER!"] = "", -- Basic_Training_-_Cluster_Bomb --- ["Cluster Bomb Training"] = "", -- Basic_Training_-_Cluster_Bomb --- ["Codename: Teamwork"] = "", + ["Cleaver"] = "Секач", -- Construction_Mode +-- ["Cleaver Placement Mode"] = "", -- Construction_Mode +-- ["Climber"] = "", -- ClimbHome +-- ["Climb Home"] = "", -- ClimbHome + ["Clowns"] = "Клоуны", -- User_Mission_-_Nobody_Laugh + ["Clumsy"] = "Неуклюжий", + ["Cluster Bomb"] = "Касcетная бомба", -- Construction_Mode + ["Cluster Bomb MASTER!"] = "МАСТЕР Касcетной бомбы", -- Basic_Training_-_Cluster_Bomb + ["Cluster Bomb Training"] = "Тренировка с Касcетной бомбой", -- Basic_Training_-_Cluster_Bomb + ["Codename: Teamwork"] = "Кодовое имя: 'Командная работа'", -- ["Collateral Damage"] = "", -- A_Classic_Fairytale:journey -- ["Collateral Damage II"] = "", -- A_Classic_Fairytale:journey -- ["Collect all the crates, but remember, our time in this life is limited!"] = "", -- A_Classic_Fairytale:first_blood --- ["Collect or destroy all the health crates."] = "", -- User_Mission_-_RCPlane_Challenge + ["Collect or destroy all the health crates."] = "Собери или уничтожь все аптечки.", -- User_Mission_-_RCPlane_Challenge -- ["Collect the crate on the right.|Hint: Select the rope, [Up] or [Down] to aim, [Space] to fire, directional keys to move.|Ropes can be fired again in the air!"] = "", -- A_Classic_Fairytale:first_blood -- ["Collect the crates within the time limit!|If you fail, you'll have to try again."] = "", -- A_Classic_Fairytale:first_blood -- ["Come closer, so that your training may continue!"] = "", -- A_Classic_Fairytale:first_blood --- ["Compete to use as few planes as possible!"] = "", -- User_Mission_-_RCPlane_Challenge --- ["Complete the track as fast as you can!"] = "", --- ["COMPLETION TIME"] = "", -- User_Mission_-_Rope_Knock_Challenge --- ["Configuration accepted."] = "", -- WxW --- ["Congratulations"] = "", -- Basic_Training_-_Rope --- ["Congratulations! You needed only half of time|to eliminate all targets."] = "", -- Basic_Training_-_Cluster_Bomb --- ["Congratulations! You've completed the Rope tutorial! |- Tutorial ends in 10 seconds!"] = "", -- Basic_Training_-_Rope --- ["Congratulations! You've eliminated all targets|within the allowed time frame."] = "", --Bazooka, Shotgun, SniperRifle + ["Compete to use as few planes as possible!"] = "Постарайся использовать как можно меньше самолетов!", -- User_Mission_-_RCPlane_Challenge + ["Complete the track as fast as you can!"] = "Закончите трек так быстро, как сможете!", + ["COMPLETION TIME"] = "ВРЕМЯ ЗАВЕРШЕНИЯ", -- User_Mission_-_Rope_Knock_Challenge + ["Configuration accepted."] = "Конфигурация принята.", -- WxW + ["Congratulations!"] = "Поздравляем!", + ["Congratulations"] = "Поздравляем", -- Basic_Training_-_Rope + ["Congratulations! You have destroyed all targets within the time."] = "Поздравляем! Вы уничтожили все цели во время.", -- TargetPractice + ["Congratulations! You have truly mastered this challenge! Don't forget to save the demo."] = "Поздравляем! Вы действительно освоили это испытание!", -- User_Mission_-_RCPlane_Challenge + ["Congratulations! You needed only half of time|to eliminate all targets."] = "Поздравляем! Тебе понадобилась только половина|времени, чтобы уничтожить все цели.", -- Basic_Training_-_Cluster_Bomb + ["Congratulations! You've completed the Rope tutorial! |- Tutorial ends in 10 seconds!"] = "Поздравляем! Ты закончил упражнение с Верёвкой! |- Упражнение завершится через 10 секунд!", -- Basic_Training_-_Rope + ["Congratulations! You've eliminated all targets|within the allowed time frame."] = "Поздравляем! Ты уничтожил все цели во время.", --Bazooka, Shotgun, SniperRifle ["Congratulations!"] = "Поздравления!", + ["CONSTRUCTION MODE"] = "РЕЖИМ СТРОИТЕЛЬСТВА", -- Construction_Mode + ["Construction Station"] = "Станция Утилит", -- Construction_Mode -- ["Continental supplies"] = "", -- Continental_supplies --- ["Control pillars to score points."] = "", + ["Copper"] = "Медный", -- User_Mission_-_Nobody_Laugh + ["CONTROL"] = "КОНТРОЛЬ", -- Control + ["Control pillars to score points."] = "Контролируй колонны, чтобы заработать очки.", -- Control + ["Core"] = "Ядро", -- Construction_Mode -- ["Corporationals"] = "", -- A_Classic_Fairytale:queen -- ["Corpsemonger"] = "", -- A_Classic_Fairytale:shadow -- ["Corpse Thrower"] = "", -- A_Classic_Fairytale:epil - ["Crates Left:"] = "Осталось ящиков:", -- User_Mission_-_RCPlane_Challenge --- ["Cybernetic Empire"] = "", + ["Cost"] = "Стоимость", -- Construction_Mode + ["Crate Placement Tool"] = "Инструмент Размещения Ящиков", -- Construction_Mode + ["Crates left: %d"] = "Осталось ящиков: %d", -- User_Mission_-_RCPlane_Challenge + ["crate(s)"] = "ящиков", -- SpeedShoppa + ["%d crate(s) remaining"] = "%d ящиков осталось", -- SpeedShoppa +-- ["Cricket time: [Drop a fireable mine! ~ Will work if fired close to your hog & far away from enemy ~ 1 sec]"] = "", -- Continental_supplies +-- ["Current setting is "] = "", -- Gravity + ["Cybernetic Empire"] = "Кибер Империя", -- User_Mission_-_Bamboo_Thicket -- ["Cyborg. It's what the aliens call themselves."] = "", -- A_Classic_Fairytale:enemy -- ["Dahmer"] = "", -- A_Classic_Fairytale:backstab --- ["DAMMIT, ROOKIE!"] = "", --- ["DAMMIT, ROOKIE! GET OFF MY HEAD!"] = "", --- ["Dangerous Ducklings"] = "", --- ["Deadweight"] = "", + ["DAMMIT, ROOKIE!"] = "ЧЁРТ ПОБЕРИ, САЛАГА!", + ["DAMMIT, ROOKIE! GET OFF MY HEAD!"] = "ЧЁРТ ПОБЕРИ! СЛЕЗЬ С МОЕЙ ГОЛОВЫ!", + ["Dangerous Ducklings"] = "Опасные Утята", -- User_Mission_-_Dangerous_Ducklings + ["Deadweight"] = "Балласт", + ["deaths"] = "смертей", -- Mutant +-- ["Decrease"] = "", -- Continental_supplies -- ["Defeat the cannibals"] = "", -- A_Classic_Fairytale:backstab -- ["Defeat the cannibals!|"] = "", -- A_Classic_Fairytale:united -- ["Defeat the cannibals!|Grenade hint: set the timer with [1-5], aim with [Up]/[Down] and hold [Space] to set power"] = "", -- A_Classic_Fairytale:shadow -- ["Defeat the cyborgs!"] = "", -- A_Classic_Fairytale:enemy +-- ["Defend your core from the enemy."] = "", -- Construction_Mode -- ["Defend yourself!|Hint: You can get tips on using weapons by moving your mouse over them in the weapon selection menu"] = "", -- A_Classic_Fairytale:shadow --- ["Demolition is fun!"] = "", + ["Dematerializes weapons and equipment carried by enemy hedgehogs."] = "Аннигилирует вражеское оружие и оборудование.", -- Construction_Mode + ["Demo"] = "Демон", -- The_Specialists + ["Demolition is fun!"] = "Разрушать весело!", -- ["Dense Cloud"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united -- ["Dense Cloud must have already told them everything..."] = "", -- A_Classic_Fairytale:shadow -- ["Depleted Kamikaze!"] = "", + ["Derp"] = "Глупый", -- User_Mission_-_Nobody_Laugh + ["Desert Eagle"] = "Пистолет Desert Eagle", -- Construction_Mode, A_Space_Adventure:death02 -- ["Destroy him, Leaks A Lot! He is responsible for the deaths of many of us!"] = "", -- A_Classic_Fairytale:first_blood -- ["Destroy invaders to score points."] = "", -- ["Destroy the targets!|Hint: Select the Shoryuken and hit [Space]|P.S. You can use it mid-air."] = "", -- A_Classic_Fairytale:first_blood -- ["Destroy the targets!|Hint: [Up], [Down] to aim, [Space] to shoot"] = "", -- A_Classic_Fairytale:first_blood + ["Destroyer of planes"] = "Уничтожитель самолётов", -- User_Mission_-_RCPlane_Challenge -- ["Did anyone follow you?"] = "", -- A_Classic_Fairytale:united -- ["Did you see him coming?"] = "", -- A_Classic_Fairytale:shadow -- ["Did you warn the village?"] = "", -- A_Classic_Fairytale:shadow -- ["Die, die, die!"] = "", -- A_Classic_Fairytale:dragon + ["Disabled"] = "Отключено", -- WxW -- ["Disguise as a Rockhopper Penguin: [Swap place with a random enemy hog in the circle]"] = "", -- Continental_supplies + ["Disqualified!"] = "Дисквалификация!", -- User_Mission_-_That_Sinking_Feeling -- ["Dist: "] = "", -- Space_Invasion -- ["Do not laugh, inexperienced one, for he speaks the truth!"] = "", -- A_Classic_Fairytale:backstab -- ["Do not let his words fool you, young one! He will stab you in the back as soon as you turn away!"] = "", -- A_Classic_Fairytale:first_blood -- ["Do the deed"] = "", -- A_Classic_Fairytale:first_blood --- ["DOUBLE KILL"] = "", -- Mutant + ["DOUBLE KILL"] = "ДВОЙНОЕ УБИЙСТВО", -- Mutant ["Double Kill!"] = "Двойное убийство!", -- ["Do you have any idea how valuable grass is?"] = "", -- A_Classic_Fairytale:enemy -- ["Do you think you're some kind of god?"] = "", -- A_Classic_Fairytale:enemy -- ["Dragon's Lair"] = "", -- A_Classic_Fairytale:dragon + ["Drill Rocket"] = "Сверлящая ракета", -- Construction_Mode -- ["Drills"] = "", -- A_Classic_Fairytale:backstab +-- ["Drill Strike"] = "", -- Construction_Mode -- ["Drone Hunter!"] = "", --- ["Drop a bomb: [drop some heroic wind that will turn into a bomb on impact]"] = "", -- Continental_supplies --- ["Drowner"] = "", +-- ["Drop a bomb: [Drop some heroic wind that will turn into a bomb on impact]"] = "", -- Continental_supplies + + ["Drowner"] = "Утопающий", -- User_Mission_-_Nobody_Laugh + ["Drunk greenhorn"] = "Пьяный молокосос", -- User_Mission_-_RCPlane_Challenge -- ["Dude, all the plants are gone!"] = "", -- A_Classic_Fairytale:family -- ["Dude, can you see Ramon and Spiky?"] = "", -- A_Classic_Fairytale:journey -- ["Dude, that's so cool!"] = "", -- A_Classic_Fairytale:backstab @@ -181,25 +260,33 @@ -- ["Dude, where are we?"] = "", -- A_Classic_Fairytale:backstab -- ["Dude, wow! I just had the weirdest high!"] = "", -- A_Classic_Fairytale:backstab -- ["Duration"] = "", -- Continental_supplies --- ["Dust storm: [Deals 20 damage to all enemies in the circle]"] = "", -- Continental_supplies --- ["Each turn you get 1-3 random weapons"] = "", --- ["Each turn you get one random weapon"] = "", +-- ["Dust storm: [Deals 15 damage to all enemies in the circle]"] = "", -- Continental_supplies + + ["Dynamite"] = "Динамит", -- Construction_Mode +-- ["Each turn is only ONE SECOND!"] = "", -- Frenzy + ["Each turn you get 1-3 random weapons"] = "Каждый ход вы получаете 1-3 случайных оружия", + ["Each turn you get one random weapon"] = "Каждый ход вы получаете одно случайное оружие", -- ["Eagle Eye"] = "", -- A_Classic_Fairytale:backstab --- ["Eagle Eye: [Blink to the impact ~ one shot]"] = "", -- Continental_supplies +-- ["Eagle Eye: [Blink to the impact ~ One shot]"] = "", -- Continental_supplies + -- ["Ear Sniffer"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:epil + ["Eckles"] = "Заика", -- User_Mission_-_Nobody_Laugh -- ["Elderbot"] = "", -- A_Classic_Fairytale:family --- ["Elimate your captor."] = "", -- User_Mission_-_The_Great_Escape --- ["Eliminate all enemies"] = "", --- ["Eliminate all targets before your time runs out.|You have unlimited ammo for this mission."] = "", --Bazooka, Shotgun, SniperRifle --- ["Eliminate enemy hogs and take their weapons."] = "", -- Highlander --- ["Eliminate Poison before the time runs out"] = "", --- ["Eliminate the Blue Team"] = "", --- ["Eliminate the enemy before the time runs out"] = "", -- User_Mission_-_Bamboo_Thicket, User_Mission_-_Newton_and_the_Hammock + ["Elimate your captor."] = "Уничтожь твоего похитителя.", -- User_Mission_-_The_Great_Escape + ["Eliminate all enemies"] = "Уничтожьте всех врагов", + ["Eliminate all targets before your time runs out.|You have unlimited ammo for this mission."] = "Уничтожь все цели, пока время не вышло.|Для этой миссии доступен неограниченный боезапас.", --Bazooka, Shotgun, SniperRifle + ["Eliminate enemy hogs and take their weapons."] = "Уничтожьте вражеских ежей и получите их оружие.", -- Highlander + ["Eliminate Poison before the time runs out"] = "Уничтожь Яд пока время не вышло", + ["Eliminate the Blue Team"] = "Уничтожь Синюю Команду", + ["Eliminate the enemy before the time runs out"] = "Уничтожь врага пока время не вышло", -- User_Mission_-_Bamboo_Thicket, User_Mission_-_Newton_and_the_Hammock -- ["Eliminate the enemy hogs to win."] = "", --- ["Eliminate the enemy specialists."] = "", --- ["- Eliminate Unit 3378 |- Feeble Resistance must survive"] = "", + ["Eliminate the enemy specialists."] = "Уничтожьте вражеских специалистов.", + ["- Eliminate Unit 3378 |- Feeble Resistance must survive"] = "- Уничтожьте Юнит 3378 |- Слабое Сопротивление должно выжить", + ["Elite pilot"] = "Элитный пилот", -- User_Mission_-_RCPlane_Challenge -- ["Elmo"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen --- ["Energetic Engineer"] = "", + ["Enabled"] = "Включено", -- WxW + ["Energetic Engineer"] = "Энергичный Инженер", -- User_Mission_-_Bamboo_Thicket + ["Engineer"] = "Инженер", -- The_Specialists ["Enjoy the swim..."] = "Приятного плавания...", -- ["[Enter]"] = "", -- ["Europe"] = "", -- Continental_supplies @@ -208,100 +295,129 @@ -- ["Every single time!"] = "", -- A_Classic_Fairytale:dragon -- ["Everything looks OK..."] = "", -- A_Classic_Fairytale:enemy -- ["Exactly, man! That was my dream."] = "", -- A_Classic_Fairytale:backstab + ["Experienced beginner"] = "Продвинутый новичок", -- User_Mission_-_RCPlane_Challenge + ["Extra Damage"] = "Дополнительный урон", -- Construction_Mode + ["Extra Time"] = "Дополнительное время", -- Construction_Mode -- ["Eye Chewer"] = "", -- A_Classic_Fairytale:journey --- ["INSANITY"] = "", -- Mutant -- ["Family Reunion"] = "", -- A_Classic_Fairytale:family --- ["Fastest lap: "] = "", --- ["Feeble Resistance"] = "", + ["Fastest lap: "] = "Лучший круг: ", + ["Feeble Resistance"] = "Слабое Сопротивление", -- ["Fell From Grace"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen -- ["Fell From Heaven"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:first_blood, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen -- ["Fell From Heaven is the best! Fell From Heaven is the greatest!"] = "", -- A_Classic_Fairytale:family -- ["Femur Lover"] = "", -- A_Classic_Fairytale:shadow -- ["Fierce Competition!"] = "", -- Space_Invasion -- ["Fiery Water"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united + ["Filthy Blue"] = "Грязный Синяк", -- User_Mission_-_Dangerous_Ducklings -- ["Find your tribe!|Cross the lake!"] = "", -- A_Classic_Fairytale:dragon -- ["Finish your training|Hint: Animations can be skipped with the [Precise] key."] = "", -- A_Classic_Fairytale:first_blood -- ["Fire"] = "", --- ["Fire a mine: [Does what it says ~ Cant be dropped close to an enemy ~ 1 sec]"] = "", -- Continental_supplies + -- ["First aid kits?!"] = "", -- A_Classic_Fairytale:united -- ["First Blood"] = "", -- A_Classic_Fairytale:first_blood --- ["FIRST BLOOD MUTATES"] = "", -- Mutant + ["FIRST BLOOD MUTATES"] = "ПЕРВАЯ КРОВЬ МУТИРУЕТ", -- Mutant -- ["First Steps"] = "", -- A_Classic_Fairytale:first_blood --- ["Flag captured!"] = "", --- ["Flag respawned!"] = "", --- ["Flag returned!"] = "", --- ["Flags, and their home base will be placed where each team ends their first turn."] = "", + ["Flag captured!"] = "Флаг захвачен!", + ["Flag respawned!"] = "Респаун флага!", + ["Flag returned!"] = "Флаг возвращен!", + ["Flags, and their home base will be placed where each team ends their first turn."] = "Флаги и базы будут помещены там, где каждая команда закончила свои первый ход.", -- ["Flamer"] = "", + ["Flamethrower"] = "Огнемет", -- Construction_Mode -- ["Flaming Worm"] = "", -- A_Classic_Fairytale:backstab --- ["Flare: [fire up some bombs depending on hogs depending on hogs in the circle"] = "", -- Continental_supplies + ["Flawless victory!"] = "Безупречная победа!", -- User_Mission_-_RCPlane_Challenge + -- ["Flesh for Brainz"] = "", -- A_Classic_Fairytale:journey + ["Flying Saucer"] = "Летающая тарелка", -- Construction_Mode, Frenzy -- ["For improved features/stability, play 0.9.18+"] = "", -- WxW + ["Frank"] = "Фрэнк", -- User_Mission_-_Nobody_Laugh -- ["Free Dense Cloud and continue the mission!"] = "", -- A_Classic_Fairytale:journey + ["Freezer"] = "Замораживатель", -- Construction_Mode +-- ["FRENZY"] = "", -- Frenzy -- ["Friendly Fire!"] = "", -- ["fuel extended!"] = "", --- ["GAME BEGUN!!!"] = "", --- ["Game Modifiers: "] = "", + ["GAME BEGUN!!!"] = "ПОЕХАЛИ!!!", + ["Game Modifiers: "] = "Игровые Модификаторы: ", ["GAME OVER!"] = "ИГРА ОКОНЧЕНА!", --- ["Game Started!"] = "", + ["Game Started!"] = "Игра Началась!", -- ["Game? Was this a game to you?!"] = "", -- A_Classic_Fairytale:enemy -- ["GasBomb"] = "", -- Continental_supplies -- ["Gas Gargler"] = "", -- A_Classic_Fairytale:queen +-- ["General information"] = "", -- Continental_supplies + ["Generates power."] = "Генерирует энергию, необходимую для постройки сооружений.", -- Construction_Mode + ["Generator"] = "Генератор", -- Construction_Mode -- ["Get Dense Cloud out of the pit!"] = "", -- A_Classic_Fairytale:journey --- ["Get on over there and take him out!"] = "", + ["Get on over there and take him out!"] = "Доберись туда и уничтожь его!", -- ["Get on the head of the mole"] = "", -- A_Classic_Fairytale:first_blood --- ["Get out of there!"] = "", -- User_Mission_-_The_Great_Escape + ["Get out of there!"] = "Выберись отсюда!", -- User_Mission_-_The_Great_Escape -- ["Get that crate!"] = "", -- A_Classic_Fairytale:first_blood -- ["Get the crate on the other side of the island!|"] = "", -- A_Classic_Fairytale:journey --- ["Get to the target using your rope! |Controls: Left & Right to swing the rope - Up & Down to Contract and Expand!"] = "", -- Basic_Training_-_Rope + ["Get to the target using your rope! |Controls: Left & Right to swing the rope - Up & Down to Contract and Expand!"] = "Доберись до цели, используя верёвку! |Упрвление: Влево и Вправо для раскачивания - Вверх и Вниз для укорочения и удлинения!", -- Basic_Training_-_Rope -- ["Get your teammates out of their natural prison and save the princess!|Hint: Drilling holes should solve everything.|Hint: It might be a good idea to place a girder before starting to drill. Just saying.|Hint: All your hedgehogs need to be above the marked height!|Hint: Leaks A Lot needs to get really close to the princess!"] = "", -- A_Classic_Fairytale:family --- ["GG!"] = "", -- User_Mission_-_Rope_Knock_Challenge + ["GG!"] = "GG!", -- User_Mission_-_Rope_Knock_Challenge -- ["Gimme Bones"] = "", -- A_Classic_Fairytale:backstab +-- ["Girder"] = "", -- Construction_Mode + ["Girder Placement Mode"] = "Режим Размещения Балок", -- Construction_Mode -- ["Glark"] = "", -- A_Classic_Fairytale:shadow ["Goal"] = "Цель", --- ["GO! GO! GO!"] = "", --- ["Good birdy......"] = "", --- ["Good Dude"] = "", -- User_Mission_-_The_Great_Escape + ["GO! GO! GO!"] = "ВПЕРЁД! ВПЕРЁД! ВПЕРЁД!", + ["Good birdy......"] = "Хорошая птичка...", + ["Good Dude"] = "Хороший", -- User_Mission_-_The_Great_Escape -- ["Good idea, they'll never find us there!"] = "", -- A_Classic_Fairytale:united -- ["Good luck...or else!"] = "", -- A_Classic_Fairytale:journey --- ["Good luck out there!"] = "", --- ["Good so far!"] = "", --- ["Good to go!"] = "", + ["Good luck out there!"] = "Удачи там!", + ["Good so far!"] = "Пока хорошо!", + ["Good to go!"] = "Пошёл!", -- ["Go on top of the flower"] = "", -- A_Classic_Fairytale:first_blood -- ["Go, quick!"] = "", -- A_Classic_Fairytale:backstab -- ["Gorkij"] = "", -- A_Classic_Fairytale:journey --- ["Go surf!"] = "", -- WxW + ["Go surf!"] = "Теперь сёрфить!", -- WxW ["GOTCHA!"] = "ПОПАЛСЯ!", -- ["Grab Mines/Explosives"] = "", + ["Grants nearby hogs life-regeneration."] = "Восстанавливает здоровье соседних ежей.", -- Construction_Mode +-- ["Gravity"] = "", -- Gravity -- ["Great choice, Steve! Mind if I call you that?"] = "", -- A_Classic_Fairytale:shadow --- ["Great work! Now hit it with your Baseball Bat! |Tip: You can change weapon with 'Right Click'!"] = "", -- Basic_Training_-_Rope + ["GREAT ! Let's kill all this enemies, using portals"] = "ПРЕКРАСНО ! Теперь можно убить всех с помощью порталов", -- portal + ["Great work! Now hit it with your Baseball Bat! |Tip: You can change weapon with 'Right Click'!"] = "Хорошая работа! А теперь ударь его Бейсбольной Битой! |Подсказка: Оружие можно сменить 'Правым кликом'!", -- Basic_Training_-_Rope -- ["Great! You will be contacted soon for assistance."] = "", -- A_Classic_Fairytale:shadow --- ["Green lipstick bullet: [Is poisonous]"] = "", -- Continental_supplies + + ["Greenhorn"] = "Молокосос", -- User_Mission_-_RCPlane_Challenge +-- ["Green lipstick bullet: [Poisonous, deals no damage]"] = "", -- Continental_supplies -- ["Greetings, "] = "", -- A_Classic_Fairytale:dragon -- ["Greetings, cloudy one!"] = "", -- A_Classic_Fairytale:shadow --- ["Grenade Training"] = "", -- Basic_Training_-_Grenade --- ["Grenadiers"] = "", -- Basic_Training_-_Grenade + ["Grenade"] = "Граната", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 + ["Grenade Group"] = "Группа Гренадеров", -- Target_Practice_-_Grenade_easy, Target_Practice_-_Grenade_hard + ["Grenade Training"] = "Тренировка с Гранатой", -- Basic_Training_-_Grenade + ["Grenadier"] = "Гренадер", -- Target_Practice_-_Grenade_easy, Target_Practice_-_Grenade_hard + ["Grenadiers"] = "Гренадеры", -- Basic_Training_-_Grenade -- ["Guys, do you think there's more of them?"] = "", -- A_Classic_Fairytale:backstab -- ["HAHA!"] = "", -- A_Classic_Fairytale:enemy -- ["Haha!"] = "", -- A_Classic_Fairytale:united --- ["Hahahaha!"] = "", --- ["Haha, now THAT would be something!"] = "", + ["Hahahaha!"] = "Хахахаха!", + ["Haha, now THAT would be something!"] = "Хаха, да не гони, ЭТО уже слишком!", + ["Hammer"] = "Молот", -- Construction_Mode, Continental_supplies -- ["Hannibal"] = "", -- A_Classic_Fairytale:epil --- ["Hapless Hogs"] = "", --- [" Hapless Hogs left!"] = "", - --- [" HAS MUTATED"] = "", -- Mutant + ["Hapless Hogs"] = "Несчастные Ежи", + ["%d Hapless Hogs left"] = "%d Несчастных Ёжиков осталось", + ["Harry"] = "Гарри", -- User_Mission_-_Nobody_Laugh + [" HAS MUTATED"] = " МУТИРОВАЛ", -- Mutant -- ["Hatless Jerry"] = "", -- A_Classic_Fairytale:queen -- ["Have no illusions, your tribe is dead, indifferent of your choice."] = "", -- A_Classic_Fairytale:shadow -- ["Have we ever attacked you first?"] = "", -- A_Classic_Fairytale:enemy + ["Healing Station"] = "Лечебная Станция", -- Construction_Mode + ["Health Crate Placement Mode"] = "Режим Размещения Аптечек", -- Construction_Mode -- ["Health crates extend your time."] = "", --- ["Heavy"] = "", + ["Heartful"] = "Сердечный", -- Challenge_-_Speed_Shoppa_-_Hedgelove + ["Heavy"] = "Тяжёлый", -- ["Heavy Cannfantry"] = "", -- A_Classic_Fairytale:united -- ["Hedge-cogs"] = "", -- A_Classic_Fairytale:enemy --- ["Hedgehog projectile: [fire your hog like a Sticky Bomb]"] = "", -- Continental_supplies --- ["Hedgewars-Basketball"] = "", --- ["Hedgewars-Knockball"] = "", +-- ["Hedgehog projectile: [Fire your hog like a Sticky Bomb]"] = "", -- Continental_supplies + + ["Hedgewars-Basketball"] = "Hedgewars Баскетбол", + ["Hedgewars-Knockball"] = "Hedgewars Вышибалы", -- ["Hedgibal Lecter"] = "", -- A_Classic_Fairytale:backstab --- ["Heh, it's not that bad."] = "", + ["Heh, it's not that bad."] = "Хех, не так уж всё и плохо.", + ["Hell Army"] = "Армия Ада", -- portal + ["Hellish Handgrenade"] = "Адская граната", -- Construction_Mode -- ["Hello again, "] = "", -- A_Classic_Fairytale:family -- ["Help me, Leaks!"] = "", -- A_Classic_Fairytale:journey -- ["Help me, please!!!"] = "", -- A_Classic_Fairytale:journey @@ -311,13 +427,14 @@ -- ["Here, let me help you!"] = "", -- A_Classic_Fairytale:backstab -- ["Here, let me help you save her!"] = "", -- A_Classic_Fairytale:family -- ["Here...pick your weapon!"] = "", -- A_Classic_Fairytale:first_blood --- ["Hero Team"] = "", -- User_Mission_-_The_Great_Escape + ["Hero Team"] = "Герои", -- User_Mission_-_The_Great_Escape -- ["He's so brave..."] = "", -- A_Classic_Fairytale:first_blood -- ["He won't be selling us out anymore!"] = "", -- A_Classic_Fairytale:backstab -- ["Hey, guys!"] = "", -- A_Classic_Fairytale:backstab -- ["Hey guys!"] = "", -- A_Classic_Fairytale:united -- ["Hey! This is cheating!"] = "", -- A_Classic_Fairytale:journey - ["HIGHLANDER"] = "Царь горы", -- Highlander + ["HIGHLANDER"] = "ЦАРЬ ГОРЫ", -- Highlander + ["hiden"] = "Скрытный", -- portal -- ["Hightime"] = "", -- A_Classic_Fairytale:first_blood -- ["Hint: Double Jump - Press [Backspace] twice"] = "", -- A_Classic_Fairytale:first_blood -- ["Hint: Select the BlowTorch, aim and press [Fire]. Press [Fire] again to stop.|Don't blow up the crate."] = "", -- A_Classic_Fairytale:journey @@ -325,16 +442,20 @@ -- ["Hint: you might want to stay out of sight and take all the crates...|"] = "", -- A_Classic_Fairytale:journey -- ["His arms are so strong!"] = "", -- A_Classic_Fairytale:first_blood -- ["Hit Combo!"] = "", + ["hits"] = "попаданий", -- Basic_Training_-_Bazooka -- ["Hmmm...actually...I didn't either."] = "", -- A_Classic_Fairytale:enemy --- ["Hmmm, I'll have to find some way of moving him off this anti-portal surface..."] = "", -- portal + ["Hmmm, I'll have to find some way of moving him off this anti-portal surface..."] = "Хмм, надо придумать как скинуть его с анти-портальной поверхности...", -- portal -- ["Hmmm...it's a draw. How unfortunate!"] = "", -- A_Classic_Fairytale:enemy -- ["Hmmm...perhaps a little more time will help."] = "", -- A_Classic_Fairytale:first_blood ["Hmmm..."] = "Хммм...", -- ["Hogminator"] = "", -- A_Classic_Fairytale:family -- ["Hogs in sight!"] = "", -- Continental_supplies --- ["HOLY SHYTE!"] = "", -- Mutant + ["HOLY SHYTE!"] = "ВОТ ЧЕРТ!", -- Mutant + ["Homing Bee"] = "Пчёлка", -- Construction_Mode -- ["Honest Lee"] = "", -- A_Classic_Fairytale:enemy + ["Hook"] = "Крюк", -- Challenge_-_Speed_Shoppa_-_Ropes ["Hooray!"] = "Ура!", + ["Hopeless case"] = "Безнадежный случай", -- User_Mission_-_RCPlane_Challenge -- ["Hostage Situation"] = "", -- A_Classic_Fairytale:family -- ["How can I ever repay you for saving my life?"] = "", -- A_Classic_Fairytale:journey -- ["How come in a village full of warriors, it's up to me to save it?"] = "", -- A_Classic_Fairytale:dragon @@ -343,7 +464,7 @@ -- ["However, if you fail to do so, she dies a most violent death, just like your friend! Muahahaha!"] = "", -- A_Classic_Fairytale:journey -- ["However, if you fail to do so, she dies a most violent death! Muahahaha!"] = "", -- A_Classic_Fairytale:journey -- ["However, my mates don't agree with me on letting you go..."] = "", -- A_Classic_Fairytale:dragon --- [" HP"] = "", -- Mutant + [" HP"] = " HP", -- Mutant ["Hunter"] = "Охотник", --Bazooka, Shotgun, SniperRifle -- ["I believe there's more of them."] = "", -- A_Classic_Fairytale:backstab -- ["I can see you have been training diligently."] = "", -- A_Classic_Fairytale:first_blood @@ -354,7 +475,7 @@ -- ["I could just teleport myself there..."] = "", -- A_Classic_Fairytale:family -- ["I'd better get going myself."] = "", -- A_Classic_Fairytale:journey -- ["I didn't until about a month ago."] = "", -- A_Classic_Fairytale:enemy --- ["I don't know how you did that.. But good work! |The next one should be easy as cake for you!"] = "", -- Basic_Training_-_Rope + ["I don't know how you did that.. But good work! |The next one should be easy as cake for you!"] = "Я не знаю, как ты это сделал... Но ты молодец! |Следующая цель вообще не составит тебе труда!", -- Basic_Training_-_Rope -- ["I feel something...a place! They will arrive near the circles!"] = "", -- A_Classic_Fairytale:backstab -- ["If only I had a way..."] = "", -- A_Classic_Fairytale:backstab -- ["If only I were given a chance to explain my being here..."] = "", -- A_Classic_Fairytale:first_blood @@ -366,7 +487,7 @@ -- ["If you get stuck, use your Desert Eagle or restart the mission!|"] = "", -- A_Classic_Fairytale:journey -- ["If you know what I mean..."] = "", -- A_Classic_Fairytale:shadow -- ["If you say so..."] = "", -- A_Classic_Fairytale:shadow - + ["Igmund"] = "Джокер", -- User_Mission_-_Nobody_Laugh -- ["I guess you'll have to kill them."] = "", -- A_Classic_Fairytale:dragon -- ["I have come to make you an offering..."] = "", -- A_Classic_Fairytale:shadow -- ["I have no idea where that mole disappeared...Can you see it?"] = "", -- A_Classic_Fairytale:shadow @@ -376,6 +497,7 @@ -- ["I just don't want to sink to your level."] = "", -- A_Classic_Fairytale:backstab -- ["I just found out that they have captured your princess!"] = "", -- A_Classic_Fairytale:family -- ["I just wonder where Ramon and Spiky disappeared..."] = "", -- A_Classic_Fairytale:journey + ["Ikeda"] = "Икэда", -- User_Mission_-_Bamboo_Thicket -- ["I'll hold them off while you return to the village!"] = "", -- A_Classic_Fairytale:shadow -- ["Imagine those targets are the wolves that killed your parents! Take your anger out on them!"] = "", -- A_Classic_Fairytale:first_blood -- ["I'm...alive? How? Why?"] = "", -- A_Classic_Fairytale:backstab @@ -389,6 +511,7 @@ -- ["I'm not sure about that!"] = "", -- A_Classic_Fairytale:united -- ["Impressive...you are still dry as the corpse of a hawk after a week in the desert..."] = "", -- A_Classic_Fairytale:first_blood -- ["I'm so scared!"] = "", -- A_Classic_Fairytale:united +-- ["Increase"] = "", -- Continental_supplies -- ["Incredible..."] = "", -- A_Classic_Fairytale:shadow -- ["I need to find the others!"] = "", -- A_Classic_Fairytale:backstab -- ["I need to get to the other side of this island, fast!"] = "", -- A_Classic_Fairytale:journey @@ -397,18 +520,25 @@ -- ["I need to warn the others."] = "", -- A_Classic_Fairytale:backstab -- ["In fact, you are the only one that's been acting strangely."] = "", -- A_Classic_Fairytale:backstab -- ["In order to get to the other side, you need to collect the crates first.|"] = "", -- A_Classic_Fairytale:dragon + ["INSANITY"] = "БЕЗУМИЕ", -- Mutant ["Instructor"] = "Инструктор", -- 01#Boot_Camp, User_Mission_-_Dangerous_Ducklings + ["Insufficient Power"] = "Недостаточно Энергии", -- Construction_Mode -- ["Interesting idea, haha!"] = "", -- A_Classic_Fairytale:enemy -- ["Interesting! Last time you said you killed a cannibal!"] = "", -- A_Classic_Fairytale:backstab -- ["In the meantime, take these and return to your \"friend\"!"] = "", -- A_Classic_Fairytale:shadow -- ["invaders destroyed"] = "", + ["Invalid Placement"] = "Неверное Размещение", -- Construction_Mode -- ["Invasion"] = "", -- A_Classic_Fairytale:united + ["Invulnerable"] = "Неуязвимость", -- Construction_Mode + ["In your best (and only) flight you took out %d crates with one RC plane!"] = "В вашем лучшем (и единственном) полёте вы достали %d ящиков с одним самолётом.", -- User_Mission_-_RCPlane_Challenge + ["In your best flight you took out %d crates with one RC plane."] = "В вашем лучшем полёте вы достали %d ящиков с одним самолётом.", -- User_Mission_-_RCPlane_Challenge -- ["I saw it with my own eyes!"] = "", -- A_Classic_Fairytale:shadow -- ["I see..."] = "", -- A_Classic_Fairytale:shadow -- ["I see you have already taken the leap of faith."] = "", -- A_Classic_Fairytale:first_blood -- ["I see you would like his punishment to be more...personal..."] = "", -- A_Classic_Fairytale:first_blood -- ["I sense another wave of cannibals heading my way!"] = "", -- A_Classic_Fairytale:backstab -- ["I sense another wave of cannibals heading our way!"] = "", -- A_Classic_Fairytale:backstab + ["I should get myself a portal gun, maybe this crate has one"] = "Надо достать портальную пушку, может в этом ящике?", -- portal -- ["I shouldn't have drunk that last pint."] = "", -- A_Classic_Fairytale:dragon -- ["Is this place in my head?"] = "", -- A_Classic_Fairytale:dragon -- ["It doesn't matter. I won't let that alien hurt my daughter!"] = "", -- A_Classic_Fairytale:dragon @@ -421,7 +551,7 @@ -- ["It must be the aliens' deed."] = "", -- A_Classic_Fairytale:backstab -- ["It must be the cyborgs again!"] = "", -- A_Classic_Fairytale:enemy -- ["I told you, I just found them."] = "", -- A_Classic_Fairytale:backstab --- ["It's a good thing SUDDEN DEATH is 99 turns away..."] = "", + ["It's a good thing SUDDEN DEATH is 99 turns away..."] = "Хорошо, что ВНЕЗАПНАЯ СМЕРТЬ аж через 99 ходов...", -- ["It's always up to women to clear up the mess men created!"] = "", -- A_Classic_Fairytale:dragon -- ["It's a shame, I forgot how to do that!"] = "", -- A_Classic_Fairytale:family -- ["It's impossible to communicate with the spirits without a shaman."] = "", -- A_Classic_Fairytale:shadow @@ -445,8 +575,9 @@ -- ["Just kidding, none of you have died!"] = "", -- A_Classic_Fairytale:enemy -- ["Just on a walk."] = "", -- A_Classic_Fairytale:united -- ["Just wait till I get my hands on that trauma! ARGH!"] = "", -- A_Classic_Fairytale:family +-- ["Kamikaze"] = "", -- Construction_Mode -- ["Kamikaze Expert!"] = "", --- ["Keep it up!"] = "", + ["Keep it up!"] = "Так держать!", -- ["Kerguelen"] = "", -- Continental_supplies -- ["Killing spree!"] = "", -- ["KILL IT!"] = "", -- A_Classic_Fairytale:first_blood @@ -454,6 +585,9 @@ -- ["Kill the aliens!"] = "", -- A_Classic_Fairytale:dragon -- ["Kill the cannibal!"] = "", -- A_Classic_Fairytale:first_blood -- ["Kill the traitor...or spare his life!|Kill him or press [Precise]!"] = "", -- A_Classic_Fairytale:backstab + ["King Customer"] = "Король Покупатель", -- Challenge_-_Speed_Shoppa_-_ShoppaKing + ["Land Sprayer"] = "Распылитель земли", -- Construction_Mode + ["Laser Sight"] = "Лазерный прицел", -- Construction_Mode ["Last Target!"] = "Последняя цель!", -- ["Leader"] = "", -- A_Classic_Fairytale:enemy -- ["Leaderbot"] = "", -- A_Classic_Fairytale:queen @@ -464,6 +598,8 @@ -- ["Led Heart"] = "", -- A_Classic_Fairytale:queen -- ["Lee"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen -- ["[Left Shift]"] = "", +-- ["left shift"] = "", -- Continental_supplies + ["Lestat"] = "Лестат", -- portal -- ["Let a Continent provide your weapons!"] = "", -- Continental_supplies -- ["Let me test your skills a little, will you?"] = "", -- A_Classic_Fairytale:journey -- ["Let's go home!"] = "", -- A_Classic_Fairytale:journey @@ -473,51 +609,74 @@ -- ["Let them have a taste of my fury!"] = "", -- A_Classic_Fairytale:backstab -- ["Let us help, too!"] = "", -- A_Classic_Fairytale:backstab -- ["Light Cannfantry"] = "", -- A_Classic_Fairytale:united --- ["Listen up, maggot!!"] = "", + ["Limburger"] = "Старый Лимбургер", -- Construction_Mode + ["Listen up, maggot!!"] = "Слушай сюда, щегол!!", -- ["Little did they know that this hunt will mark them forever..."] = "", -- A_Classic_Fairytale:shadow -- ["Lively Lifeguard"] = "", --- ["Lonely Cries: [Rise the water if no hog is in the circle and deal 1 damage to all hogs]"] = "", -- Continental_supplies + +-- ["Lonely Cries: [Rise the water if no hog is in the circle and deal 7 damage to all enemy hogs]"] = "", -- Continental_supplies +-- ["Lonely Hog"] = "", -- ClimbHome -- ["Look, I had no choice!"] = "", -- A_Classic_Fairytale:backstab -- ["Look out! There's more of them!"] = "", -- A_Classic_Fairytale:backstab -- ["Look out! We're surrounded by cannibals!"] = "", -- A_Classic_Fairytale:enemy -- ["Looks like the whole world is falling apart!"] = "", -- A_Classic_Fairytale:enemy + ["Loon"] = "Псих", -- The_Specialists + ["Low Gravity"] = "Слабая гравитация", -- Construction_Mode, Frenzy + ["Lucifer"] = "Люцифер", -- portal -- ["Luckily, I've managed to snatch some of them."] = "", -- A_Classic_Fairytale:united --- ["LUDICROUS KILL"] = "", -- Mutant + ["LUDICROUS KILL"] = "НЕЛЕПОЕ УБИЙСТВО", -- Mutant +-- ["Made it!"] = "", -- ClimbHome +-- ["- Massive weapon bonus on first turn"] = "", -- Continental_supplies -- ["May the spirits aid you in all your quests!"] = "", -- A_Classic_Fairytale:backstab -- ["Medicine: [Fire some exploding medicine that will heal all hogs effected by the explosion]"] = "", -- Continental_supplies --- ["MEGA KILL"] = "", -- Mutant + ["MEGA KILL"] = "МЕГА УБИЙСТВО", -- Mutant -- ["Meiwes"] = "", -- A_Classic_Fairytale:backstab + ["milliseconds"] = "миллисекунд", -- SpeedShoppa -- ["Mindy"] = "", -- A_Classic_Fairytale:united + ["Mine"] = "Мина", -- Construction_Mode, Frenzy -- ["Mine Deployer"] = "", -- ["Mine Eater!"] = "", --- ["|- Mines Time:"] = "", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork + ["Mine Placement Mode"] = "Режим Размещения Мин", -- Construction_Mode + ["|- Mines Time:"] = "|- Задержка Мин:", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork +-- ["Mine Strike"] = "", -- Construction_Mode ["MISSION FAILED"] = "МИССИЯ ПРОВАЛЕНА", -- User_Mission_-_Dangerous_Ducklings, User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork + ["Mission lost!"] = "Миссия провалена!", -- Basic_Training_-_Grenade -- ["MISSION SUCCESS"] = "", ["MISSION SUCCESSFUL"] = "МИССИЯ УСПЕШНА", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork + ["Mission won!"] = "Миссия успешна!", -- Basic_Training_-_Grenade + ["Molotov Cocktail"] = "Коктейль Молотова", -- Construction_Mode -- ["Molotov"] = "", -- Continental_supplies --- ["MONSTER KILL"] = "", -- Mutant + ["MONSTER KILL"] = "УБИЙСТВО МОНСТРА", -- Mutant -- ["More Natives"] = "", -- A_Classic_Fairytale:epil + ["Mortar"] = "Миномёт", -- Construction_Mode, A_Space_Adventure:death02 -- ["Movement: [Up], [Down], [Left], [Right]"] = "", + ["Mudball"] = "Комок грязи", -- Construction_Mode -- ["Multi-shot!"] = "", -- ["Muriel"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen -- ["Muscle Dissolver"] = "", -- A_Classic_Fairytale:shadow --- ["-------"] = "", -- Mutant --- ["Nade Boy"] = "", -- Basic_Training_-_Grenade + ["-------"] = "-------", -- Mutant + ["MUTANT"] = "МУТАНТ", -- Mutant + ["Mutant"] = "Мутант", -- Mutant + ["Nade Boy"] = "Снайперок", -- Basic_Training_-_Grenade -- ["Name"] = "", -- A_Classic_Fairytale:queen - ["Nameless Heroes"] = "Безымянные герои", + ["Nameless Heroes"] = "Герои Без Имен", -- ["Nancy Screw"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:queen +-- ["Napalm"] = "", -- Construction_Mode -- ["Napalm rocket: [Fire a bomb with napalm!]"] = "", -- Continental_supplies -- ["Natives"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:first_blood, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united + ["Naughty Ninja"] = "Озорной ниндзя", -- User_Mission_-_Dangerous_Ducklings -- ["New Barrels Per Turn"] = "", ["NEW CLAN RECORD: "] = "НОВЫЙ РЕКОРД КЛАНА: ", --- ["NEW fastest lap: "] = "", + ["NEW fastest lap: "] = "НОВЫЙ лучший круг: ", -- ["New Mines Per Turn"] = "", --- ["NEW RACE RECORD: "] = "", + ["NEW RACE RECORD: "] = "НОВЫЙ РЕКОРД ГОНКИ: ", ["Newton's Hammock"] = "Гамак Ньютона", -- ["Nicely done, meatbags!"] = "", -- A_Classic_Fairytale:enemy -- ["Nice work, "] = "", -- A_Classic_Fairytale:dragon -- ["Nice work!"] = "", -- A_Classic_Fairytale:enemy -- ["Nilarian"] = "", -- A_Classic_Fairytale:queen + ["Ninja"] = "Ниндзя", -- The_Specialists + ["Nobody Laugh"] = "Никто не смеётся", -- User_Mission_-_Nobody_Laugh -- ["No, I came back to help you out..."] = "", -- A_Classic_Fairytale:shadow -- ["No...I wonder where they disappeared?!"] = "", -- A_Classic_Fairytale:journey -- ["Nom-Nom"] = "", -- A_Classic_Fairytale:journey @@ -525,118 +684,165 @@ -- ["Nope. It was one fast mole, that's for sure."] = "", -- A_Classic_Fairytale:shadow -- ["No! Please, help me!"] = "", -- A_Classic_Fairytale:journey -- ["NORMAL"] = "", -- Continental_supplies + ["Normal players can only score points by killing the mutant."] = "Обычные игроки могут получить очки только убив Мутанта.", -- Mutant -- ["North America"] = "", -- Continental_supplies --- ["Not all hogs are born equal."] = "", -- Highlander --- ["NOT ENOUGH WAYPOINTS"] = "", + ["Not all hogs are born equal."] = "Не все ежи рождаются равными.", -- Highlander + ["NOT ENOUGH WAYPOINTS"] = "НЕДОСТАТОЧНО КОНТРОЛЬНЫХ ТОЧЕК", -- ["Not now, Fiery Water!"] = "", -- A_Classic_Fairytale:backstab --- ["Not So Friendly Match"] = "", -- Basketball, Knockball + ["Not So Friendly Match"] = "Совсем Не Товарищеский Матч", -- Basketball, Knockball -- ["Not you again! My head still hurts from last time!"] = "", -- A_Classic_Fairytale:shadow -- ["No, we made sure of that!"] = "", -- A_Classic_Fairytale:united --- ["Now find the next target! |Tip: Normally you lose health by falling down, so be careful!"] = "", -- Basic_Training_-_Rope + ["Now find the next target! |Tip: Normally you lose health by falling down, so be careful!"] = "Теперь найди следующую цель!|Подсказка: Ты потеряешь здоровье, если упадешь, будь осторожен!", -- Basic_Training_-_Rope -- ["No! What have I done?! What have YOU done?!"] = "", -- A_Classic_Fairytale:journey -- ["No. Where did he come from?"] = "", -- A_Classic_Fairytale:shadow -- ["Now how do I get on the other side?!"] = "", -- A_Classic_Fairytale:dragon -- ["No. You and the rest of the tribe are safer there!"] = "", -- A_Classic_Fairytale:backstab + ["Object Placement Tool"] = "Инструмент Размещения Объектов", -- Construction_Mode -- ["Obliterate them!|Hint: You might want to take cover..."] = "", -- A_Classic_Fairytale:shadow -- ["Obstacle course"] = "", -- A_Classic_Fairytale:dragon -- ["Of course I have to save her. What did I expect?!"] = "", -- A_Classic_Fairytale:family -- ["OH, COME ON!"] = "", -- A_Classic_Fairytale:journey -- ["Oh, my!"] = "", -- A_Classic_Fairytale:first_blood -- ["Oh, my! This is even more entertaining than I've expected!"] = "", -- A_Classic_Fairytale:backstab --- ["Oh no! Just try again!"] = "", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork + ["Oh no! Just try again!"] = "О, нет! Попробуй еще раз!", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork -- ["Oh no, not "] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united --- ["Oh no! Time's up! Just try again."] = "", --Bazooka, Shotgun, SniperRifle --- ["Oh no! You failed! Just try again."] = "", -- Basic_Training_-_Cluster_Bomb + ["Oh no! Time's up! Just try again."] = "О, нет! Время вышло! Попробуй еще раз.", --Bazooka, Shotgun, SniperRifle + ["Oh no! You failed! Just try again."] = "О, нет! Ты проиграл! Попробуй еще раз.", -- Basic_Training_-_Cluster_Bomb -- ["Oh, silly me! I forgot that I'm the shaman."] = "", -- A_Classic_Fairytale:backstab -- ["Olive"] = "", -- A_Classic_Fairytale:united -- ["Omnivore"] = "", -- A_Classic_Fairytale:first_blood -- ["Once upon a time, on an island with great natural resources, lived two tribes in heated conflict..."] = "", -- A_Classic_Fairytale:first_blood --- ["ONE HOG PER TEAM! KILLING EXCESS HEDGES"] = "", -- Mutant + ["ONE HOG PER TEAM! KILLING EXCESS HEDGES"] = "ТОЛЬКО ОДИН ЁЖ НА КОМАНДУ! ИЗБЫТОК ЕЖЕЙ БУДЕТ УДАЛЕН", -- Mutant -- ["One tribe was peaceful, spending their time hunting and training, enjoying the small pleasures of life..."] = "", -- A_Classic_Fairytale:first_blood + ["oneye"] = "Циклоп", -- portal +-- ["on Skip"] = "", -- Continental_supplies -- ["Oops...I dropped them."] = "", -- A_Classic_Fairytale:united -- ["Open that crate and we will continue!"] = "", -- A_Classic_Fairytale:first_blood --- ["Operation Diver"] = "", --- ["Opposing Team: "] = "", + ["Operation Diver"] = "Операция 'Ныряльщик'", + ["Opposing Team: "] = "Команда Соперника: ", +-- ["or 'g=50, g2=150, period=4000' for gravity changing|from 50 to 150 and back with period of 4000 msec"] = "", -- Gravity -- ["Orlando Boom!"] = "", -- A_Classic_Fairytale:queen --- ["Ouch!"] = "", -- User_Mission_-_Rope_Knock_Challenge + ["Other kills don't give you points."] = "Другие убийства не дадут вам очков.", -- Mutant + ["Ouch!"] = "Ох!", -- User_Mission_-_Rope_Knock_Challenge -- ["Our tribe, our beautiful island!"] = "", -- A_Classic_Fairytale:enemy --- ["Parachute"] = "", -- Continental_supplies --- ["Pathetic Hog #%d"] = "", --- ["Pathetic Resistance"] = "", -- User_Mission_-_Bamboo_Thicket, User_Mission_-_Newton_and_the_Hammock + ["Parachute"] = "Парашют", -- Continental_supplies + ["Pathetic Hog #%d"] = "Жалкий Ёж #%d", + ["Pathetic Resistance"] = "Жалкое Сопротивление", -- User_Mission_-_Bamboo_Thicket, User_Mission_-_Newton_and_the_Hammock +-- ["Penguin roar: [Deal 15 damage + 15% of your hogs health to all hogs around you and get 2/3 back]"] = "", -- Continental_supplies -- ["Perfect! Now try to get the next crate without hurting yourself!"] = "", -- A_Classic_Fairytale:first_blood --- ["Per-Hog Ammo"] = "", --- ["- Per team weapons|- 9 weaponschemes|- Unique new weapons| |Select continent first round with the Weapon Menu or by ([switch/tab]=Increase,[precise/left shift]=Decrease) on Skip|Some weapons have a second option. Find them with [switch/tab]"] = "", -- Continental_supplies - --- ["Pfew! That was close!"] = "", -- A_Classic_Fairytale:shadow --- ["Piñata bullet: [Contains some sweet candy!]"] = "", -- Continental_supplies --- ["Pings left:"] = "", -- Space_Invasion + ["Per-Hog Ammo"] = "У каждого ежа свое оружие", + ["Personal Portal Device"] = "Портальная Пушка", -- Construction_Mode --- ["Place more waypoints using the 'Air Attack' weapon."] = "", --- ["Planes Used:"] = "", -- User_Mission_-_RCPlane_Challenge --- ["Planes Used"] = "", -- User_Mission_-_RCPlane_Challenge +-- ["Per team weapons"] = "", -- Continental_supplies +-- ["Pfew! That was close!"] = "", -- A_Classic_Fairytale:shadow + ["phosphatoglucidique"] = "Углеводофосфатный", -- portal + ["Piano Strike"] = "Фортепьяновый удар", -- Construction_Mode + ["Pickhammer"] = "Отбойный молоток", -- Construction_Mode + +-- ["Pings left:"] = "", -- Space_Invasion + ["Place more waypoints using the 'Air Attack' weapon."] = "Расположите больше контрольных точек, используя 'Воздушную атаку'", + ["Planes used: %d"] = "Использовано самолётов: %d", -- User_Mission_-_RCPlane_Challenge -- ["Play with me!"] = "", -- A_Classic_Fairytale:shadow --- ["Please place the way-point further from the waterline."] = "", -- Racer --- ["Please place the way-point in the open, within the map boundaries."] = "", -- Racer + ["player"] = "игрок", -- portal + ["Please place the way-point further from the waterline."] = "Поместите контрольную точку подальше от воды.", -- Racer + ["Please place the way-point in the open, within the map boundaries."] = "Поместите контрольную точку в открытом месте внутри границ карты.", -- Racer -- ["Please, stop releasing your \"smoke signals\"!"] = "", -- A_Classic_Fairytale:shadow -- ["Point Blank Combo!"] = "", -- Space_Invasion --- ["points"] = "", -- Control, CTF_Blizzard, Basic_Training_-_Bazooka, Basic_Training_-_Shotgun, Basic_Training_-_Sniper_Rifle + ["points"] = "очки", -- Control, CTF_Blizzard, Basic_Training_-_Bazooka, Basic_Training_-_Shotgun, Basic_Training_-_Sniper_Rifle + ["POINTS"] = "ОЧКИ", -- Mutant ["Poison"] = "Яд", +-- ["Population"] = "", -- Continental_supplies -- ["Portal hint: one goes to the destination, and one is the entrance.|"] = "", -- A_Classic_Fairytale:dragon --- ["Portal mission"] = "", -- portal + ["Portal mission"] = "Портальная миссия", -- portal -- ["Power Remaining"] = "", --- ["Prepare yourself"] = "", --- ["Press [Enter] to accept this configuration."] = "", -- WxW + ["Predator"] = "Хищник", -- portal + ["Prepare yourself"] = "Готовься", +-- ["presice"] = "", -- Continental_supplies + ["Press [Enter] to accept this configuration."] = "Нажмите [Enter] для принятия конфигурации.", -- WxW -- ["Press [Left] or [Right] to move around, [Enter] to jump"] = "", -- A_Classic_Fairytale:first_blood -- ["Press [Precise] to skip intro"] = "", --- ["Private Novak"] = "", -- Basic_Training_-_Cluster_Bomb + ["Prestigious Pilot"] = "Престижный Пилот", -- User_Mission_-_RCPlane_Challenge + ["Private Nolak"] = "Рядовой Нолак", -- Target_Practice_-_Cluster_Bomb + ["Private Novak"] = "Рядовой Новак", -- Basic_Training_-_Cluster_Bomb + ["Professional pilot"] = "Профессиональный пилот", -- User_Mission_-_RCPlane_Challenge + ["Professional stunt pilot"] = "Профессиональный пилот-трюкач", -- User_Mission_-_RCPlane_Challenge -- ["Protect yourselves!|Grenade hint: set the timer with [1-5], aim with [Up]/[Down] and hold [Space] to set power"] = "", -- A_Classic_Fairytale:shadow --- ["Race complexity limit reached."] = "", --- ["RACER"] = "", + ["Pyro"] = "Пироман", -- The_Specialists + ["Race complexity limit reached."] = "Лимит сложности гонки достигнут.", + ["RACER"] = "ГОНЩИК", -- ["Rachel"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen -- ["Radar Ping"] = "", -- Space_Invasion -- ["Raging Buffalo"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united -- ["Ramon"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow --- ["RC PLANE TRAINING"] = "", -- User_Mission_-_RCPlane_Challenge + ["Rank: %s"] = "Ранк: %s", -- User_Mission_-_RCPlane_Challenge +-- ["random in range from %i%% to %i%% with period of %i msec"] = "", -- Gravity + ["razac"] = "Чумной", -- portal +-- ["RC Plane"] = "", -- Construction_Mode + ["RC PLANE TRAINING"] = "ТРЕНИРОВКА С РАДИОУПРАВЛЯЕМЫМ САМОЛЕТОМ", -- User_Mission_-_RCPlane_Challenge -- ["Really?! You thought you could harm me with your little toys?"] = "", -- A_Classic_Fairytale:shadow + ["Reflector Shield"] = "Щит-Отражатель", -- Construction_Mode + ["Reflects enemy projectiles."] = "Отражает снаряды врагов.", -- Construction_Mode -- ["Regurgitator"] = "", -- A_Classic_Fairytale:backstab -- ["Reinforcements"] = "", -- A_Classic_Fairytale:backstab --- ["Remember: The rope only bend around objects, |if it doesn't hit anything it's always stright!"] = "", -- Basic_Training_-_Rope + ["Remember: The rope only bend around objects, |if it doesn't hit anything it's always stright!"] = "Помни: Верёвка изгибается только вокруг объекты, |если же она ничего не касается, то всегда остается прямой!", -- Basic_Training_-_Rope -- ["Remember this, pathetic animal: when the day comes, you will regret your blind loyalty!"] = "", -- A_Classic_Fairytale:shadow --- [" - Return the enemy flag to your base to score | - First team to 3 captures wins | - You may only score when your flag is in your base | - Hogs will drop the flag if killed, or drowned | - Dropped flags may be returned or recaptured | - Hogs respawn when killed"] = "", +-- ["REMOVED"] = "", -- Continental_supplies + ["rescues"] = "спасено", -- User_Mission_-_That_Sinking_Feeling + ["Respawner"] = "Воскреситель", -- Construction_Mode +-- ["Resurrector"] = "", -- Construction_Mode + ["Resurrects dead hedgehogs."] = "Возвращает к жизни мертвых ежей.", -- Construction_Mode + [" - Return the enemy flag to your base to score | - First team to 3 captures wins | - You may only score when your flag is in your base | - Hogs will drop the flag if killed, or drowned | - Dropped flags may be returned or recaptured | - Hogs respawn when killed"] = " - Доставьте вражеский флаг на вашу базу для получения очков | - Выигрывает команда с 3мя захватами флага | - Вы получаете очки только когда ваш флаг находится на базе | - Убитые/Утонувшие ежи теряют флаг | - Брошенные флаги могут быть возвращены или захвачены повторно | - Убитые ежи воскресают", -- ["Return to Leaks A Lot! If you get stuck, press [Precise] to try again!"] = "", -- A_Classic_Fairytale:shadow + ["Rider"] = "Адский Всадник", -- portal -- ["Righteous Beard"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:first_blood, A_Classic_Fairytale:queen, A_Classic_Fairytale:united --- ["ROPE-KNOCKING"] = "", -- User_Mission_-_Rope_Knock_Challenge --- ["Rope Training"] = "", -- Basic_Training_-_Rope + ["ronald"] = "Рональд", -- portal + ["Rope"] = "Верёвка", -- Construction_Mode + ["ROPE-KNOCKING"] = "ВЫШИБАНИЕ-ВЕРЁВКОЙ", -- User_Mission_-_Rope_Knock_Challenge + ["Rope Master!"] = "Мастер Верёвки!", -- Basic_Training_-_Rope + ["Roper"] = "Верёвочник", -- SpeedShoppa + ["Ropes and Crates"] = "Верёвки и Ящики", -- Challenge_-_Speed_Shoppa_-_Ropes + ["Rope Team"] = "Верёвочники", -- Basic_Training_-_Rope +-- ["Rope to safety"] = "", -- ClimbHome + ["Rope Training"] = "Тренировка с Верёвкой", -- Basic_Training_-_Rope -- ["Rot Molester"] = "", -- A_Classic_Fairytale:shadow --- ["Round Limit:"] = "", + ["Round Limit:"] = "Лимит Раундов:", -- ["Round Limit"] = "", --- ["Rounds Complete: "] = "", + ["Rounds Complete: "] = "Раундов Завершено: ", -- ["Rounds Complete"] = "", --- ["RULES OF THE GAME [Press ESC to view]"] = "", +-- ["Rubber Band"] = "", -- Construction_Mode + ["Rubber Placement Mode"] = "Режим Размещения Батутов", -- Construction_Mode + ["RULES"] = "ПРАВИЛА", -- Frenzy, Mutant + ["RULES OF THE GAME [Press ESC to view]"] = "ПРАВИЛА ИГРЫ", -- ["Rusty Joe"] = "", -- A_Classic_Fairytale:queen -- ["s|"] = "", --- ["Sabotage: [Sabotage all hogs in the circle and deal ~10 dmg]"] = "", -- Continental_supplies +-- ["Sabotage/Flare: [Sabotage all hogs in the circle and deal ~1 dmg OR Fire a cluster up into the air]"] = "", -- Continental_supplies + + ["Saint"] = "Святой", -- The_Specialists -- ["Salivaslurper"] = "", -- A_Classic_Fairytale:united -- ["Salvation"] = "", -- A_Classic_Fairytale:family -- ["Salvation was one step closer now..."] = "", -- A_Classic_Fairytale:dragon --- ["Save as many hapless hogs as possible!"] = "", + ["Save as many hapless hogs as possible!"] = "Спасите как можно больше несчастных ежей!", -- ["Save Fell From Heaven!"] = "", -- A_Classic_Fairytale:journey -- ["Save Leaks A Lot!|Hint: The Switch utility might be of help to you."] = "", -- A_Classic_Fairytale:shadow -- ["Save the princess! All your hogs must survive!|Hint: Kill the cyborgs first! Use the ammo very carefully!|Hint: You might want to spare a girder for cover!"] = "", -- A_Classic_Fairytale:family -- ["Save the princess by collecting the crate in under 12 turns!"] = "", -- A_Classic_Fairytale:journey -- ["Scalp Muncher"] = "", -- A_Classic_Fairytale:backstab -- ["SCORE"] = "", --- ["Score"] = "", -- Mutant --- ["Scream from a Walrus: [Deal 20 damage + 10% of your hogs health to all hogs around you and get half back]"] = "", -- Continental_supplies + ["Score"] = "Счет", -- Mutant + ["sec"] = "сек", -- CTF_Blizzard, TrophyRace, Basic_Training_-_Bazooka, Basic_Training_-_Shotgun, Basic_Training_-_Sniper_Rifle, User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork, Capture_the_Flag --- ["Seduction"] = "", -- Continental_supplies + ["%.1f seconds were remaining."] = "%.1f секунд еще оставалось.", -- Basic_Training_-_Bazooka + ["Seduction"] = "Соблазнение", -- Continental_supplies -- ["Seems like every time you take a \"walk\", the enemy find us!"] = "", -- A_Classic_Fairytale:backstab -- ["See that crate farther on the right?"] = "", -- A_Classic_Fairytale:first_blood ["See ya!"] = "Увидимся!", -- ["Segmentation Paul"] = "", -- A_Classic_Fairytale:dragon -- ["Select continent!"] = "", -- Continental_supplies +-- ["Select continent first round with the Weapon Menu or by"] = "", -- Continental_supplies -- ["Select difficulty: [Left] - easier or [Right] - harder"] = "", -- A_Classic_Fairytale:first_blood -- ["selected!"] = "", +-- ["Set period to negative value for random gravity"] = "", -- Gravity +-- ["Setup:|'g=150', where 150 is 150% of normal gravity"] = "", -- Gravity -- ["s"] = "", -- GaudyRacer, Space_Invasion -- ["... share your beauty with the world every morning, my princess!"] = "", -- A_Classic_Fairytale:journey -- ["She's behind that tall thingy."] = "", -- A_Classic_Fairytale:family @@ -648,54 +854,92 @@ -- ["Shield OFF:"] = "", -- ["Shield ON:"] = "", -- ["Shield Seeker!"] = "", --- ["Shotgun"] = "", -- Continental_supplies + ["Shoppa Union"] = "Союз Шоппы", -- Challenge_-_Speed_Shoppa_-_Ropes, Challenge_-_Speed_Shoppa_-_ShoppaKing + ["Shoppers"] = "Шопперы", -- SpeedShoppa + ["Shoryuken"] = "Восходящий удар Дракона", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 + ["Shotgun"] = "Дробовик", -- Continental_supplies -- ["Shotgun Team"] = "", -- ["Shotgun Training"] = "", -- ["shots remaining."] = "", --- ["Silly"] = "", --- ["Sinky"] = "", + ["Silly"] = "Глупый", + ["SineGun"] = "Синус-пушка (бета)", -- Construction_Mode + ["Sinky"] = "Утопленник", -- ["Sirius Lee"] = "", -- A_Classic_Fairytale:enemy --- ["%s is out and Team %d|scored a penalty!| |Score:"] = "", -- Basketball, Knockball --- ["%s is out and Team %d|scored a point!| |Score:"] = "", -- Basketball, Knockball + ["%s is out and Team %d|scored a penalty!| |Score:"] = "%s выбит и Команда %d|оштрафована!| |Счет:", -- Basketball, Knockball + ["%s is out and Team %d|scored a point!| |Score:"] = "%s выбит и Команда %d|получает очко!| |Счет:", -- Basketball, Knockball -- ["Slippery"] = "", -- A_Classic_Fairytale:journey +-- ["Slot"] = "", -- Frenzy +-- ["Slot keys save time! (F1-F10 by default)"] = "", -- Frenzy +-- ["SLOTS"] = "", -- Frenzy -- ["Smith 0.97"] = "", -- A_Classic_Fairytale:enemy -- ["Smith 0.98"] = "", -- A_Classic_Fairytale:enemy -- ["Smith 0.99a"] = "", -- A_Classic_Fairytale:enemy -- ["Smith 0.99b"] = "", -- A_Classic_Fairytale:enemy -- ["Smith 0.99f"] = "", -- A_Classic_Fairytale:enemy -- ["Smith 1.0"] = "", -- A_Classic_Fairytale:enemy --- ["Sniper Rifle"] = "", -- Continental_supplies + ["Sniper"] = "Снайпер", -- The_Specialists + ["Sniper Rifle"] = "Снайперская винтовка", -- Continental_supplies -- ["Sniper!"] = "", -- Space_Invasion ["Sniper Training"] = "Тренировка снайпера", --- ["Sniperz"] = "", + ["Sniperz"] = "Снайперы", -- ["So humiliating..."] = "", -- A_Classic_Fairytale:first_blood + ["Soldier"] = "Солдат", -- The_Specialists +-- ["Some weapons have a second option. Find them with"] = "", -- Continental_supplies -- ["South America"] = "", -- Continental_supplies -- ["So? What will it be?"] = "", -- A_Classic_Fairytale:shadow --- ["Spawn the crate, and attack!"] = "", -- WxW + ["Spawn the crate, and attack!"] = "Подбери ящик и атакуй!", -- WxW -- ["Special Weapons:"] = "", -- Continental_supplies +-- ["Speed Shoppa"] = "", -- SpeedShoppa -- ["Spiky Cheese"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow -- ["Spleenlover"] = "", -- A_Classic_Fairytale:united --- ["Sponge"] = "", --- ["Spooky Tree"] = "", --- ["STATUS UPDATE"] = "", -- GaudyRacer, Space_Invasion + ["Sponge"] = "Губка", + ["Spooky Tree"] = "Зловещее дерево", +-- ["Sprite Placement Mode"] = "", -- Construction_Mode +-- ["Sprite Testing Mode"] = "", -- Construction_Mode + ["STATUS UPDATE"] = "ОБНОВЛЕНИЕ СТАТУСА", -- GaudyRacer, Space_Invasion -- ["Steel Eye"] = "", -- A_Classic_Fairytale:queen -- ["Step By Step"] = "", -- A_Classic_Fairytale:first_blood -- ["Steve"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen --- ["Sticky Mine"] = "", -- Continental_supplies + ["Sticky Mine"] = "Мина-Липучка", -- Continental_supplies + ["Sticky Mine Placement Mode"] = "Режим Размещения Мин-Липучек", -- Construction_Mode -- ["Stronglings"] = "", -- A_Classic_Fairytale:shadow --- ["Structure"] = "", -- Continental_supplies --- ["Super Weapons"] = "", -- WxW --- ["Surf Before Crate"] = "", -- WxW + + ["Structure Placement Mode"] = "Режим Размещения Сооружений", -- Construction_Mode + ["Structure Placement Tool"] = "Инструмент Размещения Сооружений", -- Construction_Mode + ["Subject"] = "Испытуемый", -- portal +-- ["Sundaland"] = "", -- Continental_supplies + ["Super Weapons"] = "Супер Оружие", -- WxW + ["Support Station"] = "Станция Поддержки", -- Construction_Mode + ["Surf Before Crate"] = "Сёрфинг Перед Ящиком", -- WxW -- ["Surfer! +15 points!"] = "", -- Space_Invasion -- ["Surfer!"] = "", -- WxW -- ["Survive!|Hint: Cinematics can be skipped with the [Precise] key."] = "", -- A_Classic_Fairytale:shadow -- ["Swing, Leaks A Lot, on the wings of the wind!"] = "", -- A_Classic_Fairytale:first_blood --- ["Switched to "] = "", +-- ["switch"] = "", -- Continental_supplies + ["Switched to "] = "Выбран ", +-- ["Switch Hog"] = "", -- Construction_Mode -- ["Syntax Errol"] = "", -- A_Classic_Fairytale:dragon +-- ["tab"] = "", -- Continental_supplies +-- ["Tagging Mode"] = "", -- Construction_Mode -- ["Talk about mixed signals..."] = "", -- A_Classic_Fairytale:dragon +-- ["Tardis"] = "", -- Construction_Mode +-- ["Target Placement Mode"] = "", -- Construction_Mode + ["Targets left: %d"] = "Осталось целей: %d", -- TargetPractice + ["Target Practice: Bazooka (easy)"] = "Учебная Стрельба: Базука (легко)", -- Target_Practice_-_Bazooka_easy + ["Target Practice: Bazooka (hard)"] = "Учебная Стрельба: Базука (сложно)", -- Target_Practice_-_Bazooka_hard + ["Target Practice: Grenade (easy)"] = "Учебная Стрельба: Граната (легко)", -- Target_Practice_-_Grenade_easy + ["Target Practice: Grenade (hard)"] = "Учебная Стрельба: Граната (сложно)", -- Target_Practice_-_Grenade_hard + ["Target Practice: Homing Bee"] = "Учебная Стрельба: Пчёлка", -- Target_Practice_-_Homing_Bee + ["Target Practice: Shotgun"] = "Учебная Стрельба: Дробовик", -- Target_Practice_-_Shotgun ["Team %d: "] = "Команда %d: ", - ["Team Scores"] = "Очки команды", -- Control, Space_Invasion + ["Team of Hearts"] = "Команда сердец", -- Challenge_-_Speed_Shoppa_-_Hedgelove + ["Team Scores"] = "Очки команд", -- Control, Space_Invasion + ["Team Zook"] = "Команда Зуки", -- Target_Practice_-_Bazooka_easy, Target_Practice_-_Bazooka_hard + ["Teleportation Mode"] = "Режим Телепортации", -- Construction_Mode + ["Teleportation Node"] = "Узел Телепортации", -- Construction_Mode +-- ["Teleport"] = "", -- Construction_Mode, Frenzy -- ["Teleport hint: just use the mouse to select the destination!"] = "", -- A_Classic_Fairytale:dragon + ["Teleport Unsuccessful. Please teleport within a clan teleporter's sphere of influence."] = "Неудачная Телепортация. Вы можете телепортироваться только в области влияния ваших телепортов.", -- Construction_Mode -- ["Thanks!"] = "", -- A_Classic_Fairytale:family -- ["Thank you, my hero!"] = "", -- A_Classic_Fairytale:family -- ["Thank you, oh, thank you, Leaks A Lot!"] = "", -- A_Classic_Fairytale:journey @@ -705,36 +949,46 @@ -- ["That ought to show them!"] = "", -- A_Classic_Fairytale:backstab -- ["That's for my father!"] = "", -- A_Classic_Fairytale:backstab -- ["That shaman sure knows what he's doing!"] = "", -- A_Classic_Fairytale:shadow --- ["That Sinking Feeling"] = "", + ["That Sinking Feeling"] = "Дед Мазай и Ёжики", -- ["That's not our problem!"] = "", -- A_Classic_Fairytale:enemy -- ["That's typical of you!"] = "", -- A_Classic_Fairytale:family -- ["That was just mean!"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united -- ["That was pointless."] = "", -- ["The answer is...entertaintment. You'll see what I mean."] = "", -- A_Classic_Fairytale:backstab --- ["The anti-portal zone is all over the floor, and I have nothing to kill him...Droping something could hurt him enough to kill him..."] = "", -- portal + ["The anti-portal zone is all over the floor, and I have nothing to kill him...Droping something could hurt him enough to kill him..."] = "Весь пол покрыт анти-портальной краской и мне нечем его убить... Может сбросить на него что-то?..", -- portal + ["The Bottom Feeder can score points by killing anyone."] = "Аутсайдер может заработать очки убив любого.", -- Mutant -- ["The Bull's Eye"] = "", -- A_Classic_Fairytale:first_blood -- ["The caves are well hidden, they won't find us there!"] = "", -- A_Classic_Fairytale:united -- ["The Crate Frenzy"] = "", -- A_Classic_Fairytale:first_blood + ["The Customer is King"] = "Покупатель это Король", -- Challenge_-_Speed_Shoppa_-_ShoppaKing -- ["The Dilemma"] = "", -- A_Classic_Fairytale:shadow -- ["The enemy can't move but it might be a good idea to stay out of sight!|"] = "", -- A_Classic_Fairytale:dragon --- ["The enemy is hiding out on yonder ducky!"] = "", + ["The enemy is hiding out on yonder ducky!"] = "Враг прячется на соседней утке!", -- ["The Enemy Of My Enemy"] = "", -- A_Classic_Fairytale:enemy -- ["The First Blood"] = "", -- A_Classic_Fairytale:first_blood -- ["The First Encounter"] = "", -- A_Classic_Fairytale:shadow --- ["The flag will respawn next round."] = "", + ["The first player to kill someone becomes the Mutant."] = "Первый игрок, убивший кого-либо, становится Мутантом.", -- Mutant + ["The flag will respawn next round."] = "Флаг опять появится в следующем раунде.", + ["The flood has stopped! Challenge over."] = "Наводнение остановилось! Испытание закончено.", -- User_Mission_-_That_Sinking_Feeling -- ["The food bites back"] = "", -- A_Classic_Fairytale:backstab -- ["The giant umbrella from the last crate should help break the fall."] = "", -- A_Classic_Fairytale:first_blood --- ["The Great Escape"] = "", -- User_Mission_-_The_Great_Escape + ["The Great Escape"] = "Великий Побег", -- User_Mission_-_The_Great_Escape + ["The Great Hog in the sky sees your sadness and grants you a boon."] = "Великий Ёж на небесах видит вашу печаль и благословляет вас даром.", -- Construction_Mode -- ["The guardian"] = "", -- A_Classic_Fairytale:shadow + ["The Hogies"] = "Боевые Ежи", -- Target_Practice_-_Cluster_Bomb -- ["The Individualist"] = "", -- A_Classic_Fairytale:shadow -- ["Their buildings were very primitive back then, even for an uncivilised island."] = "", -- A_Classic_Fairytale:united -- ["The Journey Back"] = "", -- A_Classic_Fairytale:journey -- ["The Leap of Faith"] = "", -- A_Classic_Fairytale:first_blood -- ["The Moonwalk"] = "", -- A_Classic_Fairytale:journey --- ["The Nameless One"] = "", --- ["The next one is pretty hard! |Tip: You have to do multiple swings!"] = "", -- Basic_Training_-_Rope + ["The Mutant has super-weapons and a lot of health."] = "У Мутанта есть супер-оружие и много здоровья.", -- Mutant + ["The Mutant loses health quickly if he doesn't keep scoring kills."] = "Мутант быстро теряет здоровье, если не зарабатывает очки за убийства.", -- Mutant + ["The Nameless One"] = "Дед Мазай", + ["The next one is pretty hard! |Tip: You have to do multiple swings!"] = "Следующая цель довольно сложна! |Подсказка: Нужно сделать несколько раскачиваний!", -- Basic_Training_-_Rope -- ["Then how do they keep appearing?"] = "", -- A_Classic_Fairytale:shadow -- ["The other one were all cannibals, spending their time eating the organs of fellow hedgehogs..."] = "", -- A_Classic_Fairytale:first_blood + ["The player with least points (or most deaths) becomes the Bottom Feeder."] = "Игрок с наименьшим количеством очков становится Аутсайдером.", -- Mutant + ["There are a variety of structures available to aid you."] = "Множество сооружений доступны вам в помощь.", -- Construction_Mode -- ["There must be a spy among us!"] = "", -- A_Classic_Fairytale:backstab -- ["There's more of them? When did they become so hungry?"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united -- ["There's nothing more satisfying for me than seeing you share your beauty with the world every morning, my princess!"] = "", -- A_Classic_Fairytale:journey @@ -746,7 +1000,7 @@ -- ["The Shadow Falls"] = "", -- A_Classic_Fairytale:shadow -- ["The Showdown"] = "", -- A_Classic_Fairytale:shadow -- ["The Slaughter"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:first_blood --- ["THE SPECIALISTS"] = "", + ["THE SPECIALISTS"] = "СПЕЦИАЛИСТЫ", -- ["The spirits of the ancerstors are surely pleased, Leaks A Lot."] = "", -- A_Classic_Fairytale:first_blood -- ["The Torment"] = "", -- A_Classic_Fairytale:first_blood -- ["The Tunnel Maker"] = "", -- A_Classic_Fairytale:journey @@ -773,28 +1027,33 @@ -- ["This is typical!"] = "", -- A_Classic_Fairytale:dragon -- ["This must be some kind of sorcery!"] = "", -- A_Classic_Fairytale:shadow -- ["This must be the caves!"] = "", -- A_Classic_Fairytale:backstab --- ["This one's tricky."] = "", --- ["This rain is really something..."] = "", + ["This one's tricky."] = "Это непростая цель.", + ["This rain is really something..."] = "Этот дождь нескончаем...", + ["This was an awesome performance! But this challenge can be finished with even just one RC plane. Can you figure out how?"] = "Потрясающее исполнение! Но это испытание можно пройти всего с одним самолётом. Знаете как?", -- User_Mission_-_RCPlane_Challenge -- ["This will be fun!"] = "", -- A_Classic_Fairytale:enemy -- ["Those aliens are destroying the island!"] = "", -- A_Classic_Fairytale:family -- ["Timed Kamikaze!"] = "", -- ["Time Extended!"] = "", -- ["Time Extension"] = "", ["TIME: "] = "ВРЕМЯ: ", --- ["Tip: The rope physics are different than in the real world, |use it to your advantage!"] = "", -- Basic_Training_-_Rope + ["Time's up!"] = "Время вышло!", -- Basic_Training_-_Sniper_Rifle + ["Tip: The rope physics are different than in the real world, |use it to your advantage!"] = "Подсказка: Поведение верёвки отличается от того, что в реальном мире, |используй это как преимущество!", -- Basic_Training_-_Rope -- ["Toggle Shield"] = "", -- ["To help you, of course!"] = "", -- A_Classic_Fairytale:journey + ["Top-class elite pilot"] = "Элитный пилот топ класса", -- User_Mission_-_RCPlane_Challenge -- ["To place a girder, select it, use [Left] and [Right] to select angle and length, place with [Left Click]"] = "", -- A_Classic_Fairytale:shadow -- ["Torn Muscle"] = "", -- A_Classic_Fairytale:journey -- [" to save the village."] = "", -- A_Classic_Fairytale:dragon -- ["To the caves..."] = "", -- A_Classic_Fairytale:united --- ["Toxic Team"] = "", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork --- ["TRACK COMPLETED"] = "", --- ["TRACK FAILED!"] = "", --- ["training"] = "", -- portal + ["Toxic Team"] = "Токсичные", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork + ["TRACK COMPLETED"] = "ТРЕК ЗАВЕРШЕН", + + ["Trainee"] = "Ученик", -- TargetPractice + ["training"] = "Тренировка", -- portal + ["Training Team"] = "Обучающиеся", -- TargetPractice -- ["Traitors"] = "", -- A_Classic_Fairytale:epil -- ["Tribe"] = "", -- A_Classic_Fairytale:backstab --- ["TrophyRace"] = "", + ["TrophyRace"] = "Трофейная Гонка", -- ["Try to protect the chief! You won't lose if he dies, but it is advised that he survives."] = "", -- A_Classic_Fairytale:united -- ["T_T"] = "", -- ["Tumbling Time Extended!"] = "", @@ -804,45 +1063,57 @@ -- ["Two little hogs cooperating, getting past obstacles..."] = "", -- A_Classic_Fairytale:journey -- ["Uhm...I met one of them and took his weapons."] = "", -- A_Classic_Fairytale:shadow -- ["Uhmm...ok no."] = "", -- A_Classic_Fairytale:enemy --- ["ULTRA KILL"] = "", -- Mutant + ["ULTRA KILL"] = "УЛЬТРА УБИЙСТВО", -- Mutant -- ["Under Construction"] = "", -- A_Classic_Fairytale:shadow -- ["Unexpected Igor"] = "", -- A_Classic_Fairytale:dragon --- ["Unit"] = "", +-- ["Unique new weapons"] = "", -- Continental_supplies + ["Unit"] = "Юнит", -- User_Mission_-_Newton_and_the_Hammock -- ["Unit 0x0007"] = "", -- A_Classic_Fairytale:family -- ["Unit 334a$7%;.*"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united --- ["Unit 3378"] = "", --- ["Unit 835"] = "", + ["Unit 3378"] = "Юнит 3378", + ["Unit 835"] = "Юнит 835", -- User_Mission_-_Bamboo_Thicket -- ["United We Stand"] = "", -- A_Classic_Fairytale:united --- ["Unlimited Attacks"] = "", --- ["Unlucky Sods"] = "", -- User_Mission_-_Rope_Knock_Challenge + ["Unlimited Attacks"] = "Бесконечные атаки", + ["Unlucky Sods"] = "Неудачники", -- User_Mission_-_Rope_Knock_Challenge -- ["Unstoppable!"] = "", --- ["Unsuspecting Louts"] = "", -- User_Mission_-_Rope_Knock_Challenge + ["Unsuspecting Louts"] = "Доверчивые хамы", -- User_Mission_-_Rope_Knock_Challenge -- ["[Up], [Down] to aim, [Space] to shoot!"] = "", -- A_Classic_Fairytale:first_blood + ["Upper-class elite pilot"] = "Элитный пилот высшего класса", -- User_Mission_-_RCPlane_Challenge -- ["Use it wisely!"] = "", -- A_Classic_Fairytale:dragon -- ["Use it with precaution!"] = "", -- A_Classic_Fairytale:first_blood --- ["User Challenge"] = "", - + ["User Challenge"] = "Одиночная Миссия", + ["Use the air-attack weapons and the arrow keys to select structures."] = "Используйте 'Воздушную атаку' и стрелки, чтобы выбрать сооружение.", -- Construction_Mode -- ["Use the portal gun to get to the next crate, then use the new gun to get to the final destination!|"] = "", -- A_Classic_Fairytale:dragon -- ["Use the rope to get on the head of the mole, young one!"] = "", -- A_Classic_Fairytale:first_blood --- ["Use the rope to knock your enemies to their doom."] = "", -- User_Mission_-_Rope_Knock_Challenge --- ["Use your rope to get from start to finish as fast as you can!"] = "", + ["Use the portal to move fast and far, use it to kill, use it with caution!"] = "Используй портал для перемещения, используй его для убийства, используй его с осторожностью!", -- portal + ["Use the rope to knock your enemies to their doom."] = "Используйте веревку, чтобы сбить врагов к их гибели.", -- User_Mission_-_Rope_Knock_Challenge +-- ["Use your ready time to think."] = "", -- Frenzy + ["Use your rope to collect all crates as fast as possible."] = "Используйте веревку, чтобы собрать все ящики как можно быстрее.", -- SpeedShoppa + ["Use your rope to get from start to finish as fast as you can!"] = "Используй веревку, чтобы добраться от старта до финиша как можно быстрее!", + ["Utility Crate Placement Mode"] = "Режим Размещения Ящиков с Утилитами", -- Construction_Mode + ["Vampirism"] = "Вампиризм", -- Construction_Mode -- ["Vedgies"] = "", -- A_Classic_Fairytale:journey -- ["Vegan Jack"] = "", -- A_Classic_Fairytale:enemy --- ["Victory!"] = "", -- Basic_Training_-_Rope --- ["Victory for the "] = "", -- CTF_Blizzard, Capture_the_Flag + ["Victory!"] = "Победа!", -- Basic_Training_-_Rope + ["Victory for the "] = "Победа за ", -- CTF_Blizzard, Capture_the_Flag + ["voldemort"] = "Волан-де-Морт", -- portal -- ["Violence is not the answer to your problems!"] = "", -- A_Classic_Fairytale:first_blood --- ["Walls Left"] = "", -- WxW --- ["Walls Required"] = "", -- WxW --- ["WALL TO WALL"] = "", -- WxW --- ["Wannabe Flyboys"] = "", -- User_Mission_-_RCPlane_Challenge --- ["Wannabe Shoppsta"] = "", -- User_Mission_-_Rope_Knock_Challenge + ["Walls Left"] = "Стен осталось", -- WxW + ["Walls Required"] = "Стен Необходимо", -- WxW +-- ["WALL TO WALL"] = "ОТ СТЕНЫ К СТЕНЕ", -- WxW + ["Wannabe Flyboys"] = "Хочу быть Пилотом", -- User_Mission_-_RCPlane_Challenge + ["Wannabe Shoppsta"] = "Хочу быть Шоппером", -- User_Mission_-_Rope_Knock_Challenge -- ["Watch your steps, young one!"] = "", -- A_Classic_Fairytale:first_blood --- ["Waypoint placed."] = "", --- ["Way-Points Remaining"] = "", + ["Watermelon Bomb"] = "Арбузная бомба", -- Construction_Mode + ["Waypoint placed."] = "Контрольная Точка добавлена.", + ["Way-Points Remaining"] = "Контрольных Точек осталось", -- ["Weaklings"] = "", -- A_Classic_Fairytale:shadow -- ["We all know what happens when you get frightened..."] = "", -- A_Classic_Fairytale:first_blood --- ["Weapons Reset"] = "", --- ["Weapons reset."] = "", -- Highlander + ["Weapon Crate Placement Mode"] = "Режим Размещения Ящиков с Оружием", -- Construction_Mode + ["Weapon Filter"] = "Фильтр Оружия", -- Construction_Mode +-- ["weaponschemes"] = "", -- Continental_supplies + ["Weapons Reset"] = "Сброс оружия", + ["Weapons reset."] = "Сброс оружия.", -- Highlander -- ["We are indeed."] = "", -- A_Classic_Fairytale:backstab -- ["We can't defeat them!"] = "", -- A_Classic_Fairytale:shadow -- ["We can't hold them up much longer!"] = "", -- A_Classic_Fairytale:united @@ -852,7 +1123,7 @@ -- ["We have to protect the village!"] = "", -- A_Classic_Fairytale:united -- ["We have to unite and defeat those cylergs!"] = "", -- A_Classic_Fairytale:enemy -- ["Welcome, Leaks A Lot!"] = "", -- A_Classic_Fairytale:journey --- ["Well done."] = "", + ["Well done."] = "Отлично.", -- ["We'll give you a problem then!"] = "", -- A_Classic_Fairytale:enemy -- ["We'll spare your life for now!"] = "", -- A_Classic_Fairytale:backstab -- ["Well, that was a waste of time."] = "", -- A_Classic_Fairytale:dragon @@ -875,7 +1146,7 @@ -- ["What a strange feeling!"] = "", -- A_Classic_Fairytale:backstab -- ["What do my faulty eyes observe? A spy!"] = "", -- A_Classic_Fairytale:first_blood -- ["Whatever floats your boat..."] = "", -- A_Classic_Fairytale:shadow --- [" What !! For all of this struggle i just win some ... TIME o0"] = "", -- portal + [" What !! For all of this struggle i just win some ... TIME o0"] = " ЧТО ?! За все эти страдания я выиграл только немного ... ВРЕМЕНИ o0", -- portal -- ["What has "] = "", -- A_Classic_Fairytale:backstab -- ["What? Here? How did they find us?!"] = "", -- A_Classic_Fairytale:backstab -- ["What is this place?"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy @@ -893,6 +1164,7 @@ -- ["Where do you get that?!"] = "", -- A_Classic_Fairytale:enemy -- ["Where have you been?!"] = "", -- A_Classic_Fairytale:backstab -- ["Where have you been?"] = "", -- A_Classic_Fairytale:united + ["Whip"] = "Кнут", -- Construction_Mode -- ["? Why?"] = "", -- A_Classic_Fairytale:backstab -- ["Why "] = "", -- A_Classic_Fairytale:backstab -- ["! Why?!"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united @@ -904,12 +1176,15 @@ -- ["Why do you want to take over our island?"] = "", -- A_Classic_Fairytale:enemy -- ["Why me?!"] = "", -- A_Classic_Fairytale:backstab -- ["Why would they do this?"] = "", -- A_Classic_Fairytale:backstab + ["Will be useful if I need a new plateform or if I want to rise...."] = "Это пригодится, чтобы подняться выше...", -- portal -- ["- Will Get 1-3 random weapons"] = "", -- Continental_supplies --- ["- Will refresh Parachute each turn."] = "", -- Continental_supplies --- ["- Will refresh portalgun each turn."] = "", -- Continental_supplies --- ["Will this ever end?"] = "", --- ["WINNER IS "] = "", -- Mutant --- ["WINNING TIME: "] = "", +-- ["- Will give you an airstrike every fifth turn."] = "", -- Continental_supplies +-- ["- Will give you a parachute every second turn."] = "", -- Continental_supplies + + + ["Will this ever end?"] = "Когда уже конец?", + ["WINNER IS "] = "ПОБЕДИЛ ", -- Mutant + ["WINNING TIME: "] = "ПОБЕДНОЕ ВРЕМЯ: ", -- ["Wise Oak"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen -- ["With Dense Cloud on the land of shadows, I'm the village's only hope..."] = "", -- A_Classic_Fairytale:journey -- ["With the rest of the tribe gone, it was up to "] = "", -- A_Classic_Fairytale:dragon @@ -925,30 +1200,53 @@ -- ["Yes!"] = "", -- A_Classic_Fairytale:enemy -- ["Yes, yeees! You are now ready to enter the real world!"] = "", -- A_Classic_Fairytale:first_blood -- ["Yo, dude, we're here, too!"] = "", -- A_Classic_Fairytale:family +-- ["You are far from home, and the water is rising, climb up as high as you can!"] = "", -- ClimbHome -- ["You are given the chance to turn your life around..."] = "", -- A_Classic_Fairytale:shadow -- ["You are playing with our lives here!"] = "", -- A_Classic_Fairytale:enemy -- ["! You bastards!"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united -- ["You bear impressive skills, "] = "", -- A_Classic_Fairytale:dragon --- ["You can't fire a portal on the blue surface"] = "", -- portal + ["You can't fire a portal on the blue surface"] = "Нельзя ставить порталы на синюю поверхность", -- portal -- ["You couldn't possibly believe that after refusing my offer I'd just let you go!"] = "", -- A_Classic_Fairytale:journey --- ["You'd almost swear the water was rising!"] = "", + ["You'd almost swear the water was rising!"] = "Могу поклясться, что вода прибывает!", -- ["You'd better watch your steps..."] = "", -- A_Classic_Fairytale:journey --- ["You did not make it in time, try again!"] = "", -- Basic_Training_-_Rope + ["You did not make it in time, try again!"] = "Время вышло, попробуй еще раз!", -- Basic_Training_-_Rope + ["You had %.2fs remaining on the clock (+%d points)."] = "У вас оставалось %.2f секунд на таймере (+%d очков).", -- Basic_Training_-_Sniper_Rifle + ["You had %.1fs remaining on the clock (+%d points)."] = "У вас оставалось %.1f секунд на таймере (+%d очков).", -- TargetPractice -- ["You have 7 turns until the next wave arrives.|Make sure the arriving cannibals are greeted appropriately!|If the hog dies, the cause is lost.|Hint: you might want to use some mines..."] = "", -- A_Classic_Fairytale:backstab -- ["You have "] = "", -- A_Classic_Fairytale:dragon -- ["You have been giving us out to the enemy, haven't you!"] = "", -- A_Classic_Fairytale:backstab --- ["You have been respawned, at your last checkpoint!"] = "", -- Basic_Training_-_Rope --- ["You have been respawned, be more carefull next time!"] = "", -- Basic_Training_-_Rope + ["You have been respawned, at your last checkpoint!"] = "Ты возродился на последней контрольной точке!", -- Basic_Training_-_Rope + ["You have been respawned, be more carefull next time!"] = "Ты возродился, будь осторожней в следующий раз!", -- Basic_Training_-_Rope -- ["You have chosen the perfect moment to leave."] = "", -- A_Classic_Fairytale:united + ["You have collected %d out of %d crate(s)."] = "Вы собрали %d из %d ящиков.", -- SpeedShoppa + ["You have destroyed %d of %d targets."] = "Вы уничтожили %d из %d целей.", -- Basic_Training_-_Bazooka + ["You have destroyed %d of %d targets (+%d points)."] = "Вы уничтожили %d из %d целей (+%d очков).", -- Basic_Training_-_Sniper_Rifle + ["You have dropped %d missiles."] = "Вы запустили %d ракет.", -- User_Mission_-_RCPlane_Challenge -- ["You have failed to complete your task, young one!"] = "", -- A_Classic_Fairytale:journey -- ["You have failed to save the tribe!"] = "", -- A_Classic_Fairytale:backstab -- ["You have finally figured it out!"] = "", -- A_Classic_Fairytale:enemy + ["You have finished the bazooka training!"] = "Вы прошли тренировку с базукой!", -- Basic_Training_-_Bazooka + ["You have finished the challenge!"] = "Вы прошли испытание!", -- User_Mission_-_RCPlane_Challenge + ["You have finished the challenge in %.3f s."] = "Вы прошли испытание за %.3f сек.", -- SpeedShoppa + ["You have finished the target practice!"] = "Вы завершили учебную стрельбу!", -- TargetPractice + ["You have gained an achievement: %s"] = "Вы получили достижение: %s", -- User_Mission_-_RCPlane_Challenge -- ["You have kidnapped our whole tribe!"] = "", -- A_Classic_Fairytale:enemy -- ["You have killed an innocent hedgehog!"] = "", -- A_Classic_Fairytale:backstab + ["You have launched %d bazookas."] = "Вы запустили %d базук.", -- Basic_Training_-_Bazooka + ["You have launched %d homing bees."] = "Вы запустили %d пчёлок.", -- Target_Practice_-_Homing_Bee + ["You have made %d shots."] = "Вы сделали %d выстрелов.", -- Basic_Training_-_Sniper_Rifle + ["You haven't rescued anyone."] = "Вы никого не спасли.", -- User_Mission_-_That_Sinking_Feeling + ["You have obtained an achievement: Lively Lifeguard"] = "Вы получили достижение: Живучий Спасатель", -- User_Mission_-_That_Sinking_Feeling + ["You have perfectly beaten the challenge!"] = "Вы прекрасно прошли испытание!", -- User_Mission_-_RCPlane_Challenge -- ["You have proven yourself worthy to see our most ancient secret!"] = "", -- A_Classic_Fairytale:first_blood -- ["You have proven yourselves worthy!"] = "", -- A_Classic_Fairytale:enemy --- ["You have SCORED!!"] = "", --- ["You have to destroy 12 targets in 180 seconds"] = "", -- Basic_Training_-_Cluster_Bomb + ["You have SCORED!!"] = "Вы доставили флаг!!", + ["You have shot %d times."] = "Вы выстрелили %d раз.", -- TargetPractice + ["You have thrown %d grenades."] = "Вы бросили %d гранат.", -- Target_Practice_-_Grenade_easy, Target_Practice_-_Grenade_hard + ["You have to destroy 12 targets in 180 seconds"] = "Тебе надо уничтожить 12 целей за 180 секунд", -- Basic_Training_-_Cluster_Bomb + ["You have used only 1 RC plane. Outstanding!"] = "Вы использовали всего 1 самолёт. Выдающееся достижение!", -- User_Mission_-_RCPlane_Challenge + ["You have used %d RC planes."] = "Вы использовали %d самолётов.", -- User_Mission_-_RCPlane_Challenge + ["You have successfully finished the sniper rifle training!"] = "Вы успешно завершили тренировку со снайперской винтовкой!", -- Basic_Training_-_Sniper_Rifle -- ["You have won the game by proving true cooperative skills!"] = "", -- A_Classic_Fairytale:enemy -- ["You just appeared out of thin air!"] = "", -- A_Classic_Fairytale:backstab -- ["You just committed suicide..."] = "", -- A_Classic_Fairytale:shadow @@ -956,30 +1254,42 @@ -- ["You know...taking a stroll."] = "", -- A_Classic_Fairytale:backstab -- ["You know what? I don't even regret anything!"] = "", -- A_Classic_Fairytale:backstab -- ["You'll see what I mean!"] = "", -- A_Classic_Fairytale:enemy --- ["You may only attack from a rope!"] = "", -- WxW + ["You lose!"] = "Вы проиграли!", -- Basic_Training_-_Bazooka + ["You may only attack from a rope!"] = "Вы можете атаковать только с верёвки!", -- WxW + ["You may only spawn 5 crates per turn."] = "Вы можете создавать только 5 ящиков за ход.", -- Construction_Mode + ["You may only use 1 Extra Time per turn."] = "Вы можете использовать Дополнительное Время только один раз за ход.", -- Construction_Mode -- ["You meatbags are pretty slow, you know!"] = "", -- A_Classic_Fairytale:enemy -- ["You might want to find a way to instantly kill arriving cannibals!"] = "", -- A_Classic_Fairytale:backstab + ["You must survive the flood in order to score."] = "Вы должны пережить наводнение, чтобы заработать очки.", -- User_Mission_-_That_Sinking_Feeling -- ["Young one, you are telling us that they can instantly change location without a shaman?"] = "", -- A_Classic_Fairytale:united -- ["You probably know what to do next..."] = "", -- A_Classic_Fairytale:first_blood + ["Your accuracy was %.1f%%."] = "Ваша точность составила %.1f%%.", -- Basic_Training_-_Bazooka + ["Your accuracy was %.1f%% (+%d points)."] = "Ваша точность составила %.1f%% (+%d очков).", -- TargetPractice -- ["Your deaths will be avenged, cannibals!"] = "", -- A_Classic_Fairytale:enemy -- ["Your death will not be in vain, Dense Cloud!"] = "", -- A_Classic_Fairytale:shadow -- ["You're...alive!? But we saw you die!"] = "", -- A_Classic_Fairytale:backstab -- ["You're a pathetic liar!"] = "", -- A_Classic_Fairytale:backstab -- ["You're funny!"] = "", -- A_Classic_Fairytale:journey --- ["You're getting pretty good! |Tip: When you shorten you rope you move faster! |and when you lengthen it you move slower"] = "", -- Basic_Training_-_Rope + ["You're getting pretty good! |Tip: When you shorten you rope you move faster! |and when you lengthen it you move slower"] = "У тебя хорошо получается! |Подсказка: Когда веревка укорачивается, ты двигаешься быстрее! |А когда удлиняется - медленнее!", -- Basic_Training_-_Rope -- ["You're pathetic! You are not worthy of my attention..."] = "", -- A_Classic_Fairytale:shadow -- ["You're probably wondering why I bought you back..."] = "", -- A_Classic_Fairytale:backstab -- ["You're terrorizing the forest...We won't catch anything like this!"] = "", -- A_Classic_Fairytale:shadow + ["Your hedgehog died!"] = "Ваш ёж умер!", -- User_Mission_-_That_Sinking_Feeling -- ["Your hogs must survive!"] = "", -- A_Classic_Fairytale:journey -- ["Your movement skills will be evaluated now."] = "", -- A_Classic_Fairytale:first_blood + ["Your rank: %s"] = "Ваш ранк: %s", -- User_Mission_-_RCPlane_Challenge -- ["You saved"] = "", + ["You saved %d of 8 Hapless Hogs."] = "Вы спасли %d из 8 Несчастных Ёжиков", -- User_Mission_-_That_Sinking_Feeling -- ["You've been assaulting us, we have been just defending ourselves!"] = "", -- A_Classic_Fairytale:enemy --- ["You've failed. Try again."] = "", --- ["You've reached the goal!| |Time: "] = "", + ["You've failed. Try again."] = "Ты проиграл. Попробуй еще раз.", + ["You've reached the goal!| |Time: "] = "Вы достигли цели!| |Время: ", -- ["You will be avenged!"] = "", -- A_Classic_Fairytale:shadow +-- ["- You will recieve 2-4 weapons on each kill! (Even on own hogs)"] = "", -- Continental_supplies -- ["You won't believe what happened to me!"] = "", -- A_Classic_Fairytale:backstab -- ["Yuck! I bet they'll keep worshipping her even after I save the village!"] = "", -- A_Classic_Fairytale:family -- ["Zealandia"] = "", -- Continental_supplies --- ["'Zooka Team"] = "", + ["zombi"] = "Зомби", -- portal + ["Zook"] = "Зук", -- Target_Practice_-_Bazooka_easy, Target_Practice_-_Bazooka_hard + ["'Zooka Team"] = "Команда Зука", -- ["Zork"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen } diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/ru.txt --- a/share/hedgewars/Data/Locale/ru.txt Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/ru.txt Tue Nov 10 20:43:13 2015 +0100 @@ -42,7 +42,7 @@ 00:39=Летающая тарелка 00:40=Коктейль Молотова 00:41=Птичка -00:42=Портативный телепорт +00:42=Портальная Пушка 00:43=Фортепьяновый удар 00:44=Старый Лимбургер 00:45=Синус-пушка (бета) @@ -58,6 +58,8 @@ 00:54=Распылитель земли 00:55=Замораживатель 00:56=Секач +00:57=Батут +00:58=Воздушная мина 01:00=Вперёд к победе! 01:01=Ничья @@ -82,6 +84,9 @@ 01:20=%1 отскок 01:21=Звук отключен 01:22=Режим отсутствия +01:23=Авто Камера Выкл. +01:24=Авто Камера Вкл. +01:25=Нажмите кнопку мишени для указания цели ; Event messages ; Hog (%1) died @@ -453,6 +458,10 @@ 03:53=Модель 40 ;03:54=Построй что нибудь 03:54=Полезная вещь +03:55=Холоднее уже не будет! +03:56=Употребляй или злоупотребляй +03:57=Полезная вещь +03:58=Летающая неконтактная бомба ; Weapon Descriptions (use | as line breaks) 04:00=Атакуй своих врагов обычной гранатой.|Она взорвется сразу, как только таймер|достигнет нуля.|1-5: Установить таймер гранаты|Атака: Удерживай для более дальнего броска @@ -505,6 +514,15 @@ 04:47=Удвой веселье с двумя шипованными, коварными,|липучими минами. Устрой цепную реакцию или|защити себя (или то и другое!)|Атака: Удерживай для более дальнего броска|(дважды) 04:48=Почему кротам достаются все оскорбления?|Вакингующий ёж может быть столь забавным!|Хороший удар этого молота сбреет треть|здоровья ежа и погрузит его в землю.|Атака: Ударить молотом 04:49=Воскреси своих друзей!|Но будь осторожен, т.к. оно также воскресит|твоих врагов.|Атака: Удерживай атаку нажатой для медленного|воскрешения|Вверх: Ускорить воскрешение +04:50=Кто-то скрывается под землёй?|Достань их сверлящим ударом!|Таймер контролирует глубину бурения.|Влево/Вправо: Определить направление атаки|1-5: Установить таймер|Курсор: Выбрать бомбардируемую область +04:51=Швырни в противника комок грязи задаром!|Не наносит урона, но сталкивает|ежей и другие объекты назад.|Атака: Удерживай для более дальнего броска +04:52=Не используется +04:53=Проделайте путь сквозь время и пространство,|пока ваши соратники борятся в одиночестве.|Будьте готовы вернуться в любое время,|при Внезапной Смерти или когда все союзники повержены.|Предупреждение. Не работает во время Внезапной Смерти,|если вы один или если вы Король.|Атака: Активировать +04:54=Распыляет поток липких хлопьеы.|Строит мосты, хоронит врагов, перекрывает туннели.|Будьте осторожны - эти хлопья не прилипают к вам!|Атака: Активировать|Вверх/Вниз: Продолжать прицельную стрельбу|Влево/Вправо: Изменить силу (дальность) распыления +04:55=Bерните ледниковый период!|Замораживает ежей, делает пол скользким или|спасает вас от утопления, замораживая воду.|Атака: Включить/Выключить замораживатель|Вверх/Вниз: Продолжать прицельную стрельбу +04:56=Вы можете бросить два секача во врага,|заблокировать проходы и туннели|и даже использовать их для восхождения!|Bострожно! Игры с ножами опасны.|Атака: Удерживай для выстрела с большей силой (дважды) +04:57=Строит ОЧЕНЬ эластичный батут, от которого|ежи и другие объекты будут отскакивать|без получения урона.|Влево/Вправо: Изменить положение батута|Курсор: Разместить батут в нужной позиции +04:58=Эта неконтактная бомба будет свободно летать в воздухе|и следовать за неосторожными ежами,|подходящими к ней слишком близко.|Однако, урон от взрыва слабее урона от обычной мины.|Атака: Удерживай для выстрела с большей силой ; Game goal strings 05:00=Режимы игры diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/sk.lua --- a/share/hedgewars/Data/Locale/sk.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/sk.lua Tue Nov 10 20:43:13 2015 +0100 @@ -4,6 +4,10 @@ ["..."] = "...", -- ["011101000"] = "", -- A_Classic_Fairytale:dragon -- ["011101001"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:family, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united +-- ["+1 to a Bottom Feeder for killing anyone"] = "", -- Mutant +-- ["+1 to a Mutant for killing anyone"] = "", -- Mutant +-- ["-1 to anyone for a suicide"] = "", -- Mutant +-- ["+2 for becoming a Mutant"] = "", -- Mutant -- ["30 minutes later..."] = "", -- A_Classic_Fairytale:shadow -- ["About a month ago, a cyborg came and told us that you're the cannibals!"] = "", -- A_Classic_Fairytale:enemy ["Accuracy Bonus!"] = "Bonus za presnosť!", @@ -13,17 +17,27 @@ -- ["???"] = "", -- A_Classic_Fairytale:backstab -- ["Actually, you aren't worthy of life! Take this..."] = "", -- A_Classic_Fairytale:shadow -- ["A cy-what?"] = "", -- A_Classic_Fairytale:enemy +-- ["Advanced Repositioning Mode"] = "", -- Construction_Mode -- ["Adventurous"] = "", -- A_Classic_Fairytale:journey +-- ["a frenetic Hedgewars mini-game"] = "", -- Frenzy -- ["Africa"] = "", -- Continental_supplies -- ["After Leaks A Lot betrayed his tribe, he joined the cannibals..."] = "", -- A_Classic_Fairytale:first_blood -- ["After the shock caused by the enemy spy, Leaks A Lot and Dense Cloud went hunting to relax."] = "", -- A_Classic_Fairytale:shadow -- ["Again with the 'cannibals' thing!"] = "", -- A_Classic_Fairytale:enemy +-- ["Aggressively removes enemy hedgehogs."] = "", -- Construction_Mode -- ["a Hedgewars challenge"] = "", -- User_Mission_-_RCPlane_Challenge, User_Mission_-_Rope_Knock_Challenge ["a Hedgewars mini-game"] = "minihra Hedgewars", -- Space_Invasion, The_Specialists +-- ["a Hedgewars tag game"] = "", -- Mutant +-- ["AHHh, home sweet home. Made it in %d seconds."] = "", -- ClimbHome ["Aiming Practice"] = "Tréning presnosti", --Bazooka, Shotgun, SniperRifle +-- ["Air Attack"] = "", -- Construction_Mode -- ["A leap in a leap"] = "", -- A_Classic_Fairytale:first_blood -- ["A little gift from the cyborgs"] = "", -- A_Classic_Fairytale:shadow -- ["All gone...everything!"] = "", -- A_Classic_Fairytale:enemy +-- ["Allows free teleportation between other nodes."] = "", -- Construction_Mode +-- ["Allows placement of girders, rubber-bands, mines, sticky mines and barrels."] = "", -- Construction_Mode +-- ["Allows placement of structures."] = "", -- Construction_Mode +-- ["Allows the placement of weapons, utiliites, and health crates."] = "", -- Construction_Mode -- ["All right, we just need to get to the other side of the island!"] = "", -- A_Classic_Fairytale:journey -- ["All walls touched!"] = "", -- WxW ["Ammo Depleted!"] = "Výzbroj vyčerpaná!", @@ -38,8 +52,11 @@ -- ["And so they discovered that cyborgs weren't invulnerable..."] = "", -- A_Classic_Fairytale:journey -- ["And where's all the weed?"] = "", -- A_Classic_Fairytale:dragon -- ["And you believed me? Oh, god, that's cute!"] = "", -- A_Classic_Fairytale:journey --- ["Anno 1032: [The explosion will make a strong push ~ wide range, wont affect hogs close to the target]"] = "", -- Continental_supplies +-- ["Anno 1032: [The explosion will make a strong push ~ Wide range, wont affect hogs close to the target]"] = "", -- Continental_supplies + -- ["Antarctica"] = "", -- Continental_supplies +-- ["Antarctic summer: - Will give you one girder/mudball and two sineguns/portals every fourth turn."] = "", -- Continental_supplies +-- ["Area"] = "", -- Continental_supplies -- ["Are we there yet?"] = "", -- A_Classic_Fairytale:shadow -- ["Are you accusing me of something?"] = "", -- A_Classic_Fairytale:backstab -- ["Are you saying that many of us have died for your entertainment?"] = "", -- A_Classic_Fairytale:enemy @@ -59,27 +76,35 @@ ["[Backspace]"] = "[Backspace]", -- ["Backstab"] = "", -- A_Classic_Fairytale:backstab -- ["Bad Team"] = "", -- User_Mission_-_The_Great_Escape +-- ["Ballgun"] = "", -- Construction_Mode ["Bamboo Thicket"] = "Bambusové krovie", ["Barrel Eater!"] = "Sudový labužník!", ["Barrel Launcher"] = "Vystreľovač sudov", +-- ["Barrel Placement Mode"] = "", -- Construction_Mode +-- ["Baseball Bat"] = "", -- Construction_Mode -- ["Baseballbat"] = "", -- Continental_supplies ["Bat balls at your enemies and|push them into the sea!"] = "Loptami triafajte vašich nepriateľov|a zhoďte ich tak do mora!", ["Bat your opponents through the|baskets and out of the map!"] = "Odpálkujte vašich súperov do koša|a von z mapy!", +-- ["Bazooka"] = "", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 ["Bazooka Training"] = "Tréning s bazukou", -- ["Beep Loopers"] = "", -- A_Classic_Fairytale:queen ["Best laps per team: "] = "Najrýchlejšie kolá podľa tímov: ", ["Best Team Times: "] = "Najrýchlejšie tímové časy: ", -- ["Beware, though! If you are slow, you die!"] = "", -- A_Classic_Fairytale:dragon +-- ["Bio-Filter"] = "", -- Construction_Mode -- ["Biomechanic Team"] = "", -- A_Classic_Fairytale:family +-- ["Birdy"] = "", -- Construction_Mode -- ["Blender"] = "", -- A_Classic_Fairytale:family -- ["Bloodpie"] = "", -- A_Classic_Fairytale:backstab -- ["Bloodrocutor"] = "", -- A_Classic_Fairytale:shadow -- ["Bloodsucker"] = "", -- A_Classic_Fairytale:shadow ["Bloody Rookies"] = "Mizerní zelenáči", -- 01#Boot_Camp, User_Mission_-_Dangerous_Ducklings, User_Mission_-_Diver, User_Mission_-_Spooky_Tree +-- ["Blowtorch"] = "", -- Construction_Mode, Frenzy +-- ["Blue Team"] = "", -- User_Mission_-_Dangerous_Ducklings -- ["Bone Jackson"] = "", -- A_Classic_Fairytale:backstab -- ["Bonely"] = "", -- A_Classic_Fairytale:shadow + ["BOOM!"] = "BUM!", ["Boom!"] = "Bum!", - ["BOOM!"] = "BUM!", ["Boss defeated!"] = "Vodca bol porazený!", ["Boss Slayer!"] = "Vodca zabitý!", -- ["Brain Blower"] = "", -- A_Classic_Fairytale:journey @@ -89,6 +114,7 @@ -- ["Brain Teaser"] = "", -- A_Classic_Fairytale:backstab -- ["Brutal Lily"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil -- ["Brutus"] = "", -- A_Classic_Fairytale:backstab +-- ["Build a fortress and destroy your enemy."] = "", -- Construction_Mode ["Build a track and race."] = "Vybudujte trasu a pretekajte.", -- ["Bullseye"] = "", -- A_Classic_Fairytale:dragon -- ["But it proved to be no easy task!"] = "", -- A_Classic_Fairytale:dragon @@ -99,6 +125,7 @@ -- ["But why would they help us?"] = "", -- A_Classic_Fairytale:backstab -- ["But you're cannibals. It's what you do."] = "", -- A_Classic_Fairytale:enemy -- ["But you said you'd let her go!"] = "", -- A_Classic_Fairytale:journey +-- ["Cake"] = "", -- Construction_Mode -- ["Call me Beep! Well, 'cause I'm such a nice...person!"] = "", -- A_Classic_Fairytale:family -- ["Cannibals"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:first_blood -- ["Cannibal Sentry"] = "", -- A_Classic_Fairytale:journey @@ -108,8 +135,15 @@ -- ["Carol"] = "", -- A_Classic_Fairytale:family -- ["CHALLENGE COMPLETE"] = "", -- User_Mission_-_RCPlane_Challenge ["Change Weapon"] = "Zmeniť zbraň", +-- ["changing range from %i%% to %i%% with period of %i msec"] = "", -- Gravity -- ["Choose your side! If you want to join the strange man, walk up to him.|Otherwise, walk away from him. If you decide to att...nevermind..."] = "", -- A_Classic_Fairytale:shadow +-- ["Cleaver"] = "", -- Construction_Mode +-- ["Cleaver Placement Mode"] = "", -- Construction_Mode +-- ["Climber"] = "", -- ClimbHome +-- ["Climb Home"] = "", -- ClimbHome +-- ["Clowns"] = "", -- User_Mission_-_Nobody_Laugh ["Clumsy"] = "Nešikovný", +-- ["Cluster Bomb"] = "", -- Construction_Mode -- ["Cluster Bomb MASTER!"] = "", -- Basic_Training_-_Cluster_Bomb -- ["Cluster Bomb Training"] = "", -- Basic_Training_-_Cluster_Bomb ["Codename: Teamwork"] = "Kódové meno: Tímová práca", @@ -129,12 +163,19 @@ -- ["Congratulations! You needed only half of time|to eliminate all targets."] = "", -- Basic_Training_-_Cluster_Bomb -- ["Congratulations! You've completed the Rope tutorial! |- Tutorial ends in 10 seconds!"] = "", -- Basic_Training_-_Rope ["Congratulations! You've eliminated all targets|within the allowed time frame."] = "Gratulujem! Zneškodnili ste všetky ciele|v stanovenom čase.", --Bazooka, Shotgun, SniperRifle +-- ["CONSTRUCTION MODE"] = "", -- Construction_Mode +-- ["Construction Station"] = "", -- Construction_Mode -- ["Continental supplies"] = "", -- Continental_supplies ["Control pillars to score points."] = "Ovládnite piliere, aby ste skórovali", +-- ["Core"] = "", -- Construction_Mode -- ["Corporationals"] = "", -- A_Classic_Fairytale:queen -- ["Corpsemonger"] = "", -- A_Classic_Fairytale:shadow -- ["Corpse Thrower"] = "", -- A_Classic_Fairytale:epil +-- ["Cost"] = "", -- Construction_Mode +-- ["Crate Placement Tool"] = "", -- Construction_Mode -- ["Crates Left:"] = "", -- User_Mission_-_RCPlane_Challenge +-- ["Cricket time: [Drop a fireable mine! ~ Will work if fired close to your hog & far away from enemy ~ 1 sec]"] = "", -- Continental_supplies +-- ["Current setting is "] = "", -- Gravity ["Cybernetic Empire"] = "Kybertnetické impérium", -- ["Cyborg. It's what the aliens call themselves."] = "", -- A_Classic_Fairytale:enemy -- ["Dahmer"] = "", -- A_Classic_Fairytale:backstab @@ -142,15 +183,19 @@ ["DAMMIT, ROOKIE!"] = "Prekliaty zelenáč!", ["Dangerous Ducklings"] = "Nebezpečné kačiatka", ["Deadweight"] = "Mŕtva váha", +-- ["Decrease"] = "", -- Continental_supplies -- ["Defeat the cannibals"] = "", -- A_Classic_Fairytale:backstab -- ["Defeat the cannibals!|"] = "", -- A_Classic_Fairytale:united -- ["Defeat the cannibals!|Grenade hint: set the timer with [1-5], aim with [Up]/[Down] and hold [Space] to set power"] = "", -- A_Classic_Fairytale:shadow -- ["Defeat the cyborgs!"] = "", -- A_Classic_Fairytale:enemy +-- ["Defend your core from the enemy."] = "", -- Construction_Mode -- ["Defend yourself!|Hint: You can get tips on using weapons by moving your mouse over them in the weapon selection menu"] = "", -- A_Classic_Fairytale:shadow +-- ["Dematerializes weapons and equipment carried by enemy hedgehogs."] = "", -- Construction_Mode ["Demolition is fun!"] = "Demolícia je super!", -- ["Dense Cloud"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united -- ["Dense Cloud must have already told them everything..."] = "", -- A_Classic_Fairytale:shadow ["Depleted Kamikaze!"] = "Vyčerpané kamikadze!", +-- ["Desert Eagle"] = "", -- Construction_Mode, A_Space_Adventure:death02 -- ["Destroy him, Leaks A Lot! He is responsible for the deaths of many of us!"] = "", -- A_Classic_Fairytale:first_blood ["Destroy invaders to score points."] = "Ničte votrelcov a zbierajte tak body.", -- ["Destroy the targets!|Hint: Select the Shoryuken and hit [Space]|P.S. You can use it mid-air."] = "", -- A_Classic_Fairytale:first_blood @@ -169,9 +214,12 @@ -- ["Do you have any idea how valuable grass is?"] = "", -- A_Classic_Fairytale:enemy -- ["Do you think you're some kind of god?"] = "", -- A_Classic_Fairytale:enemy -- ["Dragon's Lair"] = "", -- A_Classic_Fairytale:dragon +-- ["Drill Rocket"] = "", -- Construction_Mode -- ["Drills"] = "", -- A_Classic_Fairytale:backstab +-- ["Drill Strike"] = "", -- Construction_Mode ["Drone Hunter!"] = "Lovec špionážnych lietadiel!", --- ["Drop a bomb: [drop some heroic wind that will turn into a bomb on impact]"] = "", -- Continental_supplies +-- ["Drop a bomb: [Drop some heroic wind that will turn into a bomb on impact]"] = "", -- Continental_supplies + ["Drowner"] = "Utopenec", -- ["Dude, all the plants are gone!"] = "", -- A_Classic_Fairytale:family -- ["Dude, can you see Ramon and Spiky?"] = "", -- A_Classic_Fairytale:journey @@ -181,11 +229,15 @@ -- ["Dude, where are we?"] = "", -- A_Classic_Fairytale:backstab -- ["Dude, wow! I just had the weirdest high!"] = "", -- A_Classic_Fairytale:backstab -- ["Duration"] = "", -- Continental_supplies --- ["Dust storm: [Deals 20 damage to all enemies in the circle]"] = "", -- Continental_supplies +-- ["Dust storm: [Deals 15 damage to all enemies in the circle]"] = "", -- Continental_supplies + +-- ["Dynamite"] = "", -- Construction_Mode +-- ["Each turn is only ONE SECOND!"] = "", -- Frenzy ["Each turn you get 1-3 random weapons"] = "V každom ťahu dostanete 1-3 náhodné zbrane", ["Each turn you get one random weapon"] = "Každé koho dostanete jednu náhodnú zbraň", -- ["Eagle Eye"] = "", -- A_Classic_Fairytale:backstab --- ["Eagle Eye: [Blink to the impact ~ one shot]"] = "", -- Continental_supplies +-- ["Eagle Eye: [Blink to the impact ~ One shot]"] = "", -- Continental_supplies + -- ["Ear Sniffer"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:epil -- ["Elderbot"] = "", -- A_Classic_Fairytale:family -- ["Elimate your captor."] = "", -- User_Mission_-_The_Great_Escape @@ -208,8 +260,9 @@ -- ["Every single time!"] = "", -- A_Classic_Fairytale:dragon -- ["Everything looks OK..."] = "", -- A_Classic_Fairytale:enemy -- ["Exactly, man! That was my dream."] = "", -- A_Classic_Fairytale:backstab +-- ["Extra Damage"] = "", -- Construction_Mode +-- ["Extra Time"] = "", -- Construction_Mode -- ["Eye Chewer"] = "", -- A_Classic_Fairytale:journey --- ["INSANITY"] = "", -- Mutant -- ["Family Reunion"] = "", -- A_Classic_Fairytale:family ["Fastest lap: "] = "Najrýchlejšie kolo: ", ["Feeble Resistance"] = "Slabý odpor", @@ -219,10 +272,11 @@ -- ["Femur Lover"] = "", -- A_Classic_Fairytale:shadow -- ["Fierce Competition!"] = "", -- Space_Invasion -- ["Fiery Water"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united +-- ["Filthy Blue"] = "", -- User_Mission_-_Dangerous_Ducklings -- ["Find your tribe!|Cross the lake!"] = "", -- A_Classic_Fairytale:dragon -- ["Finish your training|Hint: Animations can be skipped with the [Precise] key."] = "", -- A_Classic_Fairytale:first_blood -- ["Fire"] = "", --- ["Fire a mine: [Does what it says ~ Cant be dropped close to an enemy ~ 1 sec]"] = "", -- Continental_supplies + -- ["First aid kits?!"] = "", -- A_Classic_Fairytale:united -- ["First Blood"] = "", -- A_Classic_Fairytale:first_blood -- ["FIRST BLOOD MUTATES"] = "", -- Mutant @@ -232,11 +286,15 @@ ["Flag returned!"] = "Vlajka vrátená!", ["Flags, and their home base will be placed where each team ends their first turn."] = "Vlajky a domovské základňe budú umiestnené tam, kde každý tím skončí svoj ťah.", ["Flamer"] = "Plameňomet", +-- ["Flamethrower"] = "", -- Construction_Mode -- ["Flaming Worm"] = "", -- A_Classic_Fairytale:backstab --- ["Flare: [fire up some bombs depending on hogs depending on hogs in the circle"] = "", -- Continental_supplies + -- ["Flesh for Brainz"] = "", -- A_Classic_Fairytale:journey +-- ["Flying Saucer"] = "", -- Construction_Mode, Frenzy -- ["For improved features/stability, play 0.9.18+"] = "", -- WxW -- ["Free Dense Cloud and continue the mission!"] = "", -- A_Classic_Fairytale:journey +-- ["Freezer"] = "", -- Construction_Mode +-- ["FRENZY"] = "", -- Frenzy -- ["Friendly Fire!"] = "", ["fuel extended!"] = "palivo doplnené!", ["GAME BEGUN!!!"] = "HRA ZAČALA!!!", @@ -246,6 +304,9 @@ -- ["Game? Was this a game to you?!"] = "", -- A_Classic_Fairytale:enemy -- ["GasBomb"] = "", -- Continental_supplies -- ["Gas Gargler"] = "", -- A_Classic_Fairytale:queen +-- ["General information"] = "", -- Continental_supplies +-- ["Generates power."] = "", -- Construction_Mode +-- ["Generator"] = "", -- Construction_Mode -- ["Get Dense Cloud out of the pit!"] = "", -- A_Classic_Fairytale:journey ["Get on over there and take him out!"] = "Okamžite sa tam presuň a zneškodni ho!", -- ["Get on the head of the mole"] = "", -- A_Classic_Fairytale:first_blood @@ -256,6 +317,8 @@ -- ["Get your teammates out of their natural prison and save the princess!|Hint: Drilling holes should solve everything.|Hint: It might be a good idea to place a girder before starting to drill. Just saying.|Hint: All your hedgehogs need to be above the marked height!|Hint: Leaks A Lot needs to get really close to the princess!"] = "", -- A_Classic_Fairytale:family -- ["GG!"] = "", -- User_Mission_-_Rope_Knock_Challenge -- ["Gimme Bones"] = "", -- A_Classic_Fairytale:backstab +-- ["Girder"] = "", -- Construction_Mode +-- ["Girder Placement Mode"] = "", -- Construction_Mode -- ["Glark"] = "", -- A_Classic_Fairytale:shadow ["Goal"] = "Cieľ", ["GO! GO! GO!"] = "POHYB! POHYB! POHYB!", @@ -272,12 +335,16 @@ -- ["Go surf!"] = "", -- WxW ["GOTCHA!"] = "A MÁM ŤA!", -- ["Grab Mines/Explosives"] = "", -- Tumbler +-- ["Grants nearby hogs life-regeneration."] = "", -- Construction_Mode +-- ["Gravity"] = "", -- Gravity -- ["Great choice, Steve! Mind if I call you that?"] = "", -- A_Classic_Fairytale:shadow -- ["Great work! Now hit it with your Baseball Bat! |Tip: You can change weapon with 'Right Click'!"] = "", -- Basic_Training_-_Rope -- ["Great! You will be contacted soon for assistance."] = "", -- A_Classic_Fairytale:shadow --- ["Green lipstick bullet: [Is poisonous]"] = "", -- Continental_supplies + +-- ["Green lipstick bullet: [Poisonous, deals no damage]"] = "", -- Continental_supplies -- ["Greetings, "] = "", -- A_Classic_Fairytale:dragon -- ["Greetings, cloudy one!"] = "", -- A_Classic_Fairytale:shadow +-- ["Grenade"] = "", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 -- ["Grenade Training"] = "", -- Basic_Training_-_Grenade -- ["Grenadiers"] = "", -- Basic_Training_-_Grenade -- ["Guys, do you think there's more of them?"] = "", -- A_Classic_Fairytale:backstab @@ -285,23 +352,27 @@ -- ["Haha!"] = "", -- A_Classic_Fairytale:united ["Hahahaha!"] = "Hehehehe!", ["Haha, now THAT would be something!"] = "Haha, tak TO by bolo niečo!", +-- ["Hammer"] = "", -- Construction_Mode, Continental_supplies -- ["Hannibal"] = "", -- A_Classic_Fairytale:epil ["Hapless Hogs"] = "Bezmocní ježkovia", [" Hapless Hogs left!"] = " Bezmocných ježkov ostalo!", - -- [" HAS MUTATED"] = "", -- Mutant -- ["Hatless Jerry"] = "", -- A_Classic_Fairytale:queen -- ["Have no illusions, your tribe is dead, indifferent of your choice."] = "", -- A_Classic_Fairytale:shadow -- ["Have we ever attacked you first?"] = "", -- A_Classic_Fairytale:enemy +-- ["Healing Station"] = "", -- Construction_Mode +-- ["Health Crate Placement Mode"] = "", -- Construction_Mode ["Health crates extend your time."] = "Lekárničky vám dávajú čas naviac.", -- ["Heavy Cannfantry"] = "", -- A_Classic_Fairytale:united ["Heavy"] = "Ťažký", -- ["Hedge-cogs"] = "", -- A_Classic_Fairytale:enemy --- ["Hedgehog projectile: [fire your hog like a Sticky Bomb]"] = "", -- Continental_supplies +-- ["Hedgehog projectile: [Fire your hog like a Sticky Bomb]"] = "", -- Continental_supplies + ["Hedgewars-Basketball"] = "Hedgewars-Basketbal", ["Hedgewars-Knockball"] = "Hedgewars-Knockball", -- ["Hedgibal Lecter"] = "", -- A_Classic_Fairytale:backstab ["Heh, it's not that bad."] = "Heh, to nie je také zlé.", +-- ["Hellish Handgrenade"] = "", -- Construction_Mode -- ["Hello again, "] = "", -- A_Classic_Fairytale:family -- ["Help me, Leaks!"] = "", -- A_Classic_Fairytale:journey -- ["Help me, please!!!"] = "", -- A_Classic_Fairytale:journey @@ -333,6 +404,7 @@ -- ["Hogminator"] = "", -- A_Classic_Fairytale:family -- ["Hogs in sight!"] = "", -- Continental_supplies -- ["HOLY SHYTE!"] = "", -- Mutant +-- ["Homing Bee"] = "", -- Construction_Mode -- ["Honest Lee"] = "", -- A_Classic_Fairytale:enemy ["Hooray!"] = "Hurá!", -- ["Hostage Situation"] = "", -- A_Classic_Fairytale:family @@ -366,7 +438,6 @@ -- ["If you get stuck, use your Desert Eagle or restart the mission!|"] = "", -- A_Classic_Fairytale:journey -- ["If you know what I mean..."] = "", -- A_Classic_Fairytale:shadow -- ["If you say so..."] = "", -- A_Classic_Fairytale:shadow - -- ["I guess you'll have to kill them."] = "", -- A_Classic_Fairytale:dragon -- ["I have come to make you an offering..."] = "", -- A_Classic_Fairytale:shadow -- ["I have no idea where that mole disappeared...Can you see it?"] = "", -- A_Classic_Fairytale:shadow @@ -389,6 +460,7 @@ -- ["I'm not sure about that!"] = "", -- A_Classic_Fairytale:united -- ["Impressive...you are still dry as the corpse of a hawk after a week in the desert..."] = "", -- A_Classic_Fairytale:first_blood -- ["I'm so scared!"] = "", -- A_Classic_Fairytale:united +-- ["Increase"] = "", -- Continental_supplies -- ["Incredible..."] = "", -- A_Classic_Fairytale:shadow -- ["I need to find the others!"] = "", -- A_Classic_Fairytale:backstab -- ["I need to get to the other side of this island, fast!"] = "", -- A_Classic_Fairytale:journey @@ -397,12 +469,14 @@ -- ["I need to warn the others."] = "", -- A_Classic_Fairytale:backstab -- ["In fact, you are the only one that's been acting strangely."] = "", -- A_Classic_Fairytale:backstab -- ["In order to get to the other side, you need to collect the crates first.|"] = "", -- A_Classic_Fairytale:dragon +-- ["INSANITY"] = "", -- Mutant ["Instructor"] = "Inštruktor", -- 01#Boot_Camp, User_Mission_-_Dangerous_Ducklings -- ["Interesting idea, haha!"] = "", -- A_Classic_Fairytale:enemy -- ["Interesting! Last time you said you killed a cannibal!"] = "", -- A_Classic_Fairytale:backstab -- ["In the meantime, take these and return to your \"friend\"!"] = "", -- A_Classic_Fairytale:shadow ["invaders destroyed"] = "votrelci zničení", -- ["Invasion"] = "", -- A_Classic_Fairytale:united +-- ["Invulnerable"] = "", -- Construction_Mode -- ["I saw it with my own eyes!"] = "", -- A_Classic_Fairytale:shadow -- ["I see..."] = "", -- A_Classic_Fairytale:shadow -- ["I see you have already taken the leap of faith."] = "", -- A_Classic_Fairytale:first_blood @@ -445,6 +519,7 @@ -- ["Just kidding, none of you have died!"] = "", -- A_Classic_Fairytale:enemy -- ["Just on a walk."] = "", -- A_Classic_Fairytale:united -- ["Just wait till I get my hands on that trauma! ARGH!"] = "", -- A_Classic_Fairytale:family +-- ["Kamikaze"] = "", -- Construction_Mode ["Kamikaze Expert!"] = "Expert na samovraždy!", -- ["Keep it up!"] = "", -- Basic_Training_-_Sniper_Rifle -- ["Kerguelen"] = "", -- Continental_supplies @@ -454,6 +529,8 @@ -- ["Kill the aliens!"] = "", -- A_Classic_Fairytale:dragon -- ["Kill the cannibal!"] = "", -- A_Classic_Fairytale:first_blood -- ["Kill the traitor...or spare his life!|Kill him or press [Precise]!"] = "", -- A_Classic_Fairytale:backstab +-- ["Land Sprayer"] = "", -- Construction_Mode +-- ["Laser Sight"] = "", -- Construction_Mode -- ["Last Target!"] = "", -- Basic_Training_-_Sniper_Rifle -- ["Leader"] = "", -- A_Classic_Fairytale:enemy -- ["Leaderbot"] = "", -- A_Classic_Fairytale:queen @@ -463,6 +540,7 @@ -- ["Leaks A Lot must survive!"] = "", -- A_Classic_Fairytale:journey -- ["Led Heart"] = "", -- A_Classic_Fairytale:queen -- ["Lee"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen +-- ["left shift"] = "", -- Continental_supplies ["[Left Shift]"] = "[Ľavý Shift]", -- ["Let a Continent provide your weapons!"] = "", -- Continental_supplies -- ["Let me test your skills a little, will you?"] = "", -- A_Classic_Fairytale:journey @@ -473,41 +551,56 @@ -- ["Let them have a taste of my fury!"] = "", -- A_Classic_Fairytale:backstab -- ["Let us help, too!"] = "", -- A_Classic_Fairytale:backstab -- ["Light Cannfantry"] = "", -- A_Classic_Fairytale:united +-- ["Limburger"] = "", -- Construction_Mode ["Listen up, maggot!!"] = "Počúvaj, ty biedny červ!", -- ["Little did they know that this hunt will mark them forever..."] = "", -- A_Classic_Fairytale:shadow -- ["Lively Lifeguard"] = "", -- User_Mission_-_That_Sinking_Feeling --- ["Lonely Cries: [Rise the water if no hog is in the circle and deal 1 damage to all hogs]"] = "", -- Continental_supplies + +-- ["Lonely Cries: [Rise the water if no hog is in the circle and deal 7 damage to all enemy hogs]"] = "", -- Continental_supplies +-- ["Lonely Hog"] = "", -- ClimbHome -- ["Look, I had no choice!"] = "", -- A_Classic_Fairytale:backstab -- ["Look out! There's more of them!"] = "", -- A_Classic_Fairytale:backstab -- ["Look out! We're surrounded by cannibals!"] = "", -- A_Classic_Fairytale:enemy -- ["Looks like the whole world is falling apart!"] = "", -- A_Classic_Fairytale:enemy +-- ["Low Gravity"] = "", -- Construction_Mode, Frenzy -- ["Luckily, I've managed to snatch some of them."] = "", -- A_Classic_Fairytale:united -- ["LUDICROUS KILL"] = "", -- Mutant +-- ["Made it!"] = "", -- ClimbHome +-- ["- Massive weapon bonus on first turn"] = "", -- Continental_supplies -- ["May the spirits aid you in all your quests!"] = "", -- A_Classic_Fairytale:backstab -- ["Medicine: [Fire some exploding medicine that will heal all hogs effected by the explosion]"] = "", -- Continental_supplies -- ["MEGA KILL"] = "", -- Mutant -- ["Meiwes"] = "", -- A_Classic_Fairytale:backstab -- ["Mindy"] = "", -- A_Classic_Fairytale:united +-- ["Mine"] = "", -- Construction_Mode, Frenzy -- ["Mine Deployer"] = "", -- Space_Invasion, Tumbler -- ["Mine Eater!"] = "", -- Tumbler +-- ["Mine Placement Mode"] = "", -- Construction_Mode ["|- Mines Time:"] = "|- Časovač pre míny:", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork +-- ["Mine Strike"] = "", -- Construction_Mode ["MISSION FAILED"] = "MISIA NEÚSPEŠNÁ", -- User_Mission_-_Dangerous_Ducklings, User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork ["MISSION SUCCESSFUL"] = "MISIA ÚSPEŠNÁ", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork ["MISSION SUCCESS"] = "MISIA ÚSPEŠNÁ", +-- ["Molotov Cocktail"] = "", -- Construction_Mode -- ["Molotov"] = "", -- Continental_supplies -- ["MONSTER KILL"] = "", -- Mutant -- ["More Natives"] = "", -- A_Classic_Fairytale:epil +-- ["Mortar"] = "", -- Construction_Mode, A_Space_Adventure:death02 ["Movement: [Up], [Down], [Left], [Right]"] = "Pohyb: [Hore], [Dole], [Vľavo], [Vpravo]", +-- ["Mudball"] = "", -- Construction_Mode ["Multi-shot!"] = "Viacnásobná rana!", -- ["Muriel"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen -- ["Muscle Dissolver"] = "", -- A_Classic_Fairytale:shadow -- ["-------"] = "", -- Mutant +-- ["Mutant"] = "", -- Mutant -- ["Nade Boy"] = "", -- Basic_Training_-_Grenade -- ["Name"] = "", -- A_Classic_Fairytale:queen ["Nameless Heroes"] = "Hrdinovia bez mena", -- ["Nancy Screw"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:queen +-- ["Napalm"] = "", -- Construction_Mode -- ["Napalm rocket: [Fire a bomb with napalm!]"] = "", -- Continental_supplies -- ["Natives"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:first_blood, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united +-- ["Naughty Ninja"] = "", -- User_Mission_-_Dangerous_Ducklings -- ["New Barrels Per Turn"] = "", -- Tumbler ["NEW CLAN RECORD: "] = "NOVÝ KLANOVÝ REKORD: ", ["NEW fastest lap: "] = "NOVÉ najrýchlejšie kolo: ", @@ -518,6 +611,7 @@ -- ["Nice work, "] = "", -- A_Classic_Fairytale:dragon -- ["Nice work!"] = "", -- A_Classic_Fairytale:enemy -- ["Nilarian"] = "", -- A_Classic_Fairytale:queen +-- ["Nobody Laugh"] = "", -- User_Mission_-_Nobody_Laugh -- ["No, I came back to help you out..."] = "", -- A_Classic_Fairytale:shadow -- ["No...I wonder where they disappeared?!"] = "", -- A_Classic_Fairytale:journey -- ["Nom-Nom"] = "", -- A_Classic_Fairytale:journey @@ -525,6 +619,7 @@ -- ["Nope. It was one fast mole, that's for sure."] = "", -- A_Classic_Fairytale:shadow -- ["No! Please, help me!"] = "", -- A_Classic_Fairytale:journey -- ["NORMAL"] = "", -- Continental_supplies +-- ["Normal players can only score points by killing the mutant."] = "", -- Mutant -- ["North America"] = "", -- Continental_supplies -- ["Not all hogs are born equal."] = "", -- Highlander ["NOT ENOUGH WAYPOINTS"] = "NEDOSTATOK NAVIGAČNÝCH BODOV", @@ -537,6 +632,7 @@ -- ["No. Where did he come from?"] = "", -- A_Classic_Fairytale:shadow -- ["Now how do I get on the other side?!"] = "", -- A_Classic_Fairytale:dragon -- ["No. You and the rest of the tribe are safer there!"] = "", -- A_Classic_Fairytale:backstab +-- ["Object Placement Tool"] = "", -- Construction_Mode -- ["Obliterate them!|Hint: You might want to take cover..."] = "", -- A_Classic_Fairytale:shadow -- ["Obstacle course"] = "", -- A_Classic_Fairytale:dragon -- ["Of course I have to save her. What did I expect?!"] = "", -- A_Classic_Fairytale:family @@ -553,24 +649,30 @@ -- ["Once upon a time, on an island with great natural resources, lived two tribes in heated conflict..."] = "", -- A_Classic_Fairytale:first_blood -- ["ONE HOG PER TEAM! KILLING EXCESS HEDGES"] = "", -- Mutant -- ["One tribe was peaceful, spending their time hunting and training, enjoying the small pleasures of life..."] = "", -- A_Classic_Fairytale:first_blood +-- ["on Skip"] = "", -- Continental_supplies -- ["Oops...I dropped them."] = "", -- A_Classic_Fairytale:united -- ["Open that crate and we will continue!"] = "", -- A_Classic_Fairytale:first_blood ["Operation Diver"] = "Operácia Potápač", ["Opposing Team: "] = "Nepriateľský tím", +-- ["or 'g=50, g2=150, period=4000' for gravity changing|from 50 to 150 and back with period of 4000 msec"] = "", -- Gravity -- ["Orlando Boom!"] = "", -- A_Classic_Fairytale:queen +-- ["Other kills don't give you points."] = "", -- Mutant -- ["Ouch!"] = "", -- User_Mission_-_Rope_Knock_Challenge -- ["Our tribe, our beautiful island!"] = "", -- A_Classic_Fairytale:enemy -- ["Parachute"] = "", -- Continental_supplies ["Pathetic Hog #%d"] = "Žalostný ježko #%d", -- ["Pathetic Resistance"] = "", -- User_Mission_-_Bamboo_Thicket, User_Mission_-_Newton_and_the_Hammock +-- ["Penguin roar: [Deal 15 damage + 15% of your hogs health to all hogs around you and get 2/3 back]"] = "", -- Continental_supplies -- ["Perfect! Now try to get the next crate without hurting yourself!"] = "", -- A_Classic_Fairytale:first_blood ["Per-Hog Ammo"] = "Samostatná munícia pre ježkov", --- ["- Per team weapons|- 9 weaponschemes|- Unique new weapons| |Select continent first round with the Weapon Menu or by ([switch/tab]=Increase,[precise/left shift]=Decrease) on Skip|Some weapons have a second option. Find them with [switch/tab]"] = "", -- Continental_supplies +-- ["Personal Portal Device"] = "", -- Construction_Mode +-- ["Per team weapons"] = "", -- Continental_supplies -- ["Pfew! That was close!"] = "", -- A_Classic_Fairytale:shadow --- ["Piñata bullet: [Contains some sweet candy!]"] = "", -- Continental_supplies +-- ["Piano Strike"] = "", -- Construction_Mode +-- ["Pickhammer"] = "", -- Construction_Mode + -- ["Pings left:"] = "", -- Space_Invasion - -- ["Place more waypoints using the 'Air Attack' weapon."] = "", -- Racer -- ["Planes Used:"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Planes Used"] = "", -- User_Mission_-_RCPlane_Challenge @@ -580,14 +682,18 @@ -- ["Please, stop releasing your \"smoke signals\"!"] = "", -- A_Classic_Fairytale:shadow -- ["Point Blank Combo!"] = "", -- Space_Invasion ["points"] = "body", -- Control, CTF_Blizzard, Basic_Training_-_Bazooka, Basic_Training_-_Shotgun, Basic_Training_-_Sniper_Rifle +-- ["POINTS"] = "", -- Mutant ["Poison"] = "Poison", +-- ["Population"] = "", -- Continental_supplies -- ["Portal hint: one goes to the destination, and one is the entrance.|"] = "", -- A_Classic_Fairytale:dragon -- ["Portal mission"] = "", -- portal ["Power Remaining"] = "Zostáva energie", -- ["Prepare yourself"] = "", -- The_Specialists +-- ["presice"] = "", -- Continental_supplies -- ["Press [Enter] to accept this configuration."] = "", -- WxW -- ["Press [Left] or [Right] to move around, [Enter] to jump"] = "", -- A_Classic_Fairytale:first_blood ["Press [Precise] to skip intro"] = "Stlačte [Presnejšie mierenie] pre preskočenie intra", +-- ["Prestigious Pilot"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Private Novak"] = "", -- Basic_Training_-_Cluster_Bomb -- ["Protect yourselves!|Grenade hint: set the timer with [1-5], aim with [Up]/[Down] and hold [Space] to set power"] = "", -- A_Classic_Fairytale:shadow ["Race complexity limit reached."] = "Bol dosiahnutý limit zložitosti závodu.", @@ -596,25 +702,39 @@ -- ["Radar Ping"] = "", -- Space_Invasion -- ["Raging Buffalo"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united -- ["Ramon"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow +-- ["random in range from %i%% to %i%% with period of %i msec"] = "", -- Gravity +-- ["RC Plane"] = "", -- Construction_Mode -- ["RC PLANE TRAINING"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Really?! You thought you could harm me with your little toys?"] = "", -- A_Classic_Fairytale:shadow +-- ["Reflector Shield"] = "", -- Construction_Mode +-- ["Reflects enemy projectiles."] = "", -- Construction_Mode -- ["Regurgitator"] = "", -- A_Classic_Fairytale:backstab -- ["Reinforcements"] = "", -- A_Classic_Fairytale:backstab -- ["Remember: The rope only bend around objects, |if it doesn't hit anything it's always stright!"] = "", -- Basic_Training_-_Rope -- ["Remember this, pathetic animal: when the day comes, you will regret your blind loyalty!"] = "", -- A_Classic_Fairytale:shadow +-- ["REMOVED"] = "", -- Continental_supplies +-- ["Respawner"] = "", -- Construction_Mode +-- ["Resurrector"] = "", -- Construction_Mode +-- ["Resurrects dead hedgehogs."] = "", -- Construction_Mode [" - Return the enemy flag to your base to score | - First team to 3 captures wins | - You may only score when your flag is in your base | - Hogs will drop the flag if killed, or drowned | - Dropped flags may be returned or recaptured | - Hogs respawn when killed"] = " - Skórujete prinesením nepriateľskej vlajky do vašej základne | - Prvý tím, ktorý dosiahne 3 body, vyhráva | - Skórujete len vtedy, keď je máte svoju vlajku v základni | - Spadnuté vlajky môžu byť vrátené na základňu alebo sa ich môže zmocniť súpere | - Ježkovia po smrti ožiujú", -- ["Return to Leaks A Lot! If you get stuck, press [Precise] to try again!"] = "", -- A_Classic_Fairytale:shadow -- ["Righteous Beard"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:first_blood, A_Classic_Fairytale:queen, A_Classic_Fairytale:united +-- ["Rope"] = "", -- Construction_Mode -- ["ROPE-KNOCKING"] = "", -- User_Mission_-_Rope_Knock_Challenge +-- ["Rope to safety"] = "", -- ClimbHome -- ["Rope Training"] = "", -- Basic_Training_-_Rope -- ["Rot Molester"] = "", -- A_Classic_Fairytale:shadow ["Round Limit"] = "Limit na kolo", -- ["Round Limit:"] = "", -- Racer ["Rounds Complete"] = "Dokončených kôl", -- ["Rounds Complete: "] = "", -- Racer +-- ["Rubber Band"] = "", -- Construction_Mode +-- ["Rubber Placement Mode"] = "", -- Construction_Mode +-- ["RULES"] = "", -- Frenzy, Mutant ["RULES OF THE GAME [Press ESC to view]"] = "PRAVIDLÁ HRY [Stlačte Esc pre ich zobrazenie]", -- ["Rusty Joe"] = "", -- A_Classic_Fairytale:queen --- ["Sabotage: [Sabotage all hogs in the circle and deal ~10 dmg]"] = "", -- Continental_supplies +-- ["Sabotage/Flare: [Sabotage all hogs in the circle and deal ~1 dmg OR Fire a cluster up into the air]"] = "", -- Continental_supplies + -- ["Salivaslurper"] = "", -- A_Classic_Fairytale:united -- ["Salvation"] = "", -- A_Classic_Fairytale:family -- ["Salvation was one step closer now..."] = "", -- A_Classic_Fairytale:dragon @@ -626,7 +746,7 @@ -- ["Scalp Muncher"] = "", -- A_Classic_Fairytale:backstab -- ["Score"] = "", -- Mutant ["SCORE"] = "SKÓRE", --- ["Scream from a Walrus: [Deal 20 damage + 10% of your hogs health to all hogs around you and get half back]"] = "", -- Continental_supplies + ["sec"] = "sek", -- CTF_Blizzard, TrophyRace, Basic_Training_-_Bazooka, Basic_Training_-_Shotgun, Basic_Training_-_Sniper_Rifle, User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork, Capture_the_Flag -- ["Seduction"] = "", -- Continental_supplies -- ["Seems like every time you take a \"walk\", the enemy find us!"] = "", -- A_Classic_Fairytale:backstab @@ -634,8 +754,11 @@ ["See ya!"] = "Tak zatiaľ!", -- ["Segmentation Paul"] = "", -- A_Classic_Fairytale:dragon -- ["Select continent!"] = "", -- Continental_supplies +-- ["Select continent first round with the Weapon Menu or by"] = "", -- Continental_supplies -- ["Select difficulty: [Left] - easier or [Right] - harder"] = "", -- A_Classic_Fairytale:first_blood -- ["selected!"] = "", -- Space_Invasion, Tumbler +-- ["Set period to negative value for random gravity"] = "", -- Gravity +-- ["Setup:|'g=150', where 150 is 150% of normal gravity"] = "", -- Gravity -- ["... share your beauty with the world every morning, my princess!"] = "", -- A_Classic_Fairytale:journey -- ["She's behind that tall thingy."] = "", -- A_Classic_Fairytale:family ["Shield boosted! +30 power"] = "Štít posilnený! Energia +30", @@ -646,17 +769,22 @@ ["Shield OFF:"] = "Štít VYPNUTÝ:", ["Shield ON:"] = "Štít ZAPNUTÝ:", ["Shield Seeker!"] = "Hľadač štítov!", +-- ["Shoryuken"] = "", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 -- ["Shotgun"] = "", -- Continental_supplies ["Shotgun Team"] = "Shotgun tím", ["Shotgun Training"] = "Tréning s brokovnicou", ["Shots Left: "] = "Zostáva striel: ", -- GaudyRacer, Tumbler ["shots remaining."] = "striel ostáva.", ["Silly"] = "Hlúpy", +-- ["SineGun"] = "", -- Construction_Mode ["Sinky"] = "Prepadnutý", -- ["Sirius Lee"] = "", -- A_Classic_Fairytale:enemy ["%s is out and Team %d|scored a penalty!| |Score:"] = "%s je mimo hru a tím %d|dostal trestný bod!| |Skóre:", -- Basketball, Knockball ["%s is out and Team %d|scored a point!| |Score:"] = "%s je mimo hru a tím %d|získal bod!| |Skóre:", -- Basketball, Knockball -- ["Slippery"] = "", -- A_Classic_Fairytale:journey +-- ["Slot"] = "", -- Frenzy +-- ["Slot keys save time! (F1-F10 by default)"] = "", -- Frenzy +-- ["SLOTS"] = "", -- Frenzy -- ["Smith 0.97"] = "", -- A_Classic_Fairytale:enemy -- ["Smith 0.98"] = "", -- A_Classic_Fairytale:enemy -- ["Smith 0.99a"] = "", -- A_Classic_Fairytale:enemy @@ -668,6 +796,7 @@ ["Sniper Training"] = "Tréning pre ostreľovačov", ["Sniperz"] = "Ostreľovači", -- ["So humiliating..."] = "", -- A_Classic_Fairytale:first_blood +-- ["Some weapons have a second option. Find them with"] = "", -- Continental_supplies -- ["South America"] = "", -- Continental_supplies -- ["So? What will it be?"] = "", -- A_Classic_Fairytale:shadow -- ["Spawn the crate, and attack!"] = "", -- WxW @@ -676,6 +805,8 @@ -- ["Spleenlover"] = "", -- A_Classic_Fairytale:united ["Sponge"] = "Špongia", ["Spooky Tree"] = "Strašidelný strom", +-- ["Sprite Placement Mode"] = "", -- Construction_Mode +-- ["Sprite Testing Mode"] = "", -- Construction_Mode ["s|"] = "s|", ["s"] = "s", -- GaudyRacer, Space_Invasion ["STATUS UPDATE"] = "AKTUALIZÁCIA STAVU", -- GaudyRacer, Space_Invasion @@ -683,20 +814,36 @@ -- ["Step By Step"] = "", -- A_Classic_Fairytale:first_blood -- ["Steve"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen -- ["Sticky Mine"] = "", -- Continental_supplies +-- ["Sticky Mine Placement Mode"] = "", -- Construction_Mode -- ["Stronglings"] = "", -- A_Classic_Fairytale:shadow --- ["Structure"] = "", -- Continental_supplies + +-- ["Structure Placement Mode"] = "", -- Construction_Mode +-- ["Structure Placement Tool"] = "", -- Construction_Mode +-- ["Sundaland"] = "", -- Continental_supplies -- ["Super Weapons"] = "", -- WxW +-- ["Support Station"] = "", -- Construction_Mode -- ["Surf Before Crate"] = "", -- WxW -- ["Surfer! +15 points!"] = "", -- Space_Invasion -- ["Surfer!"] = "", -- WxW -- ["Survive!|Hint: Cinematics can be skipped with the [Precise] key."] = "", -- A_Classic_Fairytale:shadow -- ["Swing, Leaks A Lot, on the wings of the wind!"] = "", -- A_Classic_Fairytale:first_blood +-- ["switch"] = "", -- Continental_supplies ["Switched to "] = "Prepnuté na ", +-- ["Switch Hog"] = "", -- Construction_Mode -- ["Syntax Errol"] = "", -- A_Classic_Fairytale:dragon +-- ["tab"] = "", -- Continental_supplies +-- ["Tagging Mode"] = "", -- Construction_Mode -- ["Talk about mixed signals..."] = "", -- A_Classic_Fairytale:dragon +-- ["Tardis"] = "", -- Construction_Mode +-- ["Target Placement Mode"] = "", -- Construction_Mode ["Team %d: "] = "Tím %d: ", ["Team Scores"] = "Tímové skóre", -- Control, Space_Invasion +-- ["Teleporation Node"] = "", -- Construction_Mode +-- ["Teleportation Mode"] = "", -- Construction_Mode +-- ["Teleportation Node"] = "", -- Construction_Mode +-- ["Teleport"] = "", -- Construction_Mode, Frenzy -- ["Teleport hint: just use the mouse to select the destination!"] = "", -- A_Classic_Fairytale:dragon +-- ["Teleport Unsuccessful. Please teleport within a clan teleporter's sphere of influence."] = "", -- Construction_Mode -- ["Thanks!"] = "", -- A_Classic_Fairytale:family -- ["Thank you, my hero!"] = "", -- A_Classic_Fairytale:family -- ["Thank you, oh, thank you, Leaks A Lot!"] = "", -- A_Classic_Fairytale:journey @@ -713,6 +860,7 @@ ["That was pointless."] = "To bolo zbytočné.", -- ["The answer is...entertaintment. You'll see what I mean."] = "", -- A_Classic_Fairytale:backstab -- ["The anti-portal zone is all over the floor, and I have nothing to kill him...Droping something could hurt him enough to kill him..."] = "", -- portal +-- ["The Bottom Feeder can score points by killing anyone."] = "", -- Mutant -- ["The Bull's Eye"] = "", -- A_Classic_Fairytale:first_blood -- ["The caves are well hidden, they won't find us there!"] = "", -- A_Classic_Fairytale:united -- ["The Crate Frenzy"] = "", -- A_Classic_Fairytale:first_blood @@ -722,20 +870,26 @@ -- ["The Enemy Of My Enemy"] = "", -- A_Classic_Fairytale:enemy -- ["The First Blood"] = "", -- A_Classic_Fairytale:first_blood -- ["The First Encounter"] = "", -- A_Classic_Fairytale:shadow +-- ["The first player to kill someone becomes the Mutant."] = "", -- Mutant ["The flag will respawn next round."] = "V ďalšom kole sa obnoví vlajka.", -- ["The food bites back"] = "", -- A_Classic_Fairytale:backstab -- ["The giant umbrella from the last crate should help break the fall."] = "", -- A_Classic_Fairytale:first_blood -- ["The Great Escape"] = "", -- User_Mission_-_The_Great_Escape +-- ["The Great Hog in the sky sees your sadness and grants you a boon."] = "", -- Construction_Mode -- ["The guardian"] = "", -- A_Classic_Fairytale:shadow -- ["The Individualist"] = "", -- A_Classic_Fairytale:shadow -- ["Their buildings were very primitive back then, even for an uncivilised island."] = "", -- A_Classic_Fairytale:united -- ["The Journey Back"] = "", -- A_Classic_Fairytale:journey -- ["The Leap of Faith"] = "", -- A_Classic_Fairytale:first_blood -- ["The Moonwalk"] = "", -- A_Classic_Fairytale:journey +-- ["The Mutant has super-weapons and a lot of health."] = "", -- Mutant +-- ["The Mutant loses health quickly if he doesn't keep scoring kills."] = "", -- Mutant ["The Nameless One"] = "Bez mena", -- ["The next one is pretty hard! |Tip: You have to do multiple swings!"] = "", -- Basic_Training_-_Rope -- ["Then how do they keep appearing?"] = "", -- A_Classic_Fairytale:shadow -- ["The other one were all cannibals, spending their time eating the organs of fellow hedgehogs..."] = "", -- A_Classic_Fairytale:first_blood +-- ["The player with least points (or most deaths) becomes the Bottom Feeder."] = "", -- Mutant +-- ["There are a variety of structures available to aid you."] = "", -- Construction_Mode -- ["There must be a spy among us!"] = "", -- A_Classic_Fairytale:backstab -- ["There's more of them? When did they become so hungry?"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united -- ["There's nothing more satisfying for me than seeing you share your beauty with the world every morning, my princess!"] = "", -- A_Classic_Fairytale:journey @@ -792,7 +946,7 @@ -- ["To the caves..."] = "", -- A_Classic_Fairytale:united ["Toxic Team"] = "Toxic tím", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork ["TRACK COMPLETED"] = "TRAŤ DOKONČENÁ", - ["TRACK FAILED!"] = "NEDOKONČILI STE TRAŤ!", + ["Track Time: "] = "Čas: ", -- ["training"] = "", -- portal -- ["Traitors"] = "", -- A_Classic_Fairytale:epil @@ -810,6 +964,7 @@ -- ["ULTRA KILL"] = "", -- Mutant -- ["Under Construction"] = "", -- A_Classic_Fairytale:shadow -- ["Unexpected Igor"] = "", -- A_Classic_Fairytale:dragon +-- ["Unique new weapons"] = "", -- Continental_supplies -- ["Unit 0x0007"] = "", -- A_Classic_Fairytale:family -- ["Unit 334a$7%;.*"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united ["Unit 3378"] = "Jednotka 3378", @@ -824,12 +979,15 @@ -- ["Use it wisely!"] = "", -- A_Classic_Fairytale:dragon -- ["Use it with precaution!"] = "", -- A_Classic_Fairytale:first_blood ["User Challenge"] = "Výzva", - +-- ["Use the air-attack weapons and the arrow keys to select structures."] = "", -- Construction_Mode -- ["Use the portal gun to get to the next crate, then use the new gun to get to the final destination!|"] = "", -- A_Classic_Fairytale:dragon -- ["Use the rope to get on the head of the mole, young one!"] = "", -- A_Classic_Fairytale:first_blood -- ["Use the rope to knock your enemies to their doom."] = "", -- User_Mission_-_Rope_Knock_Challenge +-- ["Use your ready time to think."] = "", -- Frenzy ["Use your rope to get from start to finish as fast as you can!"] = "Použite lano na presun zo štartovnej pozície do cieľa tak rýchlo, ako to len viete!", +-- ["Utility Crate Placement Mode"] = "", -- Construction_Mode ["v.06"] = "v.06", +-- ["Vampirism"] = "", -- Construction_Mode -- ["Vedgies"] = "", -- A_Classic_Fairytale:journey -- ["Vegan Jack"] = "", -- A_Classic_Fairytale:enemy -- ["Victory!"] = "", -- Basic_Training_-_Rope @@ -841,10 +999,14 @@ -- ["Wannabe Flyboys"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Wannabe Shoppsta"] = "", -- User_Mission_-_Rope_Knock_Challenge -- ["Watch your steps, young one!"] = "", -- A_Classic_Fairytale:first_blood +-- ["Watermelon Bomb"] = "", -- Construction_Mode ["Waypoint placed."] = "Navigačný bod umiestnený.", ["Way-Points Remaining"] = "Ostáva navigačných bodov", -- ["Weaklings"] = "", -- A_Classic_Fairytale:shadow -- ["We all know what happens when you get frightened..."] = "", -- A_Classic_Fairytale:first_blood +-- ["Weapon Crate Placement Mode"] = "", -- Construction_Mode +-- ["Weapon Filter"] = "", -- Construction_Mode +-- ["weaponschemes"] = "", -- Continental_supplies -- ["Weapons reset."] = "", -- Highlander ["Weapons Reset"] = "Reset zbraní", -- ["We are indeed."] = "", -- A_Classic_Fairytale:backstab @@ -897,6 +1059,7 @@ -- ["Where do you get that?!"] = "", -- A_Classic_Fairytale:enemy -- ["Where have you been?!"] = "", -- A_Classic_Fairytale:backstab -- ["Where have you been?"] = "", -- A_Classic_Fairytale:united +-- ["Whip"] = "", -- Construction_Mode -- ["? Why?"] = "", -- A_Classic_Fairytale:backstab -- ["Why "] = "", -- A_Classic_Fairytale:backstab -- ["! Why?!"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united @@ -909,8 +1072,10 @@ -- ["Why me?!"] = "", -- A_Classic_Fairytale:backstab -- ["Why would they do this?"] = "", -- A_Classic_Fairytale:backstab -- ["- Will Get 1-3 random weapons"] = "", -- Continental_supplies --- ["- Will refresh Parachute each turn."] = "", -- Continental_supplies --- ["- Will refresh portalgun each turn."] = "", -- Continental_supplies +-- ["- Will give you an airstrike every fifth turn."] = "", -- Continental_supplies +-- ["- Will give you a parachute every second turn."] = "", -- Continental_supplies + + ["Will this ever end?"] = "Skončí to vôbec niekedy?", -- ["WINNER IS "] = "", -- Mutant ["WINNING TIME: "] = "VÍŤAZNÝ ČAS: ", @@ -929,6 +1094,7 @@ -- ["Yes!"] = "", -- A_Classic_Fairytale:enemy -- ["Yes, yeees! You are now ready to enter the real world!"] = "", -- A_Classic_Fairytale:first_blood -- ["Yo, dude, we're here, too!"] = "", -- A_Classic_Fairytale:family +-- ["You are far from home, and the water is rising, climb up as high as you can!"] = "", -- ClimbHome -- ["You are given the chance to turn your life around..."] = "", -- A_Classic_Fairytale:shadow -- ["You are playing with our lives here!"] = "", -- A_Classic_Fairytale:enemy -- ["! You bastards!"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united @@ -961,6 +1127,8 @@ -- ["You know what? I don't even regret anything!"] = "", -- A_Classic_Fairytale:backstab -- ["You'll see what I mean!"] = "", -- A_Classic_Fairytale:enemy -- ["You may only attack from a rope!"] = "", -- WxW +-- ["You may only spawn 5 crates per turn."] = "", -- Construction_Mode +-- ["You may only use 1 Extra Time per turn."] = "", -- Construction_Mode -- ["You meatbags are pretty slow, you know!"] = "", -- A_Classic_Fairytale:enemy -- ["You might want to find a way to instantly kill arriving cannibals!"] = "", -- A_Classic_Fairytale:backstab -- ["Young one, you are telling us that they can instantly change location without a shaman?"] = "", -- A_Classic_Fairytale:united @@ -981,6 +1149,7 @@ ["You've failed. Try again."] = "Neuspeli ste. Skúste to znova.", ["You've reached the goal!| |Time: "] = "Dosiahli ste cieľ!| |Čas: ", -- ["You will be avenged!"] = "", -- A_Classic_Fairytale:shadow +-- ["- You will recieve 2-4 weapons on each kill! (Even on own hogs)"] = "", -- Continental_supplies -- ["You won't believe what happened to me!"] = "", -- A_Classic_Fairytale:backstab -- ["Yuck! I bet they'll keep worshipping her even after I save the village!"] = "", -- A_Classic_Fairytale:family -- ["Zealandia"] = "", -- Continental_supplies diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/stub.lua --- a/share/hedgewars/Data/Locale/stub.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/stub.lua Tue Nov 10 20:43:13 2015 +0100 @@ -4,26 +4,44 @@ -- ["..."] = "", -- ["011101000"] = "", -- A_Classic_Fairytale:dragon -- ["011101001"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:family, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united +-- ["+1 to a Bottom Feeder for killing anyone"] = "", -- Mutant +-- ["+1 to a Mutant for killing anyone"] = "", -- Mutant +-- ["-1 to anyone for a suicide"] = "", -- Mutant +-- ["+2 for becoming a Mutant"] = "", -- Mutant -- ["30 minutes later..."] = "", -- A_Classic_Fairytale:shadow -- ["About a month ago, a cyborg came and told us that you're the cannibals!"] = "", -- A_Classic_Fairytale:enemy +-- ["Above-average pilot"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Accuracy Bonus!"] = "", +-- ["Accuracy bonus: +%d points"] = "", -- Basic_Training_-_Sniper_Rifle -- ["Ace"] = "", -- User_Mission_-_RCPlane_Challenge, User_Mission_-_Rope_Knock_Challenge +-- ["Achievement obtained: Lively Lifeguard"] = "", -- User_Mission_-_That_Sinking_Feeling -- ["Achievement Unlocked"] = "", -- User_Mission_-_Bamboo_Thicket, User_Mission_-_That_Sinking_Feeling, Tumbler -- ["A Classic Fairytale"] = "", -- A_Classic_Fairytale:first_blood -- ["???"] = "", -- A_Classic_Fairytale:backstab -- ["Actually, you aren't worthy of life! Take this..."] = "", -- A_Classic_Fairytale:shadow -- ["A cy-what?"] = "", -- A_Classic_Fairytale:enemy +-- ["Advanced Repositioning Mode"] = "", -- Construction_Mode -- ["Adventurous"] = "", -- A_Classic_Fairytale:journey +-- ["a frenetic Hedgewars mini-game"] = "", -- Frenzy -- ["Africa"] = "", -- Continental_supplies -- ["After Leaks A Lot betrayed his tribe, he joined the cannibals..."] = "", -- A_Classic_Fairytale:first_blood -- ["After the shock caused by the enemy spy, Leaks A Lot and Dense Cloud went hunting to relax."] = "", -- A_Classic_Fairytale:shadow -- ["Again with the 'cannibals' thing!"] = "", -- A_Classic_Fairytale:enemy +-- ["Aggressively removes enemy hedgehogs."] = "", -- Construction_Mode -- ["a Hedgewars challenge"] = "", -- User_Mission_-_RCPlane_Challenge, User_Mission_-_Rope_Knock_Challenge -- ["a Hedgewars mini-game"] = "", -- Space_Invasion, The_Specialists +-- ["a Hedgewars tag game"] = "", -- Mutant +-- ["AHHh, home sweet home. Made it in %d seconds."] = "", -- ClimbHome -- ["Aiming Practice"] = "", --Bazooka, Shotgun, SniperRifle +-- ["Aiming practice"] = "", -- TargetPractice +-- ["Air Attack"] = "", -- Construction_Mode -- ["A leap in a leap"] = "", -- A_Classic_Fairytale:first_blood -- ["A little gift from the cyborgs"] = "", -- A_Classic_Fairytale:shadow -- ["All gone...everything!"] = "", -- A_Classic_Fairytale:enemy +-- ["Allows free teleportation between other nodes."] = "", -- Construction_Mode +-- ["Allows placement of girders, rubber-bands, mines, sticky mines and barrels."] = "", -- Construction_Mode +-- ["Allows placement of structures."] = "", -- Construction_Mode +-- ["Allows the placement of weapons, utiliites, and health crates."] = "", -- Construction_Mode -- ["All right, we just need to get to the other side of the island!"] = "", -- A_Classic_Fairytale:journey -- ["All walls touched!"] = "", -- WxW -- ["Ammo"] = "", @@ -38,8 +56,11 @@ -- ["And so they discovered that cyborgs weren't invulnerable..."] = "", -- A_Classic_Fairytale:journey -- ["And where's all the weed?"] = "", -- A_Classic_Fairytale:dragon -- ["And you believed me? Oh, god, that's cute!"] = "", -- A_Classic_Fairytale:journey --- ["Anno 1032: [The explosion will make a strong push ~ wide range, wont affect hogs close to the target]"] = "", -- Continental_supplies +-- ["Anno 1032: [The explosion will make a strong push ~ Wide range, wont affect hogs close to the target]"] = "", -- Continental_supplies + -- ["Antarctica"] = "", -- Continental_supplies +-- ["Antarctic summer: - Will give you one girder/mudball and two sineguns/portals every fourth turn."] = "", -- Continental_supplies +-- ["Area"] = "", -- Continental_supplies -- ["Are we there yet?"] = "", -- A_Classic_Fairytale:shadow -- ["Are you accusing me of something?"] = "", -- A_Classic_Fairytale:backstab -- ["Are you saying that many of us have died for your entertainment?"] = "", -- A_Classic_Fairytale:enemy @@ -54,34 +75,49 @@ -- ["Attack From Rope"] = "", -- WxW -- ["Australia"] = "", -- Continental_supplies -- ["Available points remaining: "] = "", +-- ["Average pilot"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Back Breaker"] = "", -- A_Classic_Fairytale:backstab -- ["Back in the village, after telling the villagers about the threat..."] = "", -- A_Classic_Fairytale:united -- ["[Backspace]"] = "", -- ["Backstab"] = "", -- A_Classic_Fairytale:backstab +-- ["Bad Guy"] = "", -- User_Mission_-_The_Great_Escape +-- ["badmad"] = "", -- portal -- ["Bad Team"] = "", -- User_Mission_-_The_Great_Escape --- ["Bamboo Thicket"] = "", +-- ["Ballgun"] = "", -- Construction_Mode +-- ["Bamboo Thicket"] = "", -- User_Mission_-_Bamboo_Thicket -- ["Barrel Eater!"] = "", -- ["Barrel Launcher"] = "", +-- ["Barrel Placement Mode"] = "", -- Construction_Mode +-- ["Baseball Bat"] = "", -- Construction_Mode -- ["Baseballbat"] = "", -- Continental_supplies -- ["Bat balls at your enemies and|push them into the sea!"] = "", -- ["Bat your opponents through the|baskets and out of the map!"] = "", +-- ["Bazooka"] = "", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 -- ["Bazooka Training"] = "", -- ["Beep Loopers"] = "", -- A_Classic_Fairytale:queen +-- ["Beginner"] = "", -- User_Mission_-_RCPlane_Challenge +-- ["Below-average pilot"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Best laps per team: "] = "", -- ["Best Team Times: "] = "", -- ["Beware, though! If you are slow, you die!"] = "", -- A_Classic_Fairytale:dragon +-- ["Bio-Filter"] = "", -- Construction_Mode -- ["Biomechanic Team"] = "", -- A_Classic_Fairytale:family +-- ["Birdy"] = "", -- Construction_Mode -- ["Blender"] = "", -- A_Classic_Fairytale:family -- ["Bloodpie"] = "", -- A_Classic_Fairytale:backstab -- ["Bloodrocutor"] = "", -- A_Classic_Fairytale:shadow -- ["Bloodsucker"] = "", -- A_Classic_Fairytale:shadow -- ["Bloody Rookies"] = "", -- 01#Boot_Camp, User_Mission_-_Dangerous_Ducklings, User_Mission_-_Diver, User_Mission_-_Spooky_Tree +-- ["Blowtorch"] = "", -- Construction_Mode, Frenzy +-- ["Blue Team"] = "", -- User_Mission_-_Dangerous_Ducklings +-- ["Bobo"] = "", -- User_Mission_-_Nobody_Laugh -- ["Bone Jackson"] = "", -- A_Classic_Fairytale:backstab -- ["Bonely"] = "", -- A_Classic_Fairytale:shadow +-- ["BOOM!"] = "", -- ["Boom!"] = "", --- ["BOOM!"] = "", -- ["Boss defeated!"] = "", -- ["Boss Slayer!"] = "", +-- ["BOTTOM FEEDER"] = "", -- Mutant -- ["Brain Blower"] = "", -- A_Classic_Fairytale:journey -- ["Brainiac"] = "", -- A_Classic_Fairytale:epil, A_Classic_Fairytale:first_blood, A_Classic_Fairytale:shadow -- ["Brainila"] = "", -- A_Classic_Fairytale:united @@ -89,6 +125,7 @@ -- ["Brain Teaser"] = "", -- A_Classic_Fairytale:backstab -- ["Brutal Lily"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil -- ["Brutus"] = "", -- A_Classic_Fairytale:backstab +-- ["Build a fortress and destroy your enemy."] = "", -- Construction_Mode -- ["Build a track and race."] = "", -- ["Bullseye"] = "", -- A_Classic_Fairytale:dragon -- ["But it proved to be no easy task!"] = "", -- A_Classic_Fairytale:dragon @@ -99,6 +136,9 @@ -- ["But why would they help us?"] = "", -- A_Classic_Fairytale:backstab -- ["But you're cannibals. It's what you do."] = "", -- A_Classic_Fairytale:enemy -- ["But you said you'd let her go!"] = "", -- A_Classic_Fairytale:journey +-- ["C-1"] = "", -- portal +-- ["C-2"] = "", -- portal +-- ["Cake"] = "", -- Construction_Mode -- ["Call me Beep! Well, 'cause I'm such a nice...person!"] = "", -- A_Classic_Fairytale:family -- ["Cannibals"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:first_blood -- ["Cannibal Sentry"] = "", -- A_Classic_Fairytale:journey @@ -106,10 +146,21 @@ -- ["CAPTURE THE FLAG"] = "", -- ["Careless"] = "", -- ["Carol"] = "", -- A_Classic_Fairytale:family +-- ["Challenge"] = "", -- SpeedShoppa -- ["CHALLENGE COMPLETE"] = "", -- User_Mission_-_RCPlane_Challenge +-- ["Challenge completed!"] = "", -- SpeedShoppa +-- ["Challenge failed!"] = "", -- SpeedShoppa -- ["Change Weapon"] = "", +-- ["changing range from %i%% to %i%% with period of %i msec"] = "", -- Gravity +-- ["Cheater"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Choose your side! If you want to join the strange man, walk up to him.|Otherwise, walk away from him. If you decide to att...nevermind..."] = "", -- A_Classic_Fairytale:shadow +-- ["Cleaver"] = "", -- Construction_Mode +-- ["Cleaver Placement Mode"] = "", -- Construction_Mode +-- ["Climber"] = "", -- ClimbHome +-- ["Climb Home"] = "", -- ClimbHome +-- ["Clowns"] = "", -- User_Mission_-_Nobody_Laugh -- ["Clumsy"] = "", +-- ["Cluster Bomb"] = "", -- Construction_Mode -- ["Cluster Bomb MASTER!"] = "", -- Basic_Training_-_Cluster_Bomb -- ["Cluster Bomb Training"] = "", -- Basic_Training_-_Cluster_Bomb -- ["Codename: Teamwork"] = "", @@ -126,40 +177,63 @@ -- ["Configuration accepted."] = "", -- WxW -- ["Congratulations!"] = "", -- ["Congratulations"] = "", -- Basic_Training_-_Rope +-- ["Congratulations! You have destroyed all targets within the time."] = "", -- TargetPractice +-- ["Congratulations! You have truly mastered this challenge! Don't forget to save the demo."] = "", -- User_Mission_-_RCPlane_Challenge -- ["Congratulations! You needed only half of time|to eliminate all targets."] = "", -- Basic_Training_-_Cluster_Bomb -- ["Congratulations! You've completed the Rope tutorial! |- Tutorial ends in 10 seconds!"] = "", -- Basic_Training_-_Rope -- ["Congratulations! You've eliminated all targets|within the allowed time frame."] = "", --Bazooka, Shotgun, SniperRifle +-- ["CONSTRUCTION MODE"] = "", -- Construction_Mode +-- ["Construction Station"] = "", -- Construction_Mode -- ["Continental supplies"] = "", -- Continental_supplies --- ["Control pillars to score points."] = "", +-- ["CONTROL"] = "", -- Control +-- ["Control pillars to score points."] = "", -- Control +-- ["Copper"] = "", -- User_Mission_-_Nobody_Laugh +-- ["Core"] = "", -- Construction_Mode -- ["Corporationals"] = "", -- A_Classic_Fairytale:queen -- ["Corpsemonger"] = "", -- A_Classic_Fairytale:shadow -- ["Corpse Thrower"] = "", -- A_Classic_Fairytale:epil --- ["Crates Left:"] = "", -- User_Mission_-_RCPlane_Challenge --- ["Cybernetic Empire"] = "", +-- ["Cost"] = "", -- Construction_Mode +-- ["Crate Placement Tool"] = "", -- Construction_Mode +-- ["Crates left: %d"] = "", -- User_Mission_-_RCPlane_Challenge +-- ["crate(s)"] = "", -- SpeedShoppa +-- ["%d crate(s) remaining"] = "", -- SpeedShoppa +-- ["Cricket time: [Drop a fireable mine! ~ Will work if fired close to your hog & far away from enemy ~ 1 sec]"] = "", -- Continental_supplies +-- ["Current setting is "] = "", -- Gravity +-- ["Cybernetic Empire"] = "", -- User_Mission_-_Bamboo_Thicket -- ["Cyborg. It's what the aliens call themselves."] = "", -- A_Classic_Fairytale:enemy -- ["Dahmer"] = "", -- A_Classic_Fairytale:backstab -- ["DAMMIT, ROOKIE!"] = "", -- ["DAMMIT, ROOKIE! GET OFF MY HEAD!"] = "", --- ["Dangerous Ducklings"] = "", +-- ["Dangerous Ducklings"] = "", -- User_Mission_-_Dangerous_Ducklings -- ["Deadweight"] = "", +-- ["deaths"] = "", -- Mutant +-- ["Decrease"] = "", -- Continental_supplies -- ["Defeat the cannibals"] = "", -- A_Classic_Fairytale:backstab -- ["Defeat the cannibals!|"] = "", -- A_Classic_Fairytale:united -- ["Defeat the cannibals!|Grenade hint: set the timer with [1-5], aim with [Up]/[Down] and hold [Space] to set power"] = "", -- A_Classic_Fairytale:shadow -- ["Defeat the cyborgs!"] = "", -- A_Classic_Fairytale:enemy +-- ["Defend your core from the enemy."] = "", -- Construction_Mode -- ["Defend yourself!|Hint: You can get tips on using weapons by moving your mouse over them in the weapon selection menu"] = "", -- A_Classic_Fairytale:shadow +-- ["Dematerializes weapons and equipment carried by enemy hedgehogs."] = "", -- Construction_Mode +-- ["Demo"] = "", -- The_Specialists -- ["Demolition is fun!"] = "", -- ["Dense Cloud"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united -- ["Dense Cloud must have already told them everything..."] = "", -- A_Classic_Fairytale:shadow -- ["Depleted Kamikaze!"] = "", +-- ["Derp"] = "", -- User_Mission_-_Nobody_Laugh +-- ["Desert Eagle"] = "", -- Construction_Mode, A_Space_Adventure:death02 -- ["Destroy him, Leaks A Lot! He is responsible for the deaths of many of us!"] = "", -- A_Classic_Fairytale:first_blood -- ["Destroy invaders to score points."] = "", -- ["Destroy the targets!|Hint: Select the Shoryuken and hit [Space]|P.S. You can use it mid-air."] = "", -- A_Classic_Fairytale:first_blood -- ["Destroy the targets!|Hint: [Up], [Down] to aim, [Space] to shoot"] = "", -- A_Classic_Fairytale:first_blood +-- ["Destroyer of planes"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Did anyone follow you?"] = "", -- A_Classic_Fairytale:united -- ["Did you see him coming?"] = "", -- A_Classic_Fairytale:shadow -- ["Did you warn the village?"] = "", -- A_Classic_Fairytale:shadow -- ["Die, die, die!"] = "", -- A_Classic_Fairytale:dragon +-- ["Disabled"] = "", -- WxW -- ["Disguise as a Rockhopper Penguin: [Swap place with a random enemy hog in the circle]"] = "", -- Continental_supplies +-- ["Disqualified!"] = "", -- User_Mission_-_That_Sinking_Feeling -- ["Dist: "] = "", -- Space_Invasion -- ["Do not laugh, inexperienced one, for he speaks the truth!"] = "", -- A_Classic_Fairytale:backstab -- ["Do not let his words fool you, young one! He will stab you in the back as soon as you turn away!"] = "", -- A_Classic_Fairytale:first_blood @@ -169,10 +243,14 @@ -- ["Do you have any idea how valuable grass is?"] = "", -- A_Classic_Fairytale:enemy -- ["Do you think you're some kind of god?"] = "", -- A_Classic_Fairytale:enemy -- ["Dragon's Lair"] = "", -- A_Classic_Fairytale:dragon +-- ["Drill Rocket"] = "", -- Construction_Mode -- ["Drills"] = "", -- A_Classic_Fairytale:backstab +-- ["Drill Strike"] = "", -- Construction_Mode -- ["Drone Hunter!"] = "", --- ["Drop a bomb: [drop some heroic wind that will turn into a bomb on impact]"] = "", -- Continental_supplies --- ["Drowner"] = "", +-- ["Drop a bomb: [Drop some heroic wind that will turn into a bomb on impact]"] = "", -- Continental_supplies + +-- ["Drowner"] = "", -- User_Mission_-_Nobody_Laugh +-- ["Drunk greenhorn"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Dude, all the plants are gone!"] = "", -- A_Classic_Fairytale:family -- ["Dude, can you see Ramon and Spiky?"] = "", -- A_Classic_Fairytale:journey -- ["Dude, that's so cool!"] = "", -- A_Classic_Fairytale:backstab @@ -181,12 +259,17 @@ -- ["Dude, where are we?"] = "", -- A_Classic_Fairytale:backstab -- ["Dude, wow! I just had the weirdest high!"] = "", -- A_Classic_Fairytale:backstab -- ["Duration"] = "", -- Continental_supplies --- ["Dust storm: [Deals 20 damage to all enemies in the circle]"] = "", -- Continental_supplies +-- ["Dust storm: [Deals 15 damage to all enemies in the circle]"] = "", -- Continental_supplies + +-- ["Dynamite"] = "", -- Construction_Mode +-- ["Each turn is only ONE SECOND!"] = "", -- Frenzy -- ["Each turn you get 1-3 random weapons"] = "", -- ["Each turn you get one random weapon"] = "", -- ["Eagle Eye"] = "", -- A_Classic_Fairytale:backstab --- ["Eagle Eye: [Blink to the impact ~ one shot]"] = "", -- Continental_supplies +-- ["Eagle Eye: [Blink to the impact ~ One shot]"] = "", -- Continental_supplies + -- ["Ear Sniffer"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:epil +-- ["Eckles"] = "", -- User_Mission_-_Nobody_Laugh -- ["Elderbot"] = "", -- A_Classic_Fairytale:family -- ["Elimate your captor."] = "", -- User_Mission_-_The_Great_Escape -- ["Eliminate all enemies"] = "", @@ -198,8 +281,11 @@ -- ["Eliminate the enemy hogs to win."] = "", -- ["Eliminate the enemy specialists."] = "", -- ["- Eliminate Unit 3378 |- Feeble Resistance must survive"] = "", +-- ["Elite pilot"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Elmo"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen --- ["Energetic Engineer"] = "", +-- ["Enabled"] = "", -- WxW +-- ["Energetic Engineer"] = "", -- User_Mission_-_Bamboo_Thicket +-- ["Engineer"] = "", -- The_Specialists -- ["Enjoy the swim..."] = "", -- ["[Enter]"] = "", -- ["Europe"] = "", -- Continental_supplies @@ -208,8 +294,10 @@ -- ["Every single time!"] = "", -- A_Classic_Fairytale:dragon -- ["Everything looks OK..."] = "", -- A_Classic_Fairytale:enemy -- ["Exactly, man! That was my dream."] = "", -- A_Classic_Fairytale:backstab +-- ["Experienced beginner"] = "", -- User_Mission_-_RCPlane_Challenge +-- ["Extra Damage"] = "", -- Construction_Mode +-- ["Extra Time"] = "", -- Construction_Mode -- ["Eye Chewer"] = "", -- A_Classic_Fairytale:journey --- ["INSANITY"] = "", -- Mutant -- ["Family Reunion"] = "", -- A_Classic_Fairytale:family -- ["Fastest lap: "] = "", -- ["Feeble Resistance"] = "", @@ -219,10 +307,11 @@ -- ["Femur Lover"] = "", -- A_Classic_Fairytale:shadow -- ["Fierce Competition!"] = "", -- Space_Invasion -- ["Fiery Water"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united +-- ["Filthy Blue"] = "", -- User_Mission_-_Dangerous_Ducklings -- ["Find your tribe!|Cross the lake!"] = "", -- A_Classic_Fairytale:dragon -- ["Finish your training|Hint: Animations can be skipped with the [Precise] key."] = "", -- A_Classic_Fairytale:first_blood -- ["Fire"] = "", --- ["Fire a mine: [Does what it says ~ Cant be dropped close to an enemy ~ 1 sec]"] = "", -- Continental_supplies + -- ["First aid kits?!"] = "", -- A_Classic_Fairytale:united -- ["First Blood"] = "", -- A_Classic_Fairytale:first_blood -- ["FIRST BLOOD MUTATES"] = "", -- Mutant @@ -232,11 +321,17 @@ -- ["Flag returned!"] = "", -- ["Flags, and their home base will be placed where each team ends their first turn."] = "", -- ["Flamer"] = "", +-- ["Flamethrower"] = "", -- Construction_Mode -- ["Flaming Worm"] = "", -- A_Classic_Fairytale:backstab --- ["Flare: [fire up some bombs depending on hogs depending on hogs in the circle"] = "", -- Continental_supplies +-- ["Flawless victory!"] = "", -- User_Mission_-_RCPlane_Challenge + -- ["Flesh for Brainz"] = "", -- A_Classic_Fairytale:journey +-- ["Flying Saucer"] = "", -- Construction_Mode, Frenzy -- ["For improved features/stability, play 0.9.18+"] = "", -- WxW +-- ["Frank"] = "", -- User_Mission_-_Nobody_Laugh -- ["Free Dense Cloud and continue the mission!"] = "", -- A_Classic_Fairytale:journey +-- ["Freezer"] = "", -- Construction_Mode +-- ["FRENZY"] = "", -- Frenzy -- ["Friendly Fire!"] = "", -- ["fuel extended!"] = "", -- ["GAME BEGUN!!!"] = "", @@ -246,6 +341,9 @@ -- ["Game? Was this a game to you?!"] = "", -- A_Classic_Fairytale:enemy -- ["GasBomb"] = "", -- Continental_supplies -- ["Gas Gargler"] = "", -- A_Classic_Fairytale:queen +-- ["General information"] = "", -- Continental_supplies +-- ["Generates power."] = "", -- Construction_Mode +-- ["Generator"] = "", -- Construction_Mode -- ["Get Dense Cloud out of the pit!"] = "", -- A_Classic_Fairytale:journey -- ["Get on over there and take him out!"] = "", -- ["Get on the head of the mole"] = "", -- A_Classic_Fairytale:first_blood @@ -256,6 +354,8 @@ -- ["Get your teammates out of their natural prison and save the princess!|Hint: Drilling holes should solve everything.|Hint: It might be a good idea to place a girder before starting to drill. Just saying.|Hint: All your hedgehogs need to be above the marked height!|Hint: Leaks A Lot needs to get really close to the princess!"] = "", -- A_Classic_Fairytale:family -- ["GG!"] = "", -- User_Mission_-_Rope_Knock_Challenge -- ["Gimme Bones"] = "", -- A_Classic_Fairytale:backstab +-- ["Girder"] = "", -- Construction_Mode +-- ["Girder Placement Mode"] = "", -- Construction_Mode -- ["Glark"] = "", -- A_Classic_Fairytale:shadow -- ["Goal"] = "", -- ["GO! GO! GO!"] = "", @@ -272,36 +372,51 @@ -- ["Go surf!"] = "", -- WxW -- ["GOTCHA!"] = "", -- ["Grab Mines/Explosives"] = "", +-- ["Grants nearby hogs life-regeneration."] = "", -- Construction_Mode +-- ["Gravity"] = "", -- Gravity -- ["Great choice, Steve! Mind if I call you that?"] = "", -- A_Classic_Fairytale:shadow +-- ["GREAT ! Let's kill all this enemies, using portals"] = "", -- portal -- ["Great work! Now hit it with your Baseball Bat! |Tip: You can change weapon with 'Right Click'!"] = "", -- Basic_Training_-_Rope -- ["Great! You will be contacted soon for assistance."] = "", -- A_Classic_Fairytale:shadow --- ["Green lipstick bullet: [Is poisonous]"] = "", -- Continental_supplies + +-- ["Greenhorn"] = "", -- User_Mission_-_RCPlane_Challenge +-- ["Green lipstick bullet: [Poisonous, deals no damage]"] = "", -- Continental_supplies -- ["Greetings, "] = "", -- A_Classic_Fairytale:dragon -- ["Greetings, cloudy one!"] = "", -- A_Classic_Fairytale:shadow +-- ["Grenade"] = "", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 +-- ["Grenade Group"] = "", -- Target_Practice_-_Grenade_easy, Target_Practice_-_Grenade_hard -- ["Grenade Training"] = "", -- Basic_Training_-_Grenade +-- ["Grenadier"] = "", -- Target_Practice_-_Grenade_easy, Target_Practice_-_Grenade_hard -- ["Grenadiers"] = "", -- Basic_Training_-_Grenade -- ["Guys, do you think there's more of them?"] = "", -- A_Classic_Fairytale:backstab -- ["HAHA!"] = "", -- A_Classic_Fairytale:enemy -- ["Haha!"] = "", -- A_Classic_Fairytale:united -- ["Hahahaha!"] = "", -- ["Haha, now THAT would be something!"] = "", +-- ["Hammer"] = "", -- Construction_Mode, Continental_supplies -- ["Hannibal"] = "", -- A_Classic_Fairytale:epil -- ["Hapless Hogs"] = "", --- [" Hapless Hogs left!"] = "", - +-- ["%d Hapless Hogs left"] = "", +-- ["Harry"] = "", -- User_Mission_-_Nobody_Laugh -- [" HAS MUTATED"] = "", -- Mutant -- ["Hatless Jerry"] = "", -- A_Classic_Fairytale:queen -- ["Have no illusions, your tribe is dead, indifferent of your choice."] = "", -- A_Classic_Fairytale:shadow -- ["Have we ever attacked you first?"] = "", -- A_Classic_Fairytale:enemy +-- ["Healing Station"] = "", -- Construction_Mode +-- ["Health Crate Placement Mode"] = "", -- Construction_Mode -- ["Health crates extend your time."] = "", +-- ["Heartful"] = "", -- Challenge_-_Speed_Shoppa_-_Hedgelove -- ["Heavy"] = "", -- ["Heavy Cannfantry"] = "", -- A_Classic_Fairytale:united -- ["Hedge-cogs"] = "", -- A_Classic_Fairytale:enemy --- ["Hedgehog projectile: [fire your hog like a Sticky Bomb]"] = "", -- Continental_supplies +-- ["Hedgehog projectile: [Fire your hog like a Sticky Bomb]"] = "", -- Continental_supplies + -- ["Hedgewars-Basketball"] = "", -- ["Hedgewars-Knockball"] = "", -- ["Hedgibal Lecter"] = "", -- A_Classic_Fairytale:backstab -- ["Heh, it's not that bad."] = "", +-- ["Hell Army"] = "", -- portal +-- ["Hellish Handgrenade"] = "", -- Construction_Mode -- ["Hello again, "] = "", -- A_Classic_Fairytale:family -- ["Help me, Leaks!"] = "", -- A_Classic_Fairytale:journey -- ["Help me, please!!!"] = "", -- A_Classic_Fairytale:journey @@ -318,6 +433,7 @@ -- ["Hey guys!"] = "", -- A_Classic_Fairytale:united -- ["Hey! This is cheating!"] = "", -- A_Classic_Fairytale:journey -- ["HIGHLANDER"] = "", -- Highlander +-- ["hiden"] = "", -- portal -- ["Hightime"] = "", -- A_Classic_Fairytale:first_blood -- ["Hint: Double Jump - Press [Backspace] twice"] = "", -- A_Classic_Fairytale:first_blood -- ["Hint: Select the BlowTorch, aim and press [Fire]. Press [Fire] again to stop.|Don't blow up the crate."] = "", -- A_Classic_Fairytale:journey @@ -325,6 +441,7 @@ -- ["Hint: you might want to stay out of sight and take all the crates...|"] = "", -- A_Classic_Fairytale:journey -- ["His arms are so strong!"] = "", -- A_Classic_Fairytale:first_blood -- ["Hit Combo!"] = "", +-- ["hits"] = "", -- Basic_Training_-_Bazooka -- ["Hmmm..."] = "", -- ["Hmmm...actually...I didn't either."] = "", -- A_Classic_Fairytale:enemy -- ["Hmmm, I'll have to find some way of moving him off this anti-portal surface..."] = "", -- portal @@ -333,8 +450,11 @@ -- ["Hogminator"] = "", -- A_Classic_Fairytale:family -- ["Hogs in sight!"] = "", -- Continental_supplies -- ["HOLY SHYTE!"] = "", -- Mutant +-- ["Homing Bee"] = "", -- Construction_Mode -- ["Honest Lee"] = "", -- A_Classic_Fairytale:enemy +-- ["Hook"] = "", -- Challenge_-_Speed_Shoppa_-_Ropes -- ["Hooray!"] = "", +-- ["Hopeless case"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Hostage Situation"] = "", -- A_Classic_Fairytale:family -- ["How can I ever repay you for saving my life?"] = "", -- A_Classic_Fairytale:journey -- ["How come in a village full of warriors, it's up to me to save it?"] = "", -- A_Classic_Fairytale:dragon @@ -366,7 +486,7 @@ -- ["If you get stuck, use your Desert Eagle or restart the mission!|"] = "", -- A_Classic_Fairytale:journey -- ["If you know what I mean..."] = "", -- A_Classic_Fairytale:shadow -- ["If you say so..."] = "", -- A_Classic_Fairytale:shadow - +-- ["Igmund"] = "", -- User_Mission_-_Nobody_Laugh -- ["I guess you'll have to kill them."] = "", -- A_Classic_Fairytale:dragon -- ["I have come to make you an offering..."] = "", -- A_Classic_Fairytale:shadow -- ["I have no idea where that mole disappeared...Can you see it?"] = "", -- A_Classic_Fairytale:shadow @@ -376,6 +496,7 @@ -- ["I just don't want to sink to your level."] = "", -- A_Classic_Fairytale:backstab -- ["I just found out that they have captured your princess!"] = "", -- A_Classic_Fairytale:family -- ["I just wonder where Ramon and Spiky disappeared..."] = "", -- A_Classic_Fairytale:journey +-- ["Ikeda"] = "", -- User_Mission_-_Bamboo_Thicket -- ["I'll hold them off while you return to the village!"] = "", -- A_Classic_Fairytale:shadow -- ["Imagine those targets are the wolves that killed your parents! Take your anger out on them!"] = "", -- A_Classic_Fairytale:first_blood -- ["I'm...alive? How? Why?"] = "", -- A_Classic_Fairytale:backstab @@ -389,6 +510,7 @@ -- ["I'm not sure about that!"] = "", -- A_Classic_Fairytale:united -- ["Impressive...you are still dry as the corpse of a hawk after a week in the desert..."] = "", -- A_Classic_Fairytale:first_blood -- ["I'm so scared!"] = "", -- A_Classic_Fairytale:united +-- ["Increase"] = "", -- Continental_supplies -- ["Incredible..."] = "", -- A_Classic_Fairytale:shadow -- ["I need to find the others!"] = "", -- A_Classic_Fairytale:backstab -- ["I need to get to the other side of this island, fast!"] = "", -- A_Classic_Fairytale:journey @@ -397,18 +519,25 @@ -- ["I need to warn the others."] = "", -- A_Classic_Fairytale:backstab -- ["In fact, you are the only one that's been acting strangely."] = "", -- A_Classic_Fairytale:backstab -- ["In order to get to the other side, you need to collect the crates first.|"] = "", -- A_Classic_Fairytale:dragon +-- ["INSANITY"] = "", -- Mutant -- ["Instructor"] = "", -- 01#Boot_Camp, User_Mission_-_Dangerous_Ducklings +-- ["Insufficient Power"] = "", -- Construction_Mode -- ["Interesting idea, haha!"] = "", -- A_Classic_Fairytale:enemy -- ["Interesting! Last time you said you killed a cannibal!"] = "", -- A_Classic_Fairytale:backstab -- ["In the meantime, take these and return to your \"friend\"!"] = "", -- A_Classic_Fairytale:shadow -- ["invaders destroyed"] = "", +-- ["Invalid Placement"] = "", -- Construction_Mode -- ["Invasion"] = "", -- A_Classic_Fairytale:united +-- ["Invulnerable"] = "", -- Construction_Mode +-- ["In your best (and only) flight you took out %d crates with one RC plane!"] = "", -- User_Mission_-_RCPlane_Challenge +-- ["In your best flight you took out %d crates with one RC plane."] = "", -- User_Mission_-_RCPlane_Challenge -- ["I saw it with my own eyes!"] = "", -- A_Classic_Fairytale:shadow -- ["I see..."] = "", -- A_Classic_Fairytale:shadow -- ["I see you have already taken the leap of faith."] = "", -- A_Classic_Fairytale:first_blood -- ["I see you would like his punishment to be more...personal..."] = "", -- A_Classic_Fairytale:first_blood -- ["I sense another wave of cannibals heading my way!"] = "", -- A_Classic_Fairytale:backstab -- ["I sense another wave of cannibals heading our way!"] = "", -- A_Classic_Fairytale:backstab +-- ["I should get myself a portal gun, maybe this crate has one"] = "", -- portal -- ["I shouldn't have drunk that last pint."] = "", -- A_Classic_Fairytale:dragon -- ["Is this place in my head?"] = "", -- A_Classic_Fairytale:dragon -- ["It doesn't matter. I won't let that alien hurt my daughter!"] = "", -- A_Classic_Fairytale:dragon @@ -445,6 +574,7 @@ -- ["Just kidding, none of you have died!"] = "", -- A_Classic_Fairytale:enemy -- ["Just on a walk."] = "", -- A_Classic_Fairytale:united -- ["Just wait till I get my hands on that trauma! ARGH!"] = "", -- A_Classic_Fairytale:family +-- ["Kamikaze"] = "", -- Construction_Mode -- ["Kamikaze Expert!"] = "", -- ["Keep it up!"] = "", -- ["Kerguelen"] = "", -- Continental_supplies @@ -454,6 +584,9 @@ -- ["Kill the aliens!"] = "", -- A_Classic_Fairytale:dragon -- ["Kill the cannibal!"] = "", -- A_Classic_Fairytale:first_blood -- ["Kill the traitor...or spare his life!|Kill him or press [Precise]!"] = "", -- A_Classic_Fairytale:backstab +-- ["King Customer"] = "", -- Challenge_-_Speed_Shoppa_-_ShoppaKing +-- ["Land Sprayer"] = "", -- Construction_Mode +-- ["Laser Sight"] = "", -- Construction_Mode -- ["Last Target!"] = "", -- ["Leader"] = "", -- A_Classic_Fairytale:enemy -- ["Leaderbot"] = "", -- A_Classic_Fairytale:queen @@ -464,6 +597,8 @@ -- ["Led Heart"] = "", -- A_Classic_Fairytale:queen -- ["Lee"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen -- ["[Left Shift]"] = "", +-- ["left shift"] = "", -- Continental_supplies +-- ["Lestat"] = "", -- portal -- ["Let a Continent provide your weapons!"] = "", -- Continental_supplies -- ["Let me test your skills a little, will you?"] = "", -- A_Classic_Fairytale:journey -- ["Let's go home!"] = "", -- A_Classic_Fairytale:journey @@ -473,41 +608,62 @@ -- ["Let them have a taste of my fury!"] = "", -- A_Classic_Fairytale:backstab -- ["Let us help, too!"] = "", -- A_Classic_Fairytale:backstab -- ["Light Cannfantry"] = "", -- A_Classic_Fairytale:united +-- ["Limburger"] = "", -- Construction_Mode -- ["Listen up, maggot!!"] = "", -- ["Little did they know that this hunt will mark them forever..."] = "", -- A_Classic_Fairytale:shadow -- ["Lively Lifeguard"] = "", --- ["Lonely Cries: [Rise the water if no hog is in the circle and deal 1 damage to all hogs]"] = "", -- Continental_supplies + +-- ["Lonely Cries: [Rise the water if no hog is in the circle and deal 7 damage to all enemy hogs]"] = "", -- Continental_supplies +-- ["Lonely Hog"] = "", -- ClimbHome -- ["Look, I had no choice!"] = "", -- A_Classic_Fairytale:backstab -- ["Look out! There's more of them!"] = "", -- A_Classic_Fairytale:backstab -- ["Look out! We're surrounded by cannibals!"] = "", -- A_Classic_Fairytale:enemy -- ["Looks like the whole world is falling apart!"] = "", -- A_Classic_Fairytale:enemy +-- ["Loon"] = "", -- The_Specialists +-- ["Low Gravity"] = "", -- Construction_Mode, Frenzy +-- ["Lucifer"] = "", -- portal -- ["Luckily, I've managed to snatch some of them."] = "", -- A_Classic_Fairytale:united -- ["LUDICROUS KILL"] = "", -- Mutant +-- ["Made it!"] = "", -- ClimbHome +-- ["- Massive weapon bonus on first turn"] = "", -- Continental_supplies -- ["May the spirits aid you in all your quests!"] = "", -- A_Classic_Fairytale:backstab -- ["Medicine: [Fire some exploding medicine that will heal all hogs effected by the explosion]"] = "", -- Continental_supplies -- ["MEGA KILL"] = "", -- Mutant -- ["Meiwes"] = "", -- A_Classic_Fairytale:backstab +-- ["milliseconds"] = "", -- SpeedShoppa -- ["Mindy"] = "", -- A_Classic_Fairytale:united +-- ["Mine"] = "", -- Construction_Mode, Frenzy -- ["Mine Deployer"] = "", -- ["Mine Eater!"] = "", +-- ["Mine Placement Mode"] = "", -- Construction_Mode -- ["|- Mines Time:"] = "", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork +-- ["Mine Strike"] = "", -- Construction_Mode -- ["MISSION FAILED"] = "", -- User_Mission_-_Dangerous_Ducklings, User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork +-- ["Mission lost!"] = "", -- Basic_Training_-_Grenade -- ["MISSION SUCCESS"] = "", -- ["MISSION SUCCESSFUL"] = "", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork +-- ["Mission won!"] = "", -- Basic_Training_-_Grenade +-- ["Molotov Cocktail"] = "", -- Construction_Mode -- ["Molotov"] = "", -- Continental_supplies -- ["MONSTER KILL"] = "", -- Mutant -- ["More Natives"] = "", -- A_Classic_Fairytale:epil +-- ["Mortar"] = "", -- Construction_Mode, A_Space_Adventure:death02 -- ["Movement: [Up], [Down], [Left], [Right]"] = "", +-- ["Mudball"] = "", -- Construction_Mode -- ["Multi-shot!"] = "", -- ["Muriel"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen -- ["Muscle Dissolver"] = "", -- A_Classic_Fairytale:shadow -- ["-------"] = "", -- Mutant +-- ["MUTANT"] = "", -- Mutant +-- ["Mutant"] = "", -- Mutant -- ["Nade Boy"] = "", -- Basic_Training_-_Grenade -- ["Name"] = "", -- A_Classic_Fairytale:queen -- ["Nameless Heroes"] = "", -- ["Nancy Screw"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:queen +-- ["Napalm"] = "", -- Construction_Mode -- ["Napalm rocket: [Fire a bomb with napalm!]"] = "", -- Continental_supplies -- ["Natives"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:first_blood, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united +-- ["Naughty Ninja"] = "", -- User_Mission_-_Dangerous_Ducklings -- ["New Barrels Per Turn"] = "", -- ["NEW CLAN RECORD: "] = "", -- ["NEW fastest lap: "] = "", @@ -518,6 +674,8 @@ -- ["Nice work, "] = "", -- A_Classic_Fairytale:dragon -- ["Nice work!"] = "", -- A_Classic_Fairytale:enemy -- ["Nilarian"] = "", -- A_Classic_Fairytale:queen +-- ["Ninja"] = "", -- The_Specialists +-- ["Nobody Laugh"] = "", -- User_Mission_-_Nobody_Laugh -- ["No, I came back to help you out..."] = "", -- A_Classic_Fairytale:shadow -- ["No...I wonder where they disappeared?!"] = "", -- A_Classic_Fairytale:journey -- ["Nom-Nom"] = "", -- A_Classic_Fairytale:journey @@ -525,6 +683,7 @@ -- ["Nope. It was one fast mole, that's for sure."] = "", -- A_Classic_Fairytale:shadow -- ["No! Please, help me!"] = "", -- A_Classic_Fairytale:journey -- ["NORMAL"] = "", -- Continental_supplies +-- ["Normal players can only score points by killing the mutant."] = "", -- Mutant -- ["North America"] = "", -- Continental_supplies -- ["Not all hogs are born equal."] = "", -- Highlander -- ["NOT ENOUGH WAYPOINTS"] = "", @@ -537,6 +696,7 @@ -- ["No. Where did he come from?"] = "", -- A_Classic_Fairytale:shadow -- ["Now how do I get on the other side?!"] = "", -- A_Classic_Fairytale:dragon -- ["No. You and the rest of the tribe are safer there!"] = "", -- A_Classic_Fairytale:backstab +-- ["Object Placement Tool"] = "", -- Construction_Mode -- ["Obliterate them!|Hint: You might want to take cover..."] = "", -- A_Classic_Fairytale:shadow -- ["Obstacle course"] = "", -- A_Classic_Fairytale:dragon -- ["Of course I have to save her. What did I expect?!"] = "", -- A_Classic_Fairytale:family @@ -553,69 +713,110 @@ -- ["Once upon a time, on an island with great natural resources, lived two tribes in heated conflict..."] = "", -- A_Classic_Fairytale:first_blood -- ["ONE HOG PER TEAM! KILLING EXCESS HEDGES"] = "", -- Mutant -- ["One tribe was peaceful, spending their time hunting and training, enjoying the small pleasures of life..."] = "", -- A_Classic_Fairytale:first_blood +-- ["oneye"] = "", -- portal +-- ["on Skip"] = "", -- Continental_supplies -- ["Oops...I dropped them."] = "", -- A_Classic_Fairytale:united -- ["Open that crate and we will continue!"] = "", -- A_Classic_Fairytale:first_blood -- ["Operation Diver"] = "", -- ["Opposing Team: "] = "", +-- ["or 'g=50, g2=150, period=4000' for gravity changing|from 50 to 150 and back with period of 4000 msec"] = "", -- Gravity -- ["Orlando Boom!"] = "", -- A_Classic_Fairytale:queen +-- ["Other kills don't give you points."] = "", -- Mutant -- ["Ouch!"] = "", -- User_Mission_-_Rope_Knock_Challenge -- ["Our tribe, our beautiful island!"] = "", -- A_Classic_Fairytale:enemy -- ["Parachute"] = "", -- Continental_supplies -- ["Pathetic Hog #%d"] = "", -- ["Pathetic Resistance"] = "", -- User_Mission_-_Bamboo_Thicket, User_Mission_-_Newton_and_the_Hammock +-- ["Penguin roar: [Deal 15 damage + 15% of your hogs health to all hogs around you and get 2/3 back]"] = "", -- Continental_supplies -- ["Perfect! Now try to get the next crate without hurting yourself!"] = "", -- A_Classic_Fairytale:first_blood -- ["Per-Hog Ammo"] = "", --- ["- Per team weapons|- 9 weaponschemes|- Unique new weapons| |Select continent first round with the Weapon Menu or by ([switch/tab]=Increase,[precise/left shift]=Decrease) on Skip|Some weapons have a second option. Find them with [switch/tab]"] = "", -- Continental_supplies +-- ["Personal Portal Device"] = "", -- Construction_Mode +-- ["Per team weapons"] = "", -- Continental_supplies -- ["Pfew! That was close!"] = "", -- A_Classic_Fairytale:shadow --- ["Piñata bullet: [Contains some sweet candy!]"] = "", -- Continental_supplies +-- ["phosphatoglucidique"] = "", -- portal +-- ["Piano Strike"] = "", -- Construction_Mode +-- ["Pickhammer"] = "", -- Construction_Mode + -- ["Pings left:"] = "", -- Space_Invasion - -- ["Place more waypoints using the 'Air Attack' weapon."] = "", --- ["Planes Used:"] = "", -- User_Mission_-_RCPlane_Challenge --- ["Planes Used"] = "", -- User_Mission_-_RCPlane_Challenge +-- ["Planes used: %d"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Play with me!"] = "", -- A_Classic_Fairytale:shadow +-- ["player"] = "", -- portal -- ["Please place the way-point further from the waterline."] = "", -- Racer -- ["Please place the way-point in the open, within the map boundaries."] = "", -- Racer -- ["Please, stop releasing your \"smoke signals\"!"] = "", -- A_Classic_Fairytale:shadow -- ["Point Blank Combo!"] = "", -- Space_Invasion -- ["points"] = "", -- Control, CTF_Blizzard, Basic_Training_-_Bazooka, Basic_Training_-_Shotgun, Basic_Training_-_Sniper_Rifle +-- ["POINTS"] = "", -- Mutant -- ["Poison"] = "", +-- ["Population"] = "", -- Continental_supplies -- ["Portal hint: one goes to the destination, and one is the entrance.|"] = "", -- A_Classic_Fairytale:dragon -- ["Portal mission"] = "", -- portal -- ["Power Remaining"] = "", +-- ["Predator"] = "", -- portal -- ["Prepare yourself"] = "", +-- ["presice"] = "", -- Continental_supplies -- ["Press [Enter] to accept this configuration."] = "", -- WxW -- ["Press [Left] or [Right] to move around, [Enter] to jump"] = "", -- A_Classic_Fairytale:first_blood -- ["Press [Precise] to skip intro"] = "", +-- ["Prestigious Pilot"] = "", -- User_Mission_-_RCPlane_Challenge +-- ["Private Nolak"] = "", -- Target_Practice_-_Cluster_Bomb -- ["Private Novak"] = "", -- Basic_Training_-_Cluster_Bomb +-- ["Professional pilot"] = "", -- User_Mission_-_RCPlane_Challenge +-- ["Professional stunt pilot"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Protect yourselves!|Grenade hint: set the timer with [1-5], aim with [Up]/[Down] and hold [Space] to set power"] = "", -- A_Classic_Fairytale:shadow +-- ["Pyro"] = "", -- The_Specialists -- ["Race complexity limit reached."] = "", -- ["RACER"] = "", -- ["Rachel"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen -- ["Radar Ping"] = "", -- Space_Invasion -- ["Raging Buffalo"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united -- ["Ramon"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow +-- ["Rank: %s"] = "", -- User_Mission_-_RCPlane_Challenge +-- ["random in range from %i%% to %i%% with period of %i msec"] = "", -- Gravity +-- ["razac"] = "", -- portal +-- ["RC Plane"] = "", -- Construction_Mode -- ["RC PLANE TRAINING"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Really?! You thought you could harm me with your little toys?"] = "", -- A_Classic_Fairytale:shadow +-- ["Reflector Shield"] = "", -- Construction_Mode +-- ["Reflects enemy projectiles."] = "", -- Construction_Mode -- ["Regurgitator"] = "", -- A_Classic_Fairytale:backstab -- ["Reinforcements"] = "", -- A_Classic_Fairytale:backstab -- ["Remember: The rope only bend around objects, |if it doesn't hit anything it's always stright!"] = "", -- Basic_Training_-_Rope -- ["Remember this, pathetic animal: when the day comes, you will regret your blind loyalty!"] = "", -- A_Classic_Fairytale:shadow +-- ["REMOVED"] = "", -- Continental_supplies +-- ["rescues"] = "", -- User_Mission_-_That_Sinking_Feeling +-- ["Respawner"] = "", -- Construction_Mode +-- ["Resurrector"] = "", -- Construction_Mode +-- ["Resurrects dead hedgehogs."] = "", -- Construction_Mode -- [" - Return the enemy flag to your base to score | - First team to 3 captures wins | - You may only score when your flag is in your base | - Hogs will drop the flag if killed, or drowned | - Dropped flags may be returned or recaptured | - Hogs respawn when killed"] = "", -- ["Return to Leaks A Lot! If you get stuck, press [Precise] to try again!"] = "", -- A_Classic_Fairytale:shadow +-- ["Rider"] = "", -- portal -- ["Righteous Beard"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:first_blood, A_Classic_Fairytale:queen, A_Classic_Fairytale:united +-- ["ronald"] = "", -- portal +-- ["Rope"] = "", -- Construction_Mode -- ["ROPE-KNOCKING"] = "", -- User_Mission_-_Rope_Knock_Challenge +-- ["Rope Master!"] = "", -- Basic_Training_-_Rope +-- ["Roper"] = "", -- SpeedShoppa +-- ["Ropes and Crates"] = "", -- Challenge_-_Speed_Shoppa_-_Ropes +-- ["Rope Team"] = "", -- Basic_Training_-_Rope +-- ["Rope to safety"] = "", -- ClimbHome -- ["Rope Training"] = "", -- Basic_Training_-_Rope -- ["Rot Molester"] = "", -- A_Classic_Fairytale:shadow -- ["Round Limit:"] = "", -- ["Round Limit"] = "", -- ["Rounds Complete: "] = "", -- ["Rounds Complete"] = "", +-- ["Rubber Band"] = "", -- Construction_Mode +-- ["Rubber Placement Mode"] = "", -- Construction_Mode +-- ["RULES"] = "", -- Frenzy, Mutant -- ["RULES OF THE GAME [Press ESC to view]"] = "", -- ["Rusty Joe"] = "", -- A_Classic_Fairytale:queen -- ["s|"] = "", --- ["Sabotage: [Sabotage all hogs in the circle and deal ~10 dmg]"] = "", -- Continental_supplies +-- ["Sabotage/Flare: [Sabotage all hogs in the circle and deal ~1 dmg OR Fire a cluster up into the air]"] = "", -- Continental_supplies + +-- ["Saint"] = "", -- The_Specialists -- ["Salivaslurper"] = "", -- A_Classic_Fairytale:united -- ["Salvation"] = "", -- A_Classic_Fairytale:family -- ["Salvation was one step closer now..."] = "", -- A_Classic_Fairytale:dragon @@ -627,16 +828,20 @@ -- ["Scalp Muncher"] = "", -- A_Classic_Fairytale:backstab -- ["SCORE"] = "", -- ["Score"] = "", -- Mutant --- ["Scream from a Walrus: [Deal 20 damage + 10% of your hogs health to all hogs around you and get half back]"] = "", -- Continental_supplies + -- ["sec"] = "", -- CTF_Blizzard, TrophyRace, Basic_Training_-_Bazooka, Basic_Training_-_Shotgun, Basic_Training_-_Sniper_Rifle, User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork, Capture_the_Flag +-- ["%.1f seconds were remaining."] = "", -- Basic_Training_-_Bazooka -- ["Seduction"] = "", -- Continental_supplies -- ["Seems like every time you take a \"walk\", the enemy find us!"] = "", -- A_Classic_Fairytale:backstab -- ["See that crate farther on the right?"] = "", -- A_Classic_Fairytale:first_blood -- ["See ya!"] = "", -- ["Segmentation Paul"] = "", -- A_Classic_Fairytale:dragon -- ["Select continent!"] = "", -- Continental_supplies +-- ["Select continent first round with the Weapon Menu or by"] = "", -- Continental_supplies -- ["Select difficulty: [Left] - easier or [Right] - harder"] = "", -- A_Classic_Fairytale:first_blood -- ["selected!"] = "", +-- ["Set period to negative value for random gravity"] = "", -- Gravity +-- ["Setup:|'g=150', where 150 is 150% of normal gravity"] = "", -- Gravity -- ["s"] = "", -- GaudyRacer, Space_Invasion -- ["... share your beauty with the world every morning, my princess!"] = "", -- A_Classic_Fairytale:journey -- ["She's behind that tall thingy."] = "", -- A_Classic_Fairytale:family @@ -648,54 +853,92 @@ -- ["Shield OFF:"] = "", -- ["Shield ON:"] = "", -- ["Shield Seeker!"] = "", +-- ["Shoppa Union"] = "", -- Challenge_-_Speed_Shoppa_-_Ropes, Challenge_-_Speed_Shoppa_-_ShoppaKing +-- ["Shoppers"] = "", -- SpeedShoppa +-- ["Shoryuken"] = "", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 -- ["Shotgun"] = "", -- Continental_supplies -- ["Shotgun Team"] = "", -- ["Shotgun Training"] = "", -- ["shots remaining."] = "", -- ["Silly"] = "", +-- ["SineGun"] = "", -- Construction_Mode -- ["Sinky"] = "", -- ["Sirius Lee"] = "", -- A_Classic_Fairytale:enemy -- ["%s is out and Team %d|scored a penalty!| |Score:"] = "", -- Basketball, Knockball -- ["%s is out and Team %d|scored a point!| |Score:"] = "", -- Basketball, Knockball -- ["Slippery"] = "", -- A_Classic_Fairytale:journey +-- ["Slot"] = "", -- Frenzy +-- ["Slot keys save time! (F1-F10 by default)"] = "", -- Frenzy +-- ["SLOTS"] = "", -- Frenzy -- ["Smith 0.97"] = "", -- A_Classic_Fairytale:enemy -- ["Smith 0.98"] = "", -- A_Classic_Fairytale:enemy -- ["Smith 0.99a"] = "", -- A_Classic_Fairytale:enemy -- ["Smith 0.99b"] = "", -- A_Classic_Fairytale:enemy -- ["Smith 0.99f"] = "", -- A_Classic_Fairytale:enemy -- ["Smith 1.0"] = "", -- A_Classic_Fairytale:enemy +-- ["Sniper"] = "", -- The_Specialists -- ["Sniper Rifle"] = "", -- Continental_supplies -- ["Sniper!"] = "", -- Space_Invasion -- ["Sniper Training"] = "", -- ["Sniperz"] = "", -- ["So humiliating..."] = "", -- A_Classic_Fairytale:first_blood +-- ["Soldier"] = "", -- The_Specialists +-- ["Some weapons have a second option. Find them with"] = "", -- Continental_supplies -- ["South America"] = "", -- Continental_supplies -- ["So? What will it be?"] = "", -- A_Classic_Fairytale:shadow -- ["Spawn the crate, and attack!"] = "", -- WxW -- ["Special Weapons:"] = "", -- Continental_supplies +-- ["Speed Shoppa"] = "", -- SpeedShoppa -- ["Spiky Cheese"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow -- ["Spleenlover"] = "", -- A_Classic_Fairytale:united -- ["Sponge"] = "", -- ["Spooky Tree"] = "", +-- ["Sprite Placement Mode"] = "", -- Construction_Mode +-- ["Sprite Testing Mode"] = "", -- Construction_Mode -- ["STATUS UPDATE"] = "", -- GaudyRacer, Space_Invasion -- ["Steel Eye"] = "", -- A_Classic_Fairytale:queen -- ["Step By Step"] = "", -- A_Classic_Fairytale:first_blood -- ["Steve"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen -- ["Sticky Mine"] = "", -- Continental_supplies +-- ["Sticky Mine Placement Mode"] = "", -- Construction_Mode -- ["Stronglings"] = "", -- A_Classic_Fairytale:shadow --- ["Structure"] = "", -- Continental_supplies + +-- ["Structure Placement Mode"] = "", -- Construction_Mode +-- ["Structure Placement Tool"] = "", -- Construction_Mode +-- ["Subject"] = "", -- portal +-- ["Sundaland"] = "", -- Continental_supplies -- ["Super Weapons"] = "", -- WxW +-- ["Support Station"] = "", -- Construction_Mode -- ["Surf Before Crate"] = "", -- WxW -- ["Surfer! +15 points!"] = "", -- Space_Invasion -- ["Surfer!"] = "", -- WxW -- ["Survive!|Hint: Cinematics can be skipped with the [Precise] key."] = "", -- A_Classic_Fairytale:shadow -- ["Swing, Leaks A Lot, on the wings of the wind!"] = "", -- A_Classic_Fairytale:first_blood +-- ["switch"] = "", -- Continental_supplies -- ["Switched to "] = "", +-- ["Switch Hog"] = "", -- Construction_Mode -- ["Syntax Errol"] = "", -- A_Classic_Fairytale:dragon +-- ["tab"] = "", -- Continental_supplies +-- ["Tagging Mode"] = "", -- Construction_Mode -- ["Talk about mixed signals..."] = "", -- A_Classic_Fairytale:dragon +-- ["Tardis"] = "", -- Construction_Mode +-- ["Target Placement Mode"] = "", -- Construction_Mode +-- ["Target Practice: Bazooka (easy)"] = "", -- Target_Practice_-_Bazooka_easy +-- ["Target Practice: Bazooka (hard)"] = "", -- Target_Practice_-_Bazooka_hard +-- ["Target Practice: Grenade (easy)"] = "", -- Target_Practice_-_Grenade_easy +-- ["Target Practice: Grenade (hard)"] = "", -- Target_Practice_-_Grenade_hard +-- ["Target Practice: Homing Bee"] = "", -- Target_Practice_-_Homing_Bee +-- ["Target Practice: Shotgun"] = "", -- Target_Practice_-_Shotgun +-- ["Targets left: %d"] = "", -- TargetPractice -- ["Team %d: "] = "", +-- ["Team of Hearts"] = "", -- Challenge_-_Speed_Shoppa_-_Hedgelove -- ["Team Scores"] = "", -- Control, Space_Invasion +-- ["Team Zook"] = "", -- Target_Practice_-_Bazooka_easy, Target_Practice_-_Bazooka_hard +-- ["Teleportation Mode"] = "", -- Construction_Mode +-- ["Teleportation Node"] = "", -- Construction_Mode +-- ["Teleport"] = "", -- Construction_Mode, Frenzy -- ["Teleport hint: just use the mouse to select the destination!"] = "", -- A_Classic_Fairytale:dragon +-- ["Teleport Unsuccessful. Please teleport within a clan teleporter's sphere of influence."] = "", -- Construction_Mode -- ["Thanks!"] = "", -- A_Classic_Fairytale:family -- ["Thank you, my hero!"] = "", -- A_Classic_Fairytale:family -- ["Thank you, oh, thank you, Leaks A Lot!"] = "", -- A_Classic_Fairytale:journey @@ -712,29 +955,39 @@ -- ["That was pointless."] = "", -- ["The answer is...entertaintment. You'll see what I mean."] = "", -- A_Classic_Fairytale:backstab -- ["The anti-portal zone is all over the floor, and I have nothing to kill him...Droping something could hurt him enough to kill him..."] = "", -- portal +-- ["The Bottom Feeder can score points by killing anyone."] = "", -- Mutant -- ["The Bull's Eye"] = "", -- A_Classic_Fairytale:first_blood -- ["The caves are well hidden, they won't find us there!"] = "", -- A_Classic_Fairytale:united -- ["The Crate Frenzy"] = "", -- A_Classic_Fairytale:first_blood +-- ["The Customer is King"] = "", -- Challenge_-_Speed_Shoppa_-_ShoppaKing -- ["The Dilemma"] = "", -- A_Classic_Fairytale:shadow -- ["The enemy can't move but it might be a good idea to stay out of sight!|"] = "", -- A_Classic_Fairytale:dragon -- ["The enemy is hiding out on yonder ducky!"] = "", -- ["The Enemy Of My Enemy"] = "", -- A_Classic_Fairytale:enemy -- ["The First Blood"] = "", -- A_Classic_Fairytale:first_blood -- ["The First Encounter"] = "", -- A_Classic_Fairytale:shadow +-- ["The first player to kill someone becomes the Mutant."] = "", -- Mutant -- ["The flag will respawn next round."] = "", +-- ["The flood has stopped! Challenge over."] = "", -- User_Mission_-_That_Sinking_Feeling -- ["The food bites back"] = "", -- A_Classic_Fairytale:backstab -- ["The giant umbrella from the last crate should help break the fall."] = "", -- A_Classic_Fairytale:first_blood -- ["The Great Escape"] = "", -- User_Mission_-_The_Great_Escape +-- ["The Great Hog in the sky sees your sadness and grants you a boon."] = "", -- Construction_Mode -- ["The guardian"] = "", -- A_Classic_Fairytale:shadow +-- ["The Hogies"] = "", -- Target_Practice_-_Cluster_Bomb -- ["The Individualist"] = "", -- A_Classic_Fairytale:shadow -- ["Their buildings were very primitive back then, even for an uncivilised island."] = "", -- A_Classic_Fairytale:united -- ["The Journey Back"] = "", -- A_Classic_Fairytale:journey -- ["The Leap of Faith"] = "", -- A_Classic_Fairytale:first_blood -- ["The Moonwalk"] = "", -- A_Classic_Fairytale:journey +-- ["The Mutant has super-weapons and a lot of health."] = "", -- Mutant +-- ["The Mutant loses health quickly if he doesn't keep scoring kills."] = "", -- Mutant -- ["The Nameless One"] = "", -- ["The next one is pretty hard! |Tip: You have to do multiple swings!"] = "", -- Basic_Training_-_Rope -- ["Then how do they keep appearing?"] = "", -- A_Classic_Fairytale:shadow -- ["The other one were all cannibals, spending their time eating the organs of fellow hedgehogs..."] = "", -- A_Classic_Fairytale:first_blood +-- ["The player with least points (or most deaths) becomes the Bottom Feeder."] = "", -- Mutant +-- ["There are a variety of structures available to aid you."] = "", -- Construction_Mode -- ["There must be a spy among us!"] = "", -- A_Classic_Fairytale:backstab -- ["There's more of them? When did they become so hungry?"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united -- ["There's nothing more satisfying for me than seeing you share your beauty with the world every morning, my princess!"] = "", -- A_Classic_Fairytale:journey @@ -775,23 +1028,28 @@ -- ["This must be the caves!"] = "", -- A_Classic_Fairytale:backstab -- ["This one's tricky."] = "", -- ["This rain is really something..."] = "", +-- ["This was an awesome performance! But this challenge can be finished with even just one RC plane. Can you figure out how?"] = "", -- User_Mission_-_RCPlane_Challenge -- ["This will be fun!"] = "", -- A_Classic_Fairytale:enemy -- ["Those aliens are destroying the island!"] = "", -- A_Classic_Fairytale:family -- ["TIME: "] = "", -- ["Timed Kamikaze!"] = "", -- ["Time Extended!"] = "", -- ["Time Extension"] = "", +-- ["Time's up!"] = "", -- Basic_Training_-_Sniper_Rifle -- ["Tip: The rope physics are different than in the real world, |use it to your advantage!"] = "", -- Basic_Training_-_Rope -- ["Toggle Shield"] = "", -- ["To help you, of course!"] = "", -- A_Classic_Fairytale:journey +-- ["Top-class elite pilot"] = "", -- User_Mission_-_RCPlane_Challenge -- ["To place a girder, select it, use [Left] and [Right] to select angle and length, place with [Left Click]"] = "", -- A_Classic_Fairytale:shadow -- ["Torn Muscle"] = "", -- A_Classic_Fairytale:journey -- [" to save the village."] = "", -- A_Classic_Fairytale:dragon -- ["To the caves..."] = "", -- A_Classic_Fairytale:united -- ["Toxic Team"] = "", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork -- ["TRACK COMPLETED"] = "", --- ["TRACK FAILED!"] = "", + +-- ["Trainee"] = "", -- TargetPractice -- ["training"] = "", -- portal +-- ["Training Team"] = "", -- TargetPractice -- ["Traitors"] = "", -- A_Classic_Fairytale:epil -- ["Tribe"] = "", -- A_Classic_Fairytale:backstab -- ["TrophyRace"] = "", @@ -807,29 +1065,37 @@ -- ["ULTRA KILL"] = "", -- Mutant -- ["Under Construction"] = "", -- A_Classic_Fairytale:shadow -- ["Unexpected Igor"] = "", -- A_Classic_Fairytale:dragon --- ["Unit"] = "", +-- ["Unique new weapons"] = "", -- Continental_supplies +-- ["Unit"] = "", -- User_Mission_-_Newton_and_the_Hammock -- ["Unit 0x0007"] = "", -- A_Classic_Fairytale:family -- ["Unit 334a$7%;.*"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united -- ["Unit 3378"] = "", --- ["Unit 835"] = "", +-- ["Unit 835"] = "", -- User_Mission_-_Bamboo_Thicket -- ["United We Stand"] = "", -- A_Classic_Fairytale:united -- ["Unlimited Attacks"] = "", -- ["Unlucky Sods"] = "", -- User_Mission_-_Rope_Knock_Challenge -- ["Unstoppable!"] = "", -- ["Unsuspecting Louts"] = "", -- User_Mission_-_Rope_Knock_Challenge -- ["[Up], [Down] to aim, [Space] to shoot!"] = "", -- A_Classic_Fairytale:first_blood +-- ["Upper-class elite pilot"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Use it wisely!"] = "", -- A_Classic_Fairytale:dragon -- ["Use it with precaution!"] = "", -- A_Classic_Fairytale:first_blood -- ["User Challenge"] = "", - +-- ["Use the air-attack weapons and the arrow keys to select structures."] = "", -- Construction_Mode -- ["Use the portal gun to get to the next crate, then use the new gun to get to the final destination!|"] = "", -- A_Classic_Fairytale:dragon +-- ["Use the portal to move fast and far, use it to kill, use it with caution!"] = "", -- portal -- ["Use the rope to get on the head of the mole, young one!"] = "", -- A_Classic_Fairytale:first_blood -- ["Use the rope to knock your enemies to their doom."] = "", -- User_Mission_-_Rope_Knock_Challenge +-- ["Use your ready time to think."] = "", -- Frenzy +-- ["Use your rope to collect all crates as fast as possible."] = "", -- SpeedShoppa -- ["Use your rope to get from start to finish as fast as you can!"] = "", +-- ["Utility Crate Placement Mode"] = "", -- Construction_Mode +-- ["Vampirism"] = "", -- Construction_Mode -- ["Vedgies"] = "", -- A_Classic_Fairytale:journey -- ["Vegan Jack"] = "", -- A_Classic_Fairytale:enemy -- ["Victory!"] = "", -- Basic_Training_-_Rope -- ["Victory for the "] = "", -- CTF_Blizzard, Capture_the_Flag +-- ["voldemort"] = "", -- portal -- ["Violence is not the answer to your problems!"] = "", -- A_Classic_Fairytale:first_blood -- ["Walls Left"] = "", -- WxW -- ["Walls Required"] = "", -- WxW @@ -837,10 +1103,14 @@ -- ["Wannabe Flyboys"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Wannabe Shoppsta"] = "", -- User_Mission_-_Rope_Knock_Challenge -- ["Watch your steps, young one!"] = "", -- A_Classic_Fairytale:first_blood +-- ["Watermelon Bomb"] = "", -- Construction_Mode -- ["Waypoint placed."] = "", -- ["Way-Points Remaining"] = "", -- ["Weaklings"] = "", -- A_Classic_Fairytale:shadow -- ["We all know what happens when you get frightened..."] = "", -- A_Classic_Fairytale:first_blood +-- ["Weapon Crate Placement Mode"] = "", -- Construction_Mode +-- ["Weapon Filter"] = "", -- Construction_Mode +-- ["weaponschemes"] = "", -- Continental_supplies -- ["Weapons Reset"] = "", -- ["Weapons reset."] = "", -- Highlander -- ["We are indeed."] = "", -- A_Classic_Fairytale:backstab @@ -893,6 +1163,7 @@ -- ["Where do you get that?!"] = "", -- A_Classic_Fairytale:enemy -- ["Where have you been?!"] = "", -- A_Classic_Fairytale:backstab -- ["Where have you been?"] = "", -- A_Classic_Fairytale:united +-- ["Whip"] = "", -- Construction_Mode -- ["? Why?"] = "", -- A_Classic_Fairytale:backstab -- ["Why "] = "", -- A_Classic_Fairytale:backstab -- ["! Why?!"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united @@ -904,9 +1175,12 @@ -- ["Why do you want to take over our island?"] = "", -- A_Classic_Fairytale:enemy -- ["Why me?!"] = "", -- A_Classic_Fairytale:backstab -- ["Why would they do this?"] = "", -- A_Classic_Fairytale:backstab +-- ["Will be useful if I need a new plateform or if I want to rise...."] = "", -- portal -- ["- Will Get 1-3 random weapons"] = "", -- Continental_supplies --- ["- Will refresh Parachute each turn."] = "", -- Continental_supplies --- ["- Will refresh portalgun each turn."] = "", -- Continental_supplies +-- ["- Will give you an airstrike every fifth turn."] = "", -- Continental_supplies +-- ["- Will give you a parachute every second turn."] = "", -- Continental_supplies + + -- ["Will this ever end?"] = "", -- ["WINNER IS "] = "", -- Mutant -- ["WINNING TIME: "] = "", @@ -925,6 +1199,7 @@ -- ["Yes!"] = "", -- A_Classic_Fairytale:enemy -- ["Yes, yeees! You are now ready to enter the real world!"] = "", -- A_Classic_Fairytale:first_blood -- ["Yo, dude, we're here, too!"] = "", -- A_Classic_Fairytale:family +-- ["You are far from home, and the water is rising, climb up as high as you can!"] = "", -- ClimbHome -- ["You are given the chance to turn your life around..."] = "", -- A_Classic_Fairytale:shadow -- ["You are playing with our lives here!"] = "", -- A_Classic_Fairytale:enemy -- ["! You bastards!"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united @@ -934,21 +1209,43 @@ -- ["You'd almost swear the water was rising!"] = "", -- ["You'd better watch your steps..."] = "", -- A_Classic_Fairytale:journey -- ["You did not make it in time, try again!"] = "", -- Basic_Training_-_Rope +-- ["You had %.2fs remaining on the clock (+%d points)."] = "", -- Basic_Training_-_Sniper_Rifle +-- ["You had %.1fs remaining on the clock (+%d points)."] = "", -- TargetPractice -- ["You have 7 turns until the next wave arrives.|Make sure the arriving cannibals are greeted appropriately!|If the hog dies, the cause is lost.|Hint: you might want to use some mines..."] = "", -- A_Classic_Fairytale:backstab -- ["You have "] = "", -- A_Classic_Fairytale:dragon -- ["You have been giving us out to the enemy, haven't you!"] = "", -- A_Classic_Fairytale:backstab -- ["You have been respawned, at your last checkpoint!"] = "", -- Basic_Training_-_Rope -- ["You have been respawned, be more carefull next time!"] = "", -- Basic_Training_-_Rope -- ["You have chosen the perfect moment to leave."] = "", -- A_Classic_Fairytale:united +-- ["You have collected %d out of %d crate(s)."] = "", -- SpeedShoppa +-- ["You have destroyed %d of %d targets."] = "", -- Basic_Training_-_Bazooka +-- ["You have destroyed %d of %d targets (+%d points)."] = "", -- Basic_Training_-_Sniper_Rifle +-- ["You have dropped %d missiles."] = "", -- User_Mission_-_RCPlane_Challenge -- ["You have failed to complete your task, young one!"] = "", -- A_Classic_Fairytale:journey -- ["You have failed to save the tribe!"] = "", -- A_Classic_Fairytale:backstab -- ["You have finally figured it out!"] = "", -- A_Classic_Fairytale:enemy +-- ["You have finished the bazooka training!"] = "", -- Basic_Training_-_Bazooka +-- ["You have finished the challenge!"] = "", -- User_Mission_-_RCPlane_Challenge +-- ["You have finished the challenge in %.3f s."] = "", -- SpeedShoppa +-- ["You have finished the target practice!"] = "", -- TargetPractice +-- ["You have gained an achievement: %s"] = "", -- User_Mission_-_RCPlane_Challenge -- ["You have kidnapped our whole tribe!"] = "", -- A_Classic_Fairytale:enemy -- ["You have killed an innocent hedgehog!"] = "", -- A_Classic_Fairytale:backstab +-- ["You have launched %d bazookas."] = "", -- Basic_Training_-_Bazooka +-- ["You have launched %d homing bees."] = "", -- Target_Practice_-_Homing_Bee +-- ["You have made %d shots."] = "", -- Basic_Training_-_Sniper_Rifle +-- ["You haven't rescued anyone."] = "", -- User_Mission_-_That_Sinking_Feeling +-- ["You have obtained an achievement: Lively Lifeguard"] = "", -- User_Mission_-_That_Sinking_Feeling +-- ["You have perfectly beaten the challenge!"] = "", -- User_Mission_-_RCPlane_Challenge -- ["You have proven yourself worthy to see our most ancient secret!"] = "", -- A_Classic_Fairytale:first_blood -- ["You have proven yourselves worthy!"] = "", -- A_Classic_Fairytale:enemy -- ["You have SCORED!!"] = "", +-- ["You have shot %d times."] = "", -- TargetPractice +-- ["You have successfully finished the sniper rifle training!"] = "", -- Basic_Training_-_Sniper_Rifle +-- ["You have thrown %d grenades."] = "", -- Target_Practice_-_Grenade_easy, Target_Practice_-_Grenade_hard -- ["You have to destroy 12 targets in 180 seconds"] = "", -- Basic_Training_-_Cluster_Bomb +-- ["You have used only 1 RC plane. Outstanding!"] = "", -- User_Mission_-_RCPlane_Challenge +-- ["You have used %d RC planes."] = "", -- User_Mission_-_RCPlane_Challenge -- ["You have won the game by proving true cooperative skills!"] = "", -- A_Classic_Fairytale:enemy -- ["You just appeared out of thin air!"] = "", -- A_Classic_Fairytale:backstab -- ["You just committed suicide..."] = "", -- A_Classic_Fairytale:shadow @@ -956,11 +1253,17 @@ -- ["You know...taking a stroll."] = "", -- A_Classic_Fairytale:backstab -- ["You know what? I don't even regret anything!"] = "", -- A_Classic_Fairytale:backstab -- ["You'll see what I mean!"] = "", -- A_Classic_Fairytale:enemy +-- ["You lose!] = "", -- Basic_Training_-_Bazooka -- ["You may only attack from a rope!"] = "", -- WxW +-- ["You may only spawn 5 crates per turn."] = "", -- Construction_Mode +-- ["You may only use 1 Extra Time per turn."] = "", -- Construction_Mode -- ["You meatbags are pretty slow, you know!"] = "", -- A_Classic_Fairytale:enemy -- ["You might want to find a way to instantly kill arriving cannibals!"] = "", -- A_Classic_Fairytale:backstab +-- ["You must survive the flood in order to score."] = "", -- User_Mission_-_That_Sinking_Feeling -- ["Young one, you are telling us that they can instantly change location without a shaman?"] = "", -- A_Classic_Fairytale:united -- ["You probably know what to do next..."] = "", -- A_Classic_Fairytale:first_blood +-- ["Your accuracy was %.1f%%."] = "", -- Basic_Training_-_Bazooka +-- ["Your accuracy was %.1f%% (+%d points)."] = "", -- TargetPractice -- ["Your deaths will be avenged, cannibals!"] = "", -- A_Classic_Fairytale:enemy -- ["Your death will not be in vain, Dense Cloud!"] = "", -- A_Classic_Fairytale:shadow -- ["You're...alive!? But we saw you die!"] = "", -- A_Classic_Fairytale:backstab @@ -970,16 +1273,22 @@ -- ["You're pathetic! You are not worthy of my attention..."] = "", -- A_Classic_Fairytale:shadow -- ["You're probably wondering why I bought you back..."] = "", -- A_Classic_Fairytale:backstab -- ["You're terrorizing the forest...We won't catch anything like this!"] = "", -- A_Classic_Fairytale:shadow +-- ["Your hedgehog died!"] = "", -- User_Mission_-_That_Sinking_Feeling -- ["Your hogs must survive!"] = "", -- A_Classic_Fairytale:journey -- ["Your movement skills will be evaluated now."] = "", -- A_Classic_Fairytale:first_blood +-- ["Your rank: %s"] = "", -- User_Mission_-_RCPlane_Challenge -- ["You saved"] = "", +-- ["You saved %d of 8 Hapless Hogs."] = "", -- User_Mission_-_That_Sinking_Feeling -- ["You've been assaulting us, we have been just defending ourselves!"] = "", -- A_Classic_Fairytale:enemy -- ["You've failed. Try again."] = "", -- ["You've reached the goal!| |Time: "] = "", -- ["You will be avenged!"] = "", -- A_Classic_Fairytale:shadow +-- ["- You will recieve 2-4 weapons on each kill! (Even on own hogs)"] = "", -- Continental_supplies -- ["You won't believe what happened to me!"] = "", -- A_Classic_Fairytale:backstab -- ["Yuck! I bet they'll keep worshipping her even after I save the village!"] = "", -- A_Classic_Fairytale:family -- ["Zealandia"] = "", -- Continental_supplies +-- ["zombi"] = "", -- portal +-- ["Zook"] = "", -- Target_Practice_-_Bazooka_easy, Target_Practice_-_Bazooka_hard -- ["'Zooka Team"] = "", -- ["Zork"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen } diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/sv.lua --- a/share/hedgewars/Data/Locale/sv.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/sv.lua Tue Nov 10 20:43:13 2015 +0100 @@ -4,6 +4,10 @@ ["!!!"] = "!!!", -- ["011101000"] = "", -- A_Classic_Fairytale:dragon -- ["011101001"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:family, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united +-- ["+1 to a Bottom Feeder for killing anyone"] = "", -- Mutant +-- ["+1 to a Mutant for killing anyone"] = "", -- Mutant +-- ["-1 to anyone for a suicide"] = "", -- Mutant +-- ["+2 for becoming a Mutant"] = "", -- Mutant -- ["30 minutes later..."] = "", -- A_Classic_Fairytale:shadow -- ["About a month ago, a cyborg came and told us that you're the cannibals!"] = "", -- A_Classic_Fairytale:enemy -- ["Accuracy Bonus!"] = "", @@ -13,17 +17,27 @@ -- ["???"] = "", -- A_Classic_Fairytale:backstab -- ["Actually, you aren't worthy of life! Take this..."] = "", -- A_Classic_Fairytale:shadow -- ["A cy-what?"] = "", -- A_Classic_Fairytale:enemy +-- ["Advanced Repositioning Mode"] = "", -- Construction_Mode -- ["Adventurous"] = "", -- A_Classic_Fairytale:journey +-- ["a frenetic Hedgewars mini-game"] = "", -- Frenzy -- ["Africa"] = "", -- Continental_supplies -- ["After Leaks A Lot betrayed his tribe, he joined the cannibals..."] = "", -- A_Classic_Fairytale:first_blood -- ["After the shock caused by the enemy spy, Leaks A Lot and Dense Cloud went hunting to relax."] = "", -- A_Classic_Fairytale:shadow -- ["Again with the 'cannibals' thing!"] = "", -- A_Classic_Fairytale:enemy +-- ["Aggressively removes enemy hedgehogs."] = "", -- Construction_Mode -- ["a Hedgewars challenge"] = "", -- User_Mission_-_RCPlane_Challenge, User_Mission_-_Rope_Knock_Challenge -- ["a Hedgewars mini-game"] = "", -- Space_Invasion, The_Specialists +-- ["a Hedgewars tag game"] = "", -- Mutant +-- ["AHHh, home sweet home. Made it in %d seconds."] = "", -- ClimbHome ["Aiming Practice"] = "Siktesövning", --Bazooka, Shotgun, SniperRifle +-- ["Air Attack"] = "", -- Construction_Mode -- ["A leap in a leap"] = "", -- A_Classic_Fairytale:first_blood -- ["A little gift from the cyborgs"] = "", -- A_Classic_Fairytale:shadow -- ["All gone...everything!"] = "", -- A_Classic_Fairytale:enemy +-- ["Allows free teleportation between other nodes."] = "", -- Construction_Mode +-- ["Allows placement of girders, rubber-bands, mines, sticky mines and barrels."] = "", -- Construction_Mode +-- ["Allows placement of structures."] = "", -- Construction_Mode +-- ["Allows the placement of weapons, utiliites, and health crates."] = "", -- Construction_Mode -- ["All right, we just need to get to the other side of the island!"] = "", -- A_Classic_Fairytale:journey -- ["All walls touched!"] = "", -- WxW -- ["Ammo"] = "", @@ -38,8 +52,11 @@ -- ["And so they discovered that cyborgs weren't invulnerable..."] = "", -- A_Classic_Fairytale:journey -- ["And where's all the weed?"] = "", -- A_Classic_Fairytale:dragon -- ["And you believed me? Oh, god, that's cute!"] = "", -- A_Classic_Fairytale:journey --- ["Anno 1032: [The explosion will make a strong push ~ wide range, wont affect hogs close to the target]"] = "", -- Continental_supplies +-- ["Anno 1032: [The explosion will make a strong push ~ Wide range, wont affect hogs close to the target]"] = "", -- Continental_supplies + -- ["Antarctica"] = "", -- Continental_supplies +-- ["Antarctic summer: - Will give you one girder/mudball and two sineguns/portals every fourth turn."] = "", -- Continental_supplies +-- ["Area"] = "", -- Continental_supplies -- ["Are we there yet?"] = "", -- A_Classic_Fairytale:shadow -- ["Are you accusing me of something?"] = "", -- A_Classic_Fairytale:backstab -- ["Are you saying that many of us have died for your entertainment?"] = "", -- A_Classic_Fairytale:enemy @@ -59,23 +76,31 @@ -- ["[Backspace]"] = "", -- ["Backstab"] = "", -- A_Classic_Fairytale:backstab -- ["Bad Team"] = "", -- User_Mission_-_The_Great_Escape +-- ["Ballgun"] = "", -- Construction_Mode -- ["Bamboo Thicket"] = "", -- ["Barrel Eater!"] = "", -- ["Barrel Launcher"] = "", +-- ["Barrel Placement Mode"] = "", -- Construction_Mode +-- ["Baseball Bat"] = "", -- Construction_Mode -- ["Baseballbat"] = "", -- Continental_supplies ["Bat balls at your enemies and|push them into the sea!"] = "Slå bollar mot dina fiender|och slå ner dem i havet", ["Bat your opponents through the|baskets and out of the map!"] = "Slå ner dina motståndare i|korgarna och ut ur kartan!", +-- ["Bazooka"] = "", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 ["Bazooka Training"] = "Bazookaträning", -- ["Beep Loopers"] = "", -- A_Classic_Fairytale:queen ["Best laps per team: "] = "Bästa varv per lag: ", -- ["Best Team Times: "] = "", -- ["Beware, though! If you are slow, you die!"] = "", -- A_Classic_Fairytale:dragon +-- ["Bio-Filter"] = "", -- Construction_Mode -- ["Biomechanic Team"] = "", -- A_Classic_Fairytale:family +-- ["Birdy"] = "", -- Construction_Mode -- ["Blender"] = "", -- A_Classic_Fairytale:family -- ["Bloodpie"] = "", -- A_Classic_Fairytale:backstab -- ["Bloodrocutor"] = "", -- A_Classic_Fairytale:shadow -- ["Bloodsucker"] = "", -- A_Classic_Fairytale:shadow ["Bloody Rookies"] = "Blodiga gröngölingar", -- 01#Boot_Camp, User_Mission_-_Dangerous_Ducklings, User_Mission_-_Diver, User_Mission_-_Spooky_Tree +-- ["Blowtorch"] = "", -- Construction_Mode, Frenzy +-- ["Blue Team"] = "", -- User_Mission_-_Dangerous_Ducklings -- ["Bone Jackson"] = "", -- A_Classic_Fairytale:backstab -- ["Bonely"] = "", -- A_Classic_Fairytale:shadow -- ["BOOM!"] = "", @@ -89,6 +114,7 @@ -- ["Brain Teaser"] = "", -- A_Classic_Fairytale:backstab -- ["Brutal Lily"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil -- ["Brutus"] = "", -- A_Classic_Fairytale:backstab +-- ["Build a fortress and destroy your enemy."] = "", -- Construction_Mode -- ["Build a track and race."] = "", -- ["Bullseye"] = "", -- A_Classic_Fairytale:dragon -- ["But it proved to be no easy task!"] = "", -- A_Classic_Fairytale:dragon @@ -99,6 +125,7 @@ -- ["But why would they help us?"] = "", -- A_Classic_Fairytale:backstab -- ["But you're cannibals. It's what you do."] = "", -- A_Classic_Fairytale:enemy -- ["But you said you'd let her go!"] = "", -- A_Classic_Fairytale:journey +-- ["Cake"] = "", -- Construction_Mode -- ["Call me Beep! Well, 'cause I'm such a nice...person!"] = "", -- A_Classic_Fairytale:family -- ["Cannibals"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:first_blood -- ["Cannibal Sentry"] = "", -- A_Classic_Fairytale:journey @@ -108,8 +135,15 @@ -- ["Carol"] = "", -- A_Classic_Fairytale:family -- ["CHALLENGE COMPLETE"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Change Weapon"] = "", +-- ["changing range from %i%% to %i%% with period of %i msec"] = "", -- Gravity -- ["Choose your side! If you want to join the strange man, walk up to him.|Otherwise, walk away from him. If you decide to att...nevermind..."] = "", -- A_Classic_Fairytale:shadow +-- ["Cleaver"] = "", -- Construction_Mode +-- ["Cleaver Placement Mode"] = "", -- Construction_Mode +-- ["Climber"] = "", -- ClimbHome +-- ["Climb Home"] = "", -- ClimbHome +-- ["Clowns"] = "", -- User_Mission_-_Nobody_Laugh -- ["Clumsy"] = "", +-- ["Cluster Bomb"] = "", -- Construction_Mode -- ["Cluster Bomb MASTER!"] = "", -- Basic_Training_-_Cluster_Bomb -- ["Cluster Bomb Training"] = "", -- Basic_Training_-_Cluster_Bomb ["Codename: Teamwork"] = "Kodnamn: Lagarbete", @@ -129,12 +163,19 @@ -- ["Congratulations! You needed only half of time|to eliminate all targets."] = "", -- Basic_Training_-_Cluster_Bomb -- ["Congratulations! You've completed the Rope tutorial! |- Tutorial ends in 10 seconds!"] = "", -- Basic_Training_-_Rope ["Congratulations! You've eliminated all targets|within the allowed time frame."] = "Grattis! Du har förstört alla målen inom den|tillåtna tidsramen.", --Bazooka, Shotgun, SniperRifle +-- ["CONSTRUCTION MODE"] = "", -- Construction_Mode +-- ["Construction Station"] = "", -- Construction_Mode -- ["Continental supplies"] = "", -- Continental_supplies ["Control pillars to score points."] = "Kontrollera pelare för att ta poäng", +-- ["Core"] = "", -- Construction_Mode -- ["Corporationals"] = "", -- A_Classic_Fairytale:queen -- ["Corpsemonger"] = "", -- A_Classic_Fairytale:shadow -- ["Corpse Thrower"] = "", -- A_Classic_Fairytale:epil +-- ["Cost"] = "", -- Construction_Mode +-- ["Crate Placement Tool"] = "", -- Construction_Mode -- ["Crates Left:"] = "", -- User_Mission_-_RCPlane_Challenge +-- ["Cricket time: [Drop a fireable mine! ~ Will work if fired close to your hog & far away from enemy ~ 1 sec]"] = "", -- Continental_supplies +-- ["Current setting is "] = "", -- Gravity ["Cybernetic Empire"] = "Robotriket", -- ["Cyborg. It's what the aliens call themselves."] = "", -- A_Classic_Fairytale:enemy -- ["Dahmer"] = "", -- A_Classic_Fairytale:backstab @@ -142,15 +183,19 @@ ["DAMMIT, ROOKIE!"] = "SATAN, GRÖNGÖLING!", ["Dangerous Ducklings"] = "Farliga ankungar", -- ["Deadweight"] = "", +-- ["Decrease"] = "", -- Continental_supplies -- ["Defeat the cannibals"] = "", -- A_Classic_Fairytale:backstab -- ["Defeat the cannibals!|"] = "", -- A_Classic_Fairytale:united -- ["Defeat the cannibals!|Grenade hint: set the timer with [1-5], aim with [Up]/[Down] and hold [Space] to set power"] = "", -- A_Classic_Fairytale:shadow -- ["Defeat the cyborgs!"] = "", -- A_Classic_Fairytale:enemy +-- ["Defend your core from the enemy."] = "", -- Construction_Mode -- ["Defend yourself!|Hint: You can get tips on using weapons by moving your mouse over them in the weapon selection menu"] = "", -- A_Classic_Fairytale:shadow +-- ["Dematerializes weapons and equipment carried by enemy hedgehogs."] = "", -- Construction_Mode -- ["Demolition is fun!"] = "", -- ["Dense Cloud"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united -- ["Dense Cloud must have already told them everything..."] = "", -- A_Classic_Fairytale:shadow -- ["Depleted Kamikaze!"] = "", +-- ["Desert Eagle"] = "", -- Construction_Mode, A_Space_Adventure:death02 -- ["Destroy him, Leaks A Lot! He is responsible for the deaths of many of us!"] = "", -- A_Classic_Fairytale:first_blood -- ["Destroy invaders to score points."] = "", -- ["Destroy the targets!|Hint: Select the Shoryuken and hit [Space]|P.S. You can use it mid-air."] = "", -- A_Classic_Fairytale:first_blood @@ -169,9 +214,12 @@ -- ["Do you have any idea how valuable grass is?"] = "", -- A_Classic_Fairytale:enemy -- ["Do you think you're some kind of god?"] = "", -- A_Classic_Fairytale:enemy -- ["Dragon's Lair"] = "", -- A_Classic_Fairytale:dragon +-- ["Drill Rocket"] = "", -- Construction_Mode -- ["Drills"] = "", -- A_Classic_Fairytale:backstab +-- ["Drill Strike"] = "", -- Construction_Mode -- ["Drone Hunter!"] = "", --- ["Drop a bomb: [drop some heroic wind that will turn into a bomb on impact]"] = "", -- Continental_supplies +-- ["Drop a bomb: [Drop some heroic wind that will turn into a bomb on impact]"] = "", -- Continental_supplies + -- ["Drowner"] = "", -- ["Dude, all the plants are gone!"] = "", -- A_Classic_Fairytale:family -- ["Dude, can you see Ramon and Spiky?"] = "", -- A_Classic_Fairytale:journey @@ -181,11 +229,15 @@ -- ["Dude, where are we?"] = "", -- A_Classic_Fairytale:backstab -- ["Dude, wow! I just had the weirdest high!"] = "", -- A_Classic_Fairytale:backstab -- ["Duration"] = "", -- Continental_supplies --- ["Dust storm: [Deals 20 damage to all enemies in the circle]"] = "", -- Continental_supplies +-- ["Dust storm: [Deals 15 damage to all enemies in the circle]"] = "", -- Continental_supplies + +-- ["Dynamite"] = "", -- Construction_Mode +-- ["Each turn is only ONE SECOND!"] = "", -- Frenzy -- ["Each turn you get 1-3 random weapons"] = "", -- ["Each turn you get one random weapon"] = "", -- ["Eagle Eye"] = "", -- A_Classic_Fairytale:backstab --- ["Eagle Eye: [Blink to the impact ~ one shot]"] = "", -- Continental_supplies +-- ["Eagle Eye: [Blink to the impact ~ One shot]"] = "", -- Continental_supplies + -- ["Ear Sniffer"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:epil -- ["Elderbot"] = "", -- A_Classic_Fairytale:family -- ["Elimate your captor."] = "", -- User_Mission_-_The_Great_Escape @@ -208,8 +260,9 @@ -- ["Every single time!"] = "", -- A_Classic_Fairytale:dragon -- ["Everything looks OK..."] = "", -- A_Classic_Fairytale:enemy -- ["Exactly, man! That was my dream."] = "", -- A_Classic_Fairytale:backstab +-- ["Extra Damage"] = "", -- Construction_Mode +-- ["Extra Time"] = "", -- Construction_Mode -- ["Eye Chewer"] = "", -- A_Classic_Fairytale:journey --- ["INSANITY"] = "", -- Mutant -- ["Family Reunion"] = "", -- A_Classic_Fairytale:family ["Fastest lap: "] = "Snabbast varv: ", ["Feeble Resistance"] = "Klent motstånd", @@ -219,10 +272,11 @@ -- ["Femur Lover"] = "", -- A_Classic_Fairytale:shadow -- ["Fierce Competition!"] = "", -- Space_Invasion -- ["Fiery Water"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united +-- ["Filthy Blue"] = "", -- User_Mission_-_Dangerous_Ducklings -- ["Find your tribe!|Cross the lake!"] = "", -- A_Classic_Fairytale:dragon -- ["Finish your training|Hint: Animations can be skipped with the [Precise] key."] = "", -- A_Classic_Fairytale:first_blood -- ["Fire"] = "", --- ["Fire a mine: [Does what it says ~ Cant be dropped close to an enemy ~ 1 sec]"] = "", -- Continental_supplies + -- ["First aid kits?!"] = "", -- A_Classic_Fairytale:united -- ["First Blood"] = "", -- A_Classic_Fairytale:first_blood -- ["FIRST BLOOD MUTATES"] = "", -- Mutant @@ -232,11 +286,15 @@ ["Flag returned!"] = "Flagga återvänd!", -- ["Flags, and their home base will be placed where each team ends their first turn."] = "", -- ["Flamer"] = "", +-- ["Flamethrower"] = "", -- Construction_Mode -- ["Flaming Worm"] = "", -- A_Classic_Fairytale:backstab --- ["Flare: [fire up some bombs depending on hogs depending on hogs in the circle"] = "", -- Continental_supplies + -- ["Flesh for Brainz"] = "", -- A_Classic_Fairytale:journey +-- ["Flying Saucer"] = "", -- Construction_Mode, Frenzy -- ["For improved features/stability, play 0.9.18+"] = "", -- WxW -- ["Free Dense Cloud and continue the mission!"] = "", -- A_Classic_Fairytale:journey +-- ["Freezer"] = "", -- Construction_Mode +-- ["FRENZY"] = "", -- Frenzy -- ["Friendly Fire!"] = "", -- ["fuel extended!"] = "", -- ["GAME BEGUN!!!"] = "", @@ -246,6 +304,9 @@ -- ["Game? Was this a game to you?!"] = "", -- A_Classic_Fairytale:enemy -- ["GasBomb"] = "", -- Continental_supplies -- ["Gas Gargler"] = "", -- A_Classic_Fairytale:queen +-- ["General information"] = "", -- Continental_supplies +-- ["Generates power."] = "", -- Construction_Mode +-- ["Generator"] = "", -- Construction_Mode -- ["Get Dense Cloud out of the pit!"] = "", -- A_Classic_Fairytale:journey ["Get on over there and take him out!"] = "Ta dig bort där och gör dig av med honom!", -- ["Get on the head of the mole"] = "", -- A_Classic_Fairytale:first_blood @@ -256,6 +317,8 @@ -- ["Get your teammates out of their natural prison and save the princess!|Hint: Drilling holes should solve everything.|Hint: It might be a good idea to place a girder before starting to drill. Just saying.|Hint: All your hedgehogs need to be above the marked height!|Hint: Leaks A Lot needs to get really close to the princess!"] = "", -- A_Classic_Fairytale:family -- ["GG!"] = "", -- User_Mission_-_Rope_Knock_Challenge -- ["Gimme Bones"] = "", -- A_Classic_Fairytale:backstab +-- ["Girder"] = "", -- Construction_Mode +-- ["Girder Placement Mode"] = "", -- Construction_Mode -- ["Glark"] = "", -- A_Classic_Fairytale:shadow -- ["Goal"] = "", ["GO! GO! GO!"] = "Kör! Kör! Kör!", @@ -272,12 +335,16 @@ -- ["Go surf!"] = "", -- WxW -- ["GOTCHA!"] = "", -- ["Grab Mines/Explosives"] = "", +-- ["Grants nearby hogs life-regeneration."] = "", -- Construction_Mode +-- ["Gravity"] = "", -- Gravity -- ["Great choice, Steve! Mind if I call you that?"] = "", -- A_Classic_Fairytale:shadow -- ["Great work! Now hit it with your Baseball Bat! |Tip: You can change weapon with 'Right Click'!"] = "", -- Basic_Training_-_Rope -- ["Great! You will be contacted soon for assistance."] = "", -- A_Classic_Fairytale:shadow --- ["Green lipstick bullet: [Is poisonous]"] = "", -- Continental_supplies + +-- ["Green lipstick bullet: [Poisonous, deals no damage]"] = "", -- Continental_supplies -- ["Greetings, "] = "", -- A_Classic_Fairytale:dragon -- ["Greetings, cloudy one!"] = "", -- A_Classic_Fairytale:shadow +-- ["Grenade"] = "", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 -- ["Grenade Training"] = "", -- Basic_Training_-_Grenade -- ["Grenadiers"] = "", -- Basic_Training_-_Grenade -- ["Guys, do you think there's more of them?"] = "", -- A_Classic_Fairytale:backstab @@ -285,23 +352,27 @@ -- ["Haha!"] = "", -- A_Classic_Fairytale:united -- ["Hahahaha!"] = "", -- ["Haha, now THAT would be something!"] = "", +-- ["Hammer"] = "", -- Construction_Mode, Continental_supplies -- ["Hannibal"] = "", -- A_Classic_Fairytale:epil -- ["Hapless Hogs"] = "", -- [" Hapless Hogs left!"] = "", - -- [" HAS MUTATED"] = "", -- Mutant -- ["Hatless Jerry"] = "", -- A_Classic_Fairytale:queen -- ["Have no illusions, your tribe is dead, indifferent of your choice."] = "", -- A_Classic_Fairytale:shadow -- ["Have we ever attacked you first?"] = "", -- A_Classic_Fairytale:enemy +-- ["Healing Station"] = "", -- Construction_Mode +-- ["Health Crate Placement Mode"] = "", -- Construction_Mode -- ["Health crates extend your time."] = "", -- ["Heavy"] = "", -- ["Heavy Cannfantry"] = "", -- A_Classic_Fairytale:united -- ["Hedge-cogs"] = "", -- A_Classic_Fairytale:enemy --- ["Hedgehog projectile: [fire your hog like a Sticky Bomb]"] = "", -- Continental_supplies +-- ["Hedgehog projectile: [Fire your hog like a Sticky Bomb]"] = "", -- Continental_supplies + ["Hedgewars-Basketball"] = "Hedgewars-Basket", ["Hedgewars-Knockball"] = "Hedgewars-Knockball", -- ["Hedgibal Lecter"] = "", -- A_Classic_Fairytale:backstab -- ["Heh, it's not that bad."] = "", +-- ["Hellish Handgrenade"] = "", -- Construction_Mode -- ["Hello again, "] = "", -- A_Classic_Fairytale:family -- ["Help me, Leaks!"] = "", -- A_Classic_Fairytale:journey -- ["Help me, please!!!"] = "", -- A_Classic_Fairytale:journey @@ -333,6 +404,7 @@ -- ["Hogminator"] = "", -- A_Classic_Fairytale:family -- ["Hogs in sight!"] = "", -- Continental_supplies -- ["HOLY SHYTE!"] = "", -- Mutant +-- ["Homing Bee"] = "", -- Construction_Mode -- ["Honest Lee"] = "", -- A_Classic_Fairytale:enemy ["Hooray!"] = "Hurra!", -- ["Hostage Situation"] = "", -- A_Classic_Fairytale:family @@ -366,7 +438,6 @@ -- ["If you get stuck, use your Desert Eagle or restart the mission!|"] = "", -- A_Classic_Fairytale:journey -- ["If you know what I mean..."] = "", -- A_Classic_Fairytale:shadow -- ["If you say so..."] = "", -- A_Classic_Fairytale:shadow - -- ["I guess you'll have to kill them."] = "", -- A_Classic_Fairytale:dragon -- ["I have come to make you an offering..."] = "", -- A_Classic_Fairytale:shadow -- ["I have no idea where that mole disappeared...Can you see it?"] = "", -- A_Classic_Fairytale:shadow @@ -389,6 +460,7 @@ -- ["I'm not sure about that!"] = "", -- A_Classic_Fairytale:united -- ["Impressive...you are still dry as the corpse of a hawk after a week in the desert..."] = "", -- A_Classic_Fairytale:first_blood -- ["I'm so scared!"] = "", -- A_Classic_Fairytale:united +-- ["Increase"] = "", -- Continental_supplies -- ["Incredible..."] = "", -- A_Classic_Fairytale:shadow -- ["I need to find the others!"] = "", -- A_Classic_Fairytale:backstab -- ["I need to get to the other side of this island, fast!"] = "", -- A_Classic_Fairytale:journey @@ -397,12 +469,14 @@ -- ["I need to warn the others."] = "", -- A_Classic_Fairytale:backstab -- ["In fact, you are the only one that's been acting strangely."] = "", -- A_Classic_Fairytale:backstab -- ["In order to get to the other side, you need to collect the crates first.|"] = "", -- A_Classic_Fairytale:dragon +-- ["INSANITY"] = "", -- Mutant ["Instructor"] = "Instruktör", -- 01#Boot_Camp, User_Mission_-_Dangerous_Ducklings -- ["Interesting idea, haha!"] = "", -- A_Classic_Fairytale:enemy -- ["Interesting! Last time you said you killed a cannibal!"] = "", -- A_Classic_Fairytale:backstab -- ["In the meantime, take these and return to your \"friend\"!"] = "", -- A_Classic_Fairytale:shadow -- ["invaders destroyed"] = "", -- ["Invasion"] = "", -- A_Classic_Fairytale:united +-- ["Invulnerable"] = "", -- Construction_Mode -- ["I saw it with my own eyes!"] = "", -- A_Classic_Fairytale:shadow -- ["I see..."] = "", -- A_Classic_Fairytale:shadow -- ["I see you have already taken the leap of faith."] = "", -- A_Classic_Fairytale:first_blood @@ -445,6 +519,7 @@ -- ["Just kidding, none of you have died!"] = "", -- A_Classic_Fairytale:enemy -- ["Just on a walk."] = "", -- A_Classic_Fairytale:united -- ["Just wait till I get my hands on that trauma! ARGH!"] = "", -- A_Classic_Fairytale:family +-- ["Kamikaze"] = "", -- Construction_Mode -- ["Kamikaze Expert!"] = "", -- ["Keep it up!"] = "", -- ["Kerguelen"] = "", -- Continental_supplies @@ -454,6 +529,8 @@ -- ["Kill the aliens!"] = "", -- A_Classic_Fairytale:dragon -- ["Kill the cannibal!"] = "", -- A_Classic_Fairytale:first_blood -- ["Kill the traitor...or spare his life!|Kill him or press [Precise]!"] = "", -- A_Classic_Fairytale:backstab +-- ["Land Sprayer"] = "", -- Construction_Mode +-- ["Laser Sight"] = "", -- Construction_Mode -- ["Last Target!"] = "", -- ["Leader"] = "", -- A_Classic_Fairytale:enemy -- ["Leaderbot"] = "", -- A_Classic_Fairytale:queen @@ -464,6 +541,7 @@ -- ["Led Heart"] = "", -- A_Classic_Fairytale:queen -- ["Lee"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen -- ["[Left Shift]"] = "", +-- ["left shift"] = "", -- Continental_supplies -- ["Let a Continent provide your weapons!"] = "", -- Continental_supplies -- ["Let me test your skills a little, will you?"] = "", -- A_Classic_Fairytale:journey -- ["Let's go home!"] = "", -- A_Classic_Fairytale:journey @@ -473,41 +551,56 @@ -- ["Let them have a taste of my fury!"] = "", -- A_Classic_Fairytale:backstab -- ["Let us help, too!"] = "", -- A_Classic_Fairytale:backstab -- ["Light Cannfantry"] = "", -- A_Classic_Fairytale:united +-- ["Limburger"] = "", -- Construction_Mode ["Listen up, maggot!!"] = "Hör här, ynkrygg!!", -- ["Little did they know that this hunt will mark them forever..."] = "", -- A_Classic_Fairytale:shadow -- ["Lively Lifeguard"] = "", --- ["Lonely Cries: [Rise the water if no hog is in the circle and deal 1 damage to all hogs]"] = "", -- Continental_supplies + +-- ["Lonely Cries: [Rise the water if no hog is in the circle and deal 7 damage to all enemy hogs]"] = "", -- Continental_supplies +-- ["Lonely Hog"] = "", -- ClimbHome -- ["Look, I had no choice!"] = "", -- A_Classic_Fairytale:backstab -- ["Look out! There's more of them!"] = "", -- A_Classic_Fairytale:backstab -- ["Look out! We're surrounded by cannibals!"] = "", -- A_Classic_Fairytale:enemy -- ["Looks like the whole world is falling apart!"] = "", -- A_Classic_Fairytale:enemy +-- ["Low Gravity"] = "", -- Construction_Mode, Frenzy -- ["Luckily, I've managed to snatch some of them."] = "", -- A_Classic_Fairytale:united -- ["LUDICROUS KILL"] = "", -- Mutant +-- ["Made it!"] = "", -- ClimbHome +-- ["- Massive weapon bonus on first turn"] = "", -- Continental_supplies -- ["May the spirits aid you in all your quests!"] = "", -- A_Classic_Fairytale:backstab -- ["Medicine: [Fire some exploding medicine that will heal all hogs effected by the explosion]"] = "", -- Continental_supplies -- ["MEGA KILL"] = "", -- Mutant -- ["Meiwes"] = "", -- A_Classic_Fairytale:backstab -- ["Mindy"] = "", -- A_Classic_Fairytale:united +-- ["Mine"] = "", -- Construction_Mode, Frenzy -- ["Mine Deployer"] = "", -- ["Mine Eater!"] = "", +-- ["Mine Placement Mode"] = "", -- Construction_Mode ["|- Mines Time:"] = "|- Mintid:", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork +-- ["Mine Strike"] = "", -- Construction_Mode ["MISSION FAILED"] = "UPPDRAG MISSLYCKADES", -- User_Mission_-_Dangerous_Ducklings, User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork -- ["MISSION SUCCESS"] = "", ["MISSION SUCCESSFUL"] = "UPPDRAG SLUTFÖRT", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork +-- ["Molotov Cocktail"] = "", -- Construction_Mode -- ["Molotov"] = "", -- Continental_supplies -- ["MONSTER KILL"] = "", -- Mutant -- ["More Natives"] = "", -- A_Classic_Fairytale:epil +-- ["Mortar"] = "", -- Construction_Mode, A_Space_Adventure:death02 -- ["Movement: [Up], [Down], [Left], [Right]"] = "", +-- ["Mudball"] = "", -- Construction_Mode -- ["Multi-shot!"] = "", -- ["Muriel"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen -- ["Muscle Dissolver"] = "", -- A_Classic_Fairytale:shadow -- ["-------"] = "", -- Mutant +-- ["Mutant"] = "", -- Mutant -- ["Nade Boy"] = "", -- Basic_Training_-_Grenade -- ["Name"] = "", -- A_Classic_Fairytale:queen -- ["Nameless Heroes"] = "", -- ["Nancy Screw"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:queen +-- ["Napalm"] = "", -- Construction_Mode -- ["Napalm rocket: [Fire a bomb with napalm!]"] = "", -- Continental_supplies -- ["Natives"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:first_blood, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united +-- ["Naughty Ninja"] = "", -- User_Mission_-_Dangerous_Ducklings -- ["New Barrels Per Turn"] = "", -- ["NEW CLAN RECORD: "] = "", ["NEW fastest lap: "] = "NYTT snabbast varv: ", @@ -518,6 +611,7 @@ -- ["Nice work, "] = "", -- A_Classic_Fairytale:dragon -- ["Nice work!"] = "", -- A_Classic_Fairytale:enemy -- ["Nilarian"] = "", -- A_Classic_Fairytale:queen +-- ["Nobody Laugh"] = "", -- User_Mission_-_Nobody_Laugh -- ["No, I came back to help you out..."] = "", -- A_Classic_Fairytale:shadow -- ["No...I wonder where they disappeared?!"] = "", -- A_Classic_Fairytale:journey -- ["Nom-Nom"] = "", -- A_Classic_Fairytale:journey @@ -525,6 +619,7 @@ -- ["Nope. It was one fast mole, that's for sure."] = "", -- A_Classic_Fairytale:shadow -- ["No! Please, help me!"] = "", -- A_Classic_Fairytale:journey -- ["NORMAL"] = "", -- Continental_supplies +-- ["Normal players can only score points by killing the mutant."] = "", -- Mutant -- ["North America"] = "", -- Continental_supplies -- ["Not all hogs are born equal."] = "", -- Highlander -- ["NOT ENOUGH WAYPOINTS"] = "", @@ -537,6 +632,7 @@ -- ["No. Where did he come from?"] = "", -- A_Classic_Fairytale:shadow -- ["Now how do I get on the other side?!"] = "", -- A_Classic_Fairytale:dragon -- ["No. You and the rest of the tribe are safer there!"] = "", -- A_Classic_Fairytale:backstab +-- ["Object Placement Tool"] = "", -- Construction_Mode -- ["Obliterate them!|Hint: You might want to take cover..."] = "", -- A_Classic_Fairytale:shadow -- ["Obstacle course"] = "", -- A_Classic_Fairytale:dragon -- ["Of course I have to save her. What did I expect?!"] = "", -- A_Classic_Fairytale:family @@ -553,24 +649,30 @@ -- ["Once upon a time, on an island with great natural resources, lived two tribes in heated conflict..."] = "", -- A_Classic_Fairytale:first_blood -- ["ONE HOG PER TEAM! KILLING EXCESS HEDGES"] = "", -- Mutant -- ["One tribe was peaceful, spending their time hunting and training, enjoying the small pleasures of life..."] = "", -- A_Classic_Fairytale:first_blood +-- ["on Skip"] = "", -- Continental_supplies -- ["Oops...I dropped them."] = "", -- A_Classic_Fairytale:united -- ["Open that crate and we will continue!"] = "", -- A_Classic_Fairytale:first_blood ["Operation Diver"] = "Operationens dykare", ["Opposing Team: "] = "Motståndarlag: ", +-- ["or 'g=50, g2=150, period=4000' for gravity changing|from 50 to 150 and back with period of 4000 msec"] = "", -- Gravity -- ["Orlando Boom!"] = "", -- A_Classic_Fairytale:queen +-- ["Other kills don't give you points."] = "", -- Mutant -- ["Ouch!"] = "", -- User_Mission_-_Rope_Knock_Challenge -- ["Our tribe, our beautiful island!"] = "", -- A_Classic_Fairytale:enemy -- ["Parachute"] = "", -- Continental_supplies ["Pathetic Hog #%d"] = "Patetisk kott #%d", -- ["Pathetic Resistance"] = "", -- User_Mission_-_Bamboo_Thicket, User_Mission_-_Newton_and_the_Hammock +-- ["Penguin roar: [Deal 15 damage + 15% of your hogs health to all hogs around you and get 2/3 back]"] = "", -- Continental_supplies -- ["Perfect! Now try to get the next crate without hurting yourself!"] = "", -- A_Classic_Fairytale:first_blood -- ["Per-Hog Ammo"] = "", --- ["- Per team weapons|- 9 weaponschemes|- Unique new weapons| |Select continent first round with the Weapon Menu or by ([switch/tab]=Increase,[precise/left shift]=Decrease) on Skip|Some weapons have a second option. Find them with [switch/tab]"] = "", -- Continental_supplies +-- ["Personal Portal Device"] = "", -- Construction_Mode +-- ["Per team weapons"] = "", -- Continental_supplies -- ["Pfew! That was close!"] = "", -- A_Classic_Fairytale:shadow --- ["Piñata bullet: [Contains some sweet candy!]"] = "", -- Continental_supplies +-- ["Piano Strike"] = "", -- Construction_Mode +-- ["Pickhammer"] = "", -- Construction_Mode + -- ["Pings left:"] = "", -- Space_Invasion - -- ["Place more waypoints using the 'Air Attack' weapon."] = "", -- ["Planes Used:"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Planes Used"] = "", -- User_Mission_-_RCPlane_Challenge @@ -580,14 +682,18 @@ -- ["Please, stop releasing your \"smoke signals\"!"] = "", -- A_Classic_Fairytale:shadow -- ["Point Blank Combo!"] = "", -- Space_Invasion -- ["points"] = "", -- Control, CTF_Blizzard, Basic_Training_-_Bazooka, Basic_Training_-_Shotgun, Basic_Training_-_Sniper_Rifle +-- ["POINTS"] = "", -- Mutant ["Poison"] = "Gift", +-- ["Population"] = "", -- Continental_supplies -- ["Portal hint: one goes to the destination, and one is the entrance.|"] = "", -- A_Classic_Fairytale:dragon -- ["Portal mission"] = "", -- portal -- ["Power Remaining"] = "", -- ["Prepare yourself"] = "", +-- ["presice"] = "", -- Continental_supplies -- ["Press [Enter] to accept this configuration."] = "", -- WxW -- ["Press [Left] or [Right] to move around, [Enter] to jump"] = "", -- A_Classic_Fairytale:first_blood -- ["Press [Precise] to skip intro"] = "", +-- ["Prestigious Pilot"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Private Novak"] = "", -- Basic_Training_-_Cluster_Bomb -- ["Protect yourselves!|Grenade hint: set the timer with [1-5], aim with [Up]/[Down] and hold [Space] to set power"] = "", -- A_Classic_Fairytale:shadow -- ["Race complexity limit reached."] = "", @@ -596,26 +702,40 @@ -- ["Radar Ping"] = "", -- Space_Invasion -- ["Raging Buffalo"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united -- ["Ramon"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow +-- ["random in range from %i%% to %i%% with period of %i msec"] = "", -- Gravity +-- ["RC Plane"] = "", -- Construction_Mode -- ["RC PLANE TRAINING"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Really?! You thought you could harm me with your little toys?"] = "", -- A_Classic_Fairytale:shadow +-- ["Reflector Shield"] = "", -- Construction_Mode +-- ["Reflects enemy projectiles."] = "", -- Construction_Mode -- ["Regurgitator"] = "", -- A_Classic_Fairytale:backstab -- ["Reinforcements"] = "", -- A_Classic_Fairytale:backstab -- ["Remember: The rope only bend around objects, |if it doesn't hit anything it's always stright!"] = "", -- Basic_Training_-_Rope -- ["Remember this, pathetic animal: when the day comes, you will regret your blind loyalty!"] = "", -- A_Classic_Fairytale:shadow +-- ["REMOVED"] = "", -- Continental_supplies +-- ["Respawner"] = "", -- Construction_Mode +-- ["Resurrector"] = "", -- Construction_Mode +-- ["Resurrects dead hedgehogs."] = "", -- Construction_Mode [" - Return the enemy flag to your base to score | - First team to 3 captures wins | - You may only score when your flag is in your base | - Hogs will drop the flag if killed, or drowned | - Dropped flags may be returned or recaptured | - Hogs respawn when killed"] = " - Återvänd med fiendens flagga till din bas för att ta poäng | - Första laget till tre vinner | - Du kan bara ta poäng när din egen flagga är i basen | - Kottar tappar flaggan när de dödas eller drunknar | - Tappade flaggor kan tas tillbaka eller fångas | - Kottar kommer tillbaka när de dör", -- ["Return to Leaks A Lot! If you get stuck, press [Precise] to try again!"] = "", -- A_Classic_Fairytale:shadow -- ["Righteous Beard"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:first_blood, A_Classic_Fairytale:queen, A_Classic_Fairytale:united +-- ["Rope"] = "", -- Construction_Mode -- ["ROPE-KNOCKING"] = "", -- User_Mission_-_Rope_Knock_Challenge +-- ["Rope to safety"] = "", -- ClimbHome -- ["Rope Training"] = "", -- Basic_Training_-_Rope -- ["Rot Molester"] = "", -- A_Classic_Fairytale:shadow -- ["Round Limit:"] = "", -- ["Round Limit"] = "", -- ["Rounds Complete: "] = "", -- ["Rounds Complete"] = "", +-- ["Rubber Band"] = "", -- Construction_Mode +-- ["Rubber Placement Mode"] = "", -- Construction_Mode +-- ["RULES"] = "", -- Frenzy, Mutant ["RULES OF THE GAME [Press ESC to view]"] = "SPELREGLER [Tryck ESC för att se]", -- ["Rusty Joe"] = "", -- A_Classic_Fairytale:queen -- ["s|"] = "", --- ["Sabotage: [Sabotage all hogs in the circle and deal ~10 dmg]"] = "", -- Continental_supplies +-- ["Sabotage/Flare: [Sabotage all hogs in the circle and deal ~1 dmg OR Fire a cluster up into the air]"] = "", -- Continental_supplies + -- ["Salivaslurper"] = "", -- A_Classic_Fairytale:united -- ["Salvation"] = "", -- A_Classic_Fairytale:family -- ["Salvation was one step closer now..."] = "", -- A_Classic_Fairytale:dragon @@ -627,7 +747,7 @@ -- ["Scalp Muncher"] = "", -- A_Classic_Fairytale:backstab -- ["SCORE"] = "", -- ["Score"] = "", -- Mutant --- ["Scream from a Walrus: [Deal 20 damage + 10% of your hogs health to all hogs around you and get half back]"] = "", -- Continental_supplies + ["sec"] = "sec", -- CTF_Blizzard, TrophyRace, Basic_Training_-_Bazooka, Basic_Training_-_Shotgun, Basic_Training_-_Sniper_Rifle, User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork, Capture_the_Flag -- ["Seduction"] = "", -- Continental_supplies -- ["Seems like every time you take a \"walk\", the enemy find us!"] = "", -- A_Classic_Fairytale:backstab @@ -635,8 +755,11 @@ ["See ya!"] = "Ses!", -- ["Segmentation Paul"] = "", -- A_Classic_Fairytale:dragon -- ["Select continent!"] = "", -- Continental_supplies +-- ["Select continent first round with the Weapon Menu or by"] = "", -- Continental_supplies -- ["Select difficulty: [Left] - easier or [Right] - harder"] = "", -- A_Classic_Fairytale:first_blood -- ["selected!"] = "", +-- ["Set period to negative value for random gravity"] = "", -- Gravity +-- ["Setup:|'g=150', where 150 is 150% of normal gravity"] = "", -- Gravity -- ["s"] = "", -- GaudyRacer, Space_Invasion -- ["... share your beauty with the world every morning, my princess!"] = "", -- A_Classic_Fairytale:journey -- ["She's behind that tall thingy."] = "", -- A_Classic_Fairytale:family @@ -648,16 +771,21 @@ -- ["Shield OFF:"] = "", -- ["Shield ON:"] = "", -- ["Shield Seeker!"] = "", +-- ["Shoryuken"] = "", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 -- ["Shotgun"] = "", -- Continental_supplies ["Shotgun Team"] = "Hagelgevärslaget", ["Shotgun Training"] = "Hagelgevärsträning", -- ["shots remaining."] = "", -- ["Silly"] = "", +-- ["SineGun"] = "", -- Construction_Mode -- ["Sinky"] = "", -- ["Sirius Lee"] = "", -- A_Classic_Fairytale:enemy ["%s is out and Team %d|scored a penalty!| |Score:"] = "%s är ute och lag %d|fick ett straff!| |Poängställning:", -- Basketball, Knockball ["%s is out and Team %d|scored a point!| |Score:"] = "%s är ute och lag %d|fick ett poäng!| |Poängställning:", -- Basketball, Knockball -- ["Slippery"] = "", -- A_Classic_Fairytale:journey +-- ["Slot"] = "", -- Frenzy +-- ["Slot keys save time! (F1-F10 by default)"] = "", -- Frenzy +-- ["SLOTS"] = "", -- Frenzy -- ["Smith 0.97"] = "", -- A_Classic_Fairytale:enemy -- ["Smith 0.98"] = "", -- A_Classic_Fairytale:enemy -- ["Smith 0.99a"] = "", -- A_Classic_Fairytale:enemy @@ -669,6 +797,7 @@ ["Sniper Training"] = "Prickskyttesträning", ["Sniperz"] = "Prickskyttarna", -- ["So humiliating..."] = "", -- A_Classic_Fairytale:first_blood +-- ["Some weapons have a second option. Find them with"] = "", -- Continental_supplies -- ["South America"] = "", -- Continental_supplies -- ["So? What will it be?"] = "", -- A_Classic_Fairytale:shadow -- ["Spawn the crate, and attack!"] = "", -- WxW @@ -677,25 +806,43 @@ -- ["Spleenlover"] = "", -- A_Classic_Fairytale:united -- ["Sponge"] = "", ["Spooky Tree"] = "Kusligt träd", +-- ["Sprite Placement Mode"] = "", -- Construction_Mode +-- ["Sprite Testing Mode"] = "", -- Construction_Mode -- ["STATUS UPDATE"] = "", -- GaudyRacer, Space_Invasion -- ["Steel Eye"] = "", -- A_Classic_Fairytale:queen -- ["Step By Step"] = "", -- A_Classic_Fairytale:first_blood -- ["Steve"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen -- ["Sticky Mine"] = "", -- Continental_supplies +-- ["Sticky Mine Placement Mode"] = "", -- Construction_Mode -- ["Stronglings"] = "", -- A_Classic_Fairytale:shadow --- ["Structure"] = "", -- Continental_supplies + +-- ["Structure Placement Mode"] = "", -- Construction_Mode +-- ["Structure Placement Tool"] = "", -- Construction_Mode +-- ["Sundaland"] = "", -- Continental_supplies -- ["Super Weapons"] = "", -- WxW +-- ["Support Station"] = "", -- Construction_Mode -- ["Surf Before Crate"] = "", -- WxW -- ["Surfer! +15 points!"] = "", -- Space_Invasion -- ["Surfer!"] = "", -- WxW -- ["Survive!|Hint: Cinematics can be skipped with the [Precise] key."] = "", -- A_Classic_Fairytale:shadow -- ["Swing, Leaks A Lot, on the wings of the wind!"] = "", -- A_Classic_Fairytale:first_blood +-- ["switch"] = "", -- Continental_supplies -- ["Switched to "] = "", +-- ["Switch Hog"] = "", -- Construction_Mode -- ["Syntax Errol"] = "", -- A_Classic_Fairytale:dragon +-- ["tab"] = "", -- Continental_supplies +-- ["Tagging Mode"] = "", -- Construction_Mode -- ["Talk about mixed signals..."] = "", -- A_Classic_Fairytale:dragon +-- ["Tardis"] = "", -- Construction_Mode +-- ["Target Placement Mode"] = "", -- Construction_Mode ["Team %d: "] = "Lag %d: ", -- ["Team Scores"] = "", -- Control, Space_Invasion +-- ["Teleporation Node"] = "", -- Construction_Mode +-- ["Teleportation Mode"] = "", -- Construction_Mode +-- ["Teleportation Node"] = "", -- Construction_Mode +-- ["Teleport"] = "", -- Construction_Mode, Frenzy -- ["Teleport hint: just use the mouse to select the destination!"] = "", -- A_Classic_Fairytale:dragon +-- ["Teleport Unsuccessful. Please teleport within a clan teleporter's sphere of influence."] = "", -- Construction_Mode -- ["Thanks!"] = "", -- A_Classic_Fairytale:family -- ["Thank you, my hero!"] = "", -- A_Classic_Fairytale:family -- ["Thank you, oh, thank you, Leaks A Lot!"] = "", -- A_Classic_Fairytale:journey @@ -712,6 +859,7 @@ ["That was pointless."] = "Det där var meningslöst.", -- ["The answer is...entertaintment. You'll see what I mean."] = "", -- A_Classic_Fairytale:backstab -- ["The anti-portal zone is all over the floor, and I have nothing to kill him...Droping something could hurt him enough to kill him..."] = "", -- portal +-- ["The Bottom Feeder can score points by killing anyone."] = "", -- Mutant -- ["The Bull's Eye"] = "", -- A_Classic_Fairytale:first_blood -- ["The caves are well hidden, they won't find us there!"] = "", -- A_Classic_Fairytale:united -- ["The Crate Frenzy"] = "", -- A_Classic_Fairytale:first_blood @@ -721,20 +869,26 @@ -- ["The Enemy Of My Enemy"] = "", -- A_Classic_Fairytale:enemy -- ["The First Blood"] = "", -- A_Classic_Fairytale:first_blood -- ["The First Encounter"] = "", -- A_Classic_Fairytale:shadow +-- ["The first player to kill someone becomes the Mutant."] = "", -- Mutant ["The flag will respawn next round."] = "Flaggan kommer tillbaka nästa runda.", -- ["The food bites back"] = "", -- A_Classic_Fairytale:backstab -- ["The giant umbrella from the last crate should help break the fall."] = "", -- A_Classic_Fairytale:first_blood -- ["The Great Escape"] = "", -- User_Mission_-_The_Great_Escape +-- ["The Great Hog in the sky sees your sadness and grants you a boon."] = "", -- Construction_Mode -- ["The guardian"] = "", -- A_Classic_Fairytale:shadow -- ["The Individualist"] = "", -- A_Classic_Fairytale:shadow -- ["Their buildings were very primitive back then, even for an uncivilised island."] = "", -- A_Classic_Fairytale:united -- ["The Journey Back"] = "", -- A_Classic_Fairytale:journey -- ["The Leap of Faith"] = "", -- A_Classic_Fairytale:first_blood -- ["The Moonwalk"] = "", -- A_Classic_Fairytale:journey +-- ["The Mutant has super-weapons and a lot of health."] = "", -- Mutant +-- ["The Mutant loses health quickly if he doesn't keep scoring kills."] = "", -- Mutant -- ["The Nameless One"] = "", -- ["The next one is pretty hard! |Tip: You have to do multiple swings!"] = "", -- Basic_Training_-_Rope -- ["Then how do they keep appearing?"] = "", -- A_Classic_Fairytale:shadow -- ["The other one were all cannibals, spending their time eating the organs of fellow hedgehogs..."] = "", -- A_Classic_Fairytale:first_blood +-- ["The player with least points (or most deaths) becomes the Bottom Feeder."] = "", -- Mutant +-- ["There are a variety of structures available to aid you."] = "", -- Construction_Mode -- ["There must be a spy among us!"] = "", -- A_Classic_Fairytale:backstab -- ["There's more of them? When did they become so hungry?"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united -- ["There's nothing more satisfying for me than seeing you share your beauty with the world every morning, my princess!"] = "", -- A_Classic_Fairytale:journey @@ -790,7 +944,7 @@ -- ["To the caves..."] = "", -- A_Classic_Fairytale:united ["Toxic Team"] = "Förgiftade laget", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork -- ["TRACK COMPLETED"] = "", --- ["TRACK FAILED!"] = "", + -- ["training"] = "", -- portal -- ["Traitors"] = "", -- A_Classic_Fairytale:epil -- ["Tribe"] = "", -- A_Classic_Fairytale:backstab @@ -807,6 +961,7 @@ -- ["ULTRA KILL"] = "", -- Mutant -- ["Under Construction"] = "", -- A_Classic_Fairytale:shadow -- ["Unexpected Igor"] = "", -- A_Classic_Fairytale:dragon +-- ["Unique new weapons"] = "", -- Continental_supplies -- ["Unit"] = "", -- ["Unit 0x0007"] = "", -- A_Classic_Fairytale:family -- ["Unit 334a$7%;.*"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united @@ -821,11 +976,14 @@ -- ["Use it wisely!"] = "", -- A_Classic_Fairytale:dragon -- ["Use it with precaution!"] = "", -- A_Classic_Fairytale:first_blood -- ["User Challenge"] = "", - +-- ["Use the air-attack weapons and the arrow keys to select structures."] = "", -- Construction_Mode -- ["Use the portal gun to get to the next crate, then use the new gun to get to the final destination!|"] = "", -- A_Classic_Fairytale:dragon -- ["Use the rope to get on the head of the mole, young one!"] = "", -- A_Classic_Fairytale:first_blood -- ["Use the rope to knock your enemies to their doom."] = "", -- User_Mission_-_Rope_Knock_Challenge +-- ["Use your ready time to think."] = "", -- Frenzy ["Use your rope to get from start to finish as fast as you can!"] = "Använd ditt rep för att ta dig från start till mål så fort som möjligt!", +-- ["Utility Crate Placement Mode"] = "", -- Construction_Mode +-- ["Vampirism"] = "", -- Construction_Mode -- ["Vedgies"] = "", -- A_Classic_Fairytale:journey -- ["Vegan Jack"] = "", -- A_Classic_Fairytale:enemy -- ["Victory!"] = "", -- Basic_Training_-_Rope @@ -837,10 +995,14 @@ -- ["Wannabe Flyboys"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Wannabe Shoppsta"] = "", -- User_Mission_-_Rope_Knock_Challenge -- ["Watch your steps, young one!"] = "", -- A_Classic_Fairytale:first_blood +-- ["Watermelon Bomb"] = "", -- Construction_Mode -- ["Waypoint placed."] = "", -- ["Way-Points Remaining"] = "", -- ["Weaklings"] = "", -- A_Classic_Fairytale:shadow -- ["We all know what happens when you get frightened..."] = "", -- A_Classic_Fairytale:first_blood +-- ["Weapon Crate Placement Mode"] = "", -- Construction_Mode +-- ["Weapon Filter"] = "", -- Construction_Mode +-- ["weaponschemes"] = "", -- Continental_supplies -- ["Weapons Reset"] = "", -- ["Weapons reset."] = "", -- Highlander -- ["We are indeed."] = "", -- A_Classic_Fairytale:backstab @@ -893,6 +1055,7 @@ -- ["Where do you get that?!"] = "", -- A_Classic_Fairytale:enemy -- ["Where have you been?!"] = "", -- A_Classic_Fairytale:backstab -- ["Where have you been?"] = "", -- A_Classic_Fairytale:united +-- ["Whip"] = "", -- Construction_Mode -- ["? Why?"] = "", -- A_Classic_Fairytale:backstab -- ["Why "] = "", -- A_Classic_Fairytale:backstab -- ["! Why?!"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united @@ -905,8 +1068,10 @@ -- ["Why me?!"] = "", -- A_Classic_Fairytale:backstab -- ["Why would they do this?"] = "", -- A_Classic_Fairytale:backstab -- ["- Will Get 1-3 random weapons"] = "", -- Continental_supplies --- ["- Will refresh Parachute each turn."] = "", -- Continental_supplies --- ["- Will refresh portalgun each turn."] = "", -- Continental_supplies +-- ["- Will give you an airstrike every fifth turn."] = "", -- Continental_supplies +-- ["- Will give you a parachute every second turn."] = "", -- Continental_supplies + + -- ["Will this ever end?"] = "", -- ["WINNER IS "] = "", -- Mutant -- ["WINNING TIME: "] = "", @@ -925,6 +1090,7 @@ -- ["Yes!"] = "", -- A_Classic_Fairytale:enemy -- ["Yes, yeees! You are now ready to enter the real world!"] = "", -- A_Classic_Fairytale:first_blood -- ["Yo, dude, we're here, too!"] = "", -- A_Classic_Fairytale:family +-- ["You are far from home, and the water is rising, climb up as high as you can!"] = "", -- ClimbHome -- ["You are given the chance to turn your life around..."] = "", -- A_Classic_Fairytale:shadow -- ["You are playing with our lives here!"] = "", -- A_Classic_Fairytale:enemy -- ["! You bastards!"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united @@ -957,6 +1123,8 @@ -- ["You know what? I don't even regret anything!"] = "", -- A_Classic_Fairytale:backstab -- ["You'll see what I mean!"] = "", -- A_Classic_Fairytale:enemy -- ["You may only attack from a rope!"] = "", -- WxW +-- ["You may only spawn 5 crates per turn."] = "", -- Construction_Mode +-- ["You may only use 1 Extra Time per turn."] = "", -- Construction_Mode -- ["You meatbags are pretty slow, you know!"] = "", -- A_Classic_Fairytale:enemy -- ["You might want to find a way to instantly kill arriving cannibals!"] = "", -- A_Classic_Fairytale:backstab -- ["Young one, you are telling us that they can instantly change location without a shaman?"] = "", -- A_Classic_Fairytale:united @@ -977,6 +1145,7 @@ ["You've failed. Try again."] = "Du har misslyckats. Försök igen.", ["You've reached the goal!| |Time: "] = "Du har nått målet!| |Tid: ", -- ["You will be avenged!"] = "", -- A_Classic_Fairytale:shadow +-- ["- You will recieve 2-4 weapons on each kill! (Even on own hogs)"] = "", -- Continental_supplies -- ["You won't believe what happened to me!"] = "", -- A_Classic_Fairytale:backstab -- ["Yuck! I bet they'll keep worshipping her even after I save the village!"] = "", -- A_Classic_Fairytale:family -- ["Zealandia"] = "", -- Continental_supplies diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/tips_cs.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Locale/tips_cs.xml Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,51 @@ + + + Jednoduše zvol stejnou barvu jako spoluhráč, abys hrál ve stejném týmu. Každý z vás bude mít kontrolu nad svými vlastními ježky, ale vyhraje nebo prohraje společně. + Některé zbraně mohou způsobovat jen malé poškození, ale mohou být devastující v pravé chvíli. Zkus použít pistoli Desert Eagle ke sražení několika nepřátelských ježků do vody. + Pokud si nejsi jistý, co dělat a nechceš plýtvat municí, přeskoč tah. Ale nenech uběhnout moc času, protože pak přijde Náhlá smrt! + Pokud chceš zabránit ostatním, aby používali tvoji oblíbenou přezdívku na oficiálním serveru, zaregistruj se na http://www.hedgewars.org/. + Jsi znuděn standardní hrou? Vyzkoušej některou misi - nabídnou jiný herní zážitek v závislosti na tom, kterou si vybereš. + Standardně hra vždycky nahrává poslední odehraný zápas jako ukázku. Vyber si 'Místní hru' a zvol tlačítko 'Ukázky' v pravém spodním rohu k jejich přehrávání a správě. + Hedgewars je Open Source a Freeware, který jsme vytvořili v našem volném čase. Pokud máš problémy, zeptej se na našem fóru, ale neočekávej prosím nonstop podporu! + Hedgewars je Open Source a Freeware, který jsme vytvořili v našem volném čase. Pokud se ti líbí, pomož nám malým příspěvkem, nebo se podílej na práci! + Hedgewars je Open Source a Freeware, který jsme vytvořili v našem volném čase. Sdílej ho se svoji rodinou a přáteli dle libosti! + Čas od času se konají oficiální turnaje. Nadcházející události budou publikovány na http://www.hedgewars.org/ s několika denním předstihem. + Hedgewars je k dispozici v mnoha jazycích. Pokud překlad do tvého jazyka vypadá zastaralý nebo chybí, neváhej nás kontaktovat! + Hedgewars může být spuštěno na mnoha různých operačních systémech včetně Microsoft Windows, Mac OS X a Linuxu. + Vždycky si pamatuj, že můžeš vytvořit vlastní hru na místní síti i internetu. Nejsi odkázán jen na možnost 'Prostá hra'. + Během hraní bys měl dělat krátké přestávky alespoň jednou za hodinu. + Pokud tvoje grafická karta nepodporuje hardwarovou akceleraci OpenGL, zkus zapnout nízkou kvalitu pro zlepšení výkonu. + Jsme otevřeni návrhům a konstruktivní kritice. Pokud se ti něco nelíbí, nebo máš skvělý nápad, dej nám vědět! + Obzvláště při hře online buď slušný a vždy pamatuj na to, že s tebou nebo proti tobě může hrát někdo z nějaké menšiny! + Speciální herní módy jako třeba 'Vampyrismus' nebo 'Karma' ti dovolují vymýšlet úplně jiné herní taktiky. Vyzkoušej je v nějaké hře! + Nikdy bys neměl instalovat Hedgewars na počítači, který ti nepatří (škola, univerzita, práce a jiné). Prosím, zeptej se nejprve zodpovědné osoby! + Hedgewars mohou být perfektní pro krátkou hru během pauzy. Jen se ujisti, že jsi nepřidal příliš mnoho ježků nebo nezvolil velkou mapu. Zmenšit čas nebo zdraví také urychlí hru. + Žádný ježek nebyl zraněn během vytváření této hry. + Hedgewars je Open Source a Freeware, který jsme vytvořili v našem volném čase. Pokud ti tuto hru někdo prodal, měl bys chtít vrátit peníze! + Připojenim jednoho nebo více gamepadů před začátkem hry ti umožní nastavit je jako ovladač pro tvé týmy. + Vytvoř si účet na %1, abys zabránil ostatním používat tvoji oblíbenou přezdívku na oficiálním serveru. + Pokud tvoje grafická karta nepodporuje hardwarovou akceleraci OpenGL, zkus aktualizovat ovladače. + Některé zbraně vyžadují speciální strategii, nebo jen spoustu cvičení. Nezavrhuj hned některou zbraň, pokud jednou mineš cíl. + Většina zbraní nefunguje, jakmile se ponoří do vody. Naváděná včela nebo dort jsou vyjímka z tohoto pravidla. + Olomoucké tvarůžky vybuchují jen málo, ale vítr ovlivňuje oblak smradu, který může nakazit mnoho ježků najednou. + Útok pianem je nejničivější letecký útok. Na druhé straně ale ztratíš ježka, který tento útok vykoná. + Přisavné miny jsou perfektní nástroj na vytváření malých řetězových reakcí, které mohou nepřátelské ježky dostat do divokých situací ... nebo vody. + Kladivo je nejefektivnější při použitǐ na mostech a traverzách. Zasažený ježek prostě prorazí skrz zem. + Pokud jsi zaseklý za nepřátelským ježkem, použij kladivo, aby ses osvobodil a nemusel riskovat zranění z exploze. + Maximální vzdálenost, do které dort dojde, je ovlivněna terénem, kterým musí jít. Použij [útok] k dřívější explozi. + Plamenomet je zbraň, ale dá se použít i pro kopání tunelů. + Chceš vědět, kdo stojí za touto hrou? Klikni na logo Hedgewars v hlavním menu a podívej se. + Líbí se ti Hedgewars? Staň se fanouškem na %1 nebo nás sleduj na %2! + Neboj se kreslit vlastní hroby, čepice, vlajky nebo mapy a témata! Ale pamatuj, že je musíš někde sdílet, abys je mohl používat online. + Opravdu chceš nosit specifickou čepici? Daruj nám něco a dostaneš exklusivní čepici dle svého výběru! + Udržuj ovladače grafické karty aktuální, aby ses vyhnul problémům při hře. + Můžeš si asociovat Hedgewars soubory (uložené hry a nahrávky) tak, abys je mohl ihned spouštět z internetového prohlížeče nebo prúzkumníka souborů. + Chceš ušetřit lana? Uvolni ho ve vzduchu a vystřel znovu. Dokud se nedotkneš země, využíváš ho bez plýtvání munice! + Použij Molotov nebo plamenomet, abys dočasně zamezil ježkům v přechodu terénu jako jsou tunely nebo plošiny. + + Windows verze Hedgewars podporuje Xfire. Přidej si Hedgewars do jeho seznamu her, abys viděl přátele, kteří ho hrají. + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/tips_da.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Locale/tips_da.xml Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,57 @@ + + + Bare vælg samme farve som en ven for at spille sammen som et hold. Hver af jer vil stadig kontrollere sine egne pindsvin, men vil vinde eller tabe sammen. + Nogle våben giver måske ikke særlig meget skade, men de kan være meget mere farlige i de rigtige situationer. Prøv at bruge Desert Eagle-pistolen til at skubbe flere pindsvin i vandet. + Hvis du er usikker på hvad du skal gøre og ikke vil spilde ammunition, kan du springe en runde over. Men lad der ikke gå alt for meget tid, for ellers indtræffer Pludselig Død! + Hvis du ikke vil have at andre anvender dit foretrukne brugernavn på den officielle server, kan du registrere en bruger på http://www.hedgewars.org/. + Er du træt af den almindelige måde at spille på? Prøv en af missionerne - de tilbyder forskellige måder at spille på afhængigt af hvilken en du vælger. + Som standard optager spillet altid det sidste spil du har spillet som en demo. Tryk på 'Lokalt spil' og vælg 'Demoer'-knappen i nederste højre hjørne for at afspille eller administrere dem. + Hedgewars er Open Source og et gratis spil vi laver i vores fritid. Hvis du har problemer er du velkommen til at spørge på forummet, men forvent ikke at få hjælp 24 timer i døgnet! + Hedgewars er Open Source og et gratis spil vi laver i vores fritid. Hvis du holder af det, kan du hjælpe os med en lille donation eller ved at indsende dine egne modifikationer! + Hedgewars er Open Source og et gratis spil vi laver i vores fritid. Del det med dine venner og din familie som du ønsker! + Fra tid til anden er der officielle turneringer. Kommende begivenheder vil blive annonceret på http://www.hedgewars.org/ et par dage i forvejen. + Hedgewars er tilgængeligt på mange sprog. Hvis oversættelsen på dit sprog mangler noget eller er uddateret, skal du være velkommen til at kontakte os! + Hedgewars kan køre på mange forskellige operativsystemer, herunder Microsoft Windows, Mac OS X og Linux. + Husk altid at du kan sætte dine egne spil op under lokale-, netværks- og online-spil. Du er ikke begrænset til kun at bruge 'Simpelt spil'-muligheden. + Mens du spiller bør du tage en kort pause mindst en gang i timen. + Hvis dit grafikkort ikke understøtter hardware-accelereret OpenGL, kan du prøve at slå indstillingen 'Reduceret kvalitet' til for at forbedre ydelsen. + Vi er åbne over for foreslag og konstruktive tilbagemeldinger. Fortæl os det hvis der er noget du ikke kan lide eller hvis du har en god idé! + Specielt når du spiller online bør du være venlig og altid huske at du måske også spiller med eller mod børn! + Specielle måder at spille på som f.eks. 'Varmpyr' eller 'Karma' tillader dig at udvikle helt nye taktikker. Prøv dem i et brugerdefineret spil! + Du bør aldrig installere Hedgewars på computere du ikke ejer (skole, universitet, arbejde,e.l.). Spørg venligst den ansvarlige person i stedet! + Hedgewars er perfekt til korte spil under pauser. Bare par på du ikke tilføjer for mange pindsvin eller bruger en kæmpe bane. Det kan også hjælpe at reducere tid og liv. + Ingen pindsvin kom til skade under produktionen af dette spil. + Hedgewars er Open Source og et gratis spil vi laver i vores fritid. Hvis nogen solgte dig spiller skal du bede om at få pengene tilbage! + Tilslut en eller flere gamepads før du starter spiller for at kunne tildele dem til dit hold. + Opret en bruger på %1 hvis du ikke vil have at andre anvender dit foretrukne brugernavn på den officielle server. + Hvis du ikke er i stand til at slå hardware-accelereret OpenGL til, bør du prøve at opdatere dine grafikkort-drivere. + Der er tre forskellige typer hop tilgængelige. Tryk hurtigt på [hight jump] to gange i træk for at lave et højt, baglæns hop. + Er du bange for at falde ned fra en skrænt? Hold [precise] nede for at vende dig mod [left] eller [right] uden at bevæge dig. + Nogle våben kræver specielle strategier eller bare masser af træning, så undlad ikke at bruge et bestemt våben bare fordi du rammer ved siden af én gang. + De fleste våben virker ikke så snart de har rørt vandet. Den Målsøgende Bi og Kagen er de eneste undtagelser. + Gamle Ole laver kun en lille eksplosion. Til gengæld kan den stænkende sky den udsender føres rundt af vinden og ramme mange pindsvin på én gang. + Klaveranslaget er det luftvåben der giver allermest skade. Til gengæld mister du det pindsvin som bruger angrebet, så der er også en bagside af medaljen. + Klæbrige Miner er det perfekte værktøj til at lave små kædereaktioner og smide pindsvin ud i faretruende situationer... eller bare direkte i vandet. + Hammeren er mest effektiv når den bruges enten på broer eller bærebjælker. Sigter du mod pindsvin med den, laver du bare huller i jorden. + Hvis du sidder fast bag en af modstanderens pindsvin, kan du bruge Hammeren til at slå dig fri uden at tage skade under en eksplosion. + Kagen kan gå kortere eller længere, afhængig af hvad den skal over på vejen. Du kan brrug [attack] til at detonere den før den når sin destination. + Flammekasteren er et våben, men den kan også bruges til hurtigt at grave tunneler. + Vil du vide hvem der står bag spillet? Klik på Hedgewars-logoet i hovedmenuen for at se rulleteksterne. + Er du glad for Hedgewars? Bliv fan på %1 eller følge vores opdateringer på %2! + Du skal være velkommen til at tegne dine egne gravsten, hatte, flag eller endda baner og temaer! Men læg mærke til at du bliver nød til at dele dem med andre hvis du vil spille med dem online. + Vil du virkelig gerne have en specifik hat? Send os en donation, så kvitterer vi med en eksklusiv hat efter eget valg! + Hold dine grafikkortdrivere opdaterede for at undgå problemmer i spillet. + Du kan finde konfigurationsfilerne til Hedgewars under mappen "(Mine) Dokumenter\Hedgewars". Opret gerne en back-up eller tag filerne med dig, men lad være med selv at ændre i dem. + Du kan indstille Hedgewars-filer (gemte spil og demooptagelser) til automatisk at åbne når du trykker på dem eller åbner dem i din internet-browser. + Vil du gerne spare på dine reb? Slip rebet midt i luften og skyd straks igen. Så længe du ikke rører jorden bruger du ikke noget ammunition! + Du kan finde konfigurationsfilerne til Hedgewars under mappen "Bibliotek/Application Support/Hedgewars" i din hjemmemappe. Opret gerne en back-up eller tag filerne med dig, men lad være med selv at ændre i dem. + Du kan finde konfigurationsfilerne til Hedgewars under mappen ".hedgewars" i din hjemmemappe. Opret gerne en back-up eller tag filerne med dig, men lad være med selv at ændre i dem. + Brug en Molotovcocktail eller Flammekasteren til midlertidigt at forhindre pindsvin i at passere et område, f.eks. en tunnel eller platform. + Den Målsøgende Bi kan være svær at bruge. Den vender lettere hvis den ikke flyver alt for hurtigt, så prøv at spare på kraften når du affyrer den. + + Windows-versionen af Hedgewars understøtter integrering med Xfire. Husk at tilføje Hedgewars til din liste med spil så dine venner kan se hvornår du spiller. + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/tips_de.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Locale/tips_de.xml Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,79 @@ +# This is not xml actually, but it looks and behaves like it. +# Including an xml library would need too much resources. +# Tips between the platform specific tags are shown only on those platforms. +# Do not escape characters or use the CDATA tag. + + Wähl einfach die selbe Farbe wie die eines Freundes aus, um gemeinsam als ein Klan zu spielen. Jeder von euch wird immer noch Kontrolle über seine eigenen Igel haben, aber sie werden gemeinsam siegen oder verlieren. + Einige Waffen mögen zwar nur geringfügigen Schaden anrichten, aber sie können in der passenden Sitation verheerend sein. Versuche, die Desert Eagle zu benutzen, um mehrere Igel ins Wasser zu schubsen. + Falls du dir unsicher darüber bist, was du tun sollst und du keine Munition verschwenden willst, überspring die Runde. Aber lass nicht zu viel Zeit verstreichen, weil irgendwann der Sudden Death kommt. + Willst du Seile sparen? Lass das Seil im Flug los und schieß erneut. Solange du den Boden nicht berührst und kein Schuss daneben geht, wirst du dein Seil wiederverwenden, ohne Vorräte zu vergeuden. + Wenn du Andere davon abhalten willst, deinen Lieblingsspitznamen auf dem offiziellen Server zu benutzen, registiere ein Benutzerkonto auf http://www.hedgewars.org/. + Bist du vom Standardspiel gelangweilt? Dann probier eine der Missionen aus – sie spielen sich anders, je nach dem, welche Mission du ausgewählt hast. + Standardmäßig wird das Programm immer vom letzten Spiel eine Wiederholung abspeichern. Wähle »Auf einen einzelnen Computer spielen« und dann den »Aufgezeichnete Wiederholungen ansehen«-Knopf auf der rechten unteren Ecke, um sie abzuspielen oder zu verwalten. + Hedgewars ist freie Open-Source-Software, die wir in unserer Freizeit erstellen. Falls du Probleme hast, frag uns in unseren Foren oder besuch unseren IRC-Channel! + Hedgewars ist freie Open-Source-Software, die wir in unserer Freizeit erstellen. Wenn es dir gefällt, hilf uns mit einer kleinen Spende oder steuere deine eigenen Werke bei! + Hedgewars ist freie Open-Source-Software, die wir in unserer Freizeit erstellen. Teile es mit deiner Famlie und deinen Freunden, wie es dir gefällt! + Hedgewars ist freie Open-Source-Software, die wir in unserer Freizeit nur so zum Spaß erstellen. Triff die Entwickler auf #hedgewars! + Von Zeit zu Zeit wird es offizielle Turniere geben. Bevorstehende Ereignisse werden auf http://www.hedgewars.org/ ein paar Tage im Voraus angekündigt. + Hedgewars ist in vielen Sprachen verfügbar. Wenn die Übersetzung deiner Sprache zu fehlen oder veraltet zu sein scheint, nimm ruhig mit uns Kontakt auf! + Hedgewars läuft auf vielen verschiedenen Betriebssystemem, unter anderen Microsoft Windows, Mac OS X und GNU/Linux. + Denk immer daran, dass du in der Lage bist, deine eigenen Spiele in lokalen Spielen und Netzwerkspielen aufzusetzen. Du musst nicht zwangsläufig nur einfache Spiele spielen. + Verbinde einen oder mehr Gamepads, bevor du das Spiel startest, damit du ihre Belegung deinen Teams zuweisen kannst. + Erstelle ein Benutzerkonto auf http://www.hedgewars.org/, um andere davon abzuhalten, deinen Lieblingsspitznamen beim Spielen auf dem offiziellen Server zu benutzen. + Wenn du spielst, solltest du dir wenigstens ein mal pro Stunde eine kurze Pause gönnen. + Wenn deine Grafikkarte nicht in der Lage ist, hardwarebeschleunigtes OpenGL zur Verfügung zu stellen, versuche es mit einer niedrigen Qualitätsstufe (in den Grafikeinstellungen), um die Geschwindigkeit zu erhöhen. + Wenn deine Grafikkarte nicht in der Lage ist, hardwarebeschleunigtes OpenGL zur Verfügung zu stellen, versuche, die benötigten Treiber zu updaten. + Wir sind offen gegenüber Vorschlägen und konstruktiver Kritik. Wenn du etwas nicht magst oder du eine großartige Idee hast, lass es uns wissen! + Inbesondere, wenn du online spielst, sei höflich und denk immer daran, dass ein paar Minderjährige mit bzw. gegen dich spielen könnten. + Mit besonderen Spielmodi wie »Vampirismus« oder »Karma« kannst du völlig andere Strategien entwickeln. Probier sie in einem benutzerdefinierten Spiel aus! + Du solltest Hedgewars niemals auf Computern, die dir nicht gehören (Schule, Universität, Arbeit, usw.), installieren. Bitte frag die verantwortliche Person stattdessen! + Hedgewars kann perfekt für kurze Spiele in Pausen sein. Stell nur sicher, dass du nicht zu viele Igel hinzufügst oder eine gigantische Karte benutzt. Das Verringern der Zeit und Anfangsgesundheit kann ebenfalls helfen. + Bei der Erstellung dieses Spiels wurden keine Igel verletzt. + Drei verschiedene Sprünge sind verfügbar. Drücke [Hochsprung] doppelt, um einen sehr hohen Rückwärtssprung zu machen. + Hast du Angst, von einer Klippe zu stürzen? Halte [Genaues Zielen], um dich nach [Links] oder [Rechts], ohne dich tatsächlich zu bewegen, umzudrehen. + Ein paar Waffen erfordern besondere Strategien oder einfach nur sehr viel Training, also gib ein bestimmtes Werkzeug nicht auf, wenn du einen Gegner mal verfehlt haben solltest. + Die meisten Waffen würden nicht funktionieren, sobald sie das Wasser berührt haben. Die zielsuchende Biene sowie der Kuchen sind Ausnahmen davon. + Der alte Limburger verursacht nur eine kleine Explosion. Allerdings kann die vom Wind beeinflusste Stinkewolke viele Igel auf einmal vergiften. + Der Pianoangriff ist der zerstörerischste Luftangriff. Du verlierst den Igel, der ihn vornimmt, also gibt es hier eben auch einen riesigen Nachteil. + Die zielsuchende Biene kann knifflig zu verwenden sein. Ihr Drehradius hängt von ihrer Geschwindigkeit hab, also versuche, nicht mit voller Kraft zu schießen. + Haftminen sind ein perfektes Werkzeug, um kleine Kettenreaktionen, die feindliche Igel in fatale Situationen – oder Wasser - befördern. + Der Hammer ist am effektivsten, wenn er auf Brücken oder Bauträgern verwendet wird. Getroffene Igel werden einfach durch den Boden fallen. + Wenn du hinter einem feindlichen Igel feststeckst, benutze den Hammer, um dich selbst, ohne selbst durch eine Explosion verletzt zu werden, zu befreien. + Des Kuchens maximale Laufentfernung hängt von dem Boden, den er überqueren muss, ab. Benutze [Angriff], um ihn vorzeitig zu detonieren. + Der Flammenwerfer ist eine Waffe, aber sie kann auch zum Tunnelgraben verwendet werden. + Benutze den Molotowcocktail oder Flammenwerfer, um kurzzeitig Igel daran zu hindern, Gelände wie Tunnel oder Bauträger zu überqueren. + Willst du wissen, wer hinter dem Spiel steckt? Klick auf das Hedgewars-Logo im Hauptmenü, um die Liste der Mitwirkenden (derzeit nur auf Englisch, Anm. eines Übersetzers) zu sehen. + Magst du Hedgewars? Werd zum Fan auf Facebook oder folg uns auf Twitter! + Tu dir keinen Zwang an, dir deine eigenen Grabsteine, Hüte, Flaggen oder sogar Karten und Szenerien zu malen! Aber beachte, dass du sie irgendwo online teilen musst, um sie online benutzen zu können. + Halte deine Grafikkartentreiber auf dem neuesten Stand, um Probleme beim Spielen des Spiels zu vermeiden. + Kopf oder Zahl? Gib »/rnd« in der Lobby ein und finde es heraus. »/rnd Schere Stein Papier« funktioniert auch! + Du kannst Hedgewars-bezogene Dateien (Spielstände und Wiederholungen) mit dem Spiel assoziieren, um sie direkt von deinem Lieblingsdateiverwaltungsprogramm oder Webbrowser starten zu können. + Blindgängerminen sind nicht harmlos: Obwohl ihr Zeitzünder defekt ist, können sie immer noch explodieren, wenn ihnen zu stark zugerichtet wurde. + Liebe ist heiß! Benutze die Verführung, um eingefrorene Igel sofort aufzutauen. + Rauch, der aus einem Pulverfass aufsteigt, ist ein Hinweis darauf, dass es beschädigt wurde. In diesem Zustand kann auch geringfügiger Schaden das Fass sprengen. + Pulverfässer starten mit 60 Gesundheitspunkten und nehmen Schaden wie Igel, also muss ihnen schon etwas zugerichtet werden, um sie zu zerstören + Mehr Sprungkraft gefällig? Ändere die Sprungstärke von Granaten, Splittergranaten, alten Limburgern und Minen, während du [Genaues Zielen] gedrückt hälst und gleichzeitig eine der Zeitzündertasten drückst. + Hast du die Spielziele oder -regeln im Spiel vergessen? Drück die Pause- oder Verlassentaste, um sie wieder sichtbar zu machen! + Du kannst nicht nur Igel, sondern auch einige Gegenstände verprügeln, auspeitschen oder mit dem Hammer in den Boden stampfen. Hau alles zu Klump! + Wenn es nicht anders geschrieben steht, werden Minen normalerweise nach 3 Sekunden explodieren. + Im Königsmodus wird dein König gesünder, stärker und widerstandsfähiger gegenüber Schaden und Schubser sein als seine Untertanen. + Im Königsmodus wird der König nach jedem Zug Schaden nehmen, wenn er alleine im Team ist. + Die Peitsche kann auch Igel und Gegenstände hinter einer dünnen Wand treffen. + Der Schaden eines Hackebeils vergrößert sich mit der Fluggeschwindigkeit. + Du kannst Torten von Klippen fallen lassen, aber du musst schon sehr nahe am Rand stehen, also sei vorsichtig. + Benutze dein Seil, um andere Igel wegzuschubsen, zum Beispiel, indem du auf dem Boden rutschst. Diese Technik ist bekannt als »Seilschubsen«. + Bleib auf einem eisigen Abhang nicht still stehen, sonst wirst du wegrutschen. Alternativ kannst du [Genaues Zielen] gedrückt halten. + In den Ländern des Schnees und der Weihnacht wird der Schnee langsam und allmählich die Landschaft bedecken, es sei denn, das Land ist unzerstörbar. + Sei vorsichtig in den Ländern des Schnees und der Weihnacht, weil die Träger aus rutschigem Eis bestehen. + Die Rückzugszeit hängt ab von der Waffe, die du benutzt hast. Sei vorsichtig, einige Waffen haben keine Rückzugszeit und beenden deinen Zug sofort! + + Diese Hedgewars-Version unterstützt Xfire. Stell sicher, Hedgewars dessen Spielliste hinzuzufügen, damit deine Freunde dich beim Spielen sehen können. + Du kannst deine Hedgewars-Einstellungsdateien unter »Eigene Dokumente\Hedgewars« finden. Erstelle Backups oder nimm die Dateien mit, aber bitte bearbeite sie nicht von Hand. + + + Du kannst deine Hedgewars-Einstellungsdateien unter »Library/Application Support/Hedgewars« in deinem »home«-Verzeichnis finden. Erstelle Backups oder nimm die Dateien mit, aber bitte bearbeite sie nicht von Hand. + + + Du kannst deine Hedgewars-Einstellungsdateien unter ».hedgewars« in deinem »home«-Verzeichnis finden. Erstelle Backups oder nimm die Dateien mit, aber bitte bearbeite sie nicht von Hand. + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/tips_en.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Locale/tips_en.xml Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,78 @@ + + + Simply pick the same color as a friend to play together as a clan. Each of you will still control his or her own hedgehogs but they’ll win or lose together. + Some weapons might do only low damage but they can be a lot more devastating in the right situation. Try to use the Desert Eagle to knock multiple hedgehogs into the water. + If you’re unsure what to do and don’t want to waste ammo, skip one round. But don’t let too much time pass as there will be Sudden Death! + Want to save ropes? Release the rope in mid air and then shoot again. As long as you don’t touch the ground or miss a shot you’ll reuse your rope without wasting ammo! + If you’d like to keep others from using your preferred nickname on the official server, register an account at http://www.hedgewars.org/. + You're bored of default gameplay? Try one of the missions — they'll offer different gameplay depending on the one you picked. + By default the game will always record the last game played as a demo. Select “Local Game” and pick the “Demos” button on the lower right corner to play or manage them. + Hedgewars is free software (Open Source) we create in our spare time. If you’ve got problems, ask on our forums or visit our IRC room! + Hedgewars is free software (Open Source) we create in our spare time. If you like it, feel free to help us with a small donation or contribute your own work! + Hedgewars is free software (Open Source) we create in our spare time. Share it with your family and friends as you like! + Hedgewars is free software (Open Source) we create in our spare time, just for fun! Meet the devs in #hedgewars! + From time to time there will be official tournaments. Upcoming events will be announced at http://www.hedgewars.org/ some days in advance. + Hedgewars is available in many languages. If the translation in your language seems to be missing or outdated, feel free to contact us! + Hedgewars can be run on lots of different operating systems including Microsoft Windows, Mac OS X and GNU/Linux. + Always remember you’re able to set up your own games in local and network/online play. You’re not restricted to the “Simple Game” option. + Connect one or more gamepads before starting the game to be able to assign their controls to your teams. + Consider giving yourself a short break at least once an hour to guard against strain from playing. + If your graphics card isn’t able to provide hardware accelerated OpenGL, try to enable the low quality mode to improve performance. + If your graphics card isn’t able to provide hardware accelerated OpenGL, try to update the associated drivers. + We’re open to suggestions and constructive feedback. If you don’t like something or got a great idea, let us know! + For your own benefit we'd like you to be polite and friendly while playing on our server. Also please keep in mind that some players are minors! + Special game modes such as “Vampirism” or “Karma” allow you to develop completely new tactics. Try them in a custom game! + Please don't install Hedgewars on computers you don’t own (school, university, work, etc.) unless you got permission. We don't want you to get into any trouble. + Hedgewars can be perfect for short games during breaks. Just ensure you don’t add too many hedgehogs or use an huge map. Reducing time and health might help as well. + No hedgehogs were harmed in making this game. + There are three different jumps available. Tap [high jump] twice to do a very high/backwards jump. + Afraid of falling off a cliff? Hold down [precise] to turn [left] or [right] without actually moving. + Some weapons require special strategies or just lots of training, so don’t give up on a particular tool if you miss an enemy once. + Most weapons won’t work once they touch the water. The Homing Bee as well as the Cake are exceptions to this. + The Old Limburger only causes a small explosion. However the wind affected smelly cloud can poison lots of hogs at once. + The Piano Strike is the most damaging air strike. You’ll lose the hedgehog performing it, so there’s a huge downside as well. + The Homing Bee can be tricky to use. Its turn radius depends on its velocity, so try to not use full power. + Sticky Mines are a perfect tool to create small chain reactions knocking enemy hedgehogs into dire situations … or water. + The Hammer is most effective when used on bridges or girders. Hit hogs will just break through the ground. + If you’re stuck behind an enemy hedgehog, use the Hammer to free yourself without getting damaged by an explosion. + The Cake’s maximum walking distance depends on the ground it has to pass. Use [attack] to detonate it early. + The Flame Thrower is a weapon but it can be used for tunnel digging as well. + Use the Molotov or Flame Thrower to temporary keep hedgehogs from passing terrain such as tunnels or platforms. + Want to know who’s behind the game? Click on the Hedgewars logo in the main menu to see the credits. + Like Hedgewars? Become a fan on Facebook or follow us on Twitter + Feel free to draw your own graves, hats, flags or even maps and themes! But note that you’ll have to share them somewhere to use them online. + Keep your video card drivers up to date to avoid issues playing the game. + Heads or tails? Type “/rnd” in the lobby and you’ll find out. Also “/rnd rock paper scissors” works! + You’re able to associate Hedgewars related files (savegames and demo recordings) with the game to launch them right from your favorite file or web browser. + Dud mines are not harmless: Although their timer is broken, they can still explode if they took too much abuse! + Love is hot! Use Seduction to thaw frozen hedgehogs. + Smoke coming from a barrel is an indicator that it is low on “health” and even small amounts of damage might cause it to burst. + Barrels start with 60 health and take damage like hedgehogs, so they need some abuse until they explode. + Need more bounce power? Change the bounce strength of grenades, cluster bombs, old limburgers and mines while holding [precise] and pressing one of the timer keys. + Did you forget the goals or game modifiers inside the game? Hit the pause or quit key to review them again! + You can punch, whip and hammer other things than just hedgehogs. Hit them all! + If not mentioned otherwise, mines normally explode after 3 seconds. + In King Mode, your king will start out healthier, stronger and more resistant to damage and blows than the minions. + In King Mode, the king will take damage each turn when there are no minions left in the team. + The whip also hits hedgehogs and objects behind a thin wall. + A cleaver deals more damage the faster it’s moving. + You can drop cakes from cliffs, but you have to stand very close to the edge, so be careful. + Use your rope to push away other hedgehogs i.e. by sliding on the ground. This technique is known as “rope-knocking”. + Don’t stand still on an icy slope, or you will slip away. Alternatively, you can hold down [precise]. + In the lands of Snow and Christmas, the snow piles up over time, unless the land is indestructible. + Be aware in lands of Snow and Christmas, because girders are made of slippery ice. + The retreat time depends on the weapon you used. Be careful, some weapons don’t have a retreat time and immediately end your turn! + + This version of Hedgewars supports Xfire. Make sure to add Hedgewars to its game list so your friends can see you playing. + You can find your Hedgewars configuration files under “My Documents\Hedgewars”. Create backups or take the files with you, but don’t edit them by hand. + + + You can find your Hedgewars configuration files under “Library/Application Support/Hedgewars” in your home directory. Create backups or take the files with you, but don’t edit them by hand. + + + You can find your Hedgewars configuration files under “.hedgewars” in your home directory. Create backups or take the files with you, but don’t edit them by hand. + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/tips_es.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Locale/tips_es.xml Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,57 @@ + + + Elige el mismo color que tus amigos para hacer una alianza con ellos. Cada uno de vosotros controlará sus propios erizos, pero la victoria o derrota será compartida por vuestra facción. + Puede que algunas armas hagan poco daño, pero pueden ser realmente devastadoras si son usadas en el momento correcto. Prueba a usar la Desert eagle para empujar erizos enemigos al agua, por ejemplo. + Si no tienes claro qué vas a hacer y prefieres no desperdiciar munición puedes pasar un turno. ¡Pero ten cuidado, si dejas pasar muchos turnos puede que empiece la muerte súbita! + Si prefieres que nadie más use tu nick en el servidor oficial puedes registrarlo en http://www.hedgewars.org/. + ¿Estás cansado del modo de juego de siempre? Prueba alguna de las misiones, encontrarás en ellas nuevos tipos de juego dependiendo de la que elijas. + El juego intentará guardar la última partida como una demo de forma predeterminada. Más tarde puedes ir a "Juego local" y visitar la sección de "Demos" en la esquina inferior derecha para reproducirlas o gestionarlas. + Hedgewars es un juego gratuito de código abierto que hemos creado en nuestro tiempo libre. Si tienes algún problema estaremos encantados de ayudarte en nuestros foros o canal de IRC, pero ¡no esperes que estemos allí las 24 horas del día! + Hedgewars es un juego gratuito de código abierto que hemos creado en nuestro tiempo libre. ¡Si te gusta podrías considerar el ayudarnos con una pequeña donación o contribuyendo con tu propio trabajo! + Hedgewars es un juego gratuito de código abierto que hemos creado en nuestro tiempo libre. ¡Compártelo con tu família y amigos tanto como quieras! + De cuando en cuando celebramos torneos oficiales. Puedes mantenerte al día sobre los próximos eventos en http://www.hedgewars.org. + Hedgewars está disponible en varios idiomas. Si no encuentras traducción a tu idioma o piensas que la actual es de baja calidad o está desactualizada estaremos encantados de aceptar tu colaboración para mejorarla. + Hedgewars es un juego multiplataforma que puede ser ejecutado en diversos sistemas operativos, incluyendo Windows, Mac OS X y Linux. + Recuerda: puedes crear tus propias partidas multijugador tanto en local como por red, no estás limitado a jugar contra la máquina. + Tu salud es lo primero. Recuerda descansar unos minutos al menos una vez por cada hora de juego. + Si tu tarjeta gráfica no soporta aceleración gráfica mediante OpenGL prueba a habilitar el modo de baja calidad gráfica en la pantalla de opciones, puede que mejore el rendimiento del juego. + Siempre estamos abiertos a sugerencias y opiniones constructivas. Si hay algo que no te guste o tienes grandes ideas que te gustaría ver en el juego, ¡háznoslo saber! + Si juegas a través de internet recuerda mantener tus buenos modales y siempre ten en cuenta que puede que estés jugando con o contra menores de edad. + Los modos de juego especiales como "vampirismo" o "karma" te permiten desarrollar tácticas de juego completamente nuevas. ¡Pruébalos en tu próxima partida! + ¡Nunca instales Hedgewars en ordenadores que no te pertenezcan tales como los de tu escuela, universidad o trabajo sin perdir permiso primero a las personas responsables de los mismos! + Hedgewars es realmente genial para jugar partidas rápidas durante pausas o descansos; sólo recuerda no añadir muchos erizos y no usar mapas excesivamente grandes para que la partida no se alargue demasiado. Reducir la duración de los turnos o la vida inicial también puede ayudar. + Ningún erizo fue lastimado durante la creación de este juego. + Hedgewars es un juego gratuito de código abierto que hemos creado en nuestro tiempo libre. Si alguien te ha vendido el juego deberías pedirle que te devuelva tu dinero. + Conecta tus mandos al ordenador antes de iniciar el juego para poder asignar correctamente los controles de a equipo. + Crea una cuenta con tu nick en %1 para evitar que otras personas puedan usarlo en el servidor oficial. + Si tu tarjeta gráfica no es capaz de usar aceleración gráfica mediante OpenGL prueba a instalar drivers más actualizados. + Hay tres tipos de salto en el juego. Presiona [salto alto] dos veces para realizar un salto muy alto, vertical y ligeramente hacia atrás. + ¿Te da miedo caerte por una cornisa? Mantén presionado [aumentar precisión] para voltearte a [izquierda] o [derecha] sin moverte del sitio. + Algunas armas pueden requerir estrategias especiales o mucho entrenamiento antes de ser usadas correctamente. No tires la a toalla con alguna de ellas sólo porque has fallado el tiro la primera vez. + La mayoría de armas se desactivarán al tocar el agua. El abejorro y la tarta son algunas de las excepciones a la regla. + La explosión del limbuger añejo es relativamente pequeña, pero produce una nube de gas venenoso que será arrastrada por el viento, siendo capaz de intoxicar a varios erizos a la vez. + El piano es el ataque aéreo más destructivo del juego, aunque perderás el erizo que lo lance, así que úsalo con cuidado. + Las bombas lapa son perfectas para crear reacciones en cadena y mandar a tus enemigos al agua... o la Luna. + El mazo es mucho más efectivo si lo usas sobre vigas o puentes. Los erizos golpeados simplemente caerán por el agujero como Alicia por la madriguera. + Si estás atrapado tras un erizo enemigo puedes usar el mazo para abrirte paso sin resultar dañado por una explosión. + El alcance de la tarta depende de lo escarpado del terreno que tenga que atravesar, aunque puedes pulsar [atacar] para detonarla antes de que el contador llegue a cero. + El lanzallamas es un arma, pero puede usarse para excavar túneles en caso de necesidad. + ¿Quieres saber quiénes son los desarrolladores del juego? Pulsa el logo del juego en la pantalla principal para ver los créditos. + ¿Te gusta Hedgewars? ¡Hazte fan en %1 o síguenos en %2! + ¡Puedes dibujar tus propias tumbas, sombreros, banderas o incluso mapas y temas! Sólo ten en cuenta que el juego no es capaz de enviar archivos todavía, así que tendrás que enviar tú mismo los archivos a tus amigos para poder jugar en red con ellos. + ¿Te gustaría poder usar un sombrero especial, sólo para ti? Haz una donación y dinos qué sombrero quieres, lo dibujaremos para ti. + Mantén los drivers de tu tarjeta gráfica actualizados para evitar posibles problemas con este y otros juegos. + Puedes encontrar los archivos de configuración del juego en la carpeta "Mis Documentos\Hedgewars". Haz copias de seguridad de los mismos o cópialos a otro ordenador si lo deseas, pero no intentes editarlos a mano para evitar posibles pérdidas de datos. + Puedes asociar los tipos de archivo relacionados, partidas guardadas y demos, con Hedgewars para lanzarlos directamente desde tu gestor de archivos o navegador favoritos. + ¿Necesitas conservar cuerdas? Cuando estés usando una cuerda puedes desengancharla y volver a lanzarla de nuevo. ¡Mientras no toques el suelo seguirás usando la misma cuerda continuamente sin desperdiciar munición adicional! + Puedes encontrar los archivos de configuración del juego en la carpeta "Library/Application Support/Hedgewars" dentro de tu directorio personal. Puedes hacer copias de seguridad de los mismos o copiarlos a otro ordenador si lo deseas, pero no intentes editarlos a mano para evitar posibles pérdidas de datos. + Puedes encontrar los archivos de configuración del juego en la carpeta ".hedgewars" dentro de tu directorio personal. Puedes hacer copias de seguridad de los mismos o copiarlos a otro ordenador si lo deseas, pero no intentes editarlos a mano para evitar posibles pérdidas de datos. + Puedes usar el cóctel molotov o el lanzallamas para evitar que erizos enemigos crucen túneles angostos o puentes. + El abejorro puede ser complicado de usar. Su maniobrabilidad depende de su velocidad, así que intenta no lanzarlo a máxima potencia. + + La versión de Hedgewars para Windows soporta Xfire. Recuerda agregar Hedgewars a tu lista de juegos para que tus amigos puedan saber cuándo estás jugando. + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/tips_fi.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Locale/tips_fi.xml Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,47 @@ + + + Valitse sama väri kaverisi kanssa pelataksesi samassa joukkueessa. Kumpikin ohjaa omia siilejään, mutta voitatte ja häviätte yhdessä. + Jotkut aseet tekevät vain vähän vahinkoa, mutta voivat olla tuhoisampia oikeassa tilanteessa. Kokeile ampua useampi siili veteen Desert Eaglella. + Jos et tiedä mitä tehdä etkä halua tuhlata ammuksia, jätä vuoro väliin. Mutta älä anna ajan kulua liikaa koska Äkkikuolema koittaa ennemmin tai myöhemmin! + Jos haluat estää muita käyttämästä nimimerkkiäsi virallisella palvelimella, rekisteröi tunnus osoitteessa http://www.hedgewars.org/. + Kyllästyttääkö normaali peli? Kokeila tehtäviä - Ne tarjoaa erilaisia pelitapoja riippuen valinnasta. + Oletuksena viimeisin peli nauhoitetaan demoksi. Valitse 'Demot' vasemmasta alakulmasta katsoaksesi ja hallitaksesi niitä. + Hedgewars on avointa lähdekoodia ja ilmainen ohjelma jota me luomme vapaa-aikanamme. Jos sinulla on ongelmia, kysy keskustelualueilta apua, mutta älä odota 24/7-tukea! + Hedgewars on avointa lähdekoodia ja ilmainen ohjelma jota me luomme vapaa-aikanamme. Jos pidät siitä, voit auttaa meitä pienellä lahjoituksella tai omaa työllä! + Hedgewars on avointa lähdekoodia ja ilmainen ohjelma jota me luomme vapaa-aikanamme. Jaa sitä perheesi ja ystäviesi kesken miten haluat! + Toisinaan järjestetään virallisia turnauksia. Tulevista tapahtumista tiedotetaan osoitteessa http://www.hedgewars.org/ muutama päivä etukäteen. + Hedgewars on saatavilla monilla kielillä. Jos oman kielinen käännös puuttuu tai on vanhentunut, ota yhteyttä! + Hedgewars toimii useilla eri käyttöjärjestelmillä, kuten Microsoft Windowsissa, Mac OS X:ssä ja Linuxissa. + Muista että voit aina luoda oman pelisi paikallisesti ja verkkopelissä. Et ole rajoitettu yksinkertaiseen peliin. + Pelatessa sinun pitäisi pitää lyhyt tauko vähintään kerran tunnissa. + Jos näytönohjaimesi ei tarjoa laitteistokiihdytettä OpenGL:ää, kokeile heikennetyn laadun tilaa parantaaksesi suorituskykyä. + Me olemme avoimia ehdotuksille ja rakentavalle palautteelle. Jos et pidä jostain tai sinulla on loistava idea, kerro meille! + Erityisesti verkossa pelattaessa ole kohtelias ja muista että alaikäisiä saattaa myös olla pelaamassa. + Erityispelimoodit kuten 'Vampyrismi' ja 'Karma' mahdollistavat kokonaan uusien taktiikoiden kehittämisen. Kokeile niitä muokatussa pelissä! + Sinun ei ikinä tulisi asentaa Hedgewarsia tietokoneille joita et omista (koulu, yliopisto, työpaikka jne.). Ole hvä ja pyydä vastuuhenkilöä tekemään se! + Hedgewars voi olla täydellinen peli tauoille. Mutta varmista ettet lisää liian montaa siiltä ta käytä liian suurta karttaa. Ajan ja terveyden vähentäminen voi myös auttaa. + Yhtään siiliä ei vahingoitettu tämän pelin tekemisen aikana. + Hedgewars on avointa lähdekoodia ja ilmainen ohjelma jota me luomme vapaa-aikanamme. Jos joku myi sinulle tämän pelin, koita saada rahasi takaisin! + Yhdistä yksi tai useampi peliohjain ennen pelin käynnistämistä liittääksesi niiden kontrollit omaan joukkueeseesi. + Luo käyttäjätili osoitteessa %1 estääksesi muita käyttämästä suosikkinimimerkkiäsi pelatessasi virallisella palvelimella. + Jos näytönohjaimesi ei tue laitteistokiihdytettyä OpenGL:ää, kokeile päivittää ajurit. + Hyppyjä on saatavilla kolmea erilaista. Napauta [korkea hyppy]-nappai kahdesti tehdäksesi todella korkean/taaksepäin hypyn. + Pelkäätkö että putoat kielekkeeltä? Pidä [tarkkuus]-näppäintä pohjassa kääntyäksesi [vasemmalle] ja [oikealle] liikkumatta. + Jotkut aseet vaativat erityisstrategiaa tai todella paljon harjoittelua, joten älä anna periksi vaikka et kerran osuisikaan. + + Vanha Limburger-juusto aiheuttaa vain pienen räjähdyksen, mutta tuulen vaikuttama hajupilvi voi myrkyttää suuren määrän siiliä kerralla. + Pianoisku on vahingollisin ilmaisku. Menetät siilen joka sen esittää, joten sillä on myös suuri huono puoli. + Tarttuvat miinat ovat täydellinen työkalu luomaan pieniä ketjureaktioita jotka vie vihollissiilit kauheisiin tilanteisiin...tai veteen. + Vasara on tehokkaimmillaan silloilla ja palkeilla. Lyödyt siilit iskeytyvät maan läpi. + Jos olet jumissa vihollissiilin takana, käytä vasaraa vapauttaaksesi itsesi ilman että vahingoidut räjädyksen voimasta. + Kakun pisin mahdollinen kulkumatka riippuu maastosta. Käytä [hyökkäystä] räjäyttääksesi sen aikaisemmin. + Liekinheitin on ase mutta sitä voi käyttää myös tunneleiden kaivamiseen. + Haluatko tietää ketkä ovat pelin takana? Klikkaa Hedgewars-logoa päävalikossa nähdäksesi tekijäluettelon. + Piirrä vapaasti omia hautoja, hattuja, lippuja ja jopa karttoja ja teemoja! Mutta huomaa että sinun pitää jakaa ne jossain käyttääksesi niitä verkossa. + Haluatko todella pitää tiettyä hattua? Lahjoita meille niin saat yksinoikeudella vapaavalintaisen hatun! + Pidä näytönohjaimesi ajurit ajantasall välttääksesi ongelmat pelin pelaamisessa. + Löydät Hedgewars-asetustiedostot hakemistosta "Omat tiedostot\Hedgewars". Ota varmuuskopio tai ota ne mukaasi, mutta älä muokkaa niitä käsin. + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/tips_fr.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Locale/tips_fr.xml Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,44 @@ + + + Choisissez la même couleur qu'un ami pour jouer dans la même équipe. Chacun de vous continuera à contrôler son ou ses hérissons mais ils gagneront ou perdront ensembles. + Certaines armes peuvent occasionner seulement de faibles dommages mais être beaucoup plus dévastatrices dans la situation adéquate. Essayez le Révolver pour envoyer plusieurs hérissons à l'eau. + Si vous ne savez pas quoi faire et ne voulez pas gaspiller de munitions, passez un tour. Mais ne laissez pas trop filer le temps ou ce sera la Mort Subite ! + Si vous voulez empêcher les autres d'utiliser votre pseudo sur le serveur officiel, créez un compte sur http://www.hedgewars.org/. + Assez du mode par défaut ? Essayez une des missions - elles offrent différents types de jeu suivant votre choix. + Par défaut le jeu enregistre la dernière partie jouée comme une démonstration. Sélectionnez « Jeu en local » puis « Démonstrations » en bas à droite pour les visionner ou les gérer. + Hedgewars est un jeu libre et gratuit créé sur notre temps libre. Si vous avez des problèmes, demandez sur nos forums mais n'attendez pas de support 24h/24. + Hedgewars est un jeu libre et gratuit créé sur notre temps libre. Si vous l'aimez, aidez-nous avec un petit don ou contribuez par votre travail ! + Hedgewars est un jeu libre et gratuit créé sur notre temps libre. Partagez-le avec votre famille et vos amis comme vous le voulez ! + De temps en temps il y aura des tournois officiels. Les évènements à venir seront annoncés sur http://www.hedgewars.org/ quelques jours à l'avance. + Hedgewars est disponible dans de nombreuses langues. Si la traduction dans votre langue est partielle ou obsolète, contactez-nous ! + Hedgewars peux être exécuté sur de nombreux systèmes d'exploitation différents, incluant Microsoft Windows, Mac OS X et Linux. + Souvenez-vous que vous pouvez créer votre propres parties en local et en ligne. Vous n'est pas limités aux options de jeu par défaut. + Vous devriez faire une petite pause au moins une fois par heure. + Si votre carte graphique ne peut pas fournir d'accélération matérielle pour OpenGL, essayez le mode de faible qualité pour améliorer les performances. + Nous sommes ouverts aux suggestions et au critiques constructives. Si vous n'aimez pas quelque chose ou avez une grande idée, contactez-nous ! + Particulièrement quand vous jouez en ligne soyez polis et n'oubliez pas que certains joueurs peuvent être mineurs. + Les modes de jeu spéciaux comme « Vampirisme » ou « Karma » vous permettent de développer de nouvelles tactiques. Essayez-les en parties personnalisées ! + Vous ne devriez jamais installer Hedgewars sur des ordinateurs ne vous appartenant pas (école, université, travail, etc...). Demandez au responsable ! + Hedgewars peut être parfait pour des parties courtes pendant une pause. Assurez-vous juste de ne pas avoir mis trop de hérissons ou de ne pas utiliser une carte énorme. Réduire le temps ou la santé peuvent aider également. + Aucun hérisson n'a été blessé durant la conception de ce jeu. + Hedgewars est un jeu libre et gratuit créé sur notre temps libre. Si quelqu'un vous l'a vendu, vous devriez vous faire rembourser ! + Branchez une ou plusieurs manettes avant de lancer le jeu pour pouvoir contrôler vos équipes avec. + Créer un compte sur %1 vous permet d'empêcher les autres d'utiliser votre pseudo favori sur le serveur officiel. + Si votre carte graphique ne peut pas fournir d'accélération matérielle pour OpenGL, essayez d'installer les drivers associés. + Certaines armes demandent de la stratégie ou juste beaucoup d'entrainement, alors ne laissez pas tomber une arme si vous avez raté une fois un ennemi. + La plupart des armes ne fonctionnent pas une fois qu'elles ont touché l'eau. L'Abeille Missile ou le Gâteau sont des exceptions. + La distance maximale que le Gâteau peux parcourir dépend du terrain qu'il doit franchir. Utiliser [attack] pour le faire exploser avant. + Vous voulez savoir qui est derrière le jeu ? Cliquez sur le logo Hedgewars dans le menu principal pour voir les crédits. + Soyez libre de dessiner vos propres tombes, chapeaux, drapeaux ou même cartes et thèmes ! Mais pour les utiliser en ligne vous devrez les partager quelque part. + Vous voulez vraiment un chapeau spécifique ? Faites un don et recevez un chapeau exclusif de votre choix. + Conservez les pilotes de votre carte graphique à jour pour éviter les problèmes en jouant. + Vous pouvez trouver vos fichiers de configuration Hedgewars sous « Mes Documents\Hedgewars ». Créez des sauvegardes ou prenez les fichiers avec vous, mais ne les modifiez pas à la main ! + Vous pouvez associer les fichiers relatifs à Hedgewars (parties enregistrées ou démonstrations) au jeu pour les lancer depuis votre navigateur de fichiers ou internet. + Vous aimez Hedgewars ? Devenez un fan sur %1 ou suivez-nous sur %2 ! + Envie d'économiser des Cordes Ninja ? Relâchez la Corde Ninja en l'air et tirez à nouveau. Du moment que vous ne touchez pas le sol, vous réutiliserez votre Corde Ninja sans gaspiller de munitions. + Vous pouvez trouver vos fichiers de configuration Hedgewars sous « Library/Application Support/Hedgewars » dans votre répertoire personnel. Créez des sauvegardes ou prenez les fichiers avec vous, mais ne les modifiez pas à la main ! + Vous pouvez trouver vos fichiers de configuration Hedgewars sous « .hedgewars » dans votre répertoire personnel. Créez des sauvegardes ou prenez les fichiers avec vous, mais ne les modifiez pas à la main ! + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/tips_it.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Locale/tips_it.xml Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,78 @@ + + + Scegli lo stesso colore di un amico per giocare in squadra. Ciascuno controllerà i propri ricci ma la vittoria o la sconfitta saranno comuni. + Alcune armi potrebbero fare pochi danni ma possono essere devastanti se usate al momento giusto. Prova ad esempio ad utilizzare la Desert Eagle per spingere più ricci in acqua. + Se non sai cosa fare e non vuoi sprecare munizioni, salta il turno. Ma non farlo troppe volte perché c'è il Sudden Death! + Vuoi utilizzare più a lungo la corda? Rilascia la corda a mezz'aria e spara di nuovo. Finché non tocchi il terreno potrai riusare la corda senza sprecare munizioni! + Se vuoi evitare che altri possano impersonarti, utilizzando il tuo nickname, sul server ufficiale, registrati su http://www.hedgewars.org/. + Sei stanco delle partite preimpostate? Prova una missione - le missioni offrono interessanti modalità differenti di partite in base alle tue scelte. + Il gioco salverà sempre l'ultima partita giocata come demo. Seleziona 'Gioco locale' e clicca il bottone 'Demos' nell'angolo in basso a destra per gestirle. + Hedgewars è un programma Open Source e gratuito che creiamo nel nostro tempo libero. Se hai problemi, chiedi nei nostri forum oppure visita il nostro canale IRC! + Hedgewars è un programma Open Source e gratuito che creiamo nel nostro tempo libero. Se ti piace, aiutaci con una piccola donazione o contribuisci con il tuo lavoro! + Hedgewars è un programma Open Source e gratuito che creiamo nel nostro tempo libero. Condividilo con tutta la famiglia e con gli amici come più ti piace! + Hedgewars è un programma Open Source e gratuito che creiamo nel nostro tempo libero. Incontra gli sviluppatori sul canale #hedgewars! + Di tanto in tanto ci saranno tornei ufficiali. Gli eventi saranno annunciati su http://www.hedgewars.org/ con qualche giorno di anticipo. + Hedgewars è disponibile in molte lingue. Se la traduzione nella tua lingua sembra mancante o non aggiornata, sentiti libero di contattaci! + Hedgewars può essere usato su molti sistemi operativi differenti come Microsoft Windows, Mac OS X e GNU/Linux. + Ricordati che sei sempre in grado di configurare partire personalizzate in locale e online. Non devi sentirti limitato alle opzioni predefinite! + Collega uno o più gamepad prima di iniziare il gioco per poterli assegnare alle tue squadra. + Durante il gioco dovresti fare una breve pausa almeno ogni ora per evitare la stanchezza da gioco eccessivo. + Se la tua scheda grafica non è in grado di fornire OpenGL con accelerazione hardware, prova ad abilitare la modalità a bassa qualità per migliorare le prestazioni. + Se la tua scheda grafica non è in grado di fornire OpenGL con accelerazione hardware, prova ad aggiornarne i driver. + Siamo aperti a suggerimenti e consigli costruttivi. Se non ti piace qualcosa o hai una buona idea, comunicacelo! + In particolare quando giochi online sii educato e ricorda che potrebbero esserci dei minorenni che stanno giocando con te o contro di te! + Le modalità di gioco speciali, come “Vampirismo” o “Karma” ti permettono di sviluppare nuove tattiche. Provale in una partita personalizzata! + Non dovresti mai installare Hedgewars su computer che non possiedi (scuola, università, lavoro, ecc.). Per favore, chiedi ai responsabili! + Hedgewars può essere perfetto per brevi partite durante le pause. Assicurati solamente di non aver aggiunto troppi ricci o di usare una mappa troppo grande. Ridurre tempo e vita può aiutare allo stesso modo. + Nessun riccio è stato maltrattato durante lo sviluppo di questo gioco. + Ci sono tre tipi di salto disponibili. Premi [salto in alto] due volte per eseguire un salto in alto all'indietro. + Paura di cadere da un dirupo? Premi [mirino di precisione] per girare a [sinistra] o a [destra] senza muoverti. + Alcune armi richiedono strategie particolari o semplicemente molto allenamento, quindi non arrenderti nell'utilizzo di un'arma specifica se manchi il nemico una volta. + Molte armi non funzionano quando toccano l'acqua. L'Ape a Ricerca così come la Torta sono delle eccezioni. + Il vecchio Limburger causa solo una piccola esplosione. Tuttavia il vento influisce sulla nuvola puzzolente e può avvelenare più ricci contemporaneamente. + L'Ultima Sonata è l'attacco aereo più dannoso. Perderai il tuo riccio, eseguendolo, quindi c'è anche una grossa controindicazione. + L'Ape a Ricerca può essere difficile da usare. Il suo raggio di curvatura dipende dalla sua velocità, quindi cerca di non usarla a piena potenza. + Le Mine Adesive sono lo strumento perfetto per creare piccole reazioni a catena e spingere i ricci nemici in situazioni difficili … o in acqua. + Il Martello è più efficate se usato su ponti o travi. Colpire i ricci li farà sprofondare attraverso il terreno. + Se sei bloccato dietro un riccio nemico, usa il Martello per liberarti senza essere danneggiato da un'esplosione. + La distanza massima di cammino della Torta dipende dal terreno che deve attraversare. Usa [attacca] per farla esplodere prima. + Il Lanciafiamme è un'arma che può essere usata anche per scavare gallerie. + Usa la Bomba Molotov o il Lanciafiamme per impedire temporaneamente ai ricci di attraversare terreni pianeggianti, tunnel o collinette. + Vuoi sapere chi c'è dietro il gioco? Clicca sul logo Hedgewars nel menu principale per vederne gli autori e sviluppatori. + Ti piace Hedgewars? Diventa fan su Facebook oppure seguici su Twitter + Sentiti libero di disegnare tombe, cappelli, bandiere o anche mappe e temi personalizzati! Ma nota che dovrai condividerli in qualche modo per usarli online. + Mantieni aggiornati i driver della tua scheda video, per evitare problemi durante il gioco. + Testa o croce? Scrivi “/rnd” nella schermata LOBBY e lo scoprirai. Funziona anche “/rnd carta sasso forbice”! + Puoi associare i file relativi a Hedgewars (partite salvate e registrazioni demo) al gioco, in modo da lanciarli direttamente dal tuo gestore file o browser web. + Le mine Dud non sono innocue: Anche se il loro timer è rotto, possono ancora esplodere se vengono abusate troppo! + L'amore è caldo! Utilizza Seduzione per scongelare ricci congelati. + Il fumo proveniente da un barile è un indicatore che è basso di “salute” e che anche piccole quantità di danno potrebbe farlo scoppiare. + I barili iniziano con 60 salute e subiscono danni come ricci, quindi hanno bisogno di un po' di danno per esplodere + Hai bisogno di più forza di rimbalzo? Modifica la forza di rimbalzo di granate, bombe a grappolo, vecchi limburgers e mine tenendo premuto [mirino di precisione] e premendo uno dei tasti del timer. + Hai dimenticato gli obiettivi o modificatori di gioco mentre stai giocando? Premi il pulsante pausa o esci per rivederli di nuovo! + Puoi prendere a pugni, frustare, e martellare anche altre cose e non solo ricci. Colpiscili tutti! + Se non menzionato altrimenti, le mine normalmente esplodono dopo 3 secondi. + In modalità Re, il tuo re partirà più sano, più forte e più resistente ai danni e colpi rispetto ai servi. + In modalità Re, il re si danneggerà in ogni turno quando non ci saranno più servi nella sua squadra. + La frusta colpisce anche i ricci e gli oggetti anche dietro una parete sottile. + La mannaia aumenta il danno con l'aumentare della velocità. + Puoi far cadere torte dalle scogliere, ma per farlo bisogna stare molto vicino al bordo, quindi stai attento. + Usa la tua corda per allontanare altri ricci ad esempio facendola scorrere sul terreno. Questa tecnica è nota come “rope-knocking”. + Non fermarti su un pendio ghiacciato, o scivolerai via. In alternativa, è possibile tenere premuto [mirino di precisione]. + Nelle terre innevate Natalizie, i mucchi di neve aumentano nel corso del tempo, a meno che la terra non sia indistruttibile. + Fai attenzione nelle terre innevate e Natalizie, perché le travi sono fatte di ghiaccio scivoloso. + Il tempo di fuga dipende dall'arma che hai usato. Fai attenzione, alcune armi non hanno un tempo di fuga e finiscono subito il tuo turno! + + Questa versione di Hedgewars supporta Xfire. Assicurati di aggiungere Hedgewars alla sua lista giochi, cosi i tuoi amici potranno vederti giocare. + Puoi trovare i file di configurazione di Hedgewars in “My Documents\Hedgewars”. Crea una copia di sicurezza o porta i file con te, ma non modificarli mai manualmente. + + + Puoi trovare i file di configurazione di Hedgewars in “Library/Application Support/Hedgewars” nella tua cartella utente. Crea una copia di sicurezza o porta i file con te, ma non modificarli mai manualmente. + + + Puoi trovare i file di configurazione di Hedgewars in “.hedgewars” nella tua cartella utente. Crea una copia di sicurezza o porta i file con te, ma non modificarli mai manualmente. + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/tips_pl.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Locale/tips_pl.xml Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,57 @@ + + + By grać ze swoim przyjacielem w tej samej drużynie po prostu wybierzcie taki sam kolor obydwu zespołów. Każdy z was będzie sterować swoimi własnymi jeżami ale wygracie bądź przegracie jako jedna drużyna. + Niektóre z broni zadają mało punktów obrażeń jednak użyte w odpowiednim momencie mogą pokazać pazur. Na przykład spróbuj użyć pistoletu by strącić swoich przeciwników do wody. + Jeśli nie jesteś pewien co zrobić w danej turze i nie chcesz tracić amunicji możesz pominąć turę. Nie rób tak jednak zbyt często gdyż nagła śmierć jest nieuchronna! + Jeśli chciałbyś zapobiec używania własnego nicka przez kogoś innego, zarejestruj go na http://www.hedgewars.org . + Znudzony domyślnymi ustawieniami gry? Spróbuj zagrać w którąś z misji. - oferują one zmienione zasady gry w zależności od tej którą wybrałeś. + Gra zawsze będzie zapisywała ostatnią rozgrywkę jako Demo. Wybierz "Grę Lokalną" i kliknij w przycisk "Dema" który znajduje się w prawym dolnym rogu ekranu by je odtworzyć i zarządzać nimi. + Hedgewars jest darmową grą o otwartym kodzie, którą tworzymy w naszym wolnym czasie. Jeśli masz jakiś problem, zapytaj na forum ale nie spodziewaj się wsparcia 24 godziny na dobę! + Hedgewars jest darmową grą o otwartym kodzie, którą tworzymy w naszym wolnym czasie. Jeśli ją lubisz, wspomóż nas małą wpłatą lub stwórz własną czapkę bądź mapę! + Hedgewars jest darmową grą o otwartym kodzie, którą tworzymy w naszym wolnym czasie. Jeśli tylko chcesz, rozdaj ją swojej rodzinie i kolegom! + Od czasu do czasu będą organizowane mistrzostwa. Będą one ogłaszane z wyprzedzeniem na http://www.hedgewars.org/ . + Hedgewars jest dostępne w wielu językach. Jeśli brakuje tłumaczenia w twoim języku bądź jest ono niekompletne, nie bój się z nami skontaktować! + Hedgewars może być uruchomione na różnych systemach operacyjnych takich jak Microsoft Windows, MacOS X, FreeBSD oraz Linux. + Zawsze możesz zmieniać ustawienia gry w opcjach gry lokalnej lub sieciowej. Nie musisz ciągle używać tzw. "Szybkiej gry". + Zawsze pamiętaj o robieniu krótkich przerw co godzinę kiedy grasz na komputerze. + Jeśli twoja karta graficzna nie ma sprzętowego przyspieszania OpenGL, spróbuj włączyć tryb obniżonej jakości by zwiększyć płynność gry. + Jesteśmy otwarci na sugestie oraz konstruktywną krytykę. Jeśli coś Ci się nie podoba bądź masz jakiś pomysł, daj nam znać! + Bądź kulturalny grając przez internet. Pamiętaj o tym, że w Hedgewars mogą grać także młodsze osoby! + Specjalne tryby gry takie jak "Karma" bądź "Wampiryzm" pozwalają na stworzenie nowej taktyki! + Nie powinieneś instalować Hedgewars na komputerach których nie posiadasz (w szkole, na studiach, w pracy itp.). Zapytaj osoby odpowiedzialnej za te komputery! + Hedgewars jest idealny do gry w czasie przerw.Upewnij się, że nie dałeś zbyt dużej ilości jeży, bądź zbyt dużej mapy. Pomóc może także zmniejszenie długości tury lub obniżenie ilości życia. + Żaden jeż nie został ranny w czasie tworzenia tej gry. + Hedgewars jest darmową grą o otwartym kodzie źródłowym którą tworzymy w naszym wolnym czasie. Jeśli ktokolwiek sprzedał Tobie tę grę powinieneś upomnieć się o swoje pieniądze! + Jeśli podłączysz jeden lub więcej gamepadów przed włączeniem gry będziesz miał możliwość przypisania klawiszy by sterować swoimi jeżami. + Stwórz konto na %1 by zapobiec używania twojego ulubionego nicku przez innych na oficjalnym serwerze. + Jeśli twoja karta nie wspiera sprzętowego przyspieszania OpenGL spróbuj uaktualnić swoje sterowniki. + Są trzy różne rodzaje skoku możliwe do wykonania. Naciśnij [wysoki skok] dwa razy by zrobić bardzo wysoki skok w tył. + Boisz się upadku z krawędzi terenu? Przytrzymaj klawisz [precyzyjnego celowania] by obrócić się w [lewo] lub [prawo] bez ruszenia się z miejsca. + Niektóre z broni wymagają specjalnej strategii lub dużo treningu by je popranie używać. Nie poddawaj się gdy nie wychodzi ci za pierwszym razem. + Większość uzbrojenia nie działa pod wodą. Pszczoła i Ciasto są wyjątkami od tej reguły. + Cuchnący ser nie powoduje wielkiego wybuchu. Jednakże pod wpływem wiatru chmura śmierdzącego gazu może bardzo daleko zawędrować i otruć wiele jeży naraz. + Zrzut pianina jest najbardziej morderczym atakiem powietrznym. Pamiętaj, że tracisz jeża którym wykonujesz ten atak więc dobrze zaplanuj swój ruch. + Miny samoprzylepne są idealnym narzędziem by tworzyć małe reakcje łańcuchowe bądź do zmuszenia przeciwnika by popadł w tarapaty lub wpadł do wody. + Młotek jest najbardziej skuteczny na mostach bądź kładkach. Uderzone jeże przelecą przez nie na sam dół. + Jeśli utknąłeś za jeżem przeciwnika, użyj młotka by wbić go w ziemię. Unikniesz wtedy eksplozji która z pewnością zabrałaby Tobie punkty życia. + Dystans który Ciasto może przebyć zależy od terenu który ma do przebycia. Użyj [ataku] by zdetonować je wcześniej. + Miotacz ognia jest śmiercionośną bronią ale może być użyty również jako narzędzie do kopania tuneli. + Chcesz wiedzieć kto tworzy tę grę? Kliknij logo w głównym menu by zobaczyć autorów. + Lubisz Hedgewars? Zostań fanem na %1 lub dołącz do grupy na %2! + Możesz rysować własne nagrobki, czapki, flagi lub nawet mapy albo tematy! Miej na uwadze to by udostępnić je każdemu który będzie grał z Tobą przez sieć. + Chcesz nosić wymarzoną czapkę? Wspomóż nas pieniężnie a my zrobimy specjalną czapkę tylko dla Ciebie! + Pamiętaj o aktualizowaniu sterowników by zapobiec problemom z grami. + Swoje zespoły i konfigurację gry znajdziesz w folderze "Moje Dokumenty\Hedgewars". Twórz regularnie kopie zapasowe, ale nie edytuj tych plików własnoręcznie. + Możesz powiązać typy plików związane z Hedgewars (zapisy gier i dema) by móc je uruchamiać bezpośrednio z ulubionego menedżera plików bądź przeglądarki internetowej. + Chcesz zaoszczędzić liny? Odłącz ją będąc w powietrzu, a potem wypuść ją ponownie. Dopóki nie dotkniesz ziemi, będziesz używał pojedynczego naboju! + Swoje zespoły i konfigurację gry znajdziesz w folderze "Library/Application Support/Hedgewars" w twoim katalogu domowym. Twórz regularnie kopie zapasowe, ale nie edytuj tych plików własnoręcznie. + Swoje zespoły i konfigurację gry znajdziesz w folderze ".hedgewars" w twoim katalogu domowym. Twórz regularnie kopie zapasowe, ale nie edytuj tych plików własnoręcznie. + Użyj koktajlu Mołotowa lub Miotacza ognia by powstrzymać przeciwnika przed przedostaniem się przez tunele lub platformy. + Pszczoła potrafi być ciężka w użyciu. Jej promień skrętu zależy od prędkości lotu, więc nie staraj się nie używać pełnej mocy podczas strzału. + + Wersja Hedgewars dla systemu Windows wspiera Xfire. Upewnij się, że dodałeś Hedgewars do listy gier by Twoi znajomi mogli zobaczyć Ciebie w czasie gry. + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/tips_ru.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Locale/tips_ru.xml Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,57 @@ + + + Выберите тот же цвет команда, что у друга, чтобы играть в союзе. Вы будете управлять своими ежами, но выиграете или проиграете вместе. + Некоторые виды оружия наносят небольшой урон, но могут наносить больший урон в правильной ситуации. Попробуйте использовать пистолет Дезерт Игл, чтобы столкнуть несколько ежей в воду. + Если вы не уверены в том, что хотите сделать и не хотите тратить снаряды, пропустите ход. Но не теряйте много времени, так как смерть неизбежна! + Если вы хотите предотвратить использование вашего псевдонима другими игроками на официальном игровом сервере, зарегистрируйтесь на http://www.hedgewars.org/. + Наскучила обычная игра? Попробуйте миссии, имеющие различные виды сценариев. + По умолчанию игры всегда записывает последнюю игру в виде демки. Выберите "Локальную игру" и нажмите кнопку "Демки" в правом нижнем углу, чтобы проиграть запись. + Hedgewars - это открытое и свободное программное обеспечение, которое мы создаём в наше свободное время. Если у вас возникают вопросы, задавайте их на нашем форуме, но пожалуйста, не ожидайте круглосуточной поддержки! + Hedgewars - это открытое и свободное программное обеспечение, которое мы создаём в наше свободное время. Если вам понравилась игра, помогите нам денежным вознаграждением или вкладом в виде вашей работы! + Hedgewars - это открытое и свободное программное обеспечение, которое мы создаём в наше свободное время. Распространяйте его среди друзей и членов семьи! + Время от времени проводятся официальные турниры. Предстоящие события анонсируются на http://www.hedgewars.org/ за несколько дней. + Hedgewars доступен на многих языках. Если перевод на ваш язык отсутствует или устарел, сообщите нам! + Hedgewars запускается на множестве различных операционных систем, включая Microsoft Windows, Mac OS X и Linux. + Помните, что у вас есть возможность создать собственную игру локально или по сети. Вы не ограничены кнопкой "Простая игра". + Играя, не забывайте делать небольшой перерыв хотя бы раз в час. + Если ваша видеокарта не поддерживает ускорение OpenGL, попробуйте включить опцию "низкое качество", чтобы улучшить производительность. + Мы открыты для предложений и конструктивной критики. Если вам что-то не понравилось или у вас появилась отличная идея, сообщите нам! + Играя по сети, будьте особенно вежливы и всегда помните, что с вами или против вас могут играть дети! + Особые настройки игры "Вампиризм" и "Карма" дают возможность выработать совершенно новую тактику. Попробуйте их! + Не следует устанавливать Hedgewars на компьютеры, не принадлежащие вам (в школе, на работе, в университете и т.п.). Не забудь спросить разрешения у ответственного лица! + Hedgewars может отлично подойти для коротких матчей на перерывах. Просто не добавляйте слишком много ежей и не играйти на больших картах. Также можно уменьшить время или количество начального здоровья. + При подготовке игры не пострадал ни один ёж. + Hedgewars - это открытое и свободное программное обеспечение, которое мы создаём в наше свободное время. Если кто-то продал вам игру, потребуйте возврат денег! + Подсоедините один или несколько геймпадов перед запуском игры, и вы сможете настроить их для управления командами. + Если вы хотите предотвратить использование вашего псевдонима другими игроками на официальном игровом сервере, зарегистрируйтесь на http://www.hedgewars.org/. + Если ваша видеокарта не поддерживает ускорение OpenGL, попробуйте обновить видеодрайвер. + Есть три вида прыжков. Нажмите [прыжок вверх] дважды, чтобы сделать очень высокий прыжок назад. + Боитесь упасть с обрыва? Нажмите левый shift, чтобы повернуться влево или вправо, не передвигаясь. + Некоторые виды оружия требуют особых стратегий или просто много тренировок, поэтому не разочаровывайтесь в инструменте, если разок промахнётесь. + Большинство видов оружия не сработают при попадании в воду. Пчела и Торт - это исключения. + Старый Лимбургер взрывается несильно. Однако ветер, несущий зловонное облако, может отравить несколько ежей за раз. + Фортепьяновый удар - это наиболее мощный из ударов с воздуха. При использовании вы потеряете ежа, в этом его недостаток. + Мины-липучки - отличный инструмент для создания небольших цепных реакций, от которых ёж попадет в неприятную ситуацию... или в воду. + Молот наиболее эффективен, когда используется на мосту или балке. Ударенный ёж пролетит сквозь землю. + Если вы застряли позади ежа противника, используйте Молот. чтобы освободить себя без риска потери здоровья от взрыва. + Дистанция, которую проходит Торт, зависит от поверхности. Используйте клавишу атаки, чтобы сдетонировать его раньше. + Огнемёт - это оружие, но он также может быть использован как инструмент для рытья туннелей. + Хотите узнать, кто стоит за разработкой игры? Нажмите на логотип Hedgewars в главном меню, чтобы увидеть состав разработчиков. + Нравится Hedgewars? Станьте фанатом на %1 или следите за нами на %2! + Рисуйте свои варианты надгробий, шляп, флагов или даже карт и тем! Но не забудьте передать их соперникам каким-либо образом для игры по сети. + Очень хочется особенную шляпу? Сделайте пожертвование и получите эксклюзивную шляпу на выбор! + Обновляйте видеодрайвера, чтобы не было проблем во время игры. + Файлы конфигурации Hedgewars находятся в папке "Мои документы\Hedgewars". Создавайте бэкапы или переносите файлы, но не редактируйте их вручную. + Можно ассоциировать файлы Hedgewars (сохранения и демки игр) с игрой, чтобы запускать их прямо из вашего любимого файлового менеджера или браузера. + Хотите сэкономить верёвки? Отпустите верёвку в воздухе и стреляйте снова. Пока вы не затронете землю, вы можете использовать верёвку сколько угодно, не тратя дополнительных! + Файлы конфигурации Hedgewars находятся в папке ""Library/Application Support/Hedgewars". Создавайте бэкапы или переносите файлы, но не редактируйте их вручную. + Файлы конфигурации Hedgewars находятся в папке ".hedgewars". Создавайте бэкапы или переносите файлы, но не редактируйте их вручную. + Используйте Коктейль Молотова или Огнемёт, чтобы временно не дать ежам пройти через туннель или по платформе. + Пчёлку можеть быть сложно использовать. Её радиус поворота зависит от скорости, поэтому попробуйте не использовать полную силу броска. + + Версия Hedgewars под операционную систему Windows поддерживает Xfire. Не забудьте добавить Hedgewars в список игр, чтобы ваши друзья видели, когда вы в игре. + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/tips_sk.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Locale/tips_sk.xml Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,57 @@ + + + Ak chcete hrať s priateľom ako tím, jednoducho si zvoľte tú istú farbu. I naďalej budete ovládať svojich vlastných ježkov, ale víťazstvá či prehry budú spoločné. + Niektoré zbrane môžu spôsobovať málo škody, ale dokážu byť oveľa účinnejšie v tej správnej situácii. Skúste použiť Desert Eagle na zostrelenie viacerých ježkov do vody. + Ak neviete, čo robiť a nechcete mrhať muníciou, preskočte ťah. Ale nerobte tak príliš často, pretože príde Náhla smrť! + Ak nechcete, aby niekto iný používal vašu prezývku na oficiálnom serveri, registrujte si účet na http://www.hedgewars.org/. + Nudí vás štandardná hra? Vyskúšajte si jednu z misii - ponúkajú iný herný zážitok v závislosti na tom, akú si vyberiete. + Vo východzom nastavení sa posledná hra automaticky ukladá ako demo. Vyberte 'Miestna hra' a kliknite na tlačidlo 'Demá' v pravom dolnom rohu, ak si chcete demo uložiť alebo prehrať. + Hedgewars je Open Source a Freeware, ktorý vytvárame vo voľnom čase. Ak máte problém, spýtajte sa na fóre, ale nečakajte podporu 24 hodín v týždni! + Hedgewars je Open Source a Freeware, ktorý vytvárame vo voľnom čase. Ak chcete pomôcť, môžete nám zaslať malú finančnú výpomoc alebo prispieť vlastnou prácou! + Hedgewars je Open Source a Freeware, ktorý vytvárame vo voľnom čase. Podeľte sa oň so svojou rodinou a priateľmi! + Z času na čas bývajú usporiadavané oficiálne turnaje. Najbližšie akcie sú vždy uverejnené na http://www.hedgewars.org/ pár dní dopredu. + Hedgewars je dostupný v mnohých jazykoch. Ak preklad do vašej reči chýba alebo nie je aktuálny, prosím, kontaktujte nás! + Hedgewars beží na množstve rozličných operačných systémov vrátane Microsoft Windows, Mac OS X a Linuxu. + Nezabudnite, že si vždy môžete vytvoriť vlastnú lokálnu alebo sieťovú/online hru. Nie ste obmedzený len na voľbu 'Jednoduchá hra'. + Mali by ste si dopriať krátky odpočinok po každej hodine hry. + Ak vaša grafická karta nie je schopná poskytnúť hardvérovo akcelerované OpenGL, skúste povoliť režim nízkej kvality, aby ste dosiahli požadovaný výkon. + Sme otvorení novým nápadom a konštruktívnej kritike. Ak sa vám niečo nepáči alebo máte skvelý nápad, dajte nám vedieť! + Obzvlášť pri hre online buďte slušný a pamätajte, že s vami alebo proti vám môžu hrať tiež neplnoletí! + Špeciálne herné režimy ako 'Vampírizmus' alebo 'Karma' vám umožnia vyvinúť úplne novú taktiku. Vyskúšajte ich vo vlastnej hre! + Nikdy by ste nemali inštalovať Hedgewars na cudzí počítač (v škole, na univerzite, v práci, atď). Prosím, radšej požiadajte zodpovednú osobu! + Hedgewars môže byť výborná hra, ak máte krátku chvíľku počas prestávky. Iba sa uistite, že nepoužijete príliš veľa ježkov alebo príliš veľkú mapu. Rovnako môže pomocť zníženie času a zdravia. + Počas tvorby tejto hry nebolo ublížené žiadnemu ježkovi. + Hedgewars je Open Source a Freeware, ktorý vytvárame vo voľnom čase. Ak vám niekto túto hru predal, skúste žiadať o refundáciu! + Ak chcete pre hru použiť jeden alebo viacero gamepadov, pripojte ich pred spustením hry. + Vytvorte si účet na %1, aby ste tak zabránili ostatným používať vašu obľúbenú prezývku počas hrania na oficiálnom serveri. + Ak vaša grafická karta nie je schopná poskytnúť hardvérovo akcelerované OpenGL, skúste aktualizovať príslušné ovládače. + Dostupné sú tri rôzne výskoky. Dvakrát stlačte [vysoký skok] pre veľmi vysoký skok vzad. + Bojíte sa pádu z útesu? Podržte [presné mierenie] a stlačte [doľava] alebo [doprava] pre otočenie na mieste. + Niektoré zbrane vyžaduju osobitnú stratégiu alebo len veľa tréningu, takže to s vybranou zbraňou nevzdávajte, ak sa vám nepodarí trafiť nepriateľa. + Väčšina zbraní prestane fungovať pri kontakte s vodou. Navádzané včela a Torta sú výnimkami z tohto pravidla. + Starý cheeseburger spôsobí len malú explóziu. Obláčik smradu, ktorý je ovplyvňovaný vetrom, však dokáže otráviť množstvo ježkov. + Klavírový útok je najničivejší vzdušný útok. Pri jeho použití prídete o ježka, čo je jeho veľké mínus. + Lepkavé míny sú perfektným nástrojom na vytvorenie malých reťazových reakcii, vďaka ktorým postavíte ježkov do krajných situácii ... alebo vody. + Kladivo je najefektívnejšie pri použití na mostoch alebo trámoch. Zasiahnutí ježkovia prerazia zem. + Ak ste zaseknutý za nepriateľským ježkom, použite kladivo, aby ste sa oslobodili bez toho, aby vám ublížila explózia. + Maximálna prejdená vzdialenosť torty zavisí na zemi, ktorou musí prejsť. Použitie [útok], ak chcete spustiť detonáciu skôr. + Plameňomet je zbraň, no rovnako môže byť použitý na kopanie tunelov. + Chcete vedieť, kto stojí za hrou? Kliknite na logo Hedgewars v hlavnom menu pre zobrazenie zásluh. + Ak máte chuť, môžte si nakresliť vlastné hrobčeky, klobúky, vlajky alebo dokonca mapy a témy! Pamätajte však, že ak ich budete chcieť použiť v hre online, budete ich musieť zdieľať s ostatnými. + Chcete nosiť špecifický klobúk? Prispejte nám a ako odmenu získate exkluzívny klobúk podľa vášho výberu! + Aby ste sa vyhli problémom pri hre, udržujte ovládače vašej grafickej karty vždy aktuálne. + Konfiguračné súbory Hedgewars nájdete v "Moje Dokumenty\Hedgewars". Vytvárajte si zálohy alebo prenášajte si tieto súbory medzi počítačmi, ale needitujte ich ručne. + Chcete ušetriť lano? Kým ste vo vzduchu, uvoľnite ho a opäť vystreľte. Kým sa nedotknete zeme, môžete to isté lano znovu použiť bez toho, aby sa vám míňali jeho zásoby! + Páčia sa vám Hedgewars? Staňte sa fanúšikom na %1 alebo sa pripojte k našej skupine na %2. Môžte nás tiež nasledovať na %3! + Môžte priradiť súbory patriace Hedgewars (uložené hry a nahrávky záznamov) ku hre, čím sa vám budú otvárať priamo z vášho obľubeného prehliadača súborov alebo internetu. + Konfiguračné súbory Hedgewars nájdete v "Library/Application Support/Hedgewars" vo vašom domovskom adresári. Vytvárajte si zálohy alebo prenášajte si tieto súbory medzi počítačmi, ale needitujte ich ručne. + Konfiguračné súbory Hedgewars nájdete v ".hedgewars" vo vašom domovskom adresári. Vytvárajte si zálohy alebo prenášajte si tieto súbory medzi počítačmi, ale needitujte ich ručne. + Použite Molotovov koktejl alebo plameňomet na dočasné zabránenie ježkom prejsť terénom ako sú tunely alebo plošiny. + Navádzaná včela je trošku zložitejšia na použitie. Jej polomer otočenia závisí na jej rýchlosti, takže ju radšej nepoužívajte pri plnej sile. + + Hedgewars vo verzii pre Windows podporujú Xfire. Pridajte si Hedgewars do vášho zoznamu hier tak, aby vás vaši priatelia videli hrať. + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/tips_uk.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Locale/tips_uk.xml Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,57 @@ + + + Виберіть той же колір що і в друга щоб грати в одній команді. Кожен з вас буде керувати власними їжаками але вони виграють чи програють разом. + Деяка зброя наносить мало шкоди, але вона може бути більш руйнівною в правильній ситуації. Спробуйте використати Пустельного Орла для скидання кількох їжаків у воду. + Якщо ви не знаєте що робити і не хочете витрачати боєприпаси, пропустіть один раунд. Але не марнуйте занадто багато часу, тому-що прийде Раптова Смерть! + Якщо ви хочете закріпити за собою нік на офіційному сервері, зареєструйте аккаунт на http://www.hedgewars.org/. + Ви втомилися від гри за замовчуванням? Спробуйте одну з місій - вони пропонують різні види гри залежно від вашого вибору. + За замовчуванням остання гра завжди буде записуватись в якості демо. Виберіть 'Локальну Гру' і натисніть кнопку 'Демонстрації' у нижньому правому куті щоб грати або керувати ними. + Hedgewars є відкритою та безплатною, ми створюємо її у вільний час. Якщо у вас є проблеми, запитайте на нашому форумі, але будь-ласка, не чекайте підтримки 24/7! + Hedgewars є відкритою та безплатною, ми створюємо її у вільний час. Якщо вона вам подобається, допоможіть нам невеликим внеском або вкладіть свою роботу! + Hedgewars є відкритою та безплатною, ми створюємо її у вільний час. Поділіться грою з родиною та друзями! + Час від часу проводяться офіційні турніри. Майбутні події будуть оголошені на http://www.hedgewars.org/ за кілька днів перед проведенням. + Hedgewars доступна на багатьох мовах. Якщо переклад на вашу мову застарів чи відсутній, не соромтеся звертатися до нас! + Hedgewars може бути запущений на багатьох операційних системах, включаючи Microsoft Windows, Mac OS X і Linux. + Завжди пам'ятайте, ви можете створити свою власну гру в локальному та мережному/онлайн-режимах. Ви не обмежені опцією 'Проста Гра'. + Поки граєте гру зробіть коротку перерву хоча б раз на годину. + Якщо ваша відеокарта не може забезпечити апаратне прискорення OpenGL, спробуйте включити режим низької якості для підвищення продуктивності. + Ми відкриті для пропозицій і конструктивного зворотнього зв'язку. Якщо вам не подобається щось або є відмінна ідея, дайте нам знати! + Особливо під час гри онлайн будьте ввічливі і завжди пам'ятайте, з вами чи проти вас можуть грати неповнолітні! + Спеціальні режими гри, такі як 'Вампіризм' чи 'Карма' дозволяють розробляти цілком нову тактику. Спробуйте їх в налаштованій грі! + Ви не повинні встановлювати Hedgewars на комп'ютерах, які вам не належать (школа, університет, робота тощо). Будь ласка, звертайтесь до відповідальної особи! + Hedgewars чудово підходить для короткої гри під час перерв. Переконайтеся, що ви не додали занадто багато їжаків і не взяли велику карту. Скорочення часу і здоров'я також підійде. + Під час розробки гри не постраждав жодний їжак. + Hedgewars є відкритою та безплатною, ми створюємо її у вільний час. Якщо хтось продав вам гру, ви повинні спробувати отримати відшкодування! + Підключіть один або кілька геймпадів перед початком гри, щоб ваші команди могли ними користуватись. + Створіть акаунт на %1 щоб запобігти використанню іншими особами вашого улюбленого ніку під час гри на офіційному сервері. + Якщо ваша відеокарта не може забезпечити апаратне прискорення OpenGL, спробуйте оновити відповідні драйвери. + В грі існують три різних види стрибків. Натисніть [високий стрибок] двічі щоб зробити дуже високий стрибок назад. + Боїтесь падіння зі скелі? Утримуйте [точно] щоб повернутись [вліво] чи [вправо] без фактичного переміщення. + Деяка зброя вимагає спеціальних стратегій або просто багато тренувань, тому не відмовляйтесь від конкретного інструменту, якщо ви раз не знешкодили ворога. + Більшість зброї не буде працювати після торкання води. Бджола та Торт є виключеннями з цього правила. + Старий лімбургський сир викликає лише невеликий вибух. Однак смердюча хмара, яку відносить вітер, може отруїти багато їжаків за раз. + Напад піаніно є найбільш руйнівним повітряним ударом. Але ви втратите їжака, тому він має і негативну сторону. + Липкі Міни чудовий інструмент створення малих ланцюгових реакцій для закидання ворогів у складні ситуації ... або у воду. + Молоток найбільш ефективний при використанні на мостах чи балках. Удар їжака просто провалить його крізь землю. + Якщо ви застрягли за ворожим їжаком, використайте Молоток, щоб звільнити себе без пошкоджень від вибуху. + Найбільший шлях ходьби Торта залежить від землі, по якій він повинен пройти. Використовуйте [атака] щоб підірвати його раніше. + Вогнемет це зброя, але його можна також використати для риття тунелю. + Хочете знати хто робить гру? Натисніть на логотип Hedgewars в головному меню, щоб побачити список. + Подобається Hedgewars? Станьте фанатом на %1 або слідуйте за нами на %2! + Ви можете самі намалювати надгробки, шапки, прапори та навіть мапи і теми! Але врахуйте, вам доведеться поділитися ними з кимось щоб використати їх в інтернет-грі. + Хочете носити особливий капелюх? Внесіть пожертву і отримайте ексклюзивний капелюх на ваш вибір! + Використовуйте останні відео драйвери щоб уникнути проблем під час гри. + Ви можете знайти файли конфігурації Hedgewars в "My Documents\Hedgewars". Ви можете створити резервні копії або взяти файли з собою, але не редагуйте їх. + Ви можете зв'язати відповідні файли Hedgewars (файли збереження та демо-записи) з грою щоб запускати їх з вашої улюбленої теки чи інтернет-браузеру. + Хочете заощадити мотузки? Випустіть мотузку в повітря а потім знову стріляйте. Поки ви не торкнулись грунту ви можете знову використовувати мотузку, не витрачаючи боєприпаси! + Ви можете знайти файли конфігурації Hedgewars в "Library/Application Support/Hedgewars" в домашній теці. Ви можете створити резервні копії або взяти файли з собою, але не редагуйте їх. + Ви можете знайти файли конфігурації Hedgewars в ".hedgewars" в домашній теці. Ви можете створити резервні копії або взяти файли з собою, але не редагуйте їх. + Використайте Коктейль Молотова або Вогнемет щоб тимчасово утримати їжаків від проходження такої місцевості як тунелі або платформи. + Навідна Бджілка може бути складною у керуванні. Радіус повороту залежить від її швидкості, тому постарайтеся не стріляти на повну силу. + + Windows-версія Hedgewars підтримує Xfire. Переконайтеся в тому, що ви додали Hedgewars до списку ігор, щоб ваші друзі могли бачити вас в грі. + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/tr.lua --- a/share/hedgewars/Data/Locale/tr.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/tr.lua Tue Nov 10 20:43:13 2015 +0100 @@ -4,6 +4,10 @@ -- ["..."] = "", -- ["011101000"] = "", -- A_Classic_Fairytale:dragon -- ["011101001"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:family, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united +-- ["+1 to a Bottom Feeder for killing anyone"] = "", -- Mutant +-- ["+1 to a Mutant for killing anyone"] = "", -- Mutant +-- ["-1 to anyone for a suicide"] = "", -- Mutant +-- ["+2 for becoming a Mutant"] = "", -- Mutant ["30 minutes later..."] = "30 dakika sonra...", -- A_Classic_Fairytale:shadow -- ["About a month ago, a cyborg came and told us that you're the cannibals!"] = "", -- A_Classic_Fairytale:enemy ["Accuracy Bonus!"] = "Güzel Nişan Bonusu!", @@ -13,23 +17,33 @@ -- ["???"] = "", -- A_Classic_Fairytale:backstab -- ["Actually, you aren't worthy of life! Take this..."] = "", -- A_Classic_Fairytale:shadow -- ["A cy-what?"] = "", -- A_Classic_Fairytale:enemy +-- ["Advanced Repositioning Mode"] = "", -- Construction_Mode -- ["Adventurous"] = "", -- A_Classic_Fairytale:journey +-- ["a frenetic Hedgewars mini-game"] = "", -- Frenzy -- ["Africa"] = "", -- Continental_supplies -- ["After Leaks A Lot betrayed his tribe, he joined the cannibals..."] = "", -- A_Classic_Fairytale:first_blood -- ["After the shock caused by the enemy spy, Leaks A Lot and Dense Cloud went hunting to relax."] = "", -- A_Classic_Fairytale:shadow -- ["Again with the 'cannibals' thing!"] = "", -- A_Classic_Fairytale:enemy +-- ["Aggressively removes enemy hedgehogs."] = "", -- Construction_Mode -- ["a Hedgewars challenge"] = "", -- User_Mission_-_RCPlane_Challenge, User_Mission_-_Rope_Knock_Challenge ["a Hedgewars mini-game"] = "Hedgewars mini oyunu", -- Space_Invasion, The_Specialists +-- ["a Hedgewars tag game"] = "", -- Mutant +-- ["AHHh, home sweet home. Made it in %d seconds."] = "", -- ClimbHome ["Aiming Practice"] = "Atış Eğitimi", --Bazooka, Shotgun, SniperRifle +-- ["Air Attack"] = "", -- Construction_Mode -- ["A leap in a leap"] = "", -- A_Classic_Fairytale:first_blood -- ["A little gift from the cyborgs"] = "", -- A_Classic_Fairytale:shadow -- ["All gone...everything!"] = "", -- A_Classic_Fairytale:enemy +-- ["Allows free teleportation between other nodes."] = "", -- Construction_Mode +-- ["Allows placement of girders, rubber-bands, mines, sticky mines and barrels."] = "", -- Construction_Mode +-- ["Allows placement of structures."] = "", -- Construction_Mode +-- ["Allows the placement of weapons, utiliites, and health crates."] = "", -- Construction_Mode -- ["All right, we just need to get to the other side of the island!"] = "", -- A_Classic_Fairytale:journey -- ["All walls touched!"] = "", -- WxW - ["Ammo Depleted!"] = "Munition erschöpft!", - ["ammo extended!"] = "Munition aufgestockt!", - ["Ammo is reset at the end of your turn."] = "Munition wird am Ende des Spielzuges zurückgesetzt.", - ["Ammo Maniac!"] = "Munitionsverrückter!", + ["Ammo Depleted!"] = "Mermi Bitti!", + ["ammo extended!"] = "mermi genişletildi!", + ["Ammo is reset at the end of your turn."] = "Mermi turunun sonunda sıfırlanır.", + ["Ammo Maniac!"] = "Mermi Manyağı!", ["Ammo"] = "Mermi", -- ["And how am I alive?!"] = "", -- A_Classic_Fairytale:enemy -- ["And so happenned that Leaks A Lot failed to complete the challenge! He landed, pressured by shame..."] = "", -- A_Classic_Fairytale:first_blood @@ -38,8 +52,11 @@ -- ["And so they discovered that cyborgs weren't invulnerable..."] = "", -- A_Classic_Fairytale:journey -- ["And where's all the weed?"] = "", -- A_Classic_Fairytale:dragon -- ["And you believed me? Oh, god, that's cute!"] = "", -- A_Classic_Fairytale:journey --- ["Anno 1032: [The explosion will make a strong push ~ wide range, wont affect hogs close to the target]"] = "", -- Continental_supplies +-- ["Anno 1032: [The explosion will make a strong push ~ Wide range, wont affect hogs close to the target]"] = "", -- Continental_supplies + -- ["Antarctica"] = "", -- Continental_supplies +-- ["Antarctic summer: - Will give you one girder/mudball and two sineguns/portals every fourth turn."] = "", -- Continental_supplies +-- ["Area"] = "", -- Continental_supplies -- ["Are we there yet?"] = "", -- A_Classic_Fairytale:shadow -- ["Are you accusing me of something?"] = "", -- A_Classic_Fairytale:backstab -- ["Are you saying that many of us have died for your entertainment?"] = "", -- A_Classic_Fairytale:enemy @@ -53,35 +70,43 @@ -- ["As you can see, there is no way to get on the other side!"] = "", -- A_Classic_Fairytale:dragon -- ["Attack From Rope"] = "", -- WxW -- ["Australia"] = "", -- Continental_supplies - ["Available points remaining: "] = "Verfügbare Punkte verbleibend:", + ["Available points remaining: "] = "Halan kullanılabilir puanlar: ", -- ["Back Breaker"] = "", -- A_Classic_Fairytale:backstab -- ["Back in the village, after telling the villagers about the threat..."] = "", -- A_Classic_Fairytale:united -- ["[Backspace]"] = "", -- ["Backstab"] = "", -- A_Classic_Fairytale:backstab -- ["Bad Team"] = "", -- User_Mission_-_The_Great_Escape +-- ["Ballgun"] = "", -- Construction_Mode -- ["Bamboo Thicket"] = "", - ["Barrel Eater!"] = "Fassfresser!", - ["Barrel Launcher"] = "Fasswerfer", + ["Barrel Eater!"] = "Varilsever!", + ["Barrel Launcher"] = "Varil Patlatıcı", +-- ["Barrel Placement Mode"] = "", -- Construction_Mode +-- ["Baseball Bat"] = "", -- Construction_Mode -- ["Baseballbat"] = "", -- Continental_supplies - ["Bat balls at your enemies and|push them into the sea!"] = "Schlage Bälle auf deine Widersacher|und lass sie ins Meer fallen!", - ["Bat your opponents through the|baskets and out of the map!"] = "Schlage deine Widersacher durch|die Körbe und aus der Karte hinaus!", - ["Bazooka Training"] = "Bazooka-Training", + ["Bat balls at your enemies and|push them into the sea!"] = "Düşmanlarına sopayla vur|ve denize dök!", + ["Bat your opponents through the|baskets and out of the map!"] = "Düşmanlarını sepetlere vurarak|harita dışına at!", +-- ["Bazooka"] = "", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 + ["Bazooka Training"] = "Roketatar Eğitimi", -- ["Beep Loopers"] = "", -- A_Classic_Fairytale:queen - ["Best laps per team: "] = "Beste Rundenzeiten pro Team: ", - ["Best Team Times: "] = "Beste Team-Zeiten: ", + ["Best laps per team: "] = "Her takım için en iyi tur: ", + ["Best Team Times: "] = "En İyi Takım Süresi: ", -- ["Beware, though! If you are slow, you die!"] = "", -- A_Classic_Fairytale:dragon +-- ["Bio-Filter"] = "", -- Construction_Mode -- ["Biomechanic Team"] = "", -- A_Classic_Fairytale:family +-- ["Birdy"] = "", -- Construction_Mode -- ["Blender"] = "", -- A_Classic_Fairytale:family -- ["Bloodpie"] = "", -- A_Classic_Fairytale:backstab -- ["Bloodrocutor"] = "", -- A_Classic_Fairytale:shadow -- ["Bloodsucker"] = "", -- A_Classic_Fairytale:shadow - ["Bloody Rookies"] = "Blutige Anfänger", -- 01#Boot_Camp, User_Mission_-_Dangerous_Ducklings, User_Mission_-_Diver, User_Mission_-_Spooky_Tree + ["Bloody Rookies"] = "Kanlı Acemiler", -- 01#Boot_Camp, User_Mission_-_Dangerous_Ducklings, User_Mission_-_Diver, User_Mission_-_Spooky_Tree +-- ["Blowtorch"] = "", -- Construction_Mode, Frenzy +-- ["Blue Team"] = "", -- User_Mission_-_Dangerous_Ducklings -- ["Bone Jackson"] = "", -- A_Classic_Fairytale:backstab -- ["Bonely"] = "", -- A_Classic_Fairytale:shadow + ["BOOM!"] = "BUMM!", ["Boom!"] = "Bumm!", - ["BOOM!"] = "KABUMM!", - ["Boss defeated!"] = "Boss wurde besiegt!", - ["Boss Slayer!"] = "Boss-Töter!", + ["Boss defeated!"] = "Patron öldürüldü!", + ["Boss Slayer!"] = "Patron Katili!", -- ["Brain Blower"] = "", -- A_Classic_Fairytale:journey -- ["Brainiac"] = "", -- A_Classic_Fairytale:epil, A_Classic_Fairytale:first_blood, A_Classic_Fairytale:shadow -- ["Brainila"] = "", -- A_Classic_Fairytale:united @@ -89,7 +114,8 @@ -- ["Brain Teaser"] = "", -- A_Classic_Fairytale:backstab -- ["Brutal Lily"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil -- ["Brutus"] = "", -- A_Classic_Fairytale:backstab - ["Build a track and race."] = "Konstruiere eine Strecke und mach ein Wettrennen.", +-- ["Build a fortress and destroy your enemy."] = "", -- Construction_Mode + ["Build a track and race."] = "Bir yol inşa et ve yarış.", -- ["Bullseye"] = "", -- A_Classic_Fairytale:dragon -- ["But it proved to be no easy task!"] = "", -- A_Classic_Fairytale:dragon -- ["But that's impossible!"] = "", -- A_Classic_Fairytale:backstab @@ -99,20 +125,28 @@ -- ["But why would they help us?"] = "", -- A_Classic_Fairytale:backstab -- ["But you're cannibals. It's what you do."] = "", -- A_Classic_Fairytale:enemy -- ["But you said you'd let her go!"] = "", -- A_Classic_Fairytale:journey +-- ["Cake"] = "", -- Construction_Mode -- ["Call me Beep! Well, 'cause I'm such a nice...person!"] = "", -- A_Classic_Fairytale:family -- ["Cannibals"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:first_blood -- ["Cannibal Sentry"] = "", -- A_Classic_Fairytale:journey -- ["Cannibals?! You're the cannibals!"] = "", -- A_Classic_Fairytale:enemy - ["CAPTURE THE FLAG"] = "EROBERE DIE FAHNE", - ["Careless"] = "Achtlos", + ["CAPTURE THE FLAG"] = "BAYRAĞI YAKALA", + ["Careless"] = "Dikkatsiz", -- ["Carol"] = "", -- A_Classic_Fairytale:family -- ["CHALLENGE COMPLETE"] = "", -- User_Mission_-_RCPlane_Challenge - ["Change Weapon"] = "Waffenwechsel", + ["Change Weapon"] = "Silahı Değiştir", +-- ["changing range from %i%% to %i%% with period of %i msec"] = "", -- Gravity -- ["Choose your side! If you want to join the strange man, walk up to him.|Otherwise, walk away from him. If you decide to att...nevermind..."] = "", -- A_Classic_Fairytale:shadow - ["Clumsy"] = "Hoppla", +-- ["Cleaver"] = "", -- Construction_Mode +-- ["Cleaver Placement Mode"] = "", -- Construction_Mode +-- ["Climber"] = "", -- ClimbHome +-- ["Climb Home"] = "", -- ClimbHome +-- ["Clowns"] = "", -- User_Mission_-_Nobody_Laugh + ["Clumsy"] = "Sakar", +-- ["Cluster Bomb"] = "", -- Construction_Mode -- ["Cluster Bomb MASTER!"] = "", -- Basic_Training_-_Cluster_Bomb -- ["Cluster Bomb Training"] = "", -- Basic_Training_-_Cluster_Bomb - ["Codename: Teamwork"] = "Code-Name: Teamwork", + ["Codename: Teamwork"] = "Kodadı: Takım Çalışması", -- ["Collateral Damage"] = "", -- A_Classic_Fairytale:journey -- ["Collateral Damage II"] = "", -- A_Classic_Fairytale:journey -- ["Collect all the crates, but remember, our time in this life is limited!"] = "", -- A_Classic_Fairytale:first_blood @@ -121,38 +155,49 @@ -- ["Collect the crates within the time limit!|If you fail, you'll have to try again."] = "", -- A_Classic_Fairytale:first_blood -- ["Come closer, so that your training may continue!"] = "", -- A_Classic_Fairytale:first_blood -- ["Compete to use as few planes as possible!"] = "", -- User_Mission_-_RCPlane_Challenge - ["Complete the track as fast as you can!"] = "Durchlaufe die Strecke so schnell du kannst!", + ["Complete the track as fast as you can!"] = "Yolu mümkün olduğunca hızlı tamamla!", -- ["COMPLETION TIME"] = "", -- User_Mission_-_Rope_Knock_Challenge -- ["Configuration accepted."] = "", -- WxW -- ["Congratulations"] = "", -- Basic_Training_-_Rope - ["Congratulations!"] = "Gratulation!", + ["Congratulations!"] = "Tebrikler!", -- ["Congratulations! You needed only half of time|to eliminate all targets."] = "", -- Basic_Training_-_Cluster_Bomb -- ["Congratulations! You've completed the Rope tutorial! |- Tutorial ends in 10 seconds!"] = "", -- Basic_Training_-_Rope - ["Congratulations! You've eliminated all targets|within the allowed time frame."] = "Gratulation! Du hast alle Ziele innerhalb der|verfügbaren Zeit ausgeschaltet.", --Bazooka, Shotgun, SniperRifle + ["Congratulations! You've eliminated all targets|within the allowed time frame."] = "Tebrikler! Tüm hedefleri|belirtilen sürede yendin.", --Bazooka, Shotgun, SniperRifle +-- ["CONSTRUCTION MODE"] = "", -- Construction_Mode +-- ["Construction Station"] = "", -- Construction_Mode -- ["Continental supplies"] = "", -- Continental_supplies - ["Control pillars to score points."] = "Kontrolliere die Säulen um Punkte zu erhalten.", + ["Control pillars to score points."] = "Puan toplamak için sütunları denetle.", +-- ["Core"] = "", -- Construction_Mode -- ["Corporationals"] = "", -- A_Classic_Fairytale:queen -- ["Corpsemonger"] = "", -- A_Classic_Fairytale:shadow -- ["Corpse Thrower"] = "", -- A_Classic_Fairytale:epil +-- ["Cost"] = "", -- Construction_Mode +-- ["Crate Placement Tool"] = "", -- Construction_Mode -- ["Crates Left:"] = "", -- User_Mission_-_RCPlane_Challenge +-- ["Cricket time: [Drop a fireable mine! ~ Will work if fired close to your hog & far away from enemy ~ 1 sec]"] = "", -- Continental_supplies +-- ["Current setting is "] = "", -- Gravity ["Cybernetic Empire"] = "Kybernetisches Imperium", -- ["Cyborg. It's what the aliens call themselves."] = "", -- A_Classic_Fairytale:enemy -- ["Dahmer"] = "", -- A_Classic_Fairytale:backstab - ["DAMMIT, ROOKIE! GET OFF MY HEAD!"] = "VERDAMMT, REKRUT! RUNTER VON MEINEM KOPF!", - ["DAMMIT, ROOKIE!"] = "VERDAMMT, REKRUT!", + ["DAMMIT, ROOKIE! GET OFF MY HEAD!"] = "LANET OLSUN ACEMİ! DEFOL BAŞIMDAN!", + ["DAMMIT, ROOKIE!"] = "LANET OLSUN ACEMİ!", -- ["Dangerous Ducklings"] = "", - ["Deadweight"] = "Gravitus", + ["Deadweight"] = "Graviton", +-- ["Decrease"] = "", -- Continental_supplies -- ["Defeat the cannibals"] = "", -- A_Classic_Fairytale:backstab -- ["Defeat the cannibals!|"] = "", -- A_Classic_Fairytale:united -- ["Defeat the cannibals!|Grenade hint: set the timer with [1-5], aim with [Up]/[Down] and hold [Space] to set power"] = "", -- A_Classic_Fairytale:shadow -- ["Defeat the cyborgs!"] = "", -- A_Classic_Fairytale:enemy +-- ["Defend your core from the enemy."] = "", -- Construction_Mode -- ["Defend yourself!|Hint: You can get tips on using weapons by moving your mouse over them in the weapon selection menu"] = "", -- A_Classic_Fairytale:shadow - ["Demolition is fun!"] = "Zerstörung macht Spaß!", +-- ["Dematerializes weapons and equipment carried by enemy hedgehogs."] = "", -- Construction_Mode + ["Demolition is fun!"] = "Yok etmek eğlencelidir!", -- ["Dense Cloud"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united -- ["Dense Cloud must have already told them everything..."] = "", -- A_Classic_Fairytale:shadow - ["Depleted Kamikaze!"] = "Munitionsloses Kamikaze!", + ["Depleted Kamikaze!"] = "Boşa yapılmış Kamikaze!", +-- ["Desert Eagle"] = "", -- Construction_Mode, A_Space_Adventure:death02 -- ["Destroy him, Leaks A Lot! He is responsible for the deaths of many of us!"] = "", -- A_Classic_Fairytale:first_blood - ["Destroy invaders to score points."] = "Zerstöre die Angreifer um Punkte zu erhalten.", + ["Destroy invaders to score points."] = "Puan kazanmak için istilacıları yok et.", -- ["Destroy the targets!|Hint: Select the Shoryuken and hit [Space]|P.S. You can use it mid-air."] = "", -- A_Classic_Fairytale:first_blood -- ["Destroy the targets!|Hint: [Up], [Down] to aim, [Space] to shoot"] = "", -- A_Classic_Fairytale:first_blood -- ["Did anyone follow you?"] = "", -- A_Classic_Fairytale:united @@ -169,10 +214,13 @@ -- ["Do you have any idea how valuable grass is?"] = "", -- A_Classic_Fairytale:enemy -- ["Do you think you're some kind of god?"] = "", -- A_Classic_Fairytale:enemy -- ["Dragon's Lair"] = "", -- A_Classic_Fairytale:dragon +-- ["Drill Rocket"] = "", -- Construction_Mode -- ["Drills"] = "", -- A_Classic_Fairytale:backstab +-- ["Drill Strike"] = "", -- Construction_Mode -- ["Drone Hunter!"] = "", --- ["Drop a bomb: [drop some heroic wind that will turn into a bomb on impact]"] = "", -- Continental_supplies - ["Drowner"] = "Absäufer", +-- ["Drop a bomb: [Drop some heroic wind that will turn into a bomb on impact]"] = "", -- Continental_supplies + + ["Drowner"] = "Boğulucu", -- ["Dude, all the plants are gone!"] = "", -- A_Classic_Fairytale:family -- ["Dude, can you see Ramon and Spiky?"] = "", -- A_Classic_Fairytale:journey -- ["Dude, that's so cool!"] = "", -- A_Classic_Fairytale:backstab @@ -181,16 +229,20 @@ -- ["Dude, where are we?"] = "", -- A_Classic_Fairytale:backstab -- ["Dude, wow! I just had the weirdest high!"] = "", -- A_Classic_Fairytale:backstab -- ["Duration"] = "", -- Continental_supplies --- ["Dust storm: [Deals 20 damage to all enemies in the circle]"] = "", -- Continental_supplies - ["Each turn you get 1-3 random weapons"] = "Du bekommst jede Runde 1-3 zufällig gewählte Waffen", - ["Each turn you get one random weapon"] = "Du bekommst jede Runde eine zufällig gewählte Waffe.", +-- ["Dust storm: [Deals 15 damage to all enemies in the circle]"] = "", -- Continental_supplies + +-- ["Dynamite"] = "", -- Construction_Mode +-- ["Each turn is only ONE SECOND!"] = "", -- Frenzy + ["Each turn you get 1-3 random weapons"] = "Her turda 1-3 rastgele silah alacaksın", + ["Each turn you get one random weapon"] = "Her turda bir adet rastgele silah alacaksın", -- ["Eagle Eye"] = "", -- A_Classic_Fairytale:backstab --- ["Eagle Eye: [Blink to the impact ~ one shot]"] = "", -- Continental_supplies +-- ["Eagle Eye: [Blink to the impact ~ One shot]"] = "", -- Continental_supplies + -- ["Ear Sniffer"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:epil -- ["Elderbot"] = "", -- A_Classic_Fairytale:family -- ["Elimate your captor."] = "", -- User_Mission_-_The_Great_Escape - ["Eliminate all enemies"] = "Vernichte alle Gegner", - ["Eliminate all targets before your time runs out.|You have unlimited ammo for this mission."] = "Eliminiere alle Ziele bevor die Zeit ausläuft.|Du hast in dieser Mission unbegrenzte Munition.", --Bazooka, Shotgun, SniperRifle + ["Eliminate all enemies"] = "Tüm düşmanı yoket", + ["Eliminate all targets before your time runs out.|You have unlimited ammo for this mission."] = "Süren dolmadan tüm hedefleri yoket.|Bu görevde sınırsız mermin var.", --Bazooka, Shotgun, SniperRifle -- ["Eliminate enemy hogs and take their weapons."] = "", -- Highlander ["Eliminate Poison before the time runs out"] = "Neutralisiere das Gift bevor die Zeit abgelaufen ist", ["Eliminate the Blue Team"] = "Lösche das Blaue Team aus", @@ -208,8 +260,9 @@ -- ["Every single time!"] = "", -- A_Classic_Fairytale:dragon -- ["Everything looks OK..."] = "", -- A_Classic_Fairytale:enemy -- ["Exactly, man! That was my dream."] = "", -- A_Classic_Fairytale:backstab +-- ["Extra Damage"] = "", -- Construction_Mode +-- ["Extra Time"] = "", -- Construction_Mode -- ["Eye Chewer"] = "", -- A_Classic_Fairytale:journey --- ["INSANITY"] = "", -- Mutant -- ["Family Reunion"] = "", -- A_Classic_Fairytale:family ["Fastest lap: "] = "Schnellste Runde: ", ["Feeble Resistance"] = "Kraftloser Widerstand", @@ -219,9 +272,10 @@ -- ["Femur Lover"] = "", -- A_Classic_Fairytale:shadow -- ["Fierce Competition!"] = "", -- Space_Invasion -- ["Fiery Water"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united +-- ["Filthy Blue"] = "", -- User_Mission_-_Dangerous_Ducklings -- ["Find your tribe!|Cross the lake!"] = "", -- A_Classic_Fairytale:dragon -- ["Finish your training|Hint: Animations can be skipped with the [Precise] key."] = "", -- A_Classic_Fairytale:first_blood --- ["Fire a mine: [Does what it says ~ Cant be dropped close to an enemy ~ 1 sec]"] = "", -- Continental_supplies + ["Fire"] = "Feuer", -- ["First aid kits?!"] = "", -- A_Classic_Fairytale:united -- ["First Blood"] = "", -- A_Classic_Fairytale:first_blood @@ -232,11 +286,15 @@ ["Flag returned!"] = "Fahne zurückgebracht!", ["Flags, and their home base will be placed where each team ends their first turn."] = "Fahnen und deren Heimatstandort werden dort plaziert wo jedes Team deren ersten Zug beendet.", -- ["Flamer"] = "", +-- ["Flamethrower"] = "", -- Construction_Mode -- ["Flaming Worm"] = "", -- A_Classic_Fairytale:backstab --- ["Flare: [fire up some bombs depending on hogs depending on hogs in the circle"] = "", -- Continental_supplies + -- ["Flesh for Brainz"] = "", -- A_Classic_Fairytale:journey +-- ["Flying Saucer"] = "", -- Construction_Mode, Frenzy -- ["For improved features/stability, play 0.9.18+"] = "", -- WxW -- ["Free Dense Cloud and continue the mission!"] = "", -- A_Classic_Fairytale:journey +-- ["Freezer"] = "", -- Construction_Mode +-- ["FRENZY"] = "", -- Frenzy -- ["Friendly Fire!"] = "", ["fuel extended!"] = "Treibstoff aus!", ["GAME BEGUN!!!"] = "SPIEL GESTARTET!!!", @@ -246,6 +304,9 @@ -- ["Game? Was this a game to you?!"] = "", -- A_Classic_Fairytale:enemy -- ["GasBomb"] = "", -- Continental_supplies -- ["Gas Gargler"] = "", -- A_Classic_Fairytale:queen +-- ["General information"] = "", -- Continental_supplies +-- ["Generates power."] = "", -- Construction_Mode +-- ["Generator"] = "", -- Construction_Mode -- ["Get Dense Cloud out of the pit!"] = "", -- A_Classic_Fairytale:journey ["Get on over there and take him out!"] = "Mach, dass du hinüber kommst und schalte ihn aus!", -- ["Get on the head of the mole"] = "", -- A_Classic_Fairytale:first_blood @@ -256,6 +317,8 @@ -- ["Get your teammates out of their natural prison and save the princess!|Hint: Drilling holes should solve everything.|Hint: It might be a good idea to place a girder before starting to drill. Just saying.|Hint: All your hedgehogs need to be above the marked height!|Hint: Leaks A Lot needs to get really close to the princess!"] = "", -- A_Classic_Fairytale:family -- ["GG!"] = "", -- User_Mission_-_Rope_Knock_Challenge -- ["Gimme Bones"] = "", -- A_Classic_Fairytale:backstab +-- ["Girder"] = "", -- Construction_Mode +-- ["Girder Placement Mode"] = "", -- Construction_Mode -- ["Glark"] = "", -- A_Classic_Fairytale:shadow ["Goal"] = "Ziel", ["GO! GO! GO!"] = "Bewegung, Bewegung, Bewegung!", @@ -272,12 +335,16 @@ -- ["Go surf!"] = "", -- WxW ["GOTCHA!"] = "ERWISCHT!", ["Grab Mines/Explosives"] = "Sammle Minen/Fässer", +-- ["Grants nearby hogs life-regeneration."] = "", -- Construction_Mode +-- ["Gravity"] = "", -- Gravity -- ["Great choice, Steve! Mind if I call you that?"] = "", -- A_Classic_Fairytale:shadow -- ["Great work! Now hit it with your Baseball Bat! |Tip: You can change weapon with 'Right Click'!"] = "", -- Basic_Training_-_Rope -- ["Great! You will be contacted soon for assistance."] = "", -- A_Classic_Fairytale:shadow --- ["Green lipstick bullet: [Is poisonous]"] = "", -- Continental_supplies + +-- ["Green lipstick bullet: [Poisonous, deals no damage]"] = "", -- Continental_supplies -- ["Greetings, "] = "", -- A_Classic_Fairytale:dragon -- ["Greetings, cloudy one!"] = "", -- A_Classic_Fairytale:shadow +-- ["Grenade"] = "", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 -- ["Grenade Training"] = "", -- Basic_Training_-_Grenade -- ["Grenadiers"] = "", -- Basic_Training_-_Grenade -- ["Guys, do you think there's more of them?"] = "", -- A_Classic_Fairytale:backstab @@ -285,23 +352,27 @@ -- ["Haha!"] = "", -- A_Classic_Fairytale:united -- ["Hahahaha!"] = "", ["Haha, now THAT would be something!"] = "Haha, na DAS wär ja was!", +-- ["Hammer"] = "", -- Construction_Mode, Continental_supplies -- ["Hannibal"] = "", -- A_Classic_Fairytale:epil ["Hapless Hogs"] = "Glücklose Igel", [" Hapless Hogs left!"] = " Glücklose Igel verbleibend!", - -- [" HAS MUTATED"] = "", -- Mutant -- ["Hatless Jerry"] = "", -- A_Classic_Fairytale:queen -- ["Have no illusions, your tribe is dead, indifferent of your choice."] = "", -- A_Classic_Fairytale:shadow -- ["Have we ever attacked you first?"] = "", -- A_Classic_Fairytale:enemy +-- ["Healing Station"] = "", -- Construction_Mode +-- ["Health Crate Placement Mode"] = "", -- Construction_Mode ["Health crates extend your time."] = "Medipacks verlängern deine Zeit.", -- ["Heavy Cannfantry"] = "", -- A_Classic_Fairytale:united ["Heavy"] = "Schwierig", -- ["Hedge-cogs"] = "", -- A_Classic_Fairytale:enemy --- ["Hedgehog projectile: [fire your hog like a Sticky Bomb]"] = "", -- Continental_supplies +-- ["Hedgehog projectile: [Fire your hog like a Sticky Bomb]"] = "", -- Continental_supplies + ["Hedgewars-Basketball"] = "Hedgewars-Basketball", ["Hedgewars-Knockball"] = "Hedgewars-Knockball", -- ["Hedgibal Lecter"] = "", -- A_Classic_Fairytale:backstab ["Heh, it's not that bad."] = "Hehe, so schlimm ist es nicht.", +-- ["Hellish Handgrenade"] = "", -- Construction_Mode -- ["Hello again, "] = "", -- A_Classic_Fairytale:family -- ["Help me, Leaks!"] = "", -- A_Classic_Fairytale:journey -- ["Help me, please!!!"] = "", -- A_Classic_Fairytale:journey @@ -333,6 +404,7 @@ -- ["Hogminator"] = "", -- A_Classic_Fairytale:family -- ["Hogs in sight!"] = "", -- Continental_supplies -- ["HOLY SHYTE!"] = "", -- Mutant +-- ["Homing Bee"] = "", -- Construction_Mode -- ["Honest Lee"] = "", -- A_Classic_Fairytale:enemy ["Hooray!"] = "Hurra!", -- ["Hostage Situation"] = "", -- A_Classic_Fairytale:family @@ -366,7 +438,6 @@ -- ["If you get stuck, use your Desert Eagle or restart the mission!|"] = "", -- A_Classic_Fairytale:journey -- ["If you know what I mean..."] = "", -- A_Classic_Fairytale:shadow -- ["If you say so..."] = "", -- A_Classic_Fairytale:shadow - -- ["I guess you'll have to kill them."] = "", -- A_Classic_Fairytale:dragon -- ["I have come to make you an offering..."] = "", -- A_Classic_Fairytale:shadow -- ["I have no idea where that mole disappeared...Can you see it?"] = "", -- A_Classic_Fairytale:shadow @@ -389,6 +460,7 @@ -- ["I'm not sure about that!"] = "", -- A_Classic_Fairytale:united -- ["Impressive...you are still dry as the corpse of a hawk after a week in the desert..."] = "", -- A_Classic_Fairytale:first_blood -- ["I'm so scared!"] = "", -- A_Classic_Fairytale:united +-- ["Increase"] = "", -- Continental_supplies -- ["Incredible..."] = "", -- A_Classic_Fairytale:shadow -- ["I need to find the others!"] = "", -- A_Classic_Fairytale:backstab -- ["I need to get to the other side of this island, fast!"] = "", -- A_Classic_Fairytale:journey @@ -397,12 +469,14 @@ -- ["I need to warn the others."] = "", -- A_Classic_Fairytale:backstab -- ["In fact, you are the only one that's been acting strangely."] = "", -- A_Classic_Fairytale:backstab -- ["In order to get to the other side, you need to collect the crates first.|"] = "", -- A_Classic_Fairytale:dragon +-- ["INSANITY"] = "", -- Mutant ["Instructor"] = "Ausbilder", -- 01#Boot_Camp, User_Mission_-_Dangerous_Ducklings -- ["Interesting idea, haha!"] = "", -- A_Classic_Fairytale:enemy -- ["Interesting! Last time you said you killed a cannibal!"] = "", -- A_Classic_Fairytale:backstab -- ["In the meantime, take these and return to your \"friend\"!"] = "", -- A_Classic_Fairytale:shadow ["invaders destroyed"] = "Angreifer zerstört", -- ["Invasion"] = "", -- A_Classic_Fairytale:united +-- ["Invulnerable"] = "", -- Construction_Mode -- ["I saw it with my own eyes!"] = "", -- A_Classic_Fairytale:shadow -- ["I see..."] = "", -- A_Classic_Fairytale:shadow -- ["I see you have already taken the leap of faith."] = "", -- A_Classic_Fairytale:first_blood @@ -445,6 +519,7 @@ -- ["Just kidding, none of you have died!"] = "", -- A_Classic_Fairytale:enemy -- ["Just on a walk."] = "", -- A_Classic_Fairytale:united -- ["Just wait till I get my hands on that trauma! ARGH!"] = "", -- A_Classic_Fairytale:family +-- ["Kamikaze"] = "", -- Construction_Mode ["Kamikaze Expert!"] = "Kamikazeexperte!", ["Keep it up!"] = "Weiter so!", -- ["Kerguelen"] = "", -- Continental_supplies @@ -454,6 +529,8 @@ -- ["Kill the aliens!"] = "", -- A_Classic_Fairytale:dragon -- ["Kill the cannibal!"] = "", -- A_Classic_Fairytale:first_blood -- ["Kill the traitor...or spare his life!|Kill him or press [Precise]!"] = "", -- A_Classic_Fairytale:backstab +-- ["Land Sprayer"] = "", -- Construction_Mode +-- ["Laser Sight"] = "", -- Construction_Mode ["Last Target!"] = "Letzte Zielscheibe!", -- ["Leader"] = "", -- A_Classic_Fairytale:enemy -- ["Leaderbot"] = "", -- A_Classic_Fairytale:queen @@ -464,6 +541,7 @@ -- ["Led Heart"] = "", -- A_Classic_Fairytale:queen -- ["Lee"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen -- ["[Left Shift]"] = "", +-- ["left shift"] = "", -- Continental_supplies -- ["Let a Continent provide your weapons!"] = "", -- Continental_supplies -- ["Let me test your skills a little, will you?"] = "", -- A_Classic_Fairytale:journey -- ["Let's go home!"] = "", -- A_Classic_Fairytale:journey @@ -473,42 +551,57 @@ -- ["Let them have a taste of my fury!"] = "", -- A_Classic_Fairytale:backstab -- ["Let us help, too!"] = "", -- A_Classic_Fairytale:backstab -- ["Light Cannfantry"] = "", -- A_Classic_Fairytale:united +-- ["Limburger"] = "", -- Construction_Mode ["Listen up, maggot!!"] = "Aufgepasst, du Made!!", -- ["Little did they know that this hunt will mark them forever..."] = "", -- A_Classic_Fairytale:shadow -- ["Lively Lifeguard"] = "", --- ["Lonely Cries: [Rise the water if no hog is in the circle and deal 1 damage to all hogs]"] = "", -- Continental_supplies + +-- ["Lonely Cries: [Rise the water if no hog is in the circle and deal 7 damage to all enemy hogs]"] = "", -- Continental_supplies +-- ["Lonely Hog"] = "", -- ClimbHome -- ["Look, I had no choice!"] = "", -- A_Classic_Fairytale:backstab -- ["Look out! There's more of them!"] = "", -- A_Classic_Fairytale:backstab -- ["Look out! We're surrounded by cannibals!"] = "", -- A_Classic_Fairytale:enemy -- ["Looks like the whole world is falling apart!"] = "", -- A_Classic_Fairytale:enemy +-- ["Low Gravity"] = "", -- Construction_Mode, Frenzy -- ["Luckily, I've managed to snatch some of them."] = "", -- A_Classic_Fairytale:united -- ["LUDICROUS KILL"] = "", -- Mutant +-- ["Made it!"] = "", -- ClimbHome +-- ["- Massive weapon bonus on first turn"] = "", -- Continental_supplies -- ["May the spirits aid you in all your quests!"] = "", -- A_Classic_Fairytale:backstab -- ["Medicine: [Fire some exploding medicine that will heal all hogs effected by the explosion]"] = "", -- Continental_supplies -- ["MEGA KILL"] = "", -- Mutant -- ["Meiwes"] = "", -- A_Classic_Fairytale:backstab -- ["Mindy"] = "", -- A_Classic_Fairytale:united +-- ["Mine"] = "", -- Construction_Mode, Frenzy ["Mine Deployer"] = "Minenleger", ["Mine Eater!"] = "Minenfresser!", +-- ["Mine Placement Mode"] = "", -- Construction_Mode ["|- Mines Time:"] = "| - Minenzündzeit: ", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork +-- ["Mine Strike"] = "", -- Construction_Mode ["MISSION FAILED"] = "MISSION GESCHEITERT", -- User_Mission_-_Dangerous_Ducklings, User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork ["MISSION SUCCESSFUL"] = "MISSION ERFOLGREICH", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork ["MISSION SUCCESS"] = "MISSIONSERFOLG", +-- ["Molotov Cocktail"] = "", -- Construction_Mode -- ["Molotov"] = "", -- Continental_supplies -- ["MONSTER KILL"] = "", -- Mutant -- ["More Natives"] = "", -- A_Classic_Fairytale:epil +-- ["Mortar"] = "", -- Construction_Mode, A_Space_Adventure:death02 ["Movement: [Up], [Down], [Left], [Right]"] = "Bewegung: [Hoch], [Runter], [Links], [Rechts]", +-- ["Mudball"] = "", -- Construction_Mode -- ["Multi-shot!"] = "", ["Munition!"] = "Munition erschöpft!", -- ["Muriel"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen -- ["Muscle Dissolver"] = "", -- A_Classic_Fairytale:shadow -- ["-------"] = "", -- Mutant +-- ["Mutant"] = "", -- Mutant -- ["Nade Boy"] = "", -- Basic_Training_-_Grenade -- ["Name"] = "", -- A_Classic_Fairytale:queen ["Nameless Heroes"] = "Namenlose Helden", -- ["Nancy Screw"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:queen +-- ["Napalm"] = "", -- Construction_Mode -- ["Napalm rocket: [Fire a bomb with napalm!]"] = "", -- Continental_supplies -- ["Natives"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:first_blood, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united +-- ["Naughty Ninja"] = "", -- User_Mission_-_Dangerous_Ducklings ["New Barrels Per Turn"] = "Neue Fässer jede Runde", ["NEW CLAN RECORD: "] = "NEUER KLAN-REKORD", ["NEW fastest lap: "] = "NEUE schnellste Runde: ", @@ -519,6 +612,7 @@ -- ["Nice work, "] = "", -- A_Classic_Fairytale:dragon -- ["Nice work!"] = "", -- A_Classic_Fairytale:enemy -- ["Nilarian"] = "", -- A_Classic_Fairytale:queen +-- ["Nobody Laugh"] = "", -- User_Mission_-_Nobody_Laugh -- ["No, I came back to help you out..."] = "", -- A_Classic_Fairytale:shadow -- ["No...I wonder where they disappeared?!"] = "", -- A_Classic_Fairytale:journey -- ["Nom-Nom"] = "", -- A_Classic_Fairytale:journey @@ -526,6 +620,7 @@ -- ["Nope. It was one fast mole, that's for sure."] = "", -- A_Classic_Fairytale:shadow -- ["No! Please, help me!"] = "", -- A_Classic_Fairytale:journey -- ["NORMAL"] = "", -- Continental_supplies +-- ["Normal players can only score points by killing the mutant."] = "", -- Mutant -- ["North America"] = "", -- Continental_supplies -- ["Not all hogs are born equal."] = "", -- Highlander ["NOT ENOUGH WAYPOINTS"] = "NICHT GENUG WEGPUNKTE", @@ -538,6 +633,7 @@ -- ["No. Where did he come from?"] = "", -- A_Classic_Fairytale:shadow -- ["Now how do I get on the other side?!"] = "", -- A_Classic_Fairytale:dragon -- ["No. You and the rest of the tribe are safer there!"] = "", -- A_Classic_Fairytale:backstab +-- ["Object Placement Tool"] = "", -- Construction_Mode -- ["Obliterate them!|Hint: You might want to take cover..."] = "", -- A_Classic_Fairytale:shadow -- ["Obstacle course"] = "", -- A_Classic_Fairytale:dragon -- ["Of course I have to save her. What did I expect?!"] = "", -- A_Classic_Fairytale:family @@ -554,24 +650,30 @@ -- ["Once upon a time, on an island with great natural resources, lived two tribes in heated conflict..."] = "", -- A_Classic_Fairytale:first_blood -- ["ONE HOG PER TEAM! KILLING EXCESS HEDGES"] = "", -- Mutant -- ["One tribe was peaceful, spending their time hunting and training, enjoying the small pleasures of life..."] = "", -- A_Classic_Fairytale:first_blood +-- ["on Skip"] = "", -- Continental_supplies -- ["Oops...I dropped them."] = "", -- A_Classic_Fairytale:united -- ["Open that crate and we will continue!"] = "", -- A_Classic_Fairytale:first_blood -- ["Operation Diver"] = "", ["Opposing Team: "] = "Gegnerisches Team: ", +-- ["or 'g=50, g2=150, period=4000' for gravity changing|from 50 to 150 and back with period of 4000 msec"] = "", -- Gravity -- ["Orlando Boom!"] = "", -- A_Classic_Fairytale:queen +-- ["Other kills don't give you points."] = "", -- Mutant -- ["Ouch!"] = "", -- User_Mission_-_Rope_Knock_Challenge -- ["Our tribe, our beautiful island!"] = "", -- A_Classic_Fairytale:enemy -- ["Parachute"] = "", -- Continental_supplies ["Pathetic Hog #%d"] = "Erbärmlicher Igel #%d", ["Pathetic Resistance"] = "Erbärmlicher Widerstand", -- User_Mission_-_Bamboo_Thicket, User_Mission_-_Newton_and_the_Hammock +-- ["Penguin roar: [Deal 15 damage + 15% of your hogs health to all hogs around you and get 2/3 back]"] = "", -- Continental_supplies -- ["Perfect! Now try to get the next crate without hurting yourself!"] = "", -- A_Classic_Fairytale:first_blood ["Per-Hog Ammo"] = "Munition pro Igel", --- ["- Per team weapons|- 9 weaponschemes|- Unique new weapons| |Select continent first round with the Weapon Menu or by ([switch/tab]=Increase,[precise/left shift]=Decrease) on Skip|Some weapons have a second option. Find them with [switch/tab]"] = "", -- Continental_supplies +-- ["Personal Portal Device"] = "", -- Construction_Mode +-- ["Per team weapons"] = "", -- Continental_supplies -- ["Pfew! That was close!"] = "", -- A_Classic_Fairytale:shadow --- ["Piñata bullet: [Contains some sweet candy!]"] = "", -- Continental_supplies +-- ["Piano Strike"] = "", -- Construction_Mode +-- ["Pickhammer"] = "", -- Construction_Mode + -- ["Pings left:"] = "", -- Space_Invasion - ["Place more waypoints using the 'Air Attack' weapon."] = "Platziere mehr Wegpunkte durch Verwenden der 'Luftangriff'-Waffe", -- ["Planes Used:"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Planes Used"] = "", -- User_Mission_-_RCPlane_Challenge @@ -580,15 +682,19 @@ -- ["Please place the way-point in the open, within the map boundaries."] = "", -- Racer -- ["Please, stop releasing your \"smoke signals\"!"] = "", -- A_Classic_Fairytale:shadow -- ["Point Blank Combo!"] = "", -- Space_Invasion +-- ["POINTS"] = "", -- Mutant ["points"] = "Punkte", -- Control, CTF_Blizzard, Basic_Training_-_Bazooka, Basic_Training_-_Shotgun, Basic_Training_-_Sniper_Rifle ["Poison"] = "Gift", +-- ["Population"] = "", -- Continental_supplies -- ["Portal hint: one goes to the destination, and one is the entrance.|"] = "", -- A_Classic_Fairytale:dragon -- ["Portal mission"] = "", -- portal ["Power Remaining"] = "Verbleibende Energie", ["Prepare yourself"] = "Mach dich bereit", +-- ["presice"] = "", -- Continental_supplies -- ["Press [Enter] to accept this configuration."] = "", -- WxW -- ["Press [Left] or [Right] to move around, [Enter] to jump"] = "", -- A_Classic_Fairytale:first_blood -- ["Press [Precise] to skip intro"] = "", +-- ["Prestigious Pilot"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Private Novak"] = "", -- Basic_Training_-_Cluster_Bomb -- ["Protect yourselves!|Grenade hint: set the timer with [1-5], aim with [Up]/[Down] and hold [Space] to set power"] = "", -- A_Classic_Fairytale:shadow ["PUNKTESTAND"] = "", @@ -598,26 +704,40 @@ -- ["Radar Ping"] = "", -- Space_Invasion -- ["Raging Buffalo"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united -- ["Ramon"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow +-- ["random in range from %i%% to %i%% with period of %i msec"] = "", -- Gravity +-- ["RC Plane"] = "", -- Construction_Mode -- ["RC PLANE TRAINING"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Really?! You thought you could harm me with your little toys?"] = "", -- A_Classic_Fairytale:shadow +-- ["Reflector Shield"] = "", -- Construction_Mode +-- ["Reflects enemy projectiles."] = "", -- Construction_Mode -- ["Regurgitator"] = "", -- A_Classic_Fairytale:backstab -- ["Reinforcements"] = "", -- A_Classic_Fairytale:backstab -- ["Remember: The rope only bend around objects, |if it doesn't hit anything it's always stright!"] = "", -- Basic_Training_-_Rope -- ["Remember this, pathetic animal: when the day comes, you will regret your blind loyalty!"] = "", -- A_Classic_Fairytale:shadow +-- ["REMOVED"] = "", -- Continental_supplies +-- ["Respawner"] = "", -- Construction_Mode +-- ["Resurrector"] = "", -- Construction_Mode +-- ["Resurrects dead hedgehogs."] = "", -- Construction_Mode [" - Return the enemy flag to your base to score | - First team to 3 captures wins | - You may only score when your flag is in your base | - Hogs will drop the flag if killed, or drowned | - Dropped flags may be returned or recaptured | - Hogs respawn when killed"] = " - Bringe die gegnerische Flagge zu deiner Heimatbasis um zu punkten. | - Das Team das zuerst 3 Flaggen erobert gewinnt. | - Du kannst nur punkten wenn deine eigene Flagge in deiner Basis ist | - Igel lassen die Flagge fallen wenn sie sterben oder ertrinken | - Fallen gelassene Flaggen können zurückgebracht oder wieder gestohlen werden | - Igel tauchen nach ihrem Tod wieder auf", -- ["Return to Leaks A Lot! If you get stuck, press [Precise] to try again!"] = "", -- A_Classic_Fairytale:shadow -- ["Righteous Beard"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:first_blood, A_Classic_Fairytale:queen, A_Classic_Fairytale:united +-- ["Rope"] = "", -- Construction_Mode -- ["ROPE-KNOCKING"] = "", -- User_Mission_-_Rope_Knock_Challenge +-- ["Rope to safety"] = "", -- ClimbHome -- ["Rope Training"] = "", -- Basic_Training_-_Rope -- ["Rot Molester"] = "", -- A_Classic_Fairytale:shadow -- ["Round Limit:"] = "", ["Round Limit"] = "Rundenbegrenzung", -- ["Rounds Complete: "] = "", ["Rounds Complete"] = "Runden Gespielt", +-- ["Rubber Band"] = "", -- Construction_Mode +-- ["Rubber Placement Mode"] = "", -- Construction_Mode +-- ["RULES"] = "", -- Frenzy, Mutant ["RULES OF THE GAME [Press ESC to view]"] = "SPIEL REGELN (Drücke ESC zum Anzeigen)", -- ["Rusty Joe"] = "", -- A_Classic_Fairytale:queen -- ["s|"] = "", --- ["Sabotage: [Sabotage all hogs in the circle and deal ~10 dmg]"] = "", -- Continental_supplies +-- ["Sabotage/Flare: [Sabotage all hogs in the circle and deal ~1 dmg OR Fire a cluster up into the air]"] = "", -- Continental_supplies + -- ["Salivaslurper"] = "", -- A_Classic_Fairytale:united -- ["Salvation"] = "", -- A_Classic_Fairytale:family -- ["Salvation was one step closer now..."] = "", -- A_Classic_Fairytale:dragon @@ -629,7 +749,7 @@ -- ["Scalp Muncher"] = "", -- A_Classic_Fairytale:backstab -- ["Score"] = "", -- Mutant -- ["SCORE"] = "", -- Space_Invasion --- ["Scream from a Walrus: [Deal 20 damage + 10% of your hogs health to all hogs around you and get half back]"] = "", -- Continental_supplies + -- ["sec"] = "", -- CTF_Blizzard, TrophyRace, Basic_Training_-_Bazooka, Basic_Training_-_Shotgun, Basic_Training_-_Sniper_Rifle, User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork, Capture_the_Flag -- ["Seduction"] = "", -- Continental_supplies -- ["Seems like every time you take a \"walk\", the enemy find us!"] = "", -- A_Classic_Fairytale:backstab @@ -637,8 +757,11 @@ ["See ya!"] = "Mach's gut!", -- ["Segmentation Paul"] = "", -- A_Classic_Fairytale:dragon -- ["Select continent!"] = "", -- Continental_supplies +-- ["Select continent first round with the Weapon Menu or by"] = "", -- Continental_supplies -- ["Select difficulty: [Left] - easier or [Right] - harder"] = "", -- A_Classic_Fairytale:first_blood ["selected!"] = "ausgewählt!", +-- ["Set period to negative value for random gravity"] = "", -- Gravity +-- ["Setup:|'g=150', where 150 is 150% of normal gravity"] = "", -- Gravity -- ["s"] = "", -- GaudyRacer, Space_Invasion -- ["... share your beauty with the world every morning, my princess!"] = "", -- A_Classic_Fairytale:journey -- ["She's behind that tall thingy."] = "", -- A_Classic_Fairytale:family @@ -650,16 +773,21 @@ ["Shield OFF:"] = "Schild AUS:", ["Shield ON:"] = "Schild AN:", ["Shield Seeker!"] = "Schildsucher!", +-- ["Shoryuken"] = "", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 -- ["Shotgun"] = "", -- Continental_supplies ["Shotgun Team"] = "Schrotflinten-Team", ["Shotgun Training"] = "Schrotflinten-Training", ["shots remaining."] = "Schüsse übrig", ["Silly"] = "Doofi", +-- ["SineGun"] = "", -- Construction_Mode ["Sinky"] = "Blubb", -- ["Sirius Lee"] = "", -- A_Classic_Fairytale:enemy ["%s is out and Team %d|scored a penalty!| |Score:"] = "%s ist draußen und Team %d|erhält eine Strafe!| |Punktestand:", -- Basketball, Knockball ["%s is out and Team %d|scored a point!| |Score:"] = "%s ist draußen und Team %d|erhält einen Punkt!| |Punktestand:", -- Basketball, Knockball -- ["Slippery"] = "", -- A_Classic_Fairytale:journey +-- ["Slot"] = "", -- Frenzy +-- ["Slot keys save time! (F1-F10 by default)"] = "", -- Frenzy +-- ["SLOTS"] = "", -- Frenzy -- ["Smith 0.97"] = "", -- A_Classic_Fairytale:enemy -- ["Smith 0.98"] = "", -- A_Classic_Fairytale:enemy -- ["Smith 0.99a"] = "", -- A_Classic_Fairytale:enemy @@ -671,6 +799,7 @@ ["Sniper Training"] = "Scharfschützen-Training", ["Sniperz"] = "Heckenschützen", -- ["So humiliating..."] = "", -- A_Classic_Fairytale:first_blood +-- ["Some weapons have a second option. Find them with"] = "", -- Continental_supplies -- ["South America"] = "", -- Continental_supplies -- ["So? What will it be?"] = "", -- A_Classic_Fairytale:shadow -- ["Spawn the crate, and attack!"] = "", -- WxW @@ -680,25 +809,43 @@ -- ["Spleenlover"] = "", -- A_Classic_Fairytale:united ["Sponge"] = "Schwamm", -- ["Spooky Tree"] = "", +-- ["Sprite Placement Mode"] = "", -- Construction_Mode +-- ["Sprite Testing Mode"] = "", -- Construction_Mode -- ["STATUS UPDATE"] = "", -- GaudyRacer, Space_Invasion -- ["Steel Eye"] = "", -- A_Classic_Fairytale:queen -- ["Step By Step"] = "", -- A_Classic_Fairytale:first_blood -- ["Steve"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen -- ["Sticky Mine"] = "", -- Continental_supplies +-- ["Sticky Mine Placement Mode"] = "", -- Construction_Mode -- ["Stronglings"] = "", -- A_Classic_Fairytale:shadow --- ["Structure"] = "", -- Continental_supplies + +-- ["Structure Placement Mode"] = "", -- Construction_Mode +-- ["Structure Placement Tool"] = "", -- Construction_Mode +-- ["Sundaland"] = "", -- Continental_supplies -- ["Super Weapons"] = "", -- WxW +-- ["Support Station"] = "", -- Construction_Mode -- ["Surf Before Crate"] = "", -- WxW -- ["Surfer! +15 points!"] = "", -- Space_Invasion -- ["Surfer!"] = "", -- WxW -- ["Survive!|Hint: Cinematics can be skipped with the [Precise] key."] = "", -- A_Classic_Fairytale:shadow -- ["Swing, Leaks A Lot, on the wings of the wind!"] = "", -- A_Classic_Fairytale:first_blood +-- ["switch"] = "", -- Continental_supplies ["Switched to "] = "Gewechselt zu ", +-- ["Switch Hog"] = "", -- Construction_Mode -- ["Syntax Errol"] = "", -- A_Classic_Fairytale:dragon +-- ["tab"] = "", -- Continental_supplies +-- ["Tagging Mode"] = "", -- Construction_Mode -- ["Talk about mixed signals..."] = "", -- A_Classic_Fairytale:dragon +-- ["Tardis"] = "", -- Construction_Mode +-- ["Target Placement Mode"] = "", -- Construction_Mode -- ["Team %d: "] = "", ["Team Scores"] = "Teampunktestand", -- Control, Space_Invasion +-- ["Teleporation Node"] = "", -- Construction_Mode +-- ["Teleportation Mode"] = "", -- Construction_Mode +-- ["Teleportation Node"] = "", -- Construction_Mode +-- ["Teleport"] = "", -- Construction_Mode, Frenzy -- ["Teleport hint: just use the mouse to select the destination!"] = "", -- A_Classic_Fairytale:dragon +-- ["Teleport Unsuccessful. Please teleport within a clan teleporter's sphere of influence."] = "", -- Construction_Mode -- ["Thanks!"] = "", -- A_Classic_Fairytale:family -- ["Thank you, my hero!"] = "", -- A_Classic_Fairytale:family -- ["Thank you, oh, thank you, Leaks A Lot!"] = "", -- A_Classic_Fairytale:journey @@ -715,6 +862,7 @@ ["That was pointless."] = "Das war sinnlos.", -- ["The answer is...entertaintment. You'll see what I mean."] = "", -- A_Classic_Fairytale:backstab -- ["The anti-portal zone is all over the floor, and I have nothing to kill him...Droping something could hurt him enough to kill him..."] = "", -- portal +-- ["The Bottom Feeder can score points by killing anyone."] = "", -- Mutant -- ["The Bull's Eye"] = "", -- A_Classic_Fairytale:first_blood -- ["The caves are well hidden, they won't find us there!"] = "", -- A_Classic_Fairytale:united -- ["The Crate Frenzy"] = "", -- A_Classic_Fairytale:first_blood @@ -724,20 +872,26 @@ -- ["The Enemy Of My Enemy"] = "", -- A_Classic_Fairytale:enemy -- ["The First Blood"] = "", -- A_Classic_Fairytale:first_blood -- ["The First Encounter"] = "", -- A_Classic_Fairytale:shadow +-- ["The first player to kill someone becomes the Mutant."] = "", -- Mutant ["The flag will respawn next round."] = "Die Fahne wird nächste Runde wieder auftauchen.", -- ["The food bites back"] = "", -- A_Classic_Fairytale:backstab -- ["The giant umbrella from the last crate should help break the fall."] = "", -- A_Classic_Fairytale:first_blood -- ["The Great Escape"] = "", -- User_Mission_-_The_Great_Escape +-- ["The Great Hog in the sky sees your sadness and grants you a boon."] = "", -- Construction_Mode -- ["The guardian"] = "", -- A_Classic_Fairytale:shadow -- ["The Individualist"] = "", -- A_Classic_Fairytale:shadow -- ["Their buildings were very primitive back then, even for an uncivilised island."] = "", -- A_Classic_Fairytale:united -- ["The Journey Back"] = "", -- A_Classic_Fairytale:journey -- ["The Leap of Faith"] = "", -- A_Classic_Fairytale:first_blood -- ["The Moonwalk"] = "", -- A_Classic_Fairytale:journey +-- ["The Mutant has super-weapons and a lot of health."] = "", -- Mutant +-- ["The Mutant loses health quickly if he doesn't keep scoring kills."] = "", -- Mutant ["The Nameless One"] = "Der Namenlose", -- ["The next one is pretty hard! |Tip: You have to do multiple swings!"] = "", -- Basic_Training_-_Rope -- ["Then how do they keep appearing?"] = "", -- A_Classic_Fairytale:shadow -- ["The other one were all cannibals, spending their time eating the organs of fellow hedgehogs..."] = "", -- A_Classic_Fairytale:first_blood +-- ["The player with least points (or most deaths) becomes the Bottom Feeder."] = "", -- Mutant +-- ["There are a variety of structures available to aid you."] = "", -- Construction_Mode -- ["There must be a spy among us!"] = "", -- A_Classic_Fairytale:backstab -- ["There's more of them? When did they become so hungry?"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united -- ["There's nothing more satisfying for me than seeing you share your beauty with the world every morning, my princess!"] = "", -- A_Classic_Fairytale:journey @@ -794,7 +948,7 @@ -- ["To the caves..."] = "", -- A_Classic_Fairytale:united ["Toxic Team"] = "Giftige Gegner", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork ["TRACK COMPLETED"] = "STRECKENLAUF BEENDET", - ["TRACK FAILED!"] = "STRECKENLAUF GESCHEITERT", + -- ["training"] = "", -- portal -- ["Traitors"] = "", -- A_Classic_Fairytale:epil -- ["Tribe"] = "", -- A_Classic_Fairytale:backstab @@ -811,6 +965,7 @@ -- ["ULTRA KILL"] = "", -- Mutant -- ["Under Construction"] = "", -- A_Classic_Fairytale:shadow -- ["Unexpected Igor"] = "", -- A_Classic_Fairytale:dragon +-- ["Unique new weapons"] = "", -- Continental_supplies -- ["Unit 0x0007"] = "", -- A_Classic_Fairytale:family -- ["Unit 334a$7%;.*"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united ["Unit 3378"] = "Einheit 3378", @@ -825,11 +980,14 @@ -- ["Use it wisely!"] = "", -- A_Classic_Fairytale:dragon -- ["Use it with precaution!"] = "", -- A_Classic_Fairytale:first_blood -- ["User Challenge"] = "", - +-- ["Use the air-attack weapons and the arrow keys to select structures."] = "", -- Construction_Mode -- ["Use the portal gun to get to the next crate, then use the new gun to get to the final destination!|"] = "", -- A_Classic_Fairytale:dragon -- ["Use the rope to get on the head of the mole, young one!"] = "", -- A_Classic_Fairytale:first_blood -- ["Use the rope to knock your enemies to their doom."] = "", -- User_Mission_-_Rope_Knock_Challenge +-- ["Use your ready time to think."] = "", -- Frenzy ["Use your rope to get from start to finish as fast as you can!"] = "Nutze das Seil um von Start zu Ziel zu gelangen - so schnell du kannst!", +-- ["Utility Crate Placement Mode"] = "", -- Construction_Mode +-- ["Vampirism"] = "", -- Construction_Mode -- ["Vedgies"] = "", -- A_Classic_Fairytale:journey -- ["Vegan Jack"] = "", -- A_Classic_Fairytale:enemy -- ["Victory!"] = "", -- Basic_Training_-_Rope @@ -841,10 +999,14 @@ -- ["Wannabe Flyboys"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Wannabe Shoppsta"] = "", -- User_Mission_-_Rope_Knock_Challenge -- ["Watch your steps, young one!"] = "", -- A_Classic_Fairytale:first_blood +-- ["Watermelon Bomb"] = "", -- Construction_Mode ["Waypoint placed."] = "Wegpunkt gesetzt", ["Way-Points Remaining"] = "Wegpunkte verbleibend", -- ["Weaklings"] = "", -- A_Classic_Fairytale:shadow -- ["We all know what happens when you get frightened..."] = "", -- A_Classic_Fairytale:first_blood +-- ["Weapon Crate Placement Mode"] = "", -- Construction_Mode +-- ["Weapon Filter"] = "", -- Construction_Mode +-- ["weaponschemes"] = "", -- Continental_supplies -- ["Weapons reset."] = "", -- Highlander ["Weapons Reset"] = "Waffenzurücksetzung", -- ["We are indeed."] = "", -- A_Classic_Fairytale:backstab @@ -897,6 +1059,7 @@ -- ["Where do you get that?!"] = "", -- A_Classic_Fairytale:enemy -- ["Where have you been?!"] = "", -- A_Classic_Fairytale:backstab -- ["Where have you been?"] = "", -- A_Classic_Fairytale:united +-- ["Whip"] = "", -- Construction_Mode -- ["? Why?"] = "", -- A_Classic_Fairytale:backstab -- ["Why "] = "", -- A_Classic_Fairytale:backstab -- ["! Why?!"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united @@ -909,8 +1072,10 @@ -- ["Why me?!"] = "", -- A_Classic_Fairytale:backstab -- ["Why would they do this?"] = "", -- A_Classic_Fairytale:backstab -- ["- Will Get 1-3 random weapons"] = "", -- Continental_supplies --- ["- Will refresh Parachute each turn."] = "", -- Continental_supplies --- ["- Will refresh portalgun each turn."] = "", -- Continental_supplies +-- ["- Will give you an airstrike every fifth turn."] = "", -- Continental_supplies +-- ["- Will give you a parachute every second turn."] = "", -- Continental_supplies + + ["Will this ever end?"] = "Bu sona erecek mi?", -- ["WINNER IS "] = "", -- Mutant ["WINNING TIME: "] = "KAZANMA SÜRESİ: ", @@ -929,6 +1094,7 @@ -- ["Yes!"] = "", -- A_Classic_Fairytale:enemy -- ["Yes, yeees! You are now ready to enter the real world!"] = "", -- A_Classic_Fairytale:first_blood -- ["Yo, dude, we're here, too!"] = "", -- A_Classic_Fairytale:family +-- ["You are far from home, and the water is rising, climb up as high as you can!"] = "", -- ClimbHome -- ["You are given the chance to turn your life around..."] = "", -- A_Classic_Fairytale:shadow -- ["You are playing with our lives here!"] = "", -- A_Classic_Fairytale:enemy -- ["! You bastards!"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united @@ -961,6 +1127,8 @@ -- ["You know what? I don't even regret anything!"] = "", -- A_Classic_Fairytale:backstab -- ["You'll see what I mean!"] = "", -- A_Classic_Fairytale:enemy -- ["You may only attack from a rope!"] = "", -- WxW +-- ["You may only spawn 5 crates per turn."] = "", -- Construction_Mode +-- ["You may only use 1 Extra Time per turn."] = "", -- Construction_Mode -- ["You meatbags are pretty slow, you know!"] = "", -- A_Classic_Fairytale:enemy -- ["You might want to find a way to instantly kill arriving cannibals!"] = "", -- A_Classic_Fairytale:backstab -- ["Young one, you are telling us that they can instantly change location without a shaman?"] = "", -- A_Classic_Fairytale:united @@ -981,6 +1149,7 @@ ["You've failed. Try again."] = "Başaramadın. Yeniden dene!", ["You've reached the goal!| |Time: "] = "Hedefe ulaştın!| |Süre: ", -- ["You will be avenged!"] = "", -- A_Classic_Fairytale:shadow +-- ["- You will recieve 2-4 weapons on each kill! (Even on own hogs)"] = "", -- Continental_supplies -- ["You won't believe what happened to me!"] = "", -- A_Classic_Fairytale:backstab -- ["Yuck! I bet they'll keep worshipping her even after I save the village!"] = "", -- A_Classic_Fairytale:family -- ["Zealandia"] = "", -- Continental_supplies diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/tr.txt --- a/share/hedgewars/Data/Locale/tr.txt Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/tr.txt Tue Nov 10 20:43:13 2015 +0100 @@ -451,8 +451,10 @@ 03:51=Zeminde bulunan 03:52=KULLANILMIYOR 03:53=Tür 40 -03:54=Bir şey inşa et -03:55=Yardımcı +; 03:54=Bir şey inşa et +03:54=Yardımcı +03:55=Bundan daha iyi olamazdı! +03:56=Lütfen yanlış veya doğru, kullanın ; Weapon Descriptions (use | as line breaks) 04:00=Düşmanlarına basit el bombası ile saldır.|Zamanlayıcı sıfır olduğunda patlayacak.|1-5: Bomba süresini ayarla|Saldır: Daha fazla güçte atmak için basılı tut @@ -511,6 +513,7 @@ 04:53=Arkadaşlarını savaşta yalnız bırakarak|zaman ve uzaya seyahat et.|Herhangi bir an, Ani Ölüm veya tümü|ölmüşse geri gelmeye hazır ol.|Yadsıma: Ani Ölüm kipinde, tek isen veya|Kralsan çalışmaz. 04:54=TAM DEĞİL 04:55=Yapışkan tanecikler püskürt.|Köprü yap, düşmanı göm, tünelleri kapat.|Dikkatli ol sana gelmesin! +04:56=İki satırı düşmanına atabilir, geçişleri|ve tünelleri kapatabilir,|hatta tırmanmak için bile|kullanabilirsin!|Dikkatli ol! Bıçakla oynamak tehlikeli!|Saldır: Daha yüksek hızda atmak için basılı tut (iki kez) ; Game goal strings 05:00=Oyun Kipleri diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/uk.lua --- a/share/hedgewars/Data/Locale/uk.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/uk.lua Tue Nov 10 20:43:13 2015 +0100 @@ -3,82 +3,107 @@ -- ["..."] = "", -- ["011101000"] = "", -- A_Classic_Fairytale:dragon -- ["011101001"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:family, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united +-- ["+1 to a Bottom Feeder for killing anyone"] = "", -- Mutant +-- ["+1 to a Mutant for killing anyone"] = "", -- Mutant +-- ["-1 to anyone for a suicide"] = "", -- Mutant +-- ["+2 for becoming a Mutant"] = "", -- Mutant -- ["30 minutes later..."] = "", -- A_Classic_Fairytale:shadow -- ["About a month ago, a cyborg came and told us that you're the cannibals!"] = "", -- A_Classic_Fairytale:enemy ["Accuracy Bonus!"] = "Бонус Точності!", -- ["Ace"] = "", -- User_Mission_-_RCPlane_Challenge, User_Mission_-_Rope_Knock_Challenge ["Achievement Unlocked"] = "Досягнення Розблоковано", -- User_Mission_-_Bamboo_Thicket, User_Mission_-_That_Sinking_Feeling, Tumbler --- ["A Classic Fairytale"] = "", -- A_Classic_Fairytale:first_blood -- ["???"] = "", -- A_Classic_Fairytale:backstab + ["A Classic Fairytale"] = "Класична казка", -- A_Classic_Fairytale:first_blood -- ["Actually, you aren't worthy of life! Take this..."] = "", -- A_Classic_Fairytale:shadow -- ["A cy-what?"] = "", -- A_Classic_Fairytale:enemy +-- ["Advanced Repositioning Mode"] = "", -- Construction_Mode -- ["Adventurous"] = "", -- A_Classic_Fairytale:journey --- ["Africa"] = "", -- Continental_supplies +-- ["a frenetic Hedgewars mini-game"] = "", -- Frenzy + ["Africa"] = "Африка", -- Continental_supplies -- ["After Leaks A Lot betrayed his tribe, he joined the cannibals..."] = "", -- A_Classic_Fairytale:first_blood -- ["After the shock caused by the enemy spy, Leaks A Lot and Dense Cloud went hunting to relax."] = "", -- A_Classic_Fairytale:shadow -- ["Again with the 'cannibals' thing!"] = "", -- A_Classic_Fairytale:enemy +-- ["Aggressively removes enemy hedgehogs."] = "", -- Construction_Mode -- ["a Hedgewars challenge"] = "", -- User_Mission_-_RCPlane_Challenge, User_Mission_-_Rope_Knock_Challenge ["a Hedgewars mini-game"] = "Міні-гра Hedgewars", -- Space_Invasion, The_Specialists +-- ["a Hedgewars tag game"] = "", -- Mutant +-- ["AHHh, home sweet home. Made it in %d seconds."] = "", -- ClimbHome ["Aiming Practice"] = "Практика прицілювання", --Bazooka, Shotgun, SniperRifle --- ["A leap in a leap"] = "", -- A_Classic_Fairytale:first_blood --- ["A little gift from the cyborgs"] = "", -- A_Classic_Fairytale:shadow +-- ["Air Attack"] = "", -- Construction_Mode + ["A leap in a leap"] = "Стрибки-скоки", -- A_Classic_Fairytale:first_blood + ["A little gift from the cyborgs"] = "Маленький подарунок від кіборгів", -- A_Classic_Fairytale:shadow -- ["All gone...everything!"] = "", -- A_Classic_Fairytale:enemy --- ["All right, we just need to get to the other side of the island!"] = "", -- A_Classic_Fairytale:journey +-- ["Allows free teleportation between other nodes."] = "", -- Construction_Mode +-- ["Allows placement of girders, rubber-bands, mines, sticky mines and barrels."] = "", -- Construction_Mode +-- ["Allows placement of structures."] = "", -- Construction_Mode +-- ["Allows the placement of weapons, utiliites, and health crates."] = "", -- Construction_Mode + ["All right, we just need to get to the other side of the island!"] = "Гаразд, нам лише треба добратись до другого кінця острова!", -- A_Classic_Fairytale:journey -- ["All walls touched!"] = "", -- WxW ["Ammo Depleted!"] = "Боєприпаси Скінчились!", ["ammo extended!"] = "Боєприпаси поповнені!", ["Ammo is reset at the end of your turn."] = "Боєприпаси обнуляються в кінці вашого ходу.", ["Ammo Maniac!"] = "Маніяк Боєприпасів!", ["Ammo"] = "Боєприпаси", --- ["And how am I alive?!"] = "", -- A_Classic_Fairytale:enemy + ["And how am I alive?!"] = "І чому я живий!?", -- A_Classic_Fairytale:enemy -- ["And so happenned that Leaks A Lot failed to complete the challenge! He landed, pressured by shame..."] = "", -- A_Classic_Fairytale:first_blood --- ["And so it began..."] = "", -- A_Classic_Fairytale:first_blood --- ["...and so the cyborgs took over the world..."] = "", -- A_Classic_Fairytale:shadow + ["And so it began..."] = "І почалось...", -- A_Classic_Fairytale:first_blood + ["...and so the cyborgs took over the world..."] = "...і так кіборги захопили світ...", -- A_Classic_Fairytale:shadow -- ["And so they discovered that cyborgs weren't invulnerable..."] = "", -- A_Classic_Fairytale:journey -- ["And where's all the weed?"] = "", -- A_Classic_Fairytale:dragon -- ["And you believed me? Oh, god, that's cute!"] = "", -- A_Classic_Fairytale:journey --- ["Anno 1032: [The explosion will make a strong push ~ wide range, wont affect hogs close to the target]"] = "", -- Continental_supplies --- ["Antarctica"] = "", -- Continental_supplies +-- ["Anno 1032: [The explosion will make a strong push ~ Wide range, wont affect hogs close to the target]"] = "", -- Continental_supplies + + ["Antarctica"] = "Антарктида", -- Continental_supplies +-- ["Antarctic summer: - Will give you one girder/mudball and two sineguns/portals every fourth turn."] = "", -- Continental_supplies +-- ["Area"] = "", -- Continental_supplies -- ["Are we there yet?"] = "", -- A_Classic_Fairytale:shadow -- ["Are you accusing me of something?"] = "", -- A_Classic_Fairytale:backstab -- ["Are you saying that many of us have died for your entertainment?"] = "", -- A_Classic_Fairytale:enemy -- ["Artur Detour"] = "", -- A_Classic_Fairytale:queen -- ["As a reward for your performance, here's some new technology!"] = "", -- A_Classic_Fairytale:dragon -- ["a shoppa minigame"] = "", -- WxW --- ["Asia"] = "", -- Continental_supplies + ["Asia"] = "Азія", -- Continental_supplies -- ["Assault Team"] = "", -- A_Classic_Fairytale:backstab -- ["As the ammo is sparse, you might want to reuse ropes while mid-air.|"] = "", -- A_Classic_Fairytale:dragon -- ["As the challenge was completed, Leaks A Lot set foot on the ground..."] = "", -- A_Classic_Fairytale:first_blood -- ["As you can see, there is no way to get on the other side!"] = "", -- A_Classic_Fairytale:dragon -- ["Attack From Rope"] = "", -- WxW --- ["Australia"] = "", -- Continental_supplies + ["Australia"] = "Австралія", -- Continental_supplies ["Available points remaining: "] = "Залишилось доступних очків: ", -- ["Back Breaker"] = "", -- A_Classic_Fairytale:backstab -- ["Back in the village, after telling the villagers about the threat..."] = "", -- A_Classic_Fairytale:united -- ["[Backspace]"] = "", -- ["Backstab"] = "", -- A_Classic_Fairytale:backstab --- ["Bad Team"] = "", -- User_Mission_-_The_Great_Escape + ["Bad Team"] = "Погана команда", -- User_Mission_-_The_Great_Escape +-- ["Ballgun"] = "", -- Construction_Mode ["Bamboo Thicket"] = "Бамбукові Хащі", ["Barrel Eater!"] = "Поїдач Бочок!", ["Barrel Launcher"] = "Катапульта для бочок", +-- ["Barrel Placement Mode"] = "", -- Construction_Mode +-- ["Baseball Bat"] = "", -- Construction_Mode -- ["Baseballbat"] = "", -- Continental_supplies ["Bat balls at your enemies and|push them into the sea!"] = "Закидайте ворогів м'ячами щоб|зіштовути їх у море!", ["Bat your opponents through the|baskets and out of the map!"] = "Дубасьте опонентів битою через|кошики та за межі карти!", +-- ["Bazooka"] = "", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 ["Bazooka Training"] = "Тренування з базукою", -- ["Beep Loopers"] = "", -- A_Classic_Fairytale:queen ["Best laps per team: "] = "Кращі партії на команду: ", ["Best Team Times: "] = "Кращий Командний Час: ", -- ["Beware, though! If you are slow, you die!"] = "", -- A_Classic_Fairytale:dragon +-- ["Bio-Filter"] = "", -- Construction_Mode -- ["Biomechanic Team"] = "", -- A_Classic_Fairytale:family +-- ["Birdy"] = "", -- Construction_Mode -- ["Blender"] = "", -- A_Classic_Fairytale:family -- ["Bloodpie"] = "", -- A_Classic_Fairytale:backstab -- ["Bloodrocutor"] = "", -- A_Classic_Fairytale:shadow -- ["Bloodsucker"] = "", -- A_Classic_Fairytale:shadow ["Bloody Rookies"] = "Криваві Салаги", -- 01#Boot_Camp, User_Mission_-_Dangerous_Ducklings, User_Mission_-_Diver, User_Mission_-_Spooky_Tree +-- ["Blowtorch"] = "", -- Construction_Mode, Frenzy +-- ["Blue Team"] = "", -- User_Mission_-_Dangerous_Ducklings -- ["Bone Jackson"] = "", -- A_Classic_Fairytale:backstab -- ["Bonely"] = "", -- A_Classic_Fairytale:shadow + ["BOOM!"] = "БАБАХ!", ["Boom!"] = "Бабах!", - ["BOOM!"] = "БАБАХ!", ["Boss defeated!"] = "Боса переможено!", ["Boss Slayer!"] = "Вбивця Боса!", -- ["Brain Blower"] = "", -- A_Classic_Fairytale:journey @@ -88,27 +113,36 @@ -- ["Brain Teaser"] = "", -- A_Classic_Fairytale:backstab -- ["Brutal Lily"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil -- ["Brutus"] = "", -- A_Classic_Fairytale:backstab +-- ["Build a fortress and destroy your enemy."] = "", -- Construction_Mode ["Build a track and race."] = "Створіть трасу та женіть.", -- ["Bullseye"] = "", -- A_Classic_Fairytale:dragon -- ["But it proved to be no easy task!"] = "", -- A_Classic_Fairytale:dragon -- ["But that's impossible!"] = "", -- A_Classic_Fairytale:backstab -- ["But the ones alive are stronger in their heart!"] = "", -- A_Classic_Fairytale:enemy --- ["But...we died!"] = "", -- A_Classic_Fairytale:backstab --- ["But where can we go?"] = "", -- A_Classic_Fairytale:united --- ["But why would they help us?"] = "", -- A_Classic_Fairytale:backstab + ["But...we died!"] = "Але...ми померли!", -- A_Classic_Fairytale:backstab + ["But where can we go?"] = "Але куди ми можемо піти?", -- A_Classic_Fairytale:united + ["But why would they help us?"] = "Чому вони нам допоможуть?", -- A_Classic_Fairytale:backstab -- ["But you're cannibals. It's what you do."] = "", -- A_Classic_Fairytale:enemy -- ["But you said you'd let her go!"] = "", -- A_Classic_Fairytale:journey +-- ["Cake"] = "", -- Construction_Mode -- ["Call me Beep! Well, 'cause I'm such a nice...person!"] = "", -- A_Classic_Fairytale:family --- ["Cannibals"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:first_blood -- ["Cannibal Sentry"] = "", -- A_Classic_Fairytale:journey --- ["Cannibals?! You're the cannibals!"] = "", -- A_Classic_Fairytale:enemy + ["Cannibals?! You're the cannibals!"] = "Канібали!? Ви канібали!", -- A_Classic_Fairytale:enemy + ["Cannibals"] = "Канібали", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:first_blood ["CAPTURE THE FLAG"] = "ЗАХОПЛЕННЯ ПРАПОРА", ["Careless"] = "Безтурботний", -- ["Carol"] = "", -- A_Classic_Fairytale:family -- ["CHALLENGE COMPLETE"] = "", -- User_Mission_-_RCPlane_Challenge ["Change Weapon"] = "Змінити Зброю", +-- ["changing range from %i%% to %i%% with period of %i msec"] = "", -- Gravity -- ["Choose your side! If you want to join the strange man, walk up to him.|Otherwise, walk away from him. If you decide to att...nevermind..."] = "", -- A_Classic_Fairytale:shadow +-- ["Cleaver"] = "", -- Construction_Mode +-- ["Cleaver Placement Mode"] = "", -- Construction_Mode +-- ["Climber"] = "", -- ClimbHome +-- ["Climb Home"] = "", -- ClimbHome +-- ["Clowns"] = "", -- User_Mission_-_Nobody_Laugh ["Clumsy"] = "Незграбний", +-- ["Cluster Bomb"] = "", -- Construction_Mode -- ["Cluster Bomb MASTER!"] = "", -- Basic_Training_-_Cluster_Bomb -- ["Cluster Bomb Training"] = "", -- Basic_Training_-_Cluster_Bomb ["Codename: Teamwork"] = "Кодова назва: Командна гра", @@ -128,12 +162,19 @@ -- ["Congratulations! You've completed the Rope tutorial! |- Tutorial ends in 10 seconds!"] = "", -- Basic_Training_-_Rope ["Congratulations! You've eliminated all targets|within the allowed time frame."] = "Вітаємо! Ви знищили всі цілі|в межах дозволеного часу.", --Bazooka, Shotgun, SniperRifle ["Congratulations!"] = "Вітаємо!", +-- ["CONSTRUCTION MODE"] = "", -- Construction_Mode +-- ["Construction Station"] = "", -- Construction_Mode -- ["Continental supplies"] = "", -- Continental_supplies ["Control pillars to score points."] = "Контрольюй стовпи щоб набрати очки.", +-- ["Core"] = "", -- Construction_Mode -- ["Corporationals"] = "", -- A_Classic_Fairytale:queen -- ["Corpsemonger"] = "", -- A_Classic_Fairytale:shadow -- ["Corpse Thrower"] = "", -- A_Classic_Fairytale:epil --- ["Crates Left:"] = "", -- User_Mission_-_RCPlane_Challenge +-- ["Cost"] = "", -- Construction_Mode +-- ["Crate Placement Tool"] = "", -- Construction_Mode + ["Crates Left:"] = "Залишилось ящиків:", -- User_Mission_-_RCPlane_Challenge +-- ["Cricket time: [Drop a fireable mine! ~ Will work if fired close to your hog & far away from enemy ~ 1 sec]"] = "", -- Continental_supplies +-- ["Current setting is "] = "", -- Gravity ["Cybernetic Empire"] = "Кібернетична Імперія", -- ["Cyborg. It's what the aliens call themselves."] = "", -- A_Classic_Fairytale:enemy -- ["Dahmer"] = "", -- A_Classic_Fairytale:backstab @@ -141,15 +182,19 @@ ["DAMMIT, ROOKIE!"] = "ЧОРТ ЗАБИРАЙ, САЛАГА!", ["Dangerous Ducklings"] = "Небезпечні Каченята", ["Deadweight"] = "Власна вага", +-- ["Decrease"] = "", -- Continental_supplies -- ["Defeat the cannibals"] = "", -- A_Classic_Fairytale:backstab -- ["Defeat the cannibals!|"] = "", -- A_Classic_Fairytale:united -- ["Defeat the cannibals!|Grenade hint: set the timer with [1-5], aim with [Up]/[Down] and hold [Space] to set power"] = "", -- A_Classic_Fairytale:shadow -- ["Defeat the cyborgs!"] = "", -- A_Classic_Fairytale:enemy +-- ["Defend your core from the enemy."] = "", -- Construction_Mode -- ["Defend yourself!|Hint: You can get tips on using weapons by moving your mouse over them in the weapon selection menu"] = "", -- A_Classic_Fairytale:shadow +-- ["Dematerializes weapons and equipment carried by enemy hedgehogs."] = "", -- Construction_Mode ["Demolition is fun!"] = "Руйнування це весело!", -- ["Dense Cloud"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united -- ["Dense Cloud must have already told them everything..."] = "", -- A_Classic_Fairytale:shadow ["Depleted Kamikaze!"] = "Виснажений Камікадзе!", +-- ["Desert Eagle"] = "", -- Construction_Mode, A_Space_Adventure:death02 -- ["Destroy him, Leaks A Lot! He is responsible for the deaths of many of us!"] = "", -- A_Classic_Fairytale:first_blood ["Destroy invaders to score points."] = "Знищіть загарбників, щоб набрати очки.", -- ["Destroy the targets!|Hint: Select the Shoryuken and hit [Space]|P.S. You can use it mid-air."] = "", -- A_Classic_Fairytale:first_blood @@ -168,9 +213,12 @@ -- ["Do you have any idea how valuable grass is?"] = "", -- A_Classic_Fairytale:enemy -- ["Do you think you're some kind of god?"] = "", -- A_Classic_Fairytale:enemy -- ["Dragon's Lair"] = "", -- A_Classic_Fairytale:dragon --- ["Drills"] = "", -- A_Classic_Fairytale:backstab +-- ["Drill Rocket"] = "", -- Construction_Mode +-- ["Drill Strike"] = "", -- Construction_Mode + ["Drills"] = "Дрелі", -- A_Classic_Fairytale:backstab ["Drone Hunter!"] = "Мисливець за Джмелями!", --- ["Drop a bomb: [drop some heroic wind that will turn into a bomb on impact]"] = "", -- Continental_supplies +-- ["Drop a bomb: [Drop some heroic wind that will turn into a bomb on impact]"] = "", -- Continental_supplies + ["Drowner"] = "Потопаючий", -- ["Dude, all the plants are gone!"] = "", -- A_Classic_Fairytale:family -- ["Dude, can you see Ramon and Spiky?"] = "", -- A_Classic_Fairytale:journey @@ -180,11 +228,15 @@ -- ["Dude, where are we?"] = "", -- A_Classic_Fairytale:backstab -- ["Dude, wow! I just had the weirdest high!"] = "", -- A_Classic_Fairytale:backstab -- ["Duration"] = "", -- Continental_supplies --- ["Dust storm: [Deals 20 damage to all enemies in the circle]"] = "", -- Continental_supplies +-- ["Dust storm: [Deals 15 damage to all enemies in the circle]"] = "", -- Continental_supplies + +-- ["Dynamite"] = "", -- Construction_Mode +-- ["Each turn is only ONE SECOND!"] = "", -- Frenzy ["Each turn you get 1-3 random weapons"] = "Кожного ходу ви отримуєте 1-3 випадкової зброї", ["Each turn you get one random weapon"] = "Кожного ходу ви отримуєте одну випадкову зброю", -- ["Eagle Eye"] = "", -- A_Classic_Fairytale:backstab --- ["Eagle Eye: [Blink to the impact ~ one shot]"] = "", -- Continental_supplies +-- ["Eagle Eye: [Blink to the impact ~ One shot]"] = "", -- Continental_supplies + -- ["Ear Sniffer"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:epil -- ["Elderbot"] = "", -- A_Classic_Fairytale:family -- ["Elimate your captor."] = "", -- User_Mission_-_The_Great_Escape @@ -203,12 +255,13 @@ -- ["[Enter]"] = "", -- ["Europe"] = "", -- Continental_supplies -- [" ever done to you?!"] = "", -- A_Classic_Fairytale:backstab --- ["Everyone knows this."] = "", -- A_Classic_Fairytale:enemy --- ["Every single time!"] = "", -- A_Classic_Fairytale:dragon + ["Everyone knows this."] = "Кожен це знає.", -- A_Classic_Fairytale:enemy + ["Every single time!"] = "КОжного разу!", -- A_Classic_Fairytale:dragon -- ["Everything looks OK..."] = "", -- A_Classic_Fairytale:enemy -- ["Exactly, man! That was my dream."] = "", -- A_Classic_Fairytale:backstab +-- ["Extra Damage"] = "", -- Construction_Mode +-- ["Extra Time"] = "", -- Construction_Mode -- ["Eye Chewer"] = "", -- A_Classic_Fairytale:journey --- ["INSANITY"] = "", -- Mutant -- ["Family Reunion"] = "", -- A_Classic_Fairytale:family ["Fastest lap: "] = "Найшвидша партія: ", ["Feeble Resistance"] = "Жалюгідні Повстанці", @@ -218,33 +271,41 @@ -- ["Femur Lover"] = "", -- A_Classic_Fairytale:shadow -- ["Fierce Competition!"] = "", -- Space_Invasion -- ["Fiery Water"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united +-- ["Filthy Blue"] = "", -- User_Mission_-_Dangerous_Ducklings -- ["Find your tribe!|Cross the lake!"] = "", -- A_Classic_Fairytale:dragon -- ["Finish your training|Hint: Animations can be skipped with the [Precise] key."] = "", -- A_Classic_Fairytale:first_blood --- ["Fire a mine: [Does what it says ~ Cant be dropped close to an enemy ~ 1 sec]"] = "", -- Continental_supplies + ["Fire"] = "Вогонь", -- ["First aid kits?!"] = "", -- A_Classic_Fairytale:united --- ["First Blood"] = "", -- A_Classic_Fairytale:first_blood -- ["FIRST BLOOD MUTATES"] = "", -- Mutant --- ["First Steps"] = "", -- A_Classic_Fairytale:first_blood + ["First Blood"] = "Перша кров", -- A_Classic_Fairytale:first_blood + ["First Steps"] = "Перші кроки", -- A_Classic_Fairytale:first_blood ["Flag captured!"] = "Прапор захоплено!", ["Flag respawned!"] = "Прапор відновлено!", ["Flag returned!"] = "Прапор повернено!", ["Flags, and their home base will be placed where each team ends their first turn."] = "Прапори і їх базування будуть розміщені там, де кожна команда закінчить її перший хід.", ["Flamer"] = "Вогнемет", --- ["Flaming Worm"] = "", -- A_Classic_Fairytale:backstab --- ["Flare: [fire up some bombs depending on hogs depending on hogs in the circle"] = "", -- Continental_supplies +-- ["Flamethrower"] = "", -- Construction_Mode + ["Flaming Worm"] = "Палаючий хробак", -- A_Classic_Fairytale:backstab + -- ["Flesh for Brainz"] = "", -- A_Classic_Fairytale:journey +-- ["Flying Saucer"] = "", -- Construction_Mode, Frenzy -- ["For improved features/stability, play 0.9.18+"] = "", -- WxW -- ["Free Dense Cloud and continue the mission!"] = "", -- A_Classic_Fairytale:journey +-- ["Freezer"] = "", -- Construction_Mode +-- ["FRENZY"] = "", -- Frenzy ["Friendly Fire!"] = "Дружній Вогонь!", ["fuel extended!"] = "пальне поповнене!", ["GAME BEGUN!!!"] = "ГРА ПОЧАЛАСЬ!!!", ["Game Modifiers: "] = "Модифікатори Гри: ", ["GAME OVER!"] = "КІНЕЦЬ ГРИ!", ["Game Started!"] = "Гра почалась!", --- ["Game? Was this a game to you?!"] = "", -- A_Classic_Fairytale:enemy + ["Game? Was this a game to you?!"] = "Гра? Це для тебе була лише гра?!", -- A_Classic_Fairytale:enemy -- ["GasBomb"] = "", -- Continental_supplies -- ["Gas Gargler"] = "", -- A_Classic_Fairytale:queen +-- ["General information"] = "", -- Continental_supplies +-- ["Generates power."] = "", -- Construction_Mode +-- ["Generator"] = "", -- Construction_Mode -- ["Get Dense Cloud out of the pit!"] = "", -- A_Classic_Fairytale:journey ["Get on over there and take him out!"] = "Залізь туди і прикінчи його!", -- ["Get on the head of the mole"] = "", -- A_Classic_Fairytale:first_blood @@ -255,67 +316,76 @@ -- ["Get your teammates out of their natural prison and save the princess!|Hint: Drilling holes should solve everything.|Hint: It might be a good idea to place a girder before starting to drill. Just saying.|Hint: All your hedgehogs need to be above the marked height!|Hint: Leaks A Lot needs to get really close to the princess!"] = "", -- A_Classic_Fairytale:family -- ["GG!"] = "", -- User_Mission_-_Rope_Knock_Challenge -- ["Gimme Bones"] = "", -- A_Classic_Fairytale:backstab +-- ["Girder"] = "", -- Construction_Mode +-- ["Girder Placement Mode"] = "", -- Construction_Mode -- ["Glark"] = "", -- A_Classic_Fairytale:shadow ["Goal"] = "Мета", ["GO! GO! GO!"] = "ДАВАЙ! ДАВАЙ! РУХАЙСЯ!", ["Good birdy......"] = "Гарна пташка......", -- ["Good Dude"] = "", -- User_Mission_-_The_Great_Escape -- ["Good idea, they'll never find us there!"] = "", -- A_Classic_Fairytale:united --- ["Good luck...or else!"] = "", -- A_Classic_Fairytale:journey + ["Good luck...or else!"] = "Удачі...або ще чогось!", -- A_Classic_Fairytale:journey ["Good luck out there!"] = "Удачі!", ["Good so far!"] = "Покищо добре!", ["Good to go!"] = "Так тримати!", --- ["Go on top of the flower"] = "", -- A_Classic_Fairytale:first_blood --- ["Go, quick!"] = "", -- A_Classic_Fairytale:backstab + ["Go on top of the flower"] = "Йди на верхівку квітки", -- A_Classic_Fairytale:first_blood + ["Go, quick!"] = "Йди, швидше!", -- A_Classic_Fairytale:backstab -- ["Gorkij"] = "", -- A_Classic_Fairytale:journey -- ["Go surf!"] = "", -- WxW ["GOTCHA!"] = "ПОПАВСЯ!", ["Grab Mines/Explosives"] = "Схопити Міни/Вибухівку", +-- ["Grants nearby hogs life-regeneration."] = "", -- Construction_Mode +-- ["Gravity"] = "", -- Gravity -- ["Great choice, Steve! Mind if I call you that?"] = "", -- A_Classic_Fairytale:shadow -- ["Great work! Now hit it with your Baseball Bat! |Tip: You can change weapon with 'Right Click'!"] = "", -- Basic_Training_-_Rope -- ["Great! You will be contacted soon for assistance."] = "", -- A_Classic_Fairytale:shadow --- ["Green lipstick bullet: [Is poisonous]"] = "", -- Continental_supplies + +-- ["Green lipstick bullet: [Poisonous, deals no damage]"] = "", -- Continental_supplies -- ["Greetings, "] = "", -- A_Classic_Fairytale:dragon -- ["Greetings, cloudy one!"] = "", -- A_Classic_Fairytale:shadow +-- ["Grenade"] = "", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 -- ["Grenade Training"] = "", -- Basic_Training_-_Grenade -- ["Grenadiers"] = "", -- Basic_Training_-_Grenade --- ["Guys, do you think there's more of them?"] = "", -- A_Classic_Fairytale:backstab --- ["HAHA!"] = "", -- A_Classic_Fairytale:enemy --- ["Haha!"] = "", -- A_Classic_Fairytale:united + ["Guys, do you think there's more of them?"] = "Хлопці, думаєте їх ще більше?", -- A_Classic_Fairytale:backstab ["Hahahaha!"] = "Хахахаха!", ["Haha, now THAT would be something!"] = "Хаха, от ЦЕ буде щось!", + ["HAHA!"] = "ХАХА!", -- A_Classic_Fairytale:enemy + ["Haha!"] = "Хаха!", -- A_Classic_Fairytale:united +-- ["Hammer"] = "", -- Construction_Mode, Continental_supplies -- ["Hannibal"] = "", -- A_Classic_Fairytale:epil [" Hapless Hogs left!"] = " Нещасних Їжаків лишилось!", ["Hapless Hogs"] = "Нещасні Їжаки", - -- [" HAS MUTATED"] = "", -- Mutant -- ["Hatless Jerry"] = "", -- A_Classic_Fairytale:queen -- ["Have no illusions, your tribe is dead, indifferent of your choice."] = "", -- A_Classic_Fairytale:shadow -- ["Have we ever attacked you first?"] = "", -- A_Classic_Fairytale:enemy +-- ["Healing Station"] = "", -- Construction_Mode +-- ["Health Crate Placement Mode"] = "", -- Construction_Mode ["Health crates extend your time."] = "Ящики зі здоров'ям продовжують ваш час.", -- ["Heavy Cannfantry"] = "", -- A_Classic_Fairytale:united ["Heavy"] = "В'ялий", -- ["Hedge-cogs"] = "", -- A_Classic_Fairytale:enemy --- ["Hedgehog projectile: [fire your hog like a Sticky Bomb]"] = "", -- Continental_supplies +-- ["Hedgehog projectile: [Fire your hog like a Sticky Bomb]"] = "", -- Continental_supplies + ["Hedgewars-Basketball"] = "Баскетбол Їжаками", ["Hedgewars-Knockball"] = "Бейсбол Їжаками", -- ["Hedgibal Lecter"] = "", -- A_Classic_Fairytale:backstab ["Heh, it's not that bad."] = "хех, це не так вже й погано.", +-- ["Hellish Handgrenade"] = "", -- Construction_Mode -- ["Hello again, "] = "", -- A_Classic_Fairytale:family -- ["Help me, Leaks!"] = "", -- A_Classic_Fairytale:journey --- ["Help me, please!!!"] = "", -- A_Classic_Fairytale:journey --- ["Help me, please!"] = "", -- A_Classic_Fairytale:journey + ["Help me, please!!!"] = "Допоможіть мені, будь ласка!!!", -- A_Classic_Fairytale:journey + ["Help me, please!"] = "Допоможіть мені, будь ласка!", -- A_Classic_Fairytale:journey -- ["He moves like an eagle in the sky."] = "", -- A_Classic_Fairytale:first_blood -- ["He must be in the village already."] = "", -- A_Classic_Fairytale:journey -- ["Here, let me help you!"] = "", -- A_Classic_Fairytale:backstab -- ["Here, let me help you save her!"] = "", -- A_Classic_Fairytale:family --- ["Here...pick your weapon!"] = "", -- A_Classic_Fairytale:first_blood --- ["Hero Team"] = "", -- User_Mission_-_The_Great_Escape --- ["He's so brave..."] = "", -- A_Classic_Fairytale:first_blood + ["Here...pick your weapon!"] = "Ось...бери зброю!", -- A_Classic_Fairytale:first_blood + ["Hero Team"] = "Команда героїв", -- User_Mission_-_The_Great_Escape + ["He's so brave..."] = "Він такий сміливий...", -- A_Classic_Fairytale:first_blood -- ["He won't be selling us out anymore!"] = "", -- A_Classic_Fairytale:backstab --- ["Hey, guys!"] = "", -- A_Classic_Fairytale:backstab --- ["Hey guys!"] = "", -- A_Classic_Fairytale:united --- ["Hey! This is cheating!"] = "", -- A_Classic_Fairytale:journey + ["Hey, guys!"] = "Гей, хлопці!", -- A_Classic_Fairytale:backstab + ["Hey guys!"] = "Гей хлопці!", -- A_Classic_Fairytale:united -- ["HIGHLANDER"] = "", -- Highlander -- ["Hightime"] = "", -- A_Classic_Fairytale:first_blood -- ["Hint: Double Jump - Press [Backspace] twice"] = "", -- A_Classic_Fairytale:first_blood @@ -331,7 +401,8 @@ ["Hmmm..."] = "Хмм...", -- ["Hogminator"] = "", -- A_Classic_Fairytale:family -- ["Hogs in sight!"] = "", -- Continental_supplies --- ["HOLY SHYTE!"] = "", -- Mutant + ["HOLY SHYTE!"] = "ОТ ЛАЙНО!", -- Mutant +-- ["Homing Bee"] = "", -- Construction_Mode -- ["Honest Lee"] = "", -- A_Classic_Fairytale:enemy ["Hooray!"] = "Урааа!", -- ["Hostage Situation"] = "", -- A_Classic_Fairytale:family @@ -342,7 +413,7 @@ -- ["However, if you fail to do so, she dies a most violent death, just like your friend! Muahahaha!"] = "", -- A_Classic_Fairytale:journey -- ["However, if you fail to do so, she dies a most violent death! Muahahaha!"] = "", -- A_Classic_Fairytale:journey -- ["However, my mates don't agree with me on letting you go..."] = "", -- A_Classic_Fairytale:dragon --- [" HP"] = "", -- Mutant + [" HP"] = " ЗД", -- Mutant ["Hunter"] = "Мисливець", --Bazooka, Shotgun, SniperRifle -- ["I believe there's more of them."] = "", -- A_Classic_Fairytale:backstab -- ["I can see you have been training diligently."] = "", -- A_Classic_Fairytale:first_blood @@ -365,7 +436,6 @@ -- ["If you get stuck, use your Desert Eagle or restart the mission!|"] = "", -- A_Classic_Fairytale:journey -- ["If you know what I mean..."] = "", -- A_Classic_Fairytale:shadow -- ["If you say so..."] = "", -- A_Classic_Fairytale:shadow - -- ["I guess you'll have to kill them."] = "", -- A_Classic_Fairytale:dragon -- ["I have come to make you an offering..."] = "", -- A_Classic_Fairytale:shadow -- ["I have no idea where that mole disappeared...Can you see it?"] = "", -- A_Classic_Fairytale:shadow @@ -388,7 +458,8 @@ -- ["I'm not sure about that!"] = "", -- A_Classic_Fairytale:united -- ["Impressive...you are still dry as the corpse of a hawk after a week in the desert..."] = "", -- A_Classic_Fairytale:first_blood -- ["I'm so scared!"] = "", -- A_Classic_Fairytale:united --- ["Incredible..."] = "", -- A_Classic_Fairytale:shadow +-- ["Increase"] = "", -- Continental_supplies + ["Incredible..."] = "Неймовірно...", -- A_Classic_Fairytale:shadow -- ["I need to find the others!"] = "", -- A_Classic_Fairytale:backstab -- ["I need to get to the other side of this island, fast!"] = "", -- A_Classic_Fairytale:journey -- ["I need to move the tribe!"] = "", -- A_Classic_Fairytale:united @@ -396,16 +467,18 @@ -- ["I need to warn the others."] = "", -- A_Classic_Fairytale:backstab -- ["In fact, you are the only one that's been acting strangely."] = "", -- A_Classic_Fairytale:backstab -- ["In order to get to the other side, you need to collect the crates first.|"] = "", -- A_Classic_Fairytale:dragon +-- ["INSANITY"] = "", -- Mutant ["Instructor"] = "Інструктор", -- 01#Boot_Camp, User_Mission_-_Dangerous_Ducklings --- ["Interesting idea, haha!"] = "", -- A_Classic_Fairytale:enemy + ["Interesting idea, haha!"] = "Цікава ідея, хаха!", -- A_Classic_Fairytale:enemy -- ["Interesting! Last time you said you killed a cannibal!"] = "", -- A_Classic_Fairytale:backstab -- ["In the meantime, take these and return to your \"friend\"!"] = "", -- A_Classic_Fairytale:shadow ["invaders destroyed"] = "Загарбників знищено", -- ["Invasion"] = "", -- A_Classic_Fairytale:united +-- ["Invulnerable"] = "", -- Construction_Mode -- ["I saw it with my own eyes!"] = "", -- A_Classic_Fairytale:shadow --- ["I see..."] = "", -- A_Classic_Fairytale:shadow -- ["I see you have already taken the leap of faith."] = "", -- A_Classic_Fairytale:first_blood -- ["I see you would like his punishment to be more...personal..."] = "", -- A_Classic_Fairytale:first_blood + ["I see..."] = "Ясно...", -- A_Classic_Fairytale:shadow -- ["I sense another wave of cannibals heading my way!"] = "", -- A_Classic_Fairytale:backstab -- ["I sense another wave of cannibals heading our way!"] = "", -- A_Classic_Fairytale:backstab -- ["I shouldn't have drunk that last pint."] = "", -- A_Classic_Fairytale:dragon @@ -444,6 +517,7 @@ -- ["Just kidding, none of you have died!"] = "", -- A_Classic_Fairytale:enemy -- ["Just on a walk."] = "", -- A_Classic_Fairytale:united -- ["Just wait till I get my hands on that trauma! ARGH!"] = "", -- A_Classic_Fairytale:family +-- ["Kamikaze"] = "", -- Construction_Mode ["Kamikaze Expert!"] = "Камікадзе Експерт!", ["Keep it up!"] = "Так тримати!", -- ["Kerguelen"] = "", -- Continental_supplies @@ -453,15 +527,18 @@ -- ["Kill the aliens!"] = "", -- A_Classic_Fairytale:dragon -- ["Kill the cannibal!"] = "", -- A_Classic_Fairytale:first_blood -- ["Kill the traitor...or spare his life!|Kill him or press [Precise]!"] = "", -- A_Classic_Fairytale:backstab +-- ["Land Sprayer"] = "", -- Construction_Mode +-- ["Laser Sight"] = "", -- Construction_Mode ["Last Target!"] = "Остання Ціль!", --- ["Leader"] = "", -- A_Classic_Fairytale:enemy -- ["Leaderbot"] = "", -- A_Classic_Fairytale:queen + ["Leader"] = "Лідер", -- A_Classic_Fairytale:enemy -- ["Leaks A Lot"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:first_blood, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united -- ["Leaks A Lot, depressed for killing his loved one, failed to save the village..."] = "", -- A_Classic_Fairytale:journey -- ["Leaks A Lot gave his life for his tribe! He should have survived!"] = "", -- A_Classic_Fairytale:first_blood -- ["Leaks A Lot must survive!"] = "", -- A_Classic_Fairytale:journey -- ["Led Heart"] = "", -- A_Classic_Fairytale:queen -- ["Lee"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen +-- ["left shift"] = "", -- Continental_supplies ["[Left Shift]"] = "[Лівий Shift]", -- ["Let a Continent provide your weapons!"] = "", -- Continental_supplies -- ["Let me test your skills a little, will you?"] = "", -- A_Classic_Fairytale:journey @@ -472,41 +549,56 @@ -- ["Let them have a taste of my fury!"] = "", -- A_Classic_Fairytale:backstab -- ["Let us help, too!"] = "", -- A_Classic_Fairytale:backstab -- ["Light Cannfantry"] = "", -- A_Classic_Fairytale:united +-- ["Limburger"] = "", -- Construction_Mode ["Listen up, maggot!!"] = "Слухай, хробак!", -- ["Little did they know that this hunt will mark them forever..."] = "", -- A_Classic_Fairytale:shadow ["Lively Lifeguard"] = "Жвавий Рятівник", --- ["Lonely Cries: [Rise the water if no hog is in the circle and deal 1 damage to all hogs]"] = "", -- Continental_supplies + +-- ["Lonely Cries: [Rise the water if no hog is in the circle and deal 7 damage to all enemy hogs]"] = "", -- Continental_supplies +-- ["Lonely Hog"] = "", -- ClimbHome -- ["Look, I had no choice!"] = "", -- A_Classic_Fairytale:backstab -- ["Look out! There's more of them!"] = "", -- A_Classic_Fairytale:backstab -- ["Look out! We're surrounded by cannibals!"] = "", -- A_Classic_Fairytale:enemy -- ["Looks like the whole world is falling apart!"] = "", -- A_Classic_Fairytale:enemy +-- ["Low Gravity"] = "", -- Construction_Mode, Frenzy -- ["Luckily, I've managed to snatch some of them."] = "", -- A_Classic_Fairytale:united -- ["LUDICROUS KILL"] = "", -- Mutant +-- ["Made it!"] = "", -- ClimbHome +-- ["- Massive weapon bonus on first turn"] = "", -- Continental_supplies -- ["May the spirits aid you in all your quests!"] = "", -- A_Classic_Fairytale:backstab -- ["Medicine: [Fire some exploding medicine that will heal all hogs effected by the explosion]"] = "", -- Continental_supplies -- ["MEGA KILL"] = "", -- Mutant -- ["Meiwes"] = "", -- A_Classic_Fairytale:backstab -- ["Mindy"] = "", -- A_Classic_Fairytale:united +-- ["Mine"] = "", -- Construction_Mode, Frenzy ["Mine Deployer"] = "Мінер", ["Mine Eater!"] = "Поїдач Мін!", +-- ["Mine Placement Mode"] = "", -- Construction_Mode ["|- Mines Time:"] = "|- Час детонування мін:", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork +-- ["Mine Strike"] = "", -- Construction_Mode ["MISSION FAILED"] = "МІСІЮ ПРОВАЛЕНО", -- User_Mission_-_Dangerous_Ducklings, User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork ["MISSION SUCCESSFUL"] = "МІСІЮ ВИКОНАНО", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork ["MISSION SUCCESS"] = "УСПІХ МІСІЇ", +-- ["Molotov Cocktail"] = "", -- Construction_Mode -- ["Molotov"] = "", -- Continental_supplies -- ["MONSTER KILL"] = "", -- Mutant -- ["More Natives"] = "", -- A_Classic_Fairytale:epil +-- ["Mortar"] = "", -- Construction_Mode, A_Space_Adventure:death02 ["Movement: [Up], [Down], [Left], [Right]"] = "Керування: [Вверх], [Вниз], [Вліво], [Вправо]", +-- ["Mudball"] = "", -- Construction_Mode ["Multi-shot!"] = "Мультипостріл!", -- ["Muriel"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen -- ["Muscle Dissolver"] = "", -- A_Classic_Fairytale:shadow -- ["-------"] = "", -- Mutant +-- ["Mutant"] = "", -- Mutant -- ["Nade Boy"] = "", -- Basic_Training_-_Grenade -- ["Name"] = "", -- A_Classic_Fairytale:queen ["Nameless Heroes"] = "Безіменні Герої", -- ["Nancy Screw"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:queen +-- ["Napalm"] = "", -- Construction_Mode -- ["Napalm rocket: [Fire a bomb with napalm!]"] = "", -- Continental_supplies -- ["Natives"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:first_blood, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united +-- ["Naughty Ninja"] = "", -- User_Mission_-_Dangerous_Ducklings ["New Barrels Per Turn"] = "Нових Бочок на Хід", ["NEW CLAN RECORD: "] = "НОВИЙ РЕКОРД КЛАНУ: ", ["NEW fastest lap: "] = "НОВА найшвидша партія: ", @@ -514,17 +606,19 @@ ["NEW RACE RECORD: "] = "НОВИЙ РЕКОРД ГОНКИ: ", ["Newton's Hammock"] = "Гамак Ньютона", -- ["Nicely done, meatbags!"] = "", -- A_Classic_Fairytale:enemy --- ["Nice work, "] = "", -- A_Classic_Fairytale:dragon --- ["Nice work!"] = "", -- A_Classic_Fairytale:enemy + ["Nice work, "] = "Гарна робота, ", -- A_Classic_Fairytale:dragon + ["Nice work!"] = "Гарна робота!", -- A_Classic_Fairytale:enemy -- ["Nilarian"] = "", -- A_Classic_Fairytale:queen +-- ["Nobody Laugh"] = "", -- User_Mission_-_Nobody_Laugh -- ["No, I came back to help you out..."] = "", -- A_Classic_Fairytale:shadow -- ["No...I wonder where they disappeared?!"] = "", -- A_Classic_Fairytale:journey --- ["Nom-Nom"] = "", -- A_Classic_Fairytale:journey --- ["NomNom"] = "", -- A_Classic_Fairytale:united + ["Nom-Nom"] = "Ням-Ням", -- A_Classic_Fairytale:journey + ["NomNom"] = "НямНям", -- A_Classic_Fairytale:united -- ["Nope. It was one fast mole, that's for sure."] = "", -- A_Classic_Fairytale:shadow -- ["No! Please, help me!"] = "", -- A_Classic_Fairytale:journey -- ["NORMAL"] = "", -- Continental_supplies --- ["North America"] = "", -- Continental_supplies +-- ["Normal players can only score points by killing the mutant."] = "", -- Mutant + ["North America"] = "Північна Америка", -- Continental_supplies -- ["Not all hogs are born equal."] = "", -- Highlander ["NOT ENOUGH WAYPOINTS"] = "НЕДОСТАТНЬО ТОЧОК ШЛЯХУ", -- ["Not now, Fiery Water!"] = "", -- A_Classic_Fairytale:backstab @@ -536,6 +630,7 @@ -- ["No. Where did he come from?"] = "", -- A_Classic_Fairytale:shadow -- ["Now how do I get on the other side?!"] = "", -- A_Classic_Fairytale:dragon -- ["No. You and the rest of the tribe are safer there!"] = "", -- A_Classic_Fairytale:backstab +-- ["Object Placement Tool"] = "", -- Construction_Mode -- ["Obliterate them!|Hint: You might want to take cover..."] = "", -- A_Classic_Fairytale:shadow -- ["Obstacle course"] = "", -- A_Classic_Fairytale:dragon -- ["Of course I have to save her. What did I expect?!"] = "", -- A_Classic_Fairytale:family @@ -552,41 +647,51 @@ -- ["Once upon a time, on an island with great natural resources, lived two tribes in heated conflict..."] = "", -- A_Classic_Fairytale:first_blood -- ["ONE HOG PER TEAM! KILLING EXCESS HEDGES"] = "", -- Mutant -- ["One tribe was peaceful, spending their time hunting and training, enjoying the small pleasures of life..."] = "", -- A_Classic_Fairytale:first_blood +-- ["on Skip"] = "", -- Continental_supplies -- ["Oops...I dropped them."] = "", -- A_Classic_Fairytale:united -- ["Open that crate and we will continue!"] = "", -- A_Classic_Fairytale:first_blood ["Operation Diver"] = "Операція Водолаз", ["Opposing Team: "] = "Команда-Противник: ", +-- ["or 'g=50, g2=150, period=4000' for gravity changing|from 50 to 150 and back with period of 4000 msec"] = "", -- Gravity -- ["Orlando Boom!"] = "", -- A_Classic_Fairytale:queen +-- ["Other kills don't give you points."] = "", -- Mutant -- ["Ouch!"] = "", -- User_Mission_-_Rope_Knock_Challenge -- ["Our tribe, our beautiful island!"] = "", -- A_Classic_Fairytale:enemy -- ["Parachute"] = "", -- Continental_supplies ["Pathetic Hog #%d"] = "Жалюгідний Їжак #%d", ["Pathetic Resistance"] = "Жалюгідний Опір", -- User_Mission_-_Bamboo_Thicket, User_Mission_-_Newton_and_the_Hammock +-- ["Penguin roar: [Deal 15 damage + 15% of your hogs health to all hogs around you and get 2/3 back]"] = "", -- Continental_supplies -- ["Perfect! Now try to get the next crate without hurting yourself!"] = "", -- A_Classic_Fairytale:first_blood ["Per-Hog Ammo"] = "Боєприпаси на їжака", --- ["- Per team weapons|- 9 weaponschemes|- Unique new weapons| |Select continent first round with the Weapon Menu or by ([switch/tab]=Increase,[precise/left shift]=Decrease) on Skip|Some weapons have a second option. Find them with [switch/tab]"] = "", -- Continental_supplies +-- ["Personal Portal Device"] = "", -- Construction_Mode +-- ["Per team weapons"] = "", -- Continental_supplies -- ["Pfew! That was close!"] = "", -- A_Classic_Fairytale:shadow --- ["Piñata bullet: [Contains some sweet candy!]"] = "", -- Continental_supplies +-- ["Piano Strike"] = "", -- Construction_Mode +-- ["Pickhammer"] = "", -- Construction_Mode + -- ["Pings left:"] = "", -- Space_Invasion - ["Place more waypoints using the 'Air Attack' weapon."] = "Розмістіть більше точок шляху використавши зброю 'Повітряна Атака'.", -- ["Planes Used:"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Planes Used"] = "", -- User_Mission_-_RCPlane_Challenge --- ["Play with me!"] = "", -- A_Classic_Fairytale:shadow + ["Play with me!"] = "Зіграй зі мною!", -- A_Classic_Fairytale:shadow -- ["Please place the way-point further from the waterline."] = "", -- Racer -- ["Please place the way-point in the open, within the map boundaries."] = "", -- Racer -- ["Please, stop releasing your \"smoke signals\"!"] = "", -- A_Classic_Fairytale:shadow -- ["Point Blank Combo!"] = "", -- Space_Invasion +-- ["POINTS"] = "", -- Mutant ["points"] = "очок", -- Control, CTF_Blizzard, Basic_Training_-_Bazooka, Basic_Training_-_Shotgun, Basic_Training_-_Sniper_Rifle ["Poison"] = "Смердюк", +-- ["Population"] = "", -- Continental_supplies -- ["Portal hint: one goes to the destination, and one is the entrance.|"] = "", -- A_Classic_Fairytale:dragon --- ["Portal mission"] = "", -- portal + ["Portal mission"] = "Портальна місія", -- portal ["Power Remaining"] = "Залишилось Енергії", ["Prepare yourself"] = "Приготуйся", +-- ["presice"] = "", -- Continental_supplies -- ["Press [Enter] to accept this configuration."] = "", -- WxW -- ["Press [Left] or [Right] to move around, [Enter] to jump"] = "", -- A_Classic_Fairytale:first_blood ["Press [Precise] to skip intro"] = "Натисніть [Приціл] щоб пропустити вступ", +-- ["Prestigious Pilot"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Private Novak"] = "", -- Basic_Training_-_Cluster_Bomb -- ["Protect yourselves!|Grenade hint: set the timer with [1-5], aim with [Up]/[Down] and hold [Space] to set power"] = "", -- A_Classic_Fairytale:shadow ["Race complexity limit reached."] = "Досягнута межа складності гонки.", @@ -595,25 +700,39 @@ -- ["Radar Ping"] = "", -- Space_Invasion -- ["Raging Buffalo"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united -- ["Ramon"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow +-- ["random in range from %i%% to %i%% with period of %i msec"] = "", -- Gravity +-- ["RC Plane"] = "", -- Construction_Mode -- ["RC PLANE TRAINING"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Really?! You thought you could harm me with your little toys?"] = "", -- A_Classic_Fairytale:shadow +-- ["Reflector Shield"] = "", -- Construction_Mode +-- ["Reflects enemy projectiles."] = "", -- Construction_Mode -- ["Regurgitator"] = "", -- A_Classic_Fairytale:backstab -- ["Reinforcements"] = "", -- A_Classic_Fairytale:backstab -- ["Remember: The rope only bend around objects, |if it doesn't hit anything it's always stright!"] = "", -- Basic_Training_-_Rope -- ["Remember this, pathetic animal: when the day comes, you will regret your blind loyalty!"] = "", -- A_Classic_Fairytale:shadow +-- ["REMOVED"] = "", -- Continental_supplies +-- ["Respawner"] = "", -- Construction_Mode +-- ["Resurrector"] = "", -- Construction_Mode +-- ["Resurrects dead hedgehogs."] = "", -- Construction_Mode [" - Return the enemy flag to your base to score | - First team to 3 captures wins | - You may only score when your flag is in your base | - Hogs will drop the flag if killed, or drowned | - Dropped flags may be returned or recaptured | - Hogs respawn when killed"] = " - Поверніть ворожий прапор на свою базу щоб заробити очко | - Виграє команда з трьома очками | - Ви можете заробити очко лише коли ваш прапор на вашій базі | - Їжак покине прапор якщо потоне чи буде вбитий | - Покинутий прапор можна повернути або захопити знов | - Їжаки відновлюються після смерті", -- ["Return to Leaks A Lot! If you get stuck, press [Precise] to try again!"] = "", -- A_Classic_Fairytale:shadow -- ["Righteous Beard"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:first_blood, A_Classic_Fairytale:queen, A_Classic_Fairytale:united +-- ["Rope"] = "", -- Construction_Mode -- ["ROPE-KNOCKING"] = "", -- User_Mission_-_Rope_Knock_Challenge +-- ["Rope to safety"] = "", -- ClimbHome -- ["Rope Training"] = "", -- Basic_Training_-_Rope -- ["Rot Molester"] = "", -- A_Classic_Fairytale:shadow ["Round Limit:"] = "Межа Раунду:", ["Round Limit"] = "Межа Раунду", ["Rounds Complete: "] = "Раундів Завершено: ", ["Rounds Complete"] = "Раундів Завершено", +-- ["Rubber Band"] = "", -- Construction_Mode +-- ["Rubber Placement Mode"] = "", -- Construction_Mode +-- ["RULES"] = "", -- Frenzy, Mutant ["RULES OF THE GAME [Press ESC to view]"] = "ПРАВИЛА ГРИ [Натисніть ESC для перегляду]", -- ["Rusty Joe"] = "", -- A_Classic_Fairytale:queen --- ["Sabotage: [Sabotage all hogs in the circle and deal ~10 dmg]"] = "", -- Continental_supplies +-- ["Sabotage/Flare: [Sabotage all hogs in the circle and deal ~1 dmg OR Fire a cluster up into the air]"] = "", -- Continental_supplies + -- ["Salivaslurper"] = "", -- A_Classic_Fairytale:united -- ["Salvation"] = "", -- A_Classic_Fairytale:family -- ["Salvation was one step closer now..."] = "", -- A_Classic_Fairytale:dragon @@ -623,9 +742,9 @@ -- ["Save the princess! All your hogs must survive!|Hint: Kill the cyborgs first! Use the ammo very carefully!|Hint: You might want to spare a girder for cover!"] = "", -- A_Classic_Fairytale:family -- ["Save the princess by collecting the crate in under 12 turns!"] = "", -- A_Classic_Fairytale:journey -- ["Scalp Muncher"] = "", -- A_Classic_Fairytale:backstab --- ["Score"] = "", -- Mutant ["SCORE"] = "РАХУНОК", --- ["Scream from a Walrus: [Deal 20 damage + 10% of your hogs health to all hogs around you and get half back]"] = "", -- Continental_supplies + ["Score"] = "Рахунок", -- Mutant + ["sec"] = "сек", -- CTF_Blizzard, TrophyRace, Basic_Training_-_Bazooka, Basic_Training_-_Shotgun, Basic_Training_-_Sniper_Rifle, User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork, Capture_the_Flag -- ["Seduction"] = "", -- Continental_supplies -- ["Seems like every time you take a \"walk\", the enemy find us!"] = "", -- A_Classic_Fairytale:backstab @@ -633,8 +752,11 @@ ["See ya!"] = "Побачимося!", -- ["Segmentation Paul"] = "", -- A_Classic_Fairytale:dragon -- ["Select continent!"] = "", -- Continental_supplies +-- ["Select continent first round with the Weapon Menu or by"] = "", -- Continental_supplies -- ["Select difficulty: [Left] - easier or [Right] - harder"] = "", -- A_Classic_Fairytale:first_blood ["selected!"] = "вибрано!", +-- ["Set period to negative value for random gravity"] = "", -- Gravity +-- ["Setup:|'g=150', where 150 is 150% of normal gravity"] = "", -- Gravity -- ["... share your beauty with the world every morning, my princess!"] = "", -- A_Classic_Fairytale:journey -- ["She's behind that tall thingy."] = "", -- A_Classic_Fairytale:family ["Shield boosted! +30 power"] = "Щит підсилено! +30 сили", @@ -645,16 +767,21 @@ ["Shield OFF:"] = "Щит Вимкнено:", ["Shield ON:"] = "Щит Ввімкнено:", ["Shield Seeker!"] = "Шукач Щита!", --- ["Shotgun"] = "", -- Continental_supplies +-- ["Shoryuken"] = "", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 ["Shotgun Team"] = "Команда Рушниць", ["Shotgun Training"] = "Тренування з рушницею", + ["Shotgun"] = "Рушниця", -- Continental_supplies ["shots remaining."] = "пострілів залишилось.", ["Silly"] = "Дурник", +-- ["SineGun"] = "", -- Construction_Mode ["Sinky"] = "Любимчик", -- ["Sirius Lee"] = "", -- A_Classic_Fairytale:enemy ["%s is out and Team %d|scored a penalty!| |Score:"] = "%s вибув і Команда %d|отримала штраф!| |Рахунок:", -- Basketball, Knockball ["%s is out and Team %d|scored a point!| |Score:"] = "%s вибув і Команда %d|заробила очко!| |Рахунок:", -- Basketball, Knockball -- ["Slippery"] = "", -- A_Classic_Fairytale:journey +-- ["Slot"] = "", -- Frenzy +-- ["Slot keys save time! (F1-F10 by default)"] = "", -- Frenzy +-- ["SLOTS"] = "", -- Frenzy -- ["Smith 0.97"] = "", -- A_Classic_Fairytale:enemy -- ["Smith 0.98"] = "", -- A_Classic_Fairytale:enemy -- ["Smith 0.99a"] = "", -- A_Classic_Fairytale:enemy @@ -666,7 +793,8 @@ ["Sniper Training"] = "Снайперське тренування", -- ["Sniperz"] = "", -- ["So humiliating..."] = "", -- A_Classic_Fairytale:first_blood --- ["South America"] = "", -- Continental_supplies +-- ["Some weapons have a second option. Find them with"] = "", -- Continental_supplies + ["South America"] = "Південна Америка", -- Continental_supplies -- ["So? What will it be?"] = "", -- A_Classic_Fairytale:shadow -- ["Spawn the crate, and attack!"] = "", -- WxW -- ["Special Weapons:"] = "", -- Continental_supplies @@ -674,28 +802,46 @@ -- ["Spleenlover"] = "", -- A_Classic_Fairytale:united ["Sponge"] = "Губка", ["Spooky Tree"] = "Примарне Дерево", +-- ["Sprite Placement Mode"] = "", -- Construction_Mode +-- ["Sprite Testing Mode"] = "", -- Construction_Mode ["STATUS UPDATE"] = "ОНОВЛЕННЯ СТАНУ", -- GaudyRacer, Space_Invasion -- ["Steel Eye"] = "", -- A_Classic_Fairytale:queen -- ["Step By Step"] = "", -- A_Classic_Fairytale:first_blood -- ["Steve"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen -- ["Sticky Mine"] = "", -- Continental_supplies +-- ["Sticky Mine Placement Mode"] = "", -- Construction_Mode -- ["Stronglings"] = "", -- A_Classic_Fairytale:shadow --- ["Structure"] = "", -- Continental_supplies + +-- ["Structure Placement Mode"] = "", -- Construction_Mode +-- ["Structure Placement Tool"] = "", -- Construction_Mode +-- ["Sundaland"] = "", -- Continental_supplies -- ["Super Weapons"] = "", -- WxW +-- ["Support Station"] = "", -- Construction_Mode -- ["Surf Before Crate"] = "", -- WxW -- ["Surfer! +15 points!"] = "", -- Space_Invasion -- ["Surfer!"] = "", -- WxW -- ["Survive!|Hint: Cinematics can be skipped with the [Precise] key."] = "", -- A_Classic_Fairytale:shadow -- ["Swing, Leaks A Lot, on the wings of the wind!"] = "", -- A_Classic_Fairytale:first_blood +-- ["switch"] = "", -- Continental_supplies ["Switched to "] = "Перейшов до ", +-- ["Switch Hog"] = "", -- Construction_Mode -- ["Syntax Errol"] = "", -- A_Classic_Fairytale:dragon ["s|"] = "с|", ["s"] = "с", -- GaudyRacer, Space_Invasion +-- ["tab"] = "", -- Continental_supplies +-- ["Tagging Mode"] = "", -- Construction_Mode -- ["Talk about mixed signals..."] = "", -- A_Classic_Fairytale:dragon +-- ["Tardis"] = "", -- Construction_Mode +-- ["Target Placement Mode"] = "", -- Construction_Mode ["Team %d: "] = "Команда %d: ", ["Team Scores"] = "Очки Команди", -- Control, Space_Invasion +-- ["Teleporation Node"] = "", -- Construction_Mode +-- ["Teleportation Mode"] = "", -- Construction_Mode +-- ["Teleportation Node"] = "", -- Construction_Mode +-- ["Teleport"] = "", -- Construction_Mode, Frenzy -- ["Teleport hint: just use the mouse to select the destination!"] = "", -- A_Classic_Fairytale:dragon --- ["Thanks!"] = "", -- A_Classic_Fairytale:family +-- ["Teleport Unsuccessful. Please teleport within a clan teleporter's sphere of influence."] = "", -- Construction_Mode + ["Thanks!"] = "Дякую!", -- A_Classic_Fairytale:family -- ["Thank you, my hero!"] = "", -- A_Classic_Fairytale:family -- ["Thank you, oh, thank you, Leaks A Lot!"] = "", -- A_Classic_Fairytale:journey -- ["Thank you, oh, thank you, my heroes!"] = "", -- A_Classic_Fairytale:journey @@ -711,6 +857,7 @@ ["That was pointless."] = "Це було безглуздо.", -- ["The answer is...entertaintment. You'll see what I mean."] = "", -- A_Classic_Fairytale:backstab -- ["The anti-portal zone is all over the floor, and I have nothing to kill him...Droping something could hurt him enough to kill him..."] = "", -- portal +-- ["The Bottom Feeder can score points by killing anyone."] = "", -- Mutant -- ["The Bull's Eye"] = "", -- A_Classic_Fairytale:first_blood -- ["The caves are well hidden, they won't find us there!"] = "", -- A_Classic_Fairytale:united -- ["The Crate Frenzy"] = "", -- A_Classic_Fairytale:first_blood @@ -720,20 +867,26 @@ -- ["The Enemy Of My Enemy"] = "", -- A_Classic_Fairytale:enemy -- ["The First Blood"] = "", -- A_Classic_Fairytale:first_blood -- ["The First Encounter"] = "", -- A_Classic_Fairytale:shadow +-- ["The first player to kill someone becomes the Mutant."] = "", -- Mutant ["The flag will respawn next round."] = "Прапор відновиться в наступному раунді.", -- ["The food bites back"] = "", -- A_Classic_Fairytale:backstab -- ["The giant umbrella from the last crate should help break the fall."] = "", -- A_Classic_Fairytale:first_blood -- ["The Great Escape"] = "", -- User_Mission_-_The_Great_Escape +-- ["The Great Hog in the sky sees your sadness and grants you a boon."] = "", -- Construction_Mode -- ["The guardian"] = "", -- A_Classic_Fairytale:shadow -- ["The Individualist"] = "", -- A_Classic_Fairytale:shadow -- ["Their buildings were very primitive back then, even for an uncivilised island."] = "", -- A_Classic_Fairytale:united -- ["The Journey Back"] = "", -- A_Classic_Fairytale:journey -- ["The Leap of Faith"] = "", -- A_Classic_Fairytale:first_blood -- ["The Moonwalk"] = "", -- A_Classic_Fairytale:journey +-- ["The Mutant has super-weapons and a lot of health."] = "", -- Mutant +-- ["The Mutant loses health quickly if he doesn't keep scoring kills."] = "", -- Mutant ["The Nameless One"] = "Безіменний", -- ["The next one is pretty hard! |Tip: You have to do multiple swings!"] = "", -- Basic_Training_-_Rope -- ["Then how do they keep appearing?"] = "", -- A_Classic_Fairytale:shadow -- ["The other one were all cannibals, spending their time eating the organs of fellow hedgehogs..."] = "", -- A_Classic_Fairytale:first_blood +-- ["The player with least points (or most deaths) becomes the Bottom Feeder."] = "", -- Mutant +-- ["There are a variety of structures available to aid you."] = "", -- Construction_Mode -- ["There must be a spy among us!"] = "", -- A_Classic_Fairytale:backstab -- ["There's more of them? When did they become so hungry?"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united -- ["There's nothing more satisfying for me than seeing you share your beauty with the world every morning, my princess!"] = "", -- A_Classic_Fairytale:journey @@ -789,10 +942,10 @@ -- ["To the caves..."] = "", -- A_Classic_Fairytale:united ["Toxic Team"] = "Токсична Команда", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork ["TRACK COMPLETED"] = "ТРАСУ ПРОЙДЕНО", - ["TRACK FAILED!"] = "ТРАСУ НЕ ПРОЙДЕНО!", --- ["training"] = "", -- portal + + ["training"] = "тренування", -- portal -- ["Traitors"] = "", -- A_Classic_Fairytale:epil --- ["Tribe"] = "", -- A_Classic_Fairytale:backstab + ["Tribe"] = "Плем'я", -- A_Classic_Fairytale:backstab ["TrophyRace"] = "Погоня за Трофеєм", -- ["Try to protect the chief! You won't lose if he dies, but it is advised that he survives."] = "", -- A_Classic_Fairytale:united ["T_T"] = "Ааааа!!!", @@ -806,6 +959,7 @@ -- ["ULTRA KILL"] = "", -- Mutant -- ["Under Construction"] = "", -- A_Classic_Fairytale:shadow -- ["Unexpected Igor"] = "", -- A_Classic_Fairytale:dragon +-- ["Unique new weapons"] = "", -- Continental_supplies -- ["Unit 0x0007"] = "", -- A_Classic_Fairytale:family -- ["Unit 334a$7%;.*"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united ["Unit 3378"] = "Об'єкт 3378", @@ -820,11 +974,14 @@ -- ["Use it wisely!"] = "", -- A_Classic_Fairytale:dragon -- ["Use it with precaution!"] = "", -- A_Classic_Fairytale:first_blood ["User Challenge"] = "Дуель між користувачами", - +-- ["Use the air-attack weapons and the arrow keys to select structures."] = "", -- Construction_Mode -- ["Use the portal gun to get to the next crate, then use the new gun to get to the final destination!|"] = "", -- A_Classic_Fairytale:dragon -- ["Use the rope to get on the head of the mole, young one!"] = "", -- A_Classic_Fairytale:first_blood -- ["Use the rope to knock your enemies to their doom."] = "", -- User_Mission_-_Rope_Knock_Challenge +-- ["Use your ready time to think."] = "", -- Frenzy ["Use your rope to get from start to finish as fast as you can!"] = "Скористайся мотузкою щоб якнайшвидше досягнути фінішу!", +-- ["Utility Crate Placement Mode"] = "", -- Construction_Mode +-- ["Vampirism"] = "", -- Construction_Mode -- ["Vedgies"] = "", -- A_Classic_Fairytale:journey -- ["Vegan Jack"] = "", -- A_Classic_Fairytale:enemy -- ["Victory!"] = "", -- Basic_Training_-_Rope @@ -836,10 +993,14 @@ -- ["Wannabe Flyboys"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Wannabe Shoppsta"] = "", -- User_Mission_-_Rope_Knock_Challenge -- ["Watch your steps, young one!"] = "", -- A_Classic_Fairytale:first_blood +-- ["Watermelon Bomb"] = "", -- Construction_Mode ["Waypoint placed."] = "Точка шляху розміщена.", ["Way-Points Remaining"] = "Залишилось Точок", -- ["Weaklings"] = "", -- A_Classic_Fairytale:shadow -- ["We all know what happens when you get frightened..."] = "", -- A_Classic_Fairytale:first_blood +-- ["Weapon Crate Placement Mode"] = "", -- Construction_Mode +-- ["Weapon Filter"] = "", -- Construction_Mode +-- ["weaponschemes"] = "", -- Continental_supplies -- ["Weapons reset."] = "", -- Highlander ["Weapons Reset"] = "Скидання Зброї", -- ["We are indeed."] = "", -- A_Classic_Fairytale:backstab @@ -892,8 +1053,7 @@ -- ["Where do you get that?!"] = "", -- A_Classic_Fairytale:enemy -- ["Where have you been?!"] = "", -- A_Classic_Fairytale:backstab -- ["Where have you been?"] = "", -- A_Classic_Fairytale:united --- ["? Why?"] = "", -- A_Classic_Fairytale:backstab --- ["Why "] = "", -- A_Classic_Fairytale:backstab +-- ["Whip"] = "", -- Construction_Mode -- ["! Why?!"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united -- ["Why are you doing this?"] = "", -- A_Classic_Fairytale:journey -- ["Why are you helping us, uhm...?"] = "", -- A_Classic_Fairytale:family @@ -903,11 +1063,15 @@ -- ["Why do you want to take over our island?"] = "", -- A_Classic_Fairytale:enemy -- ["Why me?!"] = "", -- A_Classic_Fairytale:backstab -- ["Why would they do this?"] = "", -- A_Classic_Fairytale:backstab + ["? Why?"] = "? Чому?", -- A_Classic_Fairytale:backstab + ["Why "] = "Чому ", -- A_Classic_Fairytale:backstab -- ["- Will Get 1-3 random weapons"] = "", -- Continental_supplies --- ["- Will refresh Parachute each turn."] = "", -- Continental_supplies --- ["- Will refresh portalgun each turn."] = "", -- Continental_supplies +-- ["- Will give you an airstrike every fifth turn."] = "", -- Continental_supplies +-- ["- Will give you a parachute every second turn."] = "", -- Continental_supplies + + ["Will this ever end?"] = "Це коли-небудь закінчиться?", --- ["WINNER IS "] = "", -- Mutant + ["WINNER IS "] = "ПЕРЕМІГ ", -- Mutant ["WINNING TIME: "] = "ЧАС ВИГРАШУ: ", -- ["Wise Oak"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen -- ["With Dense Cloud on the land of shadows, I'm the village's only hope..."] = "", -- A_Classic_Fairytale:journey @@ -915,15 +1079,16 @@ -- ["Worry not, for it is a peaceful animal! There is no reason to be afraid..."] = "", -- A_Classic_Fairytale:first_blood -- ["Wow, what a dream!"] = "", -- A_Classic_Fairytale:backstab -- ["Y3K1337"] = "", -- A_Classic_Fairytale:journey, A_Classic_Fairytale:shadow --- ["Yay, we won!"] = "", -- A_Classic_Fairytale:enemy + ["Yay, we won!"] = "Ура, ми перемогли!", -- A_Classic_Fairytale:enemy -- ["Y Chwiliad"] = "", -- A_Classic_Fairytale:dragon -- ["Yeah...I think it's a 'he', lol."] = "", -- A_Classic_Fairytale:shadow -- ["Yeah, sure! I died. Hillarious!"] = "", -- A_Classic_Fairytale:backstab -- ["Yeah, take that!"] = "", -- A_Classic_Fairytale:dragon -- ["Yeah? Watcha gonna do? Cry?"] = "", -- A_Classic_Fairytale:journey --- ["Yes!"] = "", -- A_Classic_Fairytale:enemy -- ["Yes, yeees! You are now ready to enter the real world!"] = "", -- A_Classic_Fairytale:first_blood + ["Yes!"] = "Так!", -- A_Classic_Fairytale:enemy -- ["Yo, dude, we're here, too!"] = "", -- A_Classic_Fairytale:family +-- ["You are far from home, and the water is rising, climb up as high as you can!"] = "", -- ClimbHome -- ["You are given the chance to turn your life around..."] = "", -- A_Classic_Fairytale:shadow -- ["You are playing with our lives here!"] = "", -- A_Classic_Fairytale:enemy -- ["! You bastards!"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united @@ -954,17 +1119,19 @@ -- ["You killed my father, you monster!"] = "", -- A_Classic_Fairytale:backstab -- ["You know...taking a stroll."] = "", -- A_Classic_Fairytale:backstab -- ["You know what? I don't even regret anything!"] = "", -- A_Classic_Fairytale:backstab --- ["You'll see what I mean!"] = "", -- A_Classic_Fairytale:enemy + ["You'll see what I mean!"] = "Ти побачиш про що я!", -- A_Classic_Fairytale:enemy -- ["You may only attack from a rope!"] = "", -- WxW +-- ["You may only spawn 5 crates per turn."] = "", -- Construction_Mode +-- ["You may only use 1 Extra Time per turn."] = "", -- Construction_Mode -- ["You meatbags are pretty slow, you know!"] = "", -- A_Classic_Fairytale:enemy -- ["You might want to find a way to instantly kill arriving cannibals!"] = "", -- A_Classic_Fairytale:backstab -- ["Young one, you are telling us that they can instantly change location without a shaman?"] = "", -- A_Classic_Fairytale:united -- ["You probably know what to do next..."] = "", -- A_Classic_Fairytale:first_blood -- ["Your deaths will be avenged, cannibals!"] = "", -- A_Classic_Fairytale:enemy -- ["Your death will not be in vain, Dense Cloud!"] = "", -- A_Classic_Fairytale:shadow --- ["You're...alive!? But we saw you die!"] = "", -- A_Classic_Fairytale:backstab + ["You're...alive!? But we saw you die!"] = "Ти...живий!? Але ми бачили як ти помер!", -- A_Classic_Fairytale:backstab -- ["You're a pathetic liar!"] = "", -- A_Classic_Fairytale:backstab --- ["You're funny!"] = "", -- A_Classic_Fairytale:journey + ["You're funny!"] = "А ти кумедний!", -- A_Classic_Fairytale:journey -- ["You're getting pretty good! |Tip: When you shorten you rope you move faster! |and when you lengthen it you move slower"] = "", -- Basic_Training_-_Rope -- ["You're pathetic! You are not worthy of my attention..."] = "", -- A_Classic_Fairytale:shadow -- ["You're probably wondering why I bought you back..."] = "", -- A_Classic_Fairytale:backstab @@ -976,10 +1143,12 @@ ["You've failed. Try again."] = "Спроба не вдалась. Спробуйте знов.", ["You've reached the goal!| |Time: "] = "Ви досягли мети!| |Час: ", -- ["You will be avenged!"] = "", -- A_Classic_Fairytale:shadow +-- ["- You will recieve 2-4 weapons on each kill! (Even on own hogs)"] = "", -- Continental_supplies -- ["You won't believe what happened to me!"] = "", -- A_Classic_Fairytale:backstab -- ["Yuck! I bet they'll keep worshipping her even after I save the village!"] = "", -- A_Classic_Fairytale:family -- ["Zealandia"] = "", -- Continental_supplies ["'Zooka Team"] = "Команда 'Zooka", -- ["Zork"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen + ["Ей! Так не чесно!"] = "", -- A_Classic_Fairytale:journey ["!!!"] = "Я!", } diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/uk.txt --- a/share/hedgewars/Data/Locale/uk.txt Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/uk.txt Tue Nov 10 20:43:13 2015 +0100 @@ -56,6 +56,9 @@ 00:53=Будка Часу ; 00:54=Структура 00:54=Земляний Спрей +00:55=Заморозка +00:56=Дровокол +00:57=Гумка 01:00=Вперед до перемоги! 01:01=Нічия @@ -72,6 +75,14 @@ 01:12=Останній раунд до Раптової Смерті! 01:13=%1 раундів до Раптової Смерті! 01:14=Приготуйся, %1! +01:15=Трохи +01:16=Низько +01:17=Звичайно +01:18=Високо +01:19=Екстремально +01:20=%1 Відскок +01:21=Звук вимкнено +01:22=AFK режим ; Event messages ; Hog (%1) died @@ -288,6 +299,9 @@ 03:53=Тип 40 ;03:54=Збудуй щось 03:54=Утиліта +03:55=Холодніше не буває! +03:56=Пограйся з цим +03:57=Утиліта ; Weapon Descriptions (use | as line breaks) 04:00=Атакуй ворогів використовуючи просту гранату.|Вона вибухне як тільки її таймер доходить до нуля.|1-5: Вистав таймер гранати|Атака: Утримуй щоб метнути сильніше @@ -346,6 +360,9 @@ 04:53=Здійсни подорож крізь час та простір,|залишивши товаришів битись далі самим.|Будь готовий повернутись в кожну мить,|або до Раптової смерті або до їх поразки.|Відмова. Не працює в Раптовій Смерті,|якщо ти один, або якщо ти Король. ;04:54=НЕЗАВЕРШЕНО 04:54=Розпили потік лепких пластівців.|будуй мости, хорони ворогів, перекривай тунелі.|Стеж щоб на тебе не впала жодна з них! +04:55=Льодовиковий період повертається!|Заморозь їжаків, нехай послизнуться або|врятуй себе від потопання заморозивши воду.|Атака: Стріляй +04:56=Ти можеш кинути два дровооли у ворога,|блокувати проходи і тунелі і навіть дертись догори!|Вважай! Гра з ножами небезпечна.|Атака: Утримуй щоб кинути сильніше (двічі) +04:57=Збудуй еластичну гумову перегородку,|від якої їжаки та інші речі|відпружинюють без пошкоджень.|Вліво/Вправо: Змінюй напрямок перегородки|Курсор: Встанови перегородку в можливе положення ; Game goal strings 05:00=Режими Гри diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Locale/zh_CN.lua --- a/share/hedgewars/Data/Locale/zh_CN.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Locale/zh_CN.lua Tue Nov 10 20:43:13 2015 +0100 @@ -3,6 +3,10 @@ -- ["..."] = "", -- ["011101000"] = "", -- A_Classic_Fairytale:dragon -- ["011101001"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:family, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united +-- ["+1 to a Bottom Feeder for killing anyone"] = "", -- Mutant +-- ["+1 to a Mutant for killing anyone"] = "", -- Mutant +-- ["-1 to anyone for a suicide"] = "", -- Mutant +-- ["+2 for becoming a Mutant"] = "", -- Mutant -- ["30 minutes later..."] = "", -- A_Classic_Fairytale:shadow -- ["About a month ago, a cyborg came and told us that you're the cannibals!"] = "", -- A_Classic_Fairytale:enemy -- ["Accuracy Bonus!"] = "", @@ -12,17 +16,27 @@ -- ["???"] = "", -- A_Classic_Fairytale:backstab -- ["Actually, you aren't worthy of life! Take this..."] = "", -- A_Classic_Fairytale:shadow -- ["A cy-what?"] = "", -- A_Classic_Fairytale:enemy +-- ["Advanced Repositioning Mode"] = "", -- Construction_Mode -- ["Adventurous"] = "", -- A_Classic_Fairytale:journey +-- ["a frenetic Hedgewars mini-game"] = "", -- Frenzy -- ["Africa"] = "", -- Continental_supplies -- ["After Leaks A Lot betrayed his tribe, he joined the cannibals..."] = "", -- A_Classic_Fairytale:first_blood -- ["After the shock caused by the enemy spy, Leaks A Lot and Dense Cloud went hunting to relax."] = "", -- A_Classic_Fairytale:shadow -- ["Again with the 'cannibals' thing!"] = "", -- A_Classic_Fairytale:enemy +-- ["Aggressively removes enemy hedgehogs."] = "", -- Construction_Mode -- ["a Hedgewars challenge"] = "", -- User_Mission_-_RCPlane_Challenge, User_Mission_-_Rope_Knock_Challenge -- ["a Hedgewars mini-game"] = "", -- Space_Invasion, The_Specialists +-- ["a Hedgewars tag game"] = "", -- Mutant +-- ["AHHh, home sweet home. Made it in %d seconds."] = "", -- ClimbHome ["Aiming Practice"] = "瞄准练习", --火箭筒、霰弹枪、狙击枪 +-- ["Air Attack"] = "", -- Construction_Mode -- ["A leap in a leap"] = "", -- A_Classic_Fairytale:first_blood -- ["A little gift from the cyborgs"] = "", -- A_Classic_Fairytale:shadow -- ["All gone...everything!"] = "", -- A_Classic_Fairytale:enemy +-- ["Allows free teleportation between other nodes."] = "", -- Construction_Mode +-- ["Allows placement of girders, rubber-bands, mines, sticky mines and barrels."] = "", -- Construction_Mode +-- ["Allows placement of structures."] = "", -- Construction_Mode +-- ["Allows the placement of weapons, utiliites, and health crates."] = "", -- Construction_Mode -- ["All right, we just need to get to the other side of the island!"] = "", -- A_Classic_Fairytale:journey -- ["All walls touched!"] = "", -- WxW -- ["Ammo"] = "", @@ -37,8 +51,11 @@ -- ["And so they discovered that cyborgs weren't invulnerable..."] = "", -- A_Classic_Fairytale:journey -- ["And where's all the weed?"] = "", -- A_Classic_Fairytale:dragon -- ["And you believed me? Oh, god, that's cute!"] = "", -- A_Classic_Fairytale:journey --- ["Anno 1032: [The explosion will make a strong push ~ wide range, wont affect hogs close to the target]"] = "", -- Continental_supplies +-- ["Anno 1032: [The explosion will make a strong push ~ Wide range, wont affect hogs close to the target]"] = "", -- Continental_supplies + -- ["Antarctica"] = "", -- Continental_supplies +-- ["Antarctic summer: - Will give you one girder/mudball and two sineguns/portals every fourth turn."] = "", -- Continental_supplies +-- ["Area"] = "", -- Continental_supplies -- ["Are we there yet?"] = "", -- A_Classic_Fairytale:shadow -- ["Are you accusing me of something?"] = "", -- A_Classic_Fairytale:backstab -- ["Are you saying that many of us have died for your entertainment?"] = "", -- A_Classic_Fairytale:enemy @@ -58,27 +75,35 @@ -- ["[Backspace]"] = "", -- ["Backstab"] = "", -- A_Classic_Fairytale:backstab -- ["Bad Team"] = "", -- User_Mission_-_The_Great_Escape +-- ["Ballgun"] = "", -- Construction_Mode -- ["Bamboo Thicket"] = "", -- ["Barrel Eater!"] = "", -- ["Barrel Launcher"] = "", +-- ["Barrel Placement Mode"] = "", -- Construction_Mode +-- ["Baseball Bat"] = "", -- Construction_Mode -- ["Baseballbat"] = "", -- Continental_supplies ["Bat balls at your enemies and|push them into the sea!"] = "发射棒球将敌人击打入水", ["Bat your opponents through the|baskets and out of the map!"] = "把敌人击出场地——对准栏框", +-- ["Bazooka"] = "", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 ["Bazooka Training"] = "火箭筒训练", -- ["Beep Loopers"] = "", -- A_Classic_Fairytale:queen ["Best laps per team: "] = "每一队最佳速度:", -- ["Best Team Times: "] = "", -- ["Beware, though! If you are slow, you die!"] = "", -- A_Classic_Fairytale:dragon +-- ["Bio-Filter"] = "", -- Construction_Mode -- ["Biomechanic Team"] = "", -- A_Classic_Fairytale:family +-- ["Birdy"] = "", -- Construction_Mode -- ["Blender"] = "", -- A_Classic_Fairytale:family -- ["Bloodpie"] = "", -- A_Classic_Fairytale:backstab -- ["Bloodrocutor"] = "", -- A_Classic_Fairytale:shadow -- ["Bloodsucker"] = "", -- A_Classic_Fairytale:shadow ["Bloody Rookies"] = "雉儿飞", -- 01#Boot_Camp, User_Mission_-_Dangerous_Ducklings, User_Mission_-_Diver, User_Mission_-_Spooky_Tree +-- ["Blowtorch"] = "", -- Construction_Mode, Frenzy +-- ["Blue Team"] = "", -- User_Mission_-_Dangerous_Ducklings -- ["Bone Jackson"] = "", -- A_Classic_Fairytale:backstab -- ["Bonely"] = "", -- A_Classic_Fairytale:shadow +-- ["BOOM!"] = "", -- ["Boom!"] = --- ["BOOM!"] = "", -- ["Boss defeated!"] = "", -- ["Boss Slayer!"] = "", -- ["Brain Blower"] = "", -- A_Classic_Fairytale:journey @@ -88,6 +113,7 @@ -- ["Brain Teaser"] = "", -- A_Classic_Fairytale:backstab -- ["Brutal Lily"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil -- ["Brutus"] = "", -- A_Classic_Fairytale:backstab +-- ["Build a fortress and destroy your enemy."] = "", -- Construction_Mode -- ["Build a track and race."] = "", -- ["Bullseye"] = "", -- A_Classic_Fairytale:dragon -- ["But it proved to be no easy task!"] = "", -- A_Classic_Fairytale:dragon @@ -98,6 +124,7 @@ -- ["But why would they help us?"] = "", -- A_Classic_Fairytale:backstab -- ["But you're cannibals. It's what you do."] = "", -- A_Classic_Fairytale:enemy -- ["But you said you'd let her go!"] = "", -- A_Classic_Fairytale:journey +-- ["Cake"] = "", -- Construction_Mode -- ["Call me Beep! Well, 'cause I'm such a nice...person!"] = "", -- A_Classic_Fairytale:family -- ["Cannibals"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:first_blood -- ["Cannibal Sentry"] = "", -- A_Classic_Fairytale:journey @@ -107,8 +134,15 @@ -- ["Carol"] = "", -- A_Classic_Fairytale:family -- ["CHALLENGE COMPLETE"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Change Weapon"] = "", +-- ["changing range from %i%% to %i%% with period of %i msec"] = "", -- Gravity -- ["Choose your side! If you want to join the strange man, walk up to him.|Otherwise, walk away from him. If you decide to att...nevermind..."] = "", -- A_Classic_Fairytale:shadow +-- ["Cleaver"] = "", -- Construction_Mode +-- ["Cleaver Placement Mode"] = "", -- Construction_Mode +-- ["Climber"] = "", -- ClimbHome +-- ["Climb Home"] = "", -- ClimbHome +-- ["Clowns"] = "", -- User_Mission_-_Nobody_Laugh -- ["Clumsy"] = "", +-- ["Cluster Bomb"] = "", -- Construction_Mode -- ["Cluster Bomb MASTER!"] = "", -- Basic_Training_-_Cluster_Bomb -- ["Cluster Bomb Training"] = "", -- Basic_Training_-_Cluster_Bomb ["Codename: Teamwork"] = "代号:团队行动", @@ -128,12 +162,19 @@ -- ["Congratulations! You've completed the Rope tutorial! |- Tutorial ends in 10 seconds!"] = "", -- Basic_Training_-_Rope ["Congratulations! You've eliminated all targets|within the allowed time frame."] = "恭喜!你在规定时限内清零全部目标。", --Bazooka, Shotgun, SniperRifle ["Congratulations!"] = "恭喜", +-- ["CONSTRUCTION MODE"] = "", -- Construction_Mode +-- ["Construction Station"] = "", -- Construction_Mode -- ["Continental supplies"] = "", -- Continental_supplies ["Control pillars to score points."] = "控制支柱得分", +-- ["Core"] = "", -- Construction_Mode -- ["Corporationals"] = "", -- A_Classic_Fairytale:queen -- ["Corpsemonger"] = "", -- A_Classic_Fairytale:shadow -- ["Corpse Thrower"] = "", -- A_Classic_Fairytale:epil +-- ["Cost"] = "", -- Construction_Mode +-- ["Crate Placement Tool"] = "", -- Construction_Mode -- ["Crates Left:"] = "", -- User_Mission_-_RCPlane_Challenge +-- ["Cricket time: [Drop a fireable mine! ~ Will work if fired close to your hog & far away from enemy ~ 1 sec]"] = "", -- Continental_supplies +-- ["Current setting is "] = "", -- Gravity ["Cybernetic Empire"] = "自动化帝国", -- ["Cyborg. It's what the aliens call themselves."] = "", -- A_Classic_Fairytale:enemy -- ["Dahmer"] = "", -- A_Classic_Fairytale:backstab @@ -141,15 +182,19 @@ ["DAMMIT, ROOKIE!"] = "新人", ["Dangerous Ducklings"] = "危险的小鸭子", -- ["Deadweight"] = "", +-- ["Decrease"] = "", -- Continental_supplies -- ["Defeat the cannibals"] = "", -- A_Classic_Fairytale:backstab -- ["Defeat the cannibals!|"] = "", -- A_Classic_Fairytale:united -- ["Defeat the cannibals!|Grenade hint: set the timer with [1-5], aim with [Up]/[Down] and hold [Space] to set power"] = "", -- A_Classic_Fairytale:shadow -- ["Defeat the cyborgs!"] = "", -- A_Classic_Fairytale:enemy +-- ["Defend your core from the enemy."] = "", -- Construction_Mode -- ["Defend yourself!|Hint: You can get tips on using weapons by moving your mouse over them in the weapon selection menu"] = "", -- A_Classic_Fairytale:shadow +-- ["Dematerializes weapons and equipment carried by enemy hedgehogs."] = "", -- Construction_Mode -- ["Demolition is fun!"] = "", -- ["Dense Cloud"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united -- ["Dense Cloud must have already told them everything..."] = "", -- A_Classic_Fairytale:shadow -- ["Depleted Kamikaze!"] = "", +-- ["Desert Eagle"] = "", -- Construction_Mode, A_Space_Adventure:death02 -- ["Destroy him, Leaks A Lot! He is responsible for the deaths of many of us!"] = "", -- A_Classic_Fairytale:first_blood -- ["Destroy invaders to score points."] = "", -- ["Destroy the targets!|Hint: Select the Shoryuken and hit [Space]|P.S. You can use it mid-air."] = "", -- A_Classic_Fairytale:first_blood @@ -168,9 +213,12 @@ -- ["Do you have any idea how valuable grass is?"] = "", -- A_Classic_Fairytale:enemy -- ["Do you think you're some kind of god?"] = "", -- A_Classic_Fairytale:enemy -- ["Dragon's Lair"] = "", -- A_Classic_Fairytale:dragon +-- ["Drill Rocket"] = "", -- Construction_Mode -- ["Drills"] = "", -- A_Classic_Fairytale:backstab +-- ["Drill Strike"] = "", -- Construction_Mode -- ["Drone Hunter!"] = "", --- ["Drop a bomb: [drop some heroic wind that will turn into a bomb on impact]"] = "", -- Continental_supplies +-- ["Drop a bomb: [Drop some heroic wind that will turn into a bomb on impact]"] = "", -- Continental_supplies + -- ["Drowner"] = "", -- ["Dude, all the plants are gone!"] = "", -- A_Classic_Fairytale:family -- ["Dude, can you see Ramon and Spiky?"] = "", -- A_Classic_Fairytale:journey @@ -180,11 +228,15 @@ -- ["Dude, where are we?"] = "", -- A_Classic_Fairytale:backstab -- ["Dude, wow! I just had the weirdest high!"] = "", -- A_Classic_Fairytale:backstab -- ["Duration"] = "", -- Continental_supplies --- ["Dust storm: [Deals 20 damage to all enemies in the circle]"] = "", -- Continental_supplies +-- ["Dust storm: [Deals 15 damage to all enemies in the circle]"] = "", -- Continental_supplies + +-- ["Dynamite"] = "", -- Construction_Mode +-- ["Each turn is only ONE SECOND!"] = "", -- Frenzy -- ["Each turn you get 1-3 random weapons"] = "", -- ["Each turn you get one random weapon"] = "", -- ["Eagle Eye"] = "", -- A_Classic_Fairytale:backstab --- ["Eagle Eye: [Blink to the impact ~ one shot]"] = "", -- Continental_supplies +-- ["Eagle Eye: [Blink to the impact ~ One shot]"] = "", -- Continental_supplies + -- ["Ear Sniffer"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:epil -- ["Elderbot"] = "", -- A_Classic_Fairytale:family -- ["Elimate your captor."] = "", -- User_Mission_-_The_Great_Escape @@ -207,8 +259,9 @@ -- ["Every single time!"] = "", -- A_Classic_Fairytale:dragon -- ["Everything looks OK..."] = "", -- A_Classic_Fairytale:enemy -- ["Exactly, man! That was my dream."] = "", -- A_Classic_Fairytale:backstab +-- ["Extra Damage"] = "", -- Construction_Mode +-- ["Extra Time"] = "", -- Construction_Mode -- ["Eye Chewer"] = "", -- A_Classic_Fairytale:journey --- ["INSANITY"] = "", -- Mutant -- ["Family Reunion"] = "", -- A_Classic_Fairytale:family ["Fastest lap: "] = "最快记录:", ["Feeble Resistance"] = "反抗者", @@ -218,10 +271,11 @@ -- ["Femur Lover"] = "", -- A_Classic_Fairytale:shadow -- ["Fierce Competition!"] = "", -- Space_Invasion -- ["Fiery Water"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united +-- ["Filthy Blue"] = "", -- User_Mission_-_Dangerous_Ducklings -- ["Find your tribe!|Cross the lake!"] = "", -- A_Classic_Fairytale:dragon -- ["Finish your training|Hint: Animations can be skipped with the [Precise] key."] = "", -- A_Classic_Fairytale:first_blood -- ["Fire"] = "", --- ["Fire a mine: [Does what it says ~ Cant be dropped close to an enemy ~ 1 sec]"] = "", -- Continental_supplies + -- ["First aid kits?!"] = "", -- A_Classic_Fairytale:united -- ["First Blood"] = "", -- A_Classic_Fairytale:first_blood -- ["FIRST BLOOD MUTATES"] = "", -- Mutant @@ -231,11 +285,15 @@ ["Flag returned!"] = "旗帜归还!", -- ["Flags, and their home base will be placed where each team ends their first turn."] = "", -- ["Flamer"] = "", +-- ["Flamethrower"] = "", -- Construction_Mode -- ["Flaming Worm"] = "", -- A_Classic_Fairytale:backstab --- ["Flare: [fire up some bombs depending on hogs depending on hogs in the circle"] = "", -- Continental_supplies + -- ["Flesh for Brainz"] = "", -- A_Classic_Fairytale:journey +-- ["Flying Saucer"] = "", -- Construction_Mode, Frenzy -- ["For improved features/stability, play 0.9.18+"] = "", -- WxW -- ["Free Dense Cloud and continue the mission!"] = "", -- A_Classic_Fairytale:journey +-- ["Freezer"] = "", -- Construction_Mode +-- ["FRENZY"] = "", -- Frenzy -- ["Friendly Fire!"] = "", -- ["fuel extended!"] = "", -- ["GAME BEGUN!!!"] = "", @@ -245,6 +303,9 @@ -- ["Game? Was this a game to you?!"] = "", -- A_Classic_Fairytale:enemy -- ["GasBomb"] = "", -- Continental_supplies -- ["Gas Gargler"] = "", -- A_Classic_Fairytale:queen +-- ["General information"] = "", -- Continental_supplies +-- ["Generates power."] = "", -- Construction_Mode +-- ["Generator"] = "", -- Construction_Mode -- ["Get Dense Cloud out of the pit!"] = "", -- A_Classic_Fairytale:journey ["Get on over there and take him out!"] = "上去把它拉下来!", -- ["Get on the head of the mole"] = "", -- A_Classic_Fairytale:first_blood @@ -255,6 +316,8 @@ -- ["Get your teammates out of their natural prison and save the princess!|Hint: Drilling holes should solve everything.|Hint: It might be a good idea to place a girder before starting to drill. Just saying.|Hint: All your hedgehogs need to be above the marked height!|Hint: Leaks A Lot needs to get really close to the princess!"] = "", -- A_Classic_Fairytale:family -- ["GG!"] = "", -- User_Mission_-_Rope_Knock_Challenge -- ["Gimme Bones"] = "", -- A_Classic_Fairytale:backstab +-- ["Girder"] = "", -- Construction_Mode +-- ["Girder Placement Mode"] = "", -- Construction_Mode -- ["Glark"] = "", -- A_Classic_Fairytale:shadow -- ["Goal"] = "", ["GO! GO! GO!"] = "上!", @@ -271,12 +334,16 @@ -- ["Go surf!"] = "", -- WxW -- ["GOTCHA!"] = "", -- ["Grab Mines/Explosives"] = "", +-- ["Grants nearby hogs life-regeneration."] = "", -- Construction_Mode +-- ["Gravity"] = "", -- Gravity -- ["Great choice, Steve! Mind if I call you that?"] = "", -- A_Classic_Fairytale:shadow -- ["Great work! Now hit it with your Baseball Bat! |Tip: You can change weapon with 'Right Click'!"] = "", -- Basic_Training_-_Rope -- ["Great! You will be contacted soon for assistance."] = "", -- A_Classic_Fairytale:shadow --- ["Green lipstick bullet: [Is poisonous]"] = "", -- Continental_supplies + +-- ["Green lipstick bullet: [Poisonous, deals no damage]"] = "", -- Continental_supplies -- ["Greetings, "] = "", -- A_Classic_Fairytale:dragon -- ["Greetings, cloudy one!"] = "", -- A_Classic_Fairytale:shadow +-- ["Grenade"] = "", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 -- ["Grenade Training"] = "", -- Basic_Training_-_Grenade -- ["Grenadiers"] = "", -- Basic_Training_-_Grenade -- ["Guys, do you think there's more of them?"] = "", -- A_Classic_Fairytale:backstab @@ -284,23 +351,27 @@ -- ["Haha!"] = "", -- A_Classic_Fairytale:united -- ["Hahahaha!"] = "", -- ["Haha, now THAT would be something!"] = "", +-- ["Hammer"] = "", -- Construction_Mode, Continental_supplies -- ["Hannibal"] = "", -- A_Classic_Fairytale:epil -- ["Hapless Hogs"] = "", -- [" Hapless Hogs left!"] = "", - -- [" HAS MUTATED"] = "", -- Mutant -- ["Hatless Jerry"] = "", -- A_Classic_Fairytale:queen -- ["Have no illusions, your tribe is dead, indifferent of your choice."] = "", -- A_Classic_Fairytale:shadow -- ["Have we ever attacked you first?"] = "", -- A_Classic_Fairytale:enemy +-- ["Healing Station"] = "", -- Construction_Mode +-- ["Health Crate Placement Mode"] = "", -- Construction_Mode -- ["Health crates extend your time."] = "", -- ["Heavy"] = "", -- ["Heavy Cannfantry"] = "", -- A_Classic_Fairytale:united -- ["Hedge-cogs"] = "", -- A_Classic_Fairytale:enemy --- ["Hedgehog projectile: [fire your hog like a Sticky Bomb]"] = "", -- Continental_supplies +-- ["Hedgehog projectile: [Fire your hog like a Sticky Bomb]"] = "", -- Continental_supplies + ["Hedgewars-Basketball"] = "刺猬大作战-篮球计划", ["Hedgewars-Knockball"] = "刺猬大作战-击球计划", -- ["Hedgibal Lecter"] = "", -- A_Classic_Fairytale:backstab -- ["Heh, it's not that bad."] = "", +-- ["Hellish Handgrenade"] = "", -- Construction_Mode -- ["Hello again, "] = "", -- A_Classic_Fairytale:family -- ["Help me, Leaks!"] = "", -- A_Classic_Fairytale:journey -- ["Help me, please!!!"] = "", -- A_Classic_Fairytale:journey @@ -332,6 +403,7 @@ -- ["Hogminator"] = "", -- A_Classic_Fairytale:family -- ["Hogs in sight!"] = "", -- Continental_supplies -- ["HOLY SHYTE!"] = "", -- Mutant +-- ["Homing Bee"] = "", -- Construction_Mode -- ["Honest Lee"] = "", -- A_Classic_Fairytale:enemy ["Hooray!"] = "呼!", -- ["Hostage Situation"] = "", -- A_Classic_Fairytale:family @@ -365,7 +437,6 @@ -- ["If you get stuck, use your Desert Eagle or restart the mission!|"] = "", -- A_Classic_Fairytale:journey -- ["If you know what I mean..."] = "", -- A_Classic_Fairytale:shadow -- ["If you say so..."] = "", -- A_Classic_Fairytale:shadow - -- ["I guess you'll have to kill them."] = "", -- A_Classic_Fairytale:dragon -- ["I have come to make you an offering..."] = "", -- A_Classic_Fairytale:shadow -- ["I have no idea where that mole disappeared...Can you see it?"] = "", -- A_Classic_Fairytale:shadow @@ -388,6 +459,7 @@ -- ["I'm not sure about that!"] = "", -- A_Classic_Fairytale:united -- ["Impressive...you are still dry as the corpse of a hawk after a week in the desert..."] = "", -- A_Classic_Fairytale:first_blood -- ["I'm so scared!"] = "", -- A_Classic_Fairytale:united +-- ["Increase"] = "", -- Continental_supplies -- ["Incredible..."] = "", -- A_Classic_Fairytale:shadow -- ["I need to find the others!"] = "", -- A_Classic_Fairytale:backstab -- ["I need to get to the other side of this island, fast!"] = "", -- A_Classic_Fairytale:journey @@ -396,12 +468,14 @@ -- ["I need to warn the others."] = "", -- A_Classic_Fairytale:backstab -- ["In fact, you are the only one that's been acting strangely."] = "", -- A_Classic_Fairytale:backstab -- ["In order to get to the other side, you need to collect the crates first.|"] = "", -- A_Classic_Fairytale:dragon +-- ["INSANITY"] = "", -- Mutant ["Instructor"] = "引导员", -- 01#Boot_Camp, User_Mission_-_Dangerous_Ducklings -- ["Interesting idea, haha!"] = "", -- A_Classic_Fairytale:enemy -- ["Interesting! Last time you said you killed a cannibal!"] = "", -- A_Classic_Fairytale:backstab -- ["In the meantime, take these and return to your \"friend\"!"] = "", -- A_Classic_Fairytale:shadow -- ["invaders destroyed"] = "", -- ["Invasion"] = "", -- A_Classic_Fairytale:united +-- ["Invulnerable"] = "", -- Construction_Mode -- ["I saw it with my own eyes!"] = "", -- A_Classic_Fairytale:shadow -- ["I see..."] = "", -- A_Classic_Fairytale:shadow -- ["I see you have already taken the leap of faith."] = "", -- A_Classic_Fairytale:first_blood @@ -444,6 +518,7 @@ -- ["Just kidding, none of you have died!"] = "", -- A_Classic_Fairytale:enemy -- ["Just on a walk."] = "", -- A_Classic_Fairytale:united -- ["Just wait till I get my hands on that trauma! ARGH!"] = "", -- A_Classic_Fairytale:family +-- ["Kamikaze"] = "", -- Construction_Mode -- ["Kamikaze Expert!"] = "", -- ["Keep it up!"] = "", -- ["Kerguelen"] = "", -- Continental_supplies @@ -453,6 +528,8 @@ -- ["Kill the aliens!"] = "", -- A_Classic_Fairytale:dragon -- ["Kill the cannibal!"] = "", -- A_Classic_Fairytale:first_blood -- ["Kill the traitor...or spare his life!|Kill him or press [Precise]!"] = "", -- A_Classic_Fairytale:backstab +-- ["Land Sprayer"] = "", -- Construction_Mode +-- ["Laser Sight"] = "", -- Construction_Mode -- ["Last Target!"] = "", -- ["Leader"] = "", -- A_Classic_Fairytale:enemy -- ["Leaderbot"] = "", -- A_Classic_Fairytale:queen @@ -463,6 +540,7 @@ -- ["Led Heart"] = "", -- A_Classic_Fairytale:queen -- ["Lee"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen -- ["[Left Shift]"] = "", +-- ["left shift"] = "", -- Continental_supplies -- ["Let a Continent provide your weapons!"] = "", -- Continental_supplies -- ["Let me test your skills a little, will you?"] = "", -- A_Classic_Fairytale:journey -- ["Let's go home!"] = "", -- A_Classic_Fairytale:journey @@ -472,41 +550,56 @@ -- ["Let them have a taste of my fury!"] = "", -- A_Classic_Fairytale:backstab -- ["Let us help, too!"] = "", -- A_Classic_Fairytale:backstab -- ["Light Cannfantry"] = "", -- A_Classic_Fairytale:united +-- ["Limburger"] = "", -- Construction_Mode ["Listen up, maggot!!"] = "听好,小子!!", -- ["Little did they know that this hunt will mark them forever..."] = "", -- A_Classic_Fairytale:shadow -- ["Lively Lifeguard"] = "", --- ["Lonely Cries: [Rise the water if no hog is in the circle and deal 1 damage to all hogs]"] = "", -- Continental_supplies + +-- ["Lonely Cries: [Rise the water if no hog is in the circle and deal 7 damage to all enemy hogs]"] = "", -- Continental_supplies +-- ["Lonely Hog"] = "", -- ClimbHome -- ["Look, I had no choice!"] = "", -- A_Classic_Fairytale:backstab -- ["Look out! There's more of them!"] = "", -- A_Classic_Fairytale:backstab -- ["Look out! We're surrounded by cannibals!"] = "", -- A_Classic_Fairytale:enemy -- ["Looks like the whole world is falling apart!"] = "", -- A_Classic_Fairytale:enemy +-- ["Low Gravity"] = "", -- Construction_Mode, Frenzy -- ["Luckily, I've managed to snatch some of them."] = "", -- A_Classic_Fairytale:united -- ["LUDICROUS KILL"] = "", -- Mutant +-- ["Made it!"] = "", -- ClimbHome +-- ["- Massive weapon bonus on first turn"] = "", -- Continental_supplies -- ["May the spirits aid you in all your quests!"] = "", -- A_Classic_Fairytale:backstab -- ["Medicine: [Fire some exploding medicine that will heal all hogs effected by the explosion]"] = "", -- Continental_supplies -- ["MEGA KILL"] = "", -- Mutant -- ["Meiwes"] = "", -- A_Classic_Fairytale:backstab -- ["Mindy"] = "", -- A_Classic_Fairytale:united +-- ["Mine"] = "", -- Construction_Mode, Frenzy -- ["Mine Deployer"] = "", -- ["Mine Eater!"] = "", +-- ["Mine Placement Mode"] = "", -- Construction_Mode -- ["|- Mines Time:"] = +-- ["Mine Strike"] = "", -- Construction_Mode ["MISSION FAILED"] = "任务失败", -- User_Mission_-_Dangerous_Ducklings, User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork -- ["MISSION SUCCESS"] = "", ["MISSION SUCCESSFUL"] = "任务成功", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork +-- ["Molotov Cocktail"] = "", -- Construction_Mode -- ["Molotov"] = "", -- Continental_supplies -- ["MONSTER KILL"] = "", -- Mutant -- ["More Natives"] = "", -- A_Classic_Fairytale:epil +-- ["Mortar"] = "", -- Construction_Mode, A_Space_Adventure:death02 -- ["Movement: [Up], [Down], [Left], [Right]"] = "", +-- ["Mudball"] = "", -- Construction_Mode -- ["Multi-shot!"] = "", -- ["Muriel"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen -- ["Muscle Dissolver"] = "", -- A_Classic_Fairytale:shadow -- ["-------"] = "", -- Mutant +-- ["Mutant"] = "", -- Mutant -- ["Nade Boy"] = "", -- Basic_Training_-_Grenade -- ["Name"] = "", -- A_Classic_Fairytale:queen -- ["Nameless Heroes"] = "", -- ["Nancy Screw"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:queen +-- ["Napalm"] = "", -- Construction_Mode -- ["Napalm rocket: [Fire a bomb with napalm!]"] = "", -- Continental_supplies -- ["Natives"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:first_blood, A_Classic_Fairytale:journey, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow, A_Classic_Fairytale:united +-- ["Naughty Ninja"] = "", -- User_Mission_-_Dangerous_Ducklings -- ["New Barrels Per Turn"] = "", -- ["NEW CLAN RECORD: "] = "", ["NEW fastest lap: "] = "新记录", @@ -517,6 +610,7 @@ -- ["Nice work, "] = "", -- A_Classic_Fairytale:dragon -- ["Nice work!"] = "", -- A_Classic_Fairytale:enemy -- ["Nilarian"] = "", -- A_Classic_Fairytale:queen +-- ["Nobody Laugh"] = "", -- User_Mission_-_Nobody_Laugh -- ["No, I came back to help you out..."] = "", -- A_Classic_Fairytale:shadow -- ["No...I wonder where they disappeared?!"] = "", -- A_Classic_Fairytale:journey -- ["Nom-Nom"] = "", -- A_Classic_Fairytale:journey @@ -524,6 +618,7 @@ -- ["Nope. It was one fast mole, that's for sure."] = "", -- A_Classic_Fairytale:shadow -- ["No! Please, help me!"] = "", -- A_Classic_Fairytale:journey -- ["NORMAL"] = "", -- Continental_supplies +-- ["Normal players can only score points by killing the mutant."] = "", -- Mutant -- ["North America"] = "", -- Continental_supplies -- ["Not all hogs are born equal."] = "", -- Highlander -- ["NOT ENOUGH WAYPOINTS"] = "", @@ -536,6 +631,7 @@ -- ["No. Where did he come from?"] = "", -- A_Classic_Fairytale:shadow -- ["Now how do I get on the other side?!"] = "", -- A_Classic_Fairytale:dragon -- ["No. You and the rest of the tribe are safer there!"] = "", -- A_Classic_Fairytale:backstab +-- ["Object Placement Tool"] = "", -- Construction_Mode -- ["Obliterate them!|Hint: You might want to take cover..."] = "", -- A_Classic_Fairytale:shadow -- ["Obstacle course"] = "", -- A_Classic_Fairytale:dragon -- ["Of course I have to save her. What did I expect?!"] = "", -- A_Classic_Fairytale:family @@ -552,11 +648,14 @@ -- ["Once upon a time, on an island with great natural resources, lived two tribes in heated conflict..."] = "", -- A_Classic_Fairytale:first_blood -- ["ONE HOG PER TEAM! KILLING EXCESS HEDGES"] = "", -- Mutant -- ["One tribe was peaceful, spending their time hunting and training, enjoying the small pleasures of life..."] = "", -- A_Classic_Fairytale:first_blood +-- ["on Skip"] = "", -- Continental_supplies -- ["Oops...I dropped them."] = "", -- A_Classic_Fairytale:united -- ["Open that crate and we will continue!"] = "", -- A_Classic_Fairytale:first_blood ["Operation Diver"] = "水下行动", ["Opposing Team: "] = "对方队伍", +-- ["or 'g=50, g2=150, period=4000' for gravity changing|from 50 to 150 and back with period of 4000 msec"] = "", -- Gravity -- ["Orlando Boom!"] = "", -- A_Classic_Fairytale:queen +-- ["Other kills don't give you points."] = "", -- Mutant -- ["Ouch!"] = "", -- User_Mission_-_Rope_Knock_Challenge -- ["Our tribe, our beautiful island!"] = "", -- A_Classic_Fairytale:enemy -- ["Parachute"] = "", -- Continental_supplies @@ -564,14 +663,17 @@ ["Pathetic Hog #2"] = "可怜刺猬二号", -- ["Pathetic Hog #%d"] = -- ["Pathetic Resistance"] = "", -- User_Mission_-_Bamboo_Thicket, User_Mission_-_Newton_and_the_Hammock +-- ["Penguin roar: [Deal 15 damage + 15% of your hogs health to all hogs around you and get 2/3 back]"] = "", -- Continental_supplies -- ["Perfect! Now try to get the next crate without hurting yourself!"] = "", -- A_Classic_Fairytale:first_blood -- ["Per-Hog Ammo"] = "", --- ["- Per team weapons|- 9 weaponschemes|- Unique new weapons| |Select continent first round with the Weapon Menu or by ([switch/tab]=Increase,[precise/left shift]=Decrease) on Skip|Some weapons have a second option. Find them with [switch/tab]"] = "", -- Continental_supplies +-- ["Personal Portal Device"] = "", -- Construction_Mode +-- ["Per team weapons"] = "", -- Continental_supplies -- ["Pfew! That was close!"] = "", -- A_Classic_Fairytale:shadow --- ["Piñata bullet: [Contains some sweet candy!]"] = "", -- Continental_supplies +-- ["Piano Strike"] = "", -- Construction_Mode +-- ["Pickhammer"] = "", -- Construction_Mode + -- ["Pings left:"] = "", -- Space_Invasion - -- ["Place more waypoints using the 'Air Attack' weapon."] = "", -- ["Planes Used:"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Planes Used"] = "", -- User_Mission_-_RCPlane_Challenge @@ -581,14 +683,18 @@ -- ["Please, stop releasing your \"smoke signals\"!"] = "", -- A_Classic_Fairytale:shadow -- ["Point Blank Combo!"] = "", -- Space_Invasion -- ["points"] = +-- ["POINTS"] = "", -- Mutant -- ["Poison"] = +-- ["Population"] = "", -- Continental_supplies -- ["Portal hint: one goes to the destination, and one is the entrance.|"] = "", -- A_Classic_Fairytale:dragon -- ["Portal mission"] = "", -- portal -- ["Power Remaining"] = "", -- ["Prepare yourself"] = "", +-- ["presice"] = "", -- Continental_supplies -- ["Press [Enter] to accept this configuration."] = "", -- WxW -- ["Press [Left] or [Right] to move around, [Enter] to jump"] = "", -- A_Classic_Fairytale:first_blood -- ["Press [Precise] to skip intro"] = "", +-- ["Prestigious Pilot"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Private Novak"] = "", -- Basic_Training_-_Cluster_Bomb -- ["Protect yourselves!|Grenade hint: set the timer with [1-5], aim with [Up]/[Down] and hold [Space] to set power"] = "", -- A_Classic_Fairytale:shadow -- ["Race complexity limit reached."] = "", @@ -597,26 +703,40 @@ -- ["Radar Ping"] = "", -- Space_Invasion -- ["Raging Buffalo"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united -- ["Ramon"] = "", -- A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:shadow +-- ["random in range from %i%% to %i%% with period of %i msec"] = "", -- Gravity +-- ["RC Plane"] = "", -- Construction_Mode -- ["RC PLANE TRAINING"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Really?! You thought you could harm me with your little toys?"] = "", -- A_Classic_Fairytale:shadow +-- ["Reflector Shield"] = "", -- Construction_Mode +-- ["Reflects enemy projectiles."] = "", -- Construction_Mode -- ["Regurgitator"] = "", -- A_Classic_Fairytale:backstab -- ["Reinforcements"] = "", -- A_Classic_Fairytale:backstab -- ["Remember: The rope only bend around objects, |if it doesn't hit anything it's always stright!"] = "", -- Basic_Training_-_Rope -- ["Remember this, pathetic animal: when the day comes, you will regret your blind loyalty!"] = "", -- A_Classic_Fairytale:shadow +-- ["REMOVED"] = "", -- Continental_supplies +-- ["Respawner"] = "", -- Construction_Mode +-- ["Resurrector"] = "", -- Construction_Mode +-- ["Resurrects dead hedgehogs."] = "", -- Construction_Mode [" - Return the enemy flag to your base to score | - First team to 3 captures wins | - You may only score when your flag is in your base | - Hogs will drop the flag if killed, or drowned | - Dropped flags may be returned or recaptured | - Hogs respawn when killed"] = "-带回敌人旗帜得分| -第一支3次夺旗队伍获胜| - 只有旗帜在己方基地才算| -带旗刺猬消逝则旗帜落下| -落下的旗帜使用方式不变| -损失的刺猬瞬间还原", -- ["Return to Leaks A Lot! If you get stuck, press [Precise] to try again!"] = "", -- A_Classic_Fairytale:shadow -- ["Righteous Beard"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:epil, A_Classic_Fairytale:family, A_Classic_Fairytale:first_blood, A_Classic_Fairytale:queen, A_Classic_Fairytale:united +-- ["Rope"] = "", -- Construction_Mode -- ["ROPE-KNOCKING"] = "", -- User_Mission_-_Rope_Knock_Challenge +-- ["Rope to safety"] = "", -- ClimbHome -- ["Rope Training"] = "", -- Basic_Training_-_Rope -- ["Rot Molester"] = "", -- A_Classic_Fairytale:shadow -- ["Round Limit:"] = "", -- ["Round Limit"] = "", -- ["Rounds Complete: "] = "", -- ["Rounds Complete"] = "", +-- ["Rubber Band"] = "", -- Construction_Mode +-- ["Rubber Placement Mode"] = "", -- Construction_Mode +-- ["RULES"] = "", -- Frenzy, Mutant ["RULES OF THE GAME [Press ESC to view]"] = "游戏规则 [按下 ESC键 查看]", -- ["Rusty Joe"] = "", -- A_Classic_Fairytale:queen -- ["s|"] = "", --- ["Sabotage: [Sabotage all hogs in the circle and deal ~10 dmg]"] = "", -- Continental_supplies +-- ["Sabotage/Flare: [Sabotage all hogs in the circle and deal ~1 dmg OR Fire a cluster up into the air]"] = "", -- Continental_supplies + -- ["Salivaslurper"] = "", -- A_Classic_Fairytale:united -- ["Salvation"] = "", -- A_Classic_Fairytale:family -- ["Salvation was one step closer now..."] = "", -- A_Classic_Fairytale:dragon @@ -628,7 +748,7 @@ -- ["Scalp Muncher"] = "", -- A_Classic_Fairytale:backstab -- ["SCORE"] = "", -- ["Score"] = "", -- Mutant --- ["Scream from a Walrus: [Deal 20 damage + 10% of your hogs health to all hogs around you and get half back]"] = "", -- Continental_supplies + -- ["sec"] = -- ["Seduction"] = "", -- Continental_supplies -- ["Seems like every time you take a \"walk\", the enemy find us!"] = "", -- A_Classic_Fairytale:backstab @@ -636,8 +756,11 @@ ["See ya!"] = "再见!", -- ["Segmentation Paul"] = "", -- A_Classic_Fairytale:dragon -- ["Select continent!"] = "", -- Continental_supplies +-- ["Select continent first round with the Weapon Menu or by"] = "", -- Continental_supplies -- ["Select difficulty: [Left] - easier or [Right] - harder"] = "", -- A_Classic_Fairytale:first_blood -- ["selected!"] = "", +-- ["Set period to negative value for random gravity"] = "", -- Gravity +-- ["Setup:|'g=150', where 150 is 150% of normal gravity"] = "", -- Gravity -- ["s"] = "", -- GaudyRacer, Space_Invasion -- ["... share your beauty with the world every morning, my princess!"] = "", -- A_Classic_Fairytale:journey -- ["She's behind that tall thingy."] = "", -- A_Classic_Fairytale:family @@ -649,16 +772,21 @@ -- ["Shield OFF:"] = "", -- ["Shield ON:"] = "", -- ["Shield Seeker!"] = "", +-- ["Shoryuken"] = "", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 -- ["Shotgun"] = "", -- Continental_supplies ["Shotgun Team"] = "霰弹枪队", ["Shotgun Training"] = "霰弹枪训练", -- ["shots remaining."] = "", -- ["Silly"] = "", +-- ["SineGun"] = "", -- Construction_Mode -- ["Sinky"] = "", -- ["Sirius Lee"] = "", -- A_Classic_Fairytale:enemy ["%s is out and Team %d|scored a penalty!| |Score:"] = "%s 出局, %d 惩罚分数!", -- Basketball, Knockball ["%s is out and Team %d|scored a point!| |Score:"] = "%s 出局, %d 得分!", -- Basketball, Knockball -- ["Slippery"] = "", -- A_Classic_Fairytale:journey +-- ["Slot"] = "", -- Frenzy +-- ["Slot keys save time! (F1-F10 by default)"] = "", -- Frenzy +-- ["SLOTS"] = "", -- Frenzy -- ["Smith 0.97"] = "", -- A_Classic_Fairytale:enemy -- ["Smith 0.98"] = "", -- A_Classic_Fairytale:enemy -- ["Smith 0.99a"] = "", -- A_Classic_Fairytale:enemy @@ -670,6 +798,7 @@ ["Sniper Training"] = "狙击训练", ["Sniperz"] = "狙击手", -- ["So humiliating..."] = "", -- A_Classic_Fairytale:first_blood +-- ["Some weapons have a second option. Find them with"] = "", -- Continental_supplies -- ["South America"] = "", -- Continental_supplies -- ["So? What will it be?"] = "", -- A_Classic_Fairytale:shadow -- ["Spawn the crate, and attack!"] = "", -- WxW @@ -678,25 +807,43 @@ -- ["Spleenlover"] = "", -- A_Classic_Fairytale:united -- ["Sponge"] = "", ["Spooky Tree"] = "怪树", +-- ["Sprite Placement Mode"] = "", -- Construction_Mode +-- ["Sprite Testing Mode"] = "", -- Construction_Mode -- ["STATUS UPDATE"] = "", -- GaudyRacer, Space_Invasion -- ["Steel Eye"] = "", -- A_Classic_Fairytale:queen -- ["Step By Step"] = "", -- A_Classic_Fairytale:first_blood -- ["Steve"] = "", -- A_Classic_Fairytale:dragon, A_Classic_Fairytale:family, A_Classic_Fairytale:queen -- ["Sticky Mine"] = "", -- Continental_supplies +-- ["Sticky Mine Placement Mode"] = "", -- Construction_Mode -- ["Stronglings"] = "", -- A_Classic_Fairytale:shadow --- ["Structure"] = "", -- Continental_supplies + +-- ["Structure Placement Mode"] = "", -- Construction_Mode +-- ["Structure Placement Tool"] = "", -- Construction_Mode +-- ["Sundaland"] = "", -- Continental_supplies -- ["Super Weapons"] = "", -- WxW +-- ["Support Station"] = "", -- Construction_Mode -- ["Surf Before Crate"] = "", -- WxW -- ["Surfer! +15 points!"] = "", -- Space_Invasion -- ["Surfer!"] = "", -- WxW -- ["Survive!|Hint: Cinematics can be skipped with the [Precise] key."] = "", -- A_Classic_Fairytale:shadow -- ["Swing, Leaks A Lot, on the wings of the wind!"] = "", -- A_Classic_Fairytale:first_blood +-- ["switch"] = "", -- Continental_supplies -- ["Switched to "] = "", +-- ["Switch Hog"] = "", -- Construction_Mode -- ["Syntax Errol"] = "", -- A_Classic_Fairytale:dragon +-- ["tab"] = "", -- Continental_supplies +-- ["Tagging Mode"] = "", -- Construction_Mode -- ["Talk about mixed signals..."] = "", -- A_Classic_Fairytale:dragon +-- ["Tardis"] = "", -- Construction_Mode +-- ["Target Placement Mode"] = "", -- Construction_Mode ["Team %d: "] = "队伍 %d", -- ["Team Scores"] = "", -- Control, Space_Invasion +-- ["Teleporation Node"] = "", -- Construction_Mode +-- ["Teleportation Mode"] = "", -- Construction_Mode +-- ["Teleportation Node"] = "", -- Construction_Mode +-- ["Teleport"] = "", -- Construction_Mode, Frenzy -- ["Teleport hint: just use the mouse to select the destination!"] = "", -- A_Classic_Fairytale:dragon +-- ["Teleport Unsuccessful. Please teleport within a clan teleporter's sphere of influence."] = "", -- Construction_Mode -- ["Thanks!"] = "", -- A_Classic_Fairytale:family -- ["Thank you, my hero!"] = "", -- A_Classic_Fairytale:family -- ["Thank you, oh, thank you, Leaks A Lot!"] = "", -- A_Classic_Fairytale:journey @@ -713,6 +860,7 @@ -- ["That was pointless."] = -- ["The answer is...entertaintment. You'll see what I mean."] = "", -- A_Classic_Fairytale:backstab -- ["The anti-portal zone is all over the floor, and I have nothing to kill him...Droping something could hurt him enough to kill him..."] = "", -- portal +-- ["The Bottom Feeder can score points by killing anyone."] = "", -- Mutant -- ["The Bull's Eye"] = "", -- A_Classic_Fairytale:first_blood -- ["The caves are well hidden, they won't find us there!"] = "", -- A_Classic_Fairytale:united -- ["The Crate Frenzy"] = "", -- A_Classic_Fairytale:first_blood @@ -722,20 +870,26 @@ -- ["The Enemy Of My Enemy"] = "", -- A_Classic_Fairytale:enemy -- ["The First Blood"] = "", -- A_Classic_Fairytale:first_blood -- ["The First Encounter"] = "", -- A_Classic_Fairytale:shadow +-- ["The first player to kill someone becomes the Mutant."] = "", -- Mutant -- ["The flag will respawn next round."] = -- ["The food bites back"] = "", -- A_Classic_Fairytale:backstab -- ["The giant umbrella from the last crate should help break the fall."] = "", -- A_Classic_Fairytale:first_blood -- ["The Great Escape"] = "", -- User_Mission_-_The_Great_Escape +-- ["The Great Hog in the sky sees your sadness and grants you a boon."] = "", -- Construction_Mode -- ["The guardian"] = "", -- A_Classic_Fairytale:shadow -- ["The Individualist"] = "", -- A_Classic_Fairytale:shadow -- ["Their buildings were very primitive back then, even for an uncivilised island."] = "", -- A_Classic_Fairytale:united -- ["The Journey Back"] = "", -- A_Classic_Fairytale:journey -- ["The Leap of Faith"] = "", -- A_Classic_Fairytale:first_blood -- ["The Moonwalk"] = "", -- A_Classic_Fairytale:journey +-- ["The Mutant has super-weapons and a lot of health."] = "", -- Mutant +-- ["The Mutant loses health quickly if he doesn't keep scoring kills."] = "", -- Mutant -- ["The Nameless One"] = "", -- ["The next one is pretty hard! |Tip: You have to do multiple swings!"] = "", -- Basic_Training_-_Rope -- ["Then how do they keep appearing?"] = "", -- A_Classic_Fairytale:shadow -- ["The other one were all cannibals, spending their time eating the organs of fellow hedgehogs..."] = "", -- A_Classic_Fairytale:first_blood +-- ["The player with least points (or most deaths) becomes the Bottom Feeder."] = "", -- Mutant +-- ["There are a variety of structures available to aid you."] = "", -- Construction_Mode -- ["There must be a spy among us!"] = "", -- A_Classic_Fairytale:backstab -- ["There's more of them? When did they become so hungry?"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united -- ["There's nothing more satisfying for me than seeing you share your beauty with the world every morning, my princess!"] = "", -- A_Classic_Fairytale:journey @@ -791,7 +945,7 @@ -- ["To the caves..."] = "", -- A_Classic_Fairytale:united ["Toxic Team"] = "腐坏的队伍", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork -- ["TRACK COMPLETED"] = "", --- ["TRACK FAILED!"] = "", + -- ["training"] = "", -- portal -- ["Traitors"] = "", -- A_Classic_Fairytale:epil -- ["Tribe"] = "", -- A_Classic_Fairytale:backstab @@ -808,6 +962,7 @@ -- ["ULTRA KILL"] = "", -- Mutant -- ["Under Construction"] = "", -- A_Classic_Fairytale:shadow -- ["Unexpected Igor"] = "", -- A_Classic_Fairytale:dragon +-- ["Unique new weapons"] = "", -- Continental_supplies -- ["Unit"] = "", -- ["Unit 0x0007"] = "", -- A_Classic_Fairytale:family -- ["Unit 334a$7%;.*"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:dragon, A_Classic_Fairytale:enemy, A_Classic_Fairytale:family, A_Classic_Fairytale:queen, A_Classic_Fairytale:united @@ -822,11 +977,14 @@ -- ["Use it wisely!"] = "", -- A_Classic_Fairytale:dragon -- ["Use it with precaution!"] = "", -- A_Classic_Fairytale:first_blood -- ["User Challenge"] = "", - +-- ["Use the air-attack weapons and the arrow keys to select structures."] = "", -- Construction_Mode -- ["Use the portal gun to get to the next crate, then use the new gun to get to the final destination!|"] = "", -- A_Classic_Fairytale:dragon -- ["Use the rope to get on the head of the mole, young one!"] = "", -- A_Classic_Fairytale:first_blood -- ["Use the rope to knock your enemies to their doom."] = "", -- User_Mission_-_Rope_Knock_Challenge +-- ["Use your ready time to think."] = "", -- Frenzy ["Use your rope to get from start to finish as fast as you can!"] = "抓起绳子飞向目的地,越快越好。", +-- ["Utility Crate Placement Mode"] = "", -- Construction_Mode +-- ["Vampirism"] = "", -- Construction_Mode -- ["Vedgies"] = "", -- A_Classic_Fairytale:journey -- ["Vegan Jack"] = "", -- A_Classic_Fairytale:enemy -- ["Victory!"] = "", -- Basic_Training_-_Rope @@ -838,10 +996,14 @@ -- ["Wannabe Flyboys"] = "", -- User_Mission_-_RCPlane_Challenge -- ["Wannabe Shoppsta"] = "", -- User_Mission_-_Rope_Knock_Challenge -- ["Watch your steps, young one!"] = "", -- A_Classic_Fairytale:first_blood +-- ["Watermelon Bomb"] = "", -- Construction_Mode -- ["Waypoint placed."] = "", -- ["Way-Points Remaining"] = "", -- ["Weaklings"] = "", -- A_Classic_Fairytale:shadow -- ["We all know what happens when you get frightened..."] = "", -- A_Classic_Fairytale:first_blood +-- ["Weapon Crate Placement Mode"] = "", -- Construction_Mode +-- ["Weapon Filter"] = "", -- Construction_Mode +-- ["weaponschemes"] = "", -- Continental_supplies -- ["Weapons Reset"] = "", -- ["Weapons reset."] = "", -- Highlander -- ["We are indeed."] = "", -- A_Classic_Fairytale:backstab @@ -894,6 +1056,7 @@ -- ["Where do you get that?!"] = "", -- A_Classic_Fairytale:enemy -- ["Where have you been?!"] = "", -- A_Classic_Fairytale:backstab -- ["Where have you been?"] = "", -- A_Classic_Fairytale:united +-- ["Whip"] = "", -- Construction_Mode -- ["? Why?"] = "", -- A_Classic_Fairytale:backstab -- ["Why "] = "", -- A_Classic_Fairytale:backstab -- ["! Why?!"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united @@ -906,8 +1069,10 @@ -- ["Why me?!"] = "", -- A_Classic_Fairytale:backstab -- ["Why would they do this?"] = "", -- A_Classic_Fairytale:backstab -- ["- Will Get 1-3 random weapons"] = "", -- Continental_supplies --- ["- Will refresh Parachute each turn."] = "", -- Continental_supplies --- ["- Will refresh portalgun each turn."] = "", -- Continental_supplies +-- ["- Will give you an airstrike every fifth turn."] = "", -- Continental_supplies +-- ["- Will give you a parachute every second turn."] = "", -- Continental_supplies + + -- ["Will this ever end?"] = "", -- ["WINNER IS "] = "", -- Mutant -- ["WINNING TIME: "] = "", @@ -926,6 +1091,7 @@ -- ["Yes!"] = "", -- A_Classic_Fairytale:enemy -- ["Yes, yeees! You are now ready to enter the real world!"] = "", -- A_Classic_Fairytale:first_blood -- ["Yo, dude, we're here, too!"] = "", -- A_Classic_Fairytale:family +-- ["You are far from home, and the water is rising, climb up as high as you can!"] = "", -- ClimbHome -- ["You are given the chance to turn your life around..."] = "", -- A_Classic_Fairytale:shadow -- ["You are playing with our lives here!"] = "", -- A_Classic_Fairytale:enemy -- ["! You bastards!"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united @@ -958,6 +1124,8 @@ -- ["You know what? I don't even regret anything!"] = "", -- A_Classic_Fairytale:backstab -- ["You'll see what I mean!"] = "", -- A_Classic_Fairytale:enemy -- ["You may only attack from a rope!"] = "", -- WxW +-- ["You may only spawn 5 crates per turn."] = "", -- Construction_Mode +-- ["You may only use 1 Extra Time per turn."] = "", -- Construction_Mode -- ["You meatbags are pretty slow, you know!"] = "", -- A_Classic_Fairytale:enemy -- ["You might want to find a way to instantly kill arriving cannibals!"] = "", -- A_Classic_Fairytale:backstab -- ["Young one, you are telling us that they can instantly change location without a shaman?"] = "", -- A_Classic_Fairytale:united @@ -978,6 +1146,7 @@ ["You've failed. Try again."] = "失败了。再尝试吧。", ["You've reached the goal!| |Time: "] = "目标达成| |时间:", -- ["You will be avenged!"] = "", -- A_Classic_Fairytale:shadow +-- ["- You will recieve 2-4 weapons on each kill! (Even on own hogs)"] = "", -- Continental_supplies -- ["You won't believe what happened to me!"] = "", -- A_Classic_Fairytale:backstab -- ["Yuck! I bet they'll keep worshipping her even after I save the village!"] = "", -- A_Classic_Fairytale:family -- ["Zealandia"] = "", -- Continental_supplies diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/BambooPlinko/preview.png Binary file share/hedgewars/Data/Maps/BambooPlinko/preview.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/Basketball/CMakeLists.txt --- a/share/hedgewars/Data/Maps/Basketball/CMakeLists.txt Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Maps/Basketball/CMakeLists.txt Tue Nov 10 20:43:13 2015 +0100 @@ -1,8 +1,6 @@ install(FILES - map.png map.cfg map.lua - mask.png preview.png desc.txt DESTINATION ${SHAREPATH}Data/Maps/Basketball) diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/Basketball/desc.txt --- a/share/hedgewars/Data/Maps/Basketball/desc.txt Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Maps/Basketball/desc.txt Tue Nov 10 20:43:13 2015 +0100 @@ -1,1 +1,1 @@ -en_US=Who said hedgehogs can't play basketball? +en_US=Who said hedgehogs can't play basketball? diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/Basketball/map.lua --- a/share/hedgewars/Data/Maps/Basketball/map.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Maps/Basketball/map.lua Tue Nov 10 20:43:13 2015 +0100 @@ -14,6 +14,7 @@ Explosives = 0 Delay = 500 SuddenDeathTurns = 99999 -- "disable" sudden death + Map = 'BasketballField' end function onGameStart() @@ -53,3 +54,7 @@ end end end + +function onNewTurn() + SetWeapon(amBaseballBat) +end diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/Basketball/map.png Binary file share/hedgewars/Data/Maps/Basketball/map.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/Basketball/mask.png Binary file share/hedgewars/Data/Maps/Basketball/mask.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/BasketballField/CMakeLists.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Maps/BasketballField/CMakeLists.txt Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,6 @@ +install(FILES + map.png + map.cfg + mask.png + preview.png + DESTINATION ${SHAREPATH}Data/Maps/BasketballField) diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/BasketballField/map.cfg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Maps/BasketballField/map.cfg Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,2 @@ +Nature +12 \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/BasketballField/map.png Binary file share/hedgewars/Data/Maps/BasketballField/map.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/BasketballField/mask.png Binary file share/hedgewars/Data/Maps/BasketballField/mask.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/BasketballField/preview.png Binary file share/hedgewars/Data/Maps/BasketballField/preview.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/BasketballField/preview@2x.png Binary file share/hedgewars/Data/Maps/BasketballField/preview@2x.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/Battlefield/mask.png Binary file share/hedgewars/Data/Maps/Battlefield/mask.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/Blizzard/mask.png Binary file share/hedgewars/Data/Maps/Blizzard/mask.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/Blox/map.png Binary file share/hedgewars/Data/Maps/Blox/map.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/Blox/mask.png Binary file share/hedgewars/Data/Maps/Blox/mask.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/CMakeLists.txt --- a/share/hedgewars/Data/Maps/CMakeLists.txt Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Maps/CMakeLists.txt Tue Nov 10 20:43:13 2015 +0100 @@ -2,6 +2,7 @@ Bamboo BambooPlinko Basketball + BasketballField Bath Battlefield Blizzard @@ -11,6 +12,7 @@ Castle Cave Cheese + ClimbHome Cogs Control CrazyMission diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/CTF_Blizzard/desc.txt --- a/share/hedgewars/Data/Maps/CTF_Blizzard/desc.txt Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Maps/CTF_Blizzard/desc.txt Tue Nov 10 20:43:13 2015 +0100 @@ -1,1 +1,1 @@ -en_US=Capture the Flag\, blizzard style! +en_US=Capture the Flag\, blizzard style! diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/Castle/mask.png Binary file share/hedgewars/Data/Maps/Castle/mask.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/Cheese/mask.png Binary file share/hedgewars/Data/Maps/Cheese/mask.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/ClimbHome/CMakeLists.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Maps/ClimbHome/CMakeLists.txt Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,6 @@ +install(FILES + mask.png + map.cfg + map.lua + preview.png + DESTINATION ${SHAREPATH}Data/Maps/ClimbHome) diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/ClimbHome/desc.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Maps/ClimbHome/desc.txt Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,1 @@ +en_US=You are far from home and the water is rising. Climb as fast as you can. diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/ClimbHome/map.cfg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Maps/ClimbHome/map.cfg Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,4 @@ +EarthRise +48 +Timeless +Shoppa diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/ClimbHome/map.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Maps/ClimbHome/map.lua Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,680 @@ +HedgewarsScriptLoad("/Scripts/Locale.lua") +HedgewarsScriptLoad("/Scripts/Utils.lua") +HedgewarsScriptLoad("/Scripts/Params.lua") + +local hTag = nil +local hTagHeight = 33000 +local tTag = nil +local rTag = nil +local startTime = 0 +local MaxHeight = 32640 +local RecordHeight = 33000 +local RecordHeightHogName = nil +local Fire = {} +--local BoomFire = nil +local HH = {} +local totalHedgehogs = 0 +local deadHedgehogs = 0 +local currTeam = '' +local teams = {} +local teamScoreStats = {} +local teamBests = {} +local MrMine -- in honour of sparkle's first arrival in the cabin +local YouWon = false +local YouLost = false +local HogsAreInvulnerable = false +local WaterRise = nil +local Cake = nil +local CakeTries = 0 +local addCake = true +local Stars = {} +local tauntNoo = false +local jokeAwardNavy = nil +local jokeAwardSpeed = nil +local jokeAwardDamage = nil +local recordBroken = false +local ready = false +local showWaterStats = false -- uses the AI team to draw water height. +local scaleGraph = false +local dummyHog = nil +local dummySkip = 0 +local baseWaterSpeed = 2 +local waterSpeed = 0 +local waterAccel = 0 +local delayHeight = 32000 +local delayTime = 0 +local airMineX = {} +local airMineY = {} +local airMine = {} +local init = true + +function onParameters() + parseParams() + + if params["speed"] ~= nil then + baseWaterSpeed = params["speed"] + end + if params["accel"] ~= nil then + waterAccel = params["accel"] + if waterAccel ~= 0 then waterAccel = div(32640000,waterAccel) end + end + if params["delaytime"] ~= nil then + delayTime = params["delaytime"] + end + if params["delaytime"] ~= nil then + delayHeight = 32768-params["delayheight"] + end + if params["nocake"] ~= nil then addCake = false end +end + +function onGameInit() + -- Ensure people get same map for same theme + TurnTime = 999999999 + CaseFreq = 0 + Explosives = 0 + MineDudPercent = 0 + EnableGameFlags(gfOneClanMode) + DisableGameFlags(gfBottomBorder+gfBorder) + --This reduced startup time by only about 15% and looked ugly + --EnableGameFlags(gfDisableLandObjects) + -- force seed instead. Some themes will still be easier, but at least you won't luck out on the same theme + Seed = ClimbHome + if showWaterStats then + AddTeam(" ", 0x545C9D, "Simple", "Island", "Default") + elseif scaleGraph then + AddTeam(" ", 0x050505, "Simple", "Island", "Default") + end + if showWaterStats or scaleGraph then + dummyHog = AddHog(" ", 0, 1, "NoHat") + HH[dummyHog] = nil + totalHedgehogs = totalHedgehogs - 1 + teams[GetHogTeamName(dummyHog)] = nil + SendStat(siClanHealth, tostring(32640), " ") + end +end + +function onGearAdd(gear) + if GetGearType(gear) == gtHedgehog then + HH[gear] = 1 + totalHedgehogs = totalHedgehogs + 1 + teams[GetHogTeamName(gear)] = 1 + elseif init and GetGearType(gear) == gtAirMine then + airMine[gear] = 1 + end +end + +function onGearDelete(gear) + if gear == MrMine then + AddCaption("Once you set off the proximity trigger, Mr. Mine is not your friend",0xffffff,0) + MrMine = nil + elseif gear == Cake then + Cake = nil + elseif GetGearType(gear) == gtHedgehog then + onGameTick20() + onGearDamage(gear, 0) + HH[gear] = nil + end +end + +function onGameStart() + if showWaterStats or scaleGraph then + DeleteGear(dummyHog) + end + --SetClanColor(ClansCount-1, 0x0000ffff) appears to be broken + SendHealthStatsOff() + ShowMission(loc("Climb Home"), + loc("Rope to safety"), + loc("You are far from home, and the water is rising, climb up as high as you can!|Your score will be based on your height."), + -amRope, 0) + local x = 1818 + for h,i in pairs(HH) do + if h ~= nil then + -- SetGearPosition(h,x,32549) + SetGearPosition(h,x,108) + SetHealth(h,1) + if x < 1978 then x = x+32 else x = 1818 end + if GetEffect(h,heInvulnerable) == 0 then + SetEffect(h,heInvulnerable,1) + else + HogsAreInvulnerable = true + end + SetState(h,bor(GetState(h),gstInvisible)) + end + end +-- 1925,263 - Mr. Mine position + MrMine = AddGear(1925,263,gtMine,0,0,0,0) +end + +function onAmmoStoreInit() + SetAmmo(amRope, 9, 0, 0, 0) +end + +function onNewTurn() + if init then + init = false + for a,i in pairs(airMine) do + x,y = GetGearPosition(a) + airMineX[a] = x + airMineY[a] = y + end + else + for a,i in pairs(airMine) do + local x,y = GetGearPosition(a) + if not x or airMineX[a] ~= x or airMineY[a] ~= y then + DeleteGear(a) + AddGear(airMineX[a],airMineY[a], gtAirMine, gsttmpFlag, 0, 0, 0) + end + end + end + + ready = false + startTime = GameTime + --disable to preserve highest over multiple turns + --will need to change water check too ofc + MaxHeight = 32640 + hTagHeight = 33000 + SetWaterLine(32768) + YouWon = false + YouLost = false + tauntNoo = false + recordBroken = false + currTeam = GetHogTeamName(CurrentHedgehog) + if CurrentHedgehog ~= nil then + if CurrentHedgehog ~= dummyHog then + SetGearPosition(CurrentHedgehog, 1951,32640) + if not HogsAreInvulnerable then SetEffect(CurrentHedgehog,heInvulnerable,0) end + AddVisualGear(1951,32640,vgtExplosion,0,false) + SetState(CurrentHedgehog,band(GetState(CurrentHedgehog),bnot(gstInvisible))) + SetWeapon(amRope) + ready = true + else + dummySkip = GameTime+1 + end + end + for f,i in pairs(Fire) do + DeleteGear(f) + end + for s,i in pairs(Stars) do + DeleteVisualGear(s) + Stars[s] = nil + end + + if CurrentHedgehog ~= dummyHog then + for i = 0,12 do + flame = AddGear(2000+i*2,308, gtFlame, gsttmpFlag, 0, 0, 0) + SetTag(flame, 999999+i) + Fire[flame]=1 + end + end + if Cake ~= nil then DeleteGear(Cake) end + CakeTries = 0 +end + +--function onGearDelete(gear) +-- if gear == WaterRise and MaxHeight > 500 and CurrentHedgehog ~= nil and band(GetState(CurrentHedgehog),gstHHDriven) ~= 0 then +-- WaterRise = AddGear(0,0,gtWaterUp, 0, 0, 0, 0) +-- end +--end + +function FireBoom(x,y,d) -- going to add for rockets too + AddVisualGear(x,y,vgtExplosion,0,false) + -- should approximate circle by removing corners + --if BoomFire == nil then BoomFire = {} end + for i = 0,50 do + fx = GetRandom(d)-div(d,2) + fy = GetRandom(d)-div(d,2) + if fx<0 then + fdx = -5000-GetRandom(3000) + else + fdx = 5000+GetRandom(3000) + end + if fy<0 then + fdy = -5000-GetRandom(3000) + else + fdy = 5000+GetRandom(3000) + end + flame = AddGear(x+fx, y+fy, gtFlame, gsttmpFlag, fdx, fdy, 0) + SetTag(flame, 999999+i) + SetFlightTime(flame, 0) + Fire[flame]=1 +-- BoomFire[flame]=1 + end +end + + +function onGameTick20() + local x,y + if math.random(20) == 1 then AddVisualGear(2012,56,vgtSmoke,0,false) end + if CurrentHedgehog == dummyHog and dummySkip ~= 0 and dummySkip < GameTime then + ParseCommand("/skip") + dummySkip = 0 + end + + --if BoomFire ~= nil then + -- for f,i in pairs(BoomFire) do + -- if band(GetState(f),gstCollision~=0) then DeleteGear(f) end + -- end + -- BoomFire = nil + --end + + for s,i in pairs(Stars) do + g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(s) + if g1 > WaterLine + 500 then + DeleteVisualGear(s) + Stars[s] = nil + end + --else wasn't really visible, pointless. + -- g5 = g5+1 + -- if g5 > 360 then g5 = 0 end + -- SetVisualGearValues(s, g1, g2, g3, g4, g5, g6, g7, g8, g9, g10) + --end + end + + if CurrentHedgehog ~= nil then x,y = GetGearPosition(CurrentHedgehog) end + if Cake ~= nil and CurrentHedgehog ~= nil then + local cx,cy = GetGearPosition(Cake) + if y < cy-1500 then + DeleteGear(Cake) + Cake = nil + end + + if Cake ~= nil and GetHealth(Cake) < 999980 and gearIsInCircle(CurrentHedgehog,cx,cy,450) then + FireBoom(cx,cy,200) -- todo animate + DeleteGear(Cake) + Cake = nil + end + end + + if CurrentHedgehog ~= nil and TurnTimeLeft > 0 and band(GetState(CurrentHedgehog),gstHHDriven) ~= 0 then + if MaxHeight < delayHeight and + TurnTimeLeft<(999999999-delayTime) and + MaxHeight > 286 and WaterLine > 286 then + if waterAccel ~= 0 then + SetWaterLine(WaterLine-(baseWaterSpeed+div(getActualHeight(MaxHeight)*100,waterAccel))) + else + SetWaterLine(WaterLine-baseWaterSpeed) + end + end + if y > 0 and y < 30000 and MaxHeight > 286 and math.random(y) < 500 then + local s = AddVisualGear(0, 0, vgtStraightShot, 0, true) + local c = div(250000,y) + if c > 255 then c = 255 end + c = c * 0x10000 + 0xFF0000FF + SetVisualGearValues(s, + math.random(2048), -5000, 0, -1-(1/y*1000), + math.random(360), + 0, + 999999999, -- frameticks + 171, -- star + 0, c) + --, 0xFFCC00FF) -- could be fun to make colour shift as you rise... + Stars[s] = 1 + end + end + + if CurrentHedgehog ~= nil and band(GetState(CurrentHedgehog),gstHHDriven) == 0 then + for f,i in pairs(Fire) do -- takes too long to fall otherwise + DeleteGear(f) + end + if Cake ~= nil then + DeleteGear(Cake) + Cake = nil + end + end + + if CurrentHedgehog ~= nil and TurnTimeLeft > 0 then + local vx, vy = GetGearVelocity(CurrentHedgehog) + local distanceFromWater = WaterLine - y + + --[[ check joke awards ]] + -- navy award: when distance from main map is over 1000 + local navyDistance = 1250 + if x < -navyDistance or x > LAND_WIDTH+navyDistance then + local awarded = false + local dist = 0 + if jokeAwardNavy == nil then + awarded = true + else + if x < 0 then + dist = math.abs(x) + else + dist = x - LAND_WIDTH + end + if dist > jokeAwardNavy.distance then + awarded = true + end + end + if awarded == true then + jokeAwardNavy = { + hogName = GetHogName(CurrentHedgehog), + teamName = GetHogTeamName(CurrentHedgehog), + distance = dist + } + end + end + + -- Speed award for largest distance from water + if distanceFromWater > 3000 and WaterLine < 32000 then + local awarded = false + if jokeAwardSpeed == nil or distanceFromWater > jokeAwardSpeed.distance then + awarded = true + end + if awarded == true then + jokeAwardSpeed = { + hogName = GetHogName(CurrentHedgehog), + teamName = GetHogTeamName(CurrentHedgehog), + distance = distanceFromWater + } + end + end + if isSinglePlayer then + if distanceFromWater < 0 and not YouLost and not YouWon then + makeSinglePlayerLoserStats() + YouLost = true + end + if not YouWon and not YouLost and gearIsInBox(CurrentHedgehog, 1920, 252, 50, 50) then + local finishTime = (GameTime-startTime)/1000 + local roundedFinishTime = math.ceil(math.floor(finishTime+0.5)) + AddCaption(loc("Victory!")) + ShowMission(loc("Climb Home"), + loc("Made it!"), + string.format(loc("Ahhh, home, sweet home. Made it in %d seconds."), roundedFinishTime), + -amRope, 0) + PlaySound(sndVictory,CurrentHedgehog) + SetState(CurrentHedgehog, gstWinner) + SendStat(siGameResult, loc("You have beaten the challenge!")) + SendStat(siGraphTitle, loc("Your height over time")) + SendStat(siCustomAchievement, string.format(loc("%s reached home in %.3f seconds. Congratulations!"), loc(GetHogName(CurrentHedgehog)), finishTime)) + SendStat(siCustomAchievement, string.format(loc("%s bravely climbed up to a dizzy height of %d to reach home."),loc(GetHogName(CurrentHedgehog)), getActualHeight(RecordHeight))) + SendStat(siPointType, loc("seconds")) + SendStat(siPlayerKills, tostring(roundedFinishTime), loc(GetHogTeamName(CurrentHedgehog))) + + EndGame() + YouWon = true + end + elseif distanceFromWater < 0 and not YouLost then + makeMultiPlayerLoserStat(CurrentHedgehog) + deadHedgehogs = deadHedgehogs + 1 + YouLost = true + if deadHedgehogs >= totalHedgehogs then + makeFinalMultiPlayerStats() + EndGame() + end + end + + if GameTime % 500 == 0 then + --if isSinglePlayer and MaxHeight < 32000 and WaterRise == nil then + -- WaterRise = AddGear(0,0,gtWaterUp, 0, 0, 0, 0) + --end + if showWaterStats == true then + SendStat(siClanHealth, tostring(getActualHeight(WaterLine)), " ") + end + for t,i in pairs(teams) do + if currTeam == t then + SendStat(siClanHealth, tostring(getActualHeight(y)), t) + else + SendStat(siClanHealth, '0', t) + end + end + + -- play taunts + if not YouWon and not YouLost then + local nooDistance = 500 + if ((x < -nooDistance and vx < 0) or (x > LAND_WIDTH+nooDistance and vx > 0)) then + if (tauntNoo == false and distanceFromWater > 80) then + PlaySound(sndNooo, CurrentHedgehog) + tauntNoo = true + end + end + end + + if addCake and CakeTries < 10 and y < 32600 and y > 3000 and Cake == nil and band(GetState(CurrentHedgehog),gstHHDriven) ~= 0 then + -- doing this just after the start the first time to take advantage of randomness sources + -- Pick a clear y to start with + if y > 31000 then cy = 24585 elseif + y > 28000 then cy = 21500 elseif + y > 24000 then cy = 19000 elseif + y > 21500 then cy = 16000 elseif + y > 19000 then cy = 12265 elseif + y > 16000 then cy = 8800 elseif + y > 12000 then cy = 5700 else + cy = 400 end + Cake = AddGear(GetRandom(2048), cy, gtCake, 0, 0, 0, 0) + SetHealth(Cake,999999) + CakeTries = CakeTries + 1 + end + + if (y > 286) or (y < 286 and MaxHeight > 286) then + if y < MaxHeight and y > 286 then MaxHeight = y end + if y < 286 then MaxHeight = 286 end + if MaxHeight < hTagHeight then + hTagHeight = MaxHeight + if hTag ~= nil then DeleteVisualGear(hTag) end + hTag = AddVisualGear(0, 0, vgtHealthTag, 0, true) + local g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(hTag) + -- snagged from space invasion + SetVisualGearValues ( + hTag, --id + -(ScreenWidth/2) + 40, --xoffset + ScreenHeight - 60, --yoffset + 0, --dx + 0, --dy + 1.1, --zoom + 1, --~= 0 means align to screen + g7, --frameticks + -- 116px off bottom for lowest rock, 286 or so off top for position of chair + -- 32650 is "0" + 32640-hTagHeight, --value + 99999999999,--timer + GetClanColor(GetHogClan(CurrentHedgehog)) + ) + end + + if MaxHeight < RecordHeight then + RecordHeight = MaxHeight + local oldName = RecordHeightHogName + RecordHeightHogName = GetHogName(CurrentHedgehog) + if oldName == nil then recordBroken = true end + if not isSinglePlayer and RecordHeight > 1500 and not recordBroken then + recordBroken = true + AddCaption(string.format(loc("%s has passed the best height of %s!"), RecordHeightHogName, oldName)) + end + if not isSinglePlayer then + if rTag ~= nil then DeleteVisualGear(rTag) end + rTag = AddVisualGear(0, 0, vgtHealthTag, 0, true) + local g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(hTag) + -- snagged from space invasion + SetVisualGearValues ( + rTag, --id + -(ScreenWidth/2) + 100, --xoffset + ScreenHeight - 60, --yoffset + 0, --dx + 0, --dy + 1.1, --zoom + 1, --~= 0 means align to screen + g7, --frameticks + -- 116px off bottom for lowest rock, 286 or so off top for position of chair + -- 32650 is "0" + getActualHeight(RecordHeight), --value + 99999999999,--timer + GetClanColor(GetHogClan(CurrentHedgehog)) + ) + end + end + end + if MaxHeight > 286 then + if tTag ~= nil then DeleteVisualGear(tTag) end + tTag = AddVisualGear(0, 0, vgtHealthTag, 0, true) + local g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(tTag) + -- snagged from space invasion + SetVisualGearValues ( + tTag, --id + -(ScreenWidth/2) + 40, --xoffset + ScreenHeight - 100, --yoffset + 0, --dx + 0, --dy + 1.1, --zoom + 1, --~= 0 means align to screen + g7, --frameticks + (GameTime-startTime)/1000, --value + 99999999999,--timer + 0xffffffff + ) + end + end + end +end + +function onGearDamage(gear, damage) + if GetGearType(gear) == gtHedgehog and not YouLost and not YouWon then + -- Joke award for largest damage to hog + local qualifyDamage = 50 + if (damage >= qualifyDamage) then + local awarded = false + if jokeAwardDamage == nil or damage > jokeAwardDamage.damage then + awarded = true + end + if awarded == true then + jokeAwardDamage = { + hogName = GetHogName(CurrentHedgehog), + teamName = GetHogTeamName(CurrentHedgehog), + damage = damage + } + end + end + + if isSinglePlayer then + makeSinglePlayerLoserStats() + else + deadHedgehogs = deadHedgehogs + 1 + if deadHedgehogs >= totalHedgehogs then + makeFinalMultiPlayerStats() + EndGame() + end + makeMultiPlayerLoserStat(gear) + end + YouLost = true + end +end + +function makeLoserComment() + local m + if isSinglePlayer then m = 10 else m = 6 end + local r = math.random(1,m) + if r == 1 then text = loc("%s never got the ninja diploma.") + elseif r == 2 then text = loc("You have to move upwards, not downwards, %s!") + elseif r == 3 then text = loc("%s never wanted to reach for the sky in the first place.") + elseif r == 4 then text = loc("%s should try the rope training mission first.") + elseif r == 5 then text = loc("%s skipped ninja classes.") + elseif r == 6 then text = loc("%s doesn’t really know how to handle a rope properly.") + elseif r == 7 then text = loc("Better luck next time!") + elseif r == 8 then text = loc("It was all just bad luck!") + elseif r == 9 then text = loc("Well, that escalated quickly!") + elseif r == 10 then text = loc("What? Is it over already?") end + return text +end + +function makeSinglePlayerLoserStats() + local actualHeight = getActualHeight(RecordHeight) + SendStat(siGameResult, loc("You lose!")) + SendStat(siGraphTitle, loc("Your height over time")) + local text + if actualHeight > 30000 then text = loc("%s was damn close to home.") + elseif actualHeight > 28000 then text = loc("%s was close to home.") + elseif actualHeight > 24265 then text = loc("%s was good, but not good enough.") + elseif actualHeight > 16177 then text = loc("%s managed to pass half of the distance towards home.") + elseif actualHeight > 8088 then text = loc("%s went over a quarter of the way towards home.") + elseif actualHeight > 5100 then text = loc("%s still had a long way to go.") + elseif actualHeight > 2000 then text = loc("%s made it past the hogosphere.") + elseif actualHeight > 1500 then text = loc("%s barely made it past the hogosphere.") + else + text = makeLoserComment() + end + if actualHeight > 1500 then + SendStat(siCustomAchievement, string.format(text, RecordHeightHogName, actualHeight)) + else + SendStat(siCustomAchievement, string.format(text, RecordHeightHogName)) + end + SendStat(siPointType, loc("points")) + SendStat(siPlayerKills, actualHeight, loc(GetHogTeamName(CurrentHedgehog))) + EndGame() +end + +function makeMultiPlayerLoserStat(gear) + local teamName = GetHogTeamName(gear) + local actualHeight = getActualHeight(MaxHeight) + if teamBests[teamName] == nil then teamBests[teamName] = actualHeight end + if teamBests[teamName] < actualHeight then teamBests[teamName] = actualHeight end + if teamScoreStats[teamName] == nil then teamScoreStats[teamName] = {} end + table.insert(teamScoreStats[teamName], actualHeight) + --SendStat(siClanHealth, tostring(teamBests[teamName]), teamName) +end + +function makeFinalMultiPlayerStats() + local ranking = {} + for k,v in pairs(teamBests) do + table.insert(ranking, {name=k, score=v}) + end + local comp = function(table1, table2) + if table1.score < table2.score then + return true + else + return false + end + end + table.sort(ranking, comp) + + local winner = ranking[#ranking] + local loser = ranking[1] + SendStat(siGameResult, string.format(loc("%s wins!"), winner.name)) + SendStat(siGraphTitle, string.format(loc("Team’s best heights per round"))) + + if winner.score < 1500 then + SendStat(siCustomAchievement, string.format(loc("This round’s award for ultimate disappointment goes to: Everyone!"))) + else + if winner.score > 30000 then text = loc("%s (%s) reached for the sky and beyond with a height of %d!") + elseif winner.score > 24750 then text = loc("%s (%s) was certainly not afraid of heights: Peak height of %d!") + elseif winner.score > 16500 then text = loc("%s (%s) does not have to feel ashamed for their best height of %d.") + elseif winner.score > 8250 then text = loc("%s (%s) reached a decent peak height of %d.") + else text = loc("%s (%s) reached a peak height of %d.") end + SendStat(siCustomAchievement, string.format(text, RecordHeightHogName, winner.name, winner.score)) + + if loser.score < 1500 then + text = makeLoserComment() + SendStat(siCustomAchievement, string.format(text, loser.name)) + end + end + checkAwards() + for i = #ranking, 1, -1 do + SendStat(siPointType, loc("points")) + SendStat(siPlayerKills, tostring(ranking[i].score), ranking[i].name) + end +end + +function checkAwards() + if jokeAwardNavy ~= nil then + if isSinglePlayer then + SendStat(siCustomAchievement, string.format(loc("The Navy greets %s for managing to get in a distance of %d away from the mainland!"), jokeAwardNavy.hogName, jokeAwardNavy.distance)) + else + SendStat(siCustomAchievement, string.format(loc("Greetings from the Navy, %s (%s), for being a distance of %d away from the mainland!"), jokeAwardNavy.hogName, jokeAwardNavy.teamName, jokeAwardNavy.distance)) + end + end + if jokeAwardSpeed ~= nil then + if isSinglePlayer then + SendStat(siCustomAchievement, string.format(loc("Your hedgehog was panicly afraid of the water and decided to go in a safe distance of %d from it."), jokeAwardSpeed.distance)) + else + SendStat(siCustomAchievement, string.format(loc("%s (%s) was panicly afraid of the water and decided to get in a safe distance of %d from it."), jokeAwardSpeed.hogName, jokeAwardSpeed.teamName, jokeAwardSpeed.distance)) + end + end + if jokeAwardDamage ~= nil then + if isSinglePlayer then + SendStat(siCustomAchievement, string.format(loc("Ouch! That must have hurt. You mutilated your poor hedgehog hog with %d damage."), jokeAwardDamage.damage)) + else + SendStat(siCustomAchievement, string.format(loc("Ouch! That must have hurt. %s (%s) hit the ground with %d damage points."), jokeAwardDamage.hogName, jokeAwardDamage.teamName, jokeAwardDamage.damage)) + end + end +end + +function getActualHeight(height) + return 32640-height +end diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/ClimbHome/mask.png Binary file share/hedgewars/Data/Maps/ClimbHome/mask.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/ClimbHome/preview.png Binary file share/hedgewars/Data/Maps/ClimbHome/preview.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/Control/desc.txt --- a/share/hedgewars/Data/Maps/Control/desc.txt Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Maps/Control/desc.txt Tue Nov 10 20:43:13 2015 +0100 @@ -1,1 +1,1 @@ -en_US=Islands scattered everywhere\, full set of weapons. +en_US=Islands scattered everywhere\, full set of weapons. diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/Control/map.lua --- a/share/hedgewars/Data/Maps/Control/map.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Maps/Control/map.lua Tue Nov 10 20:43:13 2015 +0100 @@ -369,7 +369,7 @@ --AddCaption(zz) -- number of times it took to work end - ShowMission("CONTROL", + ShowMission(loc("CONTROL"), "", loc("Control pillars to score points.") .. "|" .. loc("Goal") .. ": " .. pointLimit .. " " .. loc("points"), 0, 0) @@ -418,7 +418,7 @@ end end - ShowMission("CONTROL", + ShowMission(loc("CONTROL"), loc("Team Scores") .. ":", totalComment, 0, 1600) diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/Control/map.png Binary file share/hedgewars/Data/Maps/Control/map.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/EarthRise/map.png Binary file share/hedgewars/Data/Maps/EarthRise/map.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/EarthRise/mask.png Binary file share/hedgewars/Data/Maps/EarthRise/mask.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/HedgeFortress/mask.png Binary file share/hedgewars/Data/Maps/HedgeFortress/mask.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/Islands/map.png Binary file share/hedgewars/Data/Maps/Islands/map.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/Knockball/desc.txt --- a/share/hedgewars/Data/Maps/Knockball/desc.txt Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Maps/Knockball/desc.txt Tue Nov 10 20:43:13 2015 +0100 @@ -1,1 +1,1 @@ -en_US=Knock your opponents off the platforms using only a bat! +en_US=Knock your opponents off the platforms using only a bat! diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/Knockball/map.lua --- a/share/hedgewars/Data/Maps/Knockball/map.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Maps/Knockball/map.lua Tue Nov 10 20:43:13 2015 +0100 @@ -68,3 +68,7 @@ end end end + +function onNewTurn() + SetWeapon(amBaseballBat) +end diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/Lonely_Island/mask.png Binary file share/hedgewars/Data/Maps/Lonely_Island/mask.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/Mushrooms/map.png Binary file share/hedgewars/Data/Maps/Mushrooms/map.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/Mushrooms/mask.png Binary file share/hedgewars/Data/Maps/Mushrooms/mask.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/Octorama/map.png Binary file share/hedgewars/Data/Maps/Octorama/map.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/Ruler/map.png Binary file share/hedgewars/Data/Maps/Ruler/map.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/Ruler/preview.png Binary file share/hedgewars/Data/Maps/Ruler/preview.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/SB_Crystal/mask.png Binary file share/hedgewars/Data/Maps/SB_Crystal/mask.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/SB_Grassy/mask.png Binary file share/hedgewars/Data/Maps/SB_Grassy/mask.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/SB_Grove/mask.png Binary file share/hedgewars/Data/Maps/SB_Grove/mask.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/SB_Haunty/mask.png Binary file share/hedgewars/Data/Maps/SB_Haunty/mask.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/SB_Oaks/mask.png Binary file share/hedgewars/Data/Maps/SB_Oaks/mask.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/SB_Shrooms/mask.png Binary file share/hedgewars/Data/Maps/SB_Shrooms/mask.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/SB_Tentacles/mask.png Binary file share/hedgewars/Data/Maps/SB_Tentacles/mask.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/ShoppaKing/map.png Binary file share/hedgewars/Data/Maps/ShoppaKing/map.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/ShoppaKing/map.xcf Binary file share/hedgewars/Data/Maps/ShoppaKing/map.xcf has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/Sticks/map.png Binary file share/hedgewars/Data/Maps/Sticks/map.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/Sticks/preview.png Binary file share/hedgewars/Data/Maps/Sticks/preview.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/TrophyRace/map.lua --- a/share/hedgewars/Data/Maps/TrophyRace/map.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Maps/TrophyRace/map.lua Tue Nov 10 20:43:13 2015 +0100 @@ -33,6 +33,7 @@ local worsthog = nil local besthog = nil +local besthogname = '' -- best time local besttime = maxtime + 1 @@ -78,7 +79,8 @@ SetHealth(CurrentHedgehog, 0) SetEffect(CurrentHedgehog, heInvulnerable, 0) x, y = GetGearPosition(CurrentHedgehog) - AddGear(x, y, gtShell, 0, 0, 0, 0) + AddGear(x, y-2, gtGrenade, 0, 0, 0, 2) + SetGearVelocity(CurrentHedgehog, 0, 0) worsttime = 99999 worsthog = nil lasthog = nil @@ -101,7 +103,7 @@ if CurrentHedgehog ~= nil then SetGearVelocity(CurrentHedgehog, 1, 0) SetGearPosition(CurrentHedgehog, start_area[1] + start_area[3] / 2, start_area[2] + start_area[4] / 2) - ParseCommand("setweap " .. string.char(amRope)) + SetWeapon(amRope) lasthog = CurrentHedgehog end end @@ -141,6 +143,7 @@ if ttime < besttime then besttime = ttime besthog = CurrentHedgehog + besthogname = GetHogName(besthog) hscore = hscore .. loc("NEW fastest lap: ") else hscore = hscore .. loc("Fastest lap: ") @@ -149,7 +152,7 @@ worsttime = ttime worsthog = CurrentHedgehog end - hscore = hscore .. GetHogName(besthog) .. " - " .. (besttime / 1000) .. " s | |" .. loc("Best laps per team: ") + hscore = hscore .. besthogname .. " - " .. (besttime / 1000) .. " s | |" .. loc("Best laps per team: ") if clan == ClansCount -1 then -- Time for elimination - worst hog is out and the worst hog vars are reset. diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/TrophyRace/map.png Binary file share/hedgewars/Data/Maps/TrophyRace/map.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/TrophyRace/map.xcf Binary file share/hedgewars/Data/Maps/TrophyRace/map.xcf has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/TrophyRace/mask.png Binary file share/hedgewars/Data/Maps/TrophyRace/mask.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/portal/mask.png Binary file share/hedgewars/Data/Maps/portal/mask.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/test/map.png Binary file share/hedgewars/Data/Maps/test/map.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/test2/preview.png Binary file share/hedgewars/Data/Maps/test2/preview.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/test3/preview.png Binary file share/hedgewars/Data/Maps/test3/preview.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Maps/testmap/preview.png Binary file share/hedgewars/Data/Maps/testmap/preview.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Missions/Campaign/01#Boot_Camp.lua --- a/share/hedgewars/Data/Missions/Campaign/01#Boot_Camp.lua Tue Nov 10 18:16:35 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,357 +0,0 @@ --- IMPORTANT -- THIS IS WORK IN PROGRESS AND VERY LIKELY TO BE CHANGED AGAIN --- IMPORTANT -- DO NOT TRANSLATE THIS AS IT USES THE OLD SYSTEM AND WILL BE UPDATED LATER! - -local teamnames = {} -local hognames = {} -teamnames[0] = { - ["en"] = "Bloody Rookies", - ["de"] = "Blutige Anfänger", - ["pl"] = "Żótodzioby", - ["sv"] = "Blodiga nybörjare", - ["es"] = "Reclutas", - ["pt_PT"] = "Recrutas", - ["pt_BR"] = "Malditos Recrutas", - ["sk"] = "Regruti" -} - -teamnames[1] = { - ["en"] = "Instructors", - ["de"] = "Ausbilder", - ["pl"] = "Instruktor", - ["sv"] = "Instruktör", - ["es"] = "Instructores", - ["pt_PT"] = "Instrutores", - ["pt_BR"] = "Instrutores", - ["sk"] = "Inštruktori" -} - -hognames[0] = { - ["en"] = "Joker", - ["de"] = "Joker", - ["pl"] = "Joker", - ["sv"] = "Joker", - ["es"] = "Joker", - ["pt_PT"] = "Joker", - ["pt_BR"] = "Comediante", - ["sk"] = "Komediant" -} - -hognames[1] = { - ["en"] = "Harthog", - ["de"] = "Harthog", - ["pl"] = "Harthog", - ["sv"] = "Harthog", - ["es"] = "Harthog", - ["pt_PT"] = "Harthog", - ["pt_BR"] = "Harthog", - ["sk"] = "Harthog" -} - -local caption = { - ["en"] = "Boot Camp", - ["de"] = "Grundausbildung", - ["pl"] = "Poligon", - ["sv"] = "Grundutbildning", - ["es"] = "Campamento militar", - ["pt_PT"] = "Acampamento militar", - ["pt_BR"] = "Acampamento Militar", - ["sk"] = "Výcvikový tábor" - -} - -local subcaption = { - ["en"] = "Follow the instructions!", - ["de"] = "Befolge die Anweisungen!", - ["pl"] = "Wykonuj polecenia!", - ["sv"] = "Följ instruktioner!", - ["es"] = "¡Sigue las órdenes!", - ["pt_PT"] = "Segue as instruções!", - ["pt_BR"] = "Siga as ordens!", - ["sk"] = "Postupujte podľa inštrukcií!" -} - -local goals = {} - -goals[0] = { - ["en"] = "Listen to your Drill Instructor and follow his lead!", - ["de"] = "Höre deinem Ausbilder zu und befolge seine Anweisungen!", - ["pl"] = "Słuchaj instruktora i wykonuj jego rozkazy!", - ["sv"] = "Lyssna på din instruktör och gör som han säger!", - ["es"] = "¡Escucha atentamente a tu instructor de maniobras y sigue sus órdenes!", - ["pt_PT"] = "Ouve atentamente o teu Instrutor e segue as suas ordens!", - ["pt_BR"] = "Escute seu instrutor de escavação e siga seu líder", - ["sk"] = "Počúvajte vášho inštruktora výcviku a vykonávajte jeho rozkazy!" -} - -goals[1] = { - ["en"] = "Destroy the target to finish this mission!", - ["de"] = "Zerstöre das Ziel, um diese Mission abzuschließen!", - ["pl"] = "Zniszcz cel by ukończyć misję!", - ["sv"] = "Förstör målet för att avklara uppdraget!", - ["es"] = "¡Destruye el objetivo para completar esta misión!", - ["pt_PT"] = "Destrói o alvo para completar esta missão!", - ["pt_BR"] = "Destrua o alvo para concluir a missão", - ["sk"] = "Pre ukončenie misie zneškodnite cieľ!" -} - -goals[2] = { - ["en"] = "Excellent! You've passed the Boot Camp!", - ["de"] = "Ausgezeichnet! Du hast das Ausbildungslager bestanden!", - ["pl"] = "Doskonale! Wyszedłeś cało z poligonu!", - ["sv"] = "Brilliant! Du har klarat av grundutbildningen!", - ["es"] = "¡Excelente! ¡Has completado la maniobra de hoy!", - ["pt_PT"] = "Excelente! Completaste o treino para recrutas!", - ["pt_BR"] = "Excelente! Você completou a manobra", - ["pt_BR"] = "Výborne! Prešli ste výcvikovým táborom!" -} - -local failed = { - ["en"] = "You failed! Follow the instructions and shoot the target only!", - ["de"] = "Du hast versagt! Befolge die Anweisungen und schieß nur auf das Ziel!", - ["pl"] = "Przegrałeś! Wykonuj instrukcje poprawnie i strzelaj tylko w podane cele!", - ["sv"] = "Du har misslyckats! Följ instruktionerna och sjut endast på målen!", - ["es"] = "¡Has fallado! ¡Sigue las instrucciones y destruye únicamente el objetivo!", - ["pt_PT"] = "Falhaste! Segue as instruções e destrói apenas o alvo!", - ["pt_BR"] = "Você falhou! Siga as instruções e atire somente no alvo", - ["sk"] = "Prehrali ste! Nasledujte inštrukcie a strieľajte iba na cieľ!" -} - -local drill = {} - -drill[0] = { - ["en"] = "Allright, maggot!", - ["de"] = "Also gut, du Made!", - ["pl"] = "Słuchaj mnie gnido!", - ["sv"] = "Dåså, din mask!", - ["es"] = "¡Muy bien, escoria!", - ["pt_PT"] = "Bom trabalho verme!", - ["pt_BR"] = "Parabéns escória", - ["sk"] = "Počúvaj, ty červík!" -} - -drill[1] = { - ["en"] = "Show that you aren't that useless.", - ["de"] = "Zeig, dass du nicht so nutzlos bist.", - ["pl"] = "Udowodnij, że nie jesteś bezwartościowy.", - ["sv"] = "Visa att du inte är så värdelös!", - ["es"] = "Demuéstrame que no eres tan inútil como pareces.", - ["pt_PT"] = "Prova-me que não és tão inútil como pareces.", - ["pt_BR"] = "Mostre que você não é um inútil.", - ["sk"] = "Dokáž, že nie si na svete úplne zbytočným." -} - -drill[2] = { - ["en"] = "Use [left] to move to the left!", - ["de"] = "Benutze [Links], um nach links zu gehen!", - ["pl"] = "Użyj [lewo] by poruszyć się w lewą stronę!", - ["sv"] = "Använd [vänster] för att gå åt vänster!", - ["es"] = "¡Aprieta [izquierda] para desplazarte a la izquierda!", - ["pt_PT"] = "Carrega [esquerda] para te moveres para a esquerda!", - ["pt_BR"] = "Use [esquerda] para mover para a esquerda", - ["sk"] = "Stlačte [vľavo] pre pohyb doľava" -} - -drill[3] = { - ["en"] = "Good! Now use [right] to come back!", - ["de"] = "Gut! Nun komm mit [Rechts] zurück!", - ["pl"] = "Dobzre, Teraz użyj [prawo] by wrócić!", - ["sv"] = "Bra! Använd nu [höger] för att gå tillbaka!", - ["es"] = "¡Muy bien! ¡Ahora presiona [derecha] para volver!", - ["pt_PT"] = "Muito bem! Agora pressiona [direita] para voltar!", - ["pt_BR"] = "Bom! Agora use [direita] para voltar", - ["sk"] = "Dobre! Teraz použite [vpravo] a vráťte sa naspäť!" -} - -drill[4] = { - ["en"] = "Excellent!", - ["de"] = "Ausgezeichnet!", - ["pl"] = "Wspaniale!", - ["sv"] = "Utmärkt!", - ["es"] = "¡Excelente!", - ["pt_PT"] = "Excelente!", - ["pt_BR"] = "Excelente!", - ["sk"] = "Výborne!" -} - -drill[5] = { - ["en"] = "Now jump to the left using [return]!", - ["de"] = "Jetzt springe mit [Eingabetaste] nach links!", - ["pl"] = "Teraz skocz w lewo używając [Enter]", - ["sv"] = "Hoppa nu åt vänster med hjälp av [enter]!", - ["es"] = "¡Ahora salta hacia la izquierda usando [intro]!", - ["pt_PT"] = "Agora salta para a esquerda pressionando [retrocesso]!", - ["pt_BR"] = "Agora pule para a esquerda usando [return]!", - ["sk"] = "Teraz skočte doľava stlačením [enter]!" -} - -drill[6] = { - ["en"] = "Use [up] and [down] to aim.", - ["de"] = "Benutze [Hoch] und [Runter], um zu zielen.", - ["pl"] = "Użyj klawiszy [góra] i [dół] by celować.", - ["sv"] = "Använd [upp] och [ner] för att sikta!", - ["es"] = "Presiora [arriba] y [abajo] para apuntar.", - ["pt_PT"] = "Pressiona [cima] e [baixo] para apontar.", - ["pt_BR"] = "Pressione [acima] e [abaixo] para mirar.", - ["sk"] = "Stlačte [hore] a [dole] pre mierenie." -} - -drill[7] = { - ["en"] = "Hold [space] to power up your shot and then release it to shoot.", - ["de"] = "Halte [Leertaste], um deinen Schuss aufzuladen, und lasse dann rechtzeitig los.", - ["pl"] = "Przytrzymaj spację by zwiększyć siłę strzału.", - ["sv"] = "Håll ner [mellanslag] för att få kraft och släpp för att skjuta!", - ["es"] = "Mantén presionada la [barra espaciadora] para controlar la fuerza del disparo y suéltala para disparar.", - ["pt_PT"] = "Mantem a [barra de espaços] pressionada para controlar a força do tiro e larga-a para disparar.", - ["pt_BR"] = "Mantenha pressionado [espaço] para aumentar a força do seu tiro e solte para atirar", - ["sk"] = "Držte stlačený [medzerník] pre nabíjanie, jeho uvoľnením vystrelíte." -} - -drill[8] = { - ["en"] = "Destroy the target to finish your basic training!", - ["de"] = "Zerstöre das Ziel, um deine Grundausbildung abzuschließen!", - ["pl"] = "Zniszcz cel by by ukończyć trening podstawowy!", - ["sv"] = "Förstör målet för att avsluta din grundutbildning!", - ["es"] = "¡Destruye el objetivo para completar el entrenamiento básico!", - ["pt_PT"] = "Destrói o alvo para completar o treino básico!", - ["pt_BR"] = "Destrua o alvo para terminar o treino básico", - ["sk"] = "Zneškodnite cieľ na ukončenie základného výcviku!" -} - -local function loc(text) - if text == nil then return "**missing**" - elseif text[L] == nil then return text["en"] - else return text[L] - end -end - -local player = nil -local instructor = nil -local target = nil - -function onGameStart() - -end - -local player_start_x = 2300 -local player_start_y = 1250 -local target_x = 1900 -local target_y = 1250 -local player_health = 100 -local instructor_health = 100 -local teamcolor = 14483456 - -local progress = 0 -local time_start = 0 - -function onGameTick() - if progress == -1 and (time_start + 2500) == GameTime then - EndGame() - elseif progress == -1 then - - elseif progress > 0 and ((TurnTimeLeft == 0) or (GetHealth(player) ~= player_health) or (GetHealth(instructor) ~= instructor_health)) then - progress = -1 - ShowMission(loc(caption), loc(subcaption), loc(failed), -amBazooka, 0) - time_start = GameTime - PlaySound(sndNooo) - TurnTimeLeft = 0 - elseif GameTime == 0 then - ShowMission(loc(caption), loc(subcaption), loc(goals[0]), -amBazooka, 0) - TurnTimeLeft = 60000 - elseif GameTime == 2500 then - FollowGear(instructor) - HogSay(instructor, loc(drill[0]), SAY_SAY) - elseif GameTime == 5000 then - FollowGear(instructor) - HogSay(instructor, loc(drill[1]), SAY_SAY) - elseif GameTime == 7500 then - FollowGear(instructor) - HogSay(instructor, loc(drill[2]), SAY_SHOUT) - progress = 1 - TurnTimeLeft = 10000 - elseif progress == 1 then - local x, y = GetGearPosition(player) - if x < player_start_x - 50 then - progress = 2 - FollowGear(instructor) - HogSay(instructor, loc(drill[3]), SAY_SHOUT) - TurnTimeLeft = 10000 - end - elseif progress == 2 then - local x, y = GetGearPosition(player) - if x > player_start_x then - progress = 3 - FollowGear(instructor) - HogSay(instructor, loc(drill[4]), SAY_SAY) - time_start = GameTime - end - elseif progress == 3 and (time_start + 2500 == GameTime) then - progress = 4 - FollowGear(instructor) - HogSay(instructor, loc(drill[5]), SAY_SHOUT) - HogTurnLeft(player, true) - TurnTimeLeft = 10000 - elseif progress == 4 then - local x, y = GetGearPosition(player) - if y < player_start_y then - progress = 5 - FollowGear(instructor) - HogSay(instructor, "Yeah!", SAY_SAY) - time_start = GameTime - TurnTimeLeft = 30000 - end - elseif progress == 5 and (time_start + 2500 == GameTime) then - FollowGear(instructor) - HogSay(instructor, loc(drill[6]), SAY_SAY) - elseif progress == 5 and (time_start + 5000 == GameTime) then - FollowGear(instructor) - HogSay(instructor, loc(drill[7]), SAY_SAY) - elseif progress == 5 and (time_start + 7500 == GameTime) then - FollowGear(instructor) - HogSay(instructor, loc(drill[8]), SAY_SHOUT) - ShowMission(loc(caption), loc(subcaption), loc(goals[1]), 1, 0) - target = AddGear(target_x, target_y, gtTarget, 0, 0, 0, 0) - TurnTimeLeft = 60000 - elseif progress == 5 and (time_start + 10000 == GameTime) then - FollowGear(target) - elseif progress == 6 then - progress = 7 - ShowMission(loc(caption), loc(subcaption), loc(goals[2]), 0, 0) - PlaySound(sndVictory) - time_start = GameTime - elseif progress == 7 and (time_start + 2500 == GameTime) then - EndGame() - end -end - -function onGameInit() - Seed = 0 - GameFlags = gfMultiWeapon + gfOneClanMode - TurnTime = 25000 - CaseFreq = 0 - MinesNum = 0 - Explosives = 0 - Delay = 2500 - Map = "Mushrooms" - Theme = "Nature" - - AddTeam(loc(teamnames[0]), teamcolor, "Simple", "Island", "Default") - player = AddHog(loc(hognames[0]), 0, player_health, "NoHat") - SetGearPosition(player, player_start_x, player_start_y) - - AddTeam(loc(teamnames[1]), teamcolor + 1, "Simple", "Island", "Default") - instructor = AddHog(loc(hognames[1]), 0, instructor_health, "NoHat") - SetGearPosition(instructor, player_start_x + 100, player_start_y) - HogTurnLeft(instructor, true) - - FollowGear(player) -end - -function onAmmoStoreInit() - SetAmmo(amBazooka, 9, 0, 0, 0) -end - -function onGearDelete(gear) - if GetGearType(gear) == gtTarget then - progress = 6 - end -end diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Missions/Campaign/01-Boot_Camp.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Missions/Campaign/01-Boot_Camp.lua Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,357 @@ +-- IMPORTANT -- THIS IS WORK IN PROGRESS AND VERY LIKELY TO BE CHANGED AGAIN +-- IMPORTANT -- DO NOT TRANSLATE THIS AS IT USES THE OLD SYSTEM AND WILL BE UPDATED LATER! + +local teamnames = {} +local hognames = {} +teamnames[0] = { + ["en"] = "Bloody Rookies", + ["de"] = "Blutige Anfänger", + ["pl"] = "Żótodzioby", + ["sv"] = "Blodiga nybörjare", + ["es"] = "Reclutas", + ["pt_PT"] = "Recrutas", + ["pt_BR"] = "Malditos Recrutas", + ["sk"] = "Regruti" +} + +teamnames[1] = { + ["en"] = "Instructors", + ["de"] = "Ausbilder", + ["pl"] = "Instruktor", + ["sv"] = "Instruktör", + ["es"] = "Instructores", + ["pt_PT"] = "Instrutores", + ["pt_BR"] = "Instrutores", + ["sk"] = "Inštruktori" +} + +hognames[0] = { + ["en"] = "Joker", + ["de"] = "Joker", + ["pl"] = "Joker", + ["sv"] = "Joker", + ["es"] = "Joker", + ["pt_PT"] = "Joker", + ["pt_BR"] = "Comediante", + ["sk"] = "Komediant" +} + +hognames[1] = { + ["en"] = "Harthog", + ["de"] = "Harthog", + ["pl"] = "Harthog", + ["sv"] = "Harthog", + ["es"] = "Harthog", + ["pt_PT"] = "Harthog", + ["pt_BR"] = "Harthog", + ["sk"] = "Harthog" +} + +local caption = { + ["en"] = "Boot Camp", + ["de"] = "Grundausbildung", + ["pl"] = "Poligon", + ["sv"] = "Grundutbildning", + ["es"] = "Campamento militar", + ["pt_PT"] = "Acampamento militar", + ["pt_BR"] = "Acampamento Militar", + ["sk"] = "Výcvikový tábor" + +} + +local subcaption = { + ["en"] = "Follow the instructions!", + ["de"] = "Befolge die Anweisungen!", + ["pl"] = "Wykonuj polecenia!", + ["sv"] = "Följ instruktioner!", + ["es"] = "¡Sigue las órdenes!", + ["pt_PT"] = "Segue as instruções!", + ["pt_BR"] = "Siga as ordens!", + ["sk"] = "Postupujte podľa inštrukcií!" +} + +local goals = {} + +goals[0] = { + ["en"] = "Listen to your Drill Instructor and follow his lead!", + ["de"] = "Höre deinem Ausbilder zu und befolge seine Anweisungen!", + ["pl"] = "Słuchaj instruktora i wykonuj jego rozkazy!", + ["sv"] = "Lyssna på din instruktör och gör som han säger!", + ["es"] = "¡Escucha atentamente a tu instructor de maniobras y sigue sus órdenes!", + ["pt_PT"] = "Ouve atentamente o teu Instrutor e segue as suas ordens!", + ["pt_BR"] = "Escute seu instrutor de escavação e siga seu líder", + ["sk"] = "Počúvajte vášho inštruktora výcviku a vykonávajte jeho rozkazy!" +} + +goals[1] = { + ["en"] = "Destroy the target to finish this mission!", + ["de"] = "Zerstöre das Ziel, um diese Mission abzuschließen!", + ["pl"] = "Zniszcz cel by ukończyć misję!", + ["sv"] = "Förstör målet för att avklara uppdraget!", + ["es"] = "¡Destruye el objetivo para completar esta misión!", + ["pt_PT"] = "Destrói o alvo para completar esta missão!", + ["pt_BR"] = "Destrua o alvo para concluir a missão", + ["sk"] = "Pre ukončenie misie zneškodnite cieľ!" +} + +goals[2] = { + ["en"] = "Excellent! You've passed the Boot Camp!", + ["de"] = "Ausgezeichnet! Du hast das Ausbildungslager bestanden!", + ["pl"] = "Doskonale! Wyszedłeś cało z poligonu!", + ["sv"] = "Brilliant! Du har klarat av grundutbildningen!", + ["es"] = "¡Excelente! ¡Has completado la maniobra de hoy!", + ["pt_PT"] = "Excelente! Completaste o treino para recrutas!", + ["pt_BR"] = "Excelente! Você completou a manobra", + ["pt_BR"] = "Výborne! Prešli ste výcvikovým táborom!" +} + +local failed = { + ["en"] = "You failed! Follow the instructions and shoot the target only!", + ["de"] = "Du hast versagt! Befolge die Anweisungen und schieß nur auf das Ziel!", + ["pl"] = "Przegrałeś! Wykonuj instrukcje poprawnie i strzelaj tylko w podane cele!", + ["sv"] = "Du har misslyckats! Följ instruktionerna och sjut endast på målen!", + ["es"] = "¡Has fallado! ¡Sigue las instrucciones y destruye únicamente el objetivo!", + ["pt_PT"] = "Falhaste! Segue as instruções e destrói apenas o alvo!", + ["pt_BR"] = "Você falhou! Siga as instruções e atire somente no alvo", + ["sk"] = "Prehrali ste! Nasledujte inštrukcie a strieľajte iba na cieľ!" +} + +local drill = {} + +drill[0] = { + ["en"] = "Allright, maggot!", + ["de"] = "Also gut, du Made!", + ["pl"] = "Słuchaj mnie gnido!", + ["sv"] = "Dåså, din mask!", + ["es"] = "¡Muy bien, escoria!", + ["pt_PT"] = "Bom trabalho verme!", + ["pt_BR"] = "Parabéns escória", + ["sk"] = "Počúvaj, ty červík!" +} + +drill[1] = { + ["en"] = "Show that you aren't that useless.", + ["de"] = "Zeig, dass du nicht so nutzlos bist.", + ["pl"] = "Udowodnij, że nie jesteś bezwartościowy.", + ["sv"] = "Visa att du inte är så värdelös!", + ["es"] = "Demuéstrame que no eres tan inútil como pareces.", + ["pt_PT"] = "Prova-me que não és tão inútil como pareces.", + ["pt_BR"] = "Mostre que você não é um inútil.", + ["sk"] = "Dokáž, že nie si na svete úplne zbytočným." +} + +drill[2] = { + ["en"] = "Use [left] to move to the left!", + ["de"] = "Benutze [Links], um nach links zu gehen!", + ["pl"] = "Użyj [lewo] by poruszyć się w lewą stronę!", + ["sv"] = "Använd [vänster] för att gå åt vänster!", + ["es"] = "¡Aprieta [izquierda] para desplazarte a la izquierda!", + ["pt_PT"] = "Carrega [esquerda] para te moveres para a esquerda!", + ["pt_BR"] = "Use [esquerda] para mover para a esquerda", + ["sk"] = "Stlačte [vľavo] pre pohyb doľava" +} + +drill[3] = { + ["en"] = "Good! Now use [right] to come back!", + ["de"] = "Gut! Nun komm mit [Rechts] zurück!", + ["pl"] = "Dobzre, Teraz użyj [prawo] by wrócić!", + ["sv"] = "Bra! Använd nu [höger] för att gå tillbaka!", + ["es"] = "¡Muy bien! ¡Ahora presiona [derecha] para volver!", + ["pt_PT"] = "Muito bem! Agora pressiona [direita] para voltar!", + ["pt_BR"] = "Bom! Agora use [direita] para voltar", + ["sk"] = "Dobre! Teraz použite [vpravo] a vráťte sa naspäť!" +} + +drill[4] = { + ["en"] = "Excellent!", + ["de"] = "Ausgezeichnet!", + ["pl"] = "Wspaniale!", + ["sv"] = "Utmärkt!", + ["es"] = "¡Excelente!", + ["pt_PT"] = "Excelente!", + ["pt_BR"] = "Excelente!", + ["sk"] = "Výborne!" +} + +drill[5] = { + ["en"] = "Now jump to the left using [return]!", + ["de"] = "Jetzt springe mit [Eingabetaste] nach links!", + ["pl"] = "Teraz skocz w lewo używając [Enter]", + ["sv"] = "Hoppa nu åt vänster med hjälp av [enter]!", + ["es"] = "¡Ahora salta hacia la izquierda usando [intro]!", + ["pt_PT"] = "Agora salta para a esquerda pressionando [retrocesso]!", + ["pt_BR"] = "Agora pule para a esquerda usando [return]!", + ["sk"] = "Teraz skočte doľava stlačením [enter]!" +} + +drill[6] = { + ["en"] = "Use [up] and [down] to aim.", + ["de"] = "Benutze [Hoch] und [Runter], um zu zielen.", + ["pl"] = "Użyj klawiszy [góra] i [dół] by celować.", + ["sv"] = "Använd [upp] och [ner] för att sikta!", + ["es"] = "Presiora [arriba] y [abajo] para apuntar.", + ["pt_PT"] = "Pressiona [cima] e [baixo] para apontar.", + ["pt_BR"] = "Pressione [acima] e [abaixo] para mirar.", + ["sk"] = "Stlačte [hore] a [dole] pre mierenie." +} + +drill[7] = { + ["en"] = "Hold [space] to power up your shot and then release it to shoot.", + ["de"] = "Halte [Leertaste], um deinen Schuss aufzuladen, und lasse dann rechtzeitig los.", + ["pl"] = "Przytrzymaj spację by zwiększyć siłę strzału.", + ["sv"] = "Håll ner [mellanslag] för att få kraft och släpp för att skjuta!", + ["es"] = "Mantén presionada la [barra espaciadora] para controlar la fuerza del disparo y suéltala para disparar.", + ["pt_PT"] = "Mantem a [barra de espaços] pressionada para controlar a força do tiro e larga-a para disparar.", + ["pt_BR"] = "Mantenha pressionado [espaço] para aumentar a força do seu tiro e solte para atirar", + ["sk"] = "Držte stlačený [medzerník] pre nabíjanie, jeho uvoľnením vystrelíte." +} + +drill[8] = { + ["en"] = "Destroy the target to finish your basic training!", + ["de"] = "Zerstöre das Ziel, um deine Grundausbildung abzuschließen!", + ["pl"] = "Zniszcz cel by by ukończyć trening podstawowy!", + ["sv"] = "Förstör målet för att avsluta din grundutbildning!", + ["es"] = "¡Destruye el objetivo para completar el entrenamiento básico!", + ["pt_PT"] = "Destrói o alvo para completar o treino básico!", + ["pt_BR"] = "Destrua o alvo para terminar o treino básico", + ["sk"] = "Zneškodnite cieľ na ukončenie základného výcviku!" +} + +local function loc(text) + if text == nil then return "**missing**" + elseif text[L] == nil then return text["en"] + else return text[L] + end +end + +local player = nil +local instructor = nil +local target = nil + +function onGameStart() + +end + +local player_start_x = 2300 +local player_start_y = 1250 +local target_x = 1900 +local target_y = 1250 +local player_health = 100 +local instructor_health = 100 +local teamcolor = 14483456 + +local progress = 0 +local time_start = 0 + +function onGameTick() + if progress == -1 and (time_start + 2500) == GameTime then + EndGame() + elseif progress == -1 then + + elseif progress > 0 and ((TurnTimeLeft == 0) or (GetHealth(player) ~= player_health) or (GetHealth(instructor) ~= instructor_health)) then + progress = -1 + ShowMission(loc(caption), loc(subcaption), loc(failed), -amBazooka, 0) + time_start = GameTime + PlaySound(sndNooo) + TurnTimeLeft = 0 + elseif GameTime == 0 then + ShowMission(loc(caption), loc(subcaption), loc(goals[0]), -amBazooka, 0) + TurnTimeLeft = 60000 + elseif GameTime == 2500 then + FollowGear(instructor) + HogSay(instructor, loc(drill[0]), SAY_SAY) + elseif GameTime == 5000 then + FollowGear(instructor) + HogSay(instructor, loc(drill[1]), SAY_SAY) + elseif GameTime == 7500 then + FollowGear(instructor) + HogSay(instructor, loc(drill[2]), SAY_SHOUT) + progress = 1 + TurnTimeLeft = 10000 + elseif progress == 1 then + local x, y = GetGearPosition(player) + if x < player_start_x - 50 then + progress = 2 + FollowGear(instructor) + HogSay(instructor, loc(drill[3]), SAY_SHOUT) + TurnTimeLeft = 10000 + end + elseif progress == 2 then + local x, y = GetGearPosition(player) + if x > player_start_x then + progress = 3 + FollowGear(instructor) + HogSay(instructor, loc(drill[4]), SAY_SAY) + time_start = GameTime + end + elseif progress == 3 and (time_start + 2500 == GameTime) then + progress = 4 + FollowGear(instructor) + HogSay(instructor, loc(drill[5]), SAY_SHOUT) + HogTurnLeft(player, true) + TurnTimeLeft = 10000 + elseif progress == 4 then + local x, y = GetGearPosition(player) + if y < player_start_y then + progress = 5 + FollowGear(instructor) + HogSay(instructor, "Yeah!", SAY_SAY) + time_start = GameTime + TurnTimeLeft = 30000 + end + elseif progress == 5 and (time_start + 2500 == GameTime) then + FollowGear(instructor) + HogSay(instructor, loc(drill[6]), SAY_SAY) + elseif progress == 5 and (time_start + 5000 == GameTime) then + FollowGear(instructor) + HogSay(instructor, loc(drill[7]), SAY_SAY) + elseif progress == 5 and (time_start + 7500 == GameTime) then + FollowGear(instructor) + HogSay(instructor, loc(drill[8]), SAY_SHOUT) + ShowMission(loc(caption), loc(subcaption), loc(goals[1]), 1, 0) + target = AddGear(target_x, target_y, gtTarget, 0, 0, 0, 0) + TurnTimeLeft = 60000 + elseif progress == 5 and (time_start + 10000 == GameTime) then + FollowGear(target) + elseif progress == 6 then + progress = 7 + ShowMission(loc(caption), loc(subcaption), loc(goals[2]), 0, 0) + PlaySound(sndVictory) + time_start = GameTime + elseif progress == 7 and (time_start + 2500 == GameTime) then + EndGame() + end +end + +function onGameInit() + Seed = 0 + GameFlags = gfMultiWeapon + gfOneClanMode + TurnTime = 25000 + CaseFreq = 0 + MinesNum = 0 + Explosives = 0 + Delay = 2500 + Map = "Mushrooms" + Theme = "Nature" + + AddTeam(loc(teamnames[0]), teamcolor, "Simple", "Island", "Default") + player = AddHog(loc(hognames[0]), 0, player_health, "NoHat") + SetGearPosition(player, player_start_x, player_start_y) + + AddTeam(loc(teamnames[1]), teamcolor + 1, "Simple", "Island", "Default") + instructor = AddHog(loc(hognames[1]), 0, instructor_health, "NoHat") + SetGearPosition(instructor, player_start_x + 100, player_start_y) + HogTurnLeft(instructor, true) + + FollowGear(player) +end + +function onAmmoStoreInit() + SetAmmo(amBazooka, 9, 0, 0, 0) +end + +function onGearDelete(gear) + if GetGearType(gear) == gtTarget then + progress = 6 + end +end diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Missions/Campaign/A_Classic_Fairytale/backstab.lua --- a/share/hedgewars/Data/Missions/Campaign/A_Classic_Fairytale/backstab.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Missions/Campaign/A_Classic_Fairytale/backstab.lua Tue Nov 10 20:43:13 2015 +0100 @@ -617,9 +617,9 @@ function DoDeployedDead() ShowMission(loc("Backstab"), loc("Brutus"), loc("You have failed to save the tribe!"), 0, 6000) - ParseCommand("teamgone " .. loc("Natives")) - ParseCommand("teamgone " .. loc("Tribe")) - ParseCommand("teamgone " .. loc("011101001")) + DismissTeam(loc("Natives")) + DismissTeam(loc("Tribe")) + DismissTeam(loc("011101001")) TurnTimeLeft = 0 end @@ -662,8 +662,8 @@ function DoKilledOther() ShowMission(loc("Backstab"), loc("Brutus"), loc("You have killed an innocent hedgehog!"), 0, 6000) - ParseCommand("teamgone " .. loc("Natives")) - ParseCommand("teamgone " .. loc("Tribe")) + DismissTeam(loc("Natives")) + DismissTeam(loc("Tribe")) TurnTimeLeft = 0 end @@ -770,10 +770,10 @@ end end - ParseCommand("teamgone " .. loc("Tribe")) - ParseCommand("teamgone " .. loc("Assault Team")) - ParseCommand("teamgone " .. loc("Reinforcements")) - ParseCommand("teamgone " .. loc("011101001")) + DismissTeam(loc("Tribe")) + DismissTeam(loc("Assault Team")) + DismissTeam(loc("Reinforcements")) + DismissTeam(loc("011101001")) TurnTimeLeft = 0 end diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Missions/Campaign/A_Classic_Fairytale/dragon.lua --- a/share/hedgewars/Data/Missions/Campaign/A_Classic_Fairytale/dragon.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Missions/Campaign/A_Classic_Fairytale/dragon.lua Tue Nov 10 20:43:13 2015 +0100 @@ -561,7 +561,7 @@ MinesTime = 3000 Explosives = 6 Delay = 10 - MapGen = 2 + MapGen = mgDrawn Theme = "City" SuddenDeathTurns = 25 diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Missions/Campaign/A_Classic_Fairytale/enemy.lua --- a/share/hedgewars/Data/Missions/Campaign/A_Classic_Fairytale/enemy.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Missions/Campaign/A_Classic_Fairytale/enemy.lua Tue Nov 10 20:43:13 2015 +0100 @@ -385,9 +385,9 @@ end function LoseMission() - ParseCommand("teamgone " .. loc("Natives")) - ParseCommand("teamgone " .. loc("Cannibals")) - ParseCommand("teamgone " .. loc("011101001")) + DismissTeam(loc("Natives")) + DismissTeam(loc("Cannibals")) + DismissTeam(loc("011101001")) TurnTimeLeft = 0 end @@ -403,7 +403,7 @@ if progress and progress<9 then SaveCampaignVar("Progress", "9") end - ParseCommand("teamgone " .. loc("011101001")) + DismissTeam(loc("011101001")) TurnTimeLeft = 0 end -----------------------------Misc-------------------------------------- diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Missions/Campaign/A_Classic_Fairytale/epil.lua --- a/share/hedgewars/Data/Missions/Campaign/A_Classic_Fairytale/epil.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Missions/Campaign/A_Classic_Fairytale/epil.lua Tue Nov 10 20:43:13 2015 +0100 @@ -378,7 +378,7 @@ end function onAmmoStoreInit() - SetAmmo(amAirStrike, 9, 0, 0, 0) + SetAmmo(amAirAttack, 9, 0, 0, 0) SetAmmo(amBaseballBat, 9, 0, 0, 0) SetAmmo(amBazooka, 9, 0, 0, 0) SetAmmo(amBlowTorch, 9, 0, 0, 0) diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Missions/Campaign/A_Classic_Fairytale/family.lua --- a/share/hedgewars/Data/Missions/Campaign/A_Classic_Fairytale/family.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Missions/Campaign/A_Classic_Fairytale/family.lua Tue Nov 10 20:43:13 2015 +0100 @@ -287,7 +287,7 @@ if progress and progress<7 then SaveCampaignVar("Progress", "7") end - ParseCommand("teamgone " .. loc("011101001")) + DismissTeam(loc("011101001")) TurnTimeLeft = 0 end @@ -339,8 +339,8 @@ function EndMission() RemoveEventFunc(CheckPrincessFreed) AddCaption("So the princess was never heard of again...") - ParseCommand("teamgone " .. loc("Natives")) - ParseCommand("teamgone " .. loc("011101001")) + DismissTeam(loc("Natives")) + DismissTeam(loc("011101001")) TurnTimeLeft = 0 end @@ -417,7 +417,7 @@ AddAmmo(cyborgs[1], amBaseballBat, 100) AddAmmo(cyborgs[1], amMolotov, 100) AddAmmo(cyborgs[1], amWatermelon, 1) - AddAmmo(cyborgs[1], amAirStrike, 2) + AddAmmo(cyborgs[1], amAirAttack, 2) AddAmmo(cyborgs[1], amDrillStrike, 1) end @@ -480,7 +480,7 @@ MinesTime = 3000 Explosives = 0 Delay = 10 - MapGen = 2 + MapGen = mgDrawn Theme = "Hell" SuddenDeathTurns = 35 diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Missions/Campaign/A_Classic_Fairytale/journey.lua --- a/share/hedgewars/Data/Missions/Campaign/A_Classic_Fairytale/journey.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Missions/Campaign/A_Classic_Fairytale/journey.lua Tue Nov 10 20:43:13 2015 +0100 @@ -80,7 +80,7 @@ --/////////////////////////Animation Functions/////////////////////// function AfterMidFailAnim() - ParseCommand("teamgone " .. loc("Natives")) + DismissTeam(loc("Natives")) TurnTimeLeft = 0 end @@ -268,7 +268,7 @@ end function TargetPrincess() - ParseCommand("setweap " .. string.char(amDEagle)) + SetWeapon(amDEagle) SetGearMessage(cyborg, gmUp) return true end @@ -568,7 +568,7 @@ end function KillPrincess() - ParseCommand("teamgone " .. loc("Cannibal Sentry")) + DismissTeam(loc("Cannibal Sentry")) TurnTimeLeft = 0 end --/////////////////////////////Misc Functions//////////////////////// @@ -804,7 +804,7 @@ function DoLeaksDead() AddCaption(loc("The village, unprepared, was destroyed by the cyborgs...")) - ParseCommand("teamgone " .. loc("Natives")) + DismissTeam(loc("Natives")) end function CheckDenseDead() @@ -813,7 +813,7 @@ function DoDenseDead() AddCaption(loc("The village, unprepared, was destroyed by the cyborgs...")) - ParseCommand("teamgone " .. loc("Natives")) + DismissTeam(loc("Natives")) end function CheckTookBlowTorch() @@ -895,7 +895,7 @@ function DoLost() AddAnim(endFailAnim) - AddFunction({func = ParseCommand, args = {'teamgone ' .. loc('Natives')}}) + AddFunction({func = DismissTeam, args = {loc('Natives')}}) end function CheckWon() @@ -912,8 +912,8 @@ function FinishWon() SwitchHog(leaks) - ParseCommand("teamgone " .. loc("Cannibal Sentry")) - ParseCommand("teamgone " .. loc("011101001")) + DismissTeam(loc("Cannibal Sentry")) + DismissTeam(loc("011101001")) TurnTimeLeft = 0 end diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Missions/Campaign/A_Classic_Fairytale/queen.lua --- a/share/hedgewars/Data/Missions/Campaign/A_Classic_Fairytale/queen.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Missions/Campaign/A_Classic_Fairytale/queen.lua Tue Nov 10 20:43:13 2015 +0100 @@ -521,9 +521,9 @@ function KillEnemy() if enemyFled == "1" then - ParseCommand("teamgone " .. loc("Leaderbot")) + DismissTeam(loc("Leaderbot")) end - ParseCommand("teamgone " .. loc("011101001")) + DismissTeam(loc("011101001")) TurnTimeLeft = 0 end @@ -675,7 +675,7 @@ AddAmmo(natives[1], amBazooka, 0) AddAmmo(natives[1], amGrenade, 0) AddAmmo(natives[1], amShotgun, 0) - AddAmmo(natives[1], amAirStrike, 0) + AddAmmo(natives[1], amAirAttack, 0) AddAmmo(natives[1], amMolotov, 0) end @@ -743,7 +743,7 @@ MinesTime = 3000 Explosives = 0 Delay = 10 - MapGen = 2 + MapGen = mgDrawn Theme = "Hell" SuddenDeathTurns = 20 diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Missions/Campaign/A_Classic_Fairytale/shadow.lua --- a/share/hedgewars/Data/Missions/Campaign/A_Classic_Fairytale/shadow.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Missions/Campaign/A_Classic_Fairytale/shadow.lua Tue Nov 10 20:43:13 2015 +0100 @@ -664,7 +664,7 @@ AddAnim(stronglingsAnim) AddFunction({func = AfterStronglingsAnim, args = {}}) stage = interWeakStage - ParseCommand("teamgone " .. loc("Weaklings")) + DismissTeam(loc("Weaklings")) end function CheckRefuse() @@ -823,7 +823,7 @@ AddCaption(loc("...and so the cyborgs took over the world...")) stage = loseStage TurnTimeLeft = 0 - ParseCommand("teamgone " .. loc("Natives")) + DismissTeam(loc("Natives")) end function CheckDenseDead() diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Missions/Campaign/A_Classic_Fairytale/united.lua --- a/share/hedgewars/Data/Missions/Campaign/A_Classic_Fairytale/united.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Missions/Campaign/A_Classic_Fairytale/united.lua Tue Nov 10 20:43:13 2015 +0100 @@ -112,7 +112,7 @@ if progress and progress<4 then SaveCampaignVar("Progress", "4") end - ParseCommand("teamgone " .. loc("011101001")) + DismissTeam(loc("011101001")) TurnTimeLeft = 0 end -----------------------------Animations-------------------------------- diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/cosmos.lua --- a/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/cosmos.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/cosmos.lua Tue Nov 10 20:43:13 2015 +0100 @@ -72,7 +72,7 @@ guard2.name = loc("Sam") guard2.x = 3400 guard2.y = 1800 -teamA.name = loc("PAoTH") +teamA.name = loc("PAotH") teamA.color = tonumber("FF0000",16) -- red teamB.name = loc("Guards") teamB.color = tonumber("0033FF",16) -- blue @@ -96,8 +96,8 @@ Map = "cosmos_map" -- custom map included in file end Theme = "Nature" - -- I had originally hero in PAoTH team and changed it, may reconsider though - -- PAoTH + -- I had originally hero in PAotH team and changed it, may reconsider though + -- PAotH AddTeam(teamC.name, teamC.color, "Bone", "Island", "HillBilly", "cm_birdy") hero.gear = AddHog(hero.name, 0, 100, "war_desertgrenadier1") AnimSetGearPosition(hero.gear, hero.x, hero.y) @@ -226,6 +226,10 @@ CheckEvents() end +function onGameTick20() + setFoundDeviceVisual() +end + function onPrecise() if GameTime > 3000 then SetAnimSkip(true) @@ -471,6 +475,34 @@ sendStatsOnRetry() end +function setFoundDeviceVisual() + --WriteLnToConsole("status: "..status.fruit01.." - "..status.fruit02) + if status.moon01 then + vgear = AddVisualGear(1116, 848, vgtBeeTrace, 0, false) + + end + if status.ice01 then + vgear = AddVisualGear(1512, 120, vgtBeeTrace, 0, false) + + end + if status.desert01 then + vgear = AddVisualGear(4015, 316, vgtBeeTrace, 0, false) + + end + if status.fruit01 and status.fruit02 then + vgear = AddVisualGear(2390, 384, vgtBeeTrace, 0, false) + + end + if status.death01 then + vgear = AddVisualGear(444, 400, vgtBeeTrace, 0, false) + + end + if status.final then + vgear = AddVisualGear(3070, 810, vgtBeeTrace, 0, false) + + end +end + -------------- ANIMATIONS ------------------ function Skipanim(anim) @@ -562,6 +594,7 @@ SendStat(siGameResult, loc("Hog Solo arrived at "..planet)) SendStat(siCustomAchievement, loc("Return to the mission menu by pressing the \"Go back\" button")) SendStat(siCustomAchievement, loc("You can choose another planet by replaying this mission")) + SendStat(siCustomAchievement, loc("Planets with completed main missions will be marked with a flower")) SendStat(siPlayerKills,'1',teamC.name) EndGame() end diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/death02.lua --- a/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/death02.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/death02.lua Tue Nov 10 20:43:13 2015 +0100 @@ -14,7 +14,7 @@ loc("Each time you play this missions enemy hogs will play in a random order").."|".. loc("At the start of the game each enemy hog has only the weapon that he is named after").."|".. loc("A random hedgehog will inherit the weapons of his deceased team-mates").."|".. - loc("If you kill a hedgehog with the respective weapon your healh points will be set to 100").."|".. + loc("If you kill a hedgehog with the respective weapon your health points will be set to 100").."|".. loc("If you injure a hedgehog you'll get 35% of the damage dealt").."|".. loc("Every time you kill an enemy hog your ammo will get reset").."|".. loc("Rope won't get reset") @@ -120,9 +120,9 @@ elseif deadHog.weapon == amGrenade then hero.grenadeAmmo = 0 end - local randomHog = math.random(1,table.getn(enemies)) + local randomHog = GetRandom(table.getn(enemies))+1 while not GetHealth(enemies[randomHog].gear) do - randomHog = math.random(1,table.getn(enemies)) + randomHog = GetRandom(table.getn(enemies))+1 end table.insert(enemies[randomHog].additionalWeapons, deadHog.weapon) for i=1,table.getn(deadHog.additionalWeapons) do @@ -211,7 +211,7 @@ table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("Each time you play this missions enemy hogs will play in a random order"), 5000}}) table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("At the start of the game each enemy hog has only the weapon that he is named after"), 5000}}) table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("A random hedgehog will inherit the weapons of his deceased team-mates"), 5000}}) - table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("If you kill a hedgehog with the respective weapon your healh points will be set to 100"), 5000}}) + table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("If you kill a hedgehog with the respective weapon your health points will be set to 100"), 5000}}) table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("If you injure a hedgehog you'll get 35% of the damage dealt"), 5000}}) table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("Every time you kill an enemy hog your ammo will get reset"), 5000}}) table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("Rope won't get reset"), 2000}}) @@ -229,7 +229,7 @@ function shuffleHogs(hogs) local hogsNumber = table.getn(hogs) for i=1,hogsNumber do - local randomHog = math.random(hogsNumber) + local randomHog = GetRandom(hogsNumber) + 1 hogs[i], hogs[randomHog] = hogs[randomHog], hogs[i] end end diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/desert01.hwp Binary file share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/desert01.hwp has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/desert01.lua --- a/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/desert01.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/desert01.lua Tue Nov 10 20:43:13 2015 +0100 @@ -10,6 +10,7 @@ HedgewarsScriptLoad("/Scripts/Locale.lua") HedgewarsScriptLoad("/Scripts/Animate.lua") +HedgewarsScriptLoad("/Scripts/Utils.lua") HedgewarsScriptLoad("/Missions/Campaign/A_Space_Adventure/global_functions.lua") ----------------- VARIABLES -------------------- @@ -24,7 +25,8 @@ local dialog01 = {} -- mission objectives local goals = { - [dialog01] = {missionName, loc("Getting ready"), loc("The device part is hidden in one of the crates! Go and get it!"), 1, 4500}, + [dialog01] = {missionName, loc("Getting ready"), loc("The device part is hidden in one of the crates! Go and get it!").."|".. + loc("Most of the destructible terrain in marked with blue color"), 1, 4500}, } -- crates local btorch1Y = 60 @@ -190,22 +192,22 @@ local x = 800 while x < 1630 do AddGear(x, 900, gtMine, 0, 0, 0, 0) - x = x + math.random(8,20) + x = x + GetRandom(13)+8 end x = 1890 while x < 2988 do AddGear(x, 760, gtMine, 0, 0, 0, 0) - x = x + math.random(8,20) + x = x + GetRandom(13)+8 end x = 2500 while x < 3300 do AddGear(x, 1450, gtMine, 0, 0, 0, 0) - x = x + math.random(8,20) + x = x + GetRandom(13)+8 end x = 1570 while x < 2900 do AddGear(x, 470, gtMine, 0, 0, 0, 0) - x = x + math.random(8,20) + x = x + GetRandom(13)+8 end if checkPointReached == 1 then @@ -333,7 +335,8 @@ function onHeroFleeFirstBattle(gear) if GetHealth(hero.gear) and GetHealth(smuggler1.gear) and heroIsInBattle - and distance(hero.gear, smuggler1.gear) > 1400 and StoppedGear(hero.gear) then + and not gearIsInCircle(smuggler1.gear, GetX(hero.gear), GetY(hero.gear), 1400, false) + and StoppedGear(hero.gear) then return true end return false @@ -486,7 +489,7 @@ table.insert(dialog01, {func = AnimSay, args = {ally.gear, loc("I have heard that the local tribes say that many years ago some PAotH scientists were dumping their waste here"), SAY_SAY, 5000}}) table.insert(dialog01, {func = AnimSay, args = {ally.gear, loc("H confirmed that there isn't such a PAotH activity logged"), SAY_SAY, 4000}}) table.insert(dialog01, {func = AnimSay, args = {ally.gear, loc("So, I believe that it's a good place to start"), SAY_SAY, 3000}}) - table.insert(dialog01, {func = AnimSay, args = {ally.gear, loc("Beware though! Many smugglers come often to explore these tunnels and scavage whatever valuable items they can find"), SAY_SAY, 5000}}) + table.insert(dialog01, {func = AnimSay, args = {ally.gear, loc("Beware though! Many smugglers come often to explore these tunnels and scavenge whatever valuable items they can find"), SAY_SAY, 5000}}) table.insert(dialog01, {func = AnimSay, args = {ally.gear, loc("They won't hesitate to attack you in order to rob you!"), SAY_SAY, 4000}}) table.insert(dialog01, {func = AnimWait, args = {hero.gear, 6000}}) table.insert(dialog01, {func = AnimSay, args = {hero.gear, loc("OK, I'll be extra careful!"), SAY_SAY, 4000}}) @@ -523,7 +526,7 @@ -- bazooka - grenade - rope - parachute - deagle - btorch - construct - portal - rcplane SaveCampaignVar("HeroAmmo", GetAmmoCount(hero.gear, amBazooka)..GetAmmoCount(hero.gear, amGrenade).. GetAmmoCount(hero.gear, amRope)..GetAmmoCount(hero.gear, amParachute)..GetAmmoCount(hero.gear, amDEagle).. - GetAmmoCount(hero.gear, amBlowTorch)..GetAmmoCount(hero.gear, amConstruction).. + GetAmmoCount(hero.gear, amBlowTorch)..GetAmmoCount(hero.gear, amGirder).. GetAmmoCount(hero.gear, amPortalGun)..GetAmmoCount(hero.gear, amRCPlane)) AnimCaption(hero.gear, loc("Checkpoint reached!"), 5000) end @@ -539,7 +542,7 @@ AddAmmo(hero.gear, amBlowTorch, tonumber(ammo:sub(6,6))) -- weird, if 0 bazooka isn't displayed in the weapons menu if tonumber(ammo:sub(7,7)) > 0 then - AddAmmo(hero.gear, amConstruction, tonumber(ammo:sub(7,7))) + AddAmmo(hero.gear, amGirder, tonumber(ammo:sub(7,7))) end AddAmmo(hero.gear, amPortalGun, tonumber(ammo:sub(8,8))) AddAmmo(hero.gear, amRCPlane, tonumber(ammo:sub(9,9))) diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/desert02.lua --- a/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/desert02.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/desert02.lua Tue Nov 10 20:43:13 2015 +0100 @@ -100,7 +100,7 @@ end function onNewTurn() - ParseCommand("setweap " .. string.char(amRope)) + SetWeapon(amRope) end function onGameTick() diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/final.lua --- a/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/final.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/final.lua Tue Nov 10 20:43:13 2015 +0100 @@ -63,14 +63,14 @@ x = 400 while x < 815 do local gear = AddGear(x, 500, gtExplosives, 0, 0, 0, 0) - x = x + math.random(15,40) + x = x + GetRandom(26) + 15 table.insert(explosives, gear) end -- mines local x = 360 while x < 815 do AddGear(x, 480, gtMine, 0, 0, 0, 0) - x = x + math.random(5,20) + x = x + GetRandom(16) + 5 end -- health crate SpawnHealthCrate(910, 5) @@ -150,6 +150,7 @@ end function heroWin(gear) + saveCompletedStatus(7) SendStat(siGameResult, loc("Congratulations, you have saved Hogera!")) SendStat(siCustomAchievement, loc("Hogera is safe!")) SendStat(siPlayerKills,'1',teamA.name) diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/fruit01.lua --- a/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/fruit01.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/fruit01.lua Tue Nov 10 20:43:13 2015 +0100 @@ -142,7 +142,7 @@ -- the rest of the Yellow Watermelons local yellowHats = { "fr_apple", "fr_banana", "fr_lemon", "fr_orange" } for i=1,7 do - yellowArmy[i].gear = AddHog(yellowArmy[i].name, 1, yellowArmy[i].health, yellowHats[math.random(1,4)]) + yellowArmy[i].gear = AddHog(yellowArmy[i].name, 1, yellowArmy[i].health, yellowHats[GetRandom(4)+1]) AnimSetGearPosition(yellowArmy[i].gear, yellowArmy[i].x, yellowArmy[i].y) end @@ -456,7 +456,7 @@ SendStat(siGameResult, loc("Hog Solo couldn't escape, try again!")) SendStat(siCustomAchievement, loc("You have to get to the left-most land and remove any enemy hog from there")) SendStat(siCustomAchievement, loc("You will play every 3 turns")) - SendStat(siCustomAchievement, loc("Green hogs won't intenionally hurt you")) + SendStat(siCustomAchievement, loc("Green hogs won't intentionally hurt you")) end SendStat(siPlayerKills,'1',teamC.name) SendStat(siPlayerKills,'0',teamA.name) diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/fruit02.lua --- a/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/fruit02.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/fruit02.lua Tue Nov 10 20:43:13 2015 +0100 @@ -66,7 +66,7 @@ teamA.color = tonumber("38D61C",16) -- green teamB.name = loc("Captain Lime") teamB.color = tonumber("38D61D",16) -- greenish -teamC.name = loc("Fruit Assasins") +teamC.name = loc("Fruit Assassins") teamC.color = tonumber("FF0000",16) -- red function onGameInit() @@ -108,11 +108,11 @@ green1.bot = AddHog(green1.name, 1, 100, "war_desertofficer") AnimSetGearPosition(green1.bot, green1.x, green1.y) green1.gear = green1.human - -- Fruit Assasins + -- Fruit Assassins local assasinsHats = { "NinjaFull", "NinjaStraight", "NinjaTriangle" } AddTeam(teamC.name, teamC.color, "Bone", "Island", "HillBilly", "cm_birdy") for i=1,table.getn(redHedgehogs) do - redHedgehogs[i].gear = AddHog(redHedgehogs[i].name, 1, 100, assasinsHats[math.random(1,3)]) + redHedgehogs[i].gear = AddHog(redHedgehogs[i].name, 1, 100, assasinsHats[GetRandom(3)+1]) AnimSetGearPosition(redHedgehogs[i].gear, 2010 + 50*i, 630) end @@ -138,7 +138,7 @@ AddAmmo(green1.bot, amGrenade, 6) AddAmmo(green1.bot, amDEagle, 2) HideHog(green1.bot) - -- Assasins weapons + -- Assassins weapons AddAmmo(redHedgehogs[1].gear, amBazooka, 6) AddAmmo(redHedgehogs[1].gear, amGrenade, 6) AddAmmo(redHedgehogs[1].bot, amDEagle, 6) @@ -467,7 +467,7 @@ saveCompletedStatus(3) SendStat(siGameResult, loc("Congratulations, you won!")) SendStat(siCustomAchievement, loc("You retrieved the lost part")) - SendStat(siCustomAchievement, loc("You defended yourself against Strawberry Assasins")) + SendStat(siCustomAchievement, loc("You defended yourself against Strawberry Assassins")) SendStat(siPlayerKills,'1',teamA.name) SendStat(siPlayerKills,'0',teamC.name) EndGame() @@ -532,7 +532,7 @@ table.insert(dialog03, {func = AnimWait, args = {green1.gear, 4000}}) table.insert(dialog03, {func = AnimSay, args = {green1.gear, loc("This Hog Solo is so naive! When he returns I'll shoot him and keep that device for myself!"), SAY_THINK, 4000}}) table.insert(dialog03, {func = goToThesurface, args = {hero.gear}}) - -- DIALOG04 - At crates, hero learns about the assasins ambush + -- DIALOG04 - At crates, hero learns about the Assassins ambush AddSkipFunction(dialog04, Skipanim, {dialog04}) table.insert(dialog04, {func = AnimWait, args = {hero.gear, 4000}}) table.insert(dialog04, {func = FollowGear, args = {hero.gear}}) @@ -549,7 +549,7 @@ end function wind() - SetWind(math.random(-100,100)) + SetWind(GetRandom(201)-100) end function saveHogsPositions() diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/fruit03.lua --- a/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/fruit03.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/fruit03.lua Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ ------------------- ABOUT ---------------------- -- --- Hero has get into an Red Strawberies ambush +-- Hero has get into an Red Strawberries ambush -- He has to eliminate the enemies by using limited -- ammo of sniper rifle and watermelon @@ -89,12 +89,12 @@ "fr_pumpkin", "Gasmask", "NinjaFull", "NinjaStraight", "NinjaTriangle" } AddTeam(teamC.name, teamC.color, "Bone", "Island", "HillBilly", "cm_birdy") for i=1,table.getn(enemiesEven) do - enemiesEven[i].gear = AddHog(enemiesEven[i].name, 1, 100, hats[math.random(1,table.getn(hats))]) + enemiesEven[i].gear = AddHog(enemiesEven[i].name, 1, 100, hats[GetRandom(table.getn(hats))+1]) AnimSetGearPosition(enemiesEven[i].gear, enemiesEven[i].x, enemiesEven[i].y) end AddTeam(teamB.name, teamB.color, "Bone", "Island", "HillBilly", "cm_birdy") for i=1,table.getn(enemiesOdd) do - enemiesOdd[i].gear = AddHog(enemiesOdd[i].name, 1, 100, hats[math.random(1,table.getn(hats))]) + enemiesOdd[i].gear = AddHog(enemiesOdd[i].name, 1, 100, hats[GetRandom(table.getn(hats))+1]) AnimSetGearPosition(enemiesOdd[i].gear, enemiesOdd[i].x, enemiesOdd[i].y) end @@ -233,7 +233,7 @@ AddSkipFunction(dialog01, Skipanim, {dialog01}) table.insert(dialog01, {func = AnimWait, args = {hero.gear, 3000}}) table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("Somewhere in the Fruit Planet Hog Solo got lost..."), 5000}}) - table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("...and got ambushed by the Red Strawberies"), 5000}}) + table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("...and got ambushed by the Red Strawberries"), 5000}}) table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("Use your available weapons in order to eliminate the enemies"), 5000}}) table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("You can only use the Sniper Rifle or the Watermelon bomb"), 5000}}) table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("You'll have only 2 watermelon bombs during the game"), 5000}}) diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/global_functions.lua --- a/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/global_functions.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/global_functions.lua Tue Nov 10 20:43:13 2015 +0100 @@ -35,7 +35,7 @@ status.moon01 = true end if allStatus:sub(2,2) == "1" then - status.fuit01 = true + status.fruit01 = true end if allStatus:sub(3,3) == "1" then status.fruit02 = true @@ -118,9 +118,3 @@ end return res end - --- returns the distance of 2 gears -function distance(gear1, gear2) - local dist = math.sqrt(math.pow((GetX(gear1) - GetX(gear2)),2) + math.pow((GetY(gear1) - GetY(gear2)),2)) - return dist -end diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/ice01.lua --- a/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/ice01.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/ice01.lua Tue Nov 10 20:43:13 2015 +0100 @@ -184,9 +184,9 @@ step = step + 1 if step == 5 then step = 0 - x = x + math.random(100,300) + x = x + GetRandom(201)+100 else - x = x + math.random(10,30) + x = x + GetRandom(21)+10 end end diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/ice02.lua --- a/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/ice02.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/ice02.lua Tue Nov 10 20:43:13 2015 +0100 @@ -5,6 +5,7 @@ HedgewarsScriptLoad("/Scripts/Locale.lua") HedgewarsScriptLoad("/Scripts/Animate.lua") +HedgewarsScriptLoad("/Scripts/Utils.lua") HedgewarsScriptLoad("/Missions/Campaign/A_Space_Adventure/global_functions.lua") ----------------- VARIABLES -------------------- @@ -115,7 +116,7 @@ if not hero.dead and CurrentHedgehog == ally.gear and challengeStarted then heroLost() elseif not hero.dead and CurrentHedgehog == hero.gear and challengeStarted then - ParseCommand("setweap " .. string.char(amJetpack)) + SetWeapon(amJetpack) end end @@ -188,7 +189,7 @@ AddSkipFunction(dialog01, Skipanim, {dialog01}) table.insert(dialog01, {func = AnimWait, args = {hero.gear, 3000}}) table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("In the Ice Planet flying saucer stadium..."), 5000}}) - table.insert(dialog01, {func = AnimSay, args = {ally.gear, loc("This is the olympic stadium of saucer flying..."), SAY_SAY, 4000}}) + table.insert(dialog01, {func = AnimSay, args = {ally.gear, loc("This is the Olympic stadium of saucer flying..."), SAY_SAY, 4000}}) table.insert(dialog01, {func = AnimSay, args = {ally.gear, loc("All the saucer pilots dream to come here one day in order to compete with the best!"), SAY_SAY, 5000}}) table.insert(dialog01, {func = AnimSay, args = {ally.gear, loc("Now you have the chance to try and claim the place that you deserve among the best..."), SAY_SAY, 6000}}) table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("Use the saucer and pass through the rings..."), 5000}}) @@ -249,9 +250,8 @@ function checkIfHeroInWaypoint() if not hero.dead then local wp = waypoints[currentWaypoint-1] - local distance = math.sqrt((GetX(hero.gear)-wp.x)^2 + (GetY(hero.gear)-wp.y)^2) - if distance <= radius+4 then - SetWind(math.random(-100,100)) + if gearIsInCircle(hero.gear, wp.x, wp.y, radius+4, false) then + SetWind(GetRandom(201)-100) return true end end diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/moon01.lua --- a/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/moon01.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/moon01.lua Tue Nov 10 20:43:13 2015 +0100 @@ -2,7 +2,7 @@ -- -- This is the first stop of hero's journey. -- Here he'll get fuels to continue traveling. --- However, the PAoTH allies of the hero have +-- However, the PAotH allies of the hero have -- been taken hostages by professor Hogevil. -- So hero has to get whatever available equipement -- there is and rescue them. @@ -84,7 +84,7 @@ minion3.name = loc("Minion") minion3.x = 3500 minion3.y = 1750 -teamA.name = loc("PAoTH") +teamA.name = loc("PAotH") teamA.color = tonumber("FF0000",16) -- red teamB.name = loc("Minions") teamB.color = tonumber("0033FF",16) -- blue @@ -114,7 +114,7 @@ hero.gear = AddHog(hero.name, 0, 100, "war_desertgrenadier1") end AnimSetGearPosition(hero.gear, hero.x, hero.y) - -- PAoTH + -- PAotH AddTeam(teamA.name, teamA.color, "Bone", "Island", "HillBilly", "cm_birdy") paoth1.gear = AddHog(paoth1.name, 0, 100, "scif_2001O") AnimSetGearPosition(paoth1.gear, paoth1.x, paoth1.y) @@ -360,7 +360,7 @@ elseif GetHealth(minion3.gear) then AnimSay(minion3.gear, loc("The boss has fallen! Retreat!"), SAY_SHOUT, 6000) end - ParseCommand("teamgone " .. teamB.name) + DismissTeam(teamB.name) AnimCaption(hero.gear, loc("Congrats! You made them run away!"), 6000) AnimWait(hero.gear,5000) @@ -377,7 +377,7 @@ function minionsDeath(gear) -- do staffs here AnimSay(professor.gear, loc("I may lost this battle, but I haven't lost the war yet!"), SAY_SHOUT, 6000) - ParseCommand("teamgone " .. teamC.name) + DismissTeam(teamC.name) AnimCaption(hero.gear, loc("Congrats! You won!"), 6000) AnimWait(hero.gear,5000) diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/moon02.lua --- a/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/moon02.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Missions/Campaign/A_Space_Adventure/moon02.lua Tue Nov 10 20:43:13 2015 +0100 @@ -98,7 +98,7 @@ if GetAmmoCount(hero.gear, amRope) == 0 then lose() end - ParseCommand("setweap " .. string.char(amRope)) + SetWeapon(amRope) TurnTimeLeft = runner.places[currentPosition].turnTime + previousTimeLeft previousTimeLeft = 0 end diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Missions/Training/Basic_Training_-_Bazooka.lua --- a/share/hedgewars/Data/Missions/Training/Basic_Training_-_Bazooka.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Missions/Training/Basic_Training_-_Bazooka.lua Tue Nov 10 20:43:13 2015 +0100 @@ -30,6 +30,8 @@ local player = nil -- This variable will grab the time left at the end of the round local time_goal = 0 +-- This variable stores the number of bazooka shots +local shots = 0 -- This is a custom function to make it easier to -- spawn more targets with just one line of code @@ -99,6 +101,8 @@ -- it spawns the first target that has to be destroyed. -- In addition it shows the scenario goal(s). function onGameStart() + -- Disable the graph in the stats screen, we don't need it + SendHealthStatsOff() -- Spawn the first target. spawnTarget() @@ -112,7 +116,7 @@ end function onNewTurn() - ParseCommand("setweap " .. string.char(amBazooka)) + SetWeapon(amBazooka) end -- This function is called every game tick. @@ -123,7 +127,7 @@ -- If time's up, set the game to be lost. -- We actually check the time to be "1 ms" as it -- will be at "0 ms" right at the start of the game. - if TurnTimeLeft < 40 and TurnTimeLeft > 0 and score < score_goal then + if TurnTimeLeft < 40 and TurnTimeLeft > 0 and score < score_goal and not game_lost then game_lost = true -- ... and show a short message. ShowMission(loc("Bazooka Training"), loc("Aiming Practice"), loc("Oh no! Time's up! Just try again."), -amSkip, 0) @@ -132,12 +136,40 @@ -- Just to be sure set the goal time to 1 ms time_goal = 1 end + + if band(GetState(player), gstDrowning) == gstDrowning and game_lost == false and score < score_goal then + game_lost = true + time_goal = 1 + AddCaption(loc("You lose!"), 0xFFFFFFFF, capgrpGameState) + ShowMission(loc("Bazooka Training"), loc("Aiming Practice"), loc("Oh no! You failed! Just try again."), -amSkip, 0) + end + -- If the goal is reached or we've lost ... if score == score_goal or game_lost then -- ... check to see if the time we'd like to -- wait has passed and then ... if end_timer == 0 then - -- ... end the game ... + -- Let’s create some stats for the stats screen! + -- We will expose the number of hit targets hit, launched bazooka and the accuracy + + SendStat(siPointType, loc("hits")) + SendStat(siPlayerKills, tostring(score), loc("'Zooka Team")) + SendStat(siCustomAchievement, string.format(loc("You have destroyed %d of %d targets."), score, score_goal)) + SendStat(siCustomAchievement, string.format(loc("You have launched %d bazookas."), shots)) + + -- We must avoid a division by zero + if(shots > 0) then + SendStat(siCustomAchievement, string.format(loc("Your accuracy was %.1f%%."), (score/shots)*100)) + end + if score == score_goal then + SendStat(siGameResult, loc("You have finished the bazooka training!")) + SendStat(siCustomAchievement, string.format(loc("%.1f seconds were remaining."), (time_goal/1000), math.ceil(time_goal/12))) + end + if game_lost then + SendStat(siGameResult, loc("You lose!")) + end + + -- Finally we end the game ... EndGame() else -- ... or just lower the timer by 20ms. @@ -184,3 +216,27 @@ end end end + +-- This function is called when a gear has been damaged. +-- We only use it to determine wheather our hog took damage in order to abort the mission. +function onGearDamage(gear, damage) + if GetGearType(gear) == gtHedgehog then + if not game_lost then + game_lost = true + AddCaption(loc("You lose!", 0xFFFFFFFF, capgrpGameState)) + ShowMission(loc("Bazooka Training") , loc("Aiming Practice"), loc("Oh no! You failed! Just try again."), -amSkip, 0) + + time_goal = 1 + end + end +end + + +-- This function is called after a gear is added. +-- We use it to count the number of bazooka shots. +function onGearAdd(gear) + -- Count the number of bazooka shots for our stats + if GetGearType(gear) == gtShell then + shots = shots + 1 + end +end diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Missions/Training/Basic_Training_-_Cluster_Bomb.lua --- a/share/hedgewars/Data/Missions/Training/Basic_Training_-_Cluster_Bomb.lua Tue Nov 10 18:16:35 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,123 +0,0 @@ -HedgewarsScriptLoad("/Scripts/Locale.lua") - -local player = nil -local scored = 0 -local end_timer = 1000 -local game_lost = false -local time_goal = 0 - -function spawnTarget() - - gear = AddGear(0, 0, gtTarget, 0, 0, 0, 0) - - if scored == 0 then x = 628 end - if scored == 1 then x = 891 end - if scored == 2 then x = 1309 end - if scored == 3 then x = 1128 end - if scored == 4 then x = 410 end - if scored == 5 then x = 1564 end - if scored == 6 then x = 1348 end - if scored == 7 then x = 169 end - if scored == 8 then x = 1720 end - if scored == 9 then x = 1441 end - if scored == 10 then x = 599 end - if scored == 11 then x = 1638 end - - if scored == 6 then - SetGearPosition(gear, 1248, 476) - else - SetGearPosition(gear, x, 0) - end - -end - -function onGameInit() - - Seed = 1 - GameFlags = gfDisableWind + gfInfAttack + gfOneClanMode - TurnTime = 180 * 1000 - Map = "Trash" - Theme = "Golf" - Goals = "Take down all the targets|Achieve it using only Cluster Bomb" - CaseFreq = 0 - MinesNum = 0 - Explosives = 0 - - AddTeam("The Hogies", 2850005, "Statue", "Island", "Hog Islands") - - player = AddHog(loc("Private Novak"), 0, 1, "war_desertGrenadier1") - SetGearPosition(player, 756, 370) - -end - -function onAmmoStoreInit() - - SetAmmo(amClusterBomb, 9, 0, 0, 0) - -end - -function onGameStart() - - ShowMission(loc("Cluster Bomb Training"), loc("Aiming Practice"), loc("You have to destroy 12 targets in 180 seconds"), -amClusterBomb, 5000) - spawnTarget() - -end - -function onGameTick20() - - if TurnTimeLeft < 40 and TurnTimeLeft > 0 and scored < 12 and game_lost == false then - game_lost = true - ShowMission(loc("Cluster Bomb Training"), loc("Aiming Practice"), loc("Oh no! Time's up! Just try again."), -amSkip, 0) - SetHealth(player, 0) - time_goal = 1 - end - - if scored == 12 or game_lost then - if end_timer == 0 then - EndGame() - else - TurnTimeLeft = time_goal - end - end_timer = end_timer - 20 - end - -end - -function onNewTurn() - ParseCommand("setweap " .. string.char(amClusterBomb)) -end - ---function onGearAdd(gear) ---end - -function onGearDamage(gear, damage) - - if GetGearType(gear) == gtTarget then - scored = scored + 1 - if scored < 12 then - spawnTarget() - else - if not game_lost then - - if TurnTimeLeft > 90 * 10 then - ShowMission(loc("Cluster Bomb MASTER!"), loc("Aiming Practice"), loc("Congratulations! You needed only half of time|to eliminate all targets."), 4, 0) - else - ShowMission(loc("Cluster Bomb Training"), loc("Aiming Practice"), loc("Congratulations! You've eliminated all targets|within the allowed time frame."), 0, 0) - end - PlaySound(sndVictory) - time_goal = TurnTimeLeft - end - end - end - - if GetGearType(gear) == gtHedgehog then - game_lost = true - ShowMission(loc("Cluster Bomb Training"), loc("Aiming Practice"), loc("Oh no! You failed! Just try again."), -amSkip, 0) - SetHealth(player, 0) - time_goal = 1 - end - -end - -function onGearDelete(gear) -end diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Missions/Training/Basic_Training_-_Grenade.lua --- a/share/hedgewars/Data/Missions/Training/Basic_Training_-_Grenade.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Missions/Training/Basic_Training_-_Grenade.lua Tue Nov 10 20:43:13 2015 +0100 @@ -107,7 +107,7 @@ end function onNewTurn() - ParseCommand("setweap " .. string.char(amGrenade)) + SetWeapon(amGrenade) end -- This function is called every game tick. @@ -134,14 +134,14 @@ if end_timer == 0 then -- Override the 'Draw' message with the appropriate message. if game_lost then - AddCaption("Mission lost!", 0xffba00ff,capgrpGameState) + AddCaption(loc("Mission lost!"), 0xffba00ff,capgrpGameState) else - AddCaption("Mission won!", 0xffba00ff,capgrpGameState) + AddCaption(loc("Mission won!"), 0xffba00ff,capgrpGameState) end -- Remove the team to end the game. Only do this once. if team_death == false then team_death = true - ParseCommand("teamgone " .. "Grenadiers") + DismissTeam(loc("Grenadiers")) end else -- ... or just lower the timer by 1. diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Missions/Training/Basic_Training_-_Rope.lua --- a/share/hedgewars/Data/Missions/Training/Basic_Training_-_Rope.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Missions/Training/Basic_Training_-_Rope.lua Tue Nov 10 20:43:13 2015 +0100 @@ -125,7 +125,7 @@ end function onNewTurn() - ParseCommand( "setweap " .. string.char( amRope ) ) -- Set the default weapon to Rope + SetWeapon(amRope) -- Set the default weapon to Rope end function onGameTick20() @@ -143,7 +143,7 @@ -- in either case, end the game if (Objective == true) or (GameLost == true) then if (WaitTime == 0) then - ParseCommand("teamgone " .. loc( "Rope Team" )) + DismissTeam(loc( "Rope Team" )) --SetHealth( Player, 0 ) -- Kill the player so he can't keep moving! --SetEffect( Player, heResurrectable, 0 ) diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Missions/Training/Basic_Training_-_Shotgun.lua --- a/share/hedgewars/Data/Missions/Training/Basic_Training_-_Shotgun.lua Tue Nov 10 18:16:35 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,178 +0,0 @@ --- Hedgewars Shotgun Training --- Scripting Example - --- Lines such as this one are comments - they are ignored --- by the game, no matter what kind of text is in there. --- It's also possible to place a comment after some real --- instruction as you see below. In short, everything --- following "--" is ignored. - ---------------------------------------------------------------- --- At first we implement the localization library using loadfile. --- This allows us to localize strings without needing to think --- about translations. --- We can use the function loc(text) to localize a string. - -HedgewarsScriptLoad("/Scripts/Locale.lua") - --- This variable will hold the number of destroyed targets. -local score = 0 --- This variable represents the number of targets to destroy. -local score_goal = 5 --- This variable controls how many milliseconds/ticks we'd --- like to wait before we end the round once all targets --- have been destroyed. -local end_timer = 1000 -- 1000 ms = 1 s --- This variable is set to true if the game is lost (i.e. --- time runs out). -local game_lost = false --- This variable will point to the hog's gear -local player = nil --- This variable will grab the time left at the end of the round -local time_goal = 0 - --- This is a custom function to make it easier to --- spawn more targets with just one line of code --- You may define as many custom functions as you --- like. -function spawnTarget() - -- add a new target gear - gear = AddGear(0, 0, gtTarget, 0, 0, 0, 0) - - -- move it to a random position within 0 and - -- LAND_WIDTH - the width of the map - FindPlace(gear, true, 0, LAND_WIDTH) - - -- move the target to a higher vertical position - -- to ensure it's not somewhere down below - x, y = GetGearPosition(gear) - SetGearPosition(gear, x, 0) -end - -function onNewTurn() - ParseCommand("setweap " .. string.char(amShotgun)) -end - --- This function is called before the game loads its --- resources. --- It's one of the predefined function names that will --- be called by the game. They give you entry points --- where you're able to call your own code using either --- provided instructions or custom functions. -function onGameInit() - -- At first we have to overwrite/set some global variables - -- that define the map, the game has to load, as well as - -- other things such as the game rules to use, etc. - -- Things we don't modify here will use their default values. - - -- The base number for the random number generator - Seed = 1 - -- Game settings and rules - GameFlags = gfMultiWeapon + gfOneClanMode - -- The time the player has to move each round (in ms) - TurnTime = 30000 - -- The frequency of crate drops - CaseFreq = 0 - -- The number of mines being placed - MinesNum = 0 - -- The number of explosives being placed - Explosives = 0 - -- The delay between each round - Delay = 0 - -- The map to be played - Map = "Mushrooms" - -- The theme to be used - Theme = "Nature" - - -- Create the player team - AddTeam(loc("Shotgun Team"), 14483456, "Simple", "Island", "Default") - -- And add a hog to it - player = AddHog(loc("Hunter"), 0, 1, "NoHat") - SetGearPosition(player, 1210, 230) -end - --- This function is called when the round starts --- it spawns the first target that has to be destroyed. --- In addition it shows the scenario goal(s). -function onGameStart() - -- Spawn the first target. - spawnTarget() - - -- Show some nice mission goals. - -- Parameters are: caption, sub caption, description, - -- extra text, icon and time to show. - -- A negative icon parameter (-n) represents the n-th weapon icon - -- A positive icon paramter (n) represents the (n+1)-th mission icon - -- A timeframe of 0 is replaced with the default time to show. - ShowMission(loc("Shotgun Training"), loc("Aiming Practice"), loc("Eliminate all targets before your time runs out.|You have unlimited ammo for this mission."), -amShotgun, 0) -end - --- This function is called every game tick. --- Note that there are 1000 ticks within one second. --- You shouldn't try to calculate too complicated --- code here as this might slow down your game. -function onGameTick20() - -- If time's up, set the game to be lost. - -- We actually check the time to be "1 ms" as it - -- will be at "0 ms" right at the start of the game. - if TurnTimeLeft < 40 and TurnTimeLeft > 20 and score < score_goal then - game_lost = true - -- ... and show a short message. - ShowMission(loc("Shotgun Training"), loc("Aiming Practice"), loc("Oh no! Time's up! Just try again."), -amSkip, 0) - -- How about killing our poor hog due to his poor performance? - SetHealth(player, 0) - -- Just to be sure set the goal time to 1 ms - time_goal = 1 - end - -- If the goal is reached or we've lost ... - if score == score_goal or game_lost then - -- ... check to see if the time we'd like to - -- wait has passed and then ... - if end_timer == 0 then - -- ... end the game ... - EndGame() - else - -- ... or just lower the timer by 1. - -- Reset the time left to stop the timer - TurnTimeLeft = time_goal - end - end_timer = end_timer - 20 - end -end - --- This function is called when the game is initialized --- to request the available ammo and probabilities -function onAmmoStoreInit() - -- add an unlimited supply of shotgun ammo - SetAmmo(amShotgun, 9, 0, 0, 0) -end - --- This function is called when a new gear is added. --- We don't need it for this training, so we can --- keep it empty. --- function onGearAdd(gear) --- end - --- This function is called before a gear is destroyed. --- We use it to count the number of targets destroyed. -function onGearDelete(gear) - -- We're only interested in target gears. - if GetGearType(gear) == gtTarget then - -- Add one point to our score/counter - score = score + 1 - -- If we haven't reached the goal ... - if score < score_goal then - -- ... spawn another target. - spawnTarget() - else - if not game_lost then - -- Otherwise show that the goal was accomplished - ShowMission(loc("Shotgun Training"), loc("Aiming Practice"), loc("Congratulations! You've eliminated all targets|within the allowed time frame."), 0, 0) - -- Also let the hogs shout "victory!" - PlaySound(sndVictory) - -- Save the time left so we may keep it. - time_goal = TurnTimeLeft - end - end - end -end diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Missions/Training/Basic_Training_-_Sniper_Rifle.lua --- a/share/hedgewars/Data/Missions/Training/Basic_Training_-_Sniper_Rifle.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Missions/Training/Basic_Training_-_Sniper_Rifle.lua Tue Nov 10 20:43:13 2015 +0100 @@ -17,6 +17,8 @@ -- This variable will hold the number of destroyed targets. local score = 0 +-- This variable will hold the number of shots from the sniper rifle +local shots = 0 -- This variable represents the number of targets to destroy. local score_goal = 31 -- This variable controls how many milliseconds/ticks we'd @@ -51,7 +53,7 @@ end function onNewTurn() - ParseCommand("setweap " .. string.char(amSniperRifle)) + SetWeapon(amSniperRifle) end -- This function is called before the game loads its @@ -83,7 +85,7 @@ -- The map to be played Map = "Ropes" -- The theme to be used - Theme = "City" + Theme = "Golf" -- Create the player team AddTeam(loc("Sniperz"), 14483456, "Simple", "Island", "Default") @@ -96,9 +98,11 @@ -- it spawns the first target that has to be destroyed. -- In addition it shows the scenario goal(s). function onGameStart() + -- Disable graph in stats screen + SendHealthStatsOff() -- Spawn the first target. spawnTarget(860,1020) - + -- Show some nice mission goals. -- Parameters are: caption, sub caption, description, -- extra text, icon and time to show. @@ -127,12 +131,14 @@ -- If time's up, set the game to be lost. -- We actually check the time to be "1 ms" as it -- will be at "0 ms" right at the start of the game. - if TurnTimeLeft < 40 and TurnTimeLeft > 0 and score < score_goal then + if TurnTimeLeft < 40 and TurnTimeLeft > 0 and score < score_goal and game_lost == false then game_lost = true -- ... and show a short message. + AddCaption(loc("Time's up!")) ShowMission(loc("Sniper Training"), loc("Aiming Practice"), loc("Oh no! Time's up! Just try again."), -amSkip, 0) - -- How about killing our poor hog due to his poor performance? - SetHealth(player, 0) + -- and generate the stats and go to the stats screen + generateStats() + EndGame() -- Just to be sure set the goal time to 1 ms time_goal = 1 end @@ -142,6 +148,7 @@ -- wait has passed and then ... if end_timer == 0 then -- ... end the game ... + generateStats() EndGame() else -- ... or just lower the timer by 1. @@ -160,20 +167,23 @@ end -- This function is called when a new gear is added. --- We don't need it for this training, so we can --- keep it empty. --- function onGearAdd(gear) --- end +-- We use it to count the number of shots, which we +-- in turn use to calculate the final score and stats +function onGearAdd(gear) + if GetGearType(gear) == gtSniperRifleShot then + shots = shots + 1 + end +end -- This function is called before a gear is destroyed. -- We use it to count the number of targets destroyed. function onGearDelete(gear) - + if GetGearType(gear) == gtCase then game_lost = true return end - + if (GetGearType(gear) == gtTarget) then -- remember when the target was hit for adjusting the camera last_hit_time = TurnTimeLeft @@ -310,3 +320,30 @@ end end end + +-- This function calculates the final score of the player and provides some texts and +-- data for the final stats screen +function generateStats() + local accuracy = (score/shots)*100 + local end_score_targets = (score * 200) + local end_score_overall + if not game_lost then + local end_score_time = math.ceil(time_goal/5) + local end_score_accuracy = math.ceil(accuracy * 100) + end_score_overall = end_score_time + end_score_targets + end_score_accuracy + + SendStat(siGameResult, loc("You have successfully finished the sniper rifle training!")) + SendStat(siCustomAchievement, string.format(loc("You have destroyed %d of %d targets (+%d points)."), score, score_goal, end_score_targets)) + SendStat(siCustomAchievement, string.format(loc("You have made %d shots."), shots)) + SendStat(siCustomAchievement, string.format(loc("Accuracy bonus: +%d points"), end_score_accuracy)) + SendStat(siCustomAchievement, string.format(loc("You had %.2fs remaining on the clock (+%d points)."), (time_goal/1000), end_score_time)) + else + SendStat(siGameResult, loc("You lose!")) + + SendStat(siCustomAchievement, string.format(loc("You have destroyed %d of %d targets (+%d points)."), score, score_goal, end_score_targets)) + SendStat(siCustomAchievement, string.format(loc("You have made %d shots."), shots)) + end_score_overall = end_score_targets + end + SendStat(siPlayerKills, tostring(end_score_overall), loc("Sniperz")) + SendStat(siPointType, loc("points")) +end diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Missions/Training/Challenge_-_Speed_Shoppa_-_Hedgelove.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Missions/Training/Challenge_-_Speed_Shoppa_-_Hedgelove.lua Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,38 @@ +HedgewarsScriptLoad("/Scripts/SpeedShoppa.lua") + +local params = {} +params.missionTitle = loc("Shoppa Love") +params.teamName = loc("Team of Hearts") +params.hogName = loc("Heartful") +params.teamFlag = "cm_iluvu" +params.teamGrave = "heart" +params.hogHat = "pinksunhat" +params.crateType = "health" +params.faceLeft = true + +params.time = 45000 +params.map = "Hedgelove" +params.theme = "Nature" + +params.hog_x = 410 +params.hog_y = 934 +params.crates = { + { x = 183, y = 710 }, + { x = 202, y = 519 }, + { x = 336, y = 356 }, + { x = 658, y = 363 }, + { x = 1029, y = 39 }, + { x = 758, y = 879 }, + { x = 1324, y = 896 }, + { x = 1410, y = 390 }, + { x = 1746, y = 348 }, + { x = 1870, y = 538 }, + { x = 1884, y = 723 }, + { x = 1682, y = 970 }, +} +params.extra_onGameStart = function() + PlaceGirder(394, 1000, 0) + PlaceGirder(1696, 1000, 0) +end + +SpeedShoppaMission(params) diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Missions/Training/Challenge_-_Speed_Shoppa_-_Ropes.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Missions/Training/Challenge_-_Speed_Shoppa_-_Ropes.lua Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,43 @@ +HedgewarsScriptLoad("/Scripts/SpeedShoppa.lua") + +local params = {} +params.missionTitle = loc("Ropes and Crates") +params.teamName = loc("Shoppa Union") +params.hogName = loc("Hook") +params.teamFlag = "cm_shoppa" +params.hogHat = "NoHat" + +params.time = 115000 +params.map = "Ropes" +params.theme = "City" + +params.hog_x = 3754 +params.hog_y = 1742 +params.crates = { + { x = 3533, y = 1404 }, + { x = 3884, y = 1048 }, + { x = 3366, y = 664 }, + { x = 3162, y = 630 }, + { x = 2872, y = 402 }, + { x = 3812, y = 322 }, + { x = 3685, y = 34 }, + { x = 3324, y = 540 }, + { x = 2666, y = 224 }, + { x = 2380, y = 1002 }, + { x = 2224, y = 1008 }, + { x = 2226, y = 854 }, + { x = 3274, y = 1754 }, + { x = 3016, y = 1278 }, + { x = 2756, y = 1716 }, + { x = 2334, y = 1756 }, + { x = 1716, y = 1752 }, + { x = 1526, y = 1464 }, + { x = 356, y = 1734 }, + { x = 598, y = 1444 }, + { x = 1084, y = 1150 }, + { x = 358, y = 834 }, + { x = 936, y = 200 }, + { x = 1540, y = 514 }, +} + +SpeedShoppaMission(params) diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Missions/Training/Challenge_-_Speed_Shoppa_-_ShoppaKing.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Missions/Training/Challenge_-_Speed_Shoppa_-_ShoppaKing.lua Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,54 @@ +HedgewarsScriptLoad("/Scripts/SpeedShoppa.lua") + +local params = {} +params.missionTitle = loc("The Customer is King") +params.teamName = loc("Shoppa Union") +params.hogName = loc("King Customer") +params.teamFlag = "cm_shoppa" +params.teamGrave = "money" +params.hogHat = "crown" + +params.time = 160000 +params.map = "ShoppaKing" +params.theme = "Castle" + +params.hog_x = 543 +params.hog_y = 1167 +params.crates = { + { x = 170, y = 172 }, + { x = 216, y = 478 }, + { x = 616, y = 966 }, + { x = 291, y = 1898 }, + { x = 486, y = 1965 }, + { x = 852, y = 1289 }, + { x = 1224, y = 1625 }, + { x = 925, y = 584 }, + { x = 2013, y = 141 }, + { x = 2250, y = 351 }, + { x = 2250, y = 537 }, + { x = 2472, y = 513 }, + { x = 1974, y = 459 }, + { x = 1995, y = 1068 }, + { x = 2385, y = 1788 }, + { x = 1698, y = 1725 }, + { x = 2913, y = 1092 }, + { x = 3972, y = 1788 }, + { x = 3762, y = 1635 }, + { x = 2577, y = 1473 }, + { x = 3612, y = 1068 }, + { x = 3945, y = 687 }, + { x = 2883, y = 618 }, + { x = 3543, y = 471 }, + { x = 3636, y = 306 }, + { x = 3210, y = 321 }, + { x = 3426, y = 126 }, + { x = 3033, y = 1590 }, + { x = 3774, y = 1341 }, + { x = 1254, y = 297 }, + { x = 1300, y = 1022 }, + { x = 1410, y = 1292 }, + { x = 868, y = 1812 }, + { x = 3426, y = 954 }, +} + +SpeedShoppaMission(params) diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Missions/Training/ClimbHome.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Missions/Training/ClimbHome.lua Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,41 @@ +HedgewarsScriptLoad("/Scripts/Locale.lua") + +local isSinglePlayer = true + +-- trying to allow random theme, but fixed theme objects... +-- Also skip some ugly themes, or ones where the sky is "meh" +--local themes = { "Art","Cake","City","EarthRise","Halloween","Olympics","Underwater","Bamboo","Castle","Compost","Eyes","Hell","Planes","Bath","Cave","CrazyMission","Freeway","Island","Sheep","Blox","Cheese","Deepspace","Fruit","Jungle","Snow","Brick","Christmas","Desert","Golf","Nature","Stage" } +local themes = {"Christmas","Hell","Bamboo","City","Island","Bath","Compost","Jungle","Desert","Nature","Olympics","Brick","EarthRise","Sheep","Cake","Freeway","Snow","Castle","Fruit","Stage","Cave","Golf","Cheese","Halloween"} +local showWaterStats = true -- uses the AI team to draw water height. +local scaleGraph = true +local totalHedgehogs = 0 +local HH = {} +local teams = {} +local dummyHog = nil + + +function onGameInit() + -- Ensure people get same map for same theme + Theme = themes[GetRandom(#themes)+1] + Seed = ClimbHome + TurnTime = 999999999 + EnableGameFlags(gfOneClanMode) + DisableGameFlags(gfBottomBorder+gfBorder) + CaseFreq = 0 + Explosives = 0 + MineDudPercent = 0 + Map = "ClimbHome" + AddTeam(loc("Lonely Hog"), 0xDD0000, "Simple", "Island", "Default") + player = AddHog(loc("Climber"), 0, 1, "NoHat") + if showWaterStats then + AddTeam(" ", 0x545C9D, "Simple", "Island", "Default") + elseif scaleGraph then + AddTeam(" ", 0x050505, "Simple", "Island", "Default") + end + if showWaterStats or scaleGraph then + dummyHog = AddHog(" ", 0, 1, "NoHat") + HH[dummyHog] = nil + totalHedgehogs = totalHedgehogs - 1 + SendStat(siClanHealth, tostring(32640), " ") + end +end diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Missions/Training/Target_Practice_-_Bazooka_easy.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Missions/Training/Target_Practice_-_Bazooka_easy.lua Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,35 @@ +HedgewarsScriptLoad("/Scripts/TargetPractice.lua") + +local params = { + ammoType = amBazooka, + gearType = gtShell, + missionTitle = loc("Target Practice: Bazooka (easy)"), + wind = 50, + solidLand = true, + map = "Lonely_Island", + theme = "Island", + hog_x = 1439, + hog_y = 482, + hogName = loc("Zook"), + hogHat = "war_americanww2helmet", + teamName = loc("Team Zook"), + targets = { + { x = 1310, y = 756 }, + { x = 1281, y = 893 }, + { x = 1376, y = 670 }, + { x = 1725, y = 907 }, + { x = 1971, y = 914 }, + { x = 1098, y = 955 }, + { x = 1009, y = 877 }, + { x = 930, y = 711 }, + { x = 771, y = 744 }, + { x = 385, y = 405 }, + { x = 442, y = 780 }, + { x = 620, y = 639 }, + { x = 311, y = 239 }, + }, + time = 80000, + shootText = loc("You have launched %d bazookas."), +} + +TargetPracticeMission(params) diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Missions/Training/Target_Practice_-_Bazooka_hard.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Missions/Training/Target_Practice_-_Bazooka_hard.lua Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,40 @@ +HedgewarsScriptLoad("/Scripts/TargetPractice.lua") + +local params = { + ammoType = amBazooka, + gearType = gtShell, + missionTitle = loc("Target Practice: Bazooka (hard)"), + wind = 20, + solidLand = true, + artillery = true, + map = "SB_Grassy", + theme = "Castle", + hog_x = 2112, + hog_y = 913, + hogName = loc("Zook"), + hogHat = "war_americanww2helmet", + teamName = loc("Team Zook"), + targets = { + { x = 2660, y = 936 }, + { x = 2857, y = 629 }, + { x = 3044, y = 851 }, + { x = 3200, y = 441 }, + { x = 2931, y = 440 }, + { x = 3264, y = 370 }, + { x = 1880, y = 684 }, + { x = 1392, y = 672 }, + { x = 1587, y = 656 }, + { x = 1300, y = 840 }, + { x = 952, y = 814 }, + { x = 862, y = 634 }, + { x = 748, y = 794 }, + { x = 639, y = 548 }, + { x = 1730, y = 549 }, + { x = 1466, y = 566 }, + { x = 3716, y = 954 }, + }, + time = 180000, + shootText = loc("You have launched %d bazookas."), +} + +TargetPracticeMission(params) diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Missions/Training/Target_Practice_-_Cluster_Bomb.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Missions/Training/Target_Practice_-_Cluster_Bomb.lua Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,33 @@ +HedgewarsScriptLoad("/Scripts/TargetPractice.lua") + +local params = { + ammoType = amClusterBomb, + gearType = gtClusterBomb, + missionTitle = loc("Cluster Bomb Training"), + solidLand = false, + map = "Trash", + theme = "Golf", + hog_x = 756, + hog_y = 370, + hogName = loc("Private Nolak"), + hogHat = "war_desertgrenadier1", + teamName = loc("The Hogies"), + targets = { + { x = 628, y = 0 }, + { x = 891, y = 0 }, + { x = 1309, y = 0 }, + { x = 1128, y = 0 }, + { x = 410, y = 0 }, + { x = 1564, y = 0 }, + { x = 1248, y = 476 }, + { x = 169, y = 0 }, + { x = 1720, y = 0 }, + { x = 1441, y = 0 }, + { x = 599, y = 0 }, + { x = 1638, y = 0 }, + }, + time = 180000, + shootText = loc("You have thrown %d cluster bombs."), +} + +TargetPracticeMission(params) diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Missions/Training/Target_Practice_-_Grenade_easy.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Missions/Training/Target_Practice_-_Grenade_easy.lua Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,30 @@ +HedgewarsScriptLoad("/Scripts/TargetPractice.lua") + +local params = { + ammoType = amGrenade, + gearType = gtGrenade, + missionTitle = loc("Target Practice: Grenade (easy)"), + solidLand = true, + artillery = true, + map = "SB_Crystal", + theme = "Cave", + hog_x = 2039, + hog_y = 684, + hogName = loc("Grenadier"), + hogHat = "war_desertgrenadier2", + teamName = loc("Grenade Group"), + targets = { + { x = 1834, y = 747 }, + { x = 2308, y = 729 }, + { x = 1659, y = 718 }, + { x = 1196, y = 704 }, + { x = 2650, y = 826 }, + { x = 1450, y = 705 }, + { x = 2774, y = 848 }, + { x = 2970, y = 704 }, + }, + time = 80000, + shootText = loc("You have thrown %d grenades."), +} + +TargetPracticeMission(params) diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Missions/Training/Target_Practice_-_Grenade_hard.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Missions/Training/Target_Practice_-_Grenade_hard.lua Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,41 @@ +HedgewarsScriptLoad("/Scripts/TargetPractice.lua") + +local params = { + ammoType = amGrenade, + gearType = gtGrenade, + missionTitle = loc("Target Practice: Grenade (hard)"), + solidLand = true, + artillery = true, + map = "SB_Crystal", + theme = "Cave", + hog_x = 1456, + hog_y = 669, + hogName = loc("Grenadier"), + hogHat = "war_desertgrenadier2", + teamName = loc("Grenade Group"), + targets = { + { x = 1190, y = 694 }, + { x = 962, y = 680 }, + { x = 1090, y = 489 }, + { x = 1664, y = 666 }, + { x = 1584, y = 580 }, + { x = 2160, y = 738 }, + { x = 1836, y = 726 }, + { x = 618, y = 753 }, + { x = 837, y = 668 }, + { x = 2424, y = 405 }, + { x = 2310, y = 742 }, + { x = 294, y = 897 }, + { x = 472, y = 855 }, + { x = 2949, y = 724}, + { x = 3356, y = 926 }, + { x = 3734, y = 918 }, + { x = 170, y = 874 }, + + + }, + time = 180000, + shootText = loc("You have thrown %d grenades."), +} + +TargetPracticeMission(params) diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Missions/Training/Target_Practice_-_Homing_Bee.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Missions/Training/Target_Practice_-_Homing_Bee.lua Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,35 @@ +HedgewarsScriptLoad("/Scripts/TargetPractice.lua") + +local params = { + ammoType = amBee, + gearType = gtBee, + missionTitle = loc("Target Practice: Homing Bee"), + solidLand = true, + map = "Hedgewars", + theme = "Nature", + hog_x = 1990, + hog_y = 514, + hogHat = "NoHat", + teamGrave = "bp2", + targets = { + { x = 1949, y = 273 }, + { x = 1734, y = 322 }, + { x = 1574, y = 340 }, + { x = 1642, y = 474 }, + { x = 2006, y = 356 }, + { x = 1104, y = 285 }, + { x = 565, y = 440 }, + { x = 732, y = 350 }, + { x = 2022, y = 396 }, + { x = 366, y = 360 }, + { x = 556, y = 300 }, + { x = 902, y = 306 }, + { x = 924, y = 411 }, + { x = 227, y = 510 }, + { x = 150, y = 300 }, + }, + time = 120000, + shootText = loc("You have launched %d homing bees."), +} + +TargetPracticeMission(params) diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Missions/Training/Target_Practice_-_Shotgun.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Missions/Training/Target_Practice_-_Shotgun.lua Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,38 @@ +HedgewarsScriptLoad("/Scripts/TargetPractice.lua") + +local params = { + ammoType = amShotgun, + gearType = gtShotgunShot, + missionTitle = loc("Target Practice: Shotgun"), + solidLand = false, + map = "SB_Haunty", + theme = "Halloween", + hog_x = 320, + hog_y = 324, + hogHat = "NoHat", + hogGrave = "Bones", + targets = { + { x = 495, y = 501 }, + { x = 227, y = 530 }, + { x = 835, y = 934 }, + { x = 1075, y = 889 }, + { x = 887, y = 915 }, + { x = 1148, y = 750 }, + { x = 916, y = 915 }, + { x = 1211, y = 700 }, + { x = 443, y = 505 }, + { x = 822, y = 964 }, + { x = 1092, y = 819 }, + { x = 1301, y = 683 }, + { x = 1480, y = 661 }, + { x = 1492, y = 786 }, + { x = 1605, y = 562 }, + { x = 1545, y = 466 }, + { x = 1654, y = 392 }, + { x = 1580, y = 334 }, + { x = 1730, y = 222 }, + }, + time = 90000, +} + +TargetPracticeMission(params) diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Missions/Training/User_Mission_-_Bamboo_Thicket.lua --- a/share/hedgewars/Data/Missions/Training/User_Mission_-_Bamboo_Thicket.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Missions/Training/User_Mission_-_Bamboo_Thicket.lua Tue Nov 10 20:43:13 2015 +0100 @@ -21,7 +21,7 @@ SuddenDeathTurns = 99999 AddTeam(loc("Pathetic Resistance"), 14483456, "Simple", "Island", "Default") - player = AddHog("Ikeda", 0, 10, "StrawHat") + player = AddHog(loc("Ikeda"), 0, 10, "StrawHat") AddTeam(loc("Cybernetic Empire"), 1175851, "Simple", "Island", "Default") enemy = AddHog(loc("Unit 835"), 1, 10, "cyborg1") diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Missions/Training/User_Mission_-_Dangerous_Ducklings.lua --- a/share/hedgewars/Data/Missions/Training/User_Mission_-_Dangerous_Ducklings.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Missions/Training/User_Mission_-_Dangerous_Ducklings.lua Tue Nov 10 20:43:13 2015 +0100 @@ -113,7 +113,7 @@ if endTimer >= 3000 then --SetHealth(instructor,0) TurnTimeLeft = 1 - ParseCommand("teamgone " .. loc("Bloody Rookies")) + DismissTeam(loc("Bloody Rookies")) end ShowMission(loc("MISSION FAILED"), loc(":("), loc("You've failed. Try again."), -amRope, 5000); end @@ -136,7 +136,7 @@ HogSay(player, loc("See ya!"), SAY_THINK) TurnTimeLeft = 3000 AddCaption(loc("Achievement Unlocked") .. ": " .. loc("Naughty Ninja"),0xffba00ff,capgrpMessage2) - ParseCommand("teamgone " .. loc("Blue Team")) + DismissTeam(loc("Blue Team")) gameWon = true elseif gear == enemy then HogSay(player, loc("Enjoy the swim..."), SAY_THINK) diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Missions/Training/User_Mission_-_Newton_and_the_Hammock.lua --- a/share/hedgewars/Data/Missions/Training/User_Mission_-_Newton_and_the_Hammock.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Missions/Training/User_Mission_-_Newton_and_the_Hammock.lua Tue Nov 10 20:43:13 2015 +0100 @@ -22,7 +22,7 @@ Theme = "Nature" AddTeam(loc("Pathetic Resistance"), 14483456, "Simple", "Island", "Default") - player = AddHog("Ikeda", 0, 48, "StrawHat") + player = AddHog(loc("Ikeda"), 0, 48, "StrawHat") AddTeam(loc("Cybernetic Empire"), 1175851, "Simple", "Island", "Default") enemy = AddHog(loc("Unit") .. " 811", 1, 100, "cyborg1") diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Missions/Training/User_Mission_-_Nobody_Laugh.lua --- a/share/hedgewars/Data/Missions/Training/User_Mission_-_Nobody_Laugh.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Missions/Training/User_Mission_-_Nobody_Laugh.lua Tue Nov 10 20:43:13 2015 +0100 @@ -1,130 +1,130 @@ --------------------------------------- --- NOBODY LAUGH --- a hilarious (not really) adventure --------------------------------------- - -HedgewarsScriptLoad("/Scripts/Locale.lua") -HedgewarsScriptLoad("/Scripts/Tracker.lua") - -local hhs = {} - -function onGameInit() - - Seed = 0 - GameFlags = gfInfAttack + gfPerHogAmmo +gfDisableWind - SuddenDeathTurns = 9999 - TurnTime = 180000 - CaseFreq = 0 - MinesNum = 0 - Explosives = 0 - Map = "Bath" - Theme = "Nature" - - AddTeam(loc("Nameless Heroes"), 14483456, "eyecross", "Wood", "HillBilly", "cm_birdy") - hhs[1] = AddHog(loc( "Hunter" ), 0, 1, "Skull") - SetGearPosition(hhs[1], 1267, 451) - hhs[2] = AddHog(loc("Drowner"), 0, 31, "mp3") - SetGearPosition(hhs[2], 1332, 451) - - AddTeam(loc("Clowns"), 1175851, "Duck2", "Tank", "Mobster", "cm_spider") - hhs[3] = AddHog("Poison", 5, 100, "WhySoSerious") - SetGearPosition(hhs[3], 1133, 446) - hhs[4] = AddHog("Bobo", 5, 100, "clown") - SetGearPosition(hhs[4], 1215, 553) - hhs[5] = AddHog("Copper", 5, 10, "clown-copper") - SetGearPosition(hhs[5], 414, 376) - hhs[6] = AddHog("Derp", 5, 100, "clown-crossed") - SetGearPosition(hhs[6], 1590, 886) - hhs[7] = AddHog("Eckles", 5, 100, "clown-copper") - SetGearPosition(hhs[7], 772, 754) - hhs[8] = AddHog("Frank", 5, 50, "clown-copper") - SetGearPosition(hhs[8], 1688, 714) - hhs[9] = AddHog("Harry", 5, 50, "clown-copper") - SetGearPosition(hhs[9], 1932, 837) - hhs[10] = AddHog("Igmund", 5, 50, "WhySoSerious") - SetGearPosition(hhs[10], 1601, 733) - -end - -function onGameStart() - - AddAmmo(enemy, amAirAttack, 100) - - ShowMission( loc("Nobody Laugh"), - loc("User Challenge"), - loc("Eliminate the enemy before the time runs out") - , 0, 0 - ) - - -- GIRDERS - PlaceGirder(1212, 710, 7) - PlaceGirder(1215, 570, 4) - PlaceGirder(1288, 520, 2) - PlaceGirder(1184, 468, 4) - PlaceGirder(1344, 468, 4) - PlaceGirder(1247, 346, 4) - - PlaceGirder(667, 438, 4) - PlaceGirder(507, 438, 4) - PlaceGirder(434, 487, 2) - PlaceGirder(505, 537, 4) - PlaceGirder(665, 537, 4) - PlaceGirder(737, 487, 2) - - PlaceGirder(416, 465, 6) - PlaceGirder(1415, 378, 6) - PlaceGirder(1300, 625, 3) - PlaceGirder(1359, 566, 3) - PlaceGirder(1436, 538, 0) - PlaceGirder(1505, 468, 4) - - ------ AMMO CRATE LIST ------ - tempG = SpawnAmmoCrate(1242, 315, amBaseballBat) - tempG = SpawnAmmoCrate(1309, 315, amAirAttack) - tempG = SpawnAmmoCrate(144, 895, amAirAttack) - tempG = SpawnAmmoCrate(664, 699, amIceGun) - tempG = SpawnAmmoCrate(1572, 444, amFirePunch) - tempG = SpawnAmmoCrate(1574, 382, amDynamite) - - ------ UTIL CRATE LIST ------ - tempG = SpawnUtilityCrate(654, 513, amParachute) - tempG = SpawnUtilityCrate(1569, 413, amParachute) - - -- HOG AMMO - AddAmmo(hhs[1],amParachute,1) - AddAmmo(hhs[1],amHammer,1) - AddAmmo(hhs[2],amWhip,1) - - for i = 3, 10 do - AddAmmo(hhs[i], amDeagle, 100) - AddAmmo(hhs[i], amShotgun, 100) - AddAmmo(hhs[i], amGrenade, 100) - AddAmmo(hhs[i], amBazooka, 100) - AddAmmo(hhs[i], amDrill, 100) - end - -end - -function onNewTurn() - SetWind(100) -end - -function onAmmoStoreInit() - - SetAmmo(amBaseballBat, 0, 0, 0, 1) - SetAmmo(amAirAttack, 0, 0, 0, 1) - SetAmmo(amFirePunch, 0, 0, 0, 1) - SetAmmo(amDynamite, 0, 0, 0, 1) - SetAmmo(amHammer, 0, 0, 0, 1) - SetAmmo(amIceGun, 0, 0, 0, 1) - - SetAmmo(amParachute, 0, 0, 0, 1) - - SetAmmo(amSwitch, 9, 0, 0, 0) - SetAmmo(amSkip, 9, 0, 0, 0) - -end - ------------------------------- --- I'm in whitesppaaaaaaaaaacceeeee :D ------------------------------- +-------------------------------------- +-- NOBODY LAUGH +-- a hilarious (not really) adventure +-------------------------------------- + +HedgewarsScriptLoad("/Scripts/Locale.lua") +HedgewarsScriptLoad("/Scripts/Tracker.lua") + +local hhs = {} + +function onGameInit() + + Seed = 0 + GameFlags = gfInfAttack + gfPerHogAmmo +gfDisableWind + SuddenDeathTurns = 9999 + TurnTime = 180000 + CaseFreq = 0 + MinesNum = 0 + Explosives = 0 + Map = "Bath" + Theme = "Nature" + + AddTeam(loc("Nameless Heroes"), 14483456, "eyecross", "Wood", "HillBilly", "cm_birdy") + hhs[1] = AddHog(loc( "Hunter" ), 0, 1, "Skull") + SetGearPosition(hhs[1], 1267, 451) + hhs[2] = AddHog(loc("Drowner"), 0, 31, "mp3") + SetGearPosition(hhs[2], 1332, 451) + + AddTeam(loc("Clowns"), 1175851, "Duck2", "Tank", "Mobster", "cm_spider") + hhs[3] = AddHog(loc("Poison"), 5, 100, "WhySoSerious") + SetGearPosition(hhs[3], 1133, 446) + hhs[4] = AddHog(loc("Bobo"), 5, 100, "clown") + SetGearPosition(hhs[4], 1215, 553) + hhs[5] = AddHog(loc("Copper"), 5, 10, "clown-copper") + SetGearPosition(hhs[5], 414, 376) + hhs[6] = AddHog(loc("Derp"), 5, 100, "clown-crossed") + SetGearPosition(hhs[6], 1590, 886) + hhs[7] = AddHog(loc("Eckles"), 5, 100, "clown-copper") + SetGearPosition(hhs[7], 772, 754) + hhs[8] = AddHog(loc("Frank"), 5, 50, "clown-copper") + SetGearPosition(hhs[8], 1688, 714) + hhs[9] = AddHog(loc("Harry"), 5, 50, "clown-copper") + SetGearPosition(hhs[9], 1932, 837) + hhs[10] = AddHog(loc("Igmund"), 5, 50, "WhySoSerious") + SetGearPosition(hhs[10], 1601, 733) + +end + +function onGameStart() + + AddAmmo(enemy, amAirAttack, 100) + + ShowMission( loc("Nobody Laugh"), + loc("User Challenge"), + loc("Eliminate the enemy before the time runs out") + , 0, 0 + ) + + -- GIRDERS + PlaceGirder(1212, 710, 7) + PlaceGirder(1215, 570, 4) + PlaceGirder(1288, 520, 2) + PlaceGirder(1184, 468, 4) + PlaceGirder(1344, 468, 4) + PlaceGirder(1247, 346, 4) + + PlaceGirder(667, 438, 4) + PlaceGirder(507, 438, 4) + PlaceGirder(434, 487, 2) + PlaceGirder(505, 537, 4) + PlaceGirder(665, 537, 4) + PlaceGirder(737, 487, 2) + + PlaceGirder(416, 465, 6) + PlaceGirder(1415, 378, 6) + PlaceGirder(1300, 625, 3) + PlaceGirder(1359, 566, 3) + PlaceGirder(1436, 538, 0) + PlaceGirder(1505, 468, 4) + + ------ AMMO CRATE LIST ------ + tempG = SpawnAmmoCrate(1242, 315, amBaseballBat) + tempG = SpawnAmmoCrate(1309, 315, amAirAttack) + tempG = SpawnAmmoCrate(144, 895, amAirAttack) + tempG = SpawnAmmoCrate(664, 699, amIceGun) + tempG = SpawnAmmoCrate(1572, 444, amFirePunch) + tempG = SpawnAmmoCrate(1574, 382, amDynamite) + + ------ UTIL CRATE LIST ------ + tempG = SpawnUtilityCrate(654, 513, amParachute) + tempG = SpawnUtilityCrate(1569, 413, amParachute) + + -- HOG AMMO + AddAmmo(hhs[1],amParachute,1) + AddAmmo(hhs[1],amHammer,1) + AddAmmo(hhs[2],amWhip,1) + + for i = 3, 10 do + AddAmmo(hhs[i], amDEagle, 100) + AddAmmo(hhs[i], amShotgun, 100) + AddAmmo(hhs[i], amGrenade, 100) + AddAmmo(hhs[i], amBazooka, 100) + AddAmmo(hhs[i], amDrill, 100) + end + +end + +function onNewTurn() + SetWind(100) +end + +function onAmmoStoreInit() + + SetAmmo(amBaseballBat, 0, 0, 0, 1) + SetAmmo(amAirAttack, 0, 0, 0, 1) + SetAmmo(amFirePunch, 0, 0, 0, 1) + SetAmmo(amDynamite, 0, 0, 0, 1) + SetAmmo(amHammer, 0, 0, 0, 1) + SetAmmo(amIceGun, 0, 0, 0, 1) + + SetAmmo(amParachute, 0, 0, 0, 1) + + SetAmmo(amSwitch, 9, 0, 0, 0) + SetAmmo(amSkip, 9, 0, 0, 0) + +end + +------------------------------ +-- I'm in whitesppaaaaaaaaaacceeeee :D +------------------------------ diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Missions/Training/User_Mission_-_RCPlane_Challenge.lua --- a/share/hedgewars/Data/Missions/Training/User_Mission_-_RCPlane_Challenge.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Missions/Training/User_Mission_-_RCPlane_Challenge.lua Tue Nov 10 20:43:13 2015 +0100 @@ -3,7 +3,16 @@ local player = nil local RCGear = nil local planesUsed = 0 +local planeTimer = 0 +local planeUhOh = false local cratesLeft = 0 +local crateStreak = 0 +local longestCrateStreak = 0 +local commentTimer = 0 +local missiles = 0 +local totalMissiles = 0 +local missileScanTimer = 0 +local nextComment = sndNone function onGameInit() @@ -29,6 +38,8 @@ function onGameStart() + SendHealthStatsOff() + ShowMission ( loc("RC PLANE TRAINING"), loc("a Hedgewars challenge"), @@ -283,6 +294,30 @@ --end +function onGameTick20() + if RCGear ~= nil then + if(GetTimer(RCGear) < 3000 and planeUhOh == false) then + PlaySound(sndUhOh, player) + planeUhOh = true + end + planeTimer = planeTimer + 20 + end + if commentTimer > 0 then + commentTimer = commentTimer - 20 + elseif(nextComment ~= sndNone) then + PlaySound(nextComment, player) + nextComment = sndNone + end + if missileScanTimer > 0 then + missileScanTimer = missileScanTimer - 20 + else + if crateStreak == 0 and missiles == 3 then + PlaySound(sndMissed, player) + missiles = 4 + end + end +end + function onNewTurn() TurnTimeLeft = -1 end @@ -292,12 +327,17 @@ if GetGearType(gear) == gtRCPlane then RCGear = gear planesUsed = planesUsed + 1 + planeTimer = 0 + missiles = 0 end if GetGearType(gear) == gtCase then cratesLeft = cratesLeft + 1 end + if GetGearType(gear) == gtAirBomb then + totalMissiles = totalMissiles + 1 + end end function onGearDelete(gear) @@ -305,38 +345,146 @@ if GetGearType(gear) == gtRCPlane then RCGear = nil - AddCaption(loc("Planes Used:") .. " " .. planesUsed) + planeUhOh = false + missiles = 0 + AddCaption(string.format(loc("Planes used: %d"), planesUsed)) + + if(planeTimer < 2000 and crateStreak == 0) then + nextComment = sndStupid + commentTimer = math.min(2000-planeTimer, 800) + elseif(planeTimer < 5000 and crateStreak == 0) then + PlaySound(sndOops, player) + elseif(planesUsed == 72) then + PlaySound(sndStupid, player) + elseif(planesUsed == 50) then + PlaySound(sndNutter, player) + elseif(planesUsed == 30) then + PlaySound(sndOops, player) + end + + crateStreak = 0 + + elseif GetGearType(gear) == gtAirBomb then + missiles = missiles + 1 + missileScanTimer = 500 elseif GetGearType(gear) == gtCase then - AddCaption(loc("Crates Left:") .. " " .. cratesLeft) cratesLeft = cratesLeft - 1 + crateStreak = crateStreak + 1 + if(crateStreak > longestCrateStreak) then + longestCrateStreak = crateStreak + end + + AddCaption(string.format(loc("Crates left: %d"), cratesLeft)) if cratesLeft == 0 then + local rank = "unknown" + local color = 0xFFFFFFFF + local sound = sndVictory + if planesUsed >= 156 then + rank = loc("Destroyer of planes") + color = 0xD06700FF + sound = sndLaugh + elseif planesUsed >= 98 then + rank = loc("Hopeless case") + color = 0xFF0000FF + elseif planesUsed >= 72 then + rank = loc("Drunk greenhorn") + color = 0xFF0040FF + elseif planesUsed >= 50 then + rank = loc("Greenhorn") -- a.k.a. "absolute beginner" + color = 0xFF0080FF + elseif planesUsed >= 39 then + rank = loc("Beginner") + color = 0xFF00BFFF + elseif planesUsed >= 30 then + rank = loc("Experienced beginner") + color = 0xFF00CCFF + elseif planesUsed >= 21 then + rank = loc("Below-average pilot") + color = 0xFF00FFFF + elseif planesUsed >= 17 then + rank = loc("Average pilot") + color = 0xBF00FFFF + elseif planesUsed >= 13 then + rank = loc("Above-average pilot") + color = 0x8000FFFF + elseif planesUsed >= 8 then + rank = loc("Professional pilot") + color = 0x4000FFFF + elseif planesUsed >= 5 then + rank = loc("Professional stunt pilot") + color = 0x0000FFFF + elseif planesUsed >= 3 then + rank = loc("Elite pilot") + color = 0x0040FFFF + elseif planesUsed == 2 then + rank = loc("Upper-class elite pilot") + color = 0x0080FFFF + elseif planesUsed == 1 then + rank = loc("Top-class elite pilot") + color = 0x00FFFFFF + sound = sndFlawless + else + rank = loc("Cheater") + color = 0xFF0000FF + sound = sndCoward + end + AddCaption(string.format(loc("Rank: %s"), rank), color, capgrpMessage2) + SendStat(siCustomAchievement, string.format(loc("Your rank: %s"), rank)) if planesUsed == 1 then - AddCaption(loc("Achievement Unlocked") .. ": " .. loc("Prestigious Pilot"),0xffba00ff,capgrpMessage2) + AddCaption(loc("Flawless victory!")) + SendStat(siGameResult, loc("You have perfectly beaten the challenge!")) + SendStat(siCustomAchievement, loc("You have used only 1 RC plane. Outstanding!")) + else + AddCaption(loc("Victory!")) + SendStat(siGameResult, loc("You have finished the challenge!")) + SendStat(siCustomAchievement, string.format(loc("You have used %d RC planes."), planesUsed)) + end + + if(totalMissiles > 1) then + SendStat(siCustomAchievement, string.format(loc("You have dropped %d missiles."), totalMissiles)) + end + + if(longestCrateStreak > 5) then + if(planesUsed == 1) then + SendStat(siCustomAchievement, string.format(loc("In your best (and only) flight you took out %d crates with one RC plane!"), longestCrateStreak)) + else + SendStat(siCustomAchievement, string.format(loc("In your best flight you took out %d crates with one RC plane."), longestCrateStreak)) + end + end + + if(planesUsed == 2) then + SendStat(siCustomAchievement, loc("This was an awesome performance! But this challenge can be finished with even just one RC plane. Can you figure out how?")) + end + if(planesUsed == 1) then + SendStat(siCustomAchievement, loc("Congratulations! You have truly mastered this challenge! Don't forget to save the demo.")) + SendStat(siCustomAchievement, string.format(loc("You have gained an achievement: %s"), loc("Prestigious Pilot"))) end ShowMission ( loc("CHALLENGE COMPLETE"), loc("Congratulations!"), - loc("Planes Used") .. ": " .. planesUsed .. "|" .. + string.format(loc("Planes used: %d"), planesUsed) .. "|" .. "", 0, 0 ) + SetState(player, gstWinner) + PlaySound(sound, player) - ParseCommand("teamgone Wannabe Flyboys") + DismissTeam(loc("Wannabe Flyboys")) + EndGame() end if RCGear ~= nil then SetTimer(RCGear, GetTimer(RCGear) + 10000) end - end end function onAmmoStoreInit() SetAmmo(amRCPlane, 9, 0, 0, 0) -end +end \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Missions/Training/User_Mission_-_Rope_Knock_Challenge.lua --- a/share/hedgewars/Data/Missions/Training/User_Mission_-_Rope_Knock_Challenge.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Missions/Training/User_Mission_-_Rope_Knock_Challenge.lua Tue Nov 10 20:43:13 2015 +0100 @@ -57,9 +57,9 @@ } function GenericEnd() - ParseCommand("teamgone " .. loc("Wannabe Shoppsta")) - ParseCommand("teamgone " .. loc("Unsuspecting Louts")) - ParseCommand("teamgone " .. loc("Unlucky Sods")) + DismissTeam(loc("Wannabe Shoppsta")) + DismissTeam(loc("Unsuspecting Louts")) + DismissTeam(loc("Unlucky Sods")) end function GameOverMan() diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Missions/Training/User_Mission_-_That_Sinking_Feeling.lua --- a/share/hedgewars/Data/Missions/Training/User_Mission_-_That_Sinking_Feeling.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Missions/Training/User_Mission_-_That_Sinking_Feeling.lua Tue Nov 10 20:43:13 2015 +0100 @@ -20,14 +20,15 @@ genCounter = 0 FollowGear(CurrentHedgehog) AddCaption(loc("Good luck out there!")) - ShowMission(loc("That Sinking Feeling"), loc("User Challenge"), loc("Save as many hapless hogs as possible!"), 4, 0) + ShowMission(loc("That Sinking Feeling"), loc("Challenge"), loc("Save as many hapless hogs as possible!"), 4, 0) + SetInputMask(0xFFFFFFFF) end end function onGameInit() Seed = 0 - GameFlags = gfInfAttack + gfInvulnerable + GameFlags = gfInfAttack + gfInvulnerable + gfOneClanMode TurnTime = 90000 CaseFreq = 0 MinesNum = 0 @@ -38,10 +39,7 @@ Theme = "City" SuddenDeathTurns = 1 - AddTeam(loc("Nameless Heroes"), 14483456, "Simple", "Island", "Default") - player = AddHog(loc("The Nameless One"), 0, 1, "NoHat") - - AddTeam(loc("Hapless Hogs"), 1175851, "Simple", "Island", "Default") + AddTeam(loc("Hapless Hogs"), 14483456, "Simple", "Island", "Default") hh[0] = AddHog(loc("Sinky"), 1, 100, "fr_lemon") hh[1] = AddHog(loc("Drowner"), 1, 100, "fr_orange") hh[2] = AddHog(loc("Heavy"), 1, 100, "dish_Teapot") @@ -51,6 +49,9 @@ hh[6] = AddHog(loc("Sponge"), 1, 100, "sf_chunli") hh[7] = AddHog(loc("Deadweight"), 1, 100, "dish_Teacup") + AddTeam(loc("Nameless Heroes"), 14483456, "Simple", "Island", "Default", "cm_crossedswords") + player = AddHog(loc("The Nameless One"), 0, 1, "NoHat") + SetGearPosition(player, 3992, 733) SetGearPosition(hh[0], 938, 1369) SetGearPosition(hh[1], 1301, 1439) @@ -61,12 +62,15 @@ SetGearPosition(hh[6], 2191, 810) SetGearPosition(hh[7], 3799, 945) + -- Disable all input except [Precise] for the intro + SetInputMask(gmPrecise) end function onGameStart() + SendHealthStatsOff() - ShowMission(loc("That Sinking Feeling"), loc("User Challenge"), loc("Save as many hapless hogs as possible!"), 4, 1) + ShowMission(loc("That Sinking Feeling"), loc("Challenge"), loc("Save as many hapless hogs as possible!"), 4, 1) HogTurnLeft(hh[0], false) HogTurnLeft(hh[1], true) @@ -193,6 +197,7 @@ introStage = 110 FollowGear(CurrentHedgehog) ShowMission(loc("That Sinking Feeling"), loc("User Challenge"), loc("Save as many hapless hogs as possible!"), 4, 0) + SetInputMask(0xFFFFFFFF) end end @@ -211,24 +216,33 @@ if (waterPix >= 1615) and (GameOver == false) then GameOver = true - SetHealth(player, 0) - TurnTimeLeft = 1 - ShowMission(loc("That Sinking Feeling"), loc("MISSION SUCCESS"), loc("You saved") .. " " .. hhCount .. " " .. loc("Hapless Hogs") .."!", 0, 0) + AddCaption(loc("The flood has stopped! Challenge over.")) + SendStat(siGameResult, loc("Challenge completed!")) + SendStat(siPlayerKills, tostring(hhCount), loc("Nameless Heroes")) + SendStat(siPointType, loc("rescues")) - if hhCount == 8 then - AddCaption(loc("Achievement Unlocked") .. ": " .. loc("Lively Lifeguard"),0xffba00ff,capgrpMessage2) + -- Do not count drowning hedgehogs + local hhLeft = hhCount + for i=1,#hh do + local isDrowning = band(GetState(hh[i]),gstDrowning) ~= 0 + if isDrowning then + hhLeft = hhLeft - 1 + end end + SendStat(siCustomAchievement, string.format(loc("You saved %d of 8 Hapless Hogs."), hhLeft)) + + if hhLeft == 8 then + AddCaption(loc("Achievement obtained: Lively Lifeguard"),0xffba00ff,capgrpMessage2) + SendStat(siCustomAchievement, loc("You have obtained an achievement: Lively Lifeguard")) + end + EndGame() + end end end - - if TurnTimeLeft == 1 then - SetHealth(player, 0) - end - end @@ -253,17 +267,27 @@ function onGearDelete(gear) if GetGearType(gear) == gtHedgehog then - if GetHogTeamName(gear) == "Hapless Hogs" then + if GetHogTeamName(gear) == loc("Hapless Hogs") then hhCount = hhCount - 1 - AddCaption(hhCount .. loc(" Hapless Hogs left!")) + AddCaption(string.format(loc("%d Hapless Hogs left"), hhCount)) end end if ((gear == player) or (hhCount == 0)) and (GameOver == false) then SetHealth(player, 0) - TurnTimeLeft = 1 - ShowMission(loc("That Sinking Feeling"), loc("MISSION FAILED"), loc("Oh no! Just try again!"), -amSkip, 0) + AddCaption(loc("Disqualified!")) + if gear == player then + SendStat(siCustomAchievement, loc("Your hedgehog died!")) + SendStat(siCustomAchievement, loc("You must survive the flood in order to score.")) + else + SendStat(siCustomAchievement, loc("You haven't rescued anyone.")) + end + SendStat(siPlayerKills, "0", loc("Nameless Heroes")) + SendStat(siPointType, loc("points")) + + SendStat(siGameResult, loc("Disqualified!")) GameOver = true + EndGame() end end diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Missions/Training/User_Mission_-_The_Great_Escape.lua --- a/share/hedgewars/Data/Missions/Training/User_Mission_-_The_Great_Escape.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Missions/Training/User_Mission_-_The_Great_Escape.lua Tue Nov 10 20:43:13 2015 +0100 @@ -20,7 +20,7 @@ player = AddHog(loc("Good Dude"), 0, 80, "NoHat") --NoHat AddTeam(loc("Bad Team"), 1175851, "Simple", "Island", "Default", "Hedgewars") - enemy = AddHog("Bad Guy", 1, 40, "NoHat") + enemy = AddHog(loc("Bad Guy"), 1, 40, "NoHat") end diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Missions/Training/portal.lua --- a/share/hedgewars/Data/Missions/Training/portal.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Missions/Training/portal.lua Tue Nov 10 20:43:13 2015 +0100 @@ -16,29 +16,29 @@ Delay = 10 -- The delay between each round Map = "portal" -- The map to be played Theme = "Hell" -- The theme to be used - Goals = "use the portal to move fast and far, use it to kill, use it with caution !" --the goal ... + Goals = loc("Use the portal to move fast and far, use it to kill, use it with caution!") --the goal ... ----AddTeam(teamname, color, grave, fort, voicepack, flag)-- - AddTeam("Subject", 14483406, "Simple", "Island", "Default", "cm_star") - player = AddHog("player", 0, 10, "Terminator_Glasses") + AddTeam(loc("Subject"), 14483406, "Simple", "Island", "Default", "cm_star") + player = AddHog(loc("player"), 0, 10, "Terminator_Glasses") - AddTeam("Hell Army", 1170801, "Simple", "Island", "Default", "cm_galaxy") - enemy1 = AddHog("Lucifer", 1, 200, "thinkingcap") - enemy2 = AddHog("voldemort", 1, 150, "WizardHat") - enemy3 = AddHog("zombi", 1, 100, "zombi") - enemy4 = AddHog("Predator", 1, 14, "predator") - enemy5 = AddHog("oneye", 1, 50, "cyclops") - enemy6 = AddHog("razac", 1, 50, "plaguemask") - enemy7 = AddHog("C-2", 1, 50, "cyborg1") - enemy8 = AddHog("Rider", 1, 50, "scif_SparkssHelmet") + AddTeam(loc("Hell Army"), 1170801, "Simple", "Island", "Default", "cm_galaxy") + enemy1 = AddHog(loc("Lucifer"), 1, 200, "thinkingcap") + enemy2 = AddHog(loc("voldemort"), 1, 150, "WizardHat") + enemy3 = AddHog(loc("zombi"), 1, 100, "zombi") + enemy4 = AddHog(loc("Predator"), 1, 14, "predator") + enemy5 = AddHog(loc("oneye"), 1, 50, "cyclops") + enemy6 = AddHog(loc("razac"), 1, 50, "plaguemask") + enemy7 = AddHog(loc("C-2"), 1, 50, "cyborg1") + enemy8 = AddHog(loc("Rider"), 1, 50, "scif_SparkssHelmet") - AddTeam("badmad", 1170801, "Simple", "Island", "Default", "cm_jupiter") - enemy9 = AddHog("C-1", 1, 50, "cyborg2") - enemy10 = AddHog("hiden", 1, 40, "daftpunkguymanuel") - enemy11 = AddHog("ronald", 1, 70, "clown") - enemy12 = AddHog("phosphatoglucidique", 1, 50, "chef") - enemy13 = AddHog("Lestat", 1, 30, "draculakz") + AddTeam(loc("badmad"), 1170801, "Simple", "Island", "Default", "cm_jupiter") + enemy9 = AddHog(loc("C-1"), 1, 50, "cyborg2") + enemy10 = AddHog(loc("hiden"), 1, 40, "daftpunkguymanuel") + enemy11 = AddHog(loc("ronald"), 1, 70, "clown") + enemy12 = AddHog(loc("phosphatoglucidique"), 1, 50, "chef") + enemy13 = AddHog(loc("Lestat"), 1, 30, "draculakz") SetGearPosition(player, 350, 1820) SetGearPosition(enemy1, 2037, 1313) @@ -168,7 +168,7 @@ ShowMission (loc("Portal mission"), loc("training"), "", -amPortalGun, 5000) - HogSay(player, "I should get myself a portal gun, maybe this crate has one", SAY_THINK) + HogSay(player, loc("I should get myself a portal gun, maybe this crate has one"), SAY_THINK) @@ -204,11 +204,11 @@ if gear == portalgun then --AddAmmo(player, amPortalGun, 10000) - HogSay(player, "GREAT ! Let's kill all this enemies, using portals", SAY_THINK) + HogSay(player, loc("GREAT ! Let's kill all this enemies, using portals"), SAY_THINK) end if gear == girder then - HogSay(player, "Will be useful if I need a new plateform or if I want to rise....", SAY_THINK) + HogSay(player, loc("Will be useful if I need a new plateform or if I want to rise...."), SAY_THINK) end if gear == parachute then diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Music/olympics_sd.ogg Binary file share/hedgewars/Data/Music/olympics_sd.ogg has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Music/sdmusic.ogg Binary file share/hedgewars/Data/Music/sdmusic.ogg has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Scripts/Multiplayer/Balanced_Random_Weapon.cfg --- a/share/hedgewars/Data/Scripts/Multiplayer/Balanced_Random_Weapon.cfg Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Scripts/Multiplayer/Balanced_Random_Weapon.cfg Tue Nov 10 20:43:13 2015 +0100 @@ -1,2 +1,2 @@ -Default +* locked diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Scripts/Multiplayer/Balanced_Random_Weapon.lua --- a/share/hedgewars/Data/Scripts/Multiplayer/Balanced_Random_Weapon.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Scripts/Multiplayer/Balanced_Random_Weapon.lua Tue Nov 10 20:43:13 2015 +0100 @@ -93,7 +93,8 @@ end function onGameInit() - GameFlags = band(bor(GameFlags, gfResetWeps), bnot(gfPerHogAmmo)) + DisableGameFlags(gfPerHogAmmo) + EnableGameFlags(gfResetWeps) Goals = loc("Each turn you get 1-3 random weapons") end diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Scripts/Multiplayer/CMakeLists.txt --- a/share/hedgewars/Data/Scripts/Multiplayer/CMakeLists.txt Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Scripts/Multiplayer/CMakeLists.txt Tue Nov 10 20:43:13 2015 +0100 @@ -1,7 +1,9 @@ file(GLOB luafiles *.lua) file(GLOB cfgfiles *.cfg) +file(GLOB hwpfiles *.hwp) install(FILES ${luafiles} ${cfgfiles} + ${hwpfiles} DESTINATION ${SHAREPATH}Data/Scripts/Multiplayer) diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Scripts/Multiplayer/Capture_the_Flag.cfg --- a/share/hedgewars/Data/Scripts/Multiplayer/Capture_the_Flag.cfg Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Scripts/Multiplayer/Capture_the_Flag.cfg Tue Nov 10 20:43:13 2015 +0100 @@ -1,2 +1,2 @@ -Default -Default +* +* diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Scripts/Multiplayer/Capture_the_Flag.lua --- a/share/hedgewars/Data/Scripts/Multiplayer/Capture_the_Flag.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Scripts/Multiplayer/Capture_the_Flag.lua Tue Nov 10 20:43:13 2015 +0100 @@ -444,7 +444,9 @@ function onGameInit() - GameFlags = band(bor(GameFlags, gfDivideTeams), bnot(gfKing + gfForts)) + DisableGameFlags(gfKing, gfForts) + EnableGameFlags(gfDivideTeams) + --SuddenDeathTurns = 999 -- suddendeath is off, effectively WaterRise = 0 Delay = 10 diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Scripts/Multiplayer/Construction_Mode.cfg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Scripts/Multiplayer/Construction_Mode.cfg Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,2 @@ +Construction_Mode +Construction_Mode diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Scripts/Multiplayer/Construction_Mode.hwp Binary file share/hedgewars/Data/Scripts/Multiplayer/Construction_Mode.hwp has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Scripts/Multiplayer/Construction_Mode.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Scripts/Multiplayer/Construction_Mode.lua Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,1909 @@ +--------------------------------------------------------- +--- LE CONSTRUCTION MODE 0.7 (badly adapted from Hedge Editor 0.5) +--------------------------------------------------------- +-- a hedgewars gameplay mode by mikade +-- special thanks to all who helped test and offered suggestions +-- additional thanks to sheepluva/nemo for adding some extra hooks + +-- (to do) +-- investigate loc not working on addcaptions +-- check for parsecommands before porting to dev +-- test onUpDown more extensively as it may need revision (check for amRubber etc) +-- test localization of weapons and utils and stuff + +-- try posistion grenades in Harmer so it blows hogs away from the struc +-- and don't explode too close to the struc + +-- additional/previous balance ideas +-- based on your money? +-- based on the number of strucs/gens you own? +-- based on your existing arsenal? +-- limit number of crates spawned per round perhaps (done) +-- limit number of generators? + +------------------------------------------------------------------------------ +--version history +------------------------------------------------------------------------------ +--v0.1 +-- concept test + +--v0.2 +-- improved documentation (in script and in game) +-- improved localisation (or is it? at any rate, crate placement should now say e.g. Bazooka and not amBazooka) +-- added variable weapon costs (based on the values from Vatten's Consumerism script) + +-- added reflector shield (still needs work and balancing) +-- added weapon-filter (probably ok) + +-- enabled super weapons like ballgun, rcplane, watermelon, hellish to test balance +-- reduce max money to 1000 + +--v0.3 +-- some /s removed + +--v0.4 +-- added support for per hog ammo (hopefully) + +--v0.5 (dev) +-- added somewhat horribly implemented support for different structure sprites +-- added override pictures for ammo menu +-- added override message on wep select to aid understanding +-- split menu into/between weps/parts: struc, crates, gears +-- add a limit on crates per turn +-- add a limit on extra time per turn +-- add a test level +-- restored rubber placement +-- cleaned up some of the code a bit and removed about 280 lines of code I didn't need, lol + +--v0.6 (dev) +-- added magic dance + +--v.07 (pushed to repo) +-- added a cfg file +-- removed another 903 lines of code we weren't using (lol) + +-------------------------------- +-- STRUCTURES LIST / IDEAS +-------------------------------- + +--Healing Station: heals hogs to 150 life +--Teleportation Node: allows teleporting to any other teleporter nodes +--Bio-filter: explodes enemy hogs +--Respawner: if you have one of these, any slain hogs are resurrected here :D +--Generator: generates energy (used to buy stuff, and possibly later other strucs might have upkeep costs) +--Support Station: allows purchasing of weapons, utilities, and med-crates +--Construction Station: allows purchasing of girders, rubber, mines, sticky mines, barrels +--Reflector Shield: reflect projectiles +--Weapon Filter: kill all equipement of enemy hogs passing through this area. + + +--to make the grill more attractive make it vaporize flying saucers +--and also rope, and maybe incoming gears + +-- make healing thing also cure poison +-- maybe make poison more virulent and dangerous + +--(not implemented / abandoned ideas) +-- Core: allows construction of other structures. +-- Automated Turret (think red drones from space invasion) +-- Canon (gives access to 3 fireballs per turn while near) +-- something that allows control of wind/water +-- Gravity Field generator : triggers world gravity change + +-- structures consume power over time and +-- maybe you can turn structures OFF/ON, manually to save power. + +-- hacking +-- allow hacking of structures, either being able to use enemy structures, +-- or turning a team's structures against them. + +-- pylons +-- allow hogs to put down a pylon-like gear which then allows the core +-- to place other structures/objects within the pylon's sphere of influence +-- this would allow aggressive structure advancement + +-- resouce mining? +-- you could designate something like mines, that you could get close to, +-- "pick up", and then "drop" back at a central location to simulate +-- resource mining. bit complicated/meh, normal power generators probably easier + +-- it would be cool to have a red mask we could apply over girders +-- that would indicate they were Indestructible + +HedgewarsScriptLoad("/Scripts/Locale.lua") +HedgewarsScriptLoad("/Scripts/Tracker.lua") + +---------------------------------------------- +-- STRUC CRAP +---------------------------------------------- + +strucID = {} +strucGear = {} +strucClan = {} +strucType = {} +strucCost = {} +strucHealth = {} + +strucCirc = {} +strucCircCol = {} +strucCircRadius = {} +strucCircType = {} +strucAltDisplay = {} + +placedExpense = 0 + +tempID = nil + +sUID = 0 + +colorRed = 0xff0000ff +colorGreen = 0x00ff00ff + +clanBoundsSX = {} +clanBoundsSY = {} +clanBoundsEX = {} +clanBoundsEY = {} + +clanPower = {} +clanBoon = {} +clanID = {} +clanLStrucIndex = {} + +clanLWepIndex = {} -- for ease of use let's track this stuff +clanLUtilIndex = {} +clanLGearIndex = {} +clanUsedExtraTime = {} +clanCratesSpawned = {} + +effectTimer = 0 + +wallsVisible = false +wX = {} +wY = {} +wWidth = {} +wHeight = {} +wCol = {} +margin = 20 + +tauntString = "" + +vTag = {} +lastWep = nil + +function HideTags() + + for i = 0, 2 do + SetVisualGearValues(vTag[i],0,0,0,0,0,1,0, 0, 240000, 0xffffff00) + end + +end + +function DrawTag(i) + + zoomL = 1.3 + + xOffset = 40 + + if i == 0 then + yOffset = 40 + tCol = 0xffba00ff + tValue = 30--TimeLeft + elseif i == 1 then + zoomL = 1.1 + xOffset = 45 + yOffset = 70 + tCol = 0x00ff00ff + tValue = clanPower[GetHogClan(CurrentHedgehog)] + elseif i == 2 then + zoomL = 1.1 + xOffset = 60 + 35 + yOffset = 70 + tCol = 0xa800ffff + tValue = 10--shieldHealth - 80 + end + + DeleteVisualGear(vTag[i]) + vTag[i] = AddVisualGear(0, 0, vgtHealthTag, 0, false) + g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(vTag[i]) + SetVisualGearValues ( + vTag[i], --id + -div(ScreenWidth,2) + xOffset, --xoffset + ScreenHeight - yOffset, --yoffset + 0, --dx + 0, --dy + zoomL, --zoom + 1, --~= 0 means align to screen + g7, --frameticks + tValue, --value + 240000, --timer + tCol --GetClanColor( GetHogClan(CurrentHedgehog) ) + ) + +end + +function onScreenResize() + + -- redraw Tags so that their screen locations are updated + if (CurrentHedgehog ~= nil) then + DrawTag(0) + DrawTag(1) + DrawTag(2) + end + +end + +function XYisInRect(px, py, psx, psy, pex, pey) + + if (px > psx) and (px < pex) and (py > psy) and (py < pey) then + return(true) + else + return(false) + end + +end + +function AddWall(zXMin,zYMin, zWidth, zHeight, zCol) + + table.insert(wX, zXMin) + table.insert(wY, zYMin) + table.insert(wWidth, zWidth) + table.insert(wHeight, zHeight) + table.insert(wCol, zCol) + +end + +function BorderSpark(zXMin,zYMin, zWidth, zHeight, bCol) + + eX = zXMin + GetRandom(zWidth+10) + eY = zYMin + GetRandom(zHeight+10) + tempE = AddVisualGear(eX, eY, vgtDust, 0, false) + if tempE ~= 0 then + g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(tempE) + SetVisualGearValues(tempE, eX, eY, g3, g4, g5, g6, g7, 1, g9, bCol ) + end + +end + +function HandleBorderEffects() + + effectTimer = effectTimer + 1 + if effectTimer > 15 then --25 + effectTimer = 1 + for i = 1, #wX do + BorderSpark(wX[i],wY[i],wWidth[i],wHeight[i], wCol[i]) + end + end + +end + +---- +-- old reflecting stuff from like 3 years ago lol +--- + +function gearCanBeDeflected(gear) + + if (GetGearType(gear) == gtShell) or + --(GetGearType(gear) == gtBee) or + (GetGearType(gear) == gtGrenade) or + (GetGearType(gear) == gtAirBomb) or + --(GetGearType(gear) == gtRCPlane) or + --(GetGearType(gear) == gtRope) or + (GetGearType(gear) == gtClusterBomb) or + (GetGearType(gear) == gtCluster) or + (GetGearType(gear) == gtGasBomb) or + --(GetGearType(gear) == gtSeduction) or + (GetGearType(gear) == gtMine) or ------- + (GetGearType(gear) == gtMortar) or + (GetGearType(gear) == gtHellishBomb) or + (GetGearType(gear) == gtWatermelon) or + (GetGearType(gear) == gtMelonPiece) or + (GetGearType(gear) == gtEgg) or + (GetGearType(gear) == gtDrill) or + (GetGearType(gear) == gtBall) or + (GetGearType(gear) == gtExplosives) or ------ + (GetGearType(gear) == gtFlame) or + (GetGearType(gear) == gtPortal) or + (GetGearType(gear) == gtDynamite) or + (GetGearType(gear) == gtSMine) or + --(GetGearType(gear) == gtKamikaze) or + --(GetGearType(gear) == gtRCPlane) or + --(GetGearType(gear) == gtCake) or + --(GetGearType(gear) == gtHedgehog) or ------ + (GetGearType(gear) == gtKnife) or + (GetGearType(gear) == gtJetpack) or -- test this and birdy plz + (GetGearType(gear) == gtBirdy) or -- test this and birdy plz + (GetGearType(gear) == gtSnowball) or + (GetGearType(gear) == gtMolotov) + then + return(true) + else + return(false) + end + +end + +function getThreatDamage(gear) + + --- damage amounts for weapons + if (GetGearType(gear) == gtGrenade) or + (GetGearType(gear) == gtClusterBomb) or + (GetGearType(gear) == gtGasBomb) or + (GetGearType(gear) == gtKnife) or + (GetGearType(gear) == gtEgg) or + (GetGearType(gear) == gtMolotov) or + (GetGearType(gear) == gtHellishBomb) or + (GetGearType(gear) == gtWatermelon) or + (GetGearType(gear) == gtSMine) + then + dmg = 30 + + elseif (GetGearType(gear) == gtMelonPiece) then + dmg = 40 + + elseif (GetGearType(gear) == gtAirBomb) or + (GetGearType(gear) == gtDrill) or + (GetGearType(gear) == gtMine) or + (GetGearType(gear) == gtCluster) then + dmg = 20 + + elseif (GetGearType(gear) == gtFlame) or + (GetGearType(gear) == gtPortal) or + (GetGearType(gear) == gtDynamite) + --(GetGearType(gear) == gtKamikaze) or + --(GetGearType(gear) == gtRCPlane) or + + --(GetGearType(gear) == gtCake) + then + dmg = 0 + + elseif (GetGearType(gear) == gtBall) then + dmg = 1 + + else --normal shell, snowball etc + dmg = 65 + end + + return(dmg) + +end + +function setGearReflectionValues(gear) + + dmg = getThreatDamage(gear) + setGearValue(gear,"damage",dmg) + setGearValue(gear,"deflects",0) + + if (CurrentHedgehog ~= nil) then --and (gameStarted == true) then + setGearValue(gear,"owner",GetHogClan(CurrentHedgehog)) -- NEW NEEDS CHANGE? + else + setGearValue(gear,"owner",10) -- nil + end + +end + +function AddStruc(pX,pY, pType, pClan) + + sUID = sUID + 1 + + tempG = AddGear(0, 0, gtTarget, 0, 0, 0, 0) + SetGearPosition(tempG, pX, pY) + setGearValue(tempG, "sUID", sUID) + + tempCirc = AddVisualGear(0,0,vgtCircle,0,true) + + SetVisualGearValues(tempCirc, 0, 0, 100, 255, 1, 100, 0, 500, 1, 0xFFFFFF00) + + table.insert(strucID, sUID) + table.insert(strucType, pType) + table.insert(strucGear,tempG) + table.insert(strucClan,pClan) + table.insert(strucCost,2) + + frameID = 0 + visualSprite = sprTarget + madness = AddVisualGear(GetX(tempG), GetY(tempG), vgtStraightShot, 1, true,1) + g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(madness) --g9 + + + if pType == loc("Reflector Shield") then + table.insert(strucHealth,255) + + --SetVisualGearValues(madness, g1, g2, 0, 0, g5, frameID, g7, visualSprite, g9, g10 ) + --SetState(tempG, bor(GetState(tempG),gstInvisible) ) + --table.insert(strucAltDisplay, madness) + + else + table.insert(strucHealth,1) + --table.insert(strucAltDisplay, 1) + end + + table.insert(strucCirc,tempCirc) + + table.insert(strucCircType, 1) + if pType == loc("Bio-Filter") then + table.insert(strucCircCol,colorRed) + table.insert(strucCircRadius,1000) + frameID = 7 + elseif pType == loc("Healing Station") then + table.insert(strucCircCol,0xFF00FF00) + --table.insert(strucCircCol,colorGreen) + table.insert(strucCircRadius,500) + frameID = 3 + elseif pType == loc("Respawner") then + table.insert(strucCircCol,0xFF00FF00) + --table.insert(strucCircCol,0xFF00FFFF) + table.insert(strucCircRadius,75) + runOnHogs(EnableHogResurrectionForThisClan) + frameID = 1 + elseif pType == loc("Teleportation Node") then + table.insert(strucCircCol,0x0000FFFF) + table.insert(strucCircRadius,350) + frameID = 6 + elseif pType == loc("Core") then + table.insert(strucCircCol,0xFFFFFFFF) + table.insert(strucCircRadius,350) + elseif pType == loc("Generator") then + table.insert(strucCircCol,0xFFFF00FF) + table.insert(strucCircRadius,75) + setGearValue(tempG, "power", 0) + frameID = 2 + elseif pType == loc("Support Station") then + table.insert(strucCircCol,0xFFFF00FF) + table.insert(strucCircRadius,500) + frameID = 4 + elseif pType == loc("Construction Station") then + table.insert(strucCircCol,0xFFFFFFFF) + table.insert(strucCircRadius,500) + frameID = 8 + elseif pType == loc("Reflector Shield") then + table.insert(strucCircCol,0xffae00ff) + table.insert(strucCircRadius,750) + frameID = 9 + elseif pType == loc("Weapon Filter") then + table.insert(strucCircCol,0xa800ffff) + table.insert(strucCircRadius,750) + frameID = 5 + end + + + SetVisualGearValues(madness, g1, g2, 0, 0, g5, frameID, g7, visualSprite, g9, g10 ) + SetState(tempG, bor(GetState(tempG),gstInvisible) ) + table.insert(strucAltDisplay, madness) + + -- may be needed for non gear-based structures + --table.insert(strucX, GetX(tempG)) + --table.insert(strucY, GetY(tempG)) + +end + +-- this is basically onStructureDelete +-- we may need to expand it for non-gear structures later +function CheckGearForStructureLink(gear) + + respawnerDestroyed = false + + for i = 1, #strucID do + if strucID[i] == getGearValue(gear,"sUID") then + + if strucType[i] == loc("Respawner") then + respawnerDestroyed = true + end + + table.remove(strucID,i) + table.remove(strucGear,i) + table.remove(strucClan,i) + table.remove(strucType,i) + table.remove(strucCost,i) + table.remove(strucHealth,i) + + DeleteVisualGear(strucCirc[i]) + table.remove(strucCirc,i) + + table.remove(strucCircCol,i) + table.remove(strucCircRadius,i) + table.remove(strucCircType,i) + + if strucAltDisplay[i] ~= 1 then + DeleteVisualGear(strucAltDisplay[i]) + end + table.remove(strucAltDisplay,i) + + end + end + + if respawnerDestroyed == true then + runOnHogs(RecalibrateRespawn) + end + +end + +-- called when we add a new respawner +function EnableHogResurrectionForThisClan(gear) + if GetHogClan(gear) == GetHogClan(CurrentHedgehog) then + SetEffect(gear, heResurrectable, 1) + end +end + +-- this is called when a respawner blows up +function RecalibrateRespawn(gear) + + respawnerList = {} + for i = 1, #strucID do + if (strucType[i] == loc("Respawner")) and (strucClan[i] == GetHogClan(gear)) then + table.insert(respawnerList, i) + end + end + + if #respawnerList >= 1 then + SetEffect(gear, heResurrectable, 1) + else + SetEffect(gear, heResurrectable, 0) + end + +end + +--resposition dead hogs at a respawner if they own one +function FindRespawner(gear) + + respawnerList = {} + for i = 1, #strucID do + if (strucType[i] == loc("Respawner")) and (strucClan[i] == GetHogClan(gear)) then + table.insert(respawnerList, i) + end + end + + if #respawnerList >= 1 then + i = GetRandom(#respawnerList)+1 + SetGearPosition(gear,GetX(strucGear[respawnerList[i]]),GetY(strucGear[respawnerList[i]])-25) + AddVisualGear(GetX(gear), GetY(gear), vgtExplosion, 0, false) + else -- (this should never happen, but just in case) + SetEffect(gear, heResurrectable, 0) + DeleteGear(gear) + end + +end + +function onGearResurrect(gear) + AddVisualGear(GetX(gear), GetY(gear), vgtExplosion, 0, false) + FindRespawner(gear) +end + + +function CheckTeleport(gear, tX, tY) + + teleportOriginSuccessful = false + teleportDestinationSuccessful = false + + for i = 1, #strucID do + + if (strucType[i] == loc("Teleportation Node")) and (strucClan[i] == GetHogClan(CurrentHedgehog)) then + + dist = GetDistFromGearToXY(CurrentHedgehog,GetX(strucGear[i]), GetY(strucGear[i])) + if strucCircType[i] == 0 then + NR = strucCircRadius[i] + else + NR = (48/100*strucCircRadius[i])/2 + --NR = div((div(48,100) * strucCircRadius[tempID]),2) + end + if dist <= NR*NR then + teleportOriginSuccessful = true + end + + dist = GetDistFromXYtoXY(tX,tY,GetX(strucGear[i]), GetY(strucGear[i])) + if strucCircType[i] == 0 then + NR = strucCircRadius[i] + else + NR = (48/100*strucCircRadius[i])/2 + --NR = div((div(48,100) * strucCircRadius[tempID]),2) + end + if dist <= NR*NR then + teleportDestinationSuccessful = true + end + + end + + + end + + if ((teleportDestinationSuccessful == false) or (teleportOriginSuccessful == false)) then + AddCaption(loc("Teleport Unsuccessful. Please teleport within a clan teleporter's sphere of influence.")) + SetGearTarget(gear, GetX(CurrentHedgehog), GetY(CurrentHedgehog)) + end + +end + +--Check for proximity of gears to structures, and make structures behave accordingly +function CheckProximity(gear) + + --if isAStructureEffectingGear(gear) then + + dist = GetDistFromGearToXY(gear, GetX(strucGear[tempID]), GetY(strucGear[tempID])) + + -- calculate my real radius if I am an aura + if strucCircType[tempID] == 0 then + NR = strucCircRadius[tempID] + else + NR = (48/100*strucCircRadius[tempID])/2 + --NR = div((div(48,100) * strucCircRadius[tempID]),2) -- doesn't work ffff + --NR = div((48/100*strucCircRadius[tempID]),2) -- still works + + end + + -- we're in business + if dist <= NR*NR then + + + -- heal clan hogs + if strucType[tempID] == loc("Healing Station") then + + if GetGearType(gear) == gtHedgehog then + if GetHogClan(gear) == strucClan[tempID] then + + hogLife = GetHealth(gear) + 1 + if hogLife > 150 then + hogLife = 150 + end + SetHealth(gear, hogLife) + + -- change this to the med kit sprite health ++++s later + tempE = AddVisualGear(GetX(strucGear[tempID]), GetY(strucGear[tempID]), vgtSmoke, 0, true) + g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(tempE) + SetVisualGearValues(tempE, g1, g2, g3, g4, g5, g6, g7, g8, g9, colorGreen ) + + + end + end + + -- explode enemy clan hogs + elseif strucType[tempID] == loc("Bio-Filter") then + + --tempE = AddVisualGear(GetX(strucGear[tempID]), GetY(strucGear[tempID]), vgtSmoke, 0, true) + --g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(tempE) + --SetVisualGearValues(tempE, g1, g2, g3, g4, g5, g6, g7, g8, g9, colorRed ) + + if GetGearType(gear) == gtHedgehog then + if (GetHogClan(gear) ~= strucClan[tempID]) and (GetHealth(gear) > 0) then + AddGear(GetX(gear), GetY(gear), gtGrenade, 0, 0, 0, 1) + end + end + + -- were those weapons in your pocket, or were you just happy to see me? + elseif strucType[tempID] == loc("Weapon Filter") then + + if GetGearType(gear) == gtHedgehog then + if (GetHogClan(gear) ~= strucClan[tempID]) then + + for wpnIndex = 1, #atkArray do + AddAmmo(gear, atkArray[wpnIndex][1], 0) + end + + for wpnIndex = 1, #utilArray do + AddAmmo(gear, utilArray[wpnIndex][1], 0) + end + + AddAmmo(gear, amAirAttack, 100) + AddAmmo(gear, amSwitch, 100) + AddAmmo(gear, amSkip, 100) + + end + end + + -- BOUNCE! POGO! POGO! POGO! POGO! + elseif strucType[tempID] == loc("Reflector Shield") then + + -- add check for whose projectile it is + if gearCanBeDeflected(gear) == true then + + gOwner = getGearValue(gear,"owner") + gDeflects = getGearValue(gear,"deflects") + gDmg = getGearValue(gear,"damage") + + if gDeflects >= 3 then + DeleteGear(gear) + AddVisualGear(GetX(gear), GetY(gear), vgtSmoke, 0, false) + PlaySound(sndVaporize) + elseif gOwner ~= strucClan[tempID] then + --whether to vaporize gears or bounce them + if gDmg ~= 0 then + dx, dy = GetGearVelocity(gear) + + if (dx == 0) and (dy == 0) then + -- static mine, explosive, etc encountered + -- do nothing + else + + --let's bounce something! + + --if dx == 0 then + -- bounce away eggs + -- dx = 0.5 + --end + + dx = dx*(-1) + dy = dy*(-1) + SetGearVelocity(gear,dx,dy) + setGearValue(gear,"deflects",(gDeflects+1)) + + AddVisualGear(GetX(gear), GetY(gear), vgtExplosion, 0, false) + PlaySound(sndExplosion) + + strucHealth[tempID] = strucHealth[tempID] - gDmg + strucCircCol[tempID] = strucCircCol[tempID] - gDmg + + if strucHealth[tempID] <= 0 then + AddVisualGear(GetX(strucGear[tempID]), GetY(strucGear[tempID]), vgtExplosion, 0, false) + DeleteGear(strucGear[tempID]) + PlaySound(sndExplosion) + end + + end + + else + DeleteGear(gear) + AddVisualGear(GetX(gear), GetY(gear), vgtSmoke, 0, false) + PlaySound(sndVaporize) + end + end + end + + --mark as within range of a teleporter node + elseif strucType[tempID] == loc("Teleportation Node") then + + if GetGearType(gear) == gtHedgehog then + if GetHogClan(gear) == strucClan[tempID] then + --tempE = AddVisualGear(GetX(strucGear[tempID]), GetY(strucGear[tempID]), vgtSmoke, 0, true) + + for i = 1, #sProx do + if sProx[i][1] == loc("Teleportation Mode") then + sProx[i][2] = true + end + end + + end + end + + -- mark as within range of construction station + -- and thus allow menu access to placement modes + -- for girders, mines, sticky mines and barrels + elseif strucType[tempID] == loc("Construction Station") then + + if GetGearType(gear) == gtHedgehog then + if GetHogClan(gear) == strucClan[tempID] then + tempE = AddVisualGear(GetX(strucGear[tempID]), GetY(strucGear[tempID]), vgtSmoke, 0, true) + + for i = 1, #sProx do + if ((sProx[i][1] == loc("Girder Placement Mode")) + or (sProx[i][1] == loc("Rubber Placement Mode")) + or (sProx[i][1] == loc("Mine Placement Mode")) + or (sProx[i][1] == loc("Sticky Mine Placement Mode")) + or (sProx[i][1] == loc("Barrel Placement Mode"))) + then + sProx[i][2] = true + end + end + + + end + end + + -- mark as within stupport station range + -- and thus allow menu access to placement modes + -- for weapon, utility, and med crates + elseif strucType[tempID] == loc("Support Station") then + + if GetGearType(gear) == gtHedgehog then + if GetHogClan(gear) == strucClan[tempID] then + tempE = AddVisualGear(GetX(strucGear[tempID]), GetY(strucGear[tempID]), vgtSmoke, 0, true) + + for i = 1, #sProx do + if ((sProx[i][1] == loc("Health Crate Placement Mode")) + or (sProx[i][1] == loc("Weapon Crate Placement Mode")) + or (sProx[i][1] == loc("Utility Crate Placement Mode"))) + then + sProx[i][2] = true + --AddCaption("wahey in a support station") + end + end + + + end + end + + -- doesn't do shit + elseif strucType[tempID] == loc("Core") then + + if GetGearType(gear) == gtHedgehog then + if GetHogClan(gear) == strucClan[tempID] then + + tempE = AddVisualGear(GetX(strucGear[tempID]), GetY(strucGear[tempID]), vgtSmoke, 0, true) + g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(tempE) + SetVisualGearValues(tempE, g1+20, g2, g3, g4, g5, g6, g7, g8, g9, GetClanColor(strucClan[tempID]) ) + + tempE = AddVisualGear(GetX(strucGear[tempID]), GetY(strucGear[tempID]), vgtSmoke, 0, true) + g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(tempE) + SetVisualGearValues(tempE, g1-20, g2, g3, g4, g5, g6, g7, g8, g9, GetClanColor(strucClan[tempID]) ) + + end + end + + end + + end + + --end + +end + +-- used to check if we need to run through all hogs or just currenthedgehog +function isAStructureThatAppliesToMultipleGears(pID) + if strucType[pID] == loc("Healing Station") or + strucType[pID] == loc("Reflector Shield") or + strucType[pID] == loc("Weapon Filter") or + strucType[pID] == loc("Bio-Filter") + then + return(true) + else + return(false) + end +end + +function HandleStructures() + + for i = 1, #sProx do + sProx[i][2] = false + + if sProx[i][1] == loc("Structure Placement Mode") then + sProx[i][2] = true + end + + end + + for i = 1, #strucID do + + g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(strucCirc[i]) + SetVisualGearValues(strucCirc[i], GetX(strucGear[i]), GetY(strucGear[i]), g3, g4, g5, g6, g7, strucCircRadius[i], g9, strucCircCol[i]) + + tempID = i + + g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(strucAltDisplay[i]) --8000 + SetVisualGearValues(strucAltDisplay[i], GetX(strucGear[i]), GetY(strucGear[i]), 0, 0, g5, g6, 800000, sprTarget, g9, g10 ) + + + + -- Check For proximity of stuff to our structures + if isAStructureThatAppliesToMultipleGears(i) then + runOnGears(CheckProximity) + else -- only check prox on CurrentHedgehog + CheckProximity(CurrentHedgehog) + end + + if strucType[i] == loc("Core") then + tempE = AddVisualGear(GetX(strucGear[i]), GetY(strucGear[i]), vgtSmoke, 0, true) + g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(tempE) + SetVisualGearValues(tempE, g1, g2, g3, g4, g5, g6, g7, g8, g9, GetClanColor(strucClan[i]) ) + elseif strucType[i] == loc("Reflector Shield") then + + + + --frameID = 1 + --visualSprite = sprTarget + --g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(strucAltDisplay[i]) --frameID / g6 + --SetVisualGearValues(strucAltDisplay[i], GetX(strucGear[i]), GetY(strucGear[i]), 0, 0, g5, g6, 8000, visualSprite, g9, g10 ) + + elseif strucType[i] == loc("Generator") then + + --frameID = 1 + --visualSprite = sprTarget + --layer + --tempE = AddVisualGear(GetX(strucGear[i]), GetY(strucGear[i]), vgtStraightShot, 1, true,1) + --g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(tempE) --g9 + --SetVisualGearValues(tempE, g1, g2, 0, 0, g5, frameID, g7, visualSprite, g9, g10 ) + --SetState(strucGear[i], bor(GetState(strucGear[i]),gstInvisible) ) + + --currently generate power for all clans. + -- or should power only be generated for current clan? + for z = 0, ClansCount-1 do + if z == strucClan[i] then + increaseGearValue(strucGear[i],"power") + if getGearValue(strucGear[i],"power") == 10 then + setGearValue(strucGear[i],"power",0) + clanPower[z] = clanPower[z] + 1 + if clanPower[z] > 1000 then + clanPower[z] = 1000 + end + end + + end + end + + end + + end + + + + -- this is kinda messy and gross (even more than usual), fix it up at some point + -- it just assumes that if you have access to girders, it works for rubbers + -- as that is what the struc implemenation means due to construction station + anyUIProx = false + for i = 1, #sProx do + + if sProx[i][1] == loc("Girder Placement Mode") then + if sProx[i][2] == true then + AddAmmo(CurrentHedgehog, amGirder, 100) + AddAmmo(CurrentHedgehog, amRubber, 100) + AddAmmo(CurrentHedgehog, amDrillStrike, 100) + else + AddAmmo(CurrentHedgehog, amGirder, 0) + AddAmmo(CurrentHedgehog, amRubber, 0) + AddAmmo(CurrentHedgehog, amDrillStrike, 0) -- new + end + elseif sProx[i][1] == loc("Teleportation Mode") then + if sProx[i][2] == true then + AddAmmo(CurrentHedgehog, amTeleport, 100) + else + AddAmmo(CurrentHedgehog, amTeleport, 0) + end + elseif sProx[i][1] == loc("Weapon Crate Placement Mode") then + -- this is new stuff + if sProx[i][2] == true then + AddAmmo(CurrentHedgehog, amNapalm, 100) + else + AddAmmo(CurrentHedgehog, amNapalm, 0) + end + end + + if (sProx[i][2] == true) then + anyUIProx = true + end + + end + + -- doesn't do shit atm, maybe later when we add cores we can use this + --if anyUIProx == true then --(and core is placed) + -- AddAmmo(CurrentHedgehog, amAirAttack, 100) + --else + -- AddAmmo(CurrentHedgehog, amAirAttack, 0) + --end + + +end + + +function checkForSpecialWeapons() + + + + if (GetCurAmmoType() == amAirAttack) then + AddCaption(loc("Structure Placement Tool"),GetClanColor(GetHogClan(CurrentHedgehog)),capgrpAmmoinfo) + elseif (GetCurAmmoType() == amDrillStrike) then + AddCaption(loc("Object Placement Tool"),GetClanColor(GetHogClan(CurrentHedgehog)),capgrpAmmoinfo) + elseif (GetCurAmmoType() == amNapalm) then + AddCaption(loc("Crate Placement Tool"),GetClanColor(GetHogClan(CurrentHedgehog)),capgrpAmmoinfo) + end + + lastWep = GetCurAmmoType() + +end + +---------------------------------------------------------- +-- EXCERPTS OF ADAPTED HEDGE_EDITOR CODE FOLLOWS +---------------------------------------------------------- +-- experimental crap + +local landType = 0 +----------------------------------------- +-- tracking vars for save slash load purposes +----------------------------------------- + +local hhs = {} + +--------------------------------- +-- crates are made of this stuff +--------------------------------- +placeholder = 20 + atkArray = + { + {amBazooka, "amBazooka", 0, loc("Bazooka"), 2*placeholder}, + --{amBee, "amBee", 0, loc("Homing Bee"), 4*placeholder}, + {amMortar, "amMortar", 0, loc("Mortar"), 1*placeholder}, + {amDrill, "amDrill", 0, loc("Drill Rocket"), 3*placeholder}, + {amSnowball, "amSnowball", 0, loc("Mudball"), 3*placeholder}, + + {amGrenade, "amGrenade", 0, loc("Grenade"), 2*placeholder}, + {amClusterBomb, "amClusterBomb", 0, loc("Cluster Bomb"), 3*placeholder}, + {amMolotov, "amMolotov", 0, loc("Molotov Cocktail"), 3*placeholder}, + {amWatermelon, "amWatermelon", 0, loc("Watermelon Bomb"), 25*placeholder}, + {amHellishBomb, "amHellishBomb", 0, loc("Hellish Handgrenade"), 25*placeholder}, + {amGasBomb, "amGasBomb", 0, loc("Limburger"), 3*placeholder}, + + {amShotgun, "amShotgun", 0, loc("Shotgun"), 2*placeholder}, + {amDEagle, "amDEagle", 0, loc("Desert Eagle"), 2*placeholder}, + {amFlamethrower,"amFlamethrower", 0, loc("Flamethrower"), 4*placeholder}, + {amSniperRifle, "amSniperRifle", 0, loc("Sniper Rifle"), 3*placeholder}, + --{amSineGun, "amSineGun", 0, loc("SineGun"), 6*placeholder}, + {amIceGun, "amIceGun", 0, loc("Freezer"), 15*placeholder}, + {amLandGun, "amLandGun", 0, loc("Land Sprayer"), 5*placeholder}, + + {amFirePunch, "amFirePunch", 0, loc("Shoryuken"), 3*placeholder}, + {amWhip, "amWhip", 0, loc("Whip"), 1*placeholder}, + {amBaseballBat, "amBaseballBat", 0, loc("Baseball Bat"), 7*placeholder}, + --{amKamikaze, "amKamikaze", 0, loc("Kamikaze"), 1*placeholder}, + {amSeduction, "amSeduction", 0, loc("Seduction"), 1*placeholder}, + {amHammer, "amHammer", 0, loc("Hammer"), 1*placeholder}, + + {amMine, "amMine", 0, loc("Mine"), 1*placeholder}, + {amDynamite, "amDynamite", 0, loc("Dynamite"), 9*placeholder}, + {amCake, "amCake", 0, loc("Cake"), 25*placeholder}, + {amBallgun, "amBallgun", 0, loc("Ballgun"), 40*placeholder}, + --{amRCPlane, "amRCPlane", 0, loc("RC Plane"), 25*placeholder}, + {amSMine, "amSMine", 0, loc("Sticky Mine"), 5*placeholder}, + + --{amAirAttack, "amAirAttack", 0, loc("Air Attack"), 10*placeholder}, + --{amMineStrike, "amMineStrike", 0, loc("Mine Strike"), 15*placeholder}, + --{amDrillStrike, "amDrillStrike", 0, loc("Drill Strike"), 15*placeholder}, + --{amNapalm, "amNapalm", 0, loc("Napalm"), 15*placeholder}, + --{amPiano, "amPiano", 0, loc("Piano Strike"), 40*placeholder}, + + {amKnife, "amKnife", 0, loc("Cleaver"), 2*placeholder}, + + {amBirdy, "amBirdy", 0, loc("Birdy"), 7*placeholder} + + } + + utilArray = + { + {amBlowTorch, "amBlowTorch", 0, loc("Blowtorch"), 4*placeholder}, + {amPickHammer, "amPickHammer", 0, loc("Pickhammer"), 2*placeholder}, + --{amGirder, "amGirder", 0, loc("Girder"), 4*placeholder}, + --{amRubber, "amRubber", 0, loc("Rubber Band"), 5*placeholder}, + {amPortalGun, "amPortalGun", 0, loc("Personal Portal Device"), 15*placeholder}, + + {amRope, "amRope", 0, loc("Rope"), 7*placeholder}, + {amParachute, "amParachute", 0, loc("Parachute"), 2*placeholder}, + --{amTeleport, "amTeleport", 0, loc("Teleport"), 6*placeholder}, + {amJetpack, "amJetpack", 0, loc("Flying Saucer"), 8*placeholder}, + + {amInvulnerable, "amInvulnerable", 0, loc("Invulnerable"), 5*placeholder}, + {amLaserSight, "amLaserSight", 0, loc("Laser Sight"), 2*placeholder}, + {amVampiric, "amVampiric", 0, loc("Vampirism"), 6*placeholder}, + + {amLowGravity, "amLowGravity", 0, loc("Low Gravity"), 4*placeholder}, + {amExtraDamage, "amExtraDamage", 0, loc("Extra Damage"), 6*placeholder}, + {amExtraTime, "amExtraTime", 0, loc("Extra Time"), 8*placeholder} + + --{amResurrector, "amResurrector", 0, loc("Resurrector"), 8*placeholder}, + --{amTardis, "amTardis", 0, loc("Tardis"), 2*placeholder}, + + --{amSwitch, "amSwitch", 0, loc("Switch Hog"), 4*placeholder} + } + +---------------------------- +-- hog and map editting junk +---------------------------- + + local reducedSpriteIDArray = { + sprBigDigit, sprKowtow, sprBee, sprExplosion50, sprGirder + } + + local reducedSpriteTextArray = { + "sprBigDigit", "sprKowtow", "sprBee", "sprExplosion50", "sprGirder" + } + +---------------------------- +-- placement shite +---------------------------- + +local cGear = nil -- detects placement of girders and objects (using airattack) +local curWep = amNothing + +-- primary placement categories +local cIndex = 1 -- category index +local cat = { + "Girder Placement Mode", + "Rubber Placement Mode", + "Mine Placement Mode", + "Sticky Mine Placement Mode", + "Barrel Placement Mode", + "Health Crate Placement Mode", + "Weapon Crate Placement Mode", + "Utility Crate Placement Mode", + --"Target Placement Mode", + --"Cleaver Placement Mode", + + --"Advanced Repositioning Mode", + --"Tagging Mode", + --"Sprite Testing Mode", + --"Sprite Placement Mode", + "Structure Placement Mode" + } + + + sProx = { + {loc("Girder Placement Mode"),false}, + {loc("Rubber Placement Mode"),false}, + {loc("Mine Placement Mode"),false}, + {loc("Sticky Mine Placement Mode"),false}, + {loc("Barrel Placement Mode"),false}, + {loc("Health Crate Placement Mode"),false}, + {loc("Weapon Crate Placement Mode"),false}, + {loc("Utility Crate Placement Mode"),false}, + --{loc("Target Placement Mode"),false}, + --{loc("Cleaver Placement Mode"),false}, + + --{loc("Advanced Repositioning Mode"),false}, + --{loc("Tagging Mode"),false}, + --{loc("Sprite Testing Mode"),false}, + --{loc("Sprite Placement Mode"),false}, + {loc("Structure Placement Mode"),false}, + {loc("Teleportation Mode"),false} + } + + +local pMode = {} -- pMode contains custom subsets of the main categories +local pIndex = 1 + +local genTimer = 0 + +local CGR = 1 -- current girder rotation, we actually need this as HW remembers what rotation you last used + +local placedX = {} +local placedY = {} +local placedSpec = {} +local placedSuperSpec = {} +local placedType = {} +local placedCount = 0 + +local sCirc -- circle that appears around selected gears +local sGear = nil +local closestDist +local closestGear = nil + +local tCirc = {} -- array of circles that appear around tagged gears + +------------------------ +-- SOME GENERAL METHODS +------------------------ + +function GetDistFromGearToXY(gear, g2X, g2Y) + + g1X, g1Y = GetGearPosition(gear) + q = g1X - g2X + w = g1Y - g2Y + + return ( (q*q) + (w*w) ) + +end + +function GetDistFromXYtoXY(a, b, c, d) + q = a - c + w = b - d + return ( (q*q) + (w*w) ) +end + +function SelectGear(gear) + + d = GetDistFromGearToXY(gear, placedX[placedCount], placedY[placedCount]) + + if d < closestDist then + closestDist = d + closestGear = gear + end + +end + +-- essentially called when user clicks the mouse +-- with girders or an airattack +function PlaceObject(x,y) + + placedX[placedCount] = x + placedY[placedCount] = y + placedType[placedCount] = cat[cIndex] + placedSpec[placedCount] = pMode[pIndex] + + if (clanUsedExtraTime[GetHogClan(CurrentHedgehog)] == true) and (cat[cIndex] == "Utility Crate Placement Mode") and (utilArray[pIndex][1] == amExtraTime) then + AddCaption(loc("You may only use 1 Extra Time per turn."),0xffba00ff,capgrpVolume) + PlaySound(sndDenied) + elseif (clanCratesSpawned[GetHogClan(CurrentHedgehog)] > 4) and ( (cat[cIndex] == "Health Crate Placement Mode") or (cat[cIndex] == "Utility Crate Placement Mode") or (cat[cIndex] == "Weapon Crate Placement Mode") ) then + AddCaption(loc("You may only spawn 5 crates per turn."),0xffba00ff,capgrpVolume) + PlaySound(sndDenied) + elseif (XYisInRect(x,y, clanBoundsSX[GetHogClan(CurrentHedgehog)],clanBoundsSY[GetHogClan(CurrentHedgehog)],clanBoundsEX[GetHogClan(CurrentHedgehog)],clanBoundsEY[GetHogClan(CurrentHedgehog)]) == true) + and (clanPower[GetHogClan(CurrentHedgehog)] >= placedExpense) + then + + + + if cat[cIndex] == "Girder Placement Mode" then + PlaceGirder(x, y, CGR) + placedSpec[placedCount] = CGR + elseif cat[cIndex] == "Rubber Placement Mode" then + PlaceSprite(x,y, sprAmRubber, CGR, nil, nil, nil, nil, lfBouncy) + --PlaceGirder(x, y, CGR) + placedSpec[placedCount] = CGR + elseif cat[cIndex] == "Target Placement Mode" then + gear = AddGear(x, y, gtTarget, 0, 0, 0, 0) + elseif cat[cIndex] == "Cleaver Placement Mode" then + gear = AddGear(x, y, gtKnife, 0, 0, 0, 0) + elseif cat[cIndex] == "Health Crate Placement Mode" then + gear = SpawnHealthCrate(x,y) + SetHealth(gear, pMode[pIndex]) + setGearValue(gear,"caseType","med") + clanCratesSpawned[GetHogClan(CurrentHedgehog)] = clanCratesSpawned[GetHogClan(CurrentHedgehog)] +1 + elseif cat[cIndex] == "Weapon Crate Placement Mode" then + gear = SpawnAmmoCrate(x, y, atkArray[pIndex][1]) + placedSpec[placedCount] = atkArray[pIndex][2] + setGearValue(gear,"caseType","ammo") + setGearValue(gear,"contents",atkArray[pIndex][2]) + clanCratesSpawned[GetHogClan(CurrentHedgehog)] = clanCratesSpawned[GetHogClan(CurrentHedgehog)] +1 + elseif cat[cIndex] == "Utility Crate Placement Mode" then + gear = SpawnUtilityCrate(x, y, utilArray[pIndex][1]) + placedSpec[placedCount] = utilArray[pIndex][2] + setGearValue(gear,"caseType","util") + setGearValue(gear,"contents",utilArray[pIndex][2]) + if utilArray[pIndex][1] == amExtraTime then + clanUsedExtraTime[GetHogClan(CurrentHedgehog)] = true + end + clanCratesSpawned[GetHogClan(CurrentHedgehog)] = clanCratesSpawned[GetHogClan(CurrentHedgehog)] +1 + elseif cat[cIndex] == "Barrel Placement Mode" then + gear = AddGear(x, y, gtExplosives, 0, 0, 0, 0) + SetHealth(gear, pMode[pIndex]) + elseif cat[cIndex] == "Mine Placement Mode" then + gear = AddGear(x, y, gtMine, 0, 0, 0, 0) + SetTimer(gear, pMode[pIndex]) + elseif cat[cIndex] == "Sticky Mine Placement Mode" then + gear = AddGear(x, y, gtSMine, 0, 0, 0, 0) + elseif cat[cIndex] == "Advanced Repositioning Mode" then + + if pMode[pIndex] == "Selection Mode" then + closestDist = 999999999 + closestGear = nil -- just in case + sGear = nil + runOnGears(SelectGear) + sGear = closestGear + closestGear = nil + elseif pMode[pIndex] == "Placement Mode" then + if sGear ~= nil then + SetGearPosition(sGear, x, y) + end + end + + elseif cat[cIndex] == "Tagging Mode" then + + closestDist = 999999999 + closestGear = nil + sGear = nil + runOnGears(SelectGear) + + + if closestGear ~= nil then + + if getGearValue(closestGear,"tag") == nil then + + --if there is no tag, add a victory/failure tag and circle + setGearValue(closestGear, "tCirc",AddVisualGear(0,0,vgtCircle,0,true)) + + --AddCaption("circ added",0xffba00ff,capgrpVolume) + + if pMode[pIndex] == "Tag Victory Mode" then + setGearValue(closestGear, "tag","victory") + SetVisualGearValues(getGearValue(closestGear,"tCirc"), 0, 0, 100, 255, 1, 10, 0, 40, 3, 0xff0000ff) + elseif pMode[pIndex] == "Tag Failure Mode" then + setGearValue(closestGear, "tag","failure") + SetVisualGearValues(getGearValue(closestGear,"tCirc"), 0, 0, 100, 255, 1, 10, 0, 40, 3, 0x0000ffff) + end + + + else + -- remove tag and delete circ + --AddCaption("circ removed",0xffba00ff,capgrpVolume) + setGearValue(closestGear, "tag", nil) + DeleteVisualGear(getGearValue(closestGear,"tCirc")) + setGearValue(closestGear, "tCirc", nil) + end + + end + + + elseif cat[cIndex] == "Sprite Testing Mode" then + + frameID = 1 + visualSprite = reducedSpriteIDArray[pIndex] + --visualSprite = spriteIDArray[pIndex] + tempE = AddVisualGear(x, y, vgtStraightShot, 0, true) + g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(tempE) + SetVisualGearValues(tempE, g1, g2, 0, 0, g5, frameID, g7, visualSprite, g9, g10 ) + --sprHorizonLong crashes game, so does skyL, as does flake + + -- reduced list of cool sprites + -- sprBigDigit, sprKnife, sprFrozenHog, sprKowtow, sprBee, sprExplosion50, sprPiano, sprChunk, sprHHTelepMask, sprSeduction, sprSwitch, sprGirder, + --sprAMAmmos, sprAMSlotKeys, sprTurnsLeft, sprExplosivesRoll + maybe some others like the health case, arrows, etc + + elseif cat[cIndex] == "Sprite Placement Mode" then + + PlaceSprite(x,y, reducedSpriteIDArray[pIndex], 1, nil, nil, nil, nil, landType) + --PlaceGirder(x, y, CGR) + placedSpec[placedCount] = reducedSpriteTextArray[pIndex] + placedSuperSpec[placedCount] = landType + + if landType == lfIce then + placedSuperSpec[placedCount] = "lfIce" + elseif landType == lfIndestructible then + placedSuperSpec[placedCount] = "lfIndestructible" + elseif landType == lfBouncy then + placedSuperSpec[placedCount] = "lfBouncy" + else + placedSuperSpec[placedCount] = "lfNormal" + end + + elseif cat[cIndex] == "Structure Placement Mode" then + + AddStruc(x,y, pMode[pIndex],GetHogClan(CurrentHedgehog)) + + end + + clanPower[GetHogClan(CurrentHedgehog)] = clanPower[GetHogClan(CurrentHedgehog)] - placedExpense + placedCount = placedCount + 1 + + else + if (clanPower[GetHogClan(CurrentHedgehog)] >= placedExpense) then + AddCaption(loc("Invalid Placement"),0xffba00ff,capgrpVolume) + else + AddCaption(loc("Insufficient Power"),0xffba00ff,capgrpVolume) + end + PlaySound(sndDenied) + end + + +end + +-- called when user changes primary selection +-- either via up/down keys +-- or selecting girder/airattack +function RedefineSubset() + + pIndex = 1 + pMode = {} + placedExpense = 1 + + if cat[cIndex] == "Girder Placement Mode" then + pIndex = CGR + pMode = {"Girder"} + -- pCount = 1 + elseif cat[cIndex] == "Rubber Placement Mode" then + pIndex = CGR + pMode = {"Rubber"} + placedExpense = 3 + -- pCount = 1??? + elseif cat[cIndex] == "Target Placement Mode" then + pMode = {"Standard Target"} + elseif cat[cIndex] == "Cleaver Placement Mode" then + pMode = {"Standard Cleaver"} + elseif cat[cIndex] == "Barrel Placement Mode" then + --pMode = {1,50,75,100} + pMode = {50} + placedExpense = 10 + elseif cat[cIndex] == "Health Crate Placement Mode" then + --pMode = {25,50,75,100} + pMode = {25} + placedExpense = 5 + elseif cat[cIndex] == "Weapon Crate Placement Mode" then + for i = 1, #atkArray do + pMode[i] = atkArray[i][4] -- was [2] + --placedExpense = atkArray[5] + end + placedExpense = 30 + elseif cat[cIndex] == "Utility Crate Placement Mode" then + for i = 1, #utilArray do + pMode[i] = utilArray[i][4] -- was [2] + --placedExpense = utilArray[5] + end + placedExpense = 20 + elseif cat[cIndex] == "Mine Placement Mode" then + --pMode = {1,1000,2000,3000,4000,5000,0} + pMode = {1,1000,2000,3000,4000,5000} + -- 0 is dud right, or is that nil? + placedExpense = 15 + elseif cat[cIndex] == "Sticky Mine Placement Mode" then + pMode = {"Normal Sticky Mine"} + --elseif cat[cIndex] == "Gear Repositioning Mode" then + -- for i = 1, #hhs do + -- pMode[i] = GetHogName(hhs[i]) + -- end + placedExpense = 20 + elseif cat[cIndex] == "Advanced Repositioning Mode" then + pMode = {"Selection Mode","Placement Mode"} + elseif cat[cIndex] == "Tagging Mode" then + pMode = {"Tag Victory Mode","Tag Failure Mode"} + elseif cat[cIndex] == "Sprite Testing Mode" or cat[cIndex] == "Sprite Placement Mode" then + --for i = 1, #spriteTextArray do + -- pMode[i] = spriteTextArray[i] + --end + for i = 1, #reducedSpriteTextArray do + pMode[i] = reducedSpriteTextArray[i] + end + placedExpense = 100 + elseif cat[cIndex] == "Structure Placement Mode" then + pMode = {loc("Healing Station"), loc("Bio-Filter"), loc("Weapon Filter"), loc("Reflector Shield"), loc("Respawner"),loc("Teleportation Node"),--[[loc("Core"),]]loc("Generator"),loc("Construction Station"),loc("Support Station")} + --placedExpense = 100 + end + + + + +end + +-- called in onGameTick() +function HandleHedgeEditor() + + if CurrentHedgehog ~= nil then + + if wallsVisible == true then + HandleBorderEffects() + end + + if (CurrentHedgehog ~= nil) and (TurnTimeLeft ~= TurnTime) then + if (lastWep ~= GetCurAmmoType()) then + checkForSpecialWeapons() + end + end + + genTimer = genTimer + 1 + + if genTimer >= 100 then + + genTimer = 0 + + DrawTag(1) + + HandleStructures() + + curWep = GetCurAmmoType() + + -- change to girder mode on weapon swap + if (cIndex ~= 1) and (curWep == amGirder) then + cIndex = 1 + RedefineSubset() + elseif (cIndex ~=2) and (curWep == amRubber) then + cIndex = 2 + RedefineSubset() + -- change to generic mode if girder no longer selected + elseif (cIndex == 1) and (curWep ~= amGirder) then + cIndex = 3 -- was 2 + RedefineSubset() + elseif (cIndex == 2) and (curWep ~= amRubber) then + cIndex = 3 --new + RedefineSubset() + + end + + -- update display selection criteria + if (curWep == amGirder) or (curWep == amAirAttack) or (curWep == amNapalm) or (curWep == amDrillStrike) or (curWep == amRubber) then + + ---------------hooolllllyyyy fucking shit this + -- code is a broken mess now + -- it was redesigned and compromised three times + -- so now it is a mess trying to do what it was + -- never designed to do + -- needs to be rewritten badly sadface + -- this bit here catches the new 3 types of weapons + if ((sProx[cIndex][1] == loc("Structure Placement Mode") and (curWep ~= amAirAttack))) then + updatePlacementDisplay(1) + elseif (sProx[cIndex][1] == loc("Health Crate Placement Mode")) or + (sProx[cIndex][1] == loc("Weapon Crate Placement Mode")) or + (sProx[cIndex][1] == loc("Utility Crate Placement Mode")) then + if curWep ~= amNapalm then + updatePlacementDisplay(1) + end + + elseif (sProx[cIndex][1] == loc("Mine Placement Mode")) or + (sProx[cIndex][1] == loc("Sticky Mine Placement Mode")) or + (sProx[cIndex][1] == loc("Barrel Placement Mode")) then + if curWep ~= amDrillStrike then + updatePlacementDisplay(1) + end + + end + + --this is called when it happens that we have placement + --mode selected and we are looking at something + --we shouldn't be allowed to look at, as would be the case + --when you WERE allowed to look at it, but then maybe + --a bomb blows up the structure that was granting you + --that ability + if (sProx[cIndex][2] ~= true) then + updatePlacementDisplay(1) + else + updateCost() + end + + + AddCaption(loc(cat[cIndex]),0xffba00ff,capgrpMessage) + AddCaption(pMode[pIndex],0xffba00ff,capgrpMessage2) + wallsVisible = true + else + wallsVisible = false + end + + end + + end + + --update selected gear display + if (cat[cIndex] == "Advanced Repositioning Mode") and (sGear ~= nil) then + SetVisualGearValues(sCirc, GetX(sGear), GetY(sGear), 100, 255, 1, 10, 0, 300, 3, 0xff00ffff) + elseif (cat[cIndex] == "Tagging Mode") then + if (sGear ~= nil) or (closestGear ~= nil) then + SetVisualGearValues(sCirc, GetX(sGear), GetY(sGear), 0, 1, 1, 10, 0, 1, 1, 0x00000000) + closestGear = nil + sGear = nil + end + end + + -- some kind of target detected, tell me your story + if cGear ~= nil then + + x,y = GetGearTarget(cGear) + + if GetGearType(cGear) == gtAirAttack then + DeleteGear(cGear) + PlaceObject(x, y) + elseif GetGearType(cGear) == gtTeleport then + + CheckTeleport(cGear, x, y) + cGear = nil + elseif GetGearType(cGear) == gtGirder then + + CGR = GetState(cGear) + + -- improve rectangle test based on CGR when you can be bothered + --if TestRectForObstacle(x-20, y-20, x+20, y+20, true) then + -- AddCaption("Invalid Girder Placement",0xffba00ff,capgrpVolume) + --else + PlaceObject(x, y) + --end + + -- this allows the girder tool to be used like a mining laser + + --[[ + + if CGR < 4 then + AddGear(x, y, gtGrenade, 0, 0, 0, 1) + elseif CGR == 4 then + g = AddGear(x-30, y, gtGrenade, 0, 0, 0, 1) + g = AddGear(x+30, y, gtGrenade, 0, 0, 0, 1) + elseif CGR == 5 then ------- + g = AddGear(x+30, y+30, gtGrenade, 0, 0, 0, 1) + g = AddGear(x-30, y-30, gtGrenade, 0, 0, 0, 1) + elseif CGR == 6 then + g = AddGear(x, y+30, gtGrenade, 0, 0, 0, 1) + g = AddGear(x, y-30, gtGrenade, 0, 0, 0, 1) + elseif CGR == 7 then ------- + g = AddGear(x+30, y-30, gtGrenade, 0, 0, 0, 1) + g = AddGear(x-30, y+30, gtGrenade, 0, 0, 0, 1) + end +]] + end + + end + +end + +-------------------------------------------------- +-- EVENT HANDLERS +-------------------------------------------------- + +function onTaunt(t) + tauntString = tauntString .. t + if (tauntString == "101") and (clanPower[GetHogClan(CurrentHedgehog)] < 300) and (clanBoon[GetHogClan(CurrentHedgehog)] == false) then + clanBoon[GetHogClan(CurrentHedgehog)] = true + clanPower[GetHogClan(CurrentHedgehog)] = 1000 + AddCaption(loc("The Great Hog in the sky sees your sadness and grants you a boon.")) + end +end + +--------------------------------------------------------------- +-- Cycle through selection subsets (by changing pIndex, pMode) +-- i.e health of barrels, medikits, +-- timer of mines +-- contents of crates +-- gears to reposition etc. +--------------------------------------------------------------- + +function updateCost() + + if pMode[pIndex] == loc("Healing Station") then + placedExpense = 50 + elseif pMode[pIndex] == loc("Weapon Filter") then + placedExpense = 50 + elseif pMode[pIndex] == loc("Bio-Filter") then + placedExpense = 100 + elseif pMode[pIndex] == loc("Respawner") then + placedExpense = 300 + elseif pMode[pIndex] == loc("Teleportation Node") then + placedExpense = 30 + elseif pMode[pIndex] == loc("Support Station") then + placedExpense = 50 + elseif pMode[pIndex] == loc("Construction Station") then + placedExpense = 50 + elseif pMode[pIndex] == loc("Generator") then + placedExpense = 300 + elseif pMode[pIndex] == loc("Reflector Shield") then + placedExpense = 200 + elseif pMode[pIndex] == loc("Core") then + placedExpense = 1 + elseif cat[cIndex] == loc("Weapon Crate Placement Mode") then + placedExpense = atkArray[pIndex][5] + elseif cat[cIndex] == loc("Utility Crate Placement Mode") then + placedExpense = utilArray[pIndex][5] + end + + AddCaption(loc("Cost") .. ": " .. placedExpense,0xffba00ff,capgrpAmmostate) + +end + +function onLeft() + + pIndex = pIndex - 1 + if pIndex == 0 then + pIndex = #pMode + end + + if (curWep == amGirder) or (curWep == amAirAttack) or (curWep == amNapalm) or (curWep == amDrillStrike) then + AddCaption(pMode[pIndex],0xffba00ff,capgrpMessage2) + updateCost() + end + + +end + +function onRight() + + pIndex = pIndex + 1 + if pIndex > #pMode then + pIndex = 1 + end + + if (curWep == amGirder) or (curWep == amAirAttack) or (curWep == amNapalm) or (curWep == amDrillStrike) then + AddCaption(pMode[pIndex],0xffba00ff,capgrpMessage2) + updateCost() + end + +end + + +function updatePlacementDisplay(pDir) + + foundMatch = false + while(foundMatch == false) do + cIndex = cIndex + pDir + + if (cIndex == 1) or (cIndex == 2) then --1 --we no longer hit girder by normal means + cIndex = #cat + elseif cIndex > #cat then + cIndex = 3 -- 2 ----we no longer hit girder by normal means + end + + -- new way of doing things + -- sProx[cIndex][2] == true just basically means we have ACCESS to something + -- but that doesn't neccessarily mean we are in the correct content menu, anymore + -- so we need to refine this a little + if sProx[cIndex][2] == true then + if (GetCurAmmoType() == amNapalm) then + if (sProx[cIndex][1] == loc("Health Crate Placement Mode")) or + (sProx[cIndex][1] == loc("Weapon Crate Placement Mode")) or + (sProx[cIndex][1] == loc("Utility Crate Placement Mode")) + then + foundMatch = true + end + elseif (GetCurAmmoType() == amDrillStrike) then + if (sProx[cIndex][1] == loc("Mine Placement Mode")) or + (sProx[cIndex][1] == loc("Sticky Mine Placement Mode")) or + (sProx[cIndex][1] == loc("Barrel Placement Mode")) + then + foundMatch = true + end + elseif (GetCurAmmoType() == amAirAttack) then + if sProx[cIndex][1] == loc("Structure Placement Mode") then + foundMatch = true + end + end + end + + + if foundMatch == true then + --if sProx[cIndex][2] == true then + -- normal case (scrolling through) + --foundMatch = true + RedefineSubset() + updateCost() + end + + end + +end + +--------------------------------------------------------- +-- Cycle through primary categories (by changing cIndex) +-- i.e mine, sticky mine, barrels +-- health/weapon/utility crate, placement of gears +--------------------------------------------------------- +function onUp() + + if ((curWep == amAirAttack) or (curWep == amNapalm) or (curWep == amDrillStrike) ) then + updatePlacementDisplay(-1) + end + +end + +function onDown() + + if ((curWep == amAirAttack) or (curWep == amNapalm) or (curWep == amDrillStrike) ) then + updatePlacementDisplay(1) + end + +end + +---------------------------- +-- standard event handlers +---------------------------- + +function onGameInit() + + Explosives = 0 + MinesNum = 0 + + EnableGameFlags(gfInfAttack) + + + RedefineSubset() + +end + +function initialSetup(gear) + + FindPlace(gear, false, clanBoundsSX[GetHogClan(gear)], clanBoundsEX[GetHogClan(gear)],true) + + -- for now, everyone should have this stuff + AddAmmo(gear, amAirAttack, 100) + AddAmmo(gear, amSwitch, 100) + AddAmmo(gear, amSkip, 100) + +end + +function onGameStart() + + trackTeams() + + ShowMission ( + loc("CONSTRUCTION MODE"), + loc("a Hedgewars mini-game"), + " " .. "|" .. + loc("Build a fortress and destroy your enemy.") .. "|" .. + --loc("Defend your core from the enemy.") .. "|" .. + loc("There are a variety of structures available to aid you.") .. "|" .. + loc("Use the air-attack weapons and the arrow keys to select structures.") .. "|" .. + " " .. "|" .. + --loc("Core") .. ": " .. loc("Allows placement of structures.") .. "|" .. + loc("Healing Station") .. ": " .. loc("Grants nearby hogs life-regeneration.") .. "|" .. + loc("Bio-Filter") .. ": " .. loc("Aggressively removes enemy hedgehogs.") .. "|" .. + loc("Weapon Filter") .. ": " .. loc("Dematerializes weapons and equipment carried by enemy hedgehogs.") .. "|" .. + loc("Reflector Shield") .. ": " .. loc("Reflects enemy projectiles.") .. "|" .. + + loc("Generator") .. ": " .. loc("Generates power.") .. "|" .. + loc("Respawner") .. ": " .. loc("Resurrects dead hedgehogs.") .. "|" .. + loc("Teleportation Node") .. ": " .. loc("Allows free teleportation between other nodes.") .. "|" .. + loc("Construction Station") .. ": " .. loc("Allows placement of girders, rubber-bands, mines, sticky mines and barrels.") .. "|" .. + loc("Support Station") .. ": " .. loc("Allows the placement of weapons, utiliites, and health crates.") .. "|" .. + + + " " .. "|" .. + --" " .. "|" .. + "", 4, 5000 + ) + + + sCirc = AddVisualGear(0,0,vgtCircle,0,true) + SetVisualGearValues(sCirc, 0, 0, 100, 255, 1, 10, 0, 40, 3, 0x00000000) + + for i = 0, ClansCount-1 do + clanPower[i] = 500 + clanBoon[i] = false + clanLWepIndex[i] = 1 -- for ease of use let's track this stuff + clanLUtilIndex[i] = 1 + clanLGearIndex[i] = 1 + clanUsedExtraTime[i] = false + clanCratesSpawned[i] = 0 + + + end + + tMapWidth = RightX - LeftX + tMapHeight = WaterLine - TopY + clanInterval = div(tMapWidth,ClansCount) + + for i = 1, ClansCount do + + clanBoundsSX[i-1] = LeftX+(clanInterval*i)-clanInterval+20 + clanBoundsSY[i-1] = TopY + clanBoundsEX[i-1] = LeftX+(clanInterval*i)-20 + clanBoundsEY[i-1] = WaterLine + + --top and bottom + AddWall(LeftX+(clanInterval*i)-clanInterval,TopY,clanInterval,margin,GetClanColor(i-1)) + AddWall(LeftX+(clanInterval*i)-clanInterval,WaterLine-25,clanInterval,margin,GetClanColor(i-1)) + + --add a wall to the left and right + AddWall(LeftX+(clanInterval*i)-clanInterval+20,TopY,margin,WaterLine,GetClanColor(i-1)) + AddWall(LeftX+(clanInterval*i)-20,TopY,margin,WaterLine,GetClanColor(i-1)) + + end + + runOnHogs(initialSetup) + +end + + +function onNewTurn() + + tauntString = "" + clanPower[GetHogClan(CurrentHedgehog)] = clanPower[GetHogClan(CurrentHedgehog)] + 50 + clanUsedExtraTime[GetHogClan(CurrentHedgehog)] = false + clanCratesSpawned[GetHogClan(CurrentHedgehog)] = 0 + +end + +function onGameTick() + HandleHedgeEditor() +end + +function isATrackedGear(gear) + if (GetGearType(gear) == gtHedgehog) or + (GetGearType(gear) == gtTarget) or + (GetGearType(gear) == gtCase) + then + return(true) + else + return(false) + end +end + +-- track hedgehogs and placement gears +function onGearAdd(gear) + + if GetGearType(gear) == gtHedgehog then + --table.insert(hhs, gear) + elseif (GetGearType(gear) == gtAirAttack) or (GetGearType(gear) == gtTeleport) or (GetGearType(gear) == gtGirder) then + cGear = gear + + end + + if isATrackedGear(gear) then + trackGear(gear) + elseif gearCanBeDeflected(gear) then + trackGear(gear) + setGearReflectionValues(gear) + end + +end + +function onGearDelete(gear) + + if GetGearType(gear) == gtTarget then + CheckGearForStructureLink(gear) + end + + if (GetGearType(gear) == gtAirAttack) or (GetGearType(gear) == gtTeleport) or (GetGearType(gear) == gtGirder) then + cGear = nil + end + + if (isATrackedGear(gear) or gearCanBeDeflected(gear)) then + + if getGearValue(gear, "tCirc") ~= nil then + DeleteVisualGear(getGearValue(gear, "tCirc")) + end + + trackDeletion(gear) + + end + +end diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Scripts/Multiplayer/Continental_supplies.lua --- a/share/hedgewars/Data/Scripts/Multiplayer/Continental_supplies.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Scripts/Multiplayer/Continental_supplies.lua Tue Nov 10 20:43:13 2015 +0100 @@ -1,41 +1,46 @@ --[[ -Version 1.1c + version 1.3n -Copyright (C) 2012 Vatten + The expat (MIT) license -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + Copyright (C) 2012 Vatten + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ]] HedgewarsScriptLoad("/Scripts/Locale.lua") HedgewarsScriptLoad("/Scripts/Utils.lua") HedgewarsScriptLoad("/Scripts/Tracker.lua") -function int_sqrt(num) +--approximative version of square root. This function follows the babylonian method. +function IntegerSqrt(num) local temp=num while(temp*temp-div(temp,2)>num) do temp=div((temp+div(num,temp)),2) end - + return math.abs(temp) end -function norm(xx,yy) +-- sqrt(x^2,y^2), work without desyncs. is approximative +function Norm(xx,yy) --to fix overflows if(((math.abs(xx)^2)+(math.abs(yy)^2))>2^26) then local bitr=2^13 - return int_sqrt((div(math.abs(xx),bitr)^2)+(div(math.abs(yy),bitr)^2))*bitr + return IntegerSqrt((div(math.abs(xx),bitr)^2)+(div(math.abs(yy),bitr)^2))*bitr else - return int_sqrt((math.abs(xx)^2)+(math.abs(yy)^2)) + return IntegerSqrt((math.abs(xx)^2)+(math.abs(yy)^2)) end end -function positive(num) +-- returns 1 or -1 depending on where it is +function GetIfNegative(num) if(num<0) then return -1 @@ -44,110 +49,164 @@ end end -local teams_ok = {} -local wepcode_teams={} -local swapweps=false +--Will end the turn + give escape time +function EndTurn() + SetState(CurrentHedgehog,bor(GetState(CurrentHedgehog),gstAttacked)) + --3 sec espace time + TurnTimeLeft = GetAwayTime*10*3 + end + + --show health tag (will mostly be used when a hog is damaged) +function ShowDamageTag(hog,damage) + healthtag=AddVisualGear(GetX(hog), GetY(hog), vgtHealthTag, damage, false) + v1, v2, v3, v4, v5, v6, v7, v8, v9, v10 = GetVisualGearValues(healthtag) + SetVisualGearValues(healthtag, v1, v2, v3, v4, v5, v6, v7, v8, v9, GetClanColor(GetHogClan(hog))) +end + +--will use IntegerSqrt +function FireGear(hedgehog,geartype,vx,vy,timer) + local hypo=Norm(vx,vy) + return AddGear(div((GetGearRadius(hedgehog)*2*vx),hypo)+GetX(hedgehog), div((GetGearRadius(hedgehog)*2*vy),hypo)+GetY(hedgehog), geartype, 0, vx, vy, timer) +end + +--This function will set the gravity on a scale from 0->100, where 50 is the standard one. + function SetGravityFromScale(grav) + if(grav>100) + then + grav=100 + elseif(grav<0) + then + grav=0 + end + + if(grav>50) + then + SetGravity(100+((grav-50)*12)) + else + SetGravity(25+grav+div(grav,2)) + end + end + +--====MISC GLOBALS==== + +--for selecting continent +local GLOBAL_INIT_TEAMS = {} +local GLOBAL_SELECT_CONTINENT_CHECK=false +local GLOBAL_TEAM_CONTINENT = {} --variables for seeing if you have swaped around on a weapon -local australianSpecial=false -local africanSpecial=0 -local africaspecial2=0 -local asianSpecial=false -local samericanSpecial=false -local namericanSpecial=1 -local sniper_s_in_use=false -local kergulenSpecial=1 -local shotgun_s=false -local europe_s=0 -local VampOn=0 +local GLOBAL_AUSTRALIAN_SPECIAL=0 +local GLOBAL_AFRICAN_SPECIAL_SEDUCTION=0 +local GLOBAL_AFRICAN_SPECIAL_STICKY=0 +local GLOBAL_SOUTH_AMERICAN_SPECIAL=false +local GLOBAL_NORTH_AMERICAN_SPECIAL_SNIPER=1 +local GLOBAL_NORTH_AMERICAN_SPECIAL_SNIPER_IS_ON=false +local GLOBAL_KERGUELEN_SPECIAL=1 +local GLOBAL_NORTH_AMERICAN_SPECIAL_SHOTGUN=false +local GLOBAL_EUROPE_SPECIAL=0 -local austmine=nil -local inpara=false -local asianflame=0 +--detection if something is activated +local GLOBAL_SWITCH_HOG_IS_ON=false +local GLOBAL_VAMPIRIC_IS_ON=0 +local GLOBAL_EXTRA_DAMAGE_IS_ON=100 +local GLOBAL_PARACHUTE_IS_ON=false -local visualcircle=nil +--the visual circle for kerguelen +local GLOBAL_VISUAL_CIRCLE=nil -local temp_val=0 +--the global temp value +local GLOBAL_TEMP_VALUE=0 --for sabotage -local disallowattack=0 -local disable_moving={} -local disableoffsetai=0 -local onsabotageai=false +local GLOBAL_SABOTAGE_COUNTER=0 +local GLOBAL_SABOTAGE_HOGS={} +local GLOBAL_SABOTAGE_FREQUENCY=0 +local GLOBAL_SABOTAGE_GRAVITY_SWITCH=true -local continent = {} +--for sundaland +local GLOBAL_SUNDALAND_END_HOG=0 -local generalinfo=loc("- Per team weapons|- 9 weaponschemes|- Unique new weapons| |Select continent first round with the Weapon Menu or by ([switch/tab]=Increase,[presice/left shift]=Decrease) on Skip|Some weapons have a second option. Find them with [switch/tab]") +--====GENERAL GLOBALS (useful for handling continents)==== + +local GLOBAL_GENERAL_INFORMATION="- "..loc("Per team weapons").."|- 10 "..loc("weaponschemes").."|- "..loc("Unique new weapons").."| |"..loc("Select your continent/weaponset: with the \"Up\" or \"Down\" keys. You can also select one with the weapons menu.").."|"..loc("Note: Some weapons have a second option (See continent information). Find and use them with the \"")..loc("switch").."\" "..loc("key.").."|"..loc("Tip: See the \"esc\" key (this menu) if you want to see the currently playing teams continent, or that continents specials.") + +local GLOBAL_SHOW_SMALL_INFO=0 -local weapontexts = { -loc("Green lipstick bullet: [Is poisonous]"), -loc("Piñata bullet: [Contains some sweet candy!]"), -loc("Anno 1032: [The explosion will make a strong push ~ wide range, wont affect hogs close to the target]"), +local GLOBAL_WEAPON_TEXTS = { +loc("Green lipstick bullet: [Poisonous, deals no damage]"), +loc("Cluck-cluck time: [Fire an egg ~ Sabotages and cures poison ~ Cannot be fired close to another hog]"), +loc("Anno 1032: [The explosion will make a strong push ~ Wide range, wont affect hogs close to the target]"), loc("Dust storm: [Deals 15 damage to all enemies in the circle]"), -loc("Fire a mine: [Does what it says ~ Cant be dropped close to an enemy ~ 1 sec]"), -loc("Drop a bomb: [drop some heroic wind that will turn into a bomb on impact ~ once per turn]"), -loc("Scream from a Walrus: [Deal 20 damage + 10% of your hogs health to all hogs around you and get half back]"), +loc("Cricket time: [Fire away a 1 sec mine! ~ Cannot be fired close to another hog]"), +loc("Drop a bomb: [Drop some heroic wind that will turn into a bomb on impact]"), +loc("Penguin roar: [Deal 15 damage + 10% of your hogs health to all hogs around you and get 2/3 back]"), loc("Disguise as a Rockhopper Penguin: [Swap place with a random enemy hog in the circle]"), -loc("Flare: [fire up some bombs depending on hogs depending on hogs in the circle"), -loc("Lonely Cries: [Rise the water if no hog is in the circle and deal 7 damage to all enemy hogs]"), -loc("Hedgehog projectile: [fire your hog like a Sticky Bomb]"), +nil, +loc("Lonely Cries: [Rise the water if no hog is in the circle and deal 6 damage to all enemy hogs.]"), +loc("Hedgehog projectile: [Fire your hog like a Sticky Bomb]"), loc("Napalm rocket: [Fire a bomb with napalm!]"), -loc("Eagle Eye: [Blink to the impact ~ one shot]"), +loc("Eagle Eye: [Blink to the impact ~ One shot]"), loc("Medicine: [Fire some exploding medicine that will heal all hogs effected by the explosion]"), -loc("Sabotage: [Sabotage all hogs in the circle and deal ~10 dmg]") +loc("Sabotage/Flare: [Sabotage all hogs in the circle and deal ~1 dmg OR Fire a cluster up into the air]") } -local weaponsets = +local GLOBAL_CONTINENT_INFORMATION = { -{loc("North America"),"Area: 24,709,000 km2, Population: 528,720,588",loc("Special Weapons:").."|"..loc("Shotgun")..": "..weapontexts[13].."|"..loc("Sniper Rifle")..": "..weapontexts[1].."|"..loc("Sniper Rifle")..": "..weapontexts[2],amSniperRifle, -{{amShotgun,100},{amDEagle,100},{amLaserSight,4},{amSniperRifle,100},{amCake,1},{amAirAttack,2},{amSwitch,6}}}, +{loc("North America"),"["..loc("Difficulty: ")..loc("EASY").."] "..loc("Area")..": 24,709,000 km2, "..loc("Population")..": 529,000,000",loc("- You can switch between hogs at the start of your turns. (Not first one)").."|"..loc("Special Weapons:").."|"..loc("Shotgun")..": "..GLOBAL_WEAPON_TEXTS[13].."|"..loc("Sniper Rifle")..": "..GLOBAL_WEAPON_TEXTS[1],amSniperRifle, +{{amShotgun,100},{amDEagle,100},{amLaserSight,2},{amSniperRifle,100},{amCake,1},{amAirAttack,2},{amSwitch,2}}}, -{loc("South America"),"Area: 17,840,000 km2, Population: 387,489,196 ",loc("Special Weapons:").."|"..loc("GasBomb")..": "..weapontexts[3],amGasBomb, -{{amBirdy,6},{amHellishBomb,1},{amBee,100},{amWhip,100},{amGasBomb,100},{amFlamethrower,100},{amNapalm,1},{amExtraDamage,2}}}, +{loc("South America"),"["..loc("Difficulty: ")..loc("MEDIUM").."] "..loc("Area")..": 17,840,000 km2, "..loc("Population")..": 387,000,000",loc("Special Weapons:").."|"..loc("GasBomb")..": "..GLOBAL_WEAPON_TEXTS[3],amGasBomb, +{{amBirdy,100},{amHellishBomb,1},{amBee,100},{amGasBomb,100},{amFlamethrower,100},{amNapalm,1},{amExtraDamage,2}}}, -{loc("Europe"),"Area: 10,180,000 km2, Population: 739,165,030",loc("Special Weapons:").."|"..loc("Molotov")..": "..weapontexts[14],amBazooka, -{{amBazooka,100},{amGrenade,100},{amMortar,100},{amClusterBomb,5},{amMolotov,5},{amVampiric,4},{amPiano,1},{amResurrector,2},{amJetpack,2}}}, +{loc("Europe"),"["..loc("Difficulty: ")..loc("EASY").."] "..loc("Area")..": 10,180,000 km2, "..loc("Population")..": 740,000,000",loc("Special Weapons:").."|"..loc("Molotov")..": "..GLOBAL_WEAPON_TEXTS[14],amBazooka, +{{amBazooka,100},{amGrenade,100},{amMortar,100},{amMolotov,100},{amVampiric,3},{amPiano,1},{amResurrector,2},{amJetpack,4}}}, -{loc("Africa"),"Area: 30,221,532 km2, Population: 1,032,532,974",loc("Special Weapons:").."|"..loc("Seduction")..": "..weapontexts[4].."|"..loc("Sticky Mine")..": "..weapontexts[11].."|"..loc("Sticky Mine")..": "..weapontexts[12],amSMine, -{{amSMine,100},{amWatermelon,1},{amDrillStrike,1},{amExtraTime,2},{amDrill,100},{amLandGun,3},{amSeduction,100}}}, +{loc("Africa"),"["..loc("Difficulty: ")..loc("MEDIUM").."] "..loc("Area")..": 30,222,000 km2, "..loc("Population")..": 1,033,000,000",loc("Special Weapons:").."|"..loc("Seduction")..": "..GLOBAL_WEAPON_TEXTS[4].."|"..loc("Sticky Mine")..": "..GLOBAL_WEAPON_TEXTS[11].."|"..loc("Sticky Mine")..": "..GLOBAL_WEAPON_TEXTS[12],amSMine, +{{amSMine,100},{amWatermelon,1},{amDrillStrike,1},{amDrill,100},{amInvulnerable,5},{amSeduction,100},{amLandGun,2}}}, -{loc("Asia"),"Area: 44,579,000 km2, Population: 3,879,000,000",loc("- Will give you a parachute each turn.").."|"..loc("Special Weapons:").."|"..loc("Parachute")..": "..weapontexts[6],amRope, -{{amKamikaze,4},{amRope,100},{amFirePunch,100},{amParachute,1},{amKnife,2},{amDynamite,1}}}, +{loc("Asia"),"["..loc("Difficulty: ")..loc("MEDIUM").."] "..loc("Area")..": 44,579,000 km2, "..loc("Population")..": 3,880,000,000",loc("- Will give you a parachute every second turn.").."|"..loc("Special Weapons:").."|"..loc("Parachute")..": "..GLOBAL_WEAPON_TEXTS[6],amRope, +{{amRope,100},{amFirePunch,100},{amParachute,2},{amKnife,2},{amDynamite,1}}}, -{loc("Australia"),"Area: 8,468,300 km2, Population: 31,260,000",loc("Special Weapons:").."|"..loc("Baseballbat")..": "..weapontexts[5],amBaseballBat, -{{amBaseballBat,100},{amMine,100},{amLowGravity,6},{amBlowTorch,100},{amRCPlane,2},{amTardis,100}}}, +{loc("Australia"),"["..loc("Difficulty: ")..loc("EASY").."] "..loc("Area")..": 8,468,000 km2, "..loc("Population")..": 31,000,000",loc("Special Weapons:").."|"..loc("Baseballbat")..": "..GLOBAL_WEAPON_TEXTS[5].."|"..loc("Baseballbat")..": "..GLOBAL_WEAPON_TEXTS[2],amBaseballBat, +{{amBaseballBat,100},{amMine,100},{amLowGravity,4},{amBlowTorch,100},{amRCPlane,2},{amTeleport,2},{amRubber,2}}}, + +{loc("Antarctica"),"["..loc("Difficulty: ")..loc("HARD").."] "..loc("Area")..": 14,000,000 km2, "..loc("Population")..": ~1,000",loc("Antarctic summer: - Will give you one girder/mudball and two sineguns/portals every fourth turn."),amIceGun, +{{amSnowball,2},{amIceGun,2},{amPickHammer,100},{amSineGun,5},{amGirder,2},{amExtraTime,1},{amPortalGun,2}}}, -{loc("Antarctica"),"Area: 14,000,000 km2, Population: ~1,000",loc("- Will give you a portalgun every second turn."),amTeleport, -{{amSnowball,4},{amTeleport,2},{amInvulnerable,6},{amPickHammer,100},{amSineGun,100},{amGirder,3},{amPortalGun,2}}}, +{loc("Kerguelen"),"["..loc("Difficulty: ")..loc("EASY").."] "..loc("Area")..": 1,100,000 km2, "..loc("Population")..": ~100",loc("Special Weapons:").."|"..loc("Hammer")..": "..GLOBAL_WEAPON_TEXTS[7].."|"..loc("Hammer")..": "..GLOBAL_WEAPON_TEXTS[8].." ("..loc("Duration")..": 2)|"..loc("Hammer")..": "..GLOBAL_WEAPON_TEXTS[10].."|"..loc("Hammer")..": "..GLOBAL_WEAPON_TEXTS[15],amHammer, +{{amHammer,100},{amMineStrike,1},{amBallgun,1}}}, -{loc("Kerguelen"),"Area: 1,100,000 km2, Population: ~70",loc("Special Weapons:").."|"..loc("Hammer")..": "..weapontexts[7].."|"..loc("Hammer")..": "..weapontexts[8].." ("..loc("Duration")..": 2)|"..loc("Hammer")..": "..weapontexts[9].."|"..loc("Hammer")..": "..weapontexts[10].."|"..loc("Hammer")..": "..weapontexts[15],amHammer, -{{amHammer,100},{amMineStrike,2},{amBallgun,1},{amIceGun,2}}}, +{loc("Zealandia"),"["..loc("Difficulty: ")..loc("MEDIUM").."] "..loc("Area")..": 3,500,000 km2, "..loc("Population")..": 5,000,000",loc("- Will Get 1-3 random weapons") .. "|" .. loc("- Massive weapon bonus on first turn"),amInvulnerable, +{{amBazooka,1},{amGrenade,1},{amBlowTorch,1},{amSwitch,100},{amRope,1},{amDrill,1},{amDEagle,1},{amPickHammer,1},{amFirePunch,1},{amWhip,1},{amMortar,1},{amSnowball,1},{amExtraTime,1},{amInvulnerable,1},{amVampiric,1},{amFlamethrower,1},{amBee,1},{amClusterBomb,1},{amTeleport,1},{amLowGravity,1},{amJetpack,1},{amGirder,1},{amLandGun,1},{amBirdy,1}}}, -{loc("Zealandia"),"Area: 3,500,000 km2, Population: 4,650,000",loc("- Will Get 1-3 random weapons"),amInvulnerable, -{{amBazooka,1},{amBlowTorch,1},{amSwitch,1}}} +{loc("Sundaland"),"["..loc("Difficulty: ")..loc("HARD").."] "..loc("Area")..": 1,850,000 km2, "..loc("Population")..": 290,000,000",loc("- You will recieve 2-4 weapons on each kill! (Even on own hogs)"),amTardis, +{{amClusterBomb,4},{amTardis,4},{amWhip,100},{amKamikaze,4}}} + } -local weaponsetssounds= +local GLOBAL_CONTINENT_SOUNDS= { -{sndShotgunFire,sndCover}, -{sndEggBreak,sndLaugh}, -{sndExplosion,sndEnemyDown}, -{sndMelonImpact,sndHello}, -{sndRopeAttach,sndComeonthen}, -{sndBaseballBat,sndNooo}, -{sndSineGun,sndOops}, -{sndPiano5,sndStupid}, -{sndSplash,sndFirstBlood} + {sndShotgunFire,sndCover}, + {sndEggBreak,sndLaugh}, + {sndExplosion,sndEnemyDown}, + {sndMelonImpact,sndCoward}, + {sndRopeAttach,sndComeonthen}, + {sndBaseballBat,sndNooo}, + {sndSineGun,sndOops}, + {sndPiano5,sndStupid}, + {sndSplash,sndFirstBlood}, + {sndWarp,sndSameTeam}, + {sndFrozenHogImpact,sndUhOh} } --weapontype,ammo,?,duration,*times your choice,affect on random team (should be placed with 1,0,1,0,1 on the 6th option for better randomness) -local weapons_dmg = { +local GLOBAL_WEAPONS_DAMAGE = { {amKamikaze, 0, 1, 0, 1, 0}, {amSineGun, 0, 1, 0, 1, 1}, {amBazooka, 0, 1, 0, 1, 0}, {amMineStrike, 0, 1, 5, 1, 2}, {amGrenade, 0, 1, 0, 1, 0}, - {amPiano, 0, 1, 5, 1, 1}, + {amPiano, 0, 1, 5, 1, 0}, {amClusterBomb, 0, 1, 0, 1, 0}, {amBee, 0, 1, 0, 1, 0}, {amShotgun, 0, 0, 0, 1, 1}, @@ -168,19 +227,18 @@ {amDrill, 0, 1, 0, 1, 0}, {amBallgun, 0, 1, 5, 1, 2}, {amMolotov, 0, 1, 0, 1, 0}, - {amBirdy, 0, 1, 1, 1, 1}, + {amHammer, 0, 1, 0, 1, 2}, + {amBirdy, 0, 1, 0, 1, 0}, {amBlowTorch, 0, 1, 0, 1, 0}, {amRCPlane, 0, 1, 5, 1, 2}, {amGasBomb, 0, 0, 0, 1, 0}, {amAirAttack, 0, 1, 4, 1, 1}, {amFlamethrower, 0, 1, 0, 1, 0}, {amSMine, 0, 1, 0, 1, 1}, - {amHammer, 0, 1, 0, 1, 0}, {amDrillStrike, 0, 1, 4, 1, 2}, {amSnowball, 0, 1, 0, 1, 0} - --{amStructure, 0, 0, 0, 1, 1} } -local weapons_supp = { +local GLOBAL_WEAPONS_SUPPORT = { {amParachute, 0, 1, 0, 1, 0}, {amGirder, 0, 1, 0, 1, 0}, {amSwitch, 0, 1, 0, 1, 0}, @@ -198,50 +256,77 @@ {amLandGun, 0, 1, 0, 1, 0}, {amTardis, 0, 1, 0, 1, 0}, {amIceGun, 0, 1, 0, 1, 0}, - {amKnife, 0, 1, 0, 1, 0} + {amKnife, 0, 1, 0, 1, 0}, + {amRubber, 0, 1, 0, 1, 0} + } --will check after borders and stuff -function validate_weapon(hog,weapon,amount) +function ValidateWeapon(hog,weapon,amount) if(MapHasBorder() == false or (MapHasBorder() == true and weapon ~= amAirAttack and weapon ~= amMineStrike and weapon ~= amNapalm and weapon ~= amDrillStrike and weapon ~= amPiano)) then - AddAmmo(hog, weapon,amount) + if(amount==1) + then + AddAmmo(hog, weapon) + else + AddAmmo(hog, weapon,amount) + end + end +end + +--removes one weapon +function RemoveWeapon(hog,weapon) + + if(GetAmmoCount(hog, weapon)<100) + then + AddAmmo(hog,weapon,GetAmmoCount(hog, weapon)-1) end end --reset all weapons for a team -function cleanweps(hog) +function CleanWeapons(hog) local i=1 - --+1 for skip +1 for freezer - while(i<=table.maxn(weapons_supp)+table.maxn(weapons_dmg)+2) + --+1 for skip + while(i<=table.maxn(GLOBAL_WEAPONS_SUPPORT)+table.maxn(GLOBAL_WEAPONS_DAMAGE)+1) do AddAmmo(hog,i,0) i=i+1 end - + AddAmmo(hog,amSkip,100) end --get the weapons from a weaponset -function load_weaponset(hog, num) - for v,w in pairs(weaponsets[num][5]) +function LoadWeaponset(hog, num) + for v,w in pairs(GLOBAL_CONTINENT_INFORMATION[num][5]) do - validate_weapon(hog, w[1],w[2]) + ValidateWeapon(hog, w[1],w[2]) end end --list up all weapons from the icons for each continent -function load_continent_selection(hog) - for v,w in pairs(weaponsets) - do - validate_weapon(hog, weaponsets[v][4],1) +function InitWeaponsMenu(hog) + + if(GetHogLevel(hog)==0) + then + for v,w in pairs(GLOBAL_CONTINENT_INFORMATION) + do + ValidateWeapon(hog, GLOBAL_CONTINENT_INFORMATION[v][4],1) + end + AddAmmo(hog,amSwitch) --random continent + + --for the computers + else + --europe + ValidateWeapon(hog, GLOBAL_CONTINENT_INFORMATION[3][4],1) + --north america + ValidateWeapon(hog, GLOBAL_CONTINENT_INFORMATION[1][4],1) end - AddAmmo(hog,amSwitch) --random continent end --shows the continent info -function show_continent_info(continent,time,generalinf) +function ShowContinentInfo(continent,time,generalinf) local geninftext="" local ns=false if(time==-1) @@ -251,9 +336,12 @@ end if(generalinf) then - geninftext="| |"..loc("General information")..": |"..generalinfo + geninftext="| |"..loc("General information")..": |"..GLOBAL_GENERAL_INFORMATION end - ShowMission(weaponsets[continent][1],weaponsets[continent][2],weaponsets[continent][3]..geninftext, -weaponsets[continent][4], time) + + GLOBAL_SHOW_SMALL_INFO=div(time,40) + + ShowMission(GLOBAL_CONTINENT_INFORMATION[continent][1],GLOBAL_CONTINENT_INFORMATION[continent][2],GLOBAL_CONTINENT_INFORMATION[continent][3]..geninftext, -GLOBAL_CONTINENT_INFORMATION[continent][4], time) if(ns) then HideMission() @@ -261,7 +349,7 @@ end --will show a circle of gears (eye candy) -function visual_gear_explosion(range,xpos,ypos,gear1,gear2) +function VisualExplosion(range,xpos,ypos,gear1,gear2) local degr=0 local lap=30 while(lapTotalRounds) + + local numberofweaponssupp=table.maxn(GLOBAL_WEAPONS_SUPPORT) + local numberofweaponsdmg=table.maxn(GLOBAL_WEAPONS_DAMAGE) + + local rand1=math.abs(GetRandom(numberofweaponssupp)+1) + local rand2=math.abs(GetRandom(numberofweaponsdmg)+1) + + random_weapon = math.abs(GetRandom(table.maxn(GLOBAL_WEAPONS_DAMAGE))+1) + + while(GLOBAL_WEAPONS_DAMAGE[random_weapon][4]>TotalRounds or (MapHasBorder() == true and (GLOBAL_WEAPONS_DAMAGE[random_weapon][1]== amAirAttack or GLOBAL_WEAPONS_DAMAGE[random_weapon][1] == amMineStrike or GLOBAL_WEAPONS_DAMAGE[random_weapon][1] == amNapalm or GLOBAL_WEAPONS_DAMAGE[random_weapon][1] == amDrillStrike or GLOBAL_WEAPONS_DAMAGE[random_weapon][1] == amPiano))) do - if(random_weapon>=numberof_weapons_dmg) + if(random_weapon>=numberofweaponsdmg) then random_weapon=0 end random_weapon = random_weapon+1 end - validate_weapon(hog, weapons_dmg[random_weapon][1],1) - rand_weaponset_power=weapons_dmg[random_weapon][6] + ValidateWeapon(hog, GLOBAL_WEAPONS_DAMAGE[random_weapon][1],1) + rand_weaponset_power=GLOBAL_WEAPONS_DAMAGE[random_weapon][6] old_rand_weap = random_weapon - + if(rand_weaponset_power <2) then random_weapon = rand1 - while(weapons_supp[random_weapon][4]>TotalRounds or rand_weaponset_power+weapons_supp[random_weapon][6]>2) + while(GLOBAL_WEAPONS_SUPPORT[random_weapon][4]>TotalRounds or rand_weaponset_power+GLOBAL_WEAPONS_SUPPORT[random_weapon][6]>2) do - if(random_weapon>=numberof_weapons_supp) + if(random_weapon>=numberofweaponssupp) then random_weapon=0 end random_weapon = random_weapon+1 end - validate_weapon(hog, weapons_supp[random_weapon][1],1) - rand_weaponset_power=rand_weaponset_power+weapons_supp[random_weapon][6] + ValidateWeapon(hog, GLOBAL_WEAPONS_SUPPORT[random_weapon][1],1) + rand_weaponset_power=rand_weaponset_power+GLOBAL_WEAPONS_SUPPORT[random_weapon][6] end --check again if the power is enough if(rand_weaponset_power <1) then random_weapon = rand2 - while(weapons_dmg[random_weapon][4]>TotalRounds or old_rand_weap == random_weapon or weapons_dmg[random_weapon][6]>0) + while(GLOBAL_WEAPONS_DAMAGE[random_weapon][4]>TotalRounds or old_rand_weap == random_weapon or GLOBAL_WEAPONS_DAMAGE[random_weapon][6]>0 or (MapHasBorder() == true and (GLOBAL_WEAPONS_DAMAGE[random_weapon][1]== amAirAttack or GLOBAL_WEAPONS_DAMAGE[random_weapon][1] == amMineStrike or GLOBAL_WEAPONS_DAMAGE[random_weapon][1] == amNapalm or GLOBAL_WEAPONS_DAMAGE[random_weapon][1] == amDrillStrike or GLOBAL_WEAPONS_DAMAGE[random_weapon][1] == amPiano))) do - if(random_weapon>=numberof_weapons_dmg) + if(random_weapon>=numberofweaponsdmg) then random_weapon=0 end random_weapon = random_weapon+1 end - validate_weapon(hog, weapons_dmg[random_weapon][1],1) + ValidateWeapon(hog, GLOBAL_WEAPONS_DAMAGE[random_weapon][1],1) end - + setTeamValue(GetHogTeamName(hog), "rand-done-turn", true) end end ---this will take that hogs settings for the weapons and add them -function setweapons() +--sundaland add weps +function SundalandGetWeapons(hog) + + local random_weapon = 0 + local old_rand_weap = 0 + local rand_weaponset_power = 0 + + local firstTurn=0 + + local numberofweaponssupp=table.maxn(GLOBAL_WEAPONS_SUPPORT) + local numberofweaponsdmg=table.maxn(GLOBAL_WEAPONS_DAMAGE) + + local rand1=GetRandom(numberofweaponssupp)+1 + local rand2=GetRandom(numberofweaponsdmg)+1 + local rand3=GetRandom(numberofweaponsdmg)+1 + + random_weapon = GetRandom(numberofweaponsdmg)+1 + + if(TotalRounds<0) + then + firstTurn=-TotalRounds + end + + while(GLOBAL_WEAPONS_DAMAGE[random_weapon][4]>(TotalRounds+firstTurn) or (MapHasBorder() == true and (GLOBAL_WEAPONS_DAMAGE[random_weapon][1]== amAirAttack or GLOBAL_WEAPONS_DAMAGE[random_weapon][1] == amMineStrike or GLOBAL_WEAPONS_DAMAGE[random_weapon][1] == amNapalm or GLOBAL_WEAPONS_DAMAGE[random_weapon][1] == amDrillStrike or GLOBAL_WEAPONS_DAMAGE[random_weapon][1] == amPiano))) + do + if(random_weapon>=numberofweaponsdmg) + then + random_weapon=0 + end + random_weapon = random_weapon+1 + end + ValidateWeapon(hog, GLOBAL_WEAPONS_DAMAGE[random_weapon][1],1) + rand_weaponset_power=GLOBAL_WEAPONS_DAMAGE[random_weapon][6] + old_rand_weap = random_weapon - cleanweps(CurrentHedgehog) - load_weaponset(CurrentHedgehog,continent[GetHogTeamName(CurrentHedgehog)]) - + random_weapon = rand1 + while(GLOBAL_WEAPONS_SUPPORT[random_weapon][4]>(TotalRounds+firstTurn) or rand_weaponset_power+GLOBAL_WEAPONS_SUPPORT[random_weapon][6]>2) + do + if(random_weapon>=numberofweaponssupp) + then + random_weapon=0 + end + random_weapon = random_weapon+1 + end + ValidateWeapon(hog, GLOBAL_WEAPONS_SUPPORT[random_weapon][1],1) + rand_weaponset_power=rand_weaponset_power+GLOBAL_WEAPONS_SUPPORT[random_weapon][6] + + --check again if the power is enough + if(rand_weaponset_power <2) + then + random_weapon = rand2 + while(GLOBAL_WEAPONS_DAMAGE[random_weapon][4]>(TotalRounds+firstTurn) or old_rand_weap == random_weapon or GLOBAL_WEAPONS_DAMAGE[random_weapon][6]>0 or (MapHasBorder() == true and (GLOBAL_WEAPONS_DAMAGE[random_weapon][1]== amAirAttack or GLOBAL_WEAPONS_DAMAGE[random_weapon][1] == amMineStrike or GLOBAL_WEAPONS_DAMAGE[random_weapon][1] == amNapalm or GLOBAL_WEAPONS_DAMAGE[random_weapon][1] == amDrillStrike or GLOBAL_WEAPONS_DAMAGE[random_weapon][1] == amPiano))) + do + if(random_weapon>=numberofweaponsdmg) + then + random_weapon=0 + end + random_weapon = random_weapon+1 + end + ValidateWeapon(hog, GLOBAL_WEAPONS_DAMAGE[random_weapon][1],1) + rand_weaponset_power=GLOBAL_WEAPONS_DAMAGE[random_weapon][6] + end + + if(rand_weaponset_power <1) + then + random_weapon = rand3 + while(GLOBAL_WEAPONS_DAMAGE[random_weapon][4]>(TotalRounds+firstTurn) or old_rand_weap == random_weapon or GLOBAL_WEAPONS_DAMAGE[random_weapon][6]>0 or (MapHasBorder() == true and (GLOBAL_WEAPONS_DAMAGE[random_weapon][1]== amAirAttack or GLOBAL_WEAPONS_DAMAGE[random_weapon][1] == amMineStrike or GLOBAL_WEAPONS_DAMAGE[random_weapon][1] == amNapalm or GLOBAL_WEAPONS_DAMAGE[random_weapon][1] == amDrillStrike or GLOBAL_WEAPONS_DAMAGE[random_weapon][1] == amPiano))) + do + if(random_weapon>=numberofweaponsdmg) + then + random_weapon=0 + end + random_weapon = random_weapon+1 + end + ValidateWeapon(hog, GLOBAL_WEAPONS_DAMAGE[random_weapon][1],1) + end + + AddVisualGear(GetX(hog), GetY(hog)-30, vgtEvilTrace,0, false) + PlaySound(sndReinforce,hog) +end + + +--this will take that hogs settings for the weapons and add them +function SetContinentWeapons() + + CleanWeapons(CurrentHedgehog) + LoadWeaponset(CurrentHedgehog,GLOBAL_TEAM_CONTINENT[GetHogTeamName(CurrentHedgehog)]) + visualstuff=AddVisualGear(GetX(CurrentHedgehog), GetY(CurrentHedgehog)-5, vgtDust,0, false) v1, v2, v3, v4, v5, v6, v7, v8, v9, v10 = GetVisualGearValues(visualstuff) SetVisualGearValues(visualstuff, v1, v2, v3, v4, v5, v6, v7, 2, v9, GetClanColor(GetHogClan(CurrentHedgehog))) - - show_continent_info(continent[GetHogTeamName(CurrentHedgehog)],0,false) -end ---show health tag (will mostly be used when a hog is damaged) -function show_damage_tag(hog,damage) - healthtag=AddVisualGear(GetX(hog), GetY(hog), vgtHealthTag, damage, false) - v1, v2, v3, v4, v5, v6, v7, v8, v9, v10 = GetVisualGearValues(healthtag) - SetVisualGearValues(healthtag, v1, v2, v3, v4, v5, v6, v7, v8, v9, GetClanColor(GetHogClan(hog))) -end - ---will use int_sqrt -function fire_gear(hedgehog,geartype,vx,vy,timer) - local hypo=norm(vx,vy) - return AddGear(div((GetGearRadius(hedgehog)*2*vx),hypo)+GetX(hedgehog), div((GetGearRadius(hedgehog)*2*vy),hypo)+GetY(hedgehog), geartype, 0, vx, vy, timer) + ShowContinentInfo(GLOBAL_TEAM_CONTINENT[GetHogTeamName(CurrentHedgehog)],3000,false) end --==========================run throw all hog/gear weapons ========================== ---will check if the mine is nicely placed -function weapon_aust_check(hog) +--will check if the mine is nicely placed +function AustraliaSpecialCheckHogs(hog) if(GetGearType(hog) == gtHedgehog) then - if(gearIsInCircle(hog,GetX(CurrentHedgehog), GetY(CurrentHedgehog), 50, false)==true and hog ~= CurrentHedgehog) + if(gearIsInCircle(hog,GetX(CurrentHedgehog), GetY(CurrentHedgehog), 40, false)==true and hog ~= CurrentHedgehog) then - temp_val=1 + GLOBAL_TEMP_VALUE=1 end end end --african special on sedunction -function weapon_duststorm(hog) +function AfricaSpecialSeduction(hog) if(GetGearType(hog) == gtHedgehog) then - local dmg=15 + local dmg=div(15*GLOBAL_EXTRA_DAMAGE_IS_ON,100) if(gearIsInCircle(hog,GetX(CurrentHedgehog), GetY(CurrentHedgehog), 250, false)==true and GetHogClan(hog) ~= GetHogClan(CurrentHedgehog)) then if(GetHealth(hog) > dmg) then - temp_val=temp_val+div(dmg*VampOn,100) + GLOBAL_TEMP_VALUE=GLOBAL_TEMP_VALUE+div(dmg*GLOBAL_VAMPIRIC_IS_ON,100) SetHealth(hog, GetHealth(hog)-dmg) else - temp_val=temp_val+div(GetHealth(hog)*VampOn,100) + GLOBAL_TEMP_VALUE=GLOBAL_TEMP_VALUE+div(GetHealth(hog)*GLOBAL_VAMPIRIC_IS_ON,100) SetHealth(hog, 0) end - show_damage_tag(hog,dmg) + ShowDamageTag(hog,dmg) end end end ---kerguelen special on structure -function weapon_scream_walrus(hog) +--kerguelen special on structure +function KerguelenSpecialRed(hog) if(GetGearType(hog) == gtHedgehog) then if(gearIsInCircle(hog,GetX(CurrentHedgehog), GetY(CurrentHedgehog), 120, false)==true and GetHogClan(hog) ~= GetHogClan(CurrentHedgehog)) then - if(GetHealth(hog)>(20+GetHealth(CurrentHedgehog)*0.1)) + local dmg=div((15+div(GetHealth(CurrentHedgehog)*10,100))*GLOBAL_EXTRA_DAMAGE_IS_ON,100) + + if(GetHealth(hog)>dmg) then - temp_val=temp_val+10+(GetHealth(CurrentHedgehog)*0.05)+div((20+GetHealth(CurrentHedgehog)*0.1)*VampOn,100) - SetHealth(hog, GetHealth(hog)-(20+GetHealth(CurrentHedgehog)*0.1)) + GLOBAL_TEMP_VALUE=GLOBAL_TEMP_VALUE+div(dmg*2,3)+div(dmg*GLOBAL_VAMPIRIC_IS_ON*2,100*3) + SetHealth(hog, GetHealth(hog)-dmg) else - temp_val=temp_val+(GetHealth(hog)*0.5)+(GetHealth(CurrentHedgehog)*0.05)+div((GetHealth(hog)+(GetHealth(CurrentHedgehog)*0.1))*VampOn,100) + GLOBAL_TEMP_VALUE=GLOBAL_TEMP_VALUE+(div(GetHealth(hog)*75,100))+(div(GetHealth(CurrentHedgehog)*10,100))+div((GetHealth(hog)+div(GetHealth(CurrentHedgehog)*10,100))*GLOBAL_VAMPIRIC_IS_ON,100) SetHealth(hog, 0) end - show_damage_tag(hog,(20+GetHealth(CurrentHedgehog)*0.1)) + ShowDamageTag(hog,dmg) AddVisualGear(GetX(hog), GetY(hog), vgtExplosion, 0, false) AddVisualGear(GetX(CurrentHedgehog), GetY(CurrentHedgehog), vgtSmokeWhite, 0, false) end end end ---kerguelen special swap hog -function weapon_swap_kerg(hog) +--will count the hogs, used to get one random hog. +function KerguelenSpecialYellowCountHogs(hog) if(GetGearType(hog) == gtHedgehog) then - if(kergulenSpecial ~= -1 and GetHogClan(hog) ~= GetHogClan(CurrentHedgehog) and gearIsInCircle(hog,GetX(CurrentHedgehog), GetY(CurrentHedgehog), 450, false)) + if(GetHogClan(hog) ~= GetHogClan(CurrentHedgehog) and gearIsInCircle(hog,GetX(CurrentHedgehog), GetY(CurrentHedgehog), 420, false)) then - local thisX=GetX(CurrentHedgehog) - local thisY=GetY(CurrentHedgehog) - SetGearPosition(CurrentHedgehog, GetX(hog), GetY(hog)) - SetGearPosition(hog, thisX, thisY) - kergulenSpecial=-1 + GLOBAL_TEMP_VALUE=GLOBAL_TEMP_VALUE+1 end end end - ---kerguelen special on structure -function weapon_flare(hog) +--kerguelen special swap hog +function KerguelenSpecialYellowSwap(hog) if(GetGearType(hog) == gtHedgehog) then - if(GetHogClan(hog) ~= GetHogClan(CurrentHedgehog) and gearIsInCircle(hog,GetX(CurrentHedgehog), GetY(CurrentHedgehog), 45, false)) + if(GLOBAL_KERGUELEN_SPECIAL ~= -1 and GetHogClan(hog) ~= GetHogClan(CurrentHedgehog) and gearIsInCircle(hog,GetX(CurrentHedgehog), GetY(CurrentHedgehog), 420, false)) then - if(GetX(hog)<=GetX(CurrentHedgehog)) + if(GLOBAL_TEMP_VALUE==0) then - dirker=1 + local thisX=GetX(CurrentHedgehog) + local thisY=GetY(CurrentHedgehog) + SetGearPosition(CurrentHedgehog, GetX(hog), GetY(hog)) + SetGearPosition(hog, thisX, thisY) + GLOBAL_KERGUELEN_SPECIAL=-1 else - dirker=-1 + GLOBAL_TEMP_VALUE=GLOBAL_TEMP_VALUE-1 end - AddVisualGear(GetX(hog), GetY(hog), vgtFire, 0, false) - SetGearPosition(CurrentHedgehog, GetX(CurrentHedgehog), GetY(CurrentHedgehog)-5) - SetGearVelocity(CurrentHedgehog, 100000*dirker, -300000) - AddGear(GetX(CurrentHedgehog), GetY(CurrentHedgehog)-20, gtCluster, 0, -10000*dirker, -1000000, 35) - PlaySound(sndHellishImpact2) end end end --kerguelen special will apply sabotage -function weapon_sabotage(hog) +function KerguelenSpecialGreen(hog) + if(GetGearType(hog) == gtHedgehog) + then + if(CurrentHedgehog~=hog and gearIsInCircle(hog,GetX(CurrentHedgehog), GetY(CurrentHedgehog), 80, false)) + then + GLOBAL_TEMP_VALUE=1 + GLOBAL_SABOTAGE_HOGS[hog]=1 + AddGear(GetX(hog), GetY(hog), gtCluster, 0, 0, 0, 1) + PlaySound(sndNooo,hog) + end + end +end + +--first part on kerguelen special (lonely cries) +function KerguelenSpecialBlueCheck(hog) + if(GetGearType(hog) == gtHedgehog and hog ~= CurrentHedgehog and gearIsInCircle(hog,GetX(CurrentHedgehog), GetY(CurrentHedgehog), 550, false)) + then + GLOBAL_KERGUELEN_SPECIAL=-1 + end +end + +--second part on kerguelen special (lonely cries) +function KerguelenSpecialBlueActivate(hog) if(GetGearType(hog) == gtHedgehog) then - if(GetHogClan(hog) ~= GetHogClan(CurrentHedgehog) and gearIsInCircle(hog,GetX(CurrentHedgehog), GetY(CurrentHedgehog), 100, false)) + local dmg=div(6*GLOBAL_EXTRA_DAMAGE_IS_ON,100) + if(GetHogClan(hog) ~= GetHogClan(CurrentHedgehog)) then - disable_moving[hog]=true - AddGear(GetX(hog), GetY(hog), gtCluster, 0, 0, 0, 10) + if(GetHealth(hog) > dmg) + then + GLOBAL_TEMP_VALUE=GLOBAL_TEMP_VALUE+div(dmg*GLOBAL_VAMPIRIC_IS_ON,100) + SetHealth(hog, GetHealth(hog)-dmg) + else + GLOBAL_TEMP_VALUE=GLOBAL_TEMP_VALUE+div(GetHealth(hog)*GLOBAL_VAMPIRIC_IS_ON,100) + SetHealth(hog, 0) + end + ShowDamageTag(hog,dmg) + + AddVisualGear(GetX(hog), GetY(hog)-30, vgtEvilTrace, 0, false) + end + end +end + +--australia +function AustraliaSpecialEggHit(hog) + if(GetGearType(hog) == gtHedgehog) + then + if(gearIsInCircle(hog,GetX(GLOBAL_TEMP_VALUE), GetY(GLOBAL_TEMP_VALUE), 18, false)) + then + GLOBAL_SABOTAGE_HOGS[hog]=1 PlaySound(sndNooo,hog) + SetEffect(hog, hePoisoned, false) end end end --south american special (used fire gear) -function weapon_anno_south(hog) - local power_radius_outer=230 - local power_radius_inner=45 - local power_sa=500000 - local hypo=0 - if(gearIsInCircle(hog,GetX(temp_val), GetY(temp_val), power_radius_outer, false) and gearIsInCircle(hog,GetX(temp_val), GetY(temp_val), power_radius_inner, false)==false) - then - if(hog == CurrentHedgehog) - then - SetState(CurrentHedgehog, gstMoving) - end - SetGearPosition(hog, GetX(hog),GetY(hog)-3) - hypo=norm(math.abs(GetX(hog)-GetX(temp_val)),math.abs(GetY(hog)-GetY(temp_val))) - SetGearVelocity(hog, div((power_radius_outer-hypo)*power_sa*positive(GetX(hog)-GetX(temp_val)),power_radius_outer), div((power_radius_outer-hypo)*power_sa*positive(GetY(hog)-GetY(temp_val)),power_radius_outer)) - end -end - ---first part on kerguelen special (lonely cries) -function weapon_cries_a(hog) - if(GetGearType(hog) == gtHedgehog and hog ~= CurrentHedgehog and gearIsInCircle(hog,GetX(CurrentHedgehog), GetY(CurrentHedgehog), 500, false)) +function SouthAmericaSpecialCheeseExplosion(hog) + if(GetGearType(hog) == gtHedgehog or GetGearType(hog) == gtMine or GetGearType(hog) == gtExplosives) then - kergulenSpecial=-1 - end -end - ---second part on kerguelen special (lonely cries) -function weapon_cries_b(hog) - if(GetGearType(hog) == gtHedgehog) - then - local dmg=7 - if(GetHogClan(hog) ~= GetHogClan(CurrentHedgehog)) + local power_radius_outer=230 + local power_radius_inner=45 + local power_sa=500000 + local hypo=0 + if(gearIsInCircle(hog,GetX(GLOBAL_TEMP_VALUE), GetY(GLOBAL_TEMP_VALUE), power_radius_outer, false) and gearIsInCircle(hog,GetX(GLOBAL_TEMP_VALUE), GetY(GLOBAL_TEMP_VALUE), power_radius_inner, false)==false) then - if(GetHealth(hog) > dmg) + if(hog == CurrentHedgehog) then - temp_val=temp_val+div(dmg*VampOn,100) - SetHealth(hog, GetHealth(hog)-dmg) - else - temp_val=temp_val+div(GetHealth(hog)*VampOn,100) - SetHealth(hog, 0) + SetState(CurrentHedgehog, gstMoving) end - show_damage_tag(hog,dmg) - AddVisualGear(GetX(hog), GetY(hog)-30, vgtEvilTrace, 0, false) + SetGearPosition(hog, GetX(hog),GetY(hog)-3) + hypo=Norm(math.abs(GetX(hog)-GetX(GLOBAL_TEMP_VALUE)),math.abs(GetY(hog)-GetY(GLOBAL_TEMP_VALUE))) + SetGearVelocity(hog, div((power_radius_outer-hypo)*power_sa*GetIfNegative(GetX(hog)-GetX(GLOBAL_TEMP_VALUE)),power_radius_outer), div((power_radius_outer-hypo)*power_sa*GetIfNegative(GetY(hog)-GetY(GLOBAL_TEMP_VALUE)),power_radius_outer)) end end end --north american special on sniper -function weapon_lipstick(hog) +function NorthAmericaSpecialSniper(hog) if(GetGearType(hog) == gtHedgehog) then - if(gearIsInCircle(temp_val,GetX(hog), GetY(hog), 20, false)) + if(gearIsInCircle(GLOBAL_TEMP_VALUE,GetX(hog), GetY(hog), 20, false)) then SetEffect(hog, hePoisoned, 1) PlaySound(sndBump) @@ -531,114 +702,210 @@ end --european special on molotov (used fire gear) -function weapon_health(hog) +function EuropeSpecialMolotovHit(hog) if(GetGearType(hog) == gtHedgehog) then - if(gearIsInCircle(temp_val,GetX(hog), GetY(hog), 100, false)) + if(gearIsInCircle(GLOBAL_TEMP_VALUE,GetX(hog), GetY(hog), 100, false)) then - SetHealth(hog, GetHealth(hog)+25) + SetHealth(hog, GetHealth(hog)+25+(div(25*GLOBAL_VAMPIRIC_IS_ON,100))) SetEffect(hog, hePoisoned, false) + GLOBAL_SABOTAGE_HOGS[hog]=0 + end + end +end + +--for sundaland +function SundalandFindOtherHogInTeam(hog) + if(GetGearType(hog) == gtHedgehog) + then + if(GetHogTeamName(GLOBAL_SUNDALAND_END_HOG)==GetHogTeamName(hog)) + then + GLOBAL_SUNDALAND_END_HOG=hog end end end --============================================================================ +--for custom made continent, follows the same standards as the globalism one. You can make your continent with ~~. Take the weapons generated from globalism, if you want a GUI :P +--weapons=, ammo = ascii[116(1 ammo) to 125(inf ammo)] types = ascii[36(Grenade), 37(Clusterbomb) to 90(knife)] see https://code.google.com/p/hedgewars/wiki/AmmoTypes +--ex "Own continent~this continent rocks!~tZ}$" will get 1 knife and inf grenades +function onParameters() + + if(ScriptParam~=nil) + then + local continentinfo={} + local numb=0 + local wepcodes=0 + local where=0 + + local x=0 + local i=1 + + --default icon + continentinfo[4]=amLowGravity + + for c in ScriptParam:gmatch"." + do + if(where==0) + then + if(string.byte(c)==126) + then + continentinfo[1]=string.sub(ScriptParam,0,numb) + wepcodes=numb + where=1 + end + elseif(where==1) + then + if(string.byte(c)==126) + then + continentinfo[2]=string.sub(ScriptParam,wepcodes+2,numb) + continentinfo[5]={} + wepcodes=numb + where=2 + end + elseif(where==2) + then + x=string.byte(c)-35 + if(x>90) + then + break + elseif(x>80) + then + if(x-80<10) + then + i=x-80 + else + i=100 + end + else + table.insert(continentinfo[5],{x,i}) + end + end + numb=numb+1 + end + + if(continentinfo[5]~=nil and continentinfo[5][1]~=nil) + then + continentinfo[3]="- "..continentinfo[1]..loc(" was extracted from the scheme|- This continent will be able to use the specials from the other continents!") + + table.insert(GLOBAL_CONTINENT_INFORMATION, continentinfo) + end + end +end + --set each weapons settings function onAmmoStoreInit() SetAmmo(amSkip, 9, 0, 0, 0) - - for v,w in pairs(weapons_dmg) + + for v,w in pairs(GLOBAL_WEAPONS_DAMAGE) do SetAmmo(w[1], w[2], w[3], w[4], w[5]) end - - for v,w in pairs(weapons_supp) + + for v,w in pairs(GLOBAL_WEAPONS_SUPPORT) do SetAmmo(w[1], w[2], w[3], w[4], w[5]) end end +--on game start function onGameStart() - --trackTeams() - - ShowMission(loc("Continental supplies").." 1.1c",loc("Let a Continent provide your weapons!"), - loc(generalinfo), -amLowGravity, 0) + ShowMission(loc("Continental supplies"),loc("Let a continent provide your weapons!"), + GLOBAL_GENERAL_INFORMATION, -amLowGravity, 0) end --what happen when a turn starts function onNewTurn() - + --will refresh the info on each tab weapon - australianSpecial=true - asianSpecial=false - austmine=nil - africanSpecial=0 - samericanSpecial=false - africaspecial2=0 - kergulenSpecial=1 - namericanSpecial=1 - asianflame=0 - shotgun_s=false - sniper_s_in_use=false - europe_s=0 - VampOn=0 - - temp_val=0 - - --for sabotage - disallowattack=0 - if(disable_moving[CurrentHedgehog]==true) - then - disableoffsetai=GetHogLevel(CurrentHedgehog) - end - + GLOBAL_AUSTRALIAN_SPECIAL=0 + GLOBAL_AFRICAN_SPECIAL_SEDUCTION=0 + GLOBAL_SOUTH_AMERICAN_SPECIAL=false + GLOBAL_AFRICAN_SPECIAL_STICKY=0 + GLOBAL_KERGUELEN_SPECIAL=1 + GLOBAL_NORTH_AMERICAN_SPECIAL_SNIPER=1 + GLOBAL_NORTH_AMERICAN_SPECIAL_SHOTGUN=false + GLOBAL_NORTH_AMERICAN_SPECIAL_SNIPER_IS_ON=false + GLOBAL_EUROPE_SPECIAL=0 + GLOBAL_VAMPIRIC_IS_ON=0 + GLOBAL_EXTRA_DAMAGE_IS_ON=100 + + GLOBAL_TEMP_VALUE=0 + + GLOBAL_SUNDALAND_END_HOG=CurrentHedgehog + --when all hogs are "placed" if(GetCurAmmoType()~=amTeleport) then --will run once when the game really starts (after placing hogs and so on - if(teams_ok[GetHogTeamName(CurrentHedgehog)] == nil) + if(GLOBAL_INIT_TEAMS[GetHogTeamName(CurrentHedgehog)] == nil) then - disable_moving[CurrentHedgehog]=false AddCaption("["..loc("Select continent!").."]") - load_continent_selection(CurrentHedgehog) - continent[GetHogTeamName(CurrentHedgehog)]=0 - swapweps=true - teams_ok[GetHogTeamName(CurrentHedgehog)] = 2 + InitWeaponsMenu(CurrentHedgehog) + GLOBAL_TEAM_CONTINENT[GetHogTeamName(CurrentHedgehog)]=0 + GLOBAL_SELECT_CONTINENT_CHECK=true + GLOBAL_INIT_TEAMS[GetHogTeamName(CurrentHedgehog)] = 2 + + if(GLOBAL_SABOTAGE_HOGS[CurrentHedgehog]~=nil and GLOBAL_SABOTAGE_HOGS[CurrentHedgehog]==1) + then + GLOBAL_SABOTAGE_COUNTER=-750 + end else --if its not the initialization turn - swapweps=false - if(continent[GetHogTeamName(CurrentHedgehog)]==0) + GLOBAL_SELECT_CONTINENT_CHECK=false + if(GLOBAL_TEAM_CONTINENT[GetHogTeamName(CurrentHedgehog)]==0) then - continent[GetHogTeamName(CurrentHedgehog)]=GetRandom(table.maxn(weaponsets))+1 - setweapons() + GLOBAL_TEAM_CONTINENT[GetHogTeamName(CurrentHedgehog)]=GetRandom(table.maxn(GLOBAL_CONTINENT_INFORMATION))+1 + SetContinentWeapons() end - show_continent_info(continent[GetHogTeamName(CurrentHedgehog)],-1,true) - + ShowContinentInfo(GLOBAL_TEAM_CONTINENT[GetHogTeamName(CurrentHedgehog)],-1,true) + --give zeelandia-teams new weapons so they can plan for the next turn - runOnGears(get_random_weapon) - - --some specials for some continents (temp_val is from get random weapons) - if(continent[GetHogTeamName(CurrentHedgehog)]==9) + runOnGears(ZealandiaGetWeapons) + + --some specials for some continents (GLOBAL_TEMP_VALUE is from get random weapons) + if(GLOBAL_TEAM_CONTINENT[GetHogTeamName(CurrentHedgehog)]==9) then setTeamValue(GetHogTeamName(CurrentHedgehog), "rand-done-turn", nil) - elseif(continent[GetHogTeamName(CurrentHedgehog)]==7) + elseif(GLOBAL_TEAM_CONTINENT[GetHogTeamName(CurrentHedgehog)]==7) then - if(getTeamValue(GetHogTeamName(CurrentHedgehog), "Antarctica-turntick")==nil) + if(getTeamValue(GetHogTeamName(CurrentHedgehog), "Antarctica2-turntick")==nil) then - setTeamValue(GetHogTeamName(CurrentHedgehog), "Antarctica-turntick", 1) + setTeamValue(GetHogTeamName(CurrentHedgehog), "Antarctica2-turntick", 1) end - - if(getTeamValue(GetHogTeamName(CurrentHedgehog), "Antarctica-turntick")>=2) + + if(getTeamValue(GetHogTeamName(CurrentHedgehog), "Antarctica2-turntick")>=4) then AddAmmo(CurrentHedgehog,amPortalGun) - setTeamValue(GetHogTeamName(CurrentHedgehog), "Antarctica-turntick", 0) + AddAmmo(CurrentHedgehog,amPortalGun) + AddAmmo(CurrentHedgehog,amSineGun) + AddAmmo(CurrentHedgehog,amSineGun) + AddAmmo(CurrentHedgehog,amGirder) + AddAmmo(CurrentHedgehog,amSnowball) + setTeamValue(GetHogTeamName(CurrentHedgehog), "Antarctica2-turntick", 0) end - setTeamValue(GetHogTeamName(CurrentHedgehog), "Antarctica-turntick", getTeamValue(GetHogTeamName(CurrentHedgehog), "Antarctica-turntick")+1) - - elseif(continent[GetHogTeamName(CurrentHedgehog)]==5) + setTeamValue(GetHogTeamName(CurrentHedgehog), "Antarctica2-turntick", getTeamValue(GetHogTeamName(CurrentHedgehog), "Antarctica2-turntick")+1) + + elseif(GLOBAL_TEAM_CONTINENT[GetHogTeamName(CurrentHedgehog)]==5) then - AddAmmo(CurrentHedgehog,amParachute) + if(getTeamValue(GetHogTeamName(CurrentHedgehog), "Asia-turntick")==nil) + then + setTeamValue(GetHogTeamName(CurrentHedgehog), "Asia-turntick", 1) + end + + if(getTeamValue(GetHogTeamName(CurrentHedgehog), "Asia-turntick")>=2) + then + AddAmmo(CurrentHedgehog,amParachute) + setTeamValue(GetHogTeamName(CurrentHedgehog), "Asia-turntick", 0) + end + setTeamValue(GetHogTeamName(CurrentHedgehog), "Asia-turntick", getTeamValue(GetHogTeamName(CurrentHedgehog), "Asia-turntick")+1) + elseif(GLOBAL_TEAM_CONTINENT[GetHogTeamName(CurrentHedgehog)]==1) + then + AddAmmo(CurrentHedgehog,amSwitch,GetAmmoCount(CurrentHedgehog, amSwitch)+1) + + ParseCommand("setweap " .. string.char(amSwitch)) + GLOBAL_TEMP_VALUE=87 end end end @@ -646,486 +913,575 @@ --what happens when you press "tab" (common button) function onSwitch() - - --place mine (australia) - if(GetCurAmmoType() == amBaseballBat and australianSpecial==true) + + if(GLOBAL_SWITCH_HOG_IS_ON==false) then - temp_val=0 - runOnGears(weapon_aust_check) - - if(temp_val==0) + --place mine (australia) + if(GetCurAmmoType() == amBaseballBat) then - austmine=AddGear(GetX(CurrentHedgehog), GetY(CurrentHedgehog)+5, gtMine, 0, 0, 0, 0) - SetHealth(austmine, 100) - SetTimer(austmine, 1000) - australianSpecial=false - swapweps=false - else - PlaySound(sndDenied) - end - end - - --Asian special - if(asianSpecial==false and inpara~=false) - then - asiabomb=AddGear(GetX(CurrentHedgehog), GetY(CurrentHedgehog)+3, gtSnowball, 0, 0, 0, 0) - SetGearMessage(asiabomb, 1) - asianSpecial=true - swapweps=false - end - - --africa - if(GetCurAmmoType() == amSeduction) - then - if(africanSpecial==0) + if(GLOBAL_AUSTRALIAN_SPECIAL==0) + then + GLOBAL_AUSTRALIAN_SPECIAL = 1 + AddCaption(GLOBAL_WEAPON_TEXTS[5]) + elseif(GLOBAL_AUSTRALIAN_SPECIAL==1) + then + GLOBAL_AUSTRALIAN_SPECIAL = 2 + AddCaption(GLOBAL_WEAPON_TEXTS[2]) + else + GLOBAL_AUSTRALIAN_SPECIAL = 0 + AddCaption(loc("NORMAL")) + end + + --Asian special + elseif(GLOBAL_PARACHUTE_IS_ON==1) + then + asiabomb=AddGear(GetX(CurrentHedgehog), GetY(CurrentHedgehog)+3, gtSnowball, 0, 0, 0, 0) + SetGearMessage(asiabomb, 1) + + GLOBAL_PARACHUTE_IS_ON=2 + GLOBAL_SELECT_CONTINENT_CHECK=false + + --africa + elseif(GetCurAmmoType() == amSeduction) then - africanSpecial = 1 - AddCaption(weapontexts[4]) - else - africanSpecial = 0 - AddCaption(loc("NORMAL")) - end - end - --south america - if(GetCurAmmoType() == amGasBomb) - then - if(samericanSpecial==false) + if(GLOBAL_AFRICAN_SPECIAL_SEDUCTION==0) + then + GLOBAL_AFRICAN_SPECIAL_SEDUCTION = 1 + AddCaption(GLOBAL_WEAPON_TEXTS[4]) + else + GLOBAL_AFRICAN_SPECIAL_SEDUCTION = 0 + AddCaption(loc("NORMAL")) + end + + --south america + elseif(GetCurAmmoType() == amGasBomb) then - samericanSpecial = true - AddCaption(weapontexts[3]) - else - samericanSpecial = false - AddCaption(loc("NORMAL")) - end - end - --africa - if(GetCurAmmoType() == amSMine) - then - if(africaspecial2==0) + if(GLOBAL_SOUTH_AMERICAN_SPECIAL==false) + then + GLOBAL_SOUTH_AMERICAN_SPECIAL = true + AddCaption(GLOBAL_WEAPON_TEXTS[3]) + else + GLOBAL_SOUTH_AMERICAN_SPECIAL = false + AddCaption(loc("NORMAL")) + end + + --africa + elseif(GetCurAmmoType() == amSMine) then - africaspecial2 = 1 - AddCaption(weapontexts[11]) - elseif(africaspecial2 == 1) - then - africaspecial2 = 2 - AddCaption(weapontexts[12]) - elseif(africaspecial2 == 2) - then - africaspecial2 = 0 - AddCaption(loc("NORMAL")) - end - end - - --north america (sniper) - if(GetCurAmmoType() == amSniperRifle and sniper_s_in_use==false) - then - if(namericanSpecial==3) + if(GLOBAL_AFRICAN_SPECIAL_STICKY==0) + then + GLOBAL_AFRICAN_SPECIAL_STICKY = 1 + AddCaption(GLOBAL_WEAPON_TEXTS[11]) + elseif(GLOBAL_AFRICAN_SPECIAL_STICKY == 1) + then + GLOBAL_AFRICAN_SPECIAL_STICKY = 2 + AddCaption(GLOBAL_WEAPON_TEXTS[12]) + elseif(GLOBAL_AFRICAN_SPECIAL_STICKY == 2) + then + GLOBAL_AFRICAN_SPECIAL_STICKY = 0 + AddCaption(loc("NORMAL")) + end + + --north america (sniper) + elseif(GetCurAmmoType() == amSniperRifle and GLOBAL_NORTH_AMERICAN_SPECIAL_SNIPER_IS_ON==false) then - namericanSpecial = 1 - AddCaption(loc("NORMAL")) - elseif(namericanSpecial==1) - then - namericanSpecial = 2 - AddCaption("#"..weapontexts[1]) - elseif(namericanSpecial==2) + if(GLOBAL_NORTH_AMERICAN_SPECIAL_SNIPER==2) + then + GLOBAL_NORTH_AMERICAN_SPECIAL_SNIPER = 1 + AddCaption(loc("NORMAL")) + elseif(GLOBAL_NORTH_AMERICAN_SPECIAL_SNIPER==1) + then + GLOBAL_NORTH_AMERICAN_SPECIAL_SNIPER = 2 + AddCaption(GLOBAL_WEAPON_TEXTS[1]) + end + + --north america (shotgun) + elseif(GetCurAmmoType() == amShotgun and GLOBAL_NORTH_AMERICAN_SPECIAL_SHOTGUN~=nil) then - namericanSpecial = 3 - AddCaption("##"..weapontexts[2]) - end - end - - --north america (shotgun) - if(GetCurAmmoType() == amShotgun and shotgun_s~=nil) - then - if(shotgun_s==false) + if(GLOBAL_NORTH_AMERICAN_SPECIAL_SHOTGUN==false) + then + GLOBAL_NORTH_AMERICAN_SPECIAL_SHOTGUN = true + AddCaption(GLOBAL_WEAPON_TEXTS[13]) + else + GLOBAL_NORTH_AMERICAN_SPECIAL_SHOTGUN = false + AddCaption(loc("NORMAL")) + end + + --europe + elseif(GetCurAmmoType() == amMolotov) then - shotgun_s = true - AddCaption(weapontexts[13]) - else - shotgun_s = false - AddCaption(loc("NORMAL")) - end - end - - --europe - if(GetCurAmmoType() == amMolotov) - then - if(europe_s==0) + if(GLOBAL_EUROPE_SPECIAL==0) + then + GLOBAL_EUROPE_SPECIAL = 1 + AddCaption(GLOBAL_WEAPON_TEXTS[14]) + else + GLOBAL_EUROPE_SPECIAL = 0 + AddCaption(loc("NORMAL")) + end + + --kerguelen + elseif(GetCurAmmoType() == amHammer) then - europe_s = 1 - AddCaption(weapontexts[14]) - else - europe_s = 0 - AddCaption(loc("NORMAL")) + if(GLOBAL_KERGUELEN_SPECIAL==6) + then + GLOBAL_KERGUELEN_SPECIAL = 1 + AddCaption("Normal") + elseif(GLOBAL_KERGUELEN_SPECIAL==1) + then + GLOBAL_KERGUELEN_SPECIAL = 2 + AddCaption("#"..GLOBAL_WEAPON_TEXTS[7]) + elseif(GLOBAL_KERGUELEN_SPECIAL==2 and TotalRounds>=1) + then + GLOBAL_KERGUELEN_SPECIAL = 3 + AddCaption("##"..GLOBAL_WEAPON_TEXTS[8]) + elseif(GLOBAL_KERGUELEN_SPECIAL==3 or (GLOBAL_KERGUELEN_SPECIAL==2 and TotalRounds<1)) + then + GLOBAL_KERGUELEN_SPECIAL = 5 + AddCaption("###"..GLOBAL_WEAPON_TEXTS[10]) + elseif(GLOBAL_KERGUELEN_SPECIAL==5) + then + GLOBAL_KERGUELEN_SPECIAL = 6 + AddCaption("####"..GLOBAL_WEAPON_TEXTS[15]) + end + --for selecting weaponset, this is mostly for old players. + elseif(GetHogLevel(CurrentHedgehog)==0 and GLOBAL_SELECT_CONTINENT_CHECK==true and (GetCurAmmoType() == amSkip or GetCurAmmoType() == amNothing)) + then + GLOBAL_TEAM_CONTINENT[GetHogTeamName(CurrentHedgehog)]=GLOBAL_TEAM_CONTINENT[GetHogTeamName(CurrentHedgehog)]+1 + + if(GLOBAL_TEAM_CONTINENT[GetHogTeamName(CurrentHedgehog)]> table.maxn(GLOBAL_CONTINENT_INFORMATION)) + then + GLOBAL_TEAM_CONTINENT[GetHogTeamName(CurrentHedgehog)]=1 + end + SetContinentWeapons() end - end - - --swap forward in the weaponmenu (1.0 style) - if(swapweps==true and (GetCurAmmoType() == amSkip or GetCurAmmoType() == amNothing)) - then - continent[GetHogTeamName(CurrentHedgehog)]=continent[GetHogTeamName(CurrentHedgehog)]+1 - - if(continent[GetHogTeamName(CurrentHedgehog)]> table.maxn(weaponsets)) - then - continent[GetHogTeamName(CurrentHedgehog)]=1 - end - setweapons() - end - - --kerguelen - if(GetCurAmmoType() == amHammer) + --if switching out from sabotage. + elseif(GLOBAL_SABOTAGE_HOGS[CurrentHedgehog]~=nil and GLOBAL_SABOTAGE_HOGS[CurrentHedgehog]==2) then - if(kergulenSpecial==6) - then - kergulenSpecial = 1 - AddCaption("Normal") - elseif(kergulenSpecial==1) - then - kergulenSpecial = 2 - AddCaption("#"..weapontexts[7]) - elseif(kergulenSpecial==2 and TotalRounds>=1) - then - kergulenSpecial = 3 - AddCaption("##"..weapontexts[8]) - elseif(kergulenSpecial==3 or (kergulenSpecial==2 and TotalRounds<1)) - then - kergulenSpecial = 4 - AddCaption("###"..weapontexts[9]) - elseif(kergulenSpecial==4) - then - kergulenSpecial = 5 - AddCaption("####"..weapontexts[10]) - elseif(kergulenSpecial==5) - then - kergulenSpecial = 6 - AddCaption("#####"..weapontexts[15]) - end + GLOBAL_SABOTAGE_HOGS[CurrentHedgehog]=1 end end -function onPrecise() - --swap backwards in the weaponmenu (1.0 style) - if(swapweps==true and (GetCurAmmoType() == amSkip or GetCurAmmoType() == amNothing)) +function onUp() + --swap forward in the weaponmenu (1.0 style) + if(GetHogLevel(CurrentHedgehog)==0 and GLOBAL_SELECT_CONTINENT_CHECK==true and (GetCurAmmoType() == amSkip or GetCurAmmoType() == amNothing)) then - continent[GetHogTeamName(CurrentHedgehog)]=continent[GetHogTeamName(CurrentHedgehog)]-1 - - if(continent[GetHogTeamName(CurrentHedgehog)]<=0) + GLOBAL_TEAM_CONTINENT[GetHogTeamName(CurrentHedgehog)]=GLOBAL_TEAM_CONTINENT[GetHogTeamName(CurrentHedgehog)]+1 + + if(GLOBAL_TEAM_CONTINENT[GetHogTeamName(CurrentHedgehog)]> table.maxn(GLOBAL_CONTINENT_INFORMATION)) then - continent[GetHogTeamName(CurrentHedgehog)]=9 + GLOBAL_TEAM_CONTINENT[GetHogTeamName(CurrentHedgehog)]=1 end - setweapons() + SetContinentWeapons() + end +end + +function onDown() + --swap backwards in the weaponmenu (1.0 style) + if(GetHogLevel(CurrentHedgehog)==0 and GLOBAL_SELECT_CONTINENT_CHECK==true and (GetCurAmmoType() == amSkip or GetCurAmmoType() == amNothing)) + then + GLOBAL_TEAM_CONTINENT[GetHogTeamName(CurrentHedgehog)]=GLOBAL_TEAM_CONTINENT[GetHogTeamName(CurrentHedgehog)]-1 + + if(GLOBAL_TEAM_CONTINENT[GetHogTeamName(CurrentHedgehog)]<=0) + then + GLOBAL_TEAM_CONTINENT[GetHogTeamName(CurrentHedgehog)]=table.maxn(GLOBAL_CONTINENT_INFORMATION) + end + SetContinentWeapons() end end function onGameTick20() --if you picked a weaponset from the weaponmenu (icon) - if(continent[GetHogTeamName(CurrentHedgehog)]==0) + if(GLOBAL_TEAM_CONTINENT[GetHogTeamName(CurrentHedgehog)]==0) then if(GetCurAmmoType()==amSwitch) then - continent[GetHogTeamName(CurrentHedgehog)]=GetRandom(table.maxn(weaponsets))+1 - setweapons() + GLOBAL_TEAM_CONTINENT[GetHogTeamName(CurrentHedgehog)]=GetRandom(table.maxn(GLOBAL_CONTINENT_INFORMATION))+1 + SetContinentWeapons() PlaySound(sndMineTick) else - for v,w in pairs(weaponsets) + for v,w in pairs(GLOBAL_CONTINENT_INFORMATION) do - if(GetCurAmmoType()==weaponsets[v][4]) + if(GetCurAmmoType()==GLOBAL_CONTINENT_INFORMATION[v][4]) then - continent[GetHogTeamName(CurrentHedgehog)]=v - setweapons() - PlaySound(weaponsetssounds[v][1]) - PlaySound(weaponsetssounds[v][2],CurrentHedgehog) + GLOBAL_TEAM_CONTINENT[GetHogTeamName(CurrentHedgehog)]=v + SetContinentWeapons() + PlaySound(GLOBAL_CONTINENT_SOUNDS[v][1]) + PlaySound(GLOBAL_CONTINENT_SOUNDS[v][2],CurrentHedgehog) end end end end - + --show the kerguelen ring - if(kergulenSpecial > 1 and GetCurAmmoType() == amHammer) + if(GLOBAL_KERGUELEN_SPECIAL > 1 and GetCurAmmoType() == amHammer) then - if(visualcircle==nil) + if(GLOBAL_VISUAL_CIRCLE==nil) then - visualcircle=AddVisualGear(GetX(CurrentHedgehog), GetY(CurrentHedgehog), vgtCircle, 0, false) + GLOBAL_VISUAL_CIRCLE=AddVisualGear(GetX(CurrentHedgehog), GetY(CurrentHedgehog), vgtCircle, 0, true) end - - if(kergulenSpecial == 2) --walrus scream + + if(GLOBAL_KERGUELEN_SPECIAL == 2) --walrus scream then - SetVisualGearValues(visualcircle, GetX(CurrentHedgehog), GetY(CurrentHedgehog),20, 200, 0, 0, 100, 120, 4, 0xff0000ee) - elseif(kergulenSpecial == 3) --swap hog + SetVisualGearValues(GLOBAL_VISUAL_CIRCLE, GetX(CurrentHedgehog), GetY(CurrentHedgehog),20, 200, 0, 0, 100, 120, 4, 0xff0000ee) + elseif(GLOBAL_KERGUELEN_SPECIAL == 3) --swap hog then - SetVisualGearValues(visualcircle, GetX(CurrentHedgehog), GetY(CurrentHedgehog),20, 200, 0, 0, 100, 450, 3, 0xffff00ee) - elseif(kergulenSpecial == 4) --flare + SetVisualGearValues(GLOBAL_VISUAL_CIRCLE, GetX(CurrentHedgehog), GetY(CurrentHedgehog),20, 200, 0, 0, 100, 420, 3, 0xffff00ee) + elseif(GLOBAL_KERGUELEN_SPECIAL == 5) --cries then - SetVisualGearValues(visualcircle, GetX(CurrentHedgehog), GetY(CurrentHedgehog),20, 200, 0, 0, 100, 45, 6, 0x00ff00ee) - elseif(kergulenSpecial == 5) --cries + SetVisualGearValues(GLOBAL_VISUAL_CIRCLE, GetX(CurrentHedgehog), GetY(CurrentHedgehog),20, 200, 0, 0, 100, 550, 1, 0x0000ffee) + elseif(GLOBAL_KERGUELEN_SPECIAL == 6) --sabotage then - SetVisualGearValues(visualcircle, GetX(CurrentHedgehog), GetY(CurrentHedgehog),20, 200, 0, 0, 100, 500, 1, 0x0000ffee) - elseif(kergulenSpecial == 6) --sabotage - then - SetVisualGearValues(visualcircle, GetX(CurrentHedgehog), GetY(CurrentHedgehog),20, 200, 0, 0, 100, 100, 10, 0xeeeeeeee) + SetVisualGearValues(GLOBAL_VISUAL_CIRCLE, GetX(CurrentHedgehog), GetY(CurrentHedgehog),20, 200, 0, 0, 100, 80, 10, 0x00ff00ee) end - - elseif(visualcircle~=nil) + + elseif(GLOBAL_VISUAL_CIRCLE~=nil) + then + DeleteVisualGear(GLOBAL_VISUAL_CIRCLE) + GLOBAL_VISUAL_CIRCLE=nil + end + + --sabotage + if(GLOBAL_SABOTAGE_HOGS[CurrentHedgehog]~=nil and GLOBAL_SABOTAGE_HOGS[CurrentHedgehog]>=1) then - DeleteVisualGear(visualcircle) - visualcircle=nil - end - - --sabotage - if(disable_moving[CurrentHedgehog]==true) - then - - if(TurnTimeLeft<=150) + --for sabotage + if(GLOBAL_SABOTAGE_HOGS[CurrentHedgehog]==1) then - disable_moving[CurrentHedgehog]=false - SetHogLevel(CurrentHedgehog,disableoffsetai) - onsabotageai=false - elseif(disallowattack>=15 and disallowattack >= 20) + local RND=GetRandom(2) + if(RND==0) + then + AddCaption(loc("You are sabotaged, RUN!")) + else + AddCaption(loc("WARNING: Sabotage detected!")) + end + PlaySound(sndHellish) + GLOBAL_SABOTAGE_COUNTER=-50 + --update the constant at the top also to something in between + GLOBAL_SABOTAGE_FREQUENCY=(25*(RND))+70 + GLOBAL_SABOTAGE_GRAVITY_SWITCH=true + + GLOBAL_SABOTAGE_HOGS[CurrentHedgehog]=2 + end + + if(GLOBAL_SABOTAGE_COUNTER >0) + then + if(GLOBAL_SABOTAGE_GRAVITY_SWITCH) + then + SetGravityFromScale(div(100*GLOBAL_SABOTAGE_COUNTER,GLOBAL_SABOTAGE_FREQUENCY)) + else + SetGravityFromScale(100-div(100*GLOBAL_SABOTAGE_COUNTER,GLOBAL_SABOTAGE_FREQUENCY)) + end + + if(GLOBAL_SABOTAGE_COUNTER % 20 == 0) + then + AddVisualGear(GetX(CurrentHedgehog), GetY(CurrentHedgehog), vgtSmokeWhite, 0, false) + end + end + + if(TurnTimeLeft<(GetAwayTime*10) or band(GetState(CurrentHedgehog),gstAttacked)==1) + then + GLOBAL_SABOTAGE_HOGS[CurrentHedgehog]=0 + SetGravity(100) + elseif(GLOBAL_SABOTAGE_COUNTER >= GLOBAL_SABOTAGE_FREQUENCY) then - disallowattack=0 - onsabotageai=true - SetHogLevel(CurrentHedgehog,1) - AddVisualGear(GetX(CurrentHedgehog), GetY(CurrentHedgehog), vgtSmokeWhite, 0, false) - elseif(onsabotageai==true) + if(GLOBAL_SABOTAGE_GRAVITY_SWITCH==true) + then + GLOBAL_SABOTAGE_GRAVITY_SWITCH=false + else + --AddGear(GetX(CurrentHedgehog), GetY(CurrentHedgehog)-10, gtCluster, 0, 0, -160000, 30) + GLOBAL_SABOTAGE_GRAVITY_SWITCH=true + end + + if(GetHealth(CurrentHedgehog)<=2) + then + SetHealth(CurrentHedgehog, 0) + GLOBAL_SABOTAGE_HOGS[CurrentHedgehog]=0 + SetGravity(100) + else + SetHealth(CurrentHedgehog, GetHealth(CurrentHedgehog)-2) + end + ShowDamageTag(CurrentHedgehog,2) + + GLOBAL_SABOTAGE_COUNTER=0 + else + GLOBAL_SABOTAGE_COUNTER=GLOBAL_SABOTAGE_COUNTER+1 + end + end + + if(GetCurAmmoType() == amSwitch and GLOBAL_TEMP_VALUE==87) + then + SetGearMessage(CurrentHedgehog,gmAttack) + GLOBAL_TEMP_VALUE=0 + end + + if(GLOBAL_SHOW_SMALL_INFO>0) + then + if(GLOBAL_SHOW_SMALL_INFO==1) then - SetHogLevel(CurrentHedgehog,disableoffsetai) - onsabotageai=false - else - disallowattack=disallowattack+1 + ShowContinentInfo(GLOBAL_TEAM_CONTINENT[GetHogTeamName(CurrentHedgehog)],-1,true) end - + + GLOBAL_SHOW_SMALL_INFO=GLOBAL_SHOW_SMALL_INFO-1 end - +end + +--some ppl complained :P +function onSlot(slot) + if(GLOBAL_TEAM_CONTINENT[GetHogTeamName(CurrentHedgehog)]==0) + then + ParseCommand("setweap " .. string.char(amSkip)) + end end --if you used hogswitch or any similar weapon, dont enable any weaponchange function onAttack() - swapweps=false - + GLOBAL_SELECT_CONTINENT_CHECK=false + --african special - if(africanSpecial == 1 and GetCurAmmoType() == amSeduction) + if(GLOBAL_AFRICAN_SPECIAL_SEDUCTION == 1 and GetCurAmmoType() == amSeduction and band(GetState(CurrentHedgehog),gstAttacked)==0) then - SetState(CurrentHedgehog, gstAttacked) - - temp_val=0 - runOnGears(weapon_duststorm) - SetHealth(CurrentHedgehog, GetHealth(CurrentHedgehog)+temp_val) + EndTurn() + + GLOBAL_TEMP_VALUE=0 + runOnGears(AfricaSpecialSeduction) + SetHealth(CurrentHedgehog, GetHealth(CurrentHedgehog)+GLOBAL_TEMP_VALUE) --visual stuff - visual_gear_explosion(250,GetX(CurrentHedgehog), GetY(CurrentHedgehog),vgtSmoke,vgtSmokeWhite) + VisualExplosion(250,GetX(CurrentHedgehog), GetY(CurrentHedgehog),vgtSmoke,vgtSmokeWhite) PlaySound(sndParachute) + RemoveWeapon(CurrentHedgehog,amSeduction) + --Kerguelen specials - elseif(GetCurAmmoType() == amHammer and kergulenSpecial > 1) + elseif(GetCurAmmoType() == amHammer and GLOBAL_KERGUELEN_SPECIAL > 1 and band(GetState(CurrentHedgehog),gstAttacked)==0) then - SetState(CurrentHedgehog, gstAttacked) --scream - if(kergulenSpecial == 2) + if(GLOBAL_KERGUELEN_SPECIAL == 2) then - temp_val=0 - runOnGears(weapon_scream_walrus) - SetHealth(CurrentHedgehog, GetHealth(CurrentHedgehog)+temp_val) + GLOBAL_TEMP_VALUE=0 + runOnGears(KerguelenSpecialRed) + SetHealth(CurrentHedgehog, GetHealth(CurrentHedgehog)+GLOBAL_TEMP_VALUE) PlaySound(sndHellish) - + --swap - elseif(kergulenSpecial == 3 and TotalRounds>=1) + elseif(GLOBAL_KERGUELEN_SPECIAL == 3 and TotalRounds>=1) then - runOnGears(weapon_swap_kerg) - PlaySound(sndPiano3) - - --flare - elseif(kergulenSpecial == 4) + GLOBAL_TEMP_VALUE=0 + runOnGears(KerguelenSpecialYellowCountHogs) + if(GLOBAL_TEMP_VALUE>0) + then + GLOBAL_TEMP_VALUE=GetRandom(GLOBAL_TEMP_VALUE) + runOnGears(KerguelenSpecialYellowSwap) + PlaySound(sndPiano3) + else + PlaySound(sndPiano6) + end + + --cries + elseif(GLOBAL_KERGUELEN_SPECIAL == 5) then - runOnGears(weapon_flare) - PlaySound(sndThrowRelease) - AddVisualGear(GetX(CurrentHedgehog), GetY(CurrentHedgehog), vgtSmokeWhite, 0, false) - AddGear(GetX(CurrentHedgehog), GetY(CurrentHedgehog)-20, gtCluster, 0, 0, -1000000, 34) - - --cries - elseif(kergulenSpecial == 5) - then - runOnGears(weapon_cries_a) - if(kergulenSpecial~=-1) + runOnGears(KerguelenSpecialBlueCheck) + if(GLOBAL_KERGUELEN_SPECIAL~=-1) then AddGear(0, 0, gtWaterUp, 0, 0,0,0) PlaySound(sndWarp) PlaySound(sndMolotov) - - temp_val=0 - runOnGears(weapon_cries_b) - SetHealth(CurrentHedgehog, GetHealth(CurrentHedgehog)+temp_val) + + GLOBAL_TEMP_VALUE=0 + runOnGears(KerguelenSpecialBlueActivate) + SetHealth(CurrentHedgehog, GetHealth(CurrentHedgehog)+GLOBAL_TEMP_VALUE) else HogSay(CurrentHedgehog, loc("Hogs in sight!"), SAY_SAY) end - + --sabotage - elseif(kergulenSpecial == 6) + elseif(GLOBAL_KERGUELEN_SPECIAL == 6) then - runOnGears(weapon_sabotage) + GLOBAL_TEMP_VALUE=0 + runOnGears(KerguelenSpecialGreen) + if(GLOBAL_TEMP_VALUE==0) + then + PlaySound(sndThrowRelease) + AddGear(GetX(CurrentHedgehog), GetY(CurrentHedgehog)-20, gtCluster, 0, 0, -1000000, 32) + end end - DeleteVisualGear(visualcircle) - visualcircle=nil - + + EndTurn() + + DeleteVisualGear(GLOBAL_VISUAL_CIRCLE) + GLOBAL_VISUAL_CIRCLE=nil + GLOBAL_KERGUELEN_SPECIAL=0 + + RemoveWeapon(CurrentHedgehog,amHammer) + elseif(GetCurAmmoType() == amVampiric) then - VampOn=75 - end - --Australian special - if(GetGearType(austmine) == gtMine and austmine ~= nil) + GLOBAL_VAMPIRIC_IS_ON=75 + elseif(GetCurAmmoType() == amExtraDamage) then - temp_val=0 - runOnGears(weapon_aust_check) - - if(gearIsInCircle(austmine,GetX(CurrentHedgehog), GetY(CurrentHedgehog), 30, false)==false or temp_val==1) - then - AddVisualGear(GetX(austmine), GetY(austmine), vgtDust, 0, false) - DeleteGear(austmine) - PlaySound(sndDenied) - end - - austmine=nil + GLOBAL_EXTRA_DAMAGE_IS_ON=150 end - - --stop sabotage (avoiding a bug) - if(disable_moving[CurrentHedgehog]==true) - then - disable_moving[CurrentHedgehog]=false - onsabotageai=false - SetHogLevel(CurrentHedgehog,disableoffsetai) - end - - australianSpecial=false end function onGearAdd(gearUid) - swapweps=false - + GLOBAL_SELECT_CONTINENT_CHECK=false + --track the gears im using - if(GetGearType(gearUid) == gtHedgehog or GetGearType(gearUid) == gtMine or GetGearType(gearUid) == gtExplosives) + if(GetGearType(gearUid) == gtHedgehog or GetGearType(gearUid) == gtMine or GetGearType(gearUid) == gtExplosives) then trackGear(gearUid) end - + --remove gasclouds on gasbombspecial - if(GetGearType(gearUid)==gtPoisonCloud and samericanSpecial == true) + if(GetGearType(gearUid)==gtPoisonCloud and GLOBAL_SOUTH_AMERICAN_SPECIAL == true) then DeleteGear(gearUid) - + --african special elseif(GetGearType(gearUid)==gtSMine) then vx,vy=GetGearVelocity(gearUid) - if(africaspecial2 == 1) + if(GLOBAL_AFRICAN_SPECIAL_STICKY == 1) then SetState(CurrentHedgehog, gstHHDriven+gstMoving) SetGearPosition(CurrentHedgehog, GetX(CurrentHedgehog),GetY(CurrentHedgehog)-3) SetGearVelocity(CurrentHedgehog, vx, vy) DeleteGear(gearUid) - - elseif(africaspecial2 == 2) + + elseif(GLOBAL_AFRICAN_SPECIAL_STICKY == 2) then - fire_gear(CurrentHedgehog,gtNapalmBomb, vx, vy, 0) + FireGear(CurrentHedgehog,gtNapalmBomb, vx, vy, 0) DeleteGear(gearUid) end - + --north american special elseif(GetGearType(gearUid)==gtSniperRifleShot) then - sniper_s_in_use=true - if(namericanSpecial~=1) + GLOBAL_NORTH_AMERICAN_SPECIAL_SNIPER_IS_ON=true + if(GLOBAL_NORTH_AMERICAN_SPECIAL_SNIPER~=1) then SetHealth(gearUid, 1) end - + --north american special elseif(GetGearType(gearUid)==gtShotgunShot) then - if(shotgun_s==true) + if(GLOBAL_NORTH_AMERICAN_SPECIAL_SHOTGUN==true) then AddVisualGear(GetX(gearUid), GetY(gearUid), vgtFeather, 0, false) AddVisualGear(GetX(gearUid), GetY(gearUid), vgtFeather, 0, false) AddVisualGear(GetX(gearUid), GetY(gearUid), vgtFeather, 0, false) PlaySound(sndBirdyLay) else - shotgun_s=nil + GLOBAL_NORTH_AMERICAN_SPECIAL_SHOTGUN=nil end - - elseif(GetGearType(gearUid)==gtMolotov and europe_s==1) + --european special + elseif(GetGearType(gearUid)==gtMolotov and GLOBAL_EUROPE_SPECIAL==1) then vx,vy=GetGearVelocity(gearUid) - e_health=fire_gear(CurrentHedgehog,gtCluster, vx, vy, 1) + e_health=FireGear(CurrentHedgehog,gtCluster, vx, vy, 1) SetGearMessage(e_health, 2) DeleteGear(gearUid) - + --australian specials + elseif(GetGearType(gearUid)==gtShover and GLOBAL_AUSTRALIAN_SPECIAL~=0) + then + GLOBAL_TEMP_VALUE=0 + runOnGears(AustraliaSpecialCheckHogs) + + if(GLOBAL_TEMP_VALUE==0) + then + vx,vy=GetGearVelocity(gearUid) + + if(GLOBAL_AUSTRALIAN_SPECIAL==1) + then + local austmine=FireGear(CurrentHedgehog,gtMine, vx, vy, 0) + SetHealth(austmine, 100) + SetTimer(austmine, 1000) + else + local austmine=FireGear(CurrentHedgehog,gtEgg, vx, vy, 10) + --SetHealth(austmine, 2000) + SetTimer(austmine, 6000) + SetGearMessage(austmine, 3) + end + else + PlaySound(sndDenied) + end elseif(GetGearType(gearUid)==gtParachute) then - inpara=gearUid + GLOBAL_PARACHUTE_IS_ON=1 + elseif(GetGearType(gearUid)==gtSwitcher) + then + GLOBAL_SWITCH_HOG_IS_ON=true end end function onGearDelete(gearUid) - if(GetGearType(gearUid) == gtHedgehog or GetGearType(gearUid) == gtMine or GetGearType(gearUid) == gtExplosives) + if(GetGearType(gearUid) == gtHedgehog or GetGearType(gearUid) == gtMine or GetGearType(gearUid) == gtExplosives) then trackDeletion(gearUid) + + --sundaland special + if(GetGearType(gearUid) == gtHedgehog and GLOBAL_TEAM_CONTINENT[GetHogTeamName(GLOBAL_SUNDALAND_END_HOG)]==10) + then + if(GLOBAL_SUNDALAND_END_HOG==CurrentHedgehog) + then + runOnGears(SundalandFindOtherHogInTeam) + end + + SundalandGetWeapons(GLOBAL_SUNDALAND_END_HOG) + end end - + --north american lipstick if(GetGearType(gearUid)==gtSniperRifleShot ) then - sniper_s_in_use=false - if(namericanSpecial==2) - then - temp_val=gearUid - runOnGears(weapon_lipstick) - - elseif(namericanSpecial==3) + GLOBAL_NORTH_AMERICAN_SPECIAL_SNIPER_IS_ON=false + if(GLOBAL_NORTH_AMERICAN_SPECIAL_SNIPER==2) then - AddVisualGear(GetX(gearUid), GetY(gearUid), vgtExplosion, 0, false) - - pinata=AddGear(GetX(gearUid), GetY(gearUid), gtCluster, 0, 0, 0, 5) - SetGearMessage(pinata,1) + GLOBAL_TEMP_VALUE=gearUid + runOnGears(NorthAmericaSpecialSniper) end - - --north american pinata - elseif(GetGearType(gearUid)==gtCluster and GetGearMessage(gearUid)==1 and namericanSpecial==3) + --north american eagle eye + elseif(GetGearType(gearUid)==gtShotgunShot and GLOBAL_NORTH_AMERICAN_SPECIAL_SHOTGUN==true) then - AddGear(GetX(gearUid), GetY(gearUid), gtCluster, 0, 0, 0, 20) - - --north american eagle eye - elseif(GetGearType(gearUid)==gtShotgunShot and shotgun_s==true) - then - SetState(CurrentHedgehog, gstMoving) + EndTurn() SetGearPosition(CurrentHedgehog, GetX(gearUid), GetY(gearUid)+7) PlaySound(sndWarp) - --south american special - elseif(GetGearType(gearUid)==gtGasBomb and samericanSpecial == true) + elseif(GetGearType(gearUid)==gtGasBomb and GLOBAL_SOUTH_AMERICAN_SPECIAL == true) then - temp_val=gearUid - runOnGears(weapon_anno_south) + GLOBAL_TEMP_VALUE=gearUid + runOnGears(SouthAmericaSpecialCheeseExplosion) AddVisualGear(GetX(gearUid), GetY(gearUid), vgtExplosion, 0, false) - + --asian special elseif(GetGearType(gearUid)==gtSnowball and GetGearMessage(gearUid)==1) then AddGear(GetX(gearUid), GetY(gearUid), gtCluster, 0, 0, 0, 22) - + --europe special elseif(GetGearType(gearUid)==gtCluster and GetGearMessage(gearUid)==2) then - temp_val=gearUid - runOnGears(weapon_health) - visual_gear_explosion(100,GetX(gearUid), GetY(gearUid),vgtSmokeWhite,vgtSmokeWhite) + GLOBAL_TEMP_VALUE=gearUid + runOnGears(EuropeSpecialMolotovHit) + VisualExplosion(100,GetX(gearUid), GetY(gearUid),vgtSmokeWhite,vgtSmokeWhite) AddVisualGear(GetX(gearUid), GetY(gearUid), vgtExplosion, 0, false) PlaySound(sndGraveImpact) - + --australian special + elseif(GetGearType(gearUid)==gtEgg and GetGearMessage(gearUid)==3) + then + GLOBAL_TEMP_VALUE=gearUid + runOnGears(AustraliaSpecialEggHit) + GLOBAL_TEMP_VALUE=0 --asia (using para) elseif(GetGearType(gearUid)==gtParachute) then - inpara=false + GLOBAL_PARACHUTE_IS_ON=false + elseif(GetGearType(gearUid)==gtSwitcher) + then + GLOBAL_SWITCH_HOG_IS_ON=false end end + --[[ -sources (populations & area): -Wikipedia -Own calculations -if you think they are wrong, then please tell me :) -]] \ No newline at end of file + sources (populations & area): + Own calculations from wikipedia. + Some are approximations. +]] diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Scripts/Multiplayer/DiagonalMaze.cfg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Scripts/Multiplayer/DiagonalMaze.cfg Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,2 @@ +* +* diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Scripts/Multiplayer/DiagonalMaze.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Scripts/Multiplayer/DiagonalMaze.lua Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,25 @@ + +function onPreviewInit() +onGameInit() +end + +function onGameInit() + MapGen = mgDrawn + TemplateFilter = 0 + local step = 80 + 10 * MapFeatureSize + local width = 1 + div(math.max(0, MapFeatureSize-12), 6) + -- center maze + local xoff = div((4000 % step), 2) + for y = 48,2048,step do + for x = 48+xoff,4048-step,step do + if GetRandom(2) == 0 then + AddPoint(x,y,width) + AddPoint(x+step,y+step) + else + AddPoint(x,y+step,width) + AddPoint(x+step,y) + end + end + end + FlushPoints() +end diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Scripts/Multiplayer/Frenzy.lua --- a/share/hedgewars/Data/Scripts/Multiplayer/Frenzy.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Scripts/Multiplayer/Frenzy.lua Tue Nov 10 20:43:13 2015 +0100 @@ -1,142 +1,142 @@ -------------------------------------------- --- FRENZY --- a hedgewars mode inspired by Hysteria -------------------------------------------- - -HedgewarsScriptLoad("/Scripts/Locale.lua") -HedgewarsScriptLoad("/Scripts/Tracker.lua") - -local cTimer = 0 -local cn = 0 - -function initialSetup(gear) - SetHealth(gear, 75) -- official is 80, but that assumes bazookas/grenades that do 50 damage -end - -function showStartingInfo() - - ruleSet = "" .. - loc("RULES") .. ": " .. "|" .. - loc("Each turn is only ONE SECOND!") .. "|" .. - loc("Use your ready time to think.") .. "|" .. - loc("Slot keys save time! (F1-F10 by default)") .. "|" .. - " |" .. - loc("SLOTS") .. ": " .. "|" .. - loc("Slot") .. " 1 - " .. loc("Bazooka") .. "|" .. - loc("Slot") .. " 2 - " .. loc("Grenade") .. "|" .. - loc("Slot") .. " 3 - " .. loc("Shotgun") .. "|" .. - loc("Slot") .. " 4 - " .. loc("Shoryuken") .. "|" .. - loc("Slot") .. " 5 - " .. loc("Mine") .. "|" .. - loc("Slot") .. " 6 - " .. loc("Teleport") .. "|" .. - loc("Slot") .. " 7 - " .. loc("Blowtorch") .. "|" .. - loc("Slot") .. " 8 - " .. loc("Flying Saucer") .. "|" .. - loc("Slot") .. " 9 - " .. loc("Molotov") .. "|" .. - loc("Slot") .. " 10 - " .. loc("Low Gravity") - - ShowMission(loc("FRENZY"), - loc("a frenetic Hedgewars mini-game"), - ruleSet, 0, 4000) - -end - -function onGameInit() - - if TurnTime > 10001 then - Ready = 8000 - else - Ready = TurnTime - end - - TurnTime = 1000 - - --These are the official settings, but I think I prefer allowing customization in this regard - --MinesNum = 8 - --MinesTime = 3000 - --MinesDudPercent = 30 - --Explosives = 0 - - --Supposedly official settings - HealthCaseProb = 0 - CrateFreq = 0 - - --Approximation of Official Settings - --SuddenDeathTurns = 10 - --WaterRise = 47 - --HealthDecrease = 0 - -end - -function onGameStart() - showStartingInfo() - runOnHogs(initialSetup) -end - -function onSlot(sln) - cTimer = 8 - cn = sln -end - -function onGameTick() - if cTimer ~= 0 then - cTimer = cTimer -1 - if cTimer == 1 then - ChangeWep(cn) - cn = 0 - cTimer = 0 - end - end -end - -function ChangeWep(s) - - if s == 0 then - ParseCommand("setweap " .. string.char(amBazooka)) - elseif s == 1 then - ParseCommand("setweap " .. string.char(amGrenade)) - elseif s == 2 then - ParseCommand("setweap " .. string.char(amShotgun)) - elseif s == 3 then - ParseCommand("setweap " .. string.char(amFirePunch)) - elseif s == 4 then - ParseCommand("setweap " .. string.char(amMine)) - elseif s == 5 then - ParseCommand("setweap " .. string.char(amTeleport)) - elseif s == 6 then - ParseCommand("setweap " .. string.char(amBlowTorch)) - elseif s == 7 then - ParseCommand("setweap " .. string.char(amJetpack)) - elseif s == 8 then - ParseCommand("setweap " .. string.char(amMolotov)) - elseif s == 9 then - ParseCommand("setweap " .. string.char(amLowGravity)) - end - -end - -function onGearAdd(gear) - if GetGearType(gear) == gtHedgehog then - trackGear(gear) - end -end - -function onGearDelete(gear) - if GetGearType(gear) == gtHedgehog then - trackDeletion(gear) - end -end - -function onAmmoStoreInit() - SetAmmo(amBazooka, 9, 0, 0, 0) - SetAmmo(amGrenade, 9, 0, 0, 0) - SetAmmo(amMolotov, 9, 0, 0, 0) - SetAmmo(amShotgun, 9, 0, 0, 0) - --SetAmmo(amFlamethrower, 9, 0, 0, 0) -- this was suggested on hw.org but it's not present on base - SetAmmo(amFirePunch, 9, 0, 0, 0) - SetAmmo(amMine, 9, 0, 0, 0) - --SetAmmo(amCake, 1, 0, 2, 0) -- maybe it's beefcake? - SetAmmo(amJetpack, 9, 0, 0, 0) - SetAmmo(amBlowTorch, 9, 0, 0, 0) - SetAmmo(amTeleport, 9, 0, 0, 0) - SetAmmo(amLowGravity, 9, 0, 0, 0) - --SetAmmo(amSkipGo, 9, 0, 0, 0) -- not needed with 1s turn time -end +------------------------------------------- +-- FRENZY +-- a hedgewars mode inspired by Hysteria +------------------------------------------- + +HedgewarsScriptLoad("/Scripts/Locale.lua") +HedgewarsScriptLoad("/Scripts/Tracker.lua") + +local cTimer = 0 +local cn = 0 + +function initialSetup(gear) + SetHealth(gear, 75) -- official is 80, but that assumes bazookas/grenades that do 50 damage +end + +function showStartingInfo() + + ruleSet = "" .. + loc("RULES") .. ": " .. "|" .. + loc("Each turn is only ONE SECOND!") .. "|" .. + loc("Use your ready time to think.") .. "|" .. + loc("Slot keys save time! (F1-F10 by default)") .. "|" .. + " |" .. + loc("SLOTS") .. ": " .. "|" .. + loc("Slot") .. " 1 - " .. loc("Bazooka") .. "|" .. + loc("Slot") .. " 2 - " .. loc("Grenade") .. "|" .. + loc("Slot") .. " 3 - " .. loc("Shotgun") .. "|" .. + loc("Slot") .. " 4 - " .. loc("Shoryuken") .. "|" .. + loc("Slot") .. " 5 - " .. loc("Mine") .. "|" .. + loc("Slot") .. " 6 - " .. loc("Teleport") .. "|" .. + loc("Slot") .. " 7 - " .. loc("Blowtorch") .. "|" .. + loc("Slot") .. " 8 - " .. loc("Flying Saucer") .. "|" .. + loc("Slot") .. " 9 - " .. loc("Molotov") .. "|" .. + loc("Slot") .. " 10 - " .. loc("Low Gravity") + + ShowMission(loc("FRENZY"), + loc("a frenetic Hedgewars mini-game"), + ruleSet, 0, 4000) + +end + +function onGameInit() + + if TurnTime > 10001 then + Ready = 8000 + else + Ready = TurnTime + end + + TurnTime = 1000 + + --These are the official settings, but I think I prefer allowing customization in this regard + --MinesNum = 8 + --MinesTime = 3000 + --MinesDudPercent = 30 + --Explosives = 0 + + --Supposedly official settings + HealthCaseProb = 0 + CrateFreq = 0 + + --Approximation of Official Settings + --SuddenDeathTurns = 10 + --WaterRise = 47 + --HealthDecrease = 0 + +end + +function onGameStart() + showStartingInfo() + runOnHogs(initialSetup) +end + +function onSlot(sln) + cTimer = 8 + cn = sln +end + +function onGameTick() + if cTimer ~= 0 then + cTimer = cTimer -1 + if cTimer == 1 then + ChangeWep(cn) + cn = 0 + cTimer = 0 + end + end +end + +function ChangeWep(s) + + if s == 0 then + SetWeapon(amBazooka) + elseif s == 1 then + SetWeapon(amGrenade) + elseif s == 2 then + SetWeapon(amShotgun) + elseif s == 3 then + SetWeapon(amFirePunch) + elseif s == 4 then + SetWeapon(amMine) + elseif s == 5 then + SetWeapon(amTeleport) + elseif s == 6 then + SetWeapon(amBlowTorch) + elseif s == 7 then + SetWeapon(amJetpack) + elseif s == 8 then + SetWeapon(amMolotov) + elseif s == 9 then + SetWeapon(amLowGravity) + end + +end + +function onGearAdd(gear) + if GetGearType(gear) == gtHedgehog then + trackGear(gear) + end +end + +function onGearDelete(gear) + if GetGearType(gear) == gtHedgehog then + trackDeletion(gear) + end +end + +function onAmmoStoreInit() + SetAmmo(amBazooka, 9, 0, 0, 0) + SetAmmo(amGrenade, 9, 0, 0, 0) + SetAmmo(amMolotov, 9, 0, 0, 0) + SetAmmo(amShotgun, 9, 0, 0, 0) + --SetAmmo(amFlamethrower, 9, 0, 0, 0) -- this was suggested on hw.org but it's not present on base + SetAmmo(amFirePunch, 9, 0, 0, 0) + SetAmmo(amMine, 9, 0, 0, 0) + --SetAmmo(amCake, 1, 0, 2, 0) -- maybe it's beefcake? + SetAmmo(amJetpack, 9, 0, 0, 0) + SetAmmo(amBlowTorch, 9, 0, 0, 0) + SetAmmo(amTeleport, 9, 0, 0, 0) + SetAmmo(amLowGravity, 9, 0, 0, 0) + --SetAmmo(amSkipGo, 9, 0, 0, 0) -- not needed with 1s turn time +end diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Scripts/Multiplayer/Gravity.cfg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Scripts/Multiplayer/Gravity.cfg Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,2 @@ +* +* diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Scripts/Multiplayer/Gravity.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Scripts/Multiplayer/Gravity.lua Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,151 @@ +HedgewarsScriptLoad("/Scripts/Locale.lua") +HedgewarsScriptLoad("/Scripts/Params.lua") + +local gravity = 100 +local mingravity +local maxgravity +local delta = 0 +local period +local periodtimer = 0 +local wdGameTicks = 0 +local wdTTL = 0 +local mln = 1000000 + +local script2_onNewTurn +local script2_onGameTick20 +local script2_onGameStart + + +function grav_onNewTurn() + if delta ~= nil and period == nil then + SetGravity(gravity) + else + SetGravity(div(gravity, mln)) + end + + wdGameTicks = GameTime + + if script2_onNewTurn ~= nil then + script2_onNewTurn() + end +end + +function grav_onGameTick20() + if wdGameTicks + 15000 < GameTime then + SetGravity(100) + else + if wdTTL ~= TurnTimeLeft then + wdGameTicks = GameTime + end + + if delta == nil then + if periodtimer == 0 then + periodtimer = period * 2 + SetGravity(div(GetRandom(maxgravity - mingravity + 1) + mingravity, mln)) + else + periodtimer = periodtimer - 1 + end + elseif delta == 0 then + SetGravity(gravity) + else + if delta > 0 and gravity + delta > maxgravity then + gravity = maxgravity + delta = -delta + elseif delta < 0 and gravity + delta < mingravity then + gravity = mingravity + delta = -delta + else + gravity = gravity + delta + end + + SetGravity(div(gravity, mln)) + end + end + + wdTTL = TurnTimeLeft + + if script2_onGameTick20 ~= nil then + script2_onGameTick20() + end +end + +function onParameters() + parseParams() + + gravity = params["g"] + + mingravity = gravity + maxgravity = params["g2"] + period = params["period"] + + if mingravity ~= nil and maxgravity ~= nil then + if period ~= nil then + period = div(period, 40) + else + period = 125 + end + + mingravity = mingravity * mln + maxgravity = maxgravity * mln + + -- note: mingravity and maxgravity MUST NOT be strings at this point + if mingravity > maxgravity then + mingravity, maxgravity = maxgravity, mingravity + end + + gravity = mingravity + + if period > 0 then + delta = div(maxgravity - mingravity, period) + else + period = -period + delta = nil + end + end + + if gravity == nil then + gravity = 100 + end + + secondScript = params["script2"] + + if secondScript ~= nil then + onParameters = nil + HedgewarsScriptLoad("/Scripts/Multiplayer/" .. secondScript .. ".lua") + + script2_onNewTurn = onNewTurn + script2_onGameTick20 = onGameTick20 + script2_onGameStart = onGameStart + + if onParameters ~= nil then + onParameters() + end + end + + onNewTurn = grav_onNewTurn + onGameTick20 = grav_onGameTick20 + onGameStart = grav_onGameStart +end + +function grav_onGameStart() + if delta == nil then + v = string.format(loc("random in range from %i%% to %i%% with period of %i msec"), div(mingravity, mln), div(maxgravity, mln), period * 40) + elseif period ~= nil then + v = string.format(loc("changing range from %i%% to %i%% with period of %i msec"), div(mingravity, mln), div(maxgravity, mln), period * 40) + else + v = gravity .. "%" + end + + ShowMission(loc("Gravity"), + loc("Current setting is ") .. v, + loc("Setup:|'g=150', where 150 is 150% of normal gravity") .. "|" + .. loc("or 'g=50, g2=150, period=4000' for gravity changing|from 50 to 150 and back with period of 4000 msec") + .. "||" .. loc("Set period to negative value for random gravity"), + 0, 5000) + + if script2_onGameStart ~= nil then + script2_onGameStart() + end +end + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Scripts/Multiplayer/HedgeEditor.cfg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Scripts/Multiplayer/HedgeEditor.cfg Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,2 @@ +Default +Default diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Scripts/Multiplayer/HedgeEditor.hwp Binary file share/hedgewars/Data/Scripts/Multiplayer/HedgeEditor.hwp has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Scripts/Multiplayer/HedgeEditor.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Scripts/Multiplayer/HedgeEditor.lua Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,4115 @@ +--------------------------------------------------------------- +--- HEDGE EDITOR 0.9 (for use with Hedgewars 0.9.22 and up) +--------------------------------------------------------------- +-- a horrible mission editor by mikade +-- place gears like a boss + +-- feel free to shower me with your adoration and/or hate mail +-- more info can be found at http://hedgewars.org/HedgeEditor + +-- special thanks to nemo, unC0Rr, sheepluva and koda for their assistance + +--------------------------------------- +-- GETTING STARTED (for best results!) +--------------------------------------- +-- create a weaponset that has NO DELAYS on any weapons, and that gives you 1 ammo per crate + +-- (optional) copy GameLogExtractor.html, jquery-1.js +-- into your Documents/Hedgewars/Logs folder + +-- (optional) copy hwpmapconverter somewhere easily accessible + +-- (optional) profit?? + +--------------------------------------- +-- CORE FEATURES as of latest version +--------------------------------------- +-- togglable help (press PRECISE + 1, while you have a tool (e.g. airstrike) selected) +-- you can also the set the ScriptParameter in scheme, e.g: helpDisabled="true" + +-- place girders, rubberbands and custom sprites anywhere on the map. +-- the above objects may be destructible, indestructible, icy, or bouncy. + +-- place mines, sticky mines, air mines, barrels, weapon crates, utility crates, +-- health crates, targets, and cleavers anywhere on the map. + +-- select, reposition, modify, or delete placed objects. + +-- read in data from a previously generated map and allow the map to be edited/saved again + +-- contextual cursor and menu graphics +-- placement sounds that are slightly more soothing + +-- meaningless version number +-- extra whitespace +-- fewer capital letters than ideal + +-- upon saving, all level data will be output to logs/game0.log. +-- game0.log also includes a lot of other data so if you only want to see the relevant lines of code +-- you can use GameLogExtractor.html to extract and prune the log into a cleaner form of data, +-- specifically: either as an automagically generated template mission, just core data, or hwmap points. +-- from there, please copy and paste any lines relevant to your interest into an existing +-- (or totally empty!) script and edit them according to taste. + +-------------------------- +-- MODE SPECIFIC SUPPORT +-------------------------- +-- FOR CUSTOM MISSIONS/CAMPAIGN LEVELS: +-- the names/hats/flags/voices/graves of any teams/hogs that you use to play this script can be saved, +-- as can (most of) the settings from your scheme and weapons selection. +-- HOWEVER, you can also use the 'hog identity' tool to give hogs preset names/hats/weapons/health +-- or use the 'team identity' tool to give an entire team themed names/hats. +-- give hogs differing health by using the health modification tool +-- create goals by tagging gears with victory/defeat/collection markers (somewhat implemented) +-- flavor text, as well as victory/defeat conditions will be generated based on these tags. + +-- SHOPPA BALANCE / CONSTRUCTION MODE (partial and/or possibly decremented): +-- Press 1-5 while repositioning hogs with the reposition tool to assign them (their position) a rank. +-- This value will be expressed as a colour that is intended to represent how "good" or "bad" +-- a position on the map is. These ranks/points will be output along with other game data to game0.log +-- This data could be pasted into the ShoppaBalance script to create balances for additional maps. + +-- TECH RACER / HEDGE EDITOR / POINT INTERPRETER: +-- place/remove waypoints/special points +-- use the ScriptParameter in the frontend scheme editor to set additional options, e.g. +-- ufoFuel=1000 (Flying Saucer will start with half the normal fuel. A value of 2000 is infinite fuel) +-- portalDistance=15 (This is the distance portals can travel before fizzling) +-- m=3 (load a particular map from the map library of Data/Scripts/TechMaps +-- helpDisabled="true" (the help pop-up overlay will be disabled by default) + +-- when saving data, points for conversion to HWMAP are also generated and placed inside block comments. +-- copy paste/these points at the START of a converted HWMAP and then convert the map back to HWMAP format. +-- following the above procedure it is then possible to load the map in frontend and play it using a +-- script like TechRacer (or HedgeEditor itself) that can interpret the points using InterpretPoints() + +--------------------------------------- +-- DISCLAIMER +--------------------------------------- +-- well, I really just made this for myself, so it's usage might be a little complicated for others. +-- it also probably has a million errors, and has grown rather bloated over time due to the addition of +-- more and more features that my initial design didn't take into account. + +-- anyway, I've tried to make it more user-friendly by including more comments and gradually adding +-- some basic guidelines such as those listed above, and also the in-game Help displays for each tool. + +----------------------------------------- +-- GIANT "TO DO" LIST / OTHER NOTES +----------------------------------------- + +-- try to prune waypoint list and portal/ufo fuel in the mission template +-- for gamelog extractor + +-- I should probably check if there are tagged gears on save +-- and if there are enable gfOneClanMode so that user can't +-- just destroy all hogs to win map. +-- (what happens if we lose all our hogs?) + +-- I might be able to make the flavor text even better (assassinate hogName) by +-- checking if there is only 1 hog, etc. + +-- possibly try show landflag addcaption constantly like we do for superdelete when +-- using girders / rubbers. + +-- check to what extent hog info is preserved on saving (does health/weps really save correctly?) +-- atm I think it's only for missions so I don't think it is preserved in core data + +-- check if we lose a mission when the enemy collects our crate (we should) + +-- try and find out why we can't save the Theme, that feels really dumb + +-- How about a weapons profile tool that is used with team ammo +-- and then hog identity tool would only be available if gfPerHogAmmo is set + +-- INVESTIGATE when you can bother to do so +-- is airmine still missing anywhere, e.g. the weplist generated FOR THE TEMPLATE SCRIPT + +-- [high] waypoints don't reload yet + +-- [high] look into placing dud/random mines (probably needs a nil value) + +-- [high] add missing weps/utils/gears as they appear +-- some gameflags and settings are probably missing, too (diff border types etc) +-- some themes are also probably missing: cake, hoggywood? +-- the ongameinit stuff is probaably missing something akin to numAirMines +-- and also probably scriptParam and gravity etc. + +-- [med] add a limited form of save/load within level before mass-output + +-- [med] rework gameflag handling to use the newer API methods (done?) + +-- [med] maybe incorporate portal effects / ufo tracking into the template generated script if +-- you want the missions to use it + +-- [med] improve ammo handling (if possible, take more scheme settings into account) +-- also be sure to generate wep data so crates don't have 0 in them (done?) + +-- [low] match the user picked color to the color array + +-- [low] break up the division of labor of the tools into airstrike, minestrike, napalm, etc. + --[[ + girder = "Girder Placement Mode", + rubber = "Rubber Placement Mode", + + airstrike = (target sprite) (gear placement) + "Mine Placement Mode", + "Sticky Mine Placement Mode", + "Air Mine Placement Mode", + "Barrel Placement Mode", + "Target Placement Mode", + "Cleaver Placement Mode", + + drillstrike = crate sprite (crate placement mode) + "Health Crate Placement Mode", + "Weapon Crate Placement Mode", + "Utility Crate Placement Mode", + + + napalm = arrow sprite (selection/modification/deletion mode) + "Advanced Repositioning Mode", -- also include a delete + "Tagging Mode", + "Hog Identity Mode", + "Team Identity Mode", + "Health Modification Mode", + "Sprite Testing Mode", + "Sprite Modification Mode", + "Sprite Placement Mode", + "Waypoint Placement Mode" + }]] + +-- [low] improve support for ShoppaBalance and ConstructionMode, see ranking) + +-- [low] consider combining landflags + +-- [low] periodically rework the code to make it less terrible (hahahahahaha!) + +-- [low] eventually incorporate scripted structures into the editor / mission mode + +-- [low] some kind of support for single team training missions +-- we could possibly add gfOneClanMode and kill the other team we're playing with? + +-- [never?] set all actors to heresurrectible (why did I want this?) + +-- [never?] more detailed goal tagging and multi-stage triggers + +-- [never?] theoretically might be possible to create forts (and other grouped objects) +-- that can be mirrored and generated/placed in a big enough space + +-- [never?] add a pulsing glow thing for sprites you have selected, +-- kind of like the invaders in SpaceInvader (currently they are just displayed as purple) + +-- [never?] add the thing that would be useful for this editor, but that others might use to cheat + +-- [never?] improve "illegal" placement detection (pretty sure should just let people do what they want) + +-- [never?] add GUIs for editing ammo, init settings, additional gear attributes +-- perhaps using precise with timer to enable/disable certain features + +--[[ gui menu ideas that have long since been abandoned +INITIALISATION MENU + --gameFlags, etc + + Map + Theme + TurnTime + Explosives + MinesNum + CaseFreq + Delay + + HealthCaseProb + HealthCaseAmount + DamagePercent + MinesTime + MineDudPercent + SuddenDeathTurns + WaterRise + HealthDecrease +HOG MENU + health + name (can be randomly generated from the list of hog names already in localisation) + poisoned (true/false) + hat + hog level? +TEAM MENU + name (can be randomly generated as above?) should there be an array of teams with an array of names + colour + grave + fort + voicepack + flag + +-- this below stuff is less important +STICKY MINE MENU + timer? +MINE MENU + timer / dud +MEDKIT MENU / EXPLOSIVE MENU + health amount +WEP AND UTIL CRATE MENU + contents + +---------------------------------------- +-- MAP IDEAS +---------------------------------------- +-- try to create a portal race (limit portal distance) +-- for portal race, include barriers that you need to drill shoot through to get lazer site crates + +-- try make a map that uses sinegun to jump between bouncy boxes (not easy until we get better control over landflags) + +-- how about a mission where you have to trap / freeze all the enemy hogs +-- and aren't allowed to kill them? +-- can set it on the islands map. +-- landgun +-- girder +-- mudball +-- hammer +-- seduction? (call a hog who has firepunch into a ditch +-- icegun (do this so you can freeze guys in an area and then blowtorch/explode an obstacle) +-- jump across a bridge that has been mined and then bat the enemy to the other side. + +-- possibly the same as part of the above, possibly different, what about a heist mission +-- the objective is to steal 3 enemy crates +-- the first one you have to fall through an invul tunnel of sticky mines and then parachute. +-- the second one you have to drill rocket / portal. +-- the third one you have to underwater ufo into, but only after opening it up with an underwater bee. + +]] + +--------------------------------------------------------- +-- HEDGE EDITOR, SCRIPT BEGINS (Hey yo, it's about time) +--------------------------------------------------------- + +HedgewarsScriptLoad("/Scripts/Locale.lua") +HedgewarsScriptLoad("/Scripts/Tracker.lua") +HedgewarsScriptLoad("/Scripts/Params.lua") +HedgewarsScriptLoad("/Scripts/TechMaps.lua") + +-- experimental crap +--local destroyMap = false + +----------------------------------------- +-- tracking vars for save/load purposes +----------------------------------------- + +local teamCounter = 0 +local lastRecordedTeam = "" +local hhs = {} + +local waypointList = {} +local girderList = {} +local rubberList = {} +local spriteList = {} + +local mineList = {} +local sMineList = {} +local airMineList = {} +local targetList = {} +local knifeList = {} +local explosivesList = {} +local healthCrateList = {} +local wepCrateList = {} +local utilCrateList = {} +local hogDataList = {} +local AIHogDataList = {} +local hFlagList = {} +local previewDataList = {} + +local shoppaPointList = {} +local shoppaPX = {} +local shoppaPY = {} +local shoppaPR = {} + +--------------------------------- +-- crates are made of this stuff +--------------------------------- + +local atkArray = + { + {amBazooka, "amBazooka", 2, loc("Bazooka")}, + {amBee, "amBee", 3, loc("Homing Bee")}, + {amMortar, "amMortar", 21, loc("Mortar")}, + {amDrill, "amDrill", 28, loc("Drill Rocket")}, + {amSnowball, "amSnowball", 50, loc("Mudball")}, + + {amGrenade, "amGrenade", 0, loc("Grenade")}, + {amClusterBomb, "amClusterBomb", 1, loc("Cluster Bomb")}, + {amMolotov, "amMolotov", 39, loc("Molotov Cocktail")}, + {amWatermelon, "amWatermelon", 25, loc("Watermelon Bomb")}, + {amHellishBomb, "amHellishBomb", 26, loc("Hellish Handgrenade")}, + {amGasBomb, "amGasBomb", 43, loc("Limburger")}, + + {amShotgun, "amShotgun", 4, loc("Shotgun")}, + {amDEagle, "amDEagle", 9, loc("Desert Eagle")}, + {amFlamethrower,"amFlamethrower", 45, loc("Flamethrower")}, + {amSniperRifle, "amSniperRifle", 37, loc("Sniper Rifle")}, + {amSineGun, "amSineGun", 44, loc("SineGun")}, + {amIceGun, "amIceGun", 53, loc("Freezer")}, + {amLandGun, "amLandGun", 52, loc("Land Spray")}, + + {amFirePunch, "amFirePunch", 11, loc("Shoryuken")}, + {amWhip, "amWhip", 12, loc("Whip")}, + {amBaseballBat, "amBaseballBat", 13, loc("Baseball Bat")}, + {amKamikaze, "amKamikaze", 22, loc("Kamikaze")}, + {amSeduction, "amSeduction", 24, loc("Seduction")}, + {amHammer, "amHammer", 47, loc("Hammer")}, + + {amMine, "amMine", 8, loc("Mine")}, + {amDynamite, "amDynamite", 10, loc("Dynamite")}, + {amCake, "amCake", 23, loc("Cake")}, + {amBallgun, "amBallgun", 29, loc("Ballgun")}, + {amRCPlane, "amRCPlane", 30, loc("RC Plane")}, + {amSMine, "amSMine", 46, loc("Sticky Mine")}, + + {amAirAttack, "amAirAttack", 15, loc("Air Attack")}, + {amMineStrike, "amMineStrike", 16, loc("Mine Strike")}, + {amDrillStrike, "amDrillStrike", 49, loc("Drill Strike")}, + {amAirMine, "amAirMine", 56, loc("Air Mine")}, + {amNapalm, "amNapalm", 27, loc("Napalm")}, + {amPiano, "amPiano", 42, loc("Piano Strike")}, + + {amKnife, "amKnife", 54, loc("Cleaver")}, + + {amBirdy, "amBirdy", 40, loc("Birdy")} + + } + +local utilArray = + { + {amBlowTorch, "amBlowTorch", 17, loc("BlowTorch")}, + {amPickHammer, "amPickHammer", 5, loc("PickHammer")}, + {amGirder, "amGirder", 18, loc("Girder")}, + {amRubber, "amRubber", 55, loc("Rubber")}, + {amPortalGun, "amPortalGun", 41, loc("Personal Portal Device")}, + + {amRope, "amRope", 7, loc("Rope")}, + {amParachute, "amParachute", 14, loc("Parachute")}, + {amTeleport, "amTeleport", 19, loc("Teleport")}, + {amJetpack, "amJetpack", 38, loc("Flying Saucer")}, + + {amInvulnerable, "amInvulnerable", 33, loc("Invulnerable")}, + {amLaserSight, "amLaserSight", 35, loc("Laser Sight")}, + {amVampiric, "amVampiric", 36, loc("Vampirism")}, + + {amLowGravity, "amLowGravity", 31, loc("Low Gravity")}, + {amExtraDamage, "amExtraDamage", 32, loc("Extra Damage")}, + {amExtraTime, "amExtraTime", 34, loc("Extra Time")}, + + {amResurrector, "amResurrector", 48, loc("Resurrector")}, + {amTardis, "amTardis", 51, loc("Tardis")}, + + {amSwitch, "amSwitch", 20, loc("Switch Hog")} + } + + --skiphog is 6 + +---------------------------- +-- hog and map editing junk +---------------------------- + +local preMadeTeam = { + + { + "Clowns", + {"WhySoSerious","clown-copper","clown-crossed","clown","Joker"}, + {"Baggy","Bingo","Bobo","Bozo","Buster","Chester","Copper","Heckles","Giggles","Jingo","Molly","Loopy","Patches","Tatters"}, + "R","cm_birdy","Mobster","Rubberduck","Castle" + }, + + { + "Street Fighters", + {"sf_balrog","sf_blanka","sf_chunli","sf_guile","sf_honda","sf_ken","sf_ryu","sf_vega"}, + {"Balrog","Blanka","Chunli","Guile","Honda","Ken","Ryu","Vega"}, + "F","cm_balrog","Surfer","dragonball","Castle" + }, + + { + "Cybernetic Empire", + {"cyborg1","cyborg2"}, + {"Unit 189","Unit 234","Unit 333","Unit 485","Unit 527","Unit 638","Unit 709","Unit 883"}, + "R","cm_binary","Robot","Grave","Castle" + }, + + { + "Color Squad", + {"hair_blue","hair_green","hair_red","hair_yellow","hair_purple","hair_grey","hair_orange","hair_pink"}, + {"Blue","Green","Red","Yellow","Purple","Grey","Orange","Pink"}, + "F","cm_birdy","Singer","Grave","Castle" + }, + + { + "Fruit", + {"fr_apple","fr_banana","fr_lemon","fr_orange","fr_pumpkin","fr_tomato"}, + {"Juicy","Squishy","Sweet","Sour","Bitter","Ripe","Rotten","Fruity"}, + "R","cm_mog","Default","Cherry","Castle" + }, + + { + "The Police", + {"bobby","bobby2v","policecap","policegirl","royalguard"}, + {"Hightower","Lassard","Callahan","Jones","Harris","Thompson","Mahoney","Hooks","Tackleberry"}, + "R","cm_star","British","Statue","Castle" + }, + + { + "The Ninja-Samurai Alliance", + {"NinjaFull","NinjaStraight","NinjaTriangle","Samurai","StrawHat","StrawHatEyes","StrawHatFacial","naruto"}, + {"Bushi","Tatsujin","Itami","Arashi","Shinobi","Ukemi","Godai","Kenshi","Ninpo"}, + "R","japan","Default","octopus","Castle" + }, + + { + "Pokemon", + {"poke_ash","poke_charmander","poke_chikorita","poke_jigglypuff","poke_lugia","poke_mudkip","poke_pikachu","poke_slowpoke","poke_squirtle","poke_voltorb"}, + {"Ash","Charmander","Chikorita","Jigglypuff","Lugia","Mudkip","Pikachu","Slowpoke","Squirtle","Voltorb"}, + "FR","cm_pokemon","Default","pokeball","Castle" + }, + + { + "The Zoo", + {"zoo_Bat","zoo_Beaver","zoo_Bunny","zoo_Deer","zoo_Hedgehog","zoo_Moose","zoo_Pig","zoo_Porkey","zoo_Sheep","zoo_chicken","zoo_elephant","zoo_fish","zoo_frog","zoo_snail","zoo_turtle"}, + {"Batty","Tails","Bunny","Deer","Spikes","Horns","Bacon","Porkey","Sheepy","Chicken","Trunks","Fishy","Legs","Slimer","Roshi"}, + "FR","cm_hurrah","Default","Bone","Castle" + }, + + { + "The Devs", + {"ushanka","zoo_Sheep","bb_bob","Skull","poke_mudkip","lambda","WizardHat","sf_ryu","android","fr_lemon","mp3"}, + {"unC0Rr", "sheepluva", "nemo", "mikade", "koda", "burp","HeneK","Tiyuri","Xeli","Displacer","szczur"}, + "FR","hedgewars","Classic","Statue","Castle" + }, + + { + "Mushroom Kingdom", + {"sm_daisy","sm_luigi","sm_mario","sm_peach","sm_toad","sm_wario"}, + {"Daisy","Luigi","Mario","Princess Peach","Toad","Wario"}, + "FR","cm_birdy","Default","Badger","Castle" + }, + + { + "Pirates", + {"pirate_jack","pirate_jack_bandana"}, + {"Rusted Diego","Fuzzy Beard","Al.Kaholic","Morris","Yumme Gunpowder","Cutlass Cain","Jim Morgan","Silver","Dubloon Devil","Ugly Mug","Fair Wind","Scallywag","Salty Dog","Bearded Beast","Timbers","Both Barrels","Jolly Roger"}, + "R","cm_pirate","Pirate","chest","Castle" + }, + + { + "Gangsters", + {"Moustache","Cowboy","anzac","Bandit","thug","Jason","NinjaFull","chef"}, + {"The Boss","Jimmy","Frankie","Morris","Mooney","Knives","Tony","Meals"}, + "F","cm_anarchy","Mobster","deadhog","Castle" + }, + + + { + "Twenty-Twenty", + {"Glasses","lambda","SunGlasses","Sniper","Terminator_Glasses","Moustache_glasses","doctor","punkman","rasta"}, + {"Specs","Speckles","Spectator","Glasses","Glassy","Harry Potter","Goggles","Clark Kent","Goggs","Lightbender","Specs Appeal","Four Eyes"}, + "R","cm_face","Default","eyecross","Castle" + }, + + + { + "Monsters", + {"Skull","Jason","ShaggyYeti","Zombi","cyclops","Mummy","hogpharoah","vampirichog"}, + {"Bones","Jason","Yeti","Zombie","Old One Eye","Ramesses","Xerxes","Count Hogula"}, + "FR","cm_vampire","Default","octopus","Castle" + }, + + { + "The Iron Curtain", + {"ushanka","war_sovietcomrade1","war_sovietcomrade1","ushanka"}, + {"Alex","Sergey","Vladimir","Andrey","Dimitry","Ivan","Oleg","Kostya","Anton","Eugene"}, + "R","cm_soviet","Russian","skull","Castle" + }, + + { + "Desert Storm", + {"war_desertofficer","war_desertgrenadier1","war_desertmedic","war_desertsapper1","war_desertgrenadier2","war_desertgrenadier4","war_desertsapper2","war_desertgrenadier5"}, + {"Brigadier Briggs","Lt. Luke","Sgt. Smith","Corporal Calvin","Frank","Joe","Sam","Donald"}, + "F","cm_birdy","Default","Grave","Castle" + }, + + --{ + --"Sci-Fi", + --{"scif_2001O","scif_2001Y","scif_BrainSlug","scif_BrainSlug2","scif_Geordi","scif_SparkssHelmet","scif_cosmonaut","scif_cyberpunk","scif_swDarthvader","scif_swStormtrooper"}, + --{}, + --"R","cm_birdy","Default","Grave","Castle" + --}, + + + + + -- + + --{ + --, + --{}, + --{}, + --"R","cm_birdy","Default","Grave","Castle" + --}, + + -- don't forget new additions need to be added to: + --pMode = {"Clowns","Street Fighters","Cybernetic Empire","Color Squad","Fruit","The Police","The Ninja-Samurai Alliance","Pokemon","The Zoo","The Devs","The Hospital"} + -- but maybe we can just get the size of this array and automatically generate a list instead + + + { + "The Hospital", + {"doctor","nurse","war_britmedic","war_desertmedic","war_germanww2medic"}, + {"Dr. Blackwell","Dr. Drew","Dr. Harvey","Dr. Crushing","Dr. Jenner","Dr. Barnard","Dr. Parkinson","Dr. Banting","Dr. Horace","Dr. Hollows","Dr. Jung"}, + "R","cm_birdy","Default","heart","Castle" + } + + } + + +--local menuArray = { +-- "Initialisation Menu", "Team Menu" +-- } + +--local hatArray = {hahahaha, you're joking, right?} +--[[well, here are most of them as vaguely ordered by theme, there may be some duplicates +NoHat, +NinjaFull,NinjaStraight,NinjaTriangle,Samurai,StrawHat,StrawHatEyes,StrawHatFacial,naruto +sm_daisy,sm_luigi,sm_mario,sm_peach,sm_toad,sm_wario, +ShortHair_Black,ShortHair_Brown,ShortHair_Grey,ShortHair_Red,ShortHair_Yellow +hair_blue,hair_green,hair_red,hair_yellow,hair_purple,hair_grey,hair_orange,hair_pink +Skull,Jason,ShaggyYeti,Zombi,cyclops,Mummy,hogpharoah,vampirichog +cap_blue,cap_red,cap_green,cap_junior,cap_yellow,cap_thinking +WhySoSerious,clown-copper,clown-crossed,clown,Joker +bobby,bobby2v,policecap,policegirl,royalguard, +spcartman,spstan,spkenny,spkyle, +sf_balrog,sf_blanka,sf_blankatoothless,sf_chunli,sf_guile,sf_honda,sf_ken,sf_ryu,sf_vega +Glasses,lambda,SunGlasses,Terminator_Glasses,Moustache_glasses +Laminaria,Dragon, +cyborg1,cyborg2, +dish_Ladle,dish_SauceBoatSilver,dish_Teacup,dish_Teapot +laurel,flag_french,flag_germany,flag_italy,flag_usa +fr_apple,fr_banana,fr_lemon,fr_orange,fr_pumpkin,fr_tomato +doctor,nurse,war_britmedic,war_desertmedic,war_germanww2medic, +poke_ash,poke_charmander,poke_chikorita,poke_jigglypuff, +poke_lugia,poke_mudkip,poke_pikachu,poke_slowpoke,poke_squirtle,poke_voltorb +zoo_Bat,zoo_Beaver,zoo_Bunny,zoo_Deer,zoo_Hedgehog,zoo_Moose,zoo_Pig,zoo_Porkey,zoo_Sheep +zoo_chicken,zoo_elephant,zoo_fish,zoo_frog,zoo_snail,zoo_turtle +bushhider,cratehider,Disguise, +tf_demoman,tf_scout,Sniper, +Bandit,thug,anzac,Cowboy +pirate_jack,pirate_jack_bandana, +tiara,crown,royalguard +punkman,Einstein, +sth_Amy,sth_AmyClassic,sth_Eggman,sth_Knux,sth_Metal,sth_Shadow,sth_Sonic,sth_SonicClassic,sth_Super,sth_Tails +vc_gakupo,vc_gumi,vc_kaito,vc_len,vc_luka,vc_meiko,vc_miku,vc_rin +touhou_chen,touhou_marisa,touhou_patchouli,touhou_remelia,touhou_suwako,touhou_yukari, +TeamHeadband,TeamSoldier,TeamTopHat,TeamWheatley,cap_team,hair_team, +bb_bob,bb_bub,bb_cororon,bb_kululun,bubble, +Viking,spartan,swordsmensquire,knight,dwarf, +WizardHat,tophats,pinksunhat,ushanka,mexicansunbrero,HogInTheHat, +4gsuif, +AkuAku, +noface, +Coonskin3, +Dan, +Dauber, +Eva_00b,Eva_00y, +Evil,InfernalHorns,angel, +Gasmask, +IndianChief,Cowboy, +MegaHogX, +Meteorhelmet, +Moustache, +OldMan, +Pantsu, +Plunger, +RSR, +Rain,stormcloud,DayAndNight, +chuckl,Rambo,RobinHood, +Santa,snowhog,ShaggyYeti,eastertop, +Sleepwalker, +SparkleSuperFun, +SunWukong, +android, +beefeater, +car, +chef, +constructor, +footballhelmet, +judo, +lamp, +mechanicaltoy, +mickey_ears, +snorkel, +quotecap, +rasta, + +metalband, +kiss_criss,kiss_frehley,kiss_simmons,kiss_stanley,mp3,Elvis +mv_Spidey,mv_Venom, +ntd_Falcon,ntd_Kirby,ntd_Link,ntd_Samus, +scif_2001O,scif_2001Y,scif_BrainSlug,scif_BrainSlug2,scif_Geordi,scif_SparkssHelmet, +scif_cosmonaut,scif_cyberpunk,scif_swDarthvader,scif_swStormtrooper, +war_UNPeacekeeper01,war_UNPeacekeeper02, +war_airwarden02,war_airwarden03, +war_americanww2helmet, +war_britmedic,war_britpthhelmet,war_britsapper, +war_desertgrenadier1,war_desertgrenadier2,war_desertgrenadier4,war_desertgrenadier5,war_desertmedic, +war_desertofficer,war_desertsapper1,war_desertsapper2, +war_frenchww1gasmask,war_frenchww1helmet, +war_germanww1helmet2,war_germanww1tankhelm,war_germanww2medic,war_germanww2pith, +war_grenadier1,war_trenchgrenadier1,war_trenchgrenadier2,war_trenchgrenadier3, +war_plainpith, +war_sovietcomrade1,war_sovietcomrade2, +war_trenchfrench01,war_trenchfrench02,]] + +local colorArray = { + --{0xff0000ff, "0xff0000ff", "Red"}, -- look up hw red + {0xff4980c1, "0xff4980c1", "Blue"}, + {0xff1de6ba, "0xff1de6ba", "Teal"}, + {0xffb541ef, "0xffb541ef", "Purple"}, + {0xffe55bb0, "0xffe55bb0", "Pink"}, + {0xff20bf00, "0xff20bf00", "Green"}, + {0xfffe8b0e, "0xfffe8b0e", "Orange"}, + {0xff5f3605, "0xff5f3605", "Brown"}, + {0xffffff01, "0xffffff01", "Yellow"} + } + +local graveArray = { + "Badger", "Bone", "bp2", "bubble", "Cherry", + "chest", "coffin", "deadhog", "dragonball", "Duck2", + "Earth", "Egg", "eyecross", "Flower", "Ghost", + "Grave", "heart", "money", "mouton1", "octopus", + "plant2", "plant3", "Plinko", "pokeball", "pyramid", + "ring", "Rip", "Rubberduck", "Simple", "skull", + "star", "Status" + } + +local voiceArray = { + "British","Classic","Default","Default_es","Default_uk", + "HillBilly","Mobster","Pirate","Robot","Russian","Singer", + "Surfer" + } + +local fortArray = { + "Cake", "Castle", "Earth", "EvilChicken", "Flowerhog", + "Hydrant", "Lego", "Plane", "Statue", "Tank", + "UFO", "Wood" + } + +-- non-exhaustive list of flags, feel free to choose others +local flagArray = { + "cm_binary", "cm_birdy", "cm_earth", "cm_pirate", "cm_star", + "cm_hurrah", "cm_hax0r", "cm_balrog", "cm_spider", "cm_eyeofhorus" + } + +local gameFlagList = { + {"gfForts", false, gfForts}, + {"gfMultiWeapon", false, gfMultiWeapon}, + {"gfBorder", false, gfBorder}, + {"gfSolidLand", false, gfSolidLand}, + {"gfDivideTeams", false, gfDivideTeams}, + {"gfLowGravity", false, gfLowGravity}, + {"gfLaserSight", true, gfLaserSight}, + {"gfInvulnerable", false, gfInvulnerable}, + {"gfMines", false, gfMines}, + {"gfVampiric", false, gfVampiric}, + {"gfKarma", false, gfKarma}, + {"gfArtillery", false, gfArtillery}, + {"gfOneClanMode", false, gfOneClanMode}, + {"gfRandomOrder", false, gfRandomOrder}, + {"gfKing", false, gfKing}, + {"gfPlaceHog", false, gfPlaceHog}, + {"gfSharedAmmo", false, gfSharedAmmo}, + {"gfDisableGirders", false, gfDisableGirders}, + {"gfExplosives", false, gfExplosives}, + {"gfDisableLandObjects", false, gfDisableLandObjects}, + {"gfAISurvival", false, gfAISurvival}, + {"gfInfAttack", true, gfInfAttack}, + {"gfResetWeps", false, gfResetWeps}, + {"gfResetHealth", false, gfResetHealth}, + {"gfPerHogAmmo", false, gfPerHogAmmo}, + {"gfDisableWind", false, gfDisableWind}, + {"gfMoreWind", false, gfMoreWind}, + {"gfTagTeam", false, gfTagTeam} + } + +local themeList = {"Art", "Bamboo", "Bath", --[["Blox",]] "Brick", "Cake", "Castle", "Cave", "Cheese", + "Christmas", "City", "Compost", --[["CrazyMission", "Deepspace",]] "Desert", "Earthrise", + --[["Eyes",]] "Freeway", "Golf", "Halloween", "Hell", --[["HogggyWood",]] "Island", "Jungle", "Nature", + "Olympics", "Planes", "Sheep", "Snow", "Stage", "Underwater" + } + +local mapList = { + "Bamboo", "BambooPlinko", "Basketball", "Bath", "Blizzard", "Blox", "Bubbleflow", + "Battlefield", "Cake", "Castle", "Cave", "Cheese", "Cogs", "Control", "Earthrise", + "Eyes", "Hammock", "Hedgelove", "Hedgewars", "Hogville", "Hydrant", "Islands", + "Knockball", "Lonely_Island", "Mushrooms", "Octorama", "PirateFlag", + "Plane", "Ropes", "Ruler", "Sheep", "ShoppaKing", "Sticks", "Trash", "Tree", + "TrophyRace" + } + +--local spriteArray = { +-- {sprBigDigit, "sprBigDigit", 0} +-- } + +local spriteIDArray = {sprWater, sprCloud, sprBomb, sprBigDigit, sprFrame, +sprLag, sprArrow, sprBazookaShell, sprTargetP, sprBee, +sprSmokeTrace, sprRopeHook, sprExplosion50, sprMineOff, +sprMineOn, sprMineDead, sprCase, sprFAid, sprDynamite, sprPower, +sprClusterBomb, sprClusterParticle, sprFlame, +sprHorizont, sprHorizontL, sprHorizontR, sprSky, sprSkyL, sprSkyR, +sprAMSlot, sprAMAmmos, sprAMAmmosBW, sprAMSlotKeys, sprAMCorners, +sprFinger, sprAirBomb, sprAirplane, sprAmAirplane, sprAmGirder, +sprHHTelepMask, sprSwitch, sprParachute, sprTarget, sprRopeNode, +sprQuestion, sprPowerBar, sprWindBar, sprWindL, sprWindR, + +sprFireButton, sprArrowUp, sprArrowDown, sprArrowLeft, sprArrowRight, +sprJumpWidget, sprAMWidget, sprPauseButton, sprTimerButton, sprTargetButton, + +sprFlake, sprHandRope, sprHandBazooka, sprHandShotgun, +sprHandDEagle, sprHandAirAttack, sprHandBaseball, sprPHammer, +sprHandBlowTorch, sprBlowTorch, sprTeleport, sprHHDeath, +sprShotgun, sprDEagle, sprHHIdle, sprMortar, sprTurnsLeft, +sprKamikaze, sprWhip, sprKowtow, sprSad, sprWave, +sprHurrah, sprLemonade, sprShrug, sprJuggle, sprExplPart, sprExplPart2, +sprCakeWalk, sprCakeDown, sprWatermelon, +sprEvilTrace, sprHellishBomb, sprSeduction, sprDress, +sprCensored, sprDrill, sprHandDrill, sprHandBallgun, sprBalls, +sprPlane, sprHandPlane, sprUtility, sprInvulnerable, sprVampiric, sprGirder, +sprSpeechCorner, sprSpeechEdge, sprSpeechTail, +sprThoughtCorner, sprThoughtEdge, sprThoughtTail, +sprShoutCorner, sprShoutEdge, sprShoutTail, +sprSniperRifle, sprBubbles, sprJetpack, sprHealth, sprHandMolotov, sprMolotov, +sprSmoke, sprSmokeWhite, sprShell, sprDust, sprSnowDust, sprExplosives, sprExplosivesRoll, +sprAmTeleport, sprSplash, sprDroplet, sprBirdy, sprHandCake, sprHandConstruction, +sprHandGrenade, sprHandMelon, sprHandMortar, sprHandSkip, sprHandCluster, +sprHandDynamite, sprHandHellish, sprHandMine, sprHandSeduction, sprHandVamp, +sprBigExplosion, sprSmokeRing, sprBeeTrace, sprEgg, sprTargetBee, sprHandBee, +sprFeather, sprPiano, sprHandSineGun, sprPortalGun, sprPortal, +sprCheese, sprHandCheese, sprHandFlamethrower, sprChunk, sprNote, +sprSMineOff, sprSMineOn, sprHandSMine, sprHammer, +sprHandResurrector, sprCross, sprAirDrill, sprNapalmBomb, +sprBulletHit, sprSnowball, sprHandSnowball, sprSnow, +sprSDFlake, sprSDWater, sprSDCloud, sprSDSplash, sprSDDroplet, sprTardis, +sprSlider, sprBotlevels, sprHandKnife, sprKnife, sprStar, sprIceTexture, sprIceGun, sprFrozenHog, sprAmRubber, sprBoing} + + +local spriteTextArray = {"sprWater", "sprCloud", "sprBomb", "sprBigDigit", "sprFrame", +"sprLag", "sprArrow", "sprBazookaShell", "sprTargetP", "sprBee", +"sprSmokeTrace", "sprRopeHook", "sprExplosion50", "sprMineOff", +"sprMineOn", "sprMineDead", "sprCase", "sprFAid", "sprDynamite", "sprPower", +"sprClusterBomb", "sprClusterParticle", "sprFlame", "sprHorizont", +"sprHorizontL", "sprHorizontR", "sprSky", "sprSkyL", "sprSkyR", "sprAMSlot", +"sprAMAmmos", "sprAMAmmosBW", "sprAMSlotKeys", "sprAMCorners", "sprFinger", +"sprAirBomb", "sprAirplane", "sprAmAirplane", "sprAmGirder", "sprHHTelepMask", + "sprSwitch", "sprParachute", "sprTarget", "sprRopeNode", "sprQuestion", + "sprPowerBar", "sprWindBar", "sprWindL", "sprWindR", "sprFireButton", + "sprArrowUp", "sprArrowDown", "sprArrowLeft", "sprArrowRight", "sprJumpWidget", + "sprAMWidget", "sprPauseButton", "sprTimerButton", "sprTargetButton", + "sprFlake", "sprHandRope", "sprHandBazooka", "sprHandShotgun", + "sprHandDEagle", "sprHandAirAttack", "sprHandBaseball", "sprPHammer", + "sprHandBlowTorch", "sprBlowTorch", "sprTeleport", "sprHHDeath", "sprShotgun", + "sprDEagle", "sprHHIdle", "sprMortar", "sprTurnsLeft", "sprKamikaze", "sprWhip", + "sprKowtow", "sprSad", "sprWave", "sprHurrah", "sprLemonade", "sprShrug", + "sprJuggle", "sprExplPart", "sprExplPart2", "sprCakeWalk", "sprCakeDown", + "sprWatermelon", "sprEvilTrace", "sprHellishBomb", "sprSeduction", "sprDress", + "sprCensored", "sprDrill", "sprHandDrill", "sprHandBallgun", "sprBalls", "sprPlane", + "sprHandPlane", "sprUtility", "sprInvulnerable", "sprVampiric", "sprGirder", + "sprSpeechCorner", "sprSpeechEdge", "sprSpeechTail", "sprThoughtCorner", + "sprThoughtEdge", "sprThoughtTail", "sprShoutCorner", "sprShoutEdge", + "sprShoutTail", "sprSniperRifle", "sprBubbles", "sprJetpack", "sprHealth", + "sprHandMolotov", "sprMolotov", "sprSmoke", "sprSmokeWhite", "sprShell", "sprDust", + "sprSnowDust", "sprExplosives", "sprExplosivesRoll", "sprAmTeleport", "sprSplash", + "sprDroplet", "sprBirdy", "sprHandCake", "sprHandConstruction", "sprHandGrenade", + "sprHandMelon", "sprHandMortar", "sprHandSkip", "sprHandCluster", "sprHandDynamite", + "sprHandHellish", "sprHandMine", "sprHandSeduction", "sprHandVamp", "sprBigExplosion", + "sprSmokeRing", "sprBeeTrace", "sprEgg", "sprTargetBee", "sprHandBee", "sprFeather", + "sprPiano", "sprHandSineGun", "sprPortalGun", "sprPortal", "sprCheese", "sprHandCheese", + "sprHandFlamethrower", "sprChunk", "sprNote", "sprSMineOff", "sprSMineOn", "sprHandSMine", + "sprHammer", "sprHandResurrector", "sprCross", "sprAirDrill", "sprNapalmBomb", "sprBulletHit", + "sprSnowball", "sprHandSnowball", "sprSnow", "sprSDFlake", "sprSDWater", "sprSDCloud", + "sprSDSplash", "sprSDDroplet", "sprTardis", "sprSlider", "sprBotlevels", "sprHandKnife", + "sprKnife", "sprStar", "sprIceTexture", "sprIceGun", "sprFrozenHog", "sprAmRubber", "sprBoing"} + + local reducedSpriteIDArray = { + sprBigDigit, sprTarget, sprKowtow, sprBee, sprAmGirder, sprExplosion50, sprGirder,sprCustom1,sprCustom2 + } + + local reducedSpriteTextArray = { + "sprBigDigit", "sprTarget", "sprKowtow", "sprBee", "sprAmGirder", "sprExplosion50", "sprGirder","sprCustom1","sprCustom2" + } + +---------------------------- +-- placement shite +---------------------------- + +local landType = 0 +local superDelete = false +local ufoGear = nil +ufoFuel = 0 +mapID = 1 +local portalDistance = 5000/5 +local helpDisabled = false --determines whether help popups pop up +local CG = nil -- this is the visual gear displayed at CursorX, CursorY +local crateSprite = nil-- this is a visual gear aid for crate placement +local tSpr = {} + +local cGear = nil -- detects placement of girders and objects (using airattack) +local curWep = amNothing +local leftHeld = false +local rightHeld = false +local preciseOn = false + +-- primary placement categories +local cIndex = 1 -- category index +local cat = { + loc("Girder Placement Mode"), + loc("Rubber Placement Mode"), + loc("Mine Placement Mode"), + loc("Sticky Mine Placement Mode"), + loc("Air Mine Placement Mode"), + loc("Barrel Placement Mode"), + loc("Health Crate Placement Mode"), + loc("Weapon Crate Placement Mode"), + loc("Utility Crate Placement Mode"), + loc("Target Placement Mode"), + loc("Cleaver Placement Mode"), + loc("Advanced Repositioning Mode"), + loc("Tagging Mode"), + loc("Hog Identity Mode"), + loc("Team Identity Mode"), + loc("Health Modification Mode"), + --loc("Sprite Testing Mode"), + loc("Sprite Placement Mode"), + loc("Sprite Modification Mode"), + loc("Waypoint Placement Mode") + } + + +local pMode = {} -- pMode contains custom subsets of the main categories +local pIndex = 1 + +local genTimer = 0 + +local CGR = 1 -- current girder rotation, we actually need this as HW remembers what rotation you last used + +local placedX = {} -- x coord of placed object +local placedY = {} -- y coord of placed object +local placedSpec = {} -- this is different depending on what was placed, for mines it is their time, for crates it is their content, (for girders/rubbers it used to be their rotation, and for sprites, their name, but this has been moved to different variables to allow more complex / smooth editing) +--local placedSuperSpec = {} -- used to be used by girders/rubbers/sprites for their landFlag +local placedType = {} -- what kind of object was placed: mine, crate, girder, rubber, barrel, etc. + +local placedTint = {} -- only girders/rubbers/sprites use this, it is their tint / colouration +local placedSprite = {} -- what sprite was placed +local placedFrame = {} -- what frame of sprite was placed (rotation for girders / rubber) +local placedLandFlags = {} +local placedHWMapFlag = {} -- this is what HWMapConverter uses +local placedCount = 0 -- do we really need this? + +local sSprite -- sprite overlay that glows to show selected sprites +local sCirc -- circle that appears around selected gears +local sGear = nil +local closestDist +local closestGear = nil +local closestSpriteID = nil + +------------------------ +-- menu shite (more or less unused currently) +------------------------ +--local menuEnabled = false +--local menuIndex = 1 +--local menu = {} +--local subMenu = {} +--local sMI = 1 -- sub menu index +--local preMenuCfg +--local postMenuCfg +--local initMenu = { +-- {"Selected Menu", "Initialisation Menu"}, +-- {"List of Gameflags", ""}, +-- {"List of Gameflags", ""} +-- } + +------------------------ +-- SOME GENERAL METHODS +------------------------ + +function BoolToString(boo) + if boo == true then + return("true") + else + return("false") + end +end + +function GetDistFromGearToXY(gear, g2X, g2Y) + + g1X, g1Y = GetGearPosition(gear) + q = g1X - g2X + w = g1Y - g2Y + + return ( (q*q) + (w*w) ) + +end + +------------------------------------------------------------ +-- STUFF FOR LOADING SPECIAL POINTS / HWMAP CONVERSION +------------------------------------------------------------ + +local specialPointsX = {} +local specialPointsY = {} +local specialPointsFlag = {} +local specialPointsCount = 0 + +function onSpecialPoint(x,y,flag) + specialPointsX[specialPointsCount] = x + specialPointsY[specialPointsCount] = y + specialPointsFlag[specialPointsCount] = flag + specialPointsCount = specialPointsCount + 1 +end + +-- you know you could probably add multiple layers to this to get more points +-- after the first set is expended have the last 1 be 127 +-- and then increment some other counter so like + +-- bobCounter = 1 +-- specialPoint(5) +-- specialPoint(127) +-- specialPoint(5) + +-- if BobCounter = 1 then +-- if specialPointsFlag == 5 then createMine +-- if specialPointFlag == 127 then bobCounter = 2 +-- elseif bobCounter == 2 then +-- if specialPointsFlag == 5 then createExlosives +-- end +-- + +-- this function interprets special points that have been embedded into an HWPMAP +function InterpretPoints() + + -- flags run from 0 to 127 + for i = 0, (specialPointsCount-1) do + + -- Mines + if specialPointsFlag[i] == 1 then + SetTimer(AddGear(specialPointsX[i], specialPointsY[i], gtMine, 0, 0, 0, 0), 1) + elseif specialPointsFlag[i] == 2 then + SetTimer(AddGear(specialPointsX[i], specialPointsY[i], gtMine, 0, 0, 0, 0), 1000) + elseif specialPointsFlag[i] == 3 then + SetTimer(AddGear(specialPointsX[i], specialPointsY[i], gtMine, 0, 0, 0, 0), 2000) + elseif specialPointsFlag[i] == 4 then + SetTimer(AddGear(specialPointsX[i], specialPointsY[i], gtMine, 0, 0, 0, 0), 3000) + elseif specialPointsFlag[i] == 5 then + SetTimer(AddGear(specialPointsX[i], specialPointsY[i], gtMine, 0, 0, 0, 0), 4000) + elseif specialPointsFlag[i] == 6 then + SetTimer(AddGear(specialPointsX[i], specialPointsY[i], gtMine, 0, 0, 0, 0), 5000) + + -- Sticky Mines + elseif specialPointsFlag[i] == 7 then + AddGear(specialPointsX[i], specialPointsY[i], gtSMine, 0, 0, 0, 0) + + -- Air Mines + elseif specialPointsFlag[i] == 8 then + AddGear(specialPointsX[i], specialPointsY[i], gtAirMine, 0, 0, 0, 0) + + -- Health Crates + elseif specialPointsFlag[i] == 9 then + SetHealth(SpawnHealthCrate(specialPointsX[i],specialPointsY[i]),25) + elseif specialPointsFlag[i] == 10 then + SetHealth(SpawnHealthCrate(specialPointsX[i],specialPointsY[i]),50) + elseif specialPointsFlag[i] == 11 then + SetHealth(SpawnHealthCrate(specialPointsX[i],specialPointsY[i]),75) + elseif specialPointsFlag[i] == 12 then + SetHealth(SpawnHealthCrate(specialPointsX[i],specialPointsY[i]),100) + + -- Cleaver + elseif specialPointsFlag[i] == 13 then + AddGear(specialPointsX[i], specialPointsY[i], gtKnife, 0, 0, 0, 0) + + -- Target + elseif specialPointsFlag[i] == 14 then + AddGear(specialPointsX[i], specialPointsY[i], gtTarget, 0, 0, 0, 0) + + --Barrels + elseif specialPointsFlag[i] == 15 then + SetHealth(AddGear(specialPointsX[i], specialPointsY[i], gtExplosives, 0, 0, 0, 0),1) + elseif specialPointsFlag[i] == 16 then + SetHealth(AddGear(specialPointsX[i], specialPointsY[i], gtExplosives, 0, 0, 0, 0),25) + elseif specialPointsFlag[i] == 17 then + SetHealth(AddGear(specialPointsX[i], specialPointsY[i], gtExplosives, 0, 0, 0, 0),50) + elseif specialPointsFlag[i] == 18 then + SetHealth(AddGear(specialPointsX[i], specialPointsY[i], gtExplosives, 0, 0, 0, 0),75) + elseif specialPointsFlag[i] == 19 then + SetHealth(AddGear(specialPointsX[i], specialPointsY[i], gtExplosives, 0, 0, 0, 0),100) + + -- There are about 58+- weps / utils + -- Weapon Crates + elseif (specialPointsFlag[i] >= 20) and (specialPointsFlag[i] < (#atkArray+20)) then + tempG = SpawnAmmoCrate(specialPointsX[i],specialPointsY[i],atkArray[specialPointsFlag[i]-19][1]) + setGearValue(tempG,"caseType","ammo") + setGearValue(tempG,"contents",atkArray[specialPointsFlag[i]-19][2]) + + + -- Utility Crates + elseif (specialPointsFlag[i] >= (#atkArray+20)) and (specialPointsFlag[i] < (#atkArray+20+#utilArray)) then + tempG = SpawnUtilityCrate(specialPointsX[i],specialPointsY[i],utilArray[specialPointsFlag[i]-19-#atkArray][1]) + setGearValue(tempG,"caseType","util") + setGearValue(tempG,"contents",utilArray[specialPointsFlag[i]-19-#atkArray][2]) + + --79-82 (reserved for future wep crates) + --89,88,87,86 and 85,84,83,82 (reserved for the 2 custom sprites and their landflags) + + --90-99 reserved for scripted structures + --[[elseif specialPointsFlag[i] == 90 then + --PlaceStruc("generator") + elseif specialPointsFlag[i] == 91 then + --PlaceStruc("healingstation") + elseif specialPointsFlag[i] == 92 then + --PlaceStruc("respawner") + elseif specialPointsFlag[i] == 93 then + --PlaceStruc("teleportationnode") + elseif specialPointsFlag[i] == 94 then + --PlaceStruc("biofilter") + elseif specialPointsFlag[i] == 95 then + --PlaceStruc("supportstation") + elseif specialPointsFlag[i] == 96 then + --PlaceStruc("constructionstation") + elseif specialPointsFlag[i] == 97 then + --PlaceStruc("reflectorshield") + elseif specialPointsFlag[i] == 98 then + --PlaceStruc("weaponfilter")]] + + elseif specialPointsFlag[i] == 98 then + portalDistance = div(specialPointsX[i],5) + ufoFuel = specialPointsY[i] + + -- Normal Girders + elseif specialPointsFlag[i] == 100 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + elseif specialPointsFlag[i] == 101 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmGirder, 1, 4294967295, nil, nil, nil, lfNormal) + elseif specialPointsFlag[i] == 102 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmGirder, 2, 4294967295, nil, nil, nil, lfNormal) + elseif specialPointsFlag[i] == 103 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmGirder, 3, 4294967295, nil, nil, nil, lfNormal) + elseif specialPointsFlag[i] == 104 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + elseif specialPointsFlag[i] == 105 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + elseif specialPointsFlag[i] == 106 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + elseif specialPointsFlag[i] == 107 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + + -- Invulnerable Girders + elseif specialPointsFlag[i] == 108 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmGirder, 0, 2516582650, nil, nil, nil, lfIndestructible) + elseif specialPointsFlag[i] == 109 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmGirder, 1, 2516582650, nil, nil, nil, lfIndestructible) + elseif specialPointsFlag[i] == 110 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmGirder, 2, 2516582650, nil, nil, nil, lfIndestructible) + elseif specialPointsFlag[i] == 111 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmGirder, 3, 2516582650, nil, nil, nil, lfIndestructible) + elseif specialPointsFlag[i] == 112 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + elseif specialPointsFlag[i] == 113 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmGirder, 5, 2516582650, nil, nil, nil, lfIndestructible) + elseif specialPointsFlag[i] == 114 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + elseif specialPointsFlag[i] == 115 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmGirder, 7, 2516582650, nil, nil, nil, lfIndestructible) + + -- Icy Girders + elseif specialPointsFlag[i] == 116 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmGirder, 0, 16448250, nil, nil, nil, lfIce) + elseif specialPointsFlag[i] == 117 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmGirder, 1, 16448250, nil, nil, nil, lfIce) + elseif specialPointsFlag[i] == 118 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmGirder, 2, 16448250, nil, nil, nil, lfIce) + elseif specialPointsFlag[i] == 119 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmGirder, 3, 16448250, nil, nil, nil, lfIce) + elseif specialPointsFlag[i] == 120 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmGirder, 4, 16448250, nil, nil, nil, lfIce) + elseif specialPointsFlag[i] == 121 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmGirder, 5, 16448250, nil, nil, nil, lfIce) + elseif specialPointsFlag[i] == 121 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmGirder, 6, 16448250, nil, nil, nil, lfIce) + elseif specialPointsFlag[i] == 123 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmGirder, 7, 16448250, nil, nil, nil, lfIce) + + -- Rubber Bands + elseif specialPointsFlag[i] == 124 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + elseif specialPointsFlag[i] == 125 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmRubber, 1, 4294967295, nil, nil, nil, lfBouncy) + elseif specialPointsFlag[i] == 126 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmRubber, 2, 4294967295, nil, nil, nil, lfBouncy) + elseif specialPointsFlag[i] == 127 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmRubber, 3, 4294967295, nil, nil, nil, lfBouncy) + + -- Waypoints + else -- 0 / no value + PlaceWaypoint(specialPointsX[i],specialPointsY[i]) + end + + end + +end + +---------------------------- +-- just fucking around +---------------------------- +-- ancient stuff that no longer has any relevance +--[[ +function BoostVeloctiy(gear) + + if (GetGearType(gear) == gtSMine) or + (GetGearType(gear) == gtMine) or + (GetGearType(gear) == gtHedgehog) then + + dx,dy = GetGearVelocity(gear) + SetGearVelocity(gear,dx*1.5,dy*1.5) + end + +end + +-- use this stuff when you want to get some idea of land and/or blow up /everything/ +function CheckGrenades(gear) + + if GetGearType(gear) == gtGrenade then + dx, dy = GetGearVelocity(gear) + if (dy == 0) then + + else + DeleteGear(gear) + end + end + +end + +function BlowShitUpPartTwo() + + destroyMap = false + runOnGears(CheckGrenades) + +end + +function BlowShitUp() + + destroyMap = true + + mapWidth = 4096 + mapHeight = 2048 + blockSize = 50 + + mY = 0 + + while (mY < WaterLine) do + + mX = 0 + mY = mY + 1*blockSize + while (mX < mapWidth) do + + mX = mX + (1*blockSize) + gear = AddGear(mX, mY, gtGrenade, 0, 0, 0, 5000) + SetState(gear, bor(GetState(gear),gstInvisible) ) + + end + + end + +end]] + + +-- you know, using this it might be possible to have a self destructing track, +-- or a moving one. +-- edit: this was from the gold old days before it was possible to erase sprites) +--[[function BoomGirder(x,y,rot) + girTime = 1 + if rot < 4 then + AddGear(x, y, gtGrenade, 0, 0, 0, girTime) + elseif rot == 4 then + g = AddGear(x-45, y, gtGrenade, 0, 0, 0, girTime) -- needed? + g = AddGear(x-30, y, gtGrenade, 0, 0, 0, girTime) + g = AddGear(x, y, gtGrenade, 0, 0, 0, girTime) -- needed? + g = AddGear(x+30, y, gtGrenade, 0, 0, 0, girTime) + g = AddGear(x+45, y, gtGrenade, 0, 0, 0, girTime) -- needed? + elseif rot == 5 then ------- diag + g = AddGear(x+45, y+45, gtGrenade, 0, 0, 0, girTime) --n + g = AddGear(x+30, y+30, gtGrenade, 0, 0, 0, girTime) + g = AddGear(x, y, gtGrenade, 0, 0, 0, girTime) -- needed? + g = AddGear(x-30, y-30, gtGrenade, 0, 0, 0, girTime) + g = AddGear(x-45, y-45, gtGrenade, 0, 0, 0, girTime) --n + elseif rot == 6 then + g = AddGear(x, y-45, gtGrenade, 0, 0, 0, girTime) -- needed? + g = AddGear(x, y+30, gtGrenade, 0, 0, 0, girTime) + g = AddGear(x, y, gtGrenade, 0, 0, 0, girTime) -- needed? + g = AddGear(x, y-30, gtGrenade, 0, 0, 0, girTime) + g = AddGear(x, y+45, gtGrenade, 0, 0, 0, girTime) -- needed? + elseif rot == 7 then ------- + g = AddGear(x+45, y-45, gtGrenade, 0, 0, 0, girTime) --n + g = AddGear(x+30, y-30, gtGrenade, 0, 0, 0, girTime) + g = AddGear(x, y, gtGrenade, 0, 0, 0, girTime) -- needed? + g = AddGear(x-30, y+30, gtGrenade, 0, 0, 0, girTime) + g = AddGear(x-45, y+45, gtGrenade, 0, 0, 0, girTime) --n + end +end]] + +--[[function SpecialGirderPlacement(x,y,rot) + + PlaceGirder(x, y, rot) + girTime = 10000 + + if rot < 4 then + AddGear(x, y, gtGrenade, 0, 0, 0, girTime) + elseif rot == 4 then + g = AddGear(x-30, y, gtGrenade, 0, 0, 0, girTime) + g = AddGear(x+30, y, gtGrenade, 0, 0, 0, girTime) + elseif rot == 5 then ------- + g = AddGear(x+30, y+30, gtGrenade, 0, 0, 0, girTime) + g = AddGear(x-30, y-30, gtGrenade, 0, 0, 0, girTime) + elseif rot == 6 then + g = AddGear(x, y+30, gtGrenade, 0, 0, 0, girTime) + g = AddGear(x, y-30, gtGrenade, 0, 0, 0, girTime) + elseif rot == 7 then ------- + g = AddGear(x+30, y-30, gtGrenade, 0, 0, 0, girTime) + g = AddGear(x-30, y+30, gtGrenade, 0, 0, 0, girTime) + end + +end]] + +--shoppabalance crap +function AddShoppaPoint(x,y,c) + table.insert(shoppaPX, x) + table.insert(shoppaPY, y) + table.insert(shoppaPR, c) +end + +function GetRankedColour(r) + if r == 1 then + return(0xFF0000FF) + elseif r == 2 then + return(0xFFFF00FF) + elseif r == 3 then + return(0x00FF00FF) + elseif r == 4 then + return(0x0000FFFF) + elseif r == 5 then + return(0xFF00FFFF) + end +end + +----------------------------------------- +-- PRIMARY HEDGE EDITOR PLACEMENT STUFF +----------------------------------------- + +function GetClosestGear() + closestDist = 999999999 + closestGear = nil + --sGear = nil + runOnGears(SelectGear) + return(closestGear) +end + +function SelectGear(gear) + + d = GetDistFromGearToXY(gear, placedX[placedCount], placedY[placedCount]) + + if d < closestDist then + closestDist = d + closestGear = gear + end + +end + +function PlaceWaypoint(x,y) + + placedX[placedCount] = x + placedY[placedCount] = y + placedType[placedCount] = loc("Waypoint Placement Mode") + placedLandFlags[placedCount] = nil -- use this to specify waypoint type maybe + placedHWMapFlag[placedCount] = 0 + + placedSprite[placedCount] = vgtCircle + placedSpec[placedCount] = AddVisualGear(x,y,vgtCircle,0,true) + placedTint[placedCount] = 0xFF0000FF + placedFrame[placedCount] = 1 --rad is 450 + SetVisualGearValues(placedSpec[placedCount], x, y, 20, 100, 1, 10, 0, 450, 5, placedTint[placedCount]) + placedCount = placedCount +1 + +end + +function LoadSprite(pX, pY, pSprite, pFrame, pTint, p1, p2, p3, pLandFlags) + + placedX[placedCount] = pX + placedY[placedCount] = pY + placedSpec[placedCount] = nil + + if pSprite == sprAmGirder then + + placedType[placedCount] = loc("Girder Placement Mode") + + --newHWMapStuff + if pLandFlags == lfIndestructible then specialMod = 1 + elseif pLandFlags == lfIce then specialMod = 2 + else specialMod = 0 + end + placedHWMapFlag[placedCount] = pFrame+100+(8*specialMod) + + + elseif pSprite == sprAmRubber then + + placedType[placedCount] = loc("Rubber Placement Mode") + + --newHWMapStuff + if pFrame == 0 then placedHWMapFlag[placedCount] = 124 + elseif pFrame == 1 then placedHWMapFlag[placedCount] = 125 + elseif pFrame == 2 then placedHWMapFlag[placedCount] = 126 + elseif pFrame == 3 then placedHWMapFlag[placedCount] = 127 + end + + else + placedType[placedCount] = loc("Sprite Placement Mode") + end + + --placedLandFlags[placedCount] = pLandFlags + if pLandFlags == lfIce then + placedLandFlags[placedCount] = "lfIce" + elseif pLandFlags == lfIndestructible then + placedLandFlags[placedCount] = "lfIndestructible" + elseif pLandFlags == lfBouncy then + placedLandFlags[placedCount] = "lfBouncy" + else + placedLandFlags[placedCount] = "lfNormal" + end + + --placedSuperSpec[placedCount] = nil + + placedTint[placedCount] = pTint + placedFrame[placedCount] = pFrame + + placedSprite[placedCount] = pSprite + + PlaceSprite(pX, pY, pSprite, pFrame, pTint, nil, nil, nil, pLandFlags) + + placedCount = placedCount + 1 + +end + +function CallPlaceSprite(pID) + + if landType == lfIce then + placedLandFlags[pID] = "lfIce" + placedTint[pID] = 250 + (250*0x100) + (250*0x10000) + (0*0x1000000) -- A BGR + elseif landType == lfIndestructible then + placedLandFlags[pID] = "lfIndestructible" + placedTint[pID] = 250 + (0*0x100) + (0*0x10000) + (150*0x1000000) -- A BGR + elseif landType == lfBouncy then + placedLandFlags[pID] = "lfBouncy" + placedTint[pID] = 250 + (0*0x100) + (250*0x10000) + (0*0x1000000) -- A BGR + else + placedLandFlags[pID] = "lfNormal" + --placedTint[pID] = nil + placedTint[pID] = 255 + (255*0x100) + (255*0x10000) + (255*0x1000000) -- A BGR + end + + PlaceSprite(placedX[pID], placedY[pID], placedSprite[pID], placedFrame[pID], + placedTint[pID], + nil, -- overrite existing land + nil, nil, -- this stuff specifies flipping + landType) + +end + +function SelectClosestSprite() + + closestDist = 999999999 + closestSpriteID = nil -- just in case + + for i = 0, (placedCount-1) do + if (placedType[i] == loc("Girder Placement Mode")) + or (placedType[i] == loc("Rubber Placement Mode")) + or (placedType[i] == loc("Sprite Placement Mode")) + then + q = placedX[i] - placedX[placedCount] + w = placedY[i] - placedY[placedCount] + d = ( (q*q) + (w*w) ) + if d < closestDist then + closestDist = d + closestSpriteID = i + g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(sSprite) + + --newTint = placedTint[i] + newTint = 0xFF00FFFF + + SetVisualGearValues(sSprite, placedX[i], placedY[i], 0, 0, g5, placedFrame[i], 10000, placedSprite[i], 10000, newTint ) + + end + end + end + +end + +function EraseClosestSprite() + if closestSpriteID ~= nil then + EraseSprite(placedX[closestSpriteID], placedY[closestSpriteID], placedSprite[closestSpriteID], placedFrame[closestSpriteID], + nil, -- erase land only where the pixels match the land flag provided + nil, -- only erase the provided land flags. don't touch other land flags or LandPixels + nil, -- flip sprite horizontally + nil, -- flip sprite vertically + placedLandFlags[closestSpriteID]) + + placedX[closestSpriteID] = nil + placedY[closestSpriteID] = nil + placedSpec[closestSpriteID] = nil + --placedSuperSpec[closestSpriteID] = nil + placedType[closestSpriteID] = nil + placedTint[closestSpriteID] = nil + placedSprite[closestSpriteID] = nil + placedFrame[closestSpriteID] = nil + placedLandFlags[closestSpriteID] = nil + closestSpriteID = nil + SetVisualGearValues(sSprite, 0, 0, 0, 0, 0, 1, 10000, sprAmGirder, 10000, 0x00000000 ) + end +end + +-- work this into the above two functions and edit them, later +function EraseClosestWaypoint() + + closestDist = 999999999 + closestSpriteID = nil -- just in case + + for i = 0, (placedCount-1) do + if (placedType[i] == loc("Waypoint Placement Mode")) then + q = placedX[i] - placedX[placedCount] + w = placedY[i] - placedY[placedCount] + d = ( (q*q) + (w*w) ) + if d < closestDist then + closestDist = d + closestSpriteID = i + g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(sSprite) + + --newTint = placedTint[i] + newTint = 0xFF00FFFF + + SetVisualGearValues(sSprite, placedX[i], placedY[i], 0, 0, g5, placedFrame[i], 10000, placedSprite[i], 10000, newTint ) + + end + end + end + + if closestSpriteID ~= nil then + DeleteVisualGear(placedSpec[closestSpriteID]) + placedX[closestSpriteID] = nil + placedY[closestSpriteID] = nil + placedSpec[closestSpriteID] = nil + --placedSuperSpec[closestSpriteID] = nil + placedType[closestSpriteID] = nil + placedTint[closestSpriteID] = nil + placedSprite[closestSpriteID] = nil + placedFrame[closestSpriteID] = nil + placedLandFlags[closestSpriteID] = nil + closestSpriteID = nil + SetVisualGearValues(sSprite, 0, 0, 0, 0, 0, 1, 10000, sprAmGirder, 10000, 0x00000000 ) + end +end + + +-- essentially called when user clicks the mouse +-- with girders or an airattack +function PlaceObject(x,y) + + placedX[placedCount] = x + placedY[placedCount] = y + placedType[placedCount] = cat[cIndex] + placedSpec[placedCount] = pMode[pIndex] + --placedSuperSpec[placedCount] = nil + placedTint[placedCount] = nil + placedFrame[placedCount] = nil + placedLandFlags[placedCount] = nil + placedSprite[placedCount] = nil + placedHWMapFlag[placedCount] = nil + + if cat[cIndex] == loc("Girder Placement Mode") then + + if superDelete == false then + --lfObject and lfBasic + placedFrame[placedCount] = CGR + placedSprite[placedCount] = sprAmGirder + CallPlaceSprite(placedCount) + + if landType == lfIndestructible then specialMod = 1 + elseif landType == lfIce then specialMod = 2 + else specialMod = 0 + end + placedHWMapFlag[placedCount] = CGR+100+(8*specialMod) + else + placedType[placedCount] = "bogus" -- we need this so we don't think we've placed a new girder and are trying to erase the things we just placed?? + SelectClosestSprite() + EraseClosestSprite() + end + + elseif cat[cIndex] == loc("Rubber Placement Mode") then + + if superDelete == false then + placedFrame[placedCount] = CGR + placedSprite[placedCount] = sprAmRubber + + --CallPlaceSprite(placedCount) + --new ermagerd + placedLandFlags[placedCount] = "lfBouncy" + placedTint[placedCount] = 255 + (255*0x100) + (255*0x10000) + (255*0x1000000) -- A BGR + PlaceSprite(placedX[placedCount], placedY[placedCount], placedSprite[placedCount], placedFrame[placedCount], + placedTint[placedCount], + nil, + nil, nil, + landType) + + if CGR == 0 then placedHWMapFlag[placedCount] = 124 + elseif CGR == 1 then placedHWMapFlag[placedCount] = 125 + elseif CGR == 2 then placedHWMapFlag[placedCount] = 126 + elseif CGR == 3 then placedHWMapFlag[placedCount] = 127 + end + else + placedType[placedCount] = "bogus" + SelectClosestSprite() + EraseClosestSprite() + end + + elseif cat[cIndex] == loc("Target Placement Mode") then + gear = AddGear(x, y, gtTarget, 0, 0, 0, 0) + elseif cat[cIndex] == loc("Cleaver Placement Mode") then + gear = AddGear(x, y, gtKnife, 0, 0, 0, 0) + elseif cat[cIndex] == loc("Health Crate Placement Mode") then + gear = SpawnHealthCrate(x,y) + SetHealth(gear, pMode[pIndex]) + setGearValue(gear,"caseType","med") + elseif cat[cIndex] == loc("Weapon Crate Placement Mode") then + gear = SpawnAmmoCrate(x, y, atkArray[pIndex][1]) + placedSpec[placedCount] = atkArray[pIndex][2] + setGearValue(gear,"caseType","ammo") + setGearValue(gear,"contents",atkArray[pIndex][2]) + elseif cat[cIndex] == loc("Utility Crate Placement Mode") then + gear = SpawnUtilityCrate(x, y, utilArray[pIndex][1]) + placedSpec[placedCount] = utilArray[pIndex][2] + setGearValue(gear,"caseType","util") + setGearValue(gear,"contents",utilArray[pIndex][2]) + elseif cat[cIndex] == loc("Barrel Placement Mode") then + gear = AddGear(x, y, gtExplosives, 0, 0, 0, 0) + SetHealth(gear, pMode[pIndex]) + elseif cat[cIndex] == loc("Mine Placement Mode") then + gear = AddGear(x, y, gtMine, 0, 0, 0, 0) + SetTimer(gear, pMode[pIndex]) + elseif cat[cIndex] == loc("Sticky Mine Placement Mode") then + gear = AddGear(x, y, gtSMine, 0, 0, 0, 0) + elseif cat[cIndex] == loc("Air Mine Placement Mode") then + gear = AddGear(x, y, gtAirMine, 0, 0, 0, 0) + SetTimer(gear, pMode[pIndex]) + elseif cat[cIndex] == loc("Advanced Repositioning Mode") then + + if pMode[pIndex] == loc("Selection Mode") then + sGear = GetClosestGear() + elseif pMode[pIndex] == loc("Placement Mode") then + if sGear ~= nil then + SetGearPosition(sGear, x, y) + end + elseif pMode[pIndex] == loc("Deletion Mode") then + sGear = GetClosestGear() + if (sGear ~= nil) and (GetGearType(sGear) ~= gtHedgehog) then + DeleteGear(sGear) + sGear = nil + end + end + + elseif (cat[cIndex] == loc("Hog Identity Mode")) or (cat[cIndex] == loc("Team Identity Mode")) then + + sGear = GetClosestGear() + if (sGear ~= nil) and (GetGearType(sGear) == gtHedgehog) then + if (cat[cIndex] == loc("Hog Identity Mode")) then + SetHogProfile(sGear, pMode[pIndex]) + else -- set for the whole team + SetTeamIdentity(sGear) + end + else + AddCaption(loc("Please click on a hedgehog."),0xffba00ff,capgrpVolume) + end + + + + elseif cat[cIndex] == loc("Health Modification Mode") then + + sGear = GetClosestGear() + if (sGear ~= nil) and (GetGearType(sGear) == gtHedgehog) then + SetHealth(sGear, pMode[pIndex]) + else + AddCaption(loc("Please click on a hedgehog."),0xffba00ff,capgrpVolume) + end + + elseif cat[cIndex] == loc("Sprite Modification Mode") then + + SelectClosestSprite() + + if closestSpriteID ~= nil then + -- we have a sprite selected somewhere + --if pMode[pIndex] == "Sprite Selection Mode" then + -- sprite is now selected, good job + --elseif pMode[pIndex] == "LandFlag Modification Mode" then + if pMode[pIndex] == loc("LandFlag Modification Mode") then + EraseSprite(placedX[closestSpriteID], placedY[closestSpriteID], placedSprite[closestSpriteID], placedFrame[closestSpriteID], nil, nil, nil, nil, placedLandFlags[closestSpriteID]) + CallPlaceSprite(closestSpriteID) + closestSpriteID = nil + SetVisualGearValues(sSprite, 0, 0, 0, 0, 0, 1, 10000, sprAmGirder, 10000, 0x00000000 ) + elseif pMode[pIndex] == loc("Sprite Erasure Mode") then + + EraseClosestSprite() + + end + end + + + elseif cat[cIndex] == loc("Tagging Mode") then + + sGear = GetClosestGear() + if sGear ~= nil then -- used to be closestGear + + if getGearValue(sGear,"tag") == nil then + + if pMode[pIndex] == loc("Tag Collection Mode") then + if GetGearType(sGear) == gtCase then + setGearValue(sGear, "tag","collection") + else + AddCaption(loc("Please click on a crate."),0xffba00ff,capgrpVolume) + end + else + if pMode[pIndex] == loc("Tag Victory Mode") then + setGearValue(sGear, "tag","victory") + elseif pMode[pIndex] == loc("Tag Failure Mode") then + setGearValue(sGear, "tag","failure") + end + end + + else + -- remove tag and delete circ + setGearValue(sGear, "tag", nil) + DeleteVisualGear(getGearValue(sGear,"tCirc")) + setGearValue(sGear, "tCirc", nil) + end + + + + end + + + --elseif cat[cIndex] == loc("Sprite Testing Mode") then + + -- frameID = 0 + -- visualSprite = reducedSpriteIDArray[pIndex] + -- tempE = AddVisualGear(x, y, vgtStraightShot, 0, true,1) + -- g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(tempE) + -- SetVisualGearValues(tempE, g1, g2, 0, 0, g5, frameID, g7, visualSprite, g9, g10 ) + + + elseif cat[cIndex] == loc("Sprite Placement Mode") then + + if superDelete == false then + placedFrame[placedCount] = 1 + placedSprite[placedCount] = reducedSpriteIDArray[pIndex] + CallPlaceSprite(placedCount) + else + placedType[placedCount] = "bogus" + SelectClosestSprite() + EraseClosestSprite() + end + + elseif cat[cIndex] == loc("Waypoint Placement Mode") then + + + if pMode[pIndex] == loc("Waypoint Deletion Mode") then + EraseClosestWaypoint() + else + PlaceWaypoint(x,y) + placedCount = placedCount - 1 + end + + end + + placedCount = placedCount + 1 + +end + +-- called when user changes primary selection +-- either via up/down keys +-- or selecting girder/airattack +function RedefineSubset() + + superDelete = false -- fairly new addition + landType = 0 --- fairly new addition + pIndex = 1 + pMode = {} + + if cat[cIndex] == loc("Girder Placement Mode") then + pIndex = CGR + pMode = {loc("Girder")} + -- pCount = 1 + elseif cat[cIndex] == loc("Rubber Placement Mode") then + pIndex = CGR + pMode = {loc("Rubber")} + landType = lfBouncy -- for now, let's not allow anything else (-- fairly new addition) + -- pCount = 1??? + elseif cat[cIndex] == loc("Target Placement Mode") then + pMode = {loc("Standard Target")} + elseif cat[cIndex] == loc("Cleaver Placement Mode") then + pMode = {loc("Standard Cleaver")} + elseif cat[cIndex] == loc("Barrel Placement Mode") then + pMode = {1,50,75,100} + elseif cat[cIndex] == loc("Health Crate Placement Mode") then + pMode = {25,50,75,100} + elseif cat[cIndex] == loc("Weapon Crate Placement Mode") then + for i = 1, #atkArray do + pMode[i] = atkArray[i][4] --pMode[i] = atkArray[i][2] + end + elseif cat[cIndex] == loc("Utility Crate Placement Mode") then + for i = 1, #utilArray do + pMode[i] = utilArray[i][4] --pMode[i] = utilArray[i][2] + end + elseif cat[cIndex] == loc("Mine Placement Mode") then + pMode = {1,1000,2000,3000,4000,5000,0} + -- 0 is dud right, or is that nil? + elseif cat[cIndex] == loc("Sticky Mine Placement Mode") then + pMode = {loc("Normal Sticky Mine")} + elseif cat[cIndex] == loc("Air Mine Placement Mode") then + pMode = {1,1000,2000,3000,4000,5000,0} + elseif cat[cIndex] == loc("Advanced Repositioning Mode") then + pMode = {loc("Selection Mode"),loc("Placement Mode"), loc("Deletion Mode")} + elseif cat[cIndex] == loc("Tagging Mode") then + pMode = {loc("Tag Victory Mode"),loc("Tag Failure Mode"),loc("Tag Collection Mode")} + elseif cat[cIndex] == loc("Hog Identity Mode") then + pMode = {loc("Soldier"),loc("Grenadier"),loc("Sniper"),loc("Pyro"),loc("Ninja"),loc("Commander"),loc("Chef"),loc("Engineer"),loc("Physicist"),loc("Trapper"),loc("Saint"),loc("Clown")} + elseif cat[cIndex] == loc("Team Identity Mode") then + pMode = {"Clowns","Street Fighters","Cybernetic Empire","Color Squad","Fruit","The Police","The Ninja-Samurai Alliance","Pokemon","The Zoo","The Devs","Mushroom Kingdom","Pirates","Gangsters","Twenty-Twenty","Monsters","The Iron Curtain","The Hospital"} + elseif cat[cIndex] == loc("Health Modification Mode") then + pMode = {1, 25, 30, 50, 75, 100, 120, 150, 200, 1000} + elseif cat[cIndex] == loc("Sprite Modification Mode") then + --pMode = {"Sprite Selection Mode","LandFlag Modification Mode","Sprite Erasure Mode"} + pMode = {loc("LandFlag Modification Mode"),loc("Sprite Erasure Mode")} + elseif cat[cIndex] == loc("Sprite Testing Mode") or cat[cIndex] == loc("Sprite Placement Mode") then + --for i = 1, #spriteTextArray do + -- pMode[i] = spriteTextArray[i] + --end + for i = 1, #reducedSpriteTextArray do + pMode[i] = reducedSpriteTextArray[i] + end + elseif cat[cIndex] == loc("Waypoint Placement Mode") then + pMode = {loc("Standard Waypoint"), loc("Waypoint Deletion Mode")} + end + +end + +------------------------------------------------ +-- LOADING AND SAVING DATA STUFF +------------------------------------------------ + +-- paste data you have saved previously here +function LoadLevelData() + + if (mapID == nil) or (mapID == 0) then + LoadMap(1) + else + LoadMap(mapID) + end + + for i = 1, techCount-1 do + PlaceWaypoint(techX[i],techY[i]) + end + +end + +-- When you save your level, this function +-- generates the AddTeam and AddHog function calls for onGameInit() +function GetDataForSavingHogs(gear) + + --AddTeam(teamname, color, grave, fort, voicepack, flag) + --AddHog(hogname, botlevel, health, hat) + + --this is a quick hack so that the human team(s) will always be + --given the first move ahead of the AI + tempDataList = {} + if GetHogLevel(gear) == 0 then + tempDataList = hogDataList + else + tempDataList = AIHogDataList + end + + if GetHogTeamName(gear) ~= lastRecordedTeam then + + teamCounter = teamCounter + 1 + if teamCounter == 9 then + teamCounter = 1 + end + + -- try match team colour to the colours recorded in the colour array + + tColor = 0x00000000 + for i = 1, #colorArray do + if GetClanColor(GetHogClan(gear)) == colorArray[i][1] then + tColor = colorArray[i][2] + end + end + + -- no match, just give him a default colour from the array, then + if tColor == 0x00000000 then + tColor = colorArray[teamCounter][2] + end + + + -- there is used to be no way to read this data, so + -- I was assigning teams a random grave, fort, flag and voice + -- but now we should be able to get the real thing + -- so let's do it if they haven't used one of the preset teams + if getGearValue(gear,"grave") == nil then + tFort = fortArray[1+GetRandom(#fortArray)] + tGrave = GetHogGrave(gear) + tFlag = GetHogFlag(gear) + tVoice = GetHogVoicepack(gear) + --tGrave = graveArray[1+GetRandom(#graveArray)] + --tFlag = flagArray[1+GetRandom(#flagArray)] + --tVoice = voiceArray[1+GetRandom(#voiceArray)] + else + tGrave = getGearValue(gear,"grave") + tFort = getGearValue(gear,"fort") + tFlag = getGearValue(gear,"flag") + tVoice = getGearValue(gear,"voice") + end + + lastRecordedTeam = GetHogTeamName(gear) + + table.insert(tempDataList, "") + table.insert (tempDataList, + " AddTeam(\"" .. + GetHogTeamName(gear) .."\"" .. + ", " .. "\"" ..tColor .. "\"" .. + -- --", " .. colorArray[teamCounter][2] .. + ", " .. "\"" .. tGrave .. "\"" .. + ", " .. "\"" .. tFort .. "\"" .. + ", " .. "\"" .. tVoice .. "\"" .. + ", " .. "\"" .. tFlag .. "\"" .. + ")" + ) + + end + + table.insert(hhs, gear) + + table.insert (tempDataList, " hhs[" .. #hhs .."] = AddHog(\"" .. + GetHogName(gear) .. "\", " .. + GetHogLevel(gear) .. ", " .. + GetHealth(gear) .. ", \"" .. + GetHogHat(gear) .. "\"" .. + ")" + ) + + table.insert (tempDataList," SetGearPosition(hhs[" .. #hhs .. "], " .. GetX(gear) .. ", " .. GetY(gear) .. ")") + + if getGearValue(gear,"tag") ~= nil then + table.insert (tempDataList," setGearValue(hhs[" .. #hhs .. "], \"tag\", \"" .. getGearValue(gear,"tag") .. "\")") + end + + -- save the ammo values for each gear, we will call this later + -- when we want to output it to console + + if getGearValue(gear,"ranking") ~= nil then + table.insert(shoppaPointList, "AddShoppaPoint(" .. GetX(gear) .. ", " .. GetY(gear) .. ", " .. getGearValue(gear,"ranking") .. ")") + end + + for i = 1, #atkArray do + setGearValue(gear, atkArray[i][1], GetAmmoCount(gear, atkArray[i][1])) + end + + for i = 1, #utilArray do + setGearValue(gear, utilArray[i][1], GetAmmoCount(gear, utilArray[i][1])) + end + + if GetHogLevel(gear) == 0 then + hogDataList = tempDataList + else + AIHogDataList = tempDataList + end + +end + +-- output hog and team data to the console +function SaveHogData() + + runOnHogs(GetDataForSavingHogs) + + WriteLnToConsole(" ------ TEAM LIST ------") + + for i = 1, #hogDataList do + WriteLnToConsole(hogDataList[i]) + end + + for i = 1, #AIHogDataList do + WriteLnToConsole(AIHogDataList[i]) + end + + WriteLnToConsole("") + + if #shoppaPointList > 0 then + WriteLnToConsole(" ------ SHOPPA POINT LIST ------") + for i = 1, #shoppaPointList do + WriteLnToConsole(shoppaPointList[i]) + end + end + + +end + +-- generates an onGameInit() template with scheme data, team adds, and hogs +function SaveConfigData() + + WriteLnToConsole("function onGameInit()") + WriteLnToConsole("") + + temp = " EnableGameFlags(gfDisableWind" + for i = 1, #gameFlagList do + if gameFlagList[i][2] == true then + temp = temp .. ", ".. gameFlagList[i][1] + end + end + + WriteLnToConsole(" ClearGameFlags()") + WriteLnToConsole(temp .. ")") + + WriteLnToConsole(" Map = \"" .. Map .. "\"") + WriteLnToConsole(" Theme = \"" .. "Nature" .. "\"") + WriteLnToConsole(" TurnTime = " .. TurnTime) + WriteLnToConsole(" Explosives = " .. Explosives) + WriteLnToConsole(" MinesNum = " .. MinesNum) + WriteLnToConsole(" CaseFreq = " .. CaseFreq) + WriteLnToConsole(" Delay = " .. Delay) + + WriteLnToConsole(" HealthCaseProb = " .. HealthCaseProb) + WriteLnToConsole(" HealthCaseAmount = " .. HealthCaseAmount) + WriteLnToConsole(" DamagePercent = " .. DamagePercent) + WriteLnToConsole(" MinesTime = " .. MinesTime) + WriteLnToConsole(" MineDudPercent = " .. MineDudPercent) + WriteLnToConsole(" SuddenDeathTurns = " .. SuddenDeathTurns) + WriteLnToConsole(" WaterRise = " .. WaterRise) + WriteLnToConsole(" HealthDecrease = " .. HealthDecrease) + + --WriteLnToConsole(" Ready = " .. Ready) + --WriteLnToConsole(" AirMinesNum = " .. AirMinesNum) + --WriteLnToConsole(" ScriptParam = " .. ScriptParam) + --WriteLnToConsole(" GetAwayTime = " .. GetAwayTime) + + WriteLnToConsole("") + + SaveHogData() + + WriteLnToConsole("") + WriteLnToConsole("end") + +end + +-- output gear data as special points to be placed in a converted HWMAP, readable by InterpretPoints() +function ConvertGearDataToHWPText() + + WriteLnToConsole("") + WriteLnToConsole("--BEGIN HWMAP CONVERTER POINTS--") + WriteLnToConsole("-- You can paste this data into the HWMAP converter if needed.") + WriteLnToConsole("--[[") + WriteLnToConsole("") + + for i = 1, #hFlagList do + WriteLnToConsole(hFlagList[i]) + end + + WriteLnToConsole("") + WriteLnToConsole("]]") + WriteLnToConsole("--END HWMAP CONVERTER POINTS--") + WriteLnToConsole("") + +end + +-- sigh +-- gradually got more bloated with the addition of hwpoint tracking and +-- distinction betweeen the need to track victory/win conditions or not +function GetDataForGearSaving(gear) + + temp = nil + specialFlag = nil + arrayList = nil + + if GetGearType(gear) == gtMine then + + if (getGearValue(gear, "tag") ~= nil) then + temp = " tempG = AddGear(" .. + GetX(gear) .. ", " .. + GetY(gear) .. ", gtMine, 0, 0, 0, 0)" + table.insert(mineList, temp) + table.insert(mineList, " SetTimer(tempG, " .. GetTimer(gear) .. ")") + table.insert(mineList, " setGearValue(tempG, \"tag\", \"" .. getGearValue(gear,"tag") .. "\")") + else + + temp = " SetTimer(" .. "AddGear(" .. + GetX(gear) .. ", " .. + GetY(gear) .. ", gtMine, 0, 0, 0, 0)" .. ", " .. + GetTimer(gear) ..")" + table.insert(mineList, temp) + + end + + if GetTimer(gear) == 1 then specialFlag = 1 + elseif GetTimer(gear) == 1000 then specialFlag = 2 + elseif GetTimer(gear) == 2000 then specialFlag = 3 + elseif GetTimer(gear) == 3000 then specialFlag = 4 + elseif GetTimer(gear) == 4000 then specialFlag = 5 + elseif GetTimer(gear) == 5000 then specialFlag = 6 + end + + elseif GetGearType(gear) == gtSMine then + + arrayList = sMineList + temp = " tempG = AddGear(" .. + GetX(gear) .. ", " .. + GetY(gear) .. ", gtSMine, 0, 0, 0, 0)" + table.insert(sMineList, temp) + specialFlag = 7 + + elseif GetGearType(gear) == gtAirMine then + + if (getGearValue(gear, "tag") ~= nil) then + temp = " tempG = AddGear(" .. + GetX(gear) .. ", " .. + GetY(gear) .. ", gtAirMine, 0, 0, 0, 0)" + table.insert(airMineList, temp) + table.insert(airMineList, " SetTimer(tempG, " .. GetTimer(gear) .. ")") + table.insert(airMineList, " setGearValue(tempG, \"tag\", \"" .. getGearValue(gear,"tag") .. "\")") + else + + temp = " SetTimer(" .. "AddGear(" .. + GetX(gear) .. ", " .. + GetY(gear) .. ", gtAirMine, 0, 0, 0, 0)" .. ", " .. + GetTimer(gear) ..")" + table.insert(airMineList, temp) + + end + + table.insert(previewDataList, " PreviewPlacedGear(" .. GetX(gear) ..", " .. GetY(gear) .. ")") + specialFlag = 8 + + elseif GetGearType(gear) == gtExplosives then + + if (getGearValue(gear, "tag") ~= nil) then + temp = " tempG = AddGear(" .. + GetX(gear) .. ", " .. + GetY(gear) .. ", gtExplosives, 0, 0, 0, 0)" + table.insert(explosivesList, temp) + table.insert(explosivesList, " SetHealth(tempG, " .. GetHealth(gear) .. ")") + table.insert(explosivesList, " setGearValue(tempG, \"tag\", \"" .. getGearValue(gear,"tag") .. "\")") + else + + temp = " SetHealth(" .. "AddGear(" .. + GetX(gear) .. ", " .. + GetY(gear) .. ", gtExplosives, 0, 0, 0, 0)" .. ", " .. + GetHealth(gear) ..")" + table.insert(explosivesList, temp) + + end + + table.insert(previewDataList, " PreviewPlacedGear(" .. GetX(gear) ..", " .. GetY(gear) .. ")") + + if GetHealth(gear) == 1 then specialFlag = 15 + elseif GetHealth(gear) == 25 then specialFlag = 16 + elseif GetHealth(gear) == 50 then specialFlag = 17 + elseif GetHealth(gear) == 75 then specialFlag = 18 + elseif GetHealth(gear) == 100 then specialFlag = 19 + end + + elseif GetGearType(gear) == gtTarget then + + arrayList = targetList + temp = " tempG = AddGear(" .. + GetX(gear) .. ", " .. + GetY(gear) .. ", gtTarget, 0, 0, 0, 0)" + table.insert(targetList, temp) + specialFlag = 14 + + elseif GetGearType(gear) == gtKnife then + + arrayList = knifeList + temp = " tempG = AddGear(" .. + GetX(gear) .. ", " .. + GetY(gear) .. ", gtKnife, 0, 0, 0, 0)" + table.insert(knifeList, temp) + specialFlag = 13 + + elseif GetGearType(gear) == gtCase then + + table.insert(previewDataList, " PreviewPlacedGear(" .. GetX(gear) ..", " .. GetY(gear) .. ")") + + if (GetHealth(gear) ~= nil) and (GetHealth(gear) ~= 0) then + + if (getGearValue(gear, "tag") ~= nil) then + temp = " tempG = SpawnHealthCrate(" .. + GetX(gear) ..", " .. + GetY(gear) .. + ")" + table.insert(healthCrateList, temp) + table.insert(healthCrateList, " SetHealth(tempG, " .. GetHealth(gear) .. ")") + table.insert(healthCrateList, " setGearValue(tempG, \"tag\", \"" .. getGearValue(gear,"tag") .. "\")") + else + temp = " SetHealth(SpawnHealthCrate(" .. + GetX(gear) ..", " .. + GetY(gear) .. + "), " .. + GetHealth(gear) ..")" + table.insert(healthCrateList, temp) + end + + if GetHealth(gear) == 25 then specialFlag = 9 + elseif GetHealth(gear) == 50 then specialFlag = 10 + elseif GetHealth(gear) == 75 then specialFlag = 11 + elseif GetHealth(gear) == 100 then specialFlag = 12 + end + + elseif getGearValue(gear,"caseType") == "ammo" then + + arrayList = wepCrateList + temp = " tempG = SpawnAmmoCrate(" .. + GetX(gear) ..", " .. + GetY(gear) ..", " .. + getGearValue(gear,"contents") .. + ")" + table.insert(wepCrateList, temp) + + tempV = getGearValue(gear,"contents") + for i = 1, #atkArray do + if tempV == atkArray[i][2] then + specialFlag = i + 19 + end + end + + --dammit, we probably need two more entries if we want to allow editing of existing maps + table.insert(wepCrateList, " setGearValue(tempG, \"caseType\", \"" .. getGearValue(gear,"caseType") .. "\")") + table.insert(wepCrateList, " setGearValue(tempG, \"contents\", \"" .. getGearValue(gear,"contents") .. "\")") + + + elseif getGearValue(gear,"caseType") == "util" then + + arrayList = utilCrateList + temp = " tempG = SpawnUtilityCrate(" .. + GetX(gear) ..", " .. + GetY(gear) ..", " .. + getGearValue(gear,"contents") .. + ")" + table.insert(utilCrateList, temp) + + tempV = getGearValue(gear,"contents") + for i = 1, #utilArray do + if tempV == utilArray[i][2] then + specialFlag = i + 19 + #atkArray + end + end + + --dammit, we probably need two more entries if we want to allow editing of existing maps + table.insert(utilCrateList, " setGearValue(tempG, \"caseType\", \"" .. getGearValue(gear,"caseType") .. "\")") + table.insert(utilCrateList, " setGearValue(tempG, \"contents\", \"" .. getGearValue(gear,"contents") .. "\")") + + end + + end + + -- add tracking of simple win/lose for simpler gears that have a tempG = listed above + if (getGearValue(gear, "tag") ~= nil) and (arrayList ~= nil) then + table.insert(arrayList, " setGearValue(tempG, \"tag\", \"" .. getGearValue(gear,"tag") .. "\")") + end + + -- this creates a big, messy list of special flags for use in hwmaps + if specialFlag ~= nil then + table.insert(hFlagList, " " .. GetX(gear) .. " " .. GetY(gear) .. " " .. specialFlag) + end + +end + +-- generate a title and list all the gears if there is at least 1 of them in the list +function AppendGearList(gearList, consoleLine) + if #gearList > 0 then + WriteLnToConsole(consoleLine) + for i = 1, #gearList do + WriteLnToConsole(gearList[i]) + end + WriteLnToConsole("") + end +end + +-- new attempt at doing shit a bit cleaner: +-- it may be a bit verbose, but this should generate a comprehensive, human-readable +-- list of gears, broken up into sections and output it to the console +function SaveGearData() + + runOnGears(GetDataForGearSaving) + + AppendGearList(healthCrateList, " ------ HEALTH CRATE LIST ------") + AppendGearList(wepCrateList, " ------ AMMO CRATE LIST ------") + AppendGearList(utilCrateList, " ------ UTILITY CRATE LIST ------") + AppendGearList(explosivesList, " ------ BARREL LIST ------") + AppendGearList(mineList, " ------ MINE LIST ------") + AppendGearList(sMineList, " ------ STICKY MINE LIST ------") + AppendGearList(airMineList, " ------ AIR MINE LIST ------") + AppendGearList(targetList, " ------ TARGET LIST ------") + AppendGearList(knifeList, " ------ CLEAVER LIST ------") + +end + +function DoAmmoLoop(i) + + for x = 1, #atkArray do + if getGearValue(hhs[i],atkArray[x][1]) ~= 0 then + WriteLnToConsole(" AddAmmo(hhs[" .. i .. "], " .. atkArray[x][2] .. ", " .. getGearValue(hhs[i],atkArray[x][1]) .. ")") + end + end + + for x = 1, #utilArray do + if getGearValue(hhs[i],utilArray[x][1]) ~= 0 then + WriteLnToConsole(" AddAmmo(hhs[" .. i .. "], " .. utilArray[x][2] .. ", " .. getGearValue(hhs[i],utilArray[x][1]) .. ")") + end + end + + WriteLnToConsole("") + +end + +-- this is called when a tagged gear is deleted during a mission +-- it determines if the game is ready to conclude in victory/defeat +function CheckForConclusion(gear) + + -- failure gears must always all be protected, so if any of them are destroyed the player loses + if getGearValue(gear,"tag") == "failure" then + EndGameIn("failure") + else + + -- the presence of other tagged gears means that the goal of this mission is not + -- simply to kill every hedgehog. Thus, we need to count the remaining tagged objects + -- to see how close we are to completing the mission successfully. + victoryObj = 0 + failObj = 0 + collectObj = 0 + runOnGears(CheckForConditions) + + if GetGearType(gear) ~= gtCase then + + -- non-crates can only be tagged as victory or failure, and as this wasn't tagged + -- "failure" in our earlier check, this must be a victory tagged gear. Let's adust + -- the number of objects accordingly as it's in the process of being destroyed. + victoryObj = victoryObj - 1 + + -- if there are no objectives left to complete, end the game in victory + if (victoryObj == 0) and (collectObj == 0) then + EndGameIn("victory") + end + + else + -- this crate was deleted, but was it collected or destroyed, and how does that match + -- the goals of our mission? + if (GetGearMessage(gear) == 256) and (getGearValue(gear,"tag") == "collection") then + if GetHogLevel(CurrentHedgehog) == 0 then + -- the enemy stole our crate + EndGameIn("failure") + else + collectObj = collectObj - 1 + if (victoryObj == 0) and (collectObj == 0) then + EndGameIn("victory") + end + end + elseif (GetGearMessage(gear) == 0) and (getGearValue(gear,"tag") == "victory") then + victoryObj = victoryObj - 1 + if (victoryObj == 0) and (collectObj == 0) then + EndGameIn("victory") + end + else + -- unfortunately, we messed up our mission. + EndGameIn("failure") + end + + end + + end + +end + +--------------------------------- +-- THE BIG ONE +--------------------------------- +-- saving process starts here +-- saves all level data to logs/game0.log and generates a simple script template +function SaveLevelData() + + WriteLnToConsole("------ BEGIN SCRIPT ------") + WriteLnToConsole("-- Copy and Paste this text into an empty text file, and save it as") + WriteLnToConsole("-- YOURTITLEHERE.lua, in your Data/Missions/Training/ folder.") + + WriteLnToConsole("") + + WriteLnToConsole("HedgewarsScriptLoad(\"/Scripts/Locale.lua\")") + WriteLnToConsole("HedgewarsScriptLoad(\"/Scripts/Tracker.lua\")") + + WriteLnToConsole("") + WriteLnToConsole("local hhs = {}") + --WriteLnToConsole("local ufoGear = nil") + WriteLnToConsole("") + + WriteLnToConsole("local wepArray = {") + WriteLnToConsole(" amBazooka, amBee, amMortar, amDrill, amSnowball,") + WriteLnToConsole(" amGrenade, amClusterBomb, amMolotov, amWatermelon, amHellishBomb, amGasBomb,") + WriteLnToConsole(" amShotgun, amDEagle, amSniperRifle, amSineGun, amLandGun, amIceGun,") + WriteLnToConsole(" amFirePunch, amWhip, amBaseballBat, amKamikaze, amSeduction, amHammer,") + WriteLnToConsole(" amMine, amDynamite, amCake, amBallgun, amRCPlane, amSMine, amAirMine,") + WriteLnToConsole(" amAirAttack, amMineStrike, amDrillStrike, amNapalm, amPiano, amBirdy,") + WriteLnToConsole(" amBlowTorch, amPickHammer, amGirder, amRubber, amPortalGun,") + WriteLnToConsole(" amRope, amParachute, amTeleport, amJetpack,") + WriteLnToConsole(" amInvulnerable, amLaserSight, amVampiric,") + WriteLnToConsole(" amLowGravity, amExtraDamage, amExtraTime, amResurrector, amTardis, amSwitch") + WriteLnToConsole(" }") + WriteLnToConsole("") + + + SaveConfigData() + + + WriteLnToConsole("") + WriteLnToConsole("function LoadHogWeapons()") + WriteLnToConsole("") + + if band(GameFlags, gfPerHogAmmo) ~= 0 then -- per hog ammo + for i = 1, #hhs do + DoAmmoLoop(i) + end + + else -- team-based ammo + + teamCounter = 0 + lastRecordedTeam = "" + for i = 1, #hhs do + + if GetHogTeamName(hhs[i]) ~= lastRecordedTeam then + lastRecordedTeam = GetHogTeamName(hhs[i]) + teamCounter = teamCounter + 1 + if teamCounter == 9 then + teamCounter = 1 + end + DoAmmoLoop(i) + end + + end + + end + + + WriteLnToConsole("end") + WriteLnToConsole("") + + WriteLnToConsole("") + WriteLnToConsole("function LoadSprite(pX, pY, pSprite, pFrame, pTint, p1, p2, p3, pLandFlags)") + WriteLnToConsole(" PlaceSprite(pX, pY, pSprite, pFrame, pTint, p1, p2, p3, pLandFlags)") + WriteLnToConsole("end") + WriteLnToConsole("") + + WriteLnToConsole("") + WriteLnToConsole("function LoadGearData()") + WriteLnToConsole("") + + WriteLnToConsole(" --BEGIN CORE DATA--") + WriteLnToConsole("") + + WriteLnToConsole(" ------ PORTAL DISTANCE and UFO FUEL ------") + WriteLnToConsole(" ufoFuel = " .. ufoFuel) + WriteLnToConsole(" portalDistance = " .. portalDistance*5) + table.insert(hFlagList, " " .. portalDistance*5 .. " " .. ufoFuel .. " " .. 98) + WriteLnToConsole("") + + for i = 0, (placedCount-1) do + if placedType[i] == loc("Waypoint Placement Mode") then + table.insert(waypointList, + " AddWayPoint(" .. + placedX[i] ..", " .. + placedY[i] ..")" + ) + table.insert(hFlagList, " " .. placedX[i] .. " " .. placedY[i] .. " " .. "0") + table.insert(previewDataList, " PreviewWayPoint(" .. placedX[i] ..", " .. placedY[i] .. ")") + end + end + + for i = 0, (placedCount-1) do + if placedType[i] == loc("Girder Placement Mode") then + table.insert(girderList, + " LoadSprite(" .. + placedX[i] ..", " .. + placedY[i] ..", sprAmGirder, " .. + placedFrame[i] .. -- the rotation/frame + ", " .. + placedTint[i] ..", " .. -- "nil, " .. -- color + "nil, nil, nil, " .. + placedLandFlags[i] .. ")" --the landType + ) + table.insert(hFlagList, " " .. placedX[i] .. " " .. placedY[i] .. " " .. placedHWMapFlag[i]) + table.insert(previewDataList, " PreviewGirder(" .. placedX[i] ..", " .. placedY[i] .. ", " .. placedFrame[i] .. ")") + end + end + + for i = 0, (placedCount-1) do + if placedType[i] == loc("Rubber Placement Mode") then + table.insert(rubberList, + " LoadSprite(" .. + placedX[i] ..", " .. + placedY[i] ..", sprAmRubber, " .. + placedFrame[i] .. + ", " .. + placedTint[i] ..", " .. -- "nil, " .. -- color + "nil, nil, nil, " .. + "lfBouncy)" --placedLandFlags[i] .. ")" --the landType + ) + table.insert(hFlagList, " " .. placedX[i] .. " " .. placedY[i] .. " " .. placedHWMapFlag[i]) + table.insert(previewDataList, " PreviewRubber(" .. placedX[i] ..", " .. placedY[i] .. ", " .. placedFrame[i] .. ")") + end + end + + for i = 0, (placedCount-1) do + if placedType[i] == loc("Sprite Placement Mode") then + table.insert(spriteList, + " LoadSprite(" .. + placedX[i] ..", " .. + placedY[i] ..", " .. placedSprite[i] .. ", " .. + placedFrame[i] .. -- I think this is the frame, can't remember + ", " .. + placedTint[i] ..", " .. -- "nil, " .. -- color + "nil, nil, nil, " .. + placedLandFlags[i] .. ")" --the landType + ) + end + end + + AppendGearList(waypointList, " ------ WAYPOINT LIST ------") + AppendGearList(girderList, " ------ GIRDER LIST ------") + AppendGearList(rubberList, " ------ RUBBER LIST ------") + AppendGearList(spriteList, " ------ SPRITE LIST ------") + + SaveGearData() + + WriteLnToConsole(" --END CORE DATA--") + + + WriteLnToConsole("") + WriteLnToConsole(" LoadHogWeapons()") + WriteLnToConsole("") + WriteLnToConsole("end") + WriteLnToConsole("") + + WriteLnToConsole("") + WriteLnToConsole("function onGameStart()") + WriteLnToConsole("") + WriteLnToConsole(" LoadGearData()") + WriteLnToConsole(" DetermineMissionGoal()") + WriteLnToConsole("") + WriteLnToConsole("end") + WriteLnToConsole("") + + WriteLnToConsole("") + WriteLnToConsole("function onNewTurn()") + WriteLnToConsole(" --insert code according to taste") + WriteLnToConsole("end") + WriteLnToConsole("") + + WriteLnToConsole("") + WriteLnToConsole("function onGameTick()") + WriteLnToConsole(" runOnGears(UpdateTagCircles)") + WriteLnToConsole("end") + WriteLnToConsole("") + + WriteLnToConsole("function UpdateTagCircles(gear)") + WriteLnToConsole(" if getGearValue(gear,\"tag\") ~= nil then") + WriteLnToConsole(" if getGearValue(gear,\"tCirc\") == nil then") + WriteLnToConsole(" setGearValue(gear, \"tCirc\",AddVisualGear(0,0,vgtCircle,0,true))") + WriteLnToConsole(" end") + WriteLnToConsole("") + WriteLnToConsole(" if getGearValue(gear,\"tag\") == \"victory\" then") + WriteLnToConsole(" SetVisualGearValues(getGearValue(gear,\"tCirc\"), GetX(gear), GetY(gear), 100, 255, 1, 10, 0, 150, 3, 0xff0000ff)") + WriteLnToConsole(" elseif getGearValue(gear,\"tag\") == \"failure\" then") + WriteLnToConsole(" SetVisualGearValues(getGearValue(gear,\"tCirc\"), GetX(gear), GetY(gear), 100, 255, 1, 10, 0, 150, 3, 0x00ff00ff)") + WriteLnToConsole(" elseif getGearValue(gear,\"tag\") == \"collection\" then") + WriteLnToConsole(" SetVisualGearValues(getGearValue(gear,\"tCirc\"), GetX(gear), GetY(gear), 100, 255, 1, 10, 0, 150, 3, 0x0000ffff)") + WriteLnToConsole(" end") + WriteLnToConsole(" end") + WriteLnToConsole("end") + WriteLnToConsole("") + + WriteLnToConsole("function CheckForConditions(gear)") + WriteLnToConsole(" if getGearValue(gear,\"tag\") == \"victory\" then") + WriteLnToConsole(" victoryObj = victoryObj +1") + WriteLnToConsole(" elseif getGearValue(gear,\"tag\") == \"failure\" then") + WriteLnToConsole(" failObj = failObj +1") + WriteLnToConsole(" elseif getGearValue(gear,\"tag\") == \"collection\" then") + WriteLnToConsole(" collectObj = collectObj +1") + WriteLnToConsole(" end") + WriteLnToConsole("end") + WriteLnToConsole("") + + WriteLnToConsole("function CheckForConclusion(gear)") + WriteLnToConsole("") + WriteLnToConsole(" if getGearValue(gear,\"tag\") == \"failure\" then ") + WriteLnToConsole(" EndGameIn(\"failure\")") + WriteLnToConsole(" else ") + WriteLnToConsole("") + WriteLnToConsole(" victoryObj = 0") + WriteLnToConsole(" failObj = 0") + WriteLnToConsole(" collectObj = 0") + WriteLnToConsole(" runOnGears(CheckForConditions)") + WriteLnToConsole("") + WriteLnToConsole(" if GetGearType(gear) ~= gtCase then") + WriteLnToConsole("") + WriteLnToConsole(" victoryObj = victoryObj - 1 ") + WriteLnToConsole("") + WriteLnToConsole(" if (victoryObj == 0) and (collectObj == 0) then") + WriteLnToConsole(" EndGameIn(\"victory\")") + WriteLnToConsole(" end") + WriteLnToConsole("") + WriteLnToConsole(" else") + WriteLnToConsole("") + WriteLnToConsole(" if (GetGearMessage(gear) == 256) and (getGearValue(gear,\"tag\") == \"collection\") then ") + WriteLnToConsole(" if GetHogLevel(CurrentHedgehog) ~= 0 then") + WriteLnToConsole(" EndGameIn(\"failure\")") + WriteLnToConsole(" else") + WriteLnToConsole(" collectObj = collectObj - 1") + WriteLnToConsole(" if (victoryObj == 0) and (collectObj == 0) then") + WriteLnToConsole(" EndGameIn(\"victory\")") + WriteLnToConsole(" end") + WriteLnToConsole(" end") + WriteLnToConsole(" elseif (GetGearMessage(gear) == 0) and (getGearValue(gear,\"tag\") == \"victory\") then") + WriteLnToConsole(" victoryObj = victoryObj - 1") + WriteLnToConsole(" if (victoryObj == 0) and (collectObj == 0) then ") + WriteLnToConsole(" EndGameIn(\"victory\")") + WriteLnToConsole(" end") + WriteLnToConsole(" else") + WriteLnToConsole(" EndGameIn(\"failure\")") + WriteLnToConsole(" end") + WriteLnToConsole("") + WriteLnToConsole(" end") + WriteLnToConsole("") + WriteLnToConsole(" end") + WriteLnToConsole("") + WriteLnToConsole("end") + WriteLnToConsole("") + + WriteLnToConsole("function DetermineMissionGoal()") + WriteLnToConsole("") + WriteLnToConsole(" victoryObj = 0") + WriteLnToConsole(" failObj = 0") + WriteLnToConsole(" collectObj = 0") + WriteLnToConsole(" vComment = \"\"") + WriteLnToConsole(" fComment = \"\"") + WriteLnToConsole(" collectComment = \"\"") + WriteLnToConsole("") + WriteLnToConsole(" runOnGears(CheckForConditions)") + WriteLnToConsole("") + WriteLnToConsole(" if victoryObj > 0 then ") + WriteLnToConsole(" if victoryObj == 1 then ") + WriteLnToConsole(" vComment = loc(\"Destroy the red target\")") + WriteLnToConsole(" else ") + WriteLnToConsole(" vComment = loc(\"Destroy the red targets\")") + WriteLnToConsole(" end") +-- WriteLnToConsole(" else") +-- WriteLnToConsole(" vComment = loc(\"Destroy the enemy.\")") + WriteLnToConsole(" end") + WriteLnToConsole("") + WriteLnToConsole(" if collectObj > 0 then ") + WriteLnToConsole(" if collectObj == 1 then ") + WriteLnToConsole(" collectComment = loc(\"Collect the blue target\")") + WriteLnToConsole(" else ") + WriteLnToConsole(" collectComment = loc(\"Collect all the blue targets\")") + WriteLnToConsole(" end") + WriteLnToConsole(" end") + WriteLnToConsole("") + WriteLnToConsole(" if (collectObj == 0) and (victoryObj == 0) then") + WriteLnToConsole(" vComment = loc(\"Destroy the enemy.\")") + WriteLnToConsole(" end") + WriteLnToConsole("") + WriteLnToConsole(" if failObj > 0 then ") + WriteLnToConsole(" if failObj == 1 then ") + WriteLnToConsole(" fComment = loc(\"The green target must survive\")") + WriteLnToConsole(" else ") + WriteLnToConsole(" fComment = loc(\"The green targets must survive\")") + WriteLnToConsole(" end") + WriteLnToConsole(" end") + WriteLnToConsole("") + WriteLnToConsole(" ShowMission(loc(\"User Challenge\"), loc(\"Mission Goals\") .. \":\", collectComment .. \"|\" .. vComment .. \"|\" .. fComment, 0, 0)") + WriteLnToConsole("") + WriteLnToConsole("end") + + WriteLnToConsole("") + WriteLnToConsole("function isATrackedGear(gear)") + WriteLnToConsole(" if (GetGearType(gear) == gtHedgehog) or") + WriteLnToConsole(" (GetGearType(gear) == gtExplosives) or") + WriteLnToConsole(" (GetGearType(gear) == gtMine) or") + WriteLnToConsole(" (GetGearType(gear) == gtSMine) or") + WriteLnToConsole(" (GetGearType(gear) == gtAirMine) or") + WriteLnToConsole(" (GetGearType(gear) == gtTarget) or") + WriteLnToConsole(" (GetGearType(gear) == gtKnife) or") + WriteLnToConsole(" (GetGearType(gear) == gtPortal) or") + WriteLnToConsole(" (GetGearType(gear) == gtCase)") + WriteLnToConsole(" then") + WriteLnToConsole(" return(true)") + WriteLnToConsole(" else") + WriteLnToConsole(" return(false)") + WriteLnToConsole(" end") + WriteLnToConsole("end") + WriteLnToConsole("") + + WriteLnToConsole("") + WriteLnToConsole("function onGearAdd(gear)") + + --WriteLnToConsole(" if GetGearType(gear) == gtJetpack then") + --WriteLnToConsole(" ufoGear = gear") + --WriteLnToConsole(" if (ufoFuel ~= 0) then") + --WriteLnToConsole(" SetHealth(ufoGear, ufoFuel)") + --WriteLnToConsole(" end") + --WriteLnToConsole(" end") + + WriteLnToConsole(" if isATrackedGear(gear) then") + WriteLnToConsole(" trackGear(gear)") + --WriteLnToConsole(" if GetGearType(gear) == gtPortal then") + --WriteLnToConsole(" setGearValue(gear,\"life\",portalDistance)") + --WriteLnToConsole(" end") + + WriteLnToConsole(" end") + WriteLnToConsole("end") + WriteLnToConsole("") + + WriteLnToConsole("") + WriteLnToConsole("function EndGameIn(c)") + WriteLnToConsole("") + WriteLnToConsole(" teamCounter = 0") + WriteLnToConsole(" lastRecordedTeam = \"\" ") + WriteLnToConsole(" for i = 1, #hhs do") + WriteLnToConsole("") + WriteLnToConsole(" if GetHogTeamName(hhs[i]) ~= lastRecordedTeam then --er, is this okay without nill checks?") + WriteLnToConsole("") + WriteLnToConsole(" lastRecordedTeam = GetHogTeamName(hhs[i])") + WriteLnToConsole(" teamCounter = teamCounter + 1") + WriteLnToConsole(" if teamCounter == 9 then") + WriteLnToConsole(" teamCounter = 1") + WriteLnToConsole(" end") + WriteLnToConsole("") + WriteLnToConsole(" if (c == \"victory\") and (GetHogLevel(hhs[i]) ~= 0) then") + WriteLnToConsole(" DismissTeam(GetHogTeamName(hhs[i]))") + WriteLnToConsole(" ShowMission(loc(\"User Challenge\"), loc(\"MISSION SUCCESSFUL\"), loc(\"Congratulations!\"), 0, 0)") + WriteLnToConsole(" elseif (c == \"failure\") and (GetHogLevel(hhs[i]) == 0) then") + WriteLnToConsole(" DismissTeam(GetHogTeamName(hhs[i]))") + WriteLnToConsole(" ShowMission(loc(\"User Challenge\"), loc(\"MISSION FAILED\"), loc(\"Oh no! Just try again!\"), -amSkip, 0)") + WriteLnToConsole(" elseif (c == \"victory\") and (GetHogLevel(hhs[i]) == 0) then") + WriteLnToConsole(" PlaySound(sndVictory,hhs[i]) -- check if we actually need this") + WriteLnToConsole(" end") + WriteLnToConsole("") + WriteLnToConsole(" end") + WriteLnToConsole("") + WriteLnToConsole(" end") + WriteLnToConsole("") + WriteLnToConsole("end") + WriteLnToConsole("") + + WriteLnToConsole("") + WriteLnToConsole("function onGearDelete(gear)") + WriteLnToConsole("") + WriteLnToConsole(" --insert code according to taste") + --WriteLnToConsole(" if GetGearType(gear) == gtJetpack then") + --WriteLnToConsole(" ufoGear = nil") + --WriteLnToConsole(" end") + WriteLnToConsole("") + WriteLnToConsole(" if isATrackedGear(gear) then") + WriteLnToConsole("") + WriteLnToConsole(" if getGearValue(gear,\"tag\") ~= nil then") + WriteLnToConsole(" CheckForConclusion(gear)") + WriteLnToConsole(" end") + + --WriteLnToConsole(" if getGearValue(gear,\"tag\") == \"failure\" then") + --WriteLnToConsole(" EndGameIn(\"failure\")") + --WriteLnToConsole(" elseif getGearValue(gear,\"tag\") == \"victory\" then") + --WriteLnToConsole(" EndGameIn(\"victory\")") + --WriteLnToConsole(" end") + WriteLnToConsole("") + WriteLnToConsole(" if getGearValue(gear, \"tCirc\") ~= nil then") + WriteLnToConsole(" DeleteVisualGear(getGearValue(gear, \"tCirc\"))") + WriteLnToConsole(" end") + WriteLnToConsole("") + WriteLnToConsole(" trackDeletion(gear)") + WriteLnToConsole("") + WriteLnToConsole(" end") + WriteLnToConsole("") + WriteLnToConsole("end") + WriteLnToConsole("") + + WriteLnToConsole("") + WriteLnToConsole("--enable and/or alter code according to taste") + WriteLnToConsole("function onAmmoStoreInit()") + WriteLnToConsole("") + + WriteLnToConsole(" for i = 1, #wepArray do") + WriteLnToConsole(" SetAmmo(wepArray[i], 0, 0, 0, 1)") + WriteLnToConsole(" end") + WriteLnToConsole("") + --WriteLnToConsole(" SetAmmo(amBazooka, 2, 0, 0, 0)") + --WriteLnToConsole(" SetAmmo(amGrenade, 1, 0, 0, 0)") + --WriteLnToConsole(" SetAmmo(amRope, 9, 0, 0, 0)") + WriteLnToConsole(" SetAmmo(amSkip, 9, 0, 0, 0)") + WriteLnToConsole("") + WriteLnToConsole("end") + WriteLnToConsole("") + + WriteLnToConsole("------ END GENERATED MISSION ------") + + -- at this point, generation for the missions/training output is intended to stop + + WriteLnToConsole("") + WriteLnToConsole("function GeneratePreviewData()") + WriteLnToConsole("") + for i = 1, #previewDataList do + WriteLnToConsole(previewDataList[i]) + end + WriteLnToConsole("") + WriteLnToConsole("end") + WriteLnToConsole("") + + ConvertGearDataToHWPText() + + WriteLnToConsole("------ END GENERATED SCRIPT ------") + + AddCaption(loc("Level Data Saved!")) + +end + +---------------------------------- +-- some special effects handling +---------------------------------- +function SmokePuff(x,y,c) + tempE = AddVisualGear(x, y, vgtSmoke, 0, false) + g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(tempE) + SetVisualGearValues(tempE, g1, g2, g3, g4, g5, g6, g7, 1, g9, c ) +end + +function HandleGearBasedRankingEffects(gear) + if getGearValue(gear, "ranking") ~= nil then + SmokePuff(GetX(gear), GetY(gear),GetRankedColour(getGearValue(gear, "ranking"))) + end +end + +function HandleRankingEffects() + for i = 1, #shoppaPX do + SmokePuff(shoppaPX[i], shoppaPY[i], GetRankedColour(shoppaPR[i])) + end + runOnHogs(HandleGearBasedRankingEffects) +end + +function UpdateTagCircles(gear) + + if getGearValue(gear,"tag") ~= nil then + + if cat[cIndex] == loc("Tagging Mode") then + + -- generate circs for tagged gears that don't have a circ yet (new) + if getGearValue(gear,"tCirc") == nil then + setGearValue(gear, "tCirc",AddVisualGear(0,0,vgtCircle,0,true)) + end + + if getGearValue(gear,"tag") == "victory" then + SetVisualGearValues(getGearValue(gear,"tCirc"), GetX(gear), GetY(gear), 100, 255, 1, 10, 0, 150, 3, 0xff0000ff) + elseif getGearValue(gear,"tag") == "failure" then + SetVisualGearValues(getGearValue(gear,"tCirc"), GetX(gear), GetY(gear), 100, 255, 1, 10, 0, 150, 3, 0x00ff00ff) + elseif getGearValue(gear,"tag") == "collection" then + SetVisualGearValues(getGearValue(gear,"tCirc"), GetX(gear), GetY(gear), 100, 255, 1, 10, 0, 150, 3, 0x0000ffff) + end + + else + SetVisualGearValues(getGearValue(gear,"tCirc"), GetX(gear), GetY(gear), 0, 1, 1, 10, 0, 1, 1, 0x00000000) + end + + end + +end + +-- handle short range portal gun +function PortalEffects(gear) + + if GetGearType(gear) == gtPortal then + + tag = GetTag(gear) + if tag == 0 then + col = 0xfab02aFF -- orange ball + elseif tag == 1 then + col = 0x00FF00FF -- orange portal + elseif tag == 2 then + col = 0x364df7FF -- blue ball + elseif tag == 3 then + col = 0xFFFF00FF -- blue portal + end + + if (tag == 0) or (tag == 2) then -- i.e ball form + tempE = AddVisualGear(GetX(gear), GetY(gear), vgtDust, 0, true) + g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(tempE) + SetVisualGearValues(tempE, g1, g2, g3, g4, g5, g6, g7, 1, g9, col ) + + remLife = getGearValue(gear,"life") + remLife = remLife - 1 + setGearValue(gear, "life", remLife) + + if remLife == 0 then + + tempE = AddVisualGear(GetX(gear)+15, GetY(gear), vgtSmoke, 0, true) + g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(tempE) + SetVisualGearValues(tempE, g1, g2, g3, g4, g5, g6, g7, g8, g9, col ) + + tempE = AddVisualGear(GetX(gear)-15, GetY(gear), vgtSmoke, 0, true) + g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(tempE) + SetVisualGearValues(tempE, g1, g2, g3, g4, g5, g6, g7, g8, g9, col ) + + tempE = AddVisualGear(GetX(gear), GetY(gear)+15, vgtSmoke, 0, true) + g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(tempE) + SetVisualGearValues(tempE, g1, g2, g3, g4, g5, g6, g7, g8, g9, col ) + + tempE = AddVisualGear(GetX(gear), GetY(gear)-15, vgtSmoke, 0, true) + g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(tempE) + SetVisualGearValues(tempE, g1, g2, g3, g4, g5, g6, g7, g8, g9, col ) + + + PlaySound(sndVaporize) + DeleteGear(gear) + + end + + end + + end + +end + +function updateHelp() + + if (GetCurAmmoType() ~= amGirder) and (GetCurAmmoType() ~= amRubber) and (GetCurAmmoType() ~= amAirAttack) then + + ShowMission ( + loc("HEDGE EDITOR"), + loc("(well... kind of...)"), + loc("Place Girder: Girder") .. "|" .. + loc("Place Rubber: Rubber") .. "|" .. + loc("Place Gear: Air Attack") .. "|" .. + loc("Change Selection: [Up], [Down], [Left], [Right]") .. "|" .. + loc("Toggle Help: Precise+1 (While a tool is selected)") .. "|" .. + " " .. "|" .. + loc("COMMANDS: (Use while no weapon is selected)") .. "|" .. + loc("Save Level: Precise+4") .. "|" .. + loc("Toggle Editing Weapons and Tools: Precise+2") .. "|" .. + " " .. "|" .. + --" " .. "|" .. + "", 4, 5000 + ) + --4 + elseif cat[cIndex] == loc("Girder Placement Mode") then + + ShowMission ( + loc("GIRDER PLACEMENT MODE"), + loc("Use this mode to place girders"), + loc("Place Girder: [Left Click]") .. "|" .. + loc("Change Rotation: [Left], [Right]") .. "|" .. + loc("Change LandFlag: [1], [2], [3], [4]") .. "|" .. + " " .. "|" .. + loc("1 - Normal Girder") .. "|" .. + loc("2 - Indestructible Girder") .. "|" .. + loc("3 - Icy Girder") .. "|" .. + loc("4 - Bouncy Girder") .. "|" .. + " " .. "|" .. + loc("Deletion Mode: [5]") .. "|" .. + loc("Toggle Help: Precise+1") .. "|" .. + "", -amGirder, 60000 + ) + + elseif cat[cIndex] == loc("Rubber Placement Mode") then + + ShowMission ( + loc("RUBBER PLACEMENT MODE"), + loc("Use this mode to place rubberbands"), + loc("Place Object: [Left Click]") .. "|" .. + loc("Change Rotation: [Left], [Right]") .. "|" .. + --"Change LandFlag: [1], [2], [3]" .. "|" .. + --" " .. "|" .. + loc("1 - Normal Rubber") .. "|" .. + --"2 - Indestructible Rubber" .. "|" .. + --"3 - Icy Rubber" .. "|" .. + " " .. "|" .. + loc("Deletion Mode: [5]") .. "|" .. + loc("Toggle Help: Precise+1") .. "|" .. + "", -amRubber, 60000 + ) + + elseif cat[cIndex] == loc("Barrel Placement Mode") then + + ShowMission ( + loc("BARREL PLACEMENT MODE"), + loc("Use this mode to place barrels"), + loc("Place Object: [Left Click]") .. "|" .. + loc("Change Health: [Left], [Right]") .. "|" .. + " " .. "|" .. + loc("Change Placement Mode: [Up], [Down]") .. "|" .. + loc("Toggle Help: Precise+1") .. "|" .. + "", 8, 60000 + ) + + elseif cat[cIndex] == loc("Cleaver Placement Mode") then + + ShowMission ( + loc("CLEAVER MINE PLACEMENT MODE"), + loc("Use this mode to place cleavers"), + loc("Place Object: [Left Click]") .. "|" .. + " " .. "|" .. + loc("Change Placement Mode: [Up], [Down]") .. "|" .. + loc("Toggle Help: Precise+1") .. "|" .. + "", -amKnife, 60000 + ) + + elseif cat[cIndex] == loc("Target Placement Mode") then + + ShowMission ( + loc("TARGET MINE PLACEMENT MODE"), + loc("Use this mode to place targets"), + loc("Place Object: [Left Click]") .. "|" .. + " " .. "|" .. + loc("Change Placement Mode: [Up], [Down]") .. "|" .. + loc("Toggle Help: Precise+1") .. "|" .. + "", 1, 60000 + ) + + elseif cat[cIndex] == loc("Waypoint Placement Mode") then + + ShowMission ( + loc("WAYPOINT PLACEMENT MODE"), + loc("Use this mode to waypoints"), + loc("Place Waypoint: [Left Click]") .. "|" .. + " " .. "|" .. + loc("Change Placement Mode: [Up], [Down]") .. "|" .. + loc("Toggle Help: Precise+1") .. "|" .. + "", -amAirAttack, 60000 + ) + + elseif cat[cIndex] == loc("Mine Placement Mode") then + + ShowMission ( + loc("MINE PLACEMENT MODE"), + loc("Use this mode to place mines"), + loc("Place Object: [Left Click]") .. "|" .. + loc("Change Timer (in milliseconds): [Left], [Right]") .. "|" .. + " " .. "|" .. + loc("Change Placement Mode: [Up], [Down]") .. "|" .. + loc("Toggle Help: Precise+1") .. "|" .. + "", -amMine, 60000 + ) + + elseif cat[cIndex] == loc("Sticky Mine Placement Mode") then + + ShowMission ( + loc("STiCKY MINE PLACEMENT MODE"), + loc("Use this mode to place sticky mines"), + loc("Place Object: [Left Click]") .. "|" .. + " " .. "|" .. + loc("Change Placement Mode: [Up], [Down]") .. "|" .. + loc("Toggle Help: Precise+1") .. "|" .. + "", -amSMine, 60000 + ) + + elseif cat[cIndex] == loc("Air Mine Placement Mode") then + + ShowMission ( + loc("AIR MINE PLACEMENT MODE"), + loc("Use this mode to place air mines"), + loc("Place Object: [Left Click]") .. "|" .. + " " .. "|" .. + loc("Change Placement Mode: [Up], [Down]") .. "|" .. + loc("Toggle Help: Precise+1") .. "|" .. + "", -amAirMine, 60000 + ) + + elseif cat[cIndex] == loc("Weapon Crate Placement Mode") then + + ShowMission ( + "WEAPON CRATE PLACEMENT MODE", + loc("Use this mode to place weapon crates"), + loc("Place Object: [Left Click]") .. "|" .. + loc("Change Content: [Left], [Right]") .. "|" .. + " " .. "|" .. + loc("Change Placement Mode: [Up], [Down]") .. "|" .. + loc("Toggle Help: Precise+1") .. "|" .. + "", 7, 60000 + ) + + elseif cat[cIndex] == loc("Utility Crate Placement Mode") then + + ShowMission ( + loc("UTILITY CRATE PLACEMENT MODE"), + loc("Use this mode to place utility crates"), + loc("Place Object: [Left Click]") .. "|" .. + loc("Change Content: [Left], [Right]") .. "|" .. + " " .. "|" .. + loc("Change Placement Mode: [Up], [Down]") .. "|" .. + loc("Toggle Help: Precise+1") .. "|" .. + "", 5, 60000 + ) + + elseif cat[cIndex] == loc("Health Crate Placement Mode") then + + ShowMission ( + loc("HEALTH CRATE PLACEMENT MODE"), + loc("Use this mode to place utility crates"), + loc("Place Object: [Left Click]") .. "|" .. + loc("Change Health Boost: [Left], [Right]") .. "|" .. + " " .. "|" .. + loc("Change Placement Mode: [Up], [Down]") .. "|" .. + loc("Toggle Help: Precise+1") .. "|" .. + "", 6, 60000 + ) + + elseif cat[cIndex] == loc("Advanced Repositioning Mode") then + + ShowMission ( + loc("ADVANCED REPOSITIONING MODE"), + loc("Use this mode to select and reposition gears"), + loc("[Left], [Right]: Change between selection and placement mode.") .. "|" .. + " " .. "|" .. + loc("Change Placement Mode: [Up], [Down]") .. "|" .. + loc("Toggle Help: Precise+1") .. "|" .. + "", -amAirAttack, 60000 + ) + + elseif cat[cIndex] == loc("Sprite Modification Mode") then + + ShowMission ( + loc("SPRITE MODIFICATION MODE"), + "", + "Use this mode to select, modify, or delete existing girders," .. "|" .. + "rubbers, or sprites." .. "|" .. + "[Left], [Right]: Change between land-flag" .. "|" .. + --"[Left], [Right]: Change between selection, land-flag" .. "|" .. + "modification, and deletion modes." .. "|" .. + "While in modification mode, you can " .. "|" .. + "change land-flag by clicking on an object." .. "|" .. + loc("Set LandFlag: [1], [2], [3], [4]") .. "|" .. + " " .. "|" .. + loc("1 - Normal Land") .. "|" .. + loc("2 - Indestructible Land") .. "|" .. + loc("3 - Icy Land") .. "|" .. + loc("4 - Bouncy Land") .. "|" .. + " " .. "|" .. + loc("Change Placement Mode: [Up], [Down]") .. "|" .. + loc("Toggle Help: Precise+1") .. "|" .. + "", -amAirAttack, 60000 + ) + + elseif cat[cIndex] == loc("Sprite Placement Mode") then + + ShowMission ( + loc("SPRITE PLACEMENT MODE"), + loc("Use this mode to place custom sprites."), + loc("[Left], [Right]: Change sprite selection") .. "|" .. + loc("Set LandFlag: [1], [2], [3], [4]") .. "|" .. + " " .. "|" .. + loc("1 - Normal Land") .. "|" .. + loc("2 - Indestructible Land") .. "|" .. + loc("3 - Icy Land") .. "|" .. + loc("4 - Bouncy Land") .. "|" .. + " " .. "|" .. + loc("Change Placement Mode: [Up], [Down]") .. "|" .. + loc("Toggle Help: Precise+1") .. "|" .. + "", 2, 60000 + ) + + --elseif cat[cIndex] == loc("Sprite Testing Mode") then + + -- ShowMission ( + -- "SPRITE TESTING MODE", + -- "Use this mode to test sprites before you place them.", + -- "Place Temporary Visual Test: [Left Click]" .. "|" .. + -- "[Left], [Right]: Change between sprites." .. "|" .. + -- " " .. "|" .. + -- loc("Change Placement Mode: [Up], [Down]") .. "|" .. + -- loc("Toggle Help: Precise+1") .. "|" .. + -- "", 3, 60000 + -- ) + + elseif cat[cIndex] == loc("Tagging Mode") then + + ShowMission ( + loc("TAGGING MODE"), + loc("Use this mode to tag gears for win/lose conditions."), + loc("Tag Gear: [Left Click]") .. "|" .. + loc("[Left], [Right]: Change between tagging modes.") .. "|" .. + " " .. "|" .. + loc("Change Placement Mode: [Up], [Down]") .. "|" .. + loc("Toggle Help: Precise+1") .. "|" .. + "", 3, 60000 + ) + elseif cat[cIndex] == loc("Hog Identity Mode") then + + ShowMission ( + loc("HOG IDENTITY MODE"), + loc("Use this mode to give a hog a preset identity and weapons."), + loc("Set Identity: [Left Click]") .. "|" .. + loc("[Left], [Right]: Change between identities.") .. "|" .. + " " .. "|" .. + loc("Change Placement Mode: [Up], [Down]") .. "|" .. + loc("Toggle Help: Precise+1") .. "|" .. + "", 3, 60000 + ) + + elseif cat[cIndex] == loc("Team Identity Mode") then + + ShowMission ( + loc("TEAM IDENTITY MODE"), + loc("Use this mode to give an entire team themed hats and names."), + loc("Set Identity: [Left Click]") .. "|" .. + loc("[Left], [Right]: Change between identities.") .. "|" .. + " " .. "|" .. + loc("Change Placement Mode: [Up], [Down]") .. "|" .. + loc("Toggle Help: Precise+1") .. "|" .. + "", 3, 60000 + ) + + elseif cat[cIndex] == loc("Health Modification Mode") then + + ShowMission ( + loc("HEALTH MODIFICATION MODE"), + loc("Use this mode to set the health of hogs."), + loc("Set Health: [Left Click]") .. "|" .. + loc("[Left], [Right]: Change health value.") .. "|" .. + " " .. "|" .. + loc("Change Placement Mode: [Up], [Down]") .. "|" .. + loc("Toggle Help: Precise+1") .. "|" .. + "", 3, 60000 + ) + + end + + + if helpDisabled == true then + HideMission() + end + +end + +-- called in onGameTick() +function HandleHedgeEditor() + + if CurrentHedgehog ~= nil then + + genTimer = genTimer + 1 + + + tSprCol = 0x00000000 + tempFrame = 0 + xDisplacement = 42 + yDisplacement = 42 + + if (curWep == amAirAttack) then + + --wowaweewa, holyeeeee shite this is badly hacked (please rewrite when less lazy/morefeatures) + dCol = 0xFFFFFFFF + dFrame = 0 + dAngle = 0 + if (cat[cIndex] == loc("Mine Placement Mode")) then + dSprite = sprBotlevels--sprMineOff + dFrame = 1 + elseif (cat[cIndex] == loc("Sticky Mine Placement Mode")) then + dSprite = sprBotlevels--sprSMineOff + dFrame = 2 + elseif (cat[cIndex] == loc("Air Mine Placement Mode")) then + dSprite = sprAirMine + elseif (cat[cIndex] == loc("Barrel Placement Mode")) then + dSprite = sprExplosives + elseif (cat[cIndex] == loc("Health Crate Placement Mode")) then + dSprite = sprFAid + elseif (cat[cIndex] == loc("Weapon Crate Placement Mode")) then + dSprite = sprCase + elseif (cat[cIndex] == loc("Utility Crate Placement Mode")) then + dSprite = sprUtility + elseif (cat[cIndex] == loc("Target Placement Mode")) then + dSprite = sprTarget + elseif (cat[cIndex] == loc("Cleaver Placement Mode")) then + dAngle = 270 + dSprite = sprKnife + elseif (cat[cIndex] == loc("Sprite Placement Mode")) then + dSprite = reducedSpriteIDArray[pIndex] + dFrame = 1 + else + dCol = 0xFFFFFF00 + dSprite = sprArrow + end + + if CG == nil then + CG = AddVisualGear(CursorX, CursorY, vgtStraightShot,0,true,3) + end + g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(CG) + SetVisualGearValues(CG, CursorX, CursorY, 0, 0, dAngle, dFrame, 1000, dSprite, 1000, dCol) + + + + if crateSprite == nil then + crateSprite = AddVisualGear(CursorX, CursorY-35, vgtStraightShot,0,true,3) + for i = 1, 4 do + tSpr[i] = AddVisualGear(CursorX, CursorY-35, vgtStraightShot,0,true,3) + end + end + + + if (cat[cIndex] == loc("Weapon Crate Placement Mode")) or (cat[cIndex] == loc("Utility Crate Placement Mode")) then + if (cat[cIndex] == loc("Weapon Crate Placement Mode")) then + tArr = atkArray + else + tArr = utilArray + end + + tSprCol = 0xFFFFFFFF + tempFrame = tArr[pIndex][3] + + end + + else + if CG ~= nil then + SetVisualGearValues(CG, 0, 0, 0, 0, 0, 0, 1000, sprArrow, 1000, 0xFFFFFF00) + end + end + + SetVisualGearValues(crateSprite, CursorX+xDisplacement, CursorY+yDisplacement, 0, 0, dAngle, tempFrame, 1000, sprAMAmmos, 1000, tSprCol) + SetVisualGearValues(tSpr[1], CursorX+xDisplacement-2, CursorY+yDisplacement-2, 0, 0, dAngle, 10, 1000, sprTarget, 1000, tSprCol) + SetVisualGearValues(tSpr[2], CursorX+xDisplacement-2, CursorY+yDisplacement+2, 0, 0, dAngle, 10, 1000, sprTarget, 1000, tSprCol) + SetVisualGearValues(tSpr[3], CursorX+xDisplacement+2, CursorY+yDisplacement-2, 0, 0, dAngle, 10, 1000, sprTarget, 1000, tSprCol) + SetVisualGearValues(tSpr[4], CursorX+xDisplacement+2, CursorY+yDisplacement+2, 0, 0, dAngle, 10, 1000, sprTarget, 1000, tSprCol) + + + if genTimer >= 100 then + + genTimer = 0 + + --if destroyMap == true then + -- BlowShitUpPartTwo() + --end + + curWep = GetCurAmmoType() + + HandleRankingEffects() + runOnGears(PortalEffects) + + -- change to girder mode on weapon swap + if (cIndex ~= 1) and (curWep == amGirder) then + cIndex = 1 + RedefineSubset() + updateHelp() + elseif (cIndex ~=2) and (curWep == amRubber) then + cIndex = 2 + RedefineSubset() + updateHelp() + -- change to generic mode if girder no longer selected + elseif (cIndex == 1) and (curWep ~= amGirder) then + cIndex = 3 -- was 2 + RedefineSubset() + --updateHelp() + elseif (cIndex == 2) and (curWep ~= amRubber) then + cIndex = 3 --new + RedefineSubset() + --updateHelp() + + end + + -- update display selection criteria + if (curWep == amGirder) or (curWep == amRubber) or (curWep == amAirAttack) then + AddCaption(cat[cIndex],0xffba00ff,capgrpMessage) + AddCaption(pMode[pIndex],0xffba00ff,capgrpMessage2) + if superDelete == true then + AddCaption(loc("Warning: Deletition Mode Active"),0xffba00ff,capgrpAmmoinfo) + end + end + + + if sSprite ~= nil then + g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(sSprite) + SetVisualGearValues(sSprite, g1, g2, 0, 0, g5, g6, 10000, g8, 10000, g10 ) + --AddCaption(g7) + end + + end + + end + + + if (ufoFuel ~= 0) then + if ufoFuel == 2000 then + SetHealth(ufoGear, 2000) + end + end + + -- kinda lazy, but at least we don't have to do elaborate tacking elsewhere + SetVisualGearValues(sCirc, 0, 0, 0, 1, 1, 10, 0, 1, 1, 0x00000000) + --update selected gear display + if (cat[cIndex] == loc("Advanced Repositioning Mode")) and (sGear ~= nil) then + SetVisualGearValues(sCirc, GetX(sGear), GetY(sGear), 100, 255, 1, 10, 0, 300, 3, 0xff00ffff) + elseif (cat[cIndex] == loc("Sprite Modification Mode")) and (sSprite ~= nil) then + g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(sSprite) + SetVisualGearValues(sSprite, g1, g2, 0, 0, g5, g6, 10000, g8, 10000, g10 ) + elseif (cat[cIndex] == loc("Tagging Mode")) then + if (sGear ~= nil) or (closestGear ~= nil) then + --recently disabled + --SetVisualGearValues(sCirc, GetX(sGear), GetY(sGear), 0, 1, 1, 10, 0, 1, 1, 0x00000000) + closestGear = nil + sGear = nil + end + end + + + runOnGears(UpdateTagCircles) + + + -- some kind of target detected, tell me your story + if cGear ~= nil then + + x,y = GetGearTarget(cGear) + + if GetGearType(cGear) == gtAirAttack then + DeleteGear(cGear) + PlaceObject(x, y) + elseif GetGearType(cGear) == gtGirder then + + CGR = GetState(cGear) + + -- improve rectangle test based on CGR when you can be bothered + --if TestRectForObstacle(x-20, y-20, x+20, y+20, true) then + -- AddCaption(loc("Invalid Girder Placement"),0xffba00ff,capgrpVolume) + --else + PlaceObject(x, y) + --end + + -- this allows the girder tool to be used like a mining laser + + --[[ + + if CGR < 4 then + AddGear(x, y, gtGrenade, 0, 0, 0, 1) + elseif CGR == 4 then + g = AddGear(x-30, y, gtGrenade, 0, 0, 0, 1) + g = AddGear(x+30, y, gtGrenade, 0, 0, 0, 1) + elseif CGR == 5 then ------- + g = AddGear(x+30, y+30, gtGrenade, 0, 0, 0, 1) + g = AddGear(x-30, y-30, gtGrenade, 0, 0, 0, 1) + elseif CGR == 6 then + g = AddGear(x, y+30, gtGrenade, 0, 0, 0, 1) + g = AddGear(x, y-30, gtGrenade, 0, 0, 0, 1) + elseif CGR == 7 then ------- + g = AddGear(x+30, y-30, gtGrenade, 0, 0, 0, 1) + g = AddGear(x-30, y+30, gtGrenade, 0, 0, 0, 1) + end +]] + end + + end + +end + +-------------------------------------------------- +-- EVENT HANDLERS +-------------------------------------------------- + +function commandMode() + if (preciseOn == true) and ((GetCurAmmoType() == amNothing) or (GetCurAmmoType() == amSkip)) then + return(true) + else + return(false) + end +end + +function onTimer(s) + + superDelete = false + if (commandMode() == true) and (s == 4) then + SaveLevelData() -- positions of crates, etc + elseif (commandMode() == true) and (s == 2) then + if GetAmmoCount(CurrentHedgehog, amAirAttack) == 100 then + SetEditingWeps(0) + AddCaption(loc("The editor weapons and tools have been removed!")) + else + SetEditingWeps(100) + AddCaption(loc("The editor weapons and tools have been added!")) + end + elseif (preciseOn == true) and (s == 1) then + if (GetCurAmmoType() == amGirder) or (GetCurAmmoType() == amRubber) or (GetCurAmmoType() == amAirAttack) then + helpDisabled = not(helpDisabled) + AddCaption("Help Disabled: " .. BoolToString(helpDisabled),0xffba00ff,capgrpVolume) + updateHelp() + end + elseif (cat[cIndex] == loc("Sprite Placement Mode")) or (cat[cIndex] == loc("Girder Placement Mode")) or (cat[cIndex] == loc("Rubber Placement Mode")) or (cat[cIndex] == loc("Sprite Modification Mode")) then + + if (cat[cIndex] == loc("Rubber Placement Mode")) and (s ~= 5) then + landType = lfBouncy + AddCaption(loc("Bouncy Land"),0xffba00ff,capgrpAmmoinfo) + elseif s == 1 then + landType = 0 + AddCaption(loc("Normal Land"),0xffba00ff,capgrpAmmoinfo) + elseif s == 2 then + landType = lfIndestructible + AddCaption(loc("Indestructible Land"),0xffba00ff,capgrpAmmoinfo) + elseif s == 3 then + landType = lfIce + AddCaption(loc("Icy Land"),0xffba00ff,capgrpAmmoinfo) + elseif (s == 4) then --and (cat[cIndex] == "Sprite Placement Mode") then + landType = lfBouncy + AddCaption(loc("Bouncy Land"),0xffba00ff,capgrpAmmoinfo) + elseif (s == 5) and (cat[cIndex] ~= loc("Sprite Modification Mode")) then + superDelete = true + -- this and the above should probably be shown in another place where the other + -- two add captions are displayed for this kinda thing + --AddCaption(loc("Warning: Deletition Mode Active"),0xffba00ff,capgrpAmmoinfo) + end + elseif pMode[pIndex] == loc("Selection Mode") then + setGearValue(sGear, "ranking", s) + end + +end + +function onPrecise() + + preciseOn = true + + --ParseCommand("voicepack " .. "Surfer") + --AddCaption(GetHogGrave(CurrentHedgehog)) + + --if (pMode[pIndex] == "Selection Mode") and (closestGear ~= nil) then + -- menuEnabled = not(menuEnabled) + --showmenu + --end + + --BlowShitUp() + +--[[ + frameID = 1 + visualSprite = sprAmGirder--reducedSpriteIDArray[pIndex] + --visualSprite = spriteIDArray[pIndex] + tempE = AddVisualGear(1, 1, vgtStraightShot, 0, true,1) + g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(tempE) + SetVisualGearValues(tempE, g1, g2, 0, 0, g5, frameID, g7, visualSprite, g9, g10 ) + +]] + +end + +function onPreciseUp() + preciseOn = false +end + +--[[function onLJump() +end + +function onHJump() +end]] + +--[[function UpdateMenu() + + preMenuCfg = loc("Use the arrow keys to navigate this menu") .. "|" + postMenuCfg = loc("Press [Fire] to accept this configuration.") + + menu = { + loc("Walls Required") .. ": " .. #wTouched .. "|", + loc("Surf Before Crate") .. ": " .. BoolToCfgTxt(requireSurfer) .. "|", + loc("Attack From Rope") .. ": " .. BoolToCfgTxt(AFR) .. "|", + loc("Super Weapons") .. ": " .. BoolToCfgTxt(allowCrazyWeps) .. "|" + } +end + +function HandleStartingStage() + + temp = menu[menuIndex] + menu[menuIndex] = "--> " .. menu[menuIndex] + + missionComment = "" + for i = 1, #menu do + missionComment = missionComment .. menu[i] + end + + ShowMission ( + loc("HEDGE EDITOR") .. " 0.4", + loc("Edit gear properties"), + preMenuCfg.. + missionComment .. + postMenuCfg .. + --" " .. "|" .. + "", 4, 300000 + ) + + menu[menuIndex] = temp + +end + +function UpdateMenuCategoryOrSomething() + temp = menu[1] + menu = {} + if temp == "Initialisation Menu" then + for i = 1, #initMenuArray do + menu[i] = initMenuArray[i] .. ": " .. initMenuArray[2] + end + elseif temp == "GameFlag Menu" then + for i = 1, #gameFlagList do + menu[i] = gameFlagList[1] .. ": " .. BoolToStr(gameFlagList[2]) + end + elseif temp == "Ammo Menu" then + for i = 1, #atkArray do --except, this should be per hog, not overall :( + --menu[i] = atkArray[i][2] .. ": " .. atkArray[i][3] + menu[i] = atkArray[i][2] .. ": " .. getGearValue(sGear,atkArray[i][1]) + end + -- you should run through all the hogs and assign them ammo values based on the + -- ammo set, yea, let's write that function in 5th + for i = #menu, #utilArray do + end + end +end + +function doMenuShit(d) + + if d == "up" then + menuIndex = menuIndex -1 + if menuIndex == 0 then + menuIndex = #menu + end + elseif d == "down" then + menuIndex = menuIndex +1 + if menuIndex > #menu then + menuIndex = 1 + end + elseif d == "left" then + + elseif d == "right" then + + end + +end]] + +--------------------------------------------------------------- +-- Cycle through selection subsets (by changing pIndex, pMode) +-- i.e health of barrels, medikits, +-- timer of mines +-- contents of crates etc. +--------------------------------------------------------------- +function onLeft() + + leftHeld = true + rightHeld = false + + --if menuEnabled == true then + --doMenuShit("left") + + --else -- normal case + + pIndex = pIndex - 1 + if pIndex == 0 then + pIndex = #pMode + end + + if (curWep == amGirder) or (curWep == amRubber) or (curWep == amAirAttack) then + AddCaption(pMode[pIndex],0xffba00ff,capgrpMessage2) + end + + --end + +end + +function onRight() + + leftHeld = false + rightHeld = true + + --if menuEnabled == true then + --doMenuShit("right") + + --else -- normal case + + pIndex = pIndex + 1 + if pIndex > #pMode then + pIndex = 1 + end + + if (curWep == amGirder) or (curWep == amRubber) or (curWep == amAirAttack) then + AddCaption(pMode[pIndex],0xffba00ff,capgrpMessage2) + end + + --end + +end + +--------------------------------------------------------- +-- Cycle through primary categories (by changing cIndex) +-- i.e mine, sticky mine, barrels +-- health/weapon/utility crate, placement of gears +--------------------------------------------------------- +function onUp() + + --if menuEnabled == true then + --doMenuShit("up") + + --elseif (curWep ~= amGirder) then + if (curWep ~= amGirder) then + --AddCaption(cIndex) + cIndex = cIndex - 1 + if (cIndex == 1) or (cIndex == 2) then --1 --we no longer hit girder by normal means + cIndex = #cat + end + + RedefineSubset() + updateHelp() + + end + +end + +function onDown() + + --if menuEnabled == true then + --doMenuShit("down") + + --elseif (curWep ~= amGirder) then + if (curWep ~= amGirder) then + cIndex = cIndex + 1 + if cIndex > #cat then + cIndex = 3 -- 2 ----we no longer hit girder by normal means + end + + RedefineSubset() + updateHelp() + + end + +end + +function onParameters() + + parseParams() + + ufoFuel = tonumber(params["ufoFuel"]) + if ufoFuel == nil then + ufoFuel = 0 + end + + mapID = tonumber(params["m"]) + + --15 is a good short range portal, for what it's worth + if tonumber(params["portalDistance"]) ~= nil then + portalDistance = div(tonumber(params["portalDistance"]),5) + end + + if portalDistance == nil then + portalDistance = 5000 + end + + if params["helpDisabled"] == "true" then + helpDisabled = true + end + + if mapID == nil then + mapID = 1 + end + +end + +function onGameInit() + + -- perhaps we can get some of this better info in parsecommandoverride + --Map = "Islands" + --Theme = "Deepspace" + --Seed = "{bacb2f87-f316-4691-a333-3bcfc4fb3d88}" + --MapGen = 0 -- 0:generated map, 1:generated maze, 2:hand drawn map + --TemplateFilter = 5 -- small=1,med=2,large=3,cavern=4,wacky=5 + + if mapID == nil then + mapID = 1 + end + + -- read gameflags and assign their values to the gameflaglist array + for i = 1, #gameFlagList do + if band(GameFlags, gameFlagList[i][3]) ~= 0 then + gameFlagList[i][2] = true + else + gameFlagList[i][2] = false + end + end + + Explosives = 0 + MinesNum = 0 + + --GameFlags = GameFlags + gfInfAttack + EnableGameFlags(gfInfAttack, gfDisableWind) + + RedefineSubset() + +end + +function onGameStart() + + trackTeams() + + + InterpretPoints() + LoadLevelData() + + ShowMission ( + loc("HEDGE EDITOR"), + loc("(well... kind of...)"), + loc("Place Girder: Girder") .. "|" .. + loc("Place Rubber: Rubber") .. "|" .. + loc("Place Gear: Air Attack") .. "|" .. + loc("Change Selection: [Up], [Down], [Left], [Right]") .. "|" .. + loc("Toggle Help: Precise+1 (While a tool is selected)") .. "|" .. + " " .. "|" .. + loc("COMMANDS: (Use while no weapon is selected)") .. "|" .. + loc("Save Level: Precise+4") .. "|" .. + loc("Toggle Editing Weapons and Tools: Precise+2") .. "|" .. + " " .. "|" .. + --" " .. "|" .. + "", 4, 5000 + ) + + + sCirc = AddVisualGear(0,0,vgtCircle,0,true) + SetVisualGearValues(sCirc, 0, 0, 100, 255, 1, 10, 0, 40, 3, 0xffba00ff) + + + frameID = 1 + visualSprite = sprAmGirder + sSprite = AddVisualGear(0, 0, vgtStraightShot, 0, true,1) + g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(sSprite) + SetVisualGearValues(sSprite, 1, 1, 0, 0, g5, frameID, 20000, visualSprite, 20000, g10 ) + + SetAmmoDelay(amAirAttack,0) + SetAmmoDelay(amGirder,0) + SetAmmoDelay(amRubber,0) + --SetAmmoDelay(amNapalm,0) + --SetAmmoDelay(amDrillStrike,0) + --SetAmmoDelay(amMineStrike,0) + +end + +function SetEditingWeps(ammoCount) + + AddAmmo(CurrentHedgehog, amAirAttack, ammoCount) + AddAmmo(CurrentHedgehog, amGirder, ammoCount) + AddAmmo(CurrentHedgehog, amRubber, ammoCount) + --AddAmmo(CurrentHedgehog, amPortalGun, ammoCount) + AddAmmo(CurrentHedgehog, amTeleport, ammoCount) + AddAmmo(CurrentHedgehog, amRope, ammoCount) + --AddAmmo(CurrentHedgehog, amJetpack, ammoCount) + --AddAmmo(CurrentHedgehog, amParachute, ammoCount) + AddAmmo(CurrentHedgehog, amSwitch, 100) --ammoCount + AddAmmo(CurrentHedgehog, amSkip, 100) + +end + +function clearAmmo(gear) + for i = 1, #atkArray do + AddAmmo(gear,atkArray[i][1],0) + end + for i = 1, #utilArray do + AddAmmo(gear,utilArray[i][1],0) + end +end + +-- the below two functions allow you to set up a themed team. +-- one day, it'd be nice to be able to set their voice/flag/grave +-- ingame at this point, too, but for now, this is impossible +function SetTeamIdentity(gear) + tName = pMode[pIndex] + hIndex = 1 + hArr = {} + for i = 1,#preMadeTeam[pIndex][2] do + table.insert(hArr,preMadeTeam[pIndex][2][i]) + end + nArr = {} + for i = 1,#preMadeTeam[pIndex][3] do + table.insert(nArr,preMadeTeam[pIndex][3][i]) + end + SetHogTeamName(gear, tName) + --runOnHogsInTeam(AssignTeam(gear),tName) + runOnHogs(AssignTeam) +end + +function AssignTeam(gear) + + if GetHogTeamName(gear) == tName then + + setGearValue(gear,"flag",preMadeTeam[pIndex][5]) + setGearValue(gear,"voice",preMadeTeam[pIndex][6]) + setGearValue(gear,"grave",preMadeTeam[pIndex][7]) + setGearValue(gear,"fort",preMadeTeam[pIndex][8]) + + if preMadeTeam[pIndex][4] == "R" then -- random team + + if #hArr > 0 then + --if there are unchosen hats left, choose one + --then remove it from the available list of hats + i = 1+GetRandom(#hArr) + SetHogHat(gear,hArr[i]) + table.remove(hArr,i) + else + -- choose any hat randomly + SetHogHat(gear,preMadeTeam[pIndex][2][1+GetRandom(#preMadeTeam[pIndex][2])]) + end + + if #nArr > 0 then + i = 1+GetRandom(#nArr) + SetHogName(gear,nArr[i]) + table.remove(nArr,i) + else + SetHogName(gear,preMadeTeam[pIndex][3][1+GetRandom(#preMadeTeam[pIndex][3])]) + end + + elseif preMadeTeam[pIndex][4] == "F" then -- fixed team w/ exactly 8 guys + SetHogName(gear,preMadeTeam[pIndex][3][hIndex]) + SetHogHat(gear,preMadeTeam[pIndex][2][hIndex]) + hIndex = hIndex +1 + else -- FR fixed random team with more or less than 8 guys + + if #hArr > 0 then + i = 1+GetRandom(#hArr) + SetHogHat(gear,hArr[i]) + SetHogName(gear,nArr[i]) + table.remove(hArr,i) + table.remove(nArr,i) + else + SetHogHat(gear,"NoHat") + SetHogName(gear,"Uninspiring hog") + end + + end + + end + +end + +-- allows you to set a sort of identity and weapon profile for a given hog +-- this should only really be used when perHogAmmo is enabled +function SetHogProfile(gear, pro) + + clearAmmo(gear) + + if pro == loc("Sniper") then + + SetHogName(gear,"Sniper") + SetHogHat(gear, "Sniper") + SetHealth(gear, 50) + AddAmmo(gear, amSniperRifle, 100) + AddAmmo(gear, amDEagle, 100) + + elseif pro == loc("Pyro") then + + SetHogName(gear,loc("Pyro")) + SetHogHat(gear, "Gasmask") + SetHealth(gear, 80) + AddAmmo(gear, amFlamethrower, 100) + AddAmmo(gear, amMolotov, 100) + AddAmmo(gear, amNapalm, 1) + + elseif pro == loc("Soldier") then + + SetHogName(gear,loc("Soldier")) + --SetHogHat(gear, "war_americanww2helmet") + SetHogHat(gear, "TeamSoldier") + SetHealth(gear, 100) + AddAmmo(gear, amBazooka, 100) + AddAmmo(gear, amShotgun, 100) + AddAmmo(gear, amMortar, 100) + + elseif pro == loc("Grenadier") then + + SetHogName(gear,loc("Grenadier")) + SetHogHat(gear, "war_desertgrenadier1") + SetHealth(gear, 100) + AddAmmo(gear, amGrenade, 100) + AddAmmo(gear, amClusterBomb, 100) + AddAmmo(gear, amGasBomb, 100) + + elseif pro == loc("Chef") then + + SetHogName(gear,loc("Chef")) + SetHogHat(gear, "chef") + SetHealth(gear, 65) + AddAmmo(gear, amGasBomb, 100) + AddAmmo(gear, amKnife, 100) + AddAmmo(gear, amCake, 1) + --AddAmmo(gear, amWatermelon, 1) + + elseif pro == loc("Ninja") then + + SetHogName(gear,loc("Ninja")) + SetHogHat(gear, "NinjaFull") + SetHealth(gear, 80) + AddAmmo(gear, amRope, 100) + AddAmmo(gear, amFirePunch, 100) + AddAmmo(gear, amParachute, 1) + + elseif pro == loc("Commander") then + + SetHogName(gear,loc("Commander")) + SetHogHat(gear, "sf_vega") + SetHealth(gear, 120) + AddAmmo(gear, amDEagle, 100) + AddAmmo(gear, amAirAttack, 2) + AddAmmo(gear, amNapalm, 1) + AddAmmo(gear, amDrillStrike, 1) + AddAmmo(gear, amMineStrike, 1) + + elseif pro == loc("Engineer") then + + SetHogName(gear,loc("Engineer")) + SetHogHat(gear, "Glasses") + SetHealth(gear, 45) + AddAmmo(gear, amGirder, 4) + AddAmmo(gear, amRubber, 2) + AddAmmo(gear, amLandGun, 2) + AddAmmo(gear, amBlowTorch, 100) + AddAmmo(gear, amPickHammer, 100) + + elseif pro == loc("Physicist") then + + SetHogName(gear,loc("Physicist")) + SetHogHat(gear, "lambda") + SetHealth(gear, 80) + AddAmmo(gear, amIceGun, 2) + AddAmmo(gear, amSineGun, 100) + AddAmmo(gear, amBee, 2) + AddAmmo(gear, amLowGravity, 100) + + elseif pro == loc("Trapper") then + + SetHogName(gear,loc("Trapper")) + SetHogHat(gear, "Skull") + SetHealth(gear, 100) + AddAmmo(gear, amMine, 100) + AddAmmo(gear, amSMine, 4) + AddAmmo(gear, amAirMine, 2) + AddAmmo(gear, amMolotov, 100) + + elseif pro == loc("Saint") then + + SetHogName(gear,loc("Saint")) + SetHogHat(gear, "angel") + SetHealth(gear, 200) + AddAmmo(gear, amSeduction, 100) + AddAmmo(gear, amInvulnerable, 100) + AddAmmo(gear, amIceGun, 2) + AddAmmo(gear, amHammer, 100) + AddAmmo(gear, amResurrector, 100) + + elseif pro == loc("Clown") then + + SetHogName(gear,loc("Clown")) + SetHogHat(gear, "clown-copper") + SetHealth(gear, 70) + AddAmmo(gear, amBaseballBat, 100) + AddAmmo(gear, amGasBomb, 100) + AddAmmo(gear, amBallgun, 1) + AddAmmo(gear, amKamikaze, 1) + --AddAmmo(gear, amPiano, 1) + + -- some other ideas/roles + -- relocator: portal, teleport, tardis, extra time, lasersite + -- vampire: vampire, whip, birdy, extra damage, seduction + -- flyboy: rc plane, deagle, whip, parachute, kamikaze + -- demo: drill, dynamite, mine, smine, blowtorch + -- alien: ufo, sine-gun, drill rocket + -- terminator: tardis, shotgun, cake, girder + -- yeti: ice-gun, firepunch, blowtorch + + end + + AddAmmo(gear, amSwitch, 100) + AddAmmo(gear, amSkip, 100) + +end + +function onNewTurn() + + -- regardless of our other ammo, give stuff that is useful for editing + SetEditingWeps(100) + if GetHogLevel(CurrentHedgehog) == 0 then + TurnTimeLeft = -1 -- is that turntime in your pocket? :D + else + TurnTimeLeft = 1 -- skip the computer's turn + end + +end + +function onGameTick() + HandleHedgeEditor() +end + +function isATrackedGear(gear) + if (GetGearType(gear) == gtHedgehog) or + (GetGearType(gear) == gtGrenade) or + (GetGearType(gear) == gtExplosives) or + (GetGearType(gear) == gtTarget) or + (GetGearType(gear) == gtKnife) or + (GetGearType(gear) == gtMine) or + (GetGearType(gear) == gtSMine) or + (GetGearType(gear) == gtPortal) or + (GetGearType(gear) == gtAirMine) or + (GetGearType(gear) == gtCase) + then + return(true) + else + return(false) + end +end + +-- track hedgehogs and placement gears +function onGearAdd(gear) + + if GetGearType(gear) == gtJetpack then + ufoGear = gear + if (ufoFuel ~= 0) then + SetHealth(ufoGear, ufoFuel) + end + end + + if GetGearType(gear) == gtHedgehog then + --table.insert(hhs, gear) + elseif (GetGearType(gear) == gtAirAttack) or (GetGearType(gear) == gtGirder) then + cGear = gear + end + + if isATrackedGear(gear) then + trackGear(gear) + + if GetGearType(gear) == gtPortal then + setGearValue(gear,"life",portalDistance) + end + + end + +end + +function onGearDelete(gear) + + if GetGearType(gear) == gtJetpack then + ufoGear = nil + end + + if (GetGearType(gear) == gtAirAttack) or (GetGearType(gear) == gtGirder) then + cGear = nil + end + + if isATrackedGear(gear) then + + if getGearValue(gear, "tCirc") ~= nil then + DeleteVisualGear(getGearValue(gear, "tCirc")) + end + + trackDeletion(gear) + + end + +end + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Scripts/Multiplayer/Highlander.cfg --- a/share/hedgewars/Data/Scripts/Multiplayer/Highlander.cfg Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Scripts/Multiplayer/Highlander.cfg Tue Nov 10 20:43:13 2015 +0100 @@ -1,2 +1,2 @@ -Default -locked +* +Highlander diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Scripts/Multiplayer/Highlander.lua --- a/share/hedgewars/Data/Scripts/Multiplayer/Highlander.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Scripts/Multiplayer/Highlander.lua Tue Nov 10 20:43:13 2015 +0100 @@ -89,29 +89,34 @@ HedgewarsScriptLoad("/Scripts/Locale.lua") HedgewarsScriptLoad("/Scripts/Tracker.lua") - -local airWeapons = {amAirAttack, amMineStrike, amNapalm, amDrillStrike --[[,amPiano]]} +HedgewarsScriptLoad("/Scripts/Params.lua") -local atkArray = { - amBazooka, amBee, amMortar, amDrill, --[[amSnowball,]] - amGrenade, amClusterBomb, amMolotov, amWatermelon, amHellishBomb, amGasBomb, - amShotgun, amDEagle, amFlamethrower, amSniperRifle, amSineGun, amIceGun, - amFirePunch, amWhip, amBaseballBat, --[[amKamikaze,]] amSeduction, --[[amHammer,]] - amMine, amDynamite, amCake, amBallgun, amRCPlane, amSMine, - amRCPlane, amSMine, - amBirdy +-- These define weps allowed by the script. At present Tardis and Resurrection is banned for example +-- These were arbitrarily defined out-of-order in initial script, so that was preserved here, resulting +-- in a moderately odd syntax. +local atkWeps = { + [amBazooka]=true, [amBee]=true, [amMortar]=true, [amDrill]=true, [amSnowball]=true, + [amGrenade]=true, [amClusterBomb]=true, [amMolotov]=true, [amWatermelon]=true, + [amHellishBomb]=true, [amGasBomb]=true, [amShotgun]=true, [amDEagle]=true, + [amFlamethrower]=true, [amSniperRifle]=true, [amSineGun]=true, + [amFirePunch]=true, [amWhip]=true, [amBaseballBat]=true, [amKamikaze]=true, + [amSeduction]=true, [amHammer]=true, [amMine]=true, [amDynamite]=true, [amCake]=true, + [amBallgun]=true, [amSMine]=true, [amRCPlane]=true, [amBirdy]=true, [amKnife]=true, + [amAirAttack]=true, [amMineStrike]=true, [amNapalm]=true, [amDrillStrike]=true, [amPiano]=true, [amAirMine] = true, } -local utilArray = { - amBlowTorch, amPickHammer, amGirder, amPortalGun, - amRope, amParachute, amTeleport, amJetpack, - amInvulnerable, amLaserSight, --[[amVampiric,]] - amLowGravity, amExtraDamage, --[[amExtraTime,]] - amLandGun - --[[,amTardis, amResurrector, amSwitch]] +local utilWeps = { + [amBlowTorch]=true, [amPickHammer]=true, [amGirder]=true, [amPortalGun]=true, + [amRope]=true, [amParachute]=true, [amTeleport]=true, [amJetpack]=true, + [amInvulnerable]=true, [amLaserSight]=true, [amVampiric]=true, + [amLowGravity]=true, [amExtraDamage]=true, [amExtraTime]=true, + [amLandGun]=true, [amRubber]=true, [amIceGun]=true, } -local wepArray = {} +local wepArray = {} + +local atkChoices = {} +local utilChoices = {} local currHog local lastHog @@ -121,6 +126,20 @@ local lastWep = amNothing local shotsFired = 0 +local probability = {1,2,5,10,20,50,200,500,1000000}; +local atktot = 0 +local utiltot = 0 +local maxWep = 57 -- game crashes if you exceed supported # + +local someHog = nil -- just for looking up the weps + +local mode = nil + +function onParameters() + parseParams() + mode = params["mode"] +end + function CheckForWeaponSwap() if GetCurAmmoType() ~= lastWep then shotsFired = 0 @@ -142,20 +161,40 @@ end function StartingSetUp(gear) - - for i = 1, #wepArray do - setGearValue(gear,wepArray[i],0) + for i = 1,maxWep do + setGearValue(gear,i,0) + end + for w,c in pairs(wepArray) do + if c == 9 and (atkWeps[w] or utilWeps[w]) then + setGearValue(gear,w,1) + end end - setGearValue(gear,amKamikaze,100) setGearValue(gear,amSkip,100) - - i = 1 + GetRandom(#atkArray) - setGearValue(gear,atkArray[i],1) - - i = 1 + GetRandom(#utilArray) - setGearValue(gear,utilArray[i],1) - + + local r = 0 + if atktot > 0 then + r = GetRandom(atktot)+1 + for i = 1,maxWep do + --for w,c in pairs(atkChoices) do + --WriteLnToConsole(' c: '..c..' w:'..w..' r:'..r) + if atkChoices[i] >= r then + setGearValue(gear,i,1) + break + end + end + end + if utiltot > 0 then + r = GetRandom(utiltot)+1 + for i = 1,maxWep do + -- for w,c in pairs(utilChoices) do + --WriteLnToConsole('util c: '..c..' w:'..w..' r:'..r) + if utilChoices[i] >= r then + setGearValue(gear,i,1) + break + end + end + end end --[[function SaveWeapons(gear) @@ -169,11 +208,9 @@ end]] function ConvertValues(gear) - - for i = 1, #wepArray do - AddAmmo(gear, wepArray[i], getGearValue(gear,wepArray[i]) ) - end - + for w,c in pairs(wepArray) do + AddAmmo(gear, w, getGearValue(gear,w) ) + end end -- this is called when a hog dies @@ -181,18 +218,17 @@ if CurrentHedgehog ~= nil then - for i = 1, #wepArray do - val = getGearValue(gear,wepArray[i]) - if val ~= 0 then - - setGearValue(CurrentHedgehog, wepArray[i], val) + for w,c in pairs(wepArray) do + val = getGearValue(gear,w) + if val ~= 0 and (mode == "orig" or (wepArray[w] ~= 9 and getGearValue(CurrentHedgehog, w) == 0)) then + setGearValue(CurrentHedgehog, w, val) -- if you are using multi-shot weapon, gimme one more - if (GetCurAmmoType() == wepArray[i]) and (shotsFired ~= 0) then - AddAmmo(CurrentHedgehog, wepArray[i], val+1) + if (GetCurAmmoType() == w) and (shotsFired ~= 0) then + AddAmmo(CurrentHedgehog, w, val+1) -- assign ammo as per normal else - AddAmmo(CurrentHedgehog, wepArray[i], val) + AddAmmo(CurrentHedgehog, w, val) end end @@ -203,12 +239,38 @@ end function onGameInit() - GameFlags = bor(GameFlags,gfInfAttack + gfRandomOrder + gfPerHogAmmo) + EnableGameFlags(gfInfAttack, gfRandomOrder, gfPerHogAmmo) + DisableGameFlags(gfResetWeps, gfSharedAmmo) HealthCaseProb = 100 end function onGameStart() + utilChoices[amSkip] = 0 + local c = 0 + for i = 1,maxWep do + atkChoices[i] = 0 + utilChoices[i] = 0 + if i ~= 7 then + wepArray[i] = 0 + c = GetAmmoCount(someHog, i) + if c > 8 then c = 9 end + wepArray[i] = c + if c < 9 and c > 0 then + if atkWeps[i] then + --WriteLnToConsole('a c: '..c..' w:'..i) + atktot = atktot + probability[c] + atkChoices[i] = atktot + elseif utilWeps[i] then + --WriteLnToConsole('u c: '..c..' w:'..i) + utiltot = utiltot + probability[c] + utilChoices[i] = utiltot + end + end + end + end + --WriteLnToConsole('utiltot:'..utiltot..' atktot:'..atktot) + ShowMission ( loc("HIGHLANDER"), loc("Not all hogs are born equal."), @@ -220,27 +282,8 @@ "", 4, 4000 ) - if MapHasBorder() == false then - for i, w in pairs(airWeapons) do - table.insert(atkArray, w) - end - end - - for i, w in pairs(atkArray) do - table.insert(wepArray, w) - end - - for i, w in pairs(utilArray) do - table.insert(wepArray, w) - end - - table.insert(wepArray, amSkip) - table.insert(wepArray, amKamikaze) - runOnGears(StartingSetUp) runOnGears(ConvertValues) - - end function CheckForHogSwitch() @@ -296,6 +339,7 @@ if (GetGearType(gear) == gtHedgehog) then trackGear(gear) + if someHog == nil then someHog = gear end end end @@ -308,8 +352,3 @@ end end - -function onAmmoStoreInit() - -- no, you can't set your own ammo scheme -end - diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Scripts/Multiplayer/Mutant.lua --- a/share/hedgewars/Data/Scripts/Multiplayer/Mutant.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Scripts/Multiplayer/Mutant.lua Tue Nov 10 20:43:13 2015 +0100 @@ -1,615 +1,621 @@ -local MUTANT_VERSION = "v0.9.5" - ---[[ ___ ___ - ( ) ( ) -___ .-. .-. ___ ___ | |_ .---. ___ .-. | |_ -( ) ' ( )( ( __) / .-, ( ) ( __) -| .-. .-. | | | | | | (__) ; || .-. .| | -| | | | | | | | | | | ___ .'` || | | || | ___ -| | | | | | | | | | |( / .'| || | | || |( ) -| | | | | | | | | | | | | / | || | | || | | | -| | | | | | | ; ' | ' | ; | ; || | | || ' | | -| | | | | ' `-' / ' `-' ' `-' || | | |' `-' ; -(___)(___)(___'.__.' `.__.`.__.'_(___)(___)`.__. - - ----- Recommended settings: ----- * one hedgehog per team ----- * 'Small' one-island map - ---]] - -HedgewarsScriptLoad("/Scripts/Locale.lua") -HedgewarsScriptLoad("/Scripts/Tracker.lua") - ---[[ - MUTANT SCRIPT - - To Do: -Clean-up this fucking piece of code - -Debug - -Find a girlfriend - -Fix Sheepluva's hat +[p] - -Cookies ------------------------]] - -local hhs = {} -local numhhs = 0 -local meh = false - -local gameOver=false - -local mutant = nil -local mutant_base_health = 200 -local mutant_base_disease = 25 -local disease_timer = 2000 - -local kill_reward = nil -local mt_hurt=false - -local killsCounter = 0 - -local team_fire_punishment = 3 -local mutant_kill_reward = 2 - -local hh_weapons = { amBazooka, amGrenade, amShotgun, amMine} - -local mt_weapons = {amWatermelon, amHellishBomb, amBallgun, amRCPlane, amTeleport} - -local disease=0 -local timer=0 - -local winScore = 15 -local hogsLimit = 1 - -local teams = {} - -local circles = {} -local circleFrame = -1 - -function showStartingInfo() - - ruleSet = loc("RULES") .. ": " .. - " |" .. --" |" .. - loc("The first player to kill someone becomes the Mutant.") .. "|" .. - loc("The Mutant has super-weapons and a lot of health.") .. "|" .. - loc("The Mutant loses health quickly if he doesn't keep scoring kills.") .. "|" .. - " |" .. - loc("Normal players can only score points by killing the mutant.") .. "|" .. - " |" .. "" .. - loc("The player with least points (or most deaths) becomes the Bottom Feeder.") .. "|" .. - loc("The Bottom Feeder can score points by killing anyone.") .. "|" .. - " |" .. - loc("POINTS") .. ": " .. - " |" .. - loc("+2 for becoming a Mutant") .. "|" .. - loc("+1 to a Mutant for killing anyone") .. "|" .. - loc("+1 to a Bottom Feeder for killing anyone") .. "|" .. - loc("-1 to anyone for a suicide") .. "|" .. - loc("Other kills don't give you points.") - - ShowMission(loc("Mutant"), - loc("a Hedgewars tag game"), - ruleSet, 0, 5000) - -end - -function onGameInit() - TurnTime = 20000 - WaterRise = 0 - GameFlags = GameFlags + gfResetWeps + gfPerHogAmmo - HealthCaseProb=0 - HealthCaseAmount=0 - MinesTime=1000 - CaseFreq = 2 -end - - -function limitHogs(gear) - cnthhs = cnthhs + 1 - if cnthhs > 1 then - hogLimitHit = true - SetEffect(gear, heResurrectable, false) - --SetHealth(gear, 0) - SetGearPosition(gear, -100,LAND_HEIGHT) - end -end - -function onGameStart() - trackTeams() - teamScan() - runOnHogs(saveStuff) - --local str = "/say " .. MUTANT_VERSION - --ParseCommand(str) - - hogLimitHit = false - for i=0 , TeamsCount - 1 do - cnthhs = 0 - runOnHogsInTeam(limitHogs, teams[i]) - end - if hogLimitHit then - AddCaption(loc("ONE HOG PER TEAM! KILLING EXCESS HEDGES")) - end - showStartingInfo() -end - - - -function giveWeapons(gear) - if gear == mutant then - AddAmmo(gear, amRope) - for i=1, #mt_weapons do - AddAmmo(gear, mt_weapons[i]) - end - - else - for i=1, #hh_weapons do - AddAmmo(gear,hh_weapons[i]) - end - end -end - -function onAmmoStoreInit() - - SetAmmo(amSkip, 9, 0, 0, 0) - SetAmmo(amRope,0,1,0,5) - SetAmmo(amSnowball,0,1,0,1) - - for i=1, #hh_weapons do - SetAmmo(hh_weapons[i], 0, 0, 0, 1) - end - - for i=1, #mt_weapons do - SetAmmo(mt_weapons[i], 0, 3, 0, 1) - end - -end - -function drawCircles() - for i = 0, #hhs do - if circles[hhs[i]] ~= nil then - DeleteVisualGear(circles[hhs[i]]) - circles[hhs[i]] = nil - end - - if hhs[i] ~= CurrentHedgehog then - if mutant == nil then - circles[hhs[i]] = AddVisualGear(0, 0, vgtCircle, 0, false) - SetVisualGearValues(circles[hhs[i]], 0, 0, 0, 0, 0, 0, 0, 22, 5, 0xff000080) - elseif CurrentHedgehog == mutant then - circles[hhs[i]] = AddVisualGear(0, 0, vgtCircle, 0, false) - SetVisualGearValues(circles[hhs[i]], 0, 0, 0, 0, 0, 0, 0, 22, 3, 0xaa000070) - elseif getGearValue(CurrentHedgehog, "Feeder") and hhs[i] ~= mutant then - circles[hhs[i]] = AddVisualGear(0, 0, vgtCircle, 0, false) - SetVisualGearValues(circles[hhs[i]], 0, 0, 0, 0, 0, 0, 0, 22, 3, 0xaa000070) - elseif hhs[i] == mutant then - circles[hhs[i]] = AddVisualGear(0, 0, vgtCircle, 0, false) - SetVisualGearValues(circles[hhs[i]], 0, 0, 0, 0, 0, 0, 0, 22, 5, 0xff000080) - end - end - end - circleFrame = 0 -end - -function onNewTurn() - - trackTeams() - killsCounter = 0 - - if mutant == nil then - AddCaption( loc("FIRST BLOOD MUTATES") ) - end - - checkScore() - giveWeapons(CurrentHedgehog) - drawCircles() - setAIHints() - kill_reward= numhhs*10 - - if CurrentHedgehog == mutant then - mt_hurt=true - disease= mutant_base_disease - numhhs - else - mt_hurt=false - end - - setGearValue(CurrentHedgehog, "Alive", true) - -end - -function countBodies() - if killsCounter == 2 then - AddCaption(loc("DOUBLE KILL")) - elseif killsCounter == 3 then - AddCaption(loc("MEGA KILL")) - PlaySound(sndRegret) - elseif killsCounter == 4 then - AddCaption(loc("ULTRA KILL")) - elseif killsCounter == 5 then - AddCaption(loc("MONSTER KILL")) - PlaySound(sndIllGetYou) - elseif killsCounter == 6 then - AddCaption(loc("LUDICROUS KILL")) - PlaySound(sndNutter) - elseif killsCounter == 7 then - AddCaption(loc("HOLY SHYTE!")) - PlaySound(sndLaugh) - elseif killsCounter > 8 then - AddCaption(loc("INSANITY")) - end -end - -function onGameTick() - - if circleFrame > -1 then - for i = 0, #hhs do - if circles[hhs[i]] ~= nil and hhs[i]~= nil then - hhx, hhy = GetGearPosition(hhs[i]) - X, Y, dX, dY, Angle, Frame, FrameTicks, State, Timer, Tint = GetVisualGearValues(circles[hhs[i]]) - SetVisualGearValues(circles[hhs[i]], hhx + 1, hhy - 3, 0, 0, 0, 0, 0, 40 - (circleFrame % 25), Timer, Tint) - end - end - - circleFrame = circleFrame + 0.06 - - if circleFrame >= 25 then - for i = 0, #hhs do - if circles[hhs[i]] ~= nil then - DeleteVisualGear(circles[hhs[i]]) - circles[hhs[i]] = nil - end - end - end - end - - if TurnTimeLeft==0 and mt_hurt then - mt_hurt = false - end - - if mt_hurt and mutant~=nil then - timer = timer + 1 - if timer > disease_timer then - timer = 0 - SetHealth(mutant, GetHealth(mutant)-disease ) - AddVisualGear(GetX(mutant), GetY(mutant)-5, vgtHealthTag, disease, true) - if GetHealth(mutant)<=0 then - SetHealth(mutant,0) - mt_hurt= false - setGearValue(mutant,"SelfDestruct",true) - TurnTimeLeft = 0 - end - end - end - -end - -function saveStuff(gear) - setGearValue(gear,"Name",GetHogName(gear)) - setGearValue(gear,"Hat",GetHogHat(gear)) -end - -function armageddon(gear) - SetState(gear, gstLoser) - SetEffect(gear, heResurrectable, false) - SetHealth(gear, 0) -end - -function updateScore() - - local showScore = "" - - for i=0, TeamsCount-1 do - if teams[i]~= nil then - - local curr_score = getTeamValue(teams[i], "Score") - showScore = showScore .. teams[i] .. ": " .. curr_score .. " (deaths: " .. getTeamValue(teams[i], "DeadHogs") .. ") " .. "|" - - end - end - - ShowMission(loc("Score"), - "-------", - showScore, 0, 200) - - HideMission() - -end - -function checkScore() -local showScore = "" -local lowest_score_team = nil -local min_score=nil -local winTeam = nil - -local only_low_score = true - - for i=0, TeamsCount-1 do - if teams[i]~=nil then - local curr_score = getTeamValue(teams[i], "Score") - - runOnHogsInTeam(removeFeeder, teams[i]) - - showScore = showScore .. teams[i] ..": " .. curr_score .. " (deaths: " .. getTeamValue(teams[i], "DeadHogs") .. ") " .. "|" - - if curr_score >= winScore then - gameOver = true - winTeam = teams[i] - end - - if min_score==nil then - min_score= curr_score - lowest_score_team = teams[i] - else - if curr_score <= min_score then - if curr_score == min_score then - if getTeamValue(teams[i], "DeadHogs") == getTeamValue(lowest_score_team, "DeadHogs") then - only_low_score = false - else - if getTeamValue(teams[i], "DeadHogs") > getTeamValue(lowest_score_team, "DeadHogs") then - lowest_score_team = teams[i] - end - only_low_score = true - end - - else - min_score= curr_score - lowest_score_team = teams[i] - only_low_score = true - end - end - end - end - end - - if gameOver then - TurnTimeLeft = 0 - for i=0, #teams do - if teams[i]~=winTeam then - runOnHogsInTeam(armageddon, teams[i]) - end - end - - ShowMission( loc("WINNER IS ") .. winTeam, - "~~~~~~~~~~~~~~~~~~~~~~~~~", - showScore, 0, 200) - else - - if only_low_score then - runOnHogsInTeam(setFeeder, lowest_score_team) - end - - if meh == false then - meh = true - else - ShowMission( loc("Score"), - loc("-------"), - showScore, 0, 200) - end - - end -end - -function backToNormal(gear) - SetHogName(gear, getGearValue(gear,"Name")) - SetHogHat(gear, 'NoHat') - SetHogHat(gear, getGearValue(gear,"Hat")) - setGearValue(mutant,"SelfDestruct",false) - mt_hurt=false - mutant=nil -end - -function setAIHints() - for i = 0, #hhs do - if mutant == nil or hhs[i] == mutant or CurrentHedgehog == mutant then - SetGearAIHints(hhs[i], aihUsual) - else - SetGearAIHints(hhs[i], aihDoesntMatter) - end - end -end - -function removeFeeder(gear) - if gear~=nil then - setGearValue(gear,"Feeder",false) - if gear~= mutant then - SetHogName(gear, getGearValue(gear,"Name") ) - SetHogHat(gear, 'NoHat') - SetHogHat(gear, getGearValue(gear,"Hat")) - end - end -end - -function setFeeder(gear) - if gear~= mutant and gear~= nil then - SetHogName(gear,"BOTTOM FEEDER") - SetHogHat(gear, 'poke_slowpoke') - setGearValue(gear,"Feeder", true) - end -end - -function setMutantStuff(gear) - mutant = gear - - SetHogName(gear,"MUTANT") - SetHogHat(gear,'WhySoSerious') - SetHealth(gear, ( mutant_base_health + numhhs*25) ) - SetEffect(gear, hePoisoned, 1) - setGearValue(mutant,"SelfDestruct",false) - setGearValue(gear, "Feeder", false) - - AddCaption(getGearValue(gear, "Name") .. loc(" HAS MUTATED")) - - TurnTimeLeft=0 - - AddVisualGear(GetX(gear), GetY(gear), vgtSmokeRing, 0, false) - AddVisualGear(GetX(gear), GetY(gear), vgtSmokeRing, 0, false) - AddVisualGear(GetX(gear), GetY(gear), vgtSmokeRing, 0, false) - AddVisualGear(GetX(gear), GetY(gear), vgtSmokeRing, 0, false) - AddVisualGear(GetX(gear), GetY(gear), vgtSmokeRing, 0, false) - PlaySound(sndSuddenDeath) -end - -function teamScan() - - for i=0, TeamsCount-1 do --nil filling - teams[i]=nil - end - - for i=0, #hhs do - for j=0, TeamsCount-1 do - if teams[j] ==nil and hhs[i]~=nil then - teams[j] = GetHogTeamName(hhs[i]) - setTeamValue(teams[j],"Score",0) - setTeamValue(teams[j], "DeadHogs",0) - break - end - - if teams[j] == GetHogTeamName(hhs[i]) then - break - end - end - end - - ---***--- -end - -function set_Mutant_and_Score(gear) - -local curr_team = GetHogTeamName(CurrentHedgehog) - - if gear == CurrentHedgehog then - if CurrentHedgehog == mutant then - PlaySound(sndHomerun) - if getGearValue(gear, "SelfDestruct")==false then - decreaseTeamValue(curr_team,"Score") - end - backToNormal(gear) - else - decreaseTeamValue(curr_team,"Score") - end - - else - if gear == mutant then - backToNormal(mutant) - if curr_team ~=GetHogTeamName(gear) then - if getGearValue(CurrentHedgehog, "Alive") then - setMutantStuff(CurrentHedgehog) - setTeamValue(curr_team,"Score",(getTeamValue(curr_team,"Score") + mutant_kill_reward)) - end - else - setTeamValue(curr_team,"Score",(getTeamValue(curr_team,"Score") - team_fire_punishment)) - end - else - if mutant==nil then - if curr_team ~=GetHogTeamName(gear) then - if getGearValue(CurrentHedgehog, "Alive") then - setMutantStuff(CurrentHedgehog) - setTeamValue(curr_team,"Score",(getTeamValue(curr_team,"Score") + mutant_kill_reward)) - else - increaseTeamValue(curr_team,"Score") - end - else - setTeamValue(curr_team,"Score",(getTeamValue(curr_team,"Score") - team_fire_punishment)) - end - else - if curr_team ~=GetHogTeamName(gear) then - if CurrentHedgehog==mutant and getGearValue(mutant,"SelfDestruct")==false then - SetHealth(CurrentHedgehog, GetHealth(CurrentHedgehog)+kill_reward) - AddCaption("+" .. kill_reward .. loc(" HP") ) - increaseTeamValue(curr_team,"Score") - end - if getGearValue(CurrentHedgehog,"Feeder") then - increaseTeamValue(curr_team,"Score") - end - else - setTeamValue(curr_team,"Score",(getTeamValue(curr_team,"Score") - team_fire_punishment)) - end - end - end - end -end - -function onGearResurrect(gear) -if not gameOver then - if GetGearType(gear) == gtHedgehog then - - increaseTeamValue(GetHogTeamName(gear), "DeadHogs") - - if gear==CurrentHedgehog then - setGearValue(CurrentHedgehog, "Alive", false) - end - set_Mutant_and_Score(gear) - if gear~=CurrentHedgehog then - killsCounter = killsCounter + 1 - countBodies() - end - AddVisualGear(GetX(gear), GetY(gear), vgtSmokeRing, 0, false) - PlaySound(sndWhack) - updateScore() - end -end -end - -function onGearAdd(gear) - - -- Catch hedgehogs for the tracker - if GetGearType(gear) == gtHedgehog then - trackGear(gear) - hhs[numhhs] = gear - numhhs = numhhs + 1 - SetEffect(gear, heResurrectable, 1) - end -end - -function checkEmptyTeam (teamName) - for i=0 , #hhs do - if hhs[i]~=nil then - if teamName == GetHogTeamName(hhs[i]) then - return false - end - end - end - return true -end - -function onGearDelete(gear) - -- Remove hogs that are gone - if GetGearType(gear) == gtHedgehog then - numhhs = numhhs - 1 - - local found - for i=0, #hhs do - if hhs[i] == gear then - found = i - break - end - end - for i = found, #hhs - 1 do - hhs[i] = hhs[i + 1] - end - hhs[#hhs] = nil - - local t_name = GetHogTeamName(gear) - if checkEmptyTeam(t_name) then - for i = 0, TeamsCount - 1 do - if teams[i] == t_name then - found = i - break - end - end - for i = found, TeamsCount - 2 do - teams[i] = teams[i + 1] - end - teams[TeamsCount - 1] = nil - TeamsCount = TeamsCount - 1 - end - AddVisualGear(GetX(gear), GetY(gear), vgtBigExplosion, 0, false) - trackDeletion(gear) - end -end - ---[[ -S T A R R I N G - prof - Coding, implementing and evangelism - vos - Initial idea and script improvements - mikade - Moving the `how to play` into the game so that people know `how to play`, and whitespace :D ---]] +local MUTANT_VERSION = "v0.9.5" + +--[[ ___ ___ + ( ) ( ) +___ .-. .-. ___ ___ | |_ .---. ___ .-. | |_ +( ) ' ( )( ( __) / .-, ( ) ( __) +| .-. .-. | | | | | | (__) ; || .-. .| | +| | | | | | | | | | | ___ .'` || | | || | ___ +| | | | | | | | | | |( / .'| || | | || |( ) +| | | | | | | | | | | | | / | || | | || | | | +| | | | | | | ; ' | ' | ; | ; || | | || ' | | +| | | | | ' `-' / ' `-' ' `-' || | | |' `-' ; +(___)(___)(___'.__.' `.__.`.__.'_(___)(___)`.__. + + +---- Recommended settings: +---- * one hedgehog per team +---- * 'Small' one-island map + +--]] + +HedgewarsScriptLoad("/Scripts/Locale.lua") +HedgewarsScriptLoad("/Scripts/Tracker.lua") +HedgewarsScriptLoad("/Scripts/Params.lua") + +--[[ + MUTANT SCRIPT + + To Do: -Clean-up this fucking piece of code + -Debug + -Find a girlfriend + -Fix Sheepluva's hat +[p] + -Cookies +-----------------------]] + +local hhs = {} +local numhhs = 0 +local meh = false + +local gameOver=false + +local mutant = nil +local mutant_base_health = 200 +local mutant_base_disease = 25 +local disease_timer = 2000 + +local kill_reward = nil +local mt_hurt=false + +local killsCounter = 0 + +local team_fire_punishment = 3 +local mutant_kill_reward = 2 + +local hh_weapons = { amBazooka, amGrenade, amShotgun, amMine} + +local mt_weapons = {amWatermelon, amHellishBomb, amBallgun, amRCPlane, amTeleport} + +local disease=0 +local timer=0 + +local winScore = 15 +local hogsLimit = 1 + +local teams = {} + +local circles = {} +local circleFrame = -1 + +function showStartingInfo() + + ruleSet = loc("RULES") .. ": " .. + " |" .. --" |" .. + loc("The first player to kill someone becomes the Mutant.") .. "|" .. + loc("The Mutant has super-weapons and a lot of health.") .. "|" .. + loc("The Mutant loses health quickly if he doesn't keep scoring kills.") .. "|" .. + " |" .. + loc("Normal players can only score points by killing the mutant.") .. "|" .. + " |" .. "" .. + loc("The player with least points (or most deaths) becomes the Bottom Feeder.") .. "|" .. + loc("The Bottom Feeder can score points by killing anyone.") .. "|" .. + " |" .. + loc("POINTS") .. ": " .. + " |" .. + loc("+2 for becoming a Mutant") .. "|" .. + loc("+1 to a Mutant for killing anyone") .. "|" .. + loc("+1 to a Bottom Feeder for killing anyone") .. "|" .. + loc("-1 to anyone for a suicide") .. "|" .. + loc("Other kills don't give you points.") + + ShowMission(loc("Mutant"), + loc("a Hedgewars tag game"), + ruleSet, 0, 5000) + +end + +function onGameInit() + TurnTime = 20000 + WaterRise = 0 + EnableGameFlags(gfResetWeps, gfPerHogAmmo) + HealthCaseProb=0 + HealthCaseAmount=0 + MinesTime=1000 + CaseFreq = 2 +end + + +function limitHogs(gear) + cnthhs = cnthhs + 1 + if cnthhs > 1 then + hogLimitHit = true + SetEffect(gear, heResurrectable, false) + --SetHealth(gear, 0) + SetGearPosition(gear, -100,LAND_HEIGHT) + end +end + +function onGameStart() + trackTeams() + teamScan() + runOnHogs(saveStuff) + --local str = "/say " .. MUTANT_VERSION + --ParseCommand(str) + + hogLimitHit = false + for i=0 , TeamsCount - 1 do + cnthhs = 0 + runOnHogsInTeam(limitHogs, teams[i]) + end + if hogLimitHit then + AddCaption(loc("ONE HOG PER TEAM! KILLING EXCESS HEDGES")) + end + showStartingInfo() +end + + + +function giveWeapons(gear) + if gear == mutant then + AddAmmo(gear, amRope) + for i=1, #mt_weapons do + AddAmmo(gear, mt_weapons[i]) + end + + else + for i=1, #hh_weapons do + AddAmmo(gear,hh_weapons[i]) + end + end +end + +function onAmmoStoreInit() + + SetAmmo(amSkip, 9, 0, 0, 0) + SetAmmo(amRope,0,1,0,5) + SetAmmo(amSnowball,0,1,0,1) + + for i=1, #hh_weapons do + SetAmmo(hh_weapons[i], 0, 0, 0, 1) + end + + for i=1, #mt_weapons do + SetAmmo(mt_weapons[i], 0, 3, 0, 1) + end + +end + +function drawCircles() + for i = 0, #hhs do + if circles[hhs[i]] ~= nil then + DeleteVisualGear(circles[hhs[i]]) + circles[hhs[i]] = nil + end + + if hhs[i] ~= CurrentHedgehog then + if mutant == nil then + circles[hhs[i]] = AddVisualGear(0, 0, vgtCircle, 0, false) + SetVisualGearValues(circles[hhs[i]], 0, 0, 0, 0, 0, 0, 0, 22, 5, 0xff000080) + elseif CurrentHedgehog == mutant then + circles[hhs[i]] = AddVisualGear(0, 0, vgtCircle, 0, false) + SetVisualGearValues(circles[hhs[i]], 0, 0, 0, 0, 0, 0, 0, 22, 3, 0xaa000070) + elseif getGearValue(CurrentHedgehog, "Feeder") and hhs[i] ~= mutant then + circles[hhs[i]] = AddVisualGear(0, 0, vgtCircle, 0, false) + SetVisualGearValues(circles[hhs[i]], 0, 0, 0, 0, 0, 0, 0, 22, 3, 0xaa000070) + elseif hhs[i] == mutant then + circles[hhs[i]] = AddVisualGear(0, 0, vgtCircle, 0, false) + SetVisualGearValues(circles[hhs[i]], 0, 0, 0, 0, 0, 0, 0, 22, 5, 0xff000080) + end + end + end + circleFrame = 0 +end + +function onNewTurn() + + trackTeams() + killsCounter = 0 + + if mutant == nil then + AddCaption( loc("FIRST BLOOD MUTATES") ) + end + + checkScore() + giveWeapons(CurrentHedgehog) + drawCircles() + setAIHints() + kill_reward= numhhs*10 + + if CurrentHedgehog == mutant then + mt_hurt=true + disease= mutant_base_disease - numhhs + else + mt_hurt=false + end + + setGearValue(CurrentHedgehog, "Alive", true) + +end + +function countBodies() + if killsCounter == 2 then + AddCaption(loc("DOUBLE KILL")) + elseif killsCounter == 3 then + AddCaption(loc("MEGA KILL")) + PlaySound(sndRegret) + elseif killsCounter == 4 then + AddCaption(loc("ULTRA KILL")) + elseif killsCounter == 5 then + AddCaption(loc("MONSTER KILL")) + PlaySound(sndIllGetYou) + elseif killsCounter == 6 then + AddCaption(loc("LUDICROUS KILL")) + PlaySound(sndNutter) + elseif killsCounter == 7 then + AddCaption(loc("HOLY SHYTE!")) + PlaySound(sndLaugh) + elseif killsCounter > 8 then + AddCaption(loc("INSANITY")) + end +end + +function onGameTick() + + if circleFrame > -1 then + for i = 0, #hhs do + if circles[hhs[i]] ~= nil and hhs[i]~= nil then + hhx, hhy = GetGearPosition(hhs[i]) + X, Y, dX, dY, Angle, Frame, FrameTicks, State, Timer, Tint = GetVisualGearValues(circles[hhs[i]]) + SetVisualGearValues(circles[hhs[i]], hhx + 1, hhy - 3, 0, 0, 0, 0, 0, 40 - (circleFrame % 25), Timer, Tint) + end + end + + circleFrame = circleFrame + 0.06 + + if circleFrame >= 25 then + for i = 0, #hhs do + if circles[hhs[i]] ~= nil then + DeleteVisualGear(circles[hhs[i]]) + circles[hhs[i]] = nil + end + end + end + end + + if TurnTimeLeft==0 and mt_hurt then + mt_hurt = false + end + + if mt_hurt and mutant~=nil then + timer = timer + 1 + if timer > disease_timer then + timer = 0 + SetHealth(mutant, GetHealth(mutant)-disease ) + AddVisualGear(GetX(mutant), GetY(mutant)-5, vgtHealthTag, disease, true) + if GetHealth(mutant)<=0 then + SetHealth(mutant,0) + mt_hurt= false + setGearValue(mutant,"SelfDestruct",true) + TurnTimeLeft = 0 + end + end + end + +end + +function saveStuff(gear) + setGearValue(gear,"Name",GetHogName(gear)) + setGearValue(gear,"Hat",GetHogHat(gear)) +end + +function armageddon(gear) + SetState(gear, gstLoser) + SetEffect(gear, heResurrectable, false) + SetHealth(gear, 0) +end + +function updateScore() + + local showScore = "" + + for i=0, TeamsCount-1 do + if teams[i]~= nil then + + local curr_score = getTeamValue(teams[i], "Score") + showScore = showScore .. teams[i] .. ": " .. curr_score .. " (" .. loc("deaths") .. ": " .. getTeamValue(teams[i], "DeadHogs") .. ") " .. "|" + + end + end + + ShowMission(loc("Score"), + "-------", + showScore, 0, 200) + + HideMission() + +end + +function checkScore() +local showScore = "" +local lowest_score_team = nil +local min_score=nil +local winTeam = nil + +local only_low_score = true + + for i=0, TeamsCount-1 do + if teams[i]~=nil then + local curr_score = getTeamValue(teams[i], "Score") + + runOnHogsInTeam(removeFeeder, teams[i]) + + showScore = showScore .. teams[i] ..": " .. curr_score .. " (" .. loc("deaths") .. ": " .. getTeamValue(teams[i], "DeadHogs") .. ") " .. "|" + + if curr_score >= winScore then + gameOver = true + winTeam = teams[i] + end + + if min_score==nil then + min_score= curr_score + lowest_score_team = teams[i] + else + if curr_score <= min_score then + if curr_score == min_score then + if getTeamValue(teams[i], "DeadHogs") == getTeamValue(lowest_score_team, "DeadHogs") then + only_low_score = false + else + if getTeamValue(teams[i], "DeadHogs") > getTeamValue(lowest_score_team, "DeadHogs") then + lowest_score_team = teams[i] + end + only_low_score = true + end + + else + min_score= curr_score + lowest_score_team = teams[i] + only_low_score = true + end + end + end + end + end + + if gameOver then + TurnTimeLeft = 0 + for i=0, #teams do + if teams[i]~=winTeam then + runOnHogsInTeam(armageddon, teams[i]) + end + end + + ShowMission( loc("WINNER IS ") .. winTeam, + "~~~~~~~~~~~~~~~~~~~~~~~~~", + showScore, 0, 200) + else + + if only_low_score then + runOnHogsInTeam(setFeeder, lowest_score_team) + end + + if meh == false then + meh = true + else + ShowMission( loc("Score"), + loc("-------"), + showScore, 0, 200) + end + + end +end + +function backToNormal(gear) + SetHogName(gear, getGearValue(gear,"Name")) + SetHogHat(gear, 'NoHat') + SetHogHat(gear, getGearValue(gear,"Hat")) + setGearValue(mutant,"SelfDestruct",false) + mt_hurt=false + mutant=nil +end + +function setAIHints() + for i = 0, #hhs do + if mutant == nil or hhs[i] == mutant or CurrentHedgehog == mutant or getGearValue(CurrentHedgehog, "Feeder") then + SetGearAIHints(hhs[i], aihUsual) + else + SetGearAIHints(hhs[i], aihDoesntMatter) + end + end +end + +function removeFeeder(gear) + if gear~=nil then + setGearValue(gear,"Feeder",false) + if gear~= mutant then + SetHogName(gear, getGearValue(gear,"Name") ) + SetHogHat(gear, 'NoHat') + SetHogHat(gear, getGearValue(gear,"Hat")) + end + end +end + +function setFeeder(gear) + if gear~= mutant and gear~= nil then + SetHogName(gear, loc("BOTTOM FEEDER")) + SetHogHat(gear, 'poke_slowpoke') + setGearValue(gear,"Feeder", true) + end +end + +function setMutantStuff(gear) + mutant = gear + + SetHogName(gear, loc("MUTANT")) + SetHogHat(gear,'WhySoSerious') + SetHealth(gear, ( mutant_base_health + numhhs*25) ) + SetEffect(gear, hePoisoned, 1) + setGearValue(mutant,"SelfDestruct",false) + setGearValue(gear, "Feeder", false) + + AddCaption(getGearValue(gear, "Name") .. loc(" HAS MUTATED")) + + TurnTimeLeft=0 + + AddVisualGear(GetX(gear), GetY(gear), vgtSmokeRing, 0, false) + AddVisualGear(GetX(gear), GetY(gear), vgtSmokeRing, 0, false) + AddVisualGear(GetX(gear), GetY(gear), vgtSmokeRing, 0, false) + AddVisualGear(GetX(gear), GetY(gear), vgtSmokeRing, 0, false) + AddVisualGear(GetX(gear), GetY(gear), vgtSmokeRing, 0, false) + PlaySound(sndSuddenDeath) +end + +function teamScan() + + for i=0, TeamsCount-1 do --nil filling + teams[i]=nil + end + + for i=0, #hhs do + for j=0, TeamsCount-1 do + if teams[j] ==nil and hhs[i]~=nil then + teams[j] = GetHogTeamName(hhs[i]) + setTeamValue(teams[j],"Score",0) + setTeamValue(teams[j], "DeadHogs",0) + break + end + + if teams[j] == GetHogTeamName(hhs[i]) then + break + end + end + end + + ---***--- +end + +function set_Mutant_and_Score(gear) + +local curr_team = GetHogTeamName(CurrentHedgehog) + + if gear == CurrentHedgehog then + if CurrentHedgehog == mutant then + PlaySound(sndHomerun) + if getGearValue(gear, "SelfDestruct")==false then + decreaseTeamValue(curr_team,"Score") + end + backToNormal(gear) + else + decreaseTeamValue(curr_team,"Score") + end + + else + if gear == mutant then + backToNormal(mutant) + if curr_team ~=GetHogTeamName(gear) then + if getGearValue(CurrentHedgehog, "Alive") then + setMutantStuff(CurrentHedgehog) + setTeamValue(curr_team,"Score",(getTeamValue(curr_team,"Score") + mutant_kill_reward)) + end + else + setTeamValue(curr_team,"Score",(getTeamValue(curr_team,"Score") - team_fire_punishment)) + end + else + if mutant==nil then + if curr_team ~=GetHogTeamName(gear) then + if getGearValue(CurrentHedgehog, "Alive") then + setMutantStuff(CurrentHedgehog) + setTeamValue(curr_team,"Score",(getTeamValue(curr_team,"Score") + mutant_kill_reward)) + else + increaseTeamValue(curr_team,"Score") + end + else + setTeamValue(curr_team,"Score",(getTeamValue(curr_team,"Score") - team_fire_punishment)) + end + else + if curr_team ~=GetHogTeamName(gear) then + if CurrentHedgehog==mutant and getGearValue(mutant,"SelfDestruct")==false then + SetHealth(CurrentHedgehog, GetHealth(CurrentHedgehog)+kill_reward) + AddCaption("+" .. kill_reward .. loc(" HP") ) + increaseTeamValue(curr_team,"Score") + end + if getGearValue(CurrentHedgehog,"Feeder") then + increaseTeamValue(curr_team,"Score") + end + else + setTeamValue(curr_team,"Score",(getTeamValue(curr_team,"Score") - team_fire_punishment)) + end + end + end + end +end + +function onGearResurrect(gear) +if not gameOver then + if GetGearType(gear) == gtHedgehog then + + increaseTeamValue(GetHogTeamName(gear), "DeadHogs") + + if gear==CurrentHedgehog then + setGearValue(CurrentHedgehog, "Alive", false) + end + set_Mutant_and_Score(gear) + if gear~=CurrentHedgehog then + killsCounter = killsCounter + 1 + countBodies() + end + AddVisualGear(GetX(gear), GetY(gear), vgtSmokeRing, 0, false) + PlaySound(sndWhack) + updateScore() + end +end +end + +function onGearAdd(gear) + + -- Catch hedgehogs for the tracker + if GetGearType(gear) == gtHedgehog then + trackGear(gear) + hhs[numhhs] = gear + numhhs = numhhs + 1 + SetEffect(gear, heResurrectable, 1) + end +end + +function checkEmptyTeam (teamName) + for i=0 , #hhs do + if hhs[i]~=nil then + if teamName == GetHogTeamName(hhs[i]) then + return false + end + end + end + return true +end + +function onGearDelete(gear) + -- Remove hogs that are gone + if GetGearType(gear) == gtHedgehog then + numhhs = numhhs - 1 + + local found + for i=0, #hhs do + if hhs[i] == gear then + found = i + break + end + end + for i = found, #hhs - 1 do + hhs[i] = hhs[i + 1] + end + hhs[#hhs] = nil + + local t_name = GetHogTeamName(gear) + if checkEmptyTeam(t_name) then + for i = 0, TeamsCount - 1 do + if teams[i] == t_name then + found = i + break + end + end + for i = found, TeamsCount - 2 do + teams[i] = teams[i + 1] + end + teams[TeamsCount - 1] = nil + TeamsCount = TeamsCount - 1 + end + AddVisualGear(GetX(gear), GetY(gear), vgtBigExplosion, 0, false) + trackDeletion(gear) + end +end + +function onParameters() + parseParams() + winScore = tonumber(params["winscore"]) or winScore +end + +--[[ +S T A R R I N G + prof - Coding, implementing and evangelism + vos - Initial idea and script improvements + mikade - Moving the `how to play` into the game so that people know `how to play`, and whitespace :D +--]] diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Scripts/Multiplayer/No_Jumping.cfg --- a/share/hedgewars/Data/Scripts/Multiplayer/No_Jumping.cfg Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Scripts/Multiplayer/No_Jumping.cfg Tue Nov 10 20:43:13 2015 +0100 @@ -1,2 +1,2 @@ -Default -Default +* +* diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Scripts/Multiplayer/Racer.lua --- a/share/hedgewars/Data/Scripts/Multiplayer/Racer.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Scripts/Multiplayer/Racer.lua Tue Nov 10 20:43:13 2015 +0100 @@ -1,720 +1,785 @@ - ------------------------------------------- --- RACER 0.6 --- map-independant racing script --- by mikade ------------------------------------------ - ------------------------------------ ---0.1: took all the code from crazy racer and scrapped most of it ------------------------------------ - --- Removed tumbler system --- Removed extra adds like boosters etc --- Added experimental waypoint placement system --- More user feedback --- Reduced race complexity limit to 5 waypoints --- stop placement at complexity limit reached and end turn --- guys dont keep racing after dying --- invulnerable feasibility --- reverted time keeping method --- reduced feedback display time --- colour-coded addcaptions --- cleaned up code --- support for more players properly added --- tardis fix --- remove airstrikes - --- i think the remainder 0 .456 sec of the tracktime isnt getting reset on newturn - --- update feedback - -------- --- 0.2 -------- - --- allow gameflags --- extend time to 90s --- remove other air-attack based weps --- turn off water rise for sd - -------- --- 0.3 -------- - --- prevent WP being placed in land --- prevent waypoints being placed outside border - -------- --- 0.4 -------- - --- update user feedback --- add more sounds - -------- --- 0.5 -------- - --- fix ghost disappearing if hog falls in water or somehow dies --- lengthen ghost tracking interval to improve performance on slower machines --- increase waypoint limit to 8 --- allow for persistent showmission information - -------- --- 0.6 -------- - --- remove hogs from racing area as per request - ------------------------------ --- SCRIPT BEGINS ------------------------------ - -HedgewarsScriptLoad("/Scripts/Locale.lua") - ------------------- --- Got Variables? ------------------- - -local fMod = 1000000 -- 1 -local roundLimit = 3 -local roundNumber = 0 -local firstClan = 10 - -local fastX = {} -local fastY = {} -local fastCount = 0 -local fastIndex = 0 -local fastColour - -local currX = {} -local currY = {} -local currCount = 0 - -local specialPointsX = {} -local specialPointsY = {} -local specialPointsCount = 0 - --------------------------- --- hog and team tracking variales --------------------------- - -local numhhs = 0 -- store number of hedgehogs -local hhs = {} -- store hedgehog gears - -local numTeams -- store the number of teams in the game -local teamNameArr = {} -- store the list of teams -local teamClan = {} -local teamSize = {} -- store how many hogs per team -local teamIndex = {} -- at what point in the hhs{} does each team begin - -local teamComment = {} -local teamScore = {} - -------- --- racer vars --------- - -local cGear = nil - -local bestClan = nil -local bestTime = nil - -local gameBegun = false -local gameOver = false -local racerActive = false -local trackTime = 0 - -local wpCirc = {} -local wpX = {} -local wpY = {} -local wpCol = {} -local wpActive = {} -local wpRad = 450 --75 -local wpCount = 0 -local wpLimit = 8 - -local roundN -local lastRound -local RoundHasChanged - -------------------- --- general methods -------------------- - -function RebuildTeamInfo() - - - -- make a list of individual team names - for i = 0, (TeamsCount-1) do - teamNameArr[i] = " " -- = i - teamSize[i] = 0 - teamIndex[i] = 0 - teamScore[i] = 100000 - end - numTeams = 0 - - for i = 0, (numhhs-1) do - - z = 0 - unfinished = true - while(unfinished == true) do - - newTeam = true - tempHogTeamName = GetHogTeamName(hhs[i]) -- this is the new name - - if tempHogTeamName == teamNameArr[z] then - newTeam = false - unfinished = false - end - - z = z + 1 - - if z == TeamsCount then - unfinished = false - if newTeam == true then - teamNameArr[numTeams] = tempHogTeamName - numTeams = numTeams + 1 - end - end - - end - - end - - -- find out how many hogs per team, and the index of the first hog in hhs - for i = 0, (numTeams-1) do - for z = 0, (numhhs-1) do - if GetHogTeamName(hhs[z]) == teamNameArr[i] then - teamClan[i] = GetHogClan(hhs[z]) - if teamSize[i] == 0 then - teamIndex[i] = z -- should give starting index - end - teamSize[i] = teamSize[i] + 1 - --add a pointer so this hog appears at i in hhs - end - end - - end - -end - - ------------------ --- RACER METHODS ------------------ - -function CheckWaypoints() - - trackFinished = true - - for i = 0, (wpCount-1) do - - g1X, g1Y = GetGearPosition(CurrentHedgehog) - g2X, g2Y = wpX[i], wpY[i] - - g1X = g1X - g2X - g1Y = g1Y - g2Y - dist = (g1X*g1X) + (g1Y*g1Y) - - --if i == 0 then - -- AddCaption(dist .. "/" .. (wpRad*wpRad) ) - --end - - NR = (48/100*wpRad)/2 - - if dist < (NR*NR) then - --if dist < (wpRad*wpRad) then - --AddCaption("howdy") - wpActive[i] = true - wpCol[i] = GetClanColor(GetHogClan(CurrentHedgehog)) -- new --GetClanColor(1) - SetVisualGearValues(wpCirc[i], wpX[i], wpY[i], 20, 100, 1, 10, 0, wpRad, 5, wpCol[i]) - - wpRem = 0 - for k = 0, (wpCount-1) do - if wpActive[k] == false then - wpRem = wpRem + 1 - end - end - - AddCaption(loc("Way-Points Remaining") .. ": " .. wpRem,0xffba00ff,capgrpAmmoinfo) - - end - - if wpActive[i] == false then - trackFinished = false - end - - end - - return(trackFinished) - -end - -function AdjustScores() - - if bestTime == nil then - bestTime = 100000 - bestClan = 10 - bestTimeComment = "N/A" - end - - newScore = false - - -- update this clan's time if the new track is better - for i = 0, (numTeams-1) do - if teamClan[i] == GetHogClan(CurrentHedgehog) then - if trackTime < teamScore[i] then - teamScore[i] = trackTime - newScore = true - else - newScore = false - end - end - end - - --bestTime = 100000 - --bestClan = 10 - - -- find the best time out of those so far - for i = 0, (numTeams-1) do - if teamScore[i] < bestTime then - bestTime = teamScore[i] - bestClan = teamClan[i] - end - end - - if bestTime ~= 100000 then - bestTimeComment = (bestTime/1000) ..loc("s") - end - - if newScore == true then - if trackTime == bestTime then -- best time of the race - ShowMission(loc("RACER"), - loc("TRACK COMPLETED"), - loc("NEW RACE RECORD: ") .. (trackTime/1000) ..loc("s") .. "|" .. - loc("WINNING TIME: ") .. bestTimeComment, 0, 4000) - PlaySound(sndHomerun) - else -- best time for the clan - ShowMission(loc("RACER"), - loc("TRACK COMPLETED"), - loc("NEW CLAN RECORD: ") .. (trackTime/1000) ..loc("s") .. "|" .. - loc("WINNING TIME: ") .. bestTimeComment, 4, 4000) - end - else -- not any kind of new score - ShowMission(loc("RACER"), - loc("TRACK COMPLETED"), - loc("TIME: ") .. (trackTime/1000) ..loc("s") .. "|" .. - loc("WINNING TIME: ") .. bestTimeComment, -amSkip, 4000) - PlaySound(sndHellish) - end - - - -------- - --new - -------- - - if bestTime == trackTime then - --AddCaption("wooooooooooooooooooooooooooooo") - - fastColour = GetClanColor(GetHogClan(CurrentHedgehog)) - - for i = 0, (currCount-1) do - fastX[i] = currX[i] - fastY[i] = currY[i] - end - - fastCount = currCount - fastIndex = 0 - - --currCount = 0 -- is this needed? - - else - currCount = 0 - fastIndex = 0 - end - - -end - -function onNewRound() - - roundNumber = roundNumber + 1 - - totalComment = "" - for i = 0, (TeamsCount-1) do - if teamNameArr[i] ~= " " then -- teamScore[teamClan[i]] - teamComment[i] = teamNameArr[i] .. ": " .. (teamScore[i]/1000) .. loc("s|") - totalComment = totalComment .. teamComment[i] - elseif teamNameArr[i] == " " then - teamComment[i] = "|" - end - end - - ShowMission( loc("RACER"), - loc("STATUS UPDATE"), - loc("Rounds Complete: ") .. roundNumber .. "/" .. roundLimit .. "|" .. " " .. "|" .. - loc("Best Team Times: ") .. "|" .. totalComment, 0, 4000) - - -- end game if its at round limit - if roundNumber == roundLimit then - for i = 0, (numhhs-1) do - if GetHogClan(hhs[i]) ~= bestClan then - SetEffect(hhs[i], heResurrectable, 0) - SetHealth(hhs[i],0) - end - end - gameOver = true - TurnTimeLeft = 1 - end - -end - -function CheckForNewRound() - - ------------- - ------ new - ------------- - - --[[turnN = turnN + 1 - if gameBegun == false then - if turnN == 2 then - for i = 0, (numhhs-1) do - if hhs[i] ~= nil then - SetEffect(hhs[i], heResurrectable, 0) - SetHealth(hhs[i],0) - end - end - gameOver = true - TurnTimeLeft = 1 - end - else - - - end]] - - --[[if roundBegun == true then - - if RoundHasChanged == true then - roundN = roundN + 1 - RoundHasChanged = false - onNewRound() - end - - if lastRound ~= TotalRounds then -- new round, but not really - - if RoundHasChanged == false then - RoundHasChanged = true - end - - end - - AddCaption("RoundN:" .. roundN .. "; " .. "TR: " .. TotalRounds) - - lastRound = TotalRounds - - end]] - - ------------ - ----- old - ------------ - - if GetHogClan(CurrentHedgehog) == firstClan then - onNewRound() - end - -end - -function DisableTumbler() - currCount = 0 - fastIndex = 0 - TurnTimeLeft = 0 - racerActive = false -- newadd -end - -function HandleGhost() - - -- get the current xy of the racer at this point - currX[currCount] = GetX(CurrentHedgehog) - currY[currCount] = GetY(CurrentHedgehog) - currCount = currCount + 1 - - -- draw a ping of smoke where the fastest player was at this point - if (fastCount ~= 0) and (fastIndex < fastCount) then - - fastIndex = fastIndex + 1 - - tempE = AddVisualGear(fastX[fastIndex], fastY[fastIndex], vgtSmoke, 0, false) - g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(tempE) - SetVisualGearValues(tempE, g1, g2, g3, g4, g5, g6, g7, g8, g9, fastColour ) - - --AddCaption("fC: " .. fastIndex .. " / " .. fastCount) - - else - - --AddCaption("excep fC: " .. fastIndex .. " / " .. fastCount) - - end - - - -end - -function TryRepositionHogs() - - if MapHasBorder() == true then - - for i = 0, (numhhs-1) do - if hhs[i] ~= nil then - SetGearPosition(hhs[i],GetX(hhs[i]), TopY-10) - end - end - - end - -end - ----------------------------------- --- GAME METHODS / EVENT HANDLERS ----------------------------------- - -function onGameInit() - GameFlags = bor(GameFlags,gfInfAttack + gfInvulnerable) - CaseFreq = 0 - TurnTime = 90000 - WaterRise = 0 -end - - -function onGameStart() - - roundN = 0 - lastRound = TotalRounds - RoundHasChanged = false -- true - - for i = 0, (specialPointsCount-1) do - PlaceWayPoint(specialPointsX[i], specialPointsY[i]) - end - - RebuildTeamInfo() - - ShowMission ( - loc("RACER"), - loc("a Hedgewars mini-game"), - - loc("Build a track and race.") .. "|" .. - loc("Round Limit:") .. " " .. roundLimit .. "|" .. - - "", 4, 4000 - ) - - TryRepositionHogs() - -end - -function PlaceWayPoint(x,y) - - if (wpCount < wpLimit) then -- seems to not work with a hedgehog nil chek - - wpX[wpCount] = x - wpY[wpCount] = y - wpCol[wpCount] = 0xffffffff - wpCirc[wpCount] = AddVisualGear(wpX[wpCount],wpY[wpCount],vgtCircle,0,true) - --100 - SetVisualGearValues(wpCirc[wpCount], wpX[wpCount], wpY[wpCount], 20, 100, 1, 10, 0, wpRad, 5, wpCol[wpCount]) - - wpCount = wpCount + 1 - - AddCaption(loc("Waypoint placed.") .. " " .. loc("Available points remaining: ") .. (wpLimit-wpCount)) - - end - -end - -function onSpecialPoint(x,y,flag) - specialPointsX[specialPointsCount] = x - specialPointsY[specialPointsCount] = y - specialPointsCount = specialPointsCount + 1 -end - -function onNewTurn() - - CheckForNewRound() - TryRepositionHogs() - - racerActive = false - - trackTime = 0 - - currCount = 0 -- hopefully this solves problem - AddAmmo(CurrentHedgehog, amAirAttack, 0) - gTimer = 0 - - -- Set the waypoints to unactive on new round - for i = 0,(wpCount-1) do - wpActive[i] = false - wpCol[i] = 0xffffffff - SetVisualGearValues(wpCirc[i], wpX[i], wpY[i], 20, 100, 1, 10, 0, wpRad, 5, wpCol[i]) - end - - -- Handle Starting Stage of Game - if (gameOver == false) and (gameBegun == false) then - if wpCount >= 3 then - gameBegun = true - roundNumber = 0 - firstClan = GetHogClan(CurrentHedgehog) - ShowMission(loc("RACER"), - loc("GAME BEGUN!!!"), - loc("Complete the track as fast as you can!"), 2, 4000) - else - ShowMission(loc("RACER"), - loc("NOT ENOUGH WAYPOINTS"), - loc("Place more waypoints using the 'Air Attack' weapon."), 2, 4000) - AddAmmo(CurrentHedgehog, amAirAttack, 4000) - ParseCommand("setweap " .. string.char(amAirAttack)) - end - end - - if gameOver == true then - gameBegun = false - racerActive = false -- newadd - end - - AddAmmo(CurrentHedgehog, amTardis, 0) - AddAmmo(CurrentHedgehog, amDrillStrike, 0) - AddAmmo(CurrentHedgehog, amMineStrike, 0) - AddAmmo(CurrentHedgehog, amNapalm, 0) - AddAmmo(CurrentHedgehog, amPiano, 0) - -end - -function onGameTick20() - - -- airstrike detected, convert this into a potential waypoint spot - if cGear ~= nil then - x,y = GetGearPosition(cGear) - if x > -9000 then - x,y = GetGearTarget(cGear) - - - if TestRectForObstacle(x-20, y-20, x+20, y+20, true) then - AddCaption(loc("Please place the way-point in the open, within the map boundaries.")) - PlaySound(sndDenied) - elseif (y > WaterLine-50) then - AddCaption(loc("Please place the way-point further from the waterline.")) - PlaySound(sndDenied) - else - PlaceWayPoint(x, y) - if wpCount == wpLimit then - AddCaption(loc("Race complexity limit reached.")) - DisableTumbler() - end - end - else - DeleteGear(cGear) - end - SetGearPosition(cGear, -10000, 0) - end - - - -- start the player tumbling with a boom once their turn has actually begun - if racerActive == false then - - if (TurnTimeLeft > 0) and (TurnTimeLeft ~= TurnTime) then - - -- if the gamehas started put the player in the middle of the first - --waypoint that was placed - if gameBegun == true then - AddCaption(loc("Good to go!")) - racerActive = true - trackTime = 0 - - SetGearPosition(CurrentHedgehog, wpX[0], wpY[0]) - AddGear(GetX(CurrentHedgehog), GetY(CurrentHedgehog), gtGrenade, 0, 0, 0, 1) - FollowGear(CurrentHedgehog) - - HideMission() - - else - -- still in placement mode - end - - end - end - - - - -- has the player started his tumbling spree? - if (CurrentHedgehog ~= nil) then - - --airstrike conversion used to be here - - -- if the RACE has started, show tracktimes and keep tabs on waypoints - if (racerActive == true) and (gameBegun == true) then - - --ghost - if GameTime%40 == 0 then - HandleGhost() - end - - trackTime = trackTime + 20 - - if GameTime%100 == 0 then - - if trackTime%1000 == 0 then - AddCaption((trackTime/1000)..'.0',GetClanColor(GetHogClan(CurrentHedgehog)),capgrpMessage2) - else - AddCaption(trackTime/1000,GetClanColor(GetHogClan(CurrentHedgehog)),capgrpMessage2) - end - - if (CheckWaypoints() == true) then - AdjustScores() - racerActive = false - DisableTumbler() - end - - end - - end - - -- if the player has expended his tunbling time, stop him tumbling - if TurnTimeLeft <= 20 then - DisableTumbler() - end - - end - -end - -function onGearResurrect(gear) - - AddVisualGear(GetX(gear), GetY(gear), vgtBigExplosion, 0, false) - - if gear == CurrentHedgehog then - DisableTumbler() - end - -end - -function onGearAdd(gear) - - if GetGearType(gear) == gtHedgehog then - hhs[numhhs] = gear - numhhs = numhhs + 1 - SetEffect(gear, heResurrectable, 1) - end - - if GetGearType(gear) == gtAirAttack then - cGear = gear - end - -end - -function onGearDelete(gear) - - if GetGearType(gear) == gtAirAttack then - cGear = nil - end - -end + +------------------------------------------ +-- RACER 0.6 +-- map-independant racing script +-- by mikade +----------------------------------------- + +----------------------------------- +--0.1: took all the code from crazy racer and scrapped most of it +----------------------------------- + +-- Removed tumbler system +-- Removed extra adds like boosters etc +-- Added experimental waypoint placement system +-- More user feedback +-- Reduced race complexity limit to 5 waypoints +-- stop placement at complexity limit reached and end turn +-- guys dont keep racing after dying +-- invulnerable feasibility +-- reverted time keeping method +-- reduced feedback display time +-- colour-coded addcaptions +-- cleaned up code +-- support for more players properly added +-- tardis fix +-- remove airstrikes + +-- i think the remainder 0 .456 sec of the tracktime isnt getting reset on newturn + +-- update feedback + +------- +-- 0.2 +------- + +-- allow gameflags +-- extend time to 90s +-- remove other air-attack based weps +-- turn off water rise for sd + +------- +-- 0.3 +------- + +-- prevent WP being placed in land +-- prevent waypoints being placed outside border + +------- +-- 0.4 +------- + +-- update user feedback +-- add more sounds + +------- +-- 0.5 +------- + +-- fix ghost disappearing if hog falls in water or somehow dies +-- lengthen ghost tracking interval to improve performance on slower machines +-- increase waypoint limit to 8 +-- allow for persistent showmission information + +------- +-- 0.6 +------- + +-- remove hogs from racing area as per request + +------- +-- 0.7 +------- + +-- switch to first available weapon if starting race with no weapon selected + +----------------------------- +-- SCRIPT BEGINS +----------------------------- + +HedgewarsScriptLoad("/Scripts/Locale.lua") +HedgewarsScriptLoad("/Scripts/OfficialChallenges.lua") +HedgewarsScriptLoad("/Scripts/Params.lua") + +------------------ +-- Got Variables? +------------------ + +local fMod = 1000000 -- 1 +local roundLimit = 3 +local roundNumber = 0 +local firstClan = 10 + +local fastX = {} +local fastY = {} +local fastCount = 0 +local fastIndex = 0 +local fastColour + +local currX = {} +local currY = {} +local currCount = 0 + +local specialPointsX = {} +local specialPointsY = {} +local specialPointsCount = 0 + +local TeamRope = false + +-------------------------- +-- hog and team tracking variales +-------------------------- + +local numhhs = 0 -- store number of hedgehogs +local hhs = {} -- store hedgehog gears + +local numTeams -- store the number of teams in the game +local teamNameArr = {} -- store the list of teams +local teamClan = {} +local teamSize = {} -- store how many hogs per team +local teamIndex = {} -- at what point in the hhs{} does each team begin + +local teamComment = {} +local teamScore = {} + +------- +-- racer vars +-------- + +local cGear = nil + +local bestClan = nil +local bestTime = nil + +local gameBegun = false +local gameOver = false +local racerActive = false +local trackTime = 0 + +local wpCirc = {} +local wpX = {} +local wpY = {} +local wpCol = {} +local wpActive = {} +local wpRad = 450 --75 +local wpCount = 0 +local wpLimit = 8 + +local usedWeapons = {} + +local roundN +local lastRound +local RoundHasChanged + +------------------- +-- general methods +------------------- + +function onParameters() + parseParams() + if params["teamrope"] ~= nil then + TeamRope = true + end +end + +function RebuildTeamInfo() + + + -- make a list of individual team names + for i = 0, (TeamsCount-1) do + teamNameArr[i] = " " -- = i + teamSize[i] = 0 + teamIndex[i] = 0 + teamScore[i] = 100000 + end + numTeams = 0 + + for i = 0, (numhhs-1) do + + z = 0 + unfinished = true + while(unfinished == true) do + + newTeam = true + tempHogTeamName = GetHogTeamName(hhs[i]) -- this is the new name + + if tempHogTeamName == teamNameArr[z] then + newTeam = false + unfinished = false + end + + z = z + 1 + + if z == TeamsCount then + unfinished = false + if newTeam == true then + teamNameArr[numTeams] = tempHogTeamName + numTeams = numTeams + 1 + end + end + + end + + end + + -- find out how many hogs per team, and the index of the first hog in hhs + for i = 0, (numTeams-1) do + for z = 0, (numhhs-1) do + if GetHogTeamName(hhs[z]) == teamNameArr[i] then + teamClan[i] = GetHogClan(hhs[z]) + if teamSize[i] == 0 then + teamIndex[i] = z -- should give starting index + end + teamSize[i] = teamSize[i] + 1 + --add a pointer so this hog appears at i in hhs + end + end + + end + +end + + +----------------- +-- RACER METHODS +----------------- + +function CheckWaypoints() + + trackFinished = true + + for i = 0, (wpCount-1) do + + g1X, g1Y = GetGearPosition(CurrentHedgehog) + g2X, g2Y = wpX[i], wpY[i] + + g1X = g1X - g2X + g1Y = g1Y - g2Y + dist = (g1X*g1X) + (g1Y*g1Y) + + --if i == 0 then + -- AddCaption(dist .. "/" .. (wpRad*wpRad) ) + --end + + NR = (48/100*wpRad)/2 + + if dist < (NR*NR) then + --if dist < (wpRad*wpRad) then + --AddCaption("howdy") + wpActive[i] = true + wpCol[i] = GetClanColor(GetHogClan(CurrentHedgehog)) -- new --GetClanColor(1) + SetVisualGearValues(wpCirc[i], wpX[i], wpY[i], 20, 100, 1, 10, 0, wpRad, 5, wpCol[i]) + + wpRem = 0 + for k = 0, (wpCount-1) do + if wpActive[k] == false then + wpRem = wpRem + 1 + end + end + + AddCaption(loc("Way-Points Remaining") .. ": " .. wpRem,0xffba00ff,capgrpAmmoinfo) + + end + + if wpActive[i] == false then + trackFinished = false + end + + end + + return(trackFinished) + +end + +function AdjustScores() + + if bestTime == nil then + bestTime = 100000 + bestClan = 10 + bestTimeComment = "N/A" + end + + newScore = false + + -- update this clan's time if the new track is better + for i = 0, (numTeams-1) do + if teamClan[i] == GetHogClan(CurrentHedgehog) then + if trackTime < teamScore[i] then + teamScore[i] = trackTime + newScore = true + else + newScore = false + end + end + end + + --bestTime = 100000 + --bestClan = 10 + + -- find the best time out of those so far + for i = 0, (numTeams-1) do + if teamScore[i] < bestTime then + bestTime = teamScore[i] + bestClan = teamClan[i] + end + end + + if bestTime ~= 100000 then + bestTimeComment = (bestTime/1000) ..loc("s") + end + + if newScore == true then + if trackTime == bestTime then -- best time of the race + ShowMission(loc("RACER"), + loc("TRACK COMPLETED"), + loc("NEW RACE RECORD: ") .. (trackTime/1000) ..loc("s") .. "|" .. + loc("WINNING TIME: ") .. bestTimeComment, 0, 4000) + PlaySound(sndHomerun) + else -- best time for the clan + ShowMission(loc("RACER"), + loc("TRACK COMPLETED"), + loc("NEW CLAN RECORD: ") .. (trackTime/1000) ..loc("s") .. "|" .. + loc("WINNING TIME: ") .. bestTimeComment, 4, 4000) + end + else -- not any kind of new score + ShowMission(loc("RACER"), + loc("TRACK COMPLETED"), + loc("TIME: ") .. (trackTime/1000) ..loc("s") .. "|" .. + loc("WINNING TIME: ") .. bestTimeComment, -amSkip, 4000) + PlaySound(sndHellish) + end + + + -------- + --new + -------- + + if bestTime == trackTime then + --AddCaption("wooooooooooooooooooooooooooooo") + + fastColour = GetClanColor(GetHogClan(CurrentHedgehog)) + + for i = 0, (currCount-1) do + fastX[i] = currX[i] + fastY[i] = currY[i] + end + + fastCount = currCount + fastIndex = 0 + + --currCount = 0 -- is this needed? + + else + currCount = 0 + fastIndex = 0 + end + + +end + +function onNewRound() + + roundNumber = roundNumber + 1 + + totalComment = "" + for i = 0, (TeamsCount-1) do + if teamNameArr[i] ~= " " then -- teamScore[teamClan[i]] + teamComment[i] = teamNameArr[i] .. ": " .. (teamScore[i]/1000) .. loc("s|") + totalComment = totalComment .. teamComment[i] + elseif teamNameArr[i] == " " then + teamComment[i] = "|" + end + end + + ShowMission( loc("RACER"), + loc("STATUS UPDATE"), + loc("Rounds Complete: ") .. roundNumber .. "/" .. roundLimit .. "|" .. " " .. "|" .. + loc("Best Team Times: ") .. "|" .. totalComment, 0, 4000) + + -- end game if its at round limit + if roundNumber >= roundLimit then + for i = 0, (numhhs-1) do + if GetHogClan(hhs[i]) ~= bestClan then + SetEffect(hhs[i], heResurrectable, 0) + SetHealth(hhs[i],0) + end + end + gameOver = true + TurnTimeLeft = 1 + end + +end + +function CheckForNewRound() + + ------------- + ------ new + ------------- + + --[[turnN = turnN + 1 + if gameBegun == false then + if turnN == 2 then + for i = 0, (numhhs-1) do + if hhs[i] ~= nil then + SetEffect(hhs[i], heResurrectable, 0) + SetHealth(hhs[i],0) + end + end + gameOver = true + TurnTimeLeft = 1 + end + else + + + end]] + + --[[if roundBegun == true then + + if RoundHasChanged == true then + roundN = roundN + 1 + RoundHasChanged = false + onNewRound() + end + + if lastRound ~= TotalRounds then -- new round, but not really + + if RoundHasChanged == false then + RoundHasChanged = true + end + + end + + AddCaption("RoundN:" .. roundN .. "; " .. "TR: " .. TotalRounds) + + lastRound = TotalRounds + + end]] + + ------------ + ----- old + ------------ + + if GetHogClan(CurrentHedgehog) == firstClan then + onNewRound() + end + +end + +function DisableTumbler() + currCount = 0 + fastIndex = 0 + TurnTimeLeft = 0 + racerActive = false -- newadd +end + +function HandleGhost() + + -- get the current xy of the racer at this point + currX[currCount] = GetX(CurrentHedgehog) + currY[currCount] = GetY(CurrentHedgehog) + currCount = currCount + 1 + + -- draw a ping of smoke where the fastest player was at this point + if (fastCount ~= 0) and (fastIndex < fastCount) then + + fastIndex = fastIndex + 1 + + tempE = AddVisualGear(fastX[fastIndex], fastY[fastIndex], vgtSmoke, 0, false) + g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(tempE) + SetVisualGearValues(tempE, g1, g2, g3, g4, g5, g6, g7, g8, g9, fastColour ) + + --AddCaption("fC: " .. fastIndex .. " / " .. fastCount) + + else + + --AddCaption("excep fC: " .. fastIndex .. " / " .. fastCount) + + end + + + +end + +function TryRepositionHogs() + + if MapHasBorder() == true then + + for i = 0, (numhhs-1) do + if hhs[i] ~= nil then + SetGearPosition(hhs[i],GetX(hhs[i]), TopY-10) + end + end + + end + +end + +---------------------------------- +-- GAME METHODS / EVENT HANDLERS +---------------------------------- + +function onGameInit() + EnableGameFlags(gfInfAttack, gfInvulnerable) + CaseFreq = 0 + TurnTime = 90000 + WaterRise = 0 +end + + +function onGameStart() + + roundN = 0 + lastRound = TotalRounds + RoundHasChanged = false -- true + + for i = 0, (specialPointsCount-1) do + PlaceWayPoint(specialPointsX[i], specialPointsY[i]) + end + + RebuildTeamInfo() + + ShowMission ( + loc("RACER"), + loc("a Hedgewars mini-game"), + + loc("Build a track and race.") .. "|" .. + loc("Round Limit:") .. " " .. roundLimit .. "|" .. + + "", 4, 4000 + ) + + TryRepositionHogs() + +end + +function PlaceWayPoint(x,y) + if not racerActive then + if wpCount == 0 or wpX[wpCount - 1] ~= x or wpY[wpCount - 1] ~= y then + + wpX[wpCount] = x + wpY[wpCount] = y + wpCol[wpCount] = 0xffffffff + wpCirc[wpCount] = AddVisualGear(wpX[wpCount],wpY[wpCount],vgtCircle,0,true) + + SetVisualGearValues(wpCirc[wpCount], wpX[wpCount], wpY[wpCount], 20, 100, 1, 10, 0, wpRad, 5, wpCol[wpCount]) + + wpCount = wpCount + 1 + + AddCaption(loc("Waypoint placed.") .. " " .. loc("Available points remaining: ") .. (wpLimit-wpCount)) + end + end +end + +function onSpecialPoint(x,y,flag) + specialPointsX[specialPointsCount] = x + specialPointsY[specialPointsCount] = y + specialPointsCount = specialPointsCount + 1 +end + +function onNewTurn() + + CheckForNewRound() + TryRepositionHogs() + + racerActive = false + + trackTime = 0 + + currCount = 0 -- hopefully this solves problem + AddAmmo(CurrentHedgehog, amAirAttack, 0) + gTimer = 0 + + -- Set the waypoints to unactive on new round + for i = 0,(wpCount-1) do + wpActive[i] = false + wpCol[i] = 0xffffffff + SetVisualGearValues(wpCirc[i], wpX[i], wpY[i], 20, 100, 1, 10, 0, wpRad, 5, wpCol[i]) + end + + -- Handle Starting Stage of Game + if (gameOver == false) and (gameBegun == false) then + if wpCount >= 3 then + gameBegun = true + roundNumber = 0 + firstClan = GetHogClan(CurrentHedgehog) + ShowMission(loc("RACER"), + loc("GAME BEGUN!!!"), + loc("Complete the track as fast as you can!"), 2, 4000) + else + ShowMission(loc("RACER"), + loc("NOT ENOUGH WAYPOINTS"), + loc("Place more waypoints using the 'Air Attack' weapon."), 2, 4000) + AddAmmo(CurrentHedgehog, amAirAttack, 4000) + SetWeapon(amAirAttack) + end + end + + if gameOver == true then + gameBegun = false + racerActive = false -- newadd + end + + AddAmmo(CurrentHedgehog, amTardis, 0) + AddAmmo(CurrentHedgehog, amDrillStrike, 0) + AddAmmo(CurrentHedgehog, amMineStrike, 0) + AddAmmo(CurrentHedgehog, amNapalm, 0) + AddAmmo(CurrentHedgehog, amPiano, 0) + +end + +function onGameTick20() + + -- airstrike detected, convert this into a potential waypoint spot + if cGear ~= nil then + x,y = GetGearPosition(cGear) + if x > -9000 then + x,y = GetGearTarget(cGear) + + + if TestRectForObstacle(x-20, y-20, x+20, y+20, true) then + AddCaption(loc("Please place the way-point in the open, within the map boundaries.")) + PlaySound(sndDenied) + elseif (y > WaterLine-50) then + AddCaption(loc("Please place the way-point further from the waterline.")) + PlaySound(sndDenied) + else + PlaceWayPoint(x, y) + if wpCount == wpLimit then + AddCaption(loc("Race complexity limit reached.")) + DisableTumbler() + end + end + else + DeleteGear(cGear) + end + SetGearPosition(cGear, -10000, 0) + end + + + -- start the player tumbling with a boom once their turn has actually begun + if racerActive == false then + + if (TurnTimeLeft > 0) and (TurnTimeLeft ~= TurnTime) then + + -- if the gamehas started put the player in the middle of the first + --waypoint that was placed + if gameBegun == true then + AddCaption(loc("Good to go!")) + racerActive = true + trackTime = 0 + + SetGearPosition(CurrentHedgehog, wpX[0], wpY[0]) + AddGear(GetX(CurrentHedgehog), GetY(CurrentHedgehog), gtGrenade, 0, 0, 0, 1) + FollowGear(CurrentHedgehog) + + HideMission() + + -- don't start empty-handed + if (GetCurAmmoType() == amNothing) then + SetNextWeapon() + end + else + -- still in placement mode + end + + end + end + + + -- has the player started his tumbling spree? + if (CurrentHedgehog ~= nil) then + + --airstrike conversion used to be here + + -- if the RACE has started, show tracktimes and keep tabs on waypoints + if (racerActive == true) and (gameBegun == true) then + + --ghost + if GameTime%40 == 0 then + HandleGhost() + end + + trackTime = trackTime + 20 + + if GameTime%100 == 0 then + + if trackTime%1000 == 0 then + AddCaption((trackTime/1000)..'.0',GetClanColor(GetHogClan(CurrentHedgehog)),capgrpMessage2) + else + AddCaption(trackTime/1000,GetClanColor(GetHogClan(CurrentHedgehog)),capgrpMessage2) + end + + if (CheckWaypoints() == true) then + AdjustScores() + DisableTumbler() + end + + end + + end + + -- if the player has expended his tunbling time, stop him tumbling + if TurnTimeLeft <= 20 then + DisableTumbler() + end + + end + +end + +function onGearResurrect(gear) + + AddVisualGear(GetX(gear), GetY(gear), vgtBigExplosion, 0, false) + + if gear == CurrentHedgehog then + DisableTumbler() + end + +end + +function onGearAdd(gear) + + if GetGearType(gear) == gtHedgehog then + hhs[numhhs] = gear + numhhs = numhhs + 1 + SetEffect(gear, heResurrectable, 1) + elseif GetGearType(gear) == gtAirAttack then + cGear = gear + elseif GetGearType(gear) == gtRope and TeamRope then + SetTag(gear,1) + SetGearValues(gear,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,GetClanColor(GetHogClan(CurrentHedgehog))) + elseif GetGearType(gear) == gtAirMine then + DeleteGear(gear) + end +end + +function onGearDelete(gear) + + if GetGearType(gear) == gtAirAttack then + cGear = nil + end + +end + +function onAttack() + at = GetCurAmmoType() + + usedWeapons[at] = 0 +end + +function onAchievementsDeclaration() + usedWeapons[amSkip] = nil + + usedRope = usedWeapons[amRope] ~= nil + usedPortal = usedWeapons[amPortalGun] ~= nil + usedSaucer = usedWeapons[amJetpack] ~= nil + + usedWeapons[amNothing] = nil + usedWeapons[amRope] = nil + usedWeapons[amPortalGun] = nil + usedWeapons[amJetpack] = nil + + usedOther = next(usedWeapons) ~= nil + + if usedOther then -- smth besides nothing, skip, rope, portal or saucer used + raceType = "unknown race" + elseif usedRope and not usedPortal and not usedSaucer then + raceType = "rope race" + elseif not usedRope and usedPortal and not usedSaucer then + raceType = "portal race" + elseif not usedRope and not usedPortal and usedSaucer then + raceType = "saucer race" + elseif (usedRope or usedPortal or usedSaucer or usedOther) == false then -- no weapons used at all? + raceType = "no tools race" + else -- at least two of rope, portal and saucer used + raceType = "mixed race" + end + + map = detectMap() + + for i = 0, (numTeams-1) do + if teamScore[i] < 100000 then + DeclareAchievement(raceType, teamNameArr[i], map, teamScore[i]) + end + end +end diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Scripts/Multiplayer/Random_Weapon.cfg --- a/share/hedgewars/Data/Scripts/Multiplayer/Random_Weapon.cfg Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Scripts/Multiplayer/Random_Weapon.cfg Tue Nov 10 20:43:13 2015 +0100 @@ -1,2 +1,2 @@ -Default +* locked diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Scripts/Multiplayer/Random_Weapon.lua --- a/share/hedgewars/Data/Scripts/Multiplayer/Random_Weapon.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Scripts/Multiplayer/Random_Weapon.lua Tue Nov 10 20:43:13 2015 +0100 @@ -46,7 +46,8 @@ function onGameInit() -- Limit flags that can be set, but allow game schemes to be used - GameFlags = band(bor(GameFlags, gfResetWeps), bnot(gfInfAttack)) + DisableGameFlags(gfInfAttack) + EnableGameFlags(gfResetWeps) -- Set a custom game goal that will show together with the scheme ones Goals = loc("Each turn you get one random weapon") end diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Scripts/Multiplayer/ShoppaMap.cfg --- a/share/hedgewars/Data/Scripts/Multiplayer/ShoppaMap.cfg Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Scripts/Multiplayer/ShoppaMap.cfg Tue Nov 10 20:43:13 2015 +0100 @@ -1,2 +1,2 @@ -Default -Default +* +* diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Scripts/Multiplayer/ShoppaMap.lua --- a/share/hedgewars/Data/Scripts/Multiplayer/ShoppaMap.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Scripts/Multiplayer/ShoppaMap.lua Tue Nov 10 20:43:13 2015 +0100 @@ -1,30 +1,15 @@ -ObjectList = {} -PointsBuffer = '' -- A string to accumulate points in +HedgewarsScriptLoad("/Scripts/Params.lua") + +local ObjectList = {} -- Overall padding for roping freedom -Padding = 430 +local Padding = 430 -function AddPoint(x, y, width, erase) - PointsBuffer = PointsBuffer .. string.char(band(x,0xff00) / 256 , band(x,0xff) , band(y,0xff00) / 256 , band(y,0xff)) - if width then - width = bor(width,0x80) - if erase then - width = bor(width,0x40) - end - PointsBuffer = PointsBuffer .. string.char(width) - else - PointsBuffer = PointsBuffer .. string.char(0) - end - if #PointsBuffer > 245 then - ParseCommand('draw '..PointsBuffer) - PointsBuffer = '' - end -end -function FlushPoints() - if #PointsBuffer > 0 then - ParseCommand('draw '..PointsBuffer) - PointsBuffer = '' - end +function onParameters() + parseParams() + if params["pad"] ~= nil then + Padding = params["pad"] + end end -- This could probably use less points and more precision @@ -352,8 +337,12 @@ end end +function onPreviewInit() +onGameInit() +end + function onGameInit() - MapGen = 2 + MapGen = mgDrawn TemplateFilter = 0 local TotGen = 0 local Tries = 0 @@ -363,8 +352,8 @@ local y = 0 local w = 0 local h = 0 - GameFlags = bor(GameFlags, gfShoppaBorder) - if band(GameFlags,gfBottomBorder) == 0 and GetRandom(2) == 0 then + if GetGameFlag(gfSolidLand) then EnableGameFlags(gfShoppaBorder) end + if not GetGameFlag(gfBottomBorder) and GetRandom(2) == 0 then AddPoint(-50,2010,7) AddPoint(4150,2010) for i = 0,GetRandom(3) do @@ -401,8 +390,8 @@ end end if GetRandom(2)==0 then - x = GetRandom(3300)+350 - y = GetRandom(1300)+350 + x = GetRandom(3300)+382 + y = GetRandom(1300)+382 if DrawStar(x,y, 1, 1+GetRandom(2)*-2) then TotGen = TotGen+1 end @@ -434,8 +423,8 @@ else if Tries > 500 then d = GetRandom(2)+3 else d = GetRandom(3)+2 end - x = GetRandom(4000-div(700,d))+div(700,d*2) - y = GetRandom(1300-div(700,d))+div(700,d*2) + x = GetRandom(4000-div(764,d))+div(764,d*2) + y = GetRandom(1300-div(764,d))+div(764,d*2) if DrawStar(x,y, d, 1+GetRandom(2)*-2) then TotGen = TotGen+1 end diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Scripts/Multiplayer/Space_Invasion.cfg --- a/share/hedgewars/Data/Scripts/Multiplayer/Space_Invasion.cfg Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Scripts/Multiplayer/Space_Invasion.cfg Tue Nov 10 20:43:13 2015 +0100 @@ -1,2 +1,2 @@ -Default -Default +* +* diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Scripts/Multiplayer/Space_Invasion.lua --- a/share/hedgewars/Data/Scripts/Multiplayer/Space_Invasion.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Scripts/Multiplayer/Space_Invasion.lua Tue Nov 10 20:43:13 2015 +0100 @@ -290,7 +290,6 @@ local chainLength = 0 local shotsFired = 0 local shotsHit = 0 -local SurfTime = 0 local sniperHits = 0 local pointBlankHits = 0 --------------------- @@ -1001,7 +1000,8 @@ -------------------------- function onGameInit() - GameFlags = 0 + gfRandomOrder + ClearGameFlags() + EnableGameFlags(gfRandomOrder) Theme = "EarthRise" CaseFreq = 0 HealthCaseProb = 0 @@ -1104,7 +1104,6 @@ pointBlankHits = 0 chainLength = 0 chainCounter = 0 - SurfTime = 12 ------------------------- -- gaudy racer @@ -1159,6 +1158,19 @@ end +function onGearWaterSkip(gear) + if gear == CurrentHedgehog then + + for i = 0,(TeamsCount-1) do + if teamClan[i] == GetHogClan(CurrentHedgehog) and (teamSurfer[i] == false) then + teamSurfer[i] = true + AddCaption(loc("Surfer! +15 points!"),0xffba00ff,capgrpVolume) + AwardPoints(15) + end + end + + end +end function onGameTick() @@ -1327,30 +1339,6 @@ -------------- -------------- - ------------------------ - -- surfer achievement - ------------------------ - - if (WaterLine - GetY(CurrentHedgehog)) < 15 then - SurfTime = SurfTime -1 - end - - if SurfTime ~= 12 then - - SurfTime = SurfTime - 1 - if SurfTime <= 0 then - for i = 0,(TeamsCount-1) do - if teamClan[i] == GetHogClan(CurrentHedgehog) and (teamSurfer[i] == false) then - teamSurfer[i] = true - SurfTime = 12 - AddCaption(loc("Surfer! +15 points!"),0xffba00ff,capgrpVolume) - AwardPoints(15) - end - end - end - end - - dx, dy = GetGearVelocity(CurrentHedgehog) --WriteLnToConsole("I just got the velocity of currenthedgehog. It is dx: " .. dx .. "; dy: " .. dy) diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Scripts/Multiplayer/TechRacer.cfg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Scripts/Multiplayer/TechRacer.cfg Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,2 @@ +Shoppa +Shoppa diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Scripts/Multiplayer/TechRacer.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Scripts/Multiplayer/TechRacer.lua Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,1295 @@ +------------------------------------------ +-- TECH RACER v0.8 +----------------------------------------- + +-------------- +-- TO DO +-------------- +-- allow scrolling of maps (was going to add this in the engine itself, but it can be done now by refreshing preview) + +-------------- +--0.2 +-------------- +-- should work better "out the box" +-- changed map generation +-- put a hog limiter in place +-- removed parsecommand +-- fix one of the test maps +-- hopefully added some support for future official challenges etc +-- changed theme +-- minor cleanups? + +-------------- +--0.3 +-------------- +-- ehh, scrap everything? those old maps probably still desync so they can die for now +-- hopefully fix map 3 +-- add two new crappy map to test an idea. + +-------------- +--0.4 +-------------- +-- updated version text (lol) +-- some preliminary support for hand-drawn map loading +-- some support for being really lazy +-- an extra map or two +-- param for infinite UFO fuel +-- param for number of rounds + +-------------- +--0.5 +-------------- +-- migrated maps to an external script + +-------------- +--0.6 +-------------- +-- move 1 line of code :D (allows loading of HWMAP points to actually work) + +-------------- +--0.7 +-------------- +-- allow waypoints to be loaded automatically via TechMaps or HWMAP +-- (temporarily?) remove ability to place waypoints manually +-- break stuff? + +-------------- +--0.8 +-------------- +-- should (more or less) work "out of the box" now +-- generate map previews for level +-- randomly assign a map in the case of no map param +-- no longer allow custom ammosets (ammo should be specified by map so that records can be valid, though we probably still need to completely limit gameflags) + +-------------- +--0.9 +-------------- +-- added variable portal limiter (and effects) from Escape script +-- allow variable ufoFuel (nil is default, 2000 is infinite) +-- disallow specifying fuel in params (do this in TechMaps or HedgeEditor please) + +----------------------------- +-- SCRIPT BEGINS +----------------------------- + +HedgewarsScriptLoad("/Scripts/Locale.lua") +HedgewarsScriptLoad("/Scripts/OfficialChallenges.lua") +HedgewarsScriptLoad("/Scripts/Tracker.lua") +HedgewarsScriptLoad("/Scripts/Params.lua") +HedgewarsScriptLoad("/Scripts/TechMaps.lua") + +------------------ +-- Got Variables? +------------------ + +local atkArray = + { + {amBazooka, "amBazooka", 0}, + {amBee, "amBee", 0}, + {amMortar, "amMortar", 0}, + {amDrill, "amDrill", 0}, + {amSnowball, "amSnowball", 0}, + + {amGrenade, "amGrenade", 0}, + {amClusterBomb, "amClusterBomb", 0}, + {amMolotov, "amMolotov", 0}, + {amWatermelon, "amWatermelon", 0}, + {amHellishBomb, "amHellishBomb", 0}, + {amGasBomb, "amGasBomb", 0}, + + {amShotgun, "amShotgun", 0}, + {amDEagle, "amDEagle", 0}, + {amFlamethrower,"amFlamethrower", 0}, + {amSniperRifle, "amSniperRifle", 0}, + {amSineGun, "amSineGun", 0}, + {amIceGun, "amIceGun", 0}, + {amLandGun, "amLandGun", 0}, + + {amFirePunch, "amFirePunch", 0}, + {amWhip, "amWhip", 0}, + {amBaseballBat, "amBaseballBat", 0}, + {amKamikaze, "amKamikaze", 0}, + {amSeduction, "amSeduction", 0}, + {amHammer, "amHammer", 0}, + + {amMine, "amMine", 0}, + {amDynamite, "amDynamite", 0}, + {amCake, "amCake", 0}, + {amBallgun, "amBallgun", 0}, + {amRCPlane, "amRCPlane", 0}, + {amSMine, "amSMine", 0}, + {amAirMine, "amAirMine", 0}, + + {amAirAttack, "amAirAttack", 0}, + {amMineStrike, "amMineStrike", 0}, + {amDrillStrike, "amDrillStrike", 0}, + {amAirMine, "amAirMine", 0}, + {amNapalm, "amNapalm", 0}, + {amPiano, "amPiano", 0}, + + {amKnife, "amKnife", 0}, + + {amBirdy, "amBirdy", 0} + + } + +local utilArray = + { + {amBlowTorch, "amBlowTorch", 0}, + {amPickHammer, "amPickHammer", 0}, + {amGirder, "amGirder", 0}, + {amRubber, "amRubber", 0}, + {amPortalGun, "amPortalGun", 0}, + + {amRope, "amRope", 0}, + {amParachute, "amParachute", 0}, + {amTeleport, "amTeleport", 0}, + {amJetpack, "amJetpack", 0}, + + {amInvulnerable, "amInvulnerable", 0}, + {amLaserSight, "amLaserSight", 0}, + {amVampiric, "amVampiric", 0}, + + {amLowGravity, "amLowGravity", 0}, + {amExtraDamage, "amExtraDamage", 0}, + {amExtraTime, "amExtraTime", 0}, + + {amResurrector, "amResurrector", 0}, + {amTardis, "amTardis", 0}, + + {amSwitch, "amSwitch", 0} + } + +local activationStage = 0 +local jet = nil +portalDistance = 5000 -- 15 +ufoFuel = 0 +local fMod = 1000000 -- 1 +local roundLimit = 3 +local roundNumber = 0 +local firstClan = 10 + +local fastX = {} +local fastY = {} +local fastCount = 0 +local fastIndex = 0 +local fastColour + +local currX = {} +local currY = {} +local currCount = 0 + +local specialPointsX = {} +local specialPointsY = {} +local specialPointsFlag = {} +local specialPointsCount = 0 + +mapID = nil + +-------------------------- +-- hog and team tracking variales +-------------------------- + +local numhhs = 0 -- store number of hedgehogs +local hhs = {} -- store hedgehog gears + +local numTeams -- store the number of teams in the game +local teamNameArr = {} -- store the list of teams +local teamClan = {} +local teamSize = {} -- store how many hogs per team +local teamIndex = {} -- at what point in the hhs{} does each team begin + +local teamComment = {} +local teamScore = {} + +------- +-- racer vars +-------- + +local cGear = nil + +local bestClan = nil +local bestTime = nil + +local gameBegun = false +local gameOver = false +local racerActive = false +local trackTime = 0 + +local wpCirc = {} +local wpX = {} +local wpY = {} +local wpCol = {} +local wpActive = {} +local wpRad = 450 --75 +local wpCount = 0 +local wpLimit = 20 + +local usedWeapons = {} + +local roundN +local lastRound +local RoundHasChanged + +------------------- +-- general methods +------------------- + +--function onPrecise() +--end + +function RebuildTeamInfo() + + + -- make a list of individual team names + for i = 0, (TeamsCount-1) do + teamNameArr[i] = " " -- = i + teamSize[i] = 0 + teamIndex[i] = 0 + teamScore[i] = 100000 + end + numTeams = 0 + + for i = 0, (numhhs-1) do + + z = 0 + unfinished = true + while(unfinished == true) do + + newTeam = true + tempHogTeamName = GetHogTeamName(hhs[i]) -- this is the new name + + if tempHogTeamName == teamNameArr[z] then + newTeam = false + unfinished = false + end + + z = z + 1 + + if z == TeamsCount then + unfinished = false + if newTeam == true then + teamNameArr[numTeams] = tempHogTeamName + numTeams = numTeams + 1 + end + end + + end + + end + + -- find out how many hogs per team, and the index of the first hog in hhs + for i = 0, (numTeams-1) do + for z = 0, (numhhs-1) do + if GetHogTeamName(hhs[z]) == teamNameArr[i] then + teamClan[i] = GetHogClan(hhs[z]) + if teamSize[i] == 0 then + teamIndex[i] = z -- should give starting index + end + teamSize[i] = teamSize[i] + 1 + --add a pointer so this hog appears at i in hhs + end + end + + end + +end + + +----------------- +-- RACER METHODS +----------------- + +function CheckWaypoints() + + trackFinished = true + + for i = 0, (wpCount-1) do + + g1X, g1Y = GetGearPosition(CurrentHedgehog) + g2X, g2Y = wpX[i], wpY[i] + + g1X = g1X - g2X + g1Y = g1Y - g2Y + dist = (g1X*g1X) + (g1Y*g1Y) + + --if i == 0 then + -- AddCaption(dist .. "/" .. (wpRad*wpRad) ) + --end + + NR = (48/100*wpRad)/2 + + if dist < (NR*NR) then + --if dist < (wpRad*wpRad) then + --AddCaption("howdy") + wpActive[i] = true + wpCol[i] = GetClanColor(GetHogClan(CurrentHedgehog)) -- new --GetClanColor(1) + SetVisualGearValues(wpCirc[i], wpX[i], wpY[i], 20, 100, 1, 10, 0, wpRad, 5, wpCol[i]) + + wpRem = 0 + for k = 0, (wpCount-1) do + if wpActive[k] == false then + wpRem = wpRem + 1 + end + end + + AddCaption(loc("Way-Points Remaining") .. ": " .. wpRem,0xffba00ff,capgrpAmmoinfo) + + end + + if wpActive[i] == false then + trackFinished = false + end + + end + + return(trackFinished) + +end + +function AdjustScores() + + if bestTime == nil then + bestTime = 100000 + bestClan = 10 + bestTimeComment = "N/A" + end + + newScore = false + + -- update this clan's time if the new track is better + for i = 0, (numTeams-1) do + if teamClan[i] == GetHogClan(CurrentHedgehog) then + if trackTime < teamScore[i] then + teamScore[i] = trackTime + newScore = true + else + newScore = false + end + end + end + + --bestTime = 100000 + --bestClan = 10 + + -- find the best time out of those so far + for i = 0, (numTeams-1) do + if teamScore[i] < bestTime then + bestTime = teamScore[i] + bestClan = teamClan[i] + end + end + + if bestTime ~= 100000 then + bestTimeComment = (bestTime/1000) ..loc("s") + end + + if newScore == true then + if trackTime == bestTime then -- best time of the race + ShowMission(loc("RACER"), + loc("TRACK COMPLETED"), + loc("NEW RACE RECORD: ") .. (trackTime/1000) ..loc("s") .. "|" .. + loc("WINNING TIME: ") .. bestTimeComment, 0, 4000) + PlaySound(sndHomerun) + else -- best time for the clan + ShowMission(loc("RACER"), + loc("TRACK COMPLETED"), + loc("NEW CLAN RECORD: ") .. (trackTime/1000) ..loc("s") .. "|" .. + loc("WINNING TIME: ") .. bestTimeComment, 4, 4000) + end + else -- not any kind of new score + ShowMission(loc("RACER"), + loc("TRACK COMPLETED"), + loc("TIME: ") .. (trackTime/1000) ..loc("s") .. "|" .. + loc("WINNING TIME: ") .. bestTimeComment, -amSkip, 4000) + PlaySound(sndHellish) + end + + + -------- + --new + -------- + + if bestTime == trackTime then + --AddCaption("wooooooooooooooooooooooooooooo") + + fastColour = GetClanColor(GetHogClan(CurrentHedgehog)) + + for i = 0, (currCount-1) do + fastX[i] = currX[i] + fastY[i] = currY[i] + end + + fastCount = currCount + fastIndex = 0 + + --currCount = 0 -- is this needed? + + else + currCount = 0 + fastIndex = 0 + end + + +end + +function onNewRound() + + roundNumber = roundNumber + 1 + + totalComment = "" + for i = 0, (TeamsCount-1) do + if teamNameArr[i] ~= " " then -- teamScore[teamClan[i]] + teamComment[i] = teamNameArr[i] .. ": " .. (teamScore[i]/1000) .. loc("s|") + totalComment = totalComment .. teamComment[i] + elseif teamNameArr[i] == " " then + teamComment[i] = "|" + end + end + + ShowMission( loc("RACER"), + loc("STATUS UPDATE"), + loc("Rounds Complete: ") .. roundNumber .. "/" .. roundLimit .. "|" .. " " .. "|" .. + loc("Best Team Times: ") .. "|" .. totalComment, 0, 4000) + + -- end game if its at round limit + if roundNumber >= roundLimit then + for i = 0, (numhhs-1) do + if GetHogClan(hhs[i]) ~= bestClan then + SetEffect(hhs[i], heResurrectable, 0) + SetHealth(hhs[i],0) + end + end + gameOver = true + TurnTimeLeft = 1 + end + +end + +function CheckForNewRound() + + ------------- + ------ new + ------------- + + --[[turnN = turnN + 1 + if gameBegun == false then + if turnN == 2 then + for i = 0, (numhhs-1) do + if hhs[i] ~= nil then + SetEffect(hhs[i], heResurrectable, 0) + SetHealth(hhs[i],0) + end + end + gameOver = true + TurnTimeLeft = 1 + end + else + + + end]] + + --[[if roundBegun == true then + + if RoundHasChanged == true then + roundN = roundN + 1 + RoundHasChanged = false + onNewRound() + end + + if lastRound ~= TotalRounds then -- new round, but not really + + if RoundHasChanged == false then + RoundHasChanged = true + end + + end + + AddCaption("RoundN:" .. roundN .. "; " .. "TR: " .. TotalRounds) + + lastRound = TotalRounds + + end]] + + ------------ + ----- old + ------------ + + if GetHogClan(CurrentHedgehog) == firstClan then + onNewRound() + end + +end + +function DisableTumbler() + currCount = 0 + fastIndex = 0 + TurnTimeLeft = 0 + racerActive = false -- newadd +end + +function HandleGhost() + + -- get the current xy of the racer at this point + currX[currCount] = GetX(CurrentHedgehog) + currY[currCount] = GetY(CurrentHedgehog) + currCount = currCount + 1 + + -- draw a ping of smoke where the fastest player was at this point + if (fastCount ~= 0) and (fastIndex < fastCount) then + + fastIndex = fastIndex + 1 + + tempE = AddVisualGear(fastX[fastIndex], fastY[fastIndex], vgtSmoke, 0, false) + g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(tempE) + SetVisualGearValues(tempE, g1, g2, g3, g4, g5, g6, g7, g8, g9, fastColour ) + + --AddCaption("fC: " .. fastIndex .. " / " .. fastCount) + + else + + --AddCaption("excep fC: " .. fastIndex .. " / " .. fastCount) + + end + +end + +function BoomGirder(x,y,rot) + girTime = 1 + if rot < 4 then + AddGear(x, y, gtGrenade, 0, 0, 0, girTime) + elseif rot == 4 then + g = AddGear(x-45, y, gtGrenade, 0, 0, 0, girTime) -- needed? + g = AddGear(x-30, y, gtGrenade, 0, 0, 0, girTime) + g = AddGear(x, y, gtGrenade, 0, 0, 0, girTime) -- needed? + g = AddGear(x+30, y, gtGrenade, 0, 0, 0, girTime) + g = AddGear(x+45, y, gtGrenade, 0, 0, 0, girTime) -- needed? + elseif rot == 5 then ------- diag + g = AddGear(x+45, y+45, gtGrenade, 0, 0, 0, girTime) --n + g = AddGear(x+30, y+30, gtGrenade, 0, 0, 0, girTime) + g = AddGear(x, y, gtGrenade, 0, 0, 0, girTime) -- needed? + g = AddGear(x-30, y-30, gtGrenade, 0, 0, 0, girTime) + g = AddGear(x-45, y-45, gtGrenade, 0, 0, 0, girTime) --n + elseif rot == 6 then + g = AddGear(x, y-45, gtGrenade, 0, 0, 0, girTime) -- needed? + g = AddGear(x, y+30, gtGrenade, 0, 0, 0, girTime) + g = AddGear(x, y, gtGrenade, 0, 0, 0, girTime) -- needed? + g = AddGear(x, y-30, gtGrenade, 0, 0, 0, girTime) + g = AddGear(x, y+45, gtGrenade, 0, 0, 0, girTime) -- needed? + elseif rot == 7 then ------- + g = AddGear(x+45, y-45, gtGrenade, 0, 0, 0, girTime) --n + g = AddGear(x+30, y-30, gtGrenade, 0, 0, 0, girTime) + g = AddGear(x, y, gtGrenade, 0, 0, 0, girTime) -- needed? + g = AddGear(x-30, y+30, gtGrenade, 0, 0, 0, girTime) + g = AddGear(x-45, y+45, gtGrenade, 0, 0, 0, girTime) --n + end +end + +function RemoveGear(gear) + if (isATrackedGear(gear) == true) and (GetGearType(gear) ~= gtHedgehog) then + DeleteGear(gear) + end +end + +function ClearMap() + + runOnGears(RemoveGear) + +end + +function CallBob(x,y) + if not racerActive then + if wpCount == 0 or wpX[wpCount - 1] ~= x or wpY[wpCount - 1] ~= y then + + wpX[wpCount] = x + wpY[wpCount] = y + wpCol[wpCount] = 0xffffffff + wpCirc[wpCount] = AddVisualGear(wpX[wpCount],wpY[wpCount],vgtCircle,0,true) + + SetVisualGearValues(wpCirc[wpCount], wpX[wpCount], wpY[wpCount], 20, 100, 1, 10, 0, wpRad, 5, wpCol[wpCount]) + + wpCount = wpCount + 1 + + --AddCaption(loc("Waypoint placed.") .. " " .. loc("Available points remaining: ") .. (wpLimit-wpCount)) + end + end +end + + + +function HandleFreshMapCreation() + + -- the boom stage, boom girders, reset ammo, and delete other map objects + if activationStage == 1 then + + ClearMap() + activationStage = activationStage + 1 + + -- the creation stage, place girders and needed gears, grant ammo + elseif activationStage == 2 then + + InterpretPoints() + + -- these are from onParameters() + if (mapID == nil) or (mapID == 0) then + LoadMap(2000) + else + LoadMap(mapID) + end + + for i = 0,(wpCount-1) do + DeleteVisualGear(wpCirc[i]) + end + wpCount = 0 + + for i = 1, techCount-1 do + CallBob(techX[i],techY[i]) + end + + activationStage = 200 + --runOnHogs(RestoreHog) + + end + +end + +function TryRepositionHogs() + + if MapHasBorder() == true then + + for i = 0, (numhhs-1) do + if hhs[i] ~= nil then + SetGearPosition(hhs[i],GetX(hhs[i]), TopY-10) + end + end + + end + +end + +---------------------------------- +-- GAME METHODS / EVENT HANDLERS +---------------------------------- + +function onParameters() + + parseParams() + mapID = tonumber(params["m"]) + + --ufoFuel = tonumber(params["ufoFuel"]) + roundLimit = tonumber(params["rounds"]) + + if (roundLimit == 0) or (roundLimit == nil) then + roundLimit = 3 + end + + if mapID == nil then + mapID = 2 + GetRandom(7) + end + +end + +function onGameInit() + + if mapID == nil then + mapID = 2 + GetRandom(7) + end + + Theme = "Cave" + + MapGen = mgDrawn + TemplateFilter = 0 + + EnableGameFlags(gfInfAttack, gfDisableWind, gfBorder) + DisableGameFlags(gfSolidLand) + CaseFreq = 0 + TurnTime = 90000 + WaterRise = 0 + + for x = 1, 16 do + AddPoint(x*100,100,5) + end + + FlushPoints() + +end + +function limitHogs(gear) + + cnthhs = cnthhs + 1 + if cnthhs > 1 then + DeleteGear(gear) + end + +end + +function onSpecialPoint(x,y,flag) + specialPointsX[specialPointsCount] = x + specialPointsY[specialPointsCount] = y + specialPointsFlag[specialPointsCount] = flag + specialPointsCount = specialPointsCount + 1 +end + +function InterpretPoints() + + -- flags run from 0 to 127 + for i = 0, (specialPointsCount-1) do + + -- Mines + if specialPointsFlag[i] == 1 then + SetTimer(AddGear(specialPointsX[i], specialPointsY[i], gtMine, 0, 0, 0, 0), 1) + elseif specialPointsFlag[i] == 2 then + SetTimer(AddGear(specialPointsX[i], specialPointsY[i], gtMine, 0, 0, 0, 0), 1000) + elseif specialPointsFlag[i] == 3 then + SetTimer(AddGear(specialPointsX[i], specialPointsY[i], gtMine, 0, 0, 0, 0), 2000) + elseif specialPointsFlag[i] == 4 then + SetTimer(AddGear(specialPointsX[i], specialPointsY[i], gtMine, 0, 0, 0, 0), 3000) + elseif specialPointsFlag[i] == 5 then + SetTimer(AddGear(specialPointsX[i], specialPointsY[i], gtMine, 0, 0, 0, 0), 4000) + elseif specialPointsFlag[i] == 6 then + SetTimer(AddGear(specialPointsX[i], specialPointsY[i], gtMine, 0, 0, 0, 0), 5000) + + -- Sticky Mines + elseif specialPointsFlag[i] == 7 then + AddGear(specialPointsX[i], specialPointsY[i], gtSMine, 0, 0, 0, 0) + + -- Air Mines + elseif specialPointsFlag[i] == 8 then + AddGear(specialPointsX[i], specialPointsY[i], gtAirMine, 0, 0, 0, 0) + + -- Health Crates + elseif specialPointsFlag[i] == 9 then + SetHealth(SpawnHealthCrate(specialPointsX[i],specialPointsY[i]),25) + elseif specialPointsFlag[i] == 10 then + SetHealth(SpawnHealthCrate(specialPointsX[i],specialPointsY[i]),50) + elseif specialPointsFlag[i] == 11 then + SetHealth(SpawnHealthCrate(specialPointsX[i],specialPointsY[i]),75) + elseif specialPointsFlag[i] == 12 then + SetHealth(SpawnHealthCrate(specialPointsX[i],specialPointsY[i]),100) + + -- Cleaver + elseif specialPointsFlag[i] == 13 then + AddGear(specialPointsX[i], specialPointsY[i], gtKnife, 0, 0, 0, 0) + + -- Target + elseif specialPointsFlag[i] == 14 then + AddGear(specialPointsX[i], specialPointsY[i], gtTarget, 0, 0, 0, 0) + + --Barrels + elseif specialPointsFlag[i] == 15 then + SetHealth(AddGear(specialPointsX[i], specialPointsY[i], gtExplosives, 0, 0, 0, 0),1) + elseif specialPointsFlag[i] == 16 then + SetHealth(AddGear(specialPointsX[i], specialPointsY[i], gtExplosives, 0, 0, 0, 0),25) + elseif specialPointsFlag[i] == 17 then + SetHealth(AddGear(specialPointsX[i], specialPointsY[i], gtExplosives, 0, 0, 0, 0),50) + elseif specialPointsFlag[i] == 18 then + SetHealth(AddGear(specialPointsX[i], specialPointsY[i], gtExplosives, 0, 0, 0, 0),75) + elseif specialPointsFlag[i] == 19 then + SetHealth(AddGear(specialPointsX[i], specialPointsY[i], gtExplosives, 0, 0, 0, 0),100) + + -- There are about 58+- weps / utils + -- Weapon Crates + elseif (specialPointsFlag[i] >= 20) and (specialPointsFlag[i] < (#atkArray+20)) then + SpawnAmmoCrate(specialPointsX[i],specialPointsY[i],atkArray[specialPointsFlag[i]-19][1]) + + + -- Utility Crates + elseif (specialPointsFlag[i] >= (#atkArray+20)) and (specialPointsFlag[i] < (#atkArray+20+#utilArray)) then + SpawnUtilityCrate(specialPointsX[i],specialPointsY[i],utilArray[specialPointsFlag[i]-19-#atkArray][1]) + + --79-82 (reserved for future wep crates) + --89,88,87,86 and 85,84,83,82 (reserved for the 2 custom sprites and their landflags) + + --90-99 reserved for scripted structures + --[[elseif specialPointsFlag[i] == 90 then + --PlaceStruc("generator") + elseif specialPointsFlag[i] == 91 then + --PlaceStruc("healingstation") + elseif specialPointsFlag[i] == 92 then + --PlaceStruc("respawner") + elseif specialPointsFlag[i] == 93 then + --PlaceStruc("teleportationnode") + elseif specialPointsFlag[i] == 94 then + --PlaceStruc("biofilter") + elseif specialPointsFlag[i] == 95 then + --PlaceStruc("supportstation") + elseif specialPointsFlag[i] == 96 then + --PlaceStruc("constructionstation") + elseif specialPointsFlag[i] == 97 then + --PlaceStruc("reflectorshield") + elseif specialPointsFlag[i] == 98 then + --PlaceStruc("weaponfilter")]] + + elseif specialPointsFlag[i] == 98 then + portalDistance = specialPointsX[i] + ufoFuel = specialPointsY[i] + + -- Normal Girders + elseif specialPointsFlag[i] == 100 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + elseif specialPointsFlag[i] == 101 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmGirder, 1, 4294967295, nil, nil, nil, lfNormal) + elseif specialPointsFlag[i] == 102 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmGirder, 2, 4294967295, nil, nil, nil, lfNormal) + elseif specialPointsFlag[i] == 103 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmGirder, 3, 4294967295, nil, nil, nil, lfNormal) + elseif specialPointsFlag[i] == 104 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + elseif specialPointsFlag[i] == 105 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + elseif specialPointsFlag[i] == 106 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + elseif specialPointsFlag[i] == 107 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + + -- Invulnerable Girders + elseif specialPointsFlag[i] == 108 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmGirder, 0, 2516582650, nil, nil, nil, lfIndestructible) + elseif specialPointsFlag[i] == 109 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmGirder, 1, 2516582650, nil, nil, nil, lfIndestructible) + elseif specialPointsFlag[i] == 110 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmGirder, 2, 2516582650, nil, nil, nil, lfIndestructible) + elseif specialPointsFlag[i] == 111 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmGirder, 3, 2516582650, nil, nil, nil, lfIndestructible) + elseif specialPointsFlag[i] == 112 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + elseif specialPointsFlag[i] == 113 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmGirder, 5, 2516582650, nil, nil, nil, lfIndestructible) + elseif specialPointsFlag[i] == 114 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + elseif specialPointsFlag[i] == 115 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmGirder, 7, 2516582650, nil, nil, nil, lfIndestructible) + + -- Icy Girders + elseif specialPointsFlag[i] == 116 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmGirder, 0, 16448250, nil, nil, nil, lfIce) + elseif specialPointsFlag[i] == 117 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmGirder, 1, 16448250, nil, nil, nil, lfIce) + elseif specialPointsFlag[i] == 118 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmGirder, 2, 16448250, nil, nil, nil, lfIce) + elseif specialPointsFlag[i] == 119 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmGirder, 3, 16448250, nil, nil, nil, lfIce) + elseif specialPointsFlag[i] == 120 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmGirder, 4, 16448250, nil, nil, nil, lfIce) + elseif specialPointsFlag[i] == 121 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmGirder, 5, 16448250, nil, nil, nil, lfIce) + elseif specialPointsFlag[i] == 121 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmGirder, 6, 16448250, nil, nil, nil, lfIce) + elseif specialPointsFlag[i] == 123 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmGirder, 7, 16448250, nil, nil, nil, lfIce) + + -- Rubber Bands + elseif specialPointsFlag[i] == 124 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + elseif specialPointsFlag[i] == 125 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmRubber, 1, 4294967295, nil, nil, nil, lfBouncy) + elseif specialPointsFlag[i] == 126 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmRubber, 2, 4294967295, nil, nil, nil, lfBouncy) + elseif specialPointsFlag[i] == 127 then + PlaceSprite(specialPointsX[i], specialPointsY[i], sprAmRubber, 3, 4294967295, nil, nil, nil, lfBouncy) + + -- Waypoints + else -- 0 / no value + CallBob(specialPointsX[i], specialPointsY[i]) + end + + end + +end + +function onGameStart() + + trackTeams() + + roundN = 0 + lastRound = TotalRounds + RoundHasChanged = false -- true + + RebuildTeamInfo() + + for i=0 , TeamsCount - 1 do + cnthhs = 0 + runOnHogsInTeam(limitHogs, teamNameArr[i]) + end + + ShowMission ( + loc("RACER"), + loc("a Hedgewars mini-game"), + + loc("Build a track and race.") .. "|" .. + loc("Round Limit:") .. " " .. roundLimit .. "|" .. + loc("You can further customize the race by changing the scheme script paramater.") .. "|" .. + --loc("For example, the below line would play map 4, with infinite fuel for the flying saucer, and four rounds.") .. "|" .. + --"m=4, ufo=true, rounds=4" .. "|" .. + + "", 4, 4000 + ) + + TryRepositionHogs() + + activationStage = 2 + HandleFreshMapCreation() + +end + + + +function onNewTurn() + + CheckForNewRound() + TryRepositionHogs() + + racerActive = false + + activationStage = 1 + + --AddAmmo(CurrentHedgehog, amBazooka, 100) + --AddAmmo(CurrentHedgehog, amJetpack, 100) + + --ClearMap() + + + trackTime = 0 + + currCount = 0 -- hopefully this solves problem + -- AddAmmo(CurrentHedgehog, amAirAttack, 0) + gTimer = 0 + + -- Set the waypoints to unactive on new round + for i = 0,(wpCount-1) do + wpActive[i] = false + wpCol[i] = 0xffffffff + SetVisualGearValues(wpCirc[i], wpX[i], wpY[i], 20, 100, 1, 10, 0, wpRad, 5, wpCol[i]) + end + + -- Handle Starting Stage of Game + if (gameOver == false) and (gameBegun == false) then + -- if wpCount >= 3 then + gameBegun = true + -- --[[activationStage = 200]] + roundNumber = 0 + firstClan = GetHogClan(CurrentHedgehog) + ShowMission(loc("RACER"), + loc("GAME BEGUN!!!"), + loc("Complete the track as fast as you can!"), 2, 4000) + --else + -- ShowMission(loc("RACER"), + -- loc("NOT ENOUGH WAYPOINTS"), + -- loc("Place more waypoints using the 'Air Attack' weapon."), 2, 4000) + -- AddAmmo(CurrentHedgehog, amAirAttack, 4000) + -- SetWeapon(amAirAttack) + -- end + end + + if gameOver == true then + gameBegun = false + racerActive = false -- newadd + end + + AddAmmo(CurrentHedgehog, amTardis, 0) + AddAmmo(CurrentHedgehog, amDrillStrike, 0) + AddAmmo(CurrentHedgehog, amMineStrike, 0) + AddAmmo(CurrentHedgehog, amNapalm, 0) + AddAmmo(CurrentHedgehog, amPiano, 0) + +end + +function onGameTick20() + + if (jet ~= nil) and (ufoFuel ~= 0) then + if ufoFuel == 2000 then + SetHealth(jet, 2000) + end + end + + runOnGears(PortalEffects) + + -- airstrike detected, convert this into a potential waypoint spot + if cGear ~= nil then + x,y = GetGearPosition(cGear) + if x > -9000 then + x,y = GetGearTarget(cGear) + + + if TestRectForObstacle(x-20, y-20, x+20, y+20, true) then + AddCaption(loc("Please place the way-point in the open, within the map boundaries.")) + PlaySound(sndDenied) + elseif (y > WaterLine-50) then + AddCaption(loc("Please place the way-point further from the waterline.")) + PlaySound(sndDenied) + else + CallBob(x, y) + if wpCount == wpLimit then + AddCaption(loc("Race complexity limit reached.")) + DisableTumbler() + end + end + else + DeleteGear(cGear) + end + SetGearPosition(cGear, -10000, 0) + end + + + if activationStage < 10 then + HandleFreshMapCreation() + end + + + -- start the player tumbling with a boom once their turn has actually begun + if racerActive == false then + + if (TurnTimeLeft > 0) and (TurnTimeLeft ~= TurnTime) then + + -- if the gamehas started put the player in the middle of the first + --waypoint that was placed + --if activationStage == 200 then + if gameBegun == true then + AddCaption(loc("Good to go!")) + racerActive = true + trackTime = 0 + + + SetGearPosition(CurrentHedgehog, wpX[0], wpY[0]) + --AddGear(GetX(CurrentHedgehog), GetY(CurrentHedgehog), gtGrenade, 0, 0, 0, 1) + --SetGearVelocity(CurrentHedgehog,1000000,1000000) + SetGearMessage(CurrentHedgehog,gmLeft) + + + FollowGear(CurrentHedgehog) + + HideMission() + activationStage = 201 + + else + -- still in placement mode + end + + end + + elseif (activationStage == 201) and (TurnTimeLeft > 0) and (TurnTimeLeft ~= TurnTime) then + SetGearMessage(CurrentHedgehog,0) + activationStage = 202 + end + + + + -- has the player started his tumbling spree? + if (CurrentHedgehog ~= nil) then + + --airstrike conversion used to be here + + -- if the RACE has started, show tracktimes and keep tabs on waypoints + if (racerActive == true) and (activationStage == 202) then + + --ghost + if GameTime%40 == 0 then + HandleGhost() + end + + trackTime = trackTime + 20 + + if GameTime%100 == 0 then + + if trackTime%1000 == 0 then + AddCaption((trackTime/1000)..'.0',GetClanColor(GetHogClan(CurrentHedgehog)),capgrpMessage2) + else + AddCaption(trackTime/1000,GetClanColor(GetHogClan(CurrentHedgehog)),capgrpMessage2) + end + + if (CheckWaypoints() == true) then + AdjustScores() + DisableTumbler() + end + + end + + end + + -- if the player has expended his tunbling time, stop him tumbling + if TurnTimeLeft <= 20 then + DisableTumbler() + end + + end + +end + +-- handle short range portal gun +function PortalEffects(gear) + + if GetGearType(gear) == gtPortal then + + tag = GetTag(gear) + if tag == 0 then + col = 0xfab02aFF -- orange ball + elseif tag == 1 then + col = 0x00FF00FF -- orange portal + elseif tag == 2 then + col = 0x364df7FF -- blue ball + elseif tag == 3 then + col = 0xFFFF00FF -- blue portal + end + + if (tag == 0) or (tag == 2) then -- i.e ball form + tempE = AddVisualGear(GetX(gear), GetY(gear), vgtDust, 0, true) + g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(tempE) + SetVisualGearValues(tempE, g1, g2, g3, g4, g5, g6, g7, 1, g9, col ) + + remLife = getGearValue(gear,"life") + remLife = remLife - 1 + setGearValue(gear, "life", remLife) + + if remLife == 0 then + + tempE = AddVisualGear(GetX(gear)+15, GetY(gear), vgtSmoke, 0, true) + g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(tempE) + SetVisualGearValues(tempE, g1, g2, g3, g4, g5, g6, g7, g8, g9, col ) + + tempE = AddVisualGear(GetX(gear)-15, GetY(gear), vgtSmoke, 0, true) + g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(tempE) + SetVisualGearValues(tempE, g1, g2, g3, g4, g5, g6, g7, g8, g9, col ) + + tempE = AddVisualGear(GetX(gear), GetY(gear)+15, vgtSmoke, 0, true) + g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(tempE) + SetVisualGearValues(tempE, g1, g2, g3, g4, g5, g6, g7, g8, g9, col ) + + tempE = AddVisualGear(GetX(gear), GetY(gear)-15, vgtSmoke, 0, true) + g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(tempE) + SetVisualGearValues(tempE, g1, g2, g3, g4, g5, g6, g7, g8, g9, col ) + + + PlaySound(sndVaporize) + DeleteGear(gear) + + end + + end + + end + +end + +function onGearResurrect(gear) + + AddVisualGear(GetX(gear), GetY(gear), vgtBigExplosion, 0, false) + + if gear == CurrentHedgehog then + DisableTumbler() + end + +end + +function isATrackedGear(gear) + if (GetGearType(gear) == gtHedgehog) or + (GetGearType(gear) == gtGrenade) or + (GetGearType(gear) == gtTarget) or + (GetGearType(gear) == gtFlame) or + (GetGearType(gear) == gtExplosives) or + (GetGearType(gear) == gtPortal) or + (GetGearType(gear) == gtMine) or + (GetGearType(gear) == gtSMine) or + (GetGearType(gear) == gtAirMine) or + (GetGearType(gear) == gtCase) + then + return(true) + else + return(false) + end +end + +function onGearAdd(gear) + + if isATrackedGear(gear) then + trackGear(gear) + + if GetGearType(gear) == gtPortal then + setGearValue(gear,"life",portalDistance) + elseif GetGearType(gear) == gtHedgehog then + hhs[numhhs] = gear + numhhs = numhhs + 1 + SetEffect(gear, heResurrectable, 1) + end + + end + + if GetGearType(gear) == gtAirAttack then + cGear = gear + elseif GetGearType(gear) == gtJetpack then + jet = gear + if (ufoFuel ~= 0) then + SetHealth(jet, ufoFuel) + end + end + + +end + +function onGearDelete(gear) + + if isATrackedGear(gear) then + trackDeletion(gear) + elseif GetGearType(gear) == gtAirAttack then + cGear = nil + elseif GetGearType(gear) == gtJetpack then + jet = nil + end + +end + +function onAttack() + at = GetCurAmmoType() + + usedWeapons[at] = 0 +end + +function onAchievementsDeclaration() + usedWeapons[amSkip] = nil + + usedRope = usedWeapons[amRope] ~= nil + usedPortal = usedWeapons[amPortalGun] ~= nil + usedSaucer = usedWeapons[amJetpack] ~= nil + + usedWeapons[amRope] = nil + usedWeapons[amPortalGun] = nil + usedWeapons[amJetpack] = nil + + usedOther = next(usedWeapons) ~= nil + + if usedOther then -- smth besides skip, rope, portal or saucer used + raceType = "unknown race" + elseif usedRope and not usedPortal and not usedSaucer then + raceType = "rope race" + elseif not usedRope and usedPortal and not usedSaucer then + raceType = "portal race" + elseif not usedRope and not usedPortal and usedSaucer then + raceType = "saucer race" + elseif (usedRope or usedPortal or usedSaucer or usedOther) == false then -- no weapons used at all? + raceType = "no tools race" + else -- at least two of rope, portal and saucer used + raceType = "mixed race" + end + + map = detectMap() + + for i = 0, (numTeams-1) do + if teamScore[i] < 100000 then + DeclareAchievement(raceType, teamNameArr[i], map, teamScore[i]) + end + end +end + +function onAmmoStoreInit() + + SetAmmo(amSkip, 9, 0, 0, 0) + + for i = 1, #atkArray do + SetAmmo(atkArray[i][1], 0, 0, 0, 1) + end + + for i = 1, #utilArray do + SetAmmo(utilArray[i][1], 0, 0, 0, 1) + end + +end + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Scripts/Multiplayer/The_Specialists.cfg --- a/share/hedgewars/Data/Scripts/Multiplayer/The_Specialists.cfg Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Scripts/Multiplayer/The_Specialists.cfg Tue Nov 10 20:43:13 2015 +0100 @@ -1,2 +1,2 @@ -Default -Default +* +locked diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Scripts/Multiplayer/The_Specialists.lua --- a/share/hedgewars/Data/Scripts/Multiplayer/The_Specialists.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Scripts/Multiplayer/The_Specialists.lua Tue Nov 10 20:43:13 2015 +0100 @@ -127,48 +127,48 @@ if z == 1 then - SetHogName(hhs[i],"Soldier") + SetHogName(hhs[i],loc("Soldier")) SetHogHat(hhs[i], "sf_vega") SetHealth(hhs[i],200) elseif z == 2 then SetHogHat(hhs[i], "Glasses") - SetHogName(hhs[i],"Engineer") + SetHogName(hhs[i],loc("Engineer")) elseif z == 3 then - SetHogName(hhs[i],"Ninja") + SetHogName(hhs[i],loc("Ninja")) SetHogHat(hhs[i], "NinjaFull") SetHealth(hhs[i],80) elseif z == 4 then - SetHogName(hhs[i],"Demo") + SetHogName(hhs[i],loc("Demo")) SetHogHat(hhs[i], "Skull") SetHealth(hhs[i],200) elseif z == 5 then - SetHogName(hhs[i],"Sniper") + SetHogName(hhs[i],loc("Sniper")) SetHogHat(hhs[i], "Sniper") SetHealth(hhs[i],120) elseif z == 6 then - SetHogName(hhs[i],"Saint") + SetHogName(hhs[i],loc("Saint")) SetHogHat(hhs[i], "angel") SetHealth(hhs[i],300) elseif z == 7 then - SetHogName(hhs[i],"Pyro") + SetHogName(hhs[i],loc("Pyro")) SetHogHat(hhs[i], "Gasmask") SetHealth(hhs[i],150) elseif z == 8 then - SetHogName(hhs[i],"Loon") + SetHogName(hhs[i],loc("Loon")) SetHogHat(hhs[i], "clown") SetHealth(hhs[i],100) @@ -181,7 +181,8 @@ end function onGameInit() - GameFlags = gfRandomOrder + gfResetWeps + gfInfAttack + gfPlaceHog +gfPerHogAmmo + ClearGameFlags() + EnableGameFlags(gfRandomOrder, gfResetWeps, gfInfAttack, gfPlaceHog, gfPerHogAmmo) Delay = 10 HealthCaseProb = 100 end @@ -242,7 +243,7 @@ AddAmmo(CurrentHedgehog, amSwitch, 1) elseif switchStage == 2 then - ParseCommand("setweap " .. string.char(amSwitch)) + SetWeapon(amSwitch) elseif switchStage == 3 then SetGearMessage(CurrentHedgehog,gmAttack) elseif switchStage == 4 then diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Scripts/Multiplayer/Tumbler.cfg --- a/share/hedgewars/Data/Scripts/Multiplayer/Tumbler.cfg Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Scripts/Multiplayer/Tumbler.cfg Tue Nov 10 20:43:13 2015 +0100 @@ -1,2 +1,2 @@ -Default -Default +* +* diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Scripts/Multiplayer/Tunnels.cfg --- a/share/hedgewars/Data/Scripts/Multiplayer/Tunnels.cfg Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Scripts/Multiplayer/Tunnels.cfg Tue Nov 10 20:43:13 2015 +0100 @@ -1,2 +1,2 @@ -Default -Default +* +* diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Scripts/Multiplayer/Tunnels.lua --- a/share/hedgewars/Data/Scripts/Multiplayer/Tunnels.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Scripts/Multiplayer/Tunnels.lua Tue Nov 10 20:43:13 2015 +0100 @@ -1,30 +1,10 @@ - PointsBuffer = '' -- A string to accumulate points in - function AddPoint(x, y, width, erase) - PointsBuffer = PointsBuffer .. string.char(band(x,0xff00) / 256 , band(x,0xff) , band(y,0xff00) / 256 , band(y,0xff)) - if width then - width = bor(width,0x80) - if erase then - width = bor(width,0x40) - end - PointsBuffer = PointsBuffer .. string.char(width) - else - PointsBuffer = PointsBuffer .. string.char(0) - end - if #PointsBuffer > 245 then - ParseCommand('draw '..PointsBuffer) - PointsBuffer = '' - end - end - function FlushPoints() - if #PointsBuffer > 0 then - ParseCommand('draw '..PointsBuffer) - PointsBuffer = '' - end - end +function onPreviewInit() +onGameInit() +end function onGameInit() - MapGen = 2 + MapGen = mgDrawn TemplateFilter = 0 for i = 200,2000,600 do AddPoint(1,i,63) @@ -32,7 +12,7 @@ end side = 0 - for i = 0,GetRandom(15)+25 do + for i = 0,1+MapFeatureSize*2 do if side > 3 then size = GetRandom(4)+4 else diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Scripts/Multiplayer/WxW.lua --- a/share/hedgewars/Data/Scripts/Multiplayer/WxW.lua Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Scripts/Multiplayer/WxW.lua Tue Nov 10 20:43:13 2015 +0100 @@ -77,8 +77,6 @@ --local margin local wallsLeft = 0 -local highestY = 0 -local surferTimer = 0 local hasSurfed = false local allWallsHit = false @@ -160,9 +158,9 @@ function BoolToCfgTxt(p) if p == false then - return("Disabled") + return loc("Disabled") else - return("Enabled") + return loc("Enabled") end end @@ -356,25 +354,14 @@ end -function CheckSurfer() - - if GetY(CurrentHedgehog) > highestY then - highestY = GetY(CurrentHedgehog) +function onGearWaterSkip(gear) + if gear == CurrentHedgehog then + hasSurfed = true + AddCaption(loc("Surfer!"),0xffba00ff,capgrpMessage2) end - - if (highestY == (WaterLine-8)) and (hasSurfed == false) then - - surferTimer = surferTimer +1 - if (surferTimer == 40) then - hasSurfed = true - AddCaption(loc("Surfer!"),0xffba00ff,capgrpMessage2) - end - end - end - function WallHit(id, zXMin,zYMin, zWidth, zHeight) if wTouched[id] == false then @@ -521,7 +508,8 @@ function onGameInit() - GameFlags = gfRandomOrder + gfBorder + gfSolidLand --+ gfInfAttack + ClearGameFlags() + EnableGameFlags(gfRandomOrder, gfBorder, gfSolidLand) --, gfInfAttack HealthCaseProb = 0 CaseFreq = 0 @@ -587,10 +575,8 @@ allowCrate = true - surferTimer = 0 hasSurfed = false allWallsHit = false - highestY = 0 crateG = nil @@ -649,8 +635,6 @@ --AddCaption(Map) --AddCaption(RightX ..";" .. GetX(CurrentHedgehog)) - CheckSurfer() - gTimer = gTimer + 1 if gTimer == 25 then gTimer = 1 diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Scripts/OfficialChallenges.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Scripts/OfficialChallenges.lua Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,41 @@ +function detectMap() + if RopePercent == 100 and MinesNum == 0 then +-- challenges with border + if band(GameFlags, gfBorder) ~= 0 then + if LandDigest == "M838018718Scripts/Multiplayer/Racer.lua" then + return("Racer Challenge #1") + elseif LandDigest == "M-490229244Scripts/Multiplayer/Racer.lua" then + return("Racer Challenge #2") + elseif LandDigest == "M806689586Scripts/Multiplayer/Racer.lua" then + return("Racer Challenge #3") + elseif LandDigest == "M1770509913Scripts/Multiplayer/Racer.lua" then + return("Racer Challenge #7") + elseif LandDigest == "M1902370941Scripts/Multiplayer/Racer.lua" then + return("Racer Challenge #8") + elseif LandDigest == "M185940363Scripts/Multiplayer/Racer.lua" then + return("Racer Challenge #9") + elseif LandDigest == "M751885839Scripts/Multiplayer/Racer.lua" then + return("Racer Challenge #10") + elseif LandDigest == "M178845011Scripts/Multiplayer/Racer.lua" then + return("Racer Challenge #11") + elseif LandDigest == "M706743197Scripts/Multiplayer/Racer.lua" then + return("Racer Challenge #12") + elseif LandDigest == "M157242054Scripts/Multiplayer/Racer.lua" then + return("Racer Challenge #13") + elseif LandDigest == "M-1585582638Scripts/Multiplayer/Racer.lua" then + return("Racer Challenge #14") + elseif LandDigest == "M-528106034Scripts/Multiplayer/Racer.lua" then + return("Racer Challenge #16") + end +-- challenges without border + elseif LandDigest == "M-134869715Scripts/Multiplayer/Racer.lua" then + return("Racer Challenge #4") + elseif LandDigest == "M-661895109Scripts/Multiplayer/Racer.lua" then + return("Racer Challenge #5") + elseif LandDigest == "M479034891Scripts/Multiplayer/Racer.lua" then + return("Racer Challenge #6") + elseif LandDigest == "M256715557Scripts/Multiplayer/Racer.lua" then + return("Racer Challenge #15") + end + end +end diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Scripts/Params.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Scripts/Params.lua Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,11 @@ +-- Library for parameters handling + +params = {} + +function parseParams() + if ScriptParam ~= nil then + for k, v in string.gmatch(ScriptParam, "(%w+)=([^,]+)") do + params[k] = v + end + end +end diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Scripts/SpeedShoppa.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Scripts/SpeedShoppa.lua Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,194 @@ +--[=[ +Speed Shoppa Mission Framework for Hedgewars + +This is a simple library intended to make setting up simple training missions a trivial +task. The library has been created to reduce redundancy in Lua scripts. + +The framework generates complete and fully Speed Shoppa missions by just +one function call. + +The missions generated by this script are all the same: +- The player will get a team with a single hedgehog. +- The team gets infinite ropes. +- A fixed set of crates will spawn at predefined positions. +- The mission ends successfully when all crates have been collected +- The mission ends unsuccessfully when the time runs out or the hedgehog dies +- When the mission ends, the time it took to finish the mission is shown + +To use this library, you first have to load it and to call SpeedShoppaMission once with +the appropriate parameters. Really, that’s all! +See the comment of SpeedShoppaMission for a specification of all parameters. + +]=] + +HedgewarsScriptLoad("/Scripts/Locale.lua") + +--[[ +SpeedShoppaMission(params) + +This function sets up the *entire* mission and needs one argument: params. +The argument “params” is a table containing fields which describe the training mission. + mandatory fields: + - map: the name of the map to be used + - theme: the name of the theme (does not need to be a standalone theme) + - time: the time limit in milliseconds + - crates: The coordinates of where the crates will be spawned. + It is a table containing tables containing coordinates of format + { x=value, y=value }. Example: + crates = { + { x = 324, y = 43 }, + { x = 123, y = 56 }, + { x = 6, y = 0 }, + } + There must be at least 1 crate. + + optional fields: + - missionTitle: the name of the mission (optional but highly recommended) (default: "Speed Shoppa") + - hogHat: hat of the hedgehog (default: "NoHat") + - hogName: name of the hedgehog (default: "Roper") + - teamName: name of the hedgehog’s team (default: "Shoppers") + - teamGrave: name of the hedgehog’s grave (default: "Statue") + - teamFlag: name of the team’s flag (default: "cm_shoppa") + - clanColor: color of the (only) clan (default: 0xFF0204, which is a red tone) + - goalText: A short string explaining the goal of the mission + (default: "Use your rope to collect all crates as fast as possible.") + - faceLeft: If true, the hog faces to the left initially, if false, it faces to the right. + (default: false (=right)) + - crateType Specify the type of crate (this has no gameplay effect), pick one of + "ammo", "utility", "health". Default: "ammo" + - extra_onGameStart: A function which is called at the end of this script's onGameStart. It takes no parameters. + You could use this to spawn additional gears like girders or mines. + - extra_onGameInit: A function which is called at the end of this script's onGameInit. +]] + + +local playerHog +local gameStarted = false +local cratesCollected = 0 +local gameEnded = false +local timeOut = false +local hogHurt = false +local endTime + +local crates + +function SpeedShoppaMission(params) + if params.hogHat == nil then params.hogHat = "NoHat" end + if params.hogName == nil then params.hogName = loc("Roper") end + if params.teamName == nil then params.teamName = loc("Shoppers") end + if params.goalText == nil then params.goalText = loc("Use your rope to collect all crates as fast as possible.") end + if params.missionTitle == nil then params.missionTitle = loc("Speed Shoppa") end + if params.clanColor == nil then params.clanColor = 0xFF0204 end + if params.teamGrave == nil then params.teamGrave = "Statue" end + if params.teamFlag == nil then params.teamFlag = "cm_shoppa" end + if params.extra_onGameInit == nil then params.extra_onGameInit = function() end end + if params.extra_onGameStart == nil then params.extra_onGameStart = function() end end + if params.faceLeft == nil then params.faceLeft = false end + + crates = params.crates + startTime = params.time + + _G.onGameInit = function() + GameFlags = gfDisableWind + gfOneClanMode + gfBorder + gfSolidLand + TurnTime = startTime + CaseFreq = 0 + MinesNum = 0 + Explosives = 0 + Delay = 10 + Theme = params.theme + Map = params.map + + AddTeam(params.teamName, params.clanColor, params.teamGrave, "Castle", "Default", params.teamFlag) + playerHog = AddHog(params.hogName, 0, 1, params.hogHat) + HogTurnLeft(playerHog, params.faceLeft) + + SetGearPosition(playerHog, params.hog_x, params.hog_y) + + params.extra_onGameInit() + end + + _G.onAmmoStoreInit = function() + SetAmmo(amRope, 9, 0, 0, 1) + end + + _G.onGameStart = function() + SendHealthStatsOff() + ShowMission(params.missionTitle, loc("Challenge"), params.goalText, -amRope, 5000) + for i=1,#crates do + spawnCrate(crates[i].x, crates[i].y) + end + params.extra_onGameStart() + end + + _G.onNewTurn = function() + SetWeapon(amRope) + gameStarted = true + end + _G.onGearDelete = function(gear) + if GetGearType(gear) == gtCase and not hogHurt and not timeOut then + cratesCollected = cratesCollected + 1 + PlaySound(sndShotgunReload) + if cratesCollected == #crates then + endTime = TurnTimeLeft + finalize() + else + AddCaption(string.format(loc("%d crate(s) remaining"), #crates - cratesCollected)) + end + elseif gear == playerHog then + finalize() + end + end + + _G.onGearDamage = function(gear) + if gear == playerHog then + hogHurt = true + end + end + + + _G.onGameTick20 = function() + if TurnTimeLeft < 40 and TurnTimeLeft > 0 and gameStarted and not timeOut and not gameEnded then + timeOut = true + AddCaption(loc("Time's up!")) + SetHealth(playerHog, 0) + hogHurt = true + end + end + + _G.finalize = function() + if not gameEnded then + if cratesCollected == #crates then + PlaySound(sndVictory, playerHog) + SetState(playerHog, bor(GetState(playerHog), gstWinner)) + SetState(playerHog, band(GetState(playerHog), bnot(gstHHDriven))) + AddCaption(loc("Challenge completed!")) + SendStat(siGameResult, loc("Challenge completed!")) + SendStat(siPointType, loc("milliseconds")) + local time = startTime - endTime + SendStat(siPlayerKills, tostring(time), params.teamName) + SendStat(siCustomAchievement, string.format(loc("You have finished the challenge in %.3f s."), (time/1000))) + TurnTimeLeft = 0 + else + SendStat(siGameResult, loc("Challenge failed!")) + SendStat(siPointType, loc("crate(s)")) + SendStat(siPlayerKills, tostring(cratesCollected), params.teamName) + SendStat(siCustomAchievement, string.format(loc("You have collected %d out of %d crate(s)."), cratesCollected, #crates)) + end + gameEnded = true + EndGame() + end + end + + _G.spawnCrate = function(x, y) + if params.crateType == "utility" then + SpawnFakeUtilityCrate(x, y, false, false) + elseif params.crateType == "ammo" then + SpawnFakeAmmoCrate(x, y, false, false) + elseif params.crateType == "health" then + SpawnFakeHealthCrate(x, y, false, false) + else + SpawnFakeAmmoCrate(x, y, false, false) + end + end + +end diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Scripts/TargetPractice.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Scripts/TargetPractice.lua Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,260 @@ +--[=[ +Target Practice Mission Framework for Hedgewars + +This is a simple library intended to make setting up simple training missions a trivial +task requiring just. The library has been created to reduce redundancy in Lua scripts. + +The training framework generates complete and fully usable training missions by just +one function call. + +The missions generated by this script are all the same: +- The player will get a team with a single hedgehog. +- The team gets a single predefined weapon infinitely times. +- A fixed sequence of targets will spawn at predefined positions. +- When a target has been destroyed, the next target of the target sequence appears +- The mission ends successfully when all targets have been destroyed +- The mission ends unsuccessfully when the time runs out or the hedgehog dies +- When the mission ends, a score is awarded, based on the performance (hit targets, + accuracy and remaining time) of the hedgehog. When not all targets are hit, there + will be no accuracy and time bonuses. + +To use this library, you first have to load it and to call TrainingMission once with +the appropriate parameters. Really, that’s all! +See the comment of TrainingMission for a specification of all parameters. + +Below is a template for your convenience, you just have to fill in the fields and delete +optional arguments you don’t want. +----- snip ----- +HedgewarsScriptLoad("/Scripts/Training.lua") +params = { + missionTitle = , + map = , + theme = , + time = , + ammoType = , + gearType = , + targets = { + { x = , y = }, + { x = , y = }, + -- etc. + }, + + wind = , + solidLand = , + artillery = , + hogHat = , + hogName = , + teamName = , + teamGrave = , + clanColor = , + goalText = , + shootText = +} +TargetPracticeMission(params) +----- snip ----- +]=] + +HedgewarsScriptLoad("/Scripts/Locale.lua") + +local player = nil +local scored = 0 +local shots = 0 +local end_timer = 1000 +local game_lost = false +local time_goal = 0 +local total_targets +local targets + +--[[ +TrainingMission(params) + +This function sets up the *entire* training mission and needs one argument: params. +The argument “params” is a table containing fields which describe the training mission. + mandatory fields: + - missionTitle: the name of the mission + - map: the name map to be used + - theme: the name of the theme (does not need to be a standalone theme) + - time: the time limit in milliseconds + - ammoType: the ammo type of the weapon to be used + - gearType: the gear type of the gear which is fired (used to count shots) + - targets: The coordinates of where the targets will be spawned. + It is a table containing tables containing coordinates of format + { x=value, y=value }. The targets will be spawned in the same + order as specified the coordinate tables appear. Example: + targets = { + { x = 324, y = 43 }, + { x = 123, y = 56 }, + { x = 6, y = 0 }, + } + There must be at least 1 target. + + optional fields: + - wind: the initial wind (-100 to 100) (default: 0 (no wind)) + - solidLand: weather the terrain is indestructible (default: false) + - artillery: if true, the hog can’t move (default: false) + - hogHat: hat of the hedgehog (default: "NoHat") + - hogName: name of the hedgehog (default: "Trainee") + - teamName: name of the hedgehog’s team (default: "Training Team") + - teamGrave: name of the hedgehog’s grave + - clanColor: color of the (only) clan (default: 0xFF0204, which is a red tone) + - goalText: A short string explaining the goal of the mission + (default: "Destroy all targets within the time!") + - shootText: A string which says how many times the player shot, “%d” is replaced + by the number of shots. (default: "You have shot %d times.") +]] +function TargetPracticeMission(params) + if params.hogHat == nil then params.hogHat = "NoHat" end + if params.hogName == nil then params.hogName = loc("Trainee") end + if params.teamName == nil then params.teamName = loc("Training Team") end + if params.goalText == nil then params.goalText = loc("Eliminate all targets before your time runs out.|You have unlimited ammo for this mission.") end + if params.shootText == nil then params.shootText = loc("You have shot %d times.") end + if params.clanColor == nil then params.clanColor = 0xFF0204 end + if params.teamGrave == nil then params.teamGrave= "Statue" end + if params.wind == nil then params.wind = 0 end + + local solid, artillery + if params.solidLand == true then solid = gfSolidLand else solid = 0 end + if params.artillery == true then artillery = gfArtillery else artillery = 0 end + + targets = params.targets + + total_targets = #targets + + _G.onAmmoStoreInit = function() + SetAmmo(params.ammoType, 9, 0, 0, 0) + end + + _G.onGameInit = function() + Seed = 1 + GameFlags = gfDisableWind + gfInfAttack + gfOneClanMode + solid + artillery + TurnTime = params.time + Map = params.map + Theme = params.theme + Goals = params.goalText + CaseFreq = 0 + MinesNum = 0 + Explosives = 0 + + SetWind(params.wind) + + AddTeam(loc(params.teamName), params.clanColor, params.teamGrave, "Island", "Default", "Flowerhog") + + player = AddHog(loc(params.hogName), 0, 1, params.hogHat) + SetGearPosition(player, params.hog_x, params.hog_y) + end + + _G.onGameStart = function() + SendHealthStatsOff() + ShowMission(params.missionTitle, loc("Aiming practice"), params.goalText, -params.ammoType, 5000) + spawnTarget() + end + + _G.onNewTurn = function() + -- TODO: Remove the else branch when 0.9.21 has been released + if SetWeapon ~= nil then + SetWeapon(params.ammoType) + else + ParseCommand("/setweap "..string.char(params.ammoType)) + end + end + + _G.spawnTarget = function() + gear = AddGear(0, 0, gtTarget, 0, 0, 0, 0) + + x = targets[scored+1].x + y = targets[scored+1].y + + SetGearPosition(gear, x, y) + end + + _G.onGameTick20 = function() + if TurnTimeLeft < 40 and TurnTimeLeft > 0 and scored < total_targets and game_lost == false then + game_lost = true + AddCaption(loc("Time’s up!"), 0xFFFFFFFF, capgrpGameState) + ShowMission(params.missionTitle, loc("Aiming practice"), loc("Oh no! Time's up! Just try again."), -amSkip, 0) + SetHealth(player, 0) + time_goal = 1 + end + + if band(GetState(player), gstDrowning) == gstDrowning and game_lost == false and scored < total_targets then + game_lost = true + time_goal = 1 + AddCaption(loc("You lose!"), 0xFFFFFFFF, capgrpGameState) + ShowMission(params.missionTitle, loc("Aiming practice"), loc("Oh no! You failed! Just try again."), -amSkip, 0) + end + + if scored == total_targets or game_lost then + if end_timer == 0 then + generateStats() + EndGame() + else + TurnTimeLeft = time_goal + end + end_timer = end_timer - 20 + end + end + + _G.onGearAdd = function(gear) + if GetGearType(gear) == params.gearType then + shots = shots + 1 + end + end + + _G.onGearDamage = function(gear, damage) + if GetGearType(gear) == gtTarget then + scored = scored + 1 + if scored < total_targets then + AddCaption(string.format(loc("Targets left: %d"), (total_targets-scored)), 0xFFFFFFFF, capgrpMessage) + spawnTarget() + else + if not game_lost then + AddCaption(loc("You have destroyed all targets!"), 0xFFFFFFFF, capgrpGameState) + ShowMission(params.missionTitle, loc("Aiming practice"), loc("Congratulations! You have destroyed all targets within the time."), 0, 0) + PlaySound(sndVictory, player) + SetState(player, bor(GetState(player), gstWinner)) + time_goal = TurnTimeLeft + end + end + end + + if GetGearType(gear) == gtHedgehog then + if not game_lost then + game_lost = true + AddCaption(loc("You lose!", 0xFFFFFFFF, capgrpGameState)) + ShowMission(params.missionTitle, loc("Aiming practice"), loc("Oh no! You failed! Just try again."), -amSkip, 0) + + SetHealth(player, 0) + time_goal = 1 + end + end + end + + _G.generateStats = function() + local accuracy = (scored/shots)*100 + local end_score_targets = scored * math.ceil(6000/#targets) + local end_score_overall + if not game_lost then + local end_score_time = math.ceil(time_goal/(params.time/6000)) + local end_score_accuracy = math.ceil(accuracy * 60) + end_score_overall = end_score_time + end_score_targets + end_score_accuracy + + SendStat(siGameResult, loc("You have finished the target practice!")) + + SendStat(siCustomAchievement, string.format(loc("You have destroyed %d of %d targets (+%d points)."), scored, total_targets, end_score_targets)) + SendStat(siCustomAchievement, string.format(params.shootText, shots)) + SendStat(siCustomAchievement, string.format(loc("Your accuracy was %.1f%% (+%d points)."), accuracy, end_score_accuracy)) + SendStat(siCustomAchievement, string.format(loc("You had %.1fs remaining on the clock (+%d points)."), (time_goal/1000), end_score_time)) + else + SendStat(siGameResult, loc("You lose!")) + + SendStat(siCustomAchievement, string.format(loc("You have destroyed %d of %d targets (+%d points)."), scored, total_targets, end_score_targets)) + SendStat(siCustomAchievement, string.format(params.shootText, shots)) + if(shots > 0) then + SendStat(siCustomAchievement, string.format(loc("Your accuracy was %.1f%%."), accuracy)) + end + end_score_overall = end_score_targets + end + SendStat(siPlayerKills, tostring(end_score_overall), loc(params.teamName)) + SendStat(siPointType, loc("points")) + end +end diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Scripts/TechMaps.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Scripts/TechMaps.lua Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,3858 @@ +------------------------------------------------ +-- TECH MAPS +------------------------------------------------ +-- a centralized collection of maps for use by TechRacer and other scripts. +-- hopefully keeps things a bit cleaner and makes cross-script editing easier. + +-------------- +-- TO DO +-------------- +-- continue to fix/improve old/broken/incompatible maps, and add more maps. +-- add ufo fuel per map + + +HedgewarsScriptLoad("/Scripts/Tracker.lua") + +techX = {} +techY = {} +techCount = 1 + +function AddWayPoint(x,y) + techX[techCount] = x + techY[techCount] = y + techCount = techCount +1 +end + +-- this handles interim lazy copypasta from HedgeEditor +-- while I'm still messing with things +function LoadSprite(pX, pY, pSprite, pFrame, pTint, p1, p2, p3, pLandFlags) + PlaceSprite(pX, pY, pSprite, pFrame, pTint, p1, p2, p3, pLandFlags) +end +function PreviewWayPoint(x,y) + AddPoint(x,y,20) + AddPoint(x,y,19,true) + for i = 0,100,50 do + AddPoint(x-120,y+i,1,true) + AddPoint(x+120,y-i) + AddPoint(x-i,y+120,1,true) + AddPoint(x+i,y-120) + end +end + +function PreviewGirder(x, y, f) + if f == 0 then + AddPoint(x-40,y,1) + AddPoint(x+40,y) + elseif f == 1 then + AddPoint(x-29,y-29,1) + AddPoint(x+29,y+29) + elseif f == 2 then + AddPoint(x,y-40,1) + AddPoint(x,y+40) + elseif f == 3 then + AddPoint(x-29,y+29,1) + AddPoint(x+29,y-29) + elseif f == 4 then + AddPoint(x-79,y,1) + AddPoint(x+79,y) + elseif f == 5 then + AddPoint(x-54,y-54,1) + AddPoint(x+54,y+54) + elseif f == 6 then + AddPoint(x,y-80,1) + AddPoint(x,y+80) + elseif f == 7 then + AddPoint(x-54,y+54,1) + AddPoint(x+54,y-54) + end +end + +function PreviewRubber(x, y, f) + if f == 0 then + AddPoint(x-79,y,1) + AddPoint(x+79,y) + elseif f == 1 then + AddPoint(x-54,y-54,1) + AddPoint(x+54,y+54) + elseif f == 2 then + AddPoint(x,y-80,1) + AddPoint(x,y+80) + elseif f == 3 then + AddPoint(x-54,y+54,1) + AddPoint(x+54,y-54) + end +end + +function PreviewPlacedGear(x, y) + AddPoint(x,y,2) +end + +function onPreviewInit() + + if mapID == nil then + mapID = 2 + GetRandom(7) + end + + MapGen = mgDrawn + TemplateFilter = 0 + + for x = 1, 16 do + AddPoint(x*100,100,5) + end + + if mapID == 1 then + -- + elseif mapID == 2 then + PreviewWayPoint(387, 621) + PreviewWayPoint(215, 1748) + PreviewWayPoint(1617, 1313) + PreviewWayPoint(1642, 562) + PreviewWayPoint(3318, 1102) + PreviewWayPoint(3554, 684) + PreviewWayPoint(2142, 1674) + PreviewGirder(402, 1863, 0) + PreviewGirder(442, 1863, 4) + PreviewGirder(2067, 1945, 6) + PreviewGirder(1943, 1653, 6) + PreviewGirder(1999, 1504, 7) + PreviewGirder(2143, 1445, 4) + PreviewGirder(2432, 1565, 4) + PreviewGirder(2593, 1565, 4) + PreviewGirder(2752, 1565, 4) + PreviewGirder(2206, 1949, 6) + PreviewGirder(2262, 1800, 7) + PreviewGirder(2407, 1745, 4) + PreviewGirder(2569, 1745, 4) + PreviewGirder(2005, 1797, 5) + PreviewGirder(2288, 1503, 5) + PreviewGirder(2715, 1802, 5) + PreviewGirder(2898, 1624, 5) + PreviewGirder(3014, 1740, 5) + PreviewGirder(2830, 1919, 5) + PreviewGirder(3131, 1856, 5) + PreviewGirder(3191, 1968, 2) + PreviewGirder(3264, 2021, 4) + PreviewGirder(2840, 2006, 3) + PreviewGirder(396, 665, 1) + PreviewGirder(619, 665, 3) + PreviewGirder(696, 635, 0) + PreviewGirder(319, 637, 0) + PreviewGirder(268, 604, 2) + PreviewGirder(746, 603, 2) + PreviewGirder(325, 495, 7) + PreviewGirder(689, 493, 5) + PreviewGirder(504, 422, 6) + PreviewGirder(595, 422, 4) + PreviewGirder(412, 422, 4) + PreviewGirder(320, 696, 4) + PreviewGirder(249, 786, 6) + PreviewGirder(249, 948, 6) + PreviewGirder(191, 785, 6) + PreviewGirder(191, 946, 6) + PreviewGirder(191, 1107, 6) + PreviewGirder(249, 1109, 6) + PreviewGirder(130, 1251, 7) + PreviewGirder(306, 1251, 5) + PreviewGirder(72, 1360, 2) + PreviewGirder(364, 1360, 2) + PreviewGirder(132, 1462, 5) + PreviewGirder(304, 1463, 7) + PreviewGirder(182, 1616, 6) + PreviewGirder(255, 1613, 6) + PreviewGirder(217, 1796, 4) + PreviewGirder(221, 1381, 0) + PreviewGirder(154, 669, 1) + PreviewGirder(124, 553, 6) + PreviewGirder(326, 467, 3) + PreviewGirder(223, 592, 3) + PreviewGirder(638, 791, 5) + PreviewGirder(752, 907, 5) + PreviewGirder(866, 1022, 5) + PreviewGirder(1505, 395, 7) + PreviewGirder(1445, 544, 6) + PreviewGirder(1506, 686, 5) + PreviewGirder(1650, 339, 4) + PreviewGirder(1797, 397, 5) + PreviewGirder(1857, 547, 6) + PreviewGirder(1797, 688, 7) + PreviewGirder(1652, 754, 4) + PreviewGirder(3326, 863, 4) + PreviewGirder(3474, 921, 5) + PreviewGirder(3180, 921, 7) + PreviewGirder(3120, 1071, 6) + PreviewGirder(3183, 1214, 5) + PreviewGirder(3536, 1071, 6) + PreviewGirder(3480, 1214, 7) + PreviewGirder(3330, 1279, 4) + PreviewGirder(1481, 1133, 7) + PreviewGirder(1626, 1078, 4) + PreviewGirder(1772, 1135, 5) + PreviewGirder(1422, 1280, 6) + PreviewGirder(1831, 1286, 6) + PreviewGirder(1773, 1429, 7) + PreviewGirder(1627, 1492, 4) + PreviewGirder(1482, 1427, 5) + PreviewGirder(587, 855, 4) + PreviewGirder(425, 855, 4) + PreviewGirder(302, 822, 1) + PreviewGirder(2502, 556, 7) + PreviewGirder(2601, 634, 7) + PreviewGirder(2616, 441, 7) + PreviewGirder(2716, 519, 7) + PreviewGirder(3469, 556, 7) + PreviewGirder(3696, 763, 7) + PreviewGirder(2756, 379, 4) + PreviewGirder(2862, 466, 4) + PreviewGirder(2918, 379, 4) + PreviewGirder(3023, 467, 4) + PreviewGirder(3080, 378, 4) + PreviewGirder(3616, 503, 4) + PreviewGirder(3552, 828, 4) + PreviewGirder(3172, 527, 5) + PreviewGirder(3232, 428, 5) + PreviewGirder(3289, 647, 5) + PreviewGirder(3350, 545, 5) + PreviewGirder(3406, 764, 5) + PreviewGirder(3708, 575, 6) + PreviewGirder(3705, 680, 1) + PreviewRubber(505, 708, 0) + PreviewRubber(175, 451, 0) + PreviewRubber(822, 1693, 0) + PreviewRubber(982, 1691, 0) + PreviewRubber(1142, 1688, 0) + PreviewRubber(1302, 1684, 0) + PreviewRubber(1450, 1750, 1) + PreviewRubber(1566, 1860, 1) + PreviewRubber(1680, 1973, 1) + + PreviewPlacedGear(324, 613) + PreviewPlacedGear(2361, 1721) + PreviewPlacedGear(2430, 1721) + PreviewPlacedGear(2510, 1721) + PreviewPlacedGear(2581, 1721) + PreviewPlacedGear(405, 1839) + PreviewPlacedGear(481, 1839) + PreviewPlacedGear(696, 611) + PreviewPlacedGear(825, 1664) + PreviewPlacedGear(919, 1657) + PreviewPlacedGear(1015, 1662) + PreviewPlacedGear(1095, 1654) + PreviewPlacedGear(1166, 1659) + PreviewPlacedGear(1250, 1650) + PreviewPlacedGear(1335, 1655) + elseif mapID == 3 then + PreviewWayPoint(3892, 478) + PreviewWayPoint(1146, 413) + PreviewWayPoint(934, 1459) + PreviewWayPoint(2635, 1459) + PreviewWayPoint(2656, 523) + PreviewWayPoint(1958, 834) + PreviewWayPoint(555, 864) + PreviewGirder(3703, 157, 7) + PreviewGirder(3846, 100, 4) + PreviewGirder(3991, 162, 5) + PreviewGirder(4049, 311, 6) + PreviewGirder(3648, 308, 6) + PreviewGirder(3988, 454, 7) + PreviewGirder(3843, 515, 4) + PreviewGirder(3616, 429, 3) + PreviewGirder(3725, 548, 3) + PreviewGirder(1155, 95, 6) + PreviewGirder(1067, 167, 4) + PreviewGirder(906, 167, 4) + PreviewGirder(747, 167, 4) + PreviewGirder(586, 167, 4) + PreviewGirder(426, 167, 4) + PreviewGirder(266, 166, 4) + PreviewGirder(105, 166, 4) + + PreviewPlacedGear(3801, 491) + PreviewPlacedGear(3803, 460) + PreviewPlacedGear(3799, 429) + PreviewPlacedGear(3846, 491) + PreviewPlacedGear(3845, 460) + PreviewPlacedGear(3845, 429) + PreviewPlacedGear(3684, 595) + PreviewPlacedGear(3648, 641) + PreviewPlacedGear(3613, 695) + PreviewPlacedGear(3575, 733) + PreviewPlacedGear(3537, 781) + PreviewPlacedGear(3505, 829) + PreviewPlacedGear(3476, 881) + PreviewPlacedGear(3447, 930) + PreviewPlacedGear(3418, 979) + PreviewPlacedGear(3388, 1021) + PreviewPlacedGear(3356, 1072) + PreviewPlacedGear(3561, 469) + PreviewPlacedGear(3528, 500) + PreviewPlacedGear(3496, 545) + PreviewPlacedGear(3467, 584) + PreviewPlacedGear(3444, 619) + PreviewPlacedGear(3404, 656) + PreviewPlacedGear(3373, 693) + PreviewPlacedGear(3351, 726) + PreviewPlacedGear(3329, 756) + PreviewPlacedGear(3306, 798) + PreviewPlacedGear(3339, 1115) + PreviewPlacedGear(3321, 1163) + PreviewPlacedGear(3298, 1206) + PreviewPlacedGear(3281, 1250) + PreviewPlacedGear(3259, 1302) + PreviewPlacedGear(3238, 1343) + PreviewPlacedGear(3220, 1397) + PreviewPlacedGear(3269, 810) + PreviewPlacedGear(3225, 788) + PreviewPlacedGear(3188, 762) + PreviewPlacedGear(3149, 735) + PreviewPlacedGear(3106, 709) + PreviewPlacedGear(3064, 682) + PreviewPlacedGear(3023, 652) + PreviewPlacedGear(2983, 619) + PreviewPlacedGear(3135, 980) + PreviewPlacedGear(3143, 1029) + PreviewPlacedGear(3130, 1077) + PreviewPlacedGear(3122, 1127) + PreviewPlacedGear(3100, 1174) + PreviewPlacedGear(3069, 1226) + PreviewPlacedGear(3042, 1287) + PreviewPlacedGear(3178, 1440) + PreviewPlacedGear(3125, 1480) + PreviewPlacedGear(3088, 1521) + PreviewPlacedGear(2988, 1326) + PreviewPlacedGear(2944, 1357) + PreviewPlacedGear(2884, 1356) + PreviewPlacedGear(2813, 1356) + PreviewPlacedGear(2755, 1356) + PreviewPlacedGear(2677, 1347) + PreviewPlacedGear(2610, 1356) + PreviewPlacedGear(2532, 1354) + PreviewPlacedGear(3045, 1553) + PreviewPlacedGear(2974, 1588) + PreviewPlacedGear(2901, 1584) + PreviewPlacedGear(2850, 1569) + PreviewPlacedGear(2782, 1570) + PreviewPlacedGear(2708, 1577) + PreviewPlacedGear(2648, 1579) + PreviewPlacedGear(2585, 1576) + PreviewPlacedGear(2525, 1581) + PreviewPlacedGear(2490, 1338) + PreviewPlacedGear(2435, 1306) + PreviewPlacedGear(2386, 1283) + PreviewPlacedGear(2344, 1242) + PreviewPlacedGear(3126, 942) + PreviewPlacedGear(3070, 919) + PreviewPlacedGear(3005, 897) + PreviewPlacedGear(2962, 865) + PreviewPlacedGear(2907, 838) + PreviewPlacedGear(2858, 803) + PreviewPlacedGear(2807, 769) + PreviewPlacedGear(2764, 741) + PreviewPlacedGear(2714, 703) + PreviewPlacedGear(2665, 671) + PreviewPlacedGear(2613, 629) + PreviewPlacedGear(2557, 591) + PreviewPlacedGear(2513, 545) + PreviewPlacedGear(2450, 537) + PreviewPlacedGear(2390, 569) + PreviewPlacedGear(2341, 603) + PreviewPlacedGear(2299, 649) + PreviewPlacedGear(2255, 684) + PreviewPlacedGear(2218, 714) + PreviewPlacedGear(2173, 756) + PreviewPlacedGear(2125, 801) + PreviewPlacedGear(2084, 864) + PreviewPlacedGear(2113, 933) + PreviewPlacedGear(2154, 974) + PreviewPlacedGear(2191, 1016) + PreviewPlacedGear(2223, 1061) + PreviewPlacedGear(2257, 1113) + PreviewPlacedGear(2283, 1153) + PreviewPlacedGear(2316, 1202) + PreviewPlacedGear(2479, 1553) + PreviewPlacedGear(2422, 1513) + PreviewPlacedGear(2363, 1477) + PreviewPlacedGear(2302, 1446) + PreviewPlacedGear(2243, 1388) + PreviewPlacedGear(2188, 1335) + PreviewPlacedGear(2136, 1273) + PreviewPlacedGear(2086, 1204) + PreviewPlacedGear(2033, 1132) + PreviewPlacedGear(1992, 1085) + PreviewPlacedGear(1967, 1022) + PreviewPlacedGear(2943, 560) + PreviewPlacedGear(2890, 511) + PreviewPlacedGear(2834, 477) + PreviewPlacedGear(2774, 451) + PreviewPlacedGear(2710, 428) + PreviewPlacedGear(2652, 410) + PreviewPlacedGear(2578, 375) + PreviewPlacedGear(2482, 342) + PreviewPlacedGear(2380, 335) + PreviewPlacedGear(2302, 359) + PreviewPlacedGear(2256, 409) + PreviewPlacedGear(2183, 469) + PreviewPlacedGear(2111, 513) + PreviewPlacedGear(2049, 558) + PreviewPlacedGear(1986, 586) + PreviewPlacedGear(1742, 412) + PreviewPlacedGear(1684, 376) + PreviewPlacedGear(1627, 344) + PreviewPlacedGear(1566, 325) + PreviewPlacedGear(1505, 298) + PreviewPlacedGear(1727, 695) + PreviewPlacedGear(1917, 1067) + PreviewPlacedGear(1874, 1122) + PreviewPlacedGear(1923, 557) + PreviewPlacedGear(1863, 501) + PreviewPlacedGear(1796, 447) + PreviewPlacedGear(1829, 1158) + PreviewPlacedGear(1778, 1201) + PreviewPlacedGear(1732, 1244) + PreviewPlacedGear(1700, 1290) + PreviewPlacedGear(1652, 1333) + PreviewPlacedGear(1599, 1380) + PreviewPlacedGear(1550, 1425) + PreviewPlacedGear(1493, 1483) + PreviewPlacedGear(1443, 1519) + PreviewPlacedGear(1381, 1557) + PreviewPlacedGear(1304, 1590) + PreviewPlacedGear(1237, 1613) + PreviewPlacedGear(1176, 1621) + PreviewPlacedGear(1104, 1626) + PreviewPlacedGear(1032, 1630) + PreviewPlacedGear(964, 1628) + PreviewPlacedGear(886, 1615) + PreviewPlacedGear(813, 1584) + PreviewPlacedGear(750, 1524) + PreviewPlacedGear(697, 1473) + PreviewPlacedGear(645, 1410) + PreviewPlacedGear(602, 1351) + PreviewPlacedGear(557, 1284) + PreviewPlacedGear(506, 1230) + PreviewPlacedGear(467, 1144) + PreviewPlacedGear(449, 1066) + PreviewPlacedGear(421, 980) + PreviewPlacedGear(425, 876) + PreviewPlacedGear(422, 789) + PreviewPlacedGear(434, 699) + PreviewPlacedGear(439, 625) + PreviewPlacedGear(481, 551) + PreviewPlacedGear(537, 494) + PreviewPlacedGear(586, 444) + PreviewPlacedGear(633, 393) + PreviewPlacedGear(674, 360) + PreviewPlacedGear(745, 332) + PreviewPlacedGear(1786, 816) + PreviewPlacedGear(1768, 744) + PreviewPlacedGear(1765, 875) + PreviewPlacedGear(1711, 936) + PreviewPlacedGear(1629, 1016) + PreviewPlacedGear(1579, 1072) + PreviewPlacedGear(1520, 1123) + PreviewPlacedGear(1462, 1185) + PreviewPlacedGear(1415, 1238) + PreviewPlacedGear(1361, 1288) + PreviewPlacedGear(1298, 1318) + PreviewPlacedGear(1230, 1345) + PreviewPlacedGear(1161, 1357) + PreviewPlacedGear(1097, 1367) + PreviewPlacedGear(1033, 1373) + PreviewPlacedGear(971, 1333) + PreviewPlacedGear(900, 1291) + PreviewPlacedGear(840, 1225) + PreviewPlacedGear(795, 1156) + PreviewPlacedGear(744, 1076) + PreviewPlacedGear(706, 995) + PreviewPlacedGear(674, 927) + PreviewPlacedGear(687, 859) + PreviewPlacedGear(719, 781) + PreviewPlacedGear(742, 720) + PreviewPlacedGear(801, 297) + PreviewPlacedGear(880, 280) + PreviewPlacedGear(954, 275) + PreviewPlacedGear(1020, 268) + PreviewPlacedGear(1093, 265) + PreviewPlacedGear(1174, 258) + PreviewPlacedGear(1270, 257) + PreviewPlacedGear(1338, 262) + PreviewPlacedGear(1433, 260) + PreviewPlacedGear(779, 657) + PreviewPlacedGear(824, 624) + PreviewPlacedGear(879, 592) + PreviewPlacedGear(928, 564) + PreviewPlacedGear(995, 544) + PreviewPlacedGear(1055, 541) + PreviewPlacedGear(1121, 540) + PreviewPlacedGear(1184, 534) + PreviewPlacedGear(1252, 536) + PreviewPlacedGear(1317, 542) + PreviewPlacedGear(1380, 553) + PreviewPlacedGear(1448, 567) + PreviewPlacedGear(1521, 582) + PreviewPlacedGear(1580, 600) + PreviewPlacedGear(1633, 626) + PreviewPlacedGear(1683, 651) + elseif mapID == 4 then + PreviewWayPoint(337, 533) + PreviewWayPoint(1069, 1367) + PreviewWayPoint(884, 729) + PreviewWayPoint(1682, 464) + PreviewWayPoint(2773, 505) + PreviewWayPoint(3512, 929) + PreviewWayPoint(4002, 106) + PreviewWayPoint(3964, 1520) + PreviewWayPoint(2592, 1334) + PreviewGirder(194, 388, 7) + PreviewGirder(338, 334, 4) + PreviewGirder(484, 390, 5) + PreviewGirder(139, 543, 6) + PreviewGirder(544, 540, 6) + PreviewGirder(201, 687, 5) + PreviewGirder(485, 684, 7) + PreviewGirder(259, 839, 6) + PreviewGirder(426, 837, 6) + PreviewGirder(259, 999, 6) + PreviewGirder(426, 998, 6) + PreviewGirder(259, 1159, 6) + PreviewGirder(426, 1158, 6) + PreviewGirder(259, 1318, 6) + PreviewGirder(426, 1318, 6) + PreviewGirder(426, 1478, 6) + PreviewGirder(259, 1478, 6) + PreviewGirder(515, 1477, 4) + PreviewGirder(659, 1537, 5) + PreviewGirder(774, 1652, 5) + PreviewGirder(836, 1799, 6) + PreviewGirder(907, 1890, 4) + PreviewGirder(1067, 1890, 4) + PreviewGirder(1212, 1823, 7) + PreviewGirder(1359, 1764, 4) + PreviewGirder(1504, 1822, 5) + PreviewGirder(1647, 1886, 4) + PreviewGirder(1807, 1886, 4) + PreviewGirder(1362, 1869, 4) + PreviewGirder(1968, 1885, 4) + PreviewGirder(2111, 1823, 7) + PreviewGirder(2257, 1769, 4) + PreviewGirder(2403, 1825, 5) + PreviewGirder(2549, 1887, 4) + PreviewGirder(2709, 1887, 4) + PreviewGirder(2868, 1887, 4) + PreviewGirder(2958, 1854, 2) + PreviewGirder(2928, 1773, 1) + PreviewGirder(2898, 1692, 2) + PreviewGirder(2928, 1613, 3) + PreviewGirder(3045, 1584, 4) + PreviewGirder(3162, 1619, 1) + PreviewGirder(3192, 1697, 2) + PreviewGirder(3160, 1777, 3) + PreviewGirder(3128, 1857, 2) + PreviewGirder(3218, 1886, 4) + PreviewGirder(3379, 1885, 4) + PreviewGirder(3524, 1818, 7) + PreviewGirder(3641, 1702, 7) + PreviewGirder(3756, 1585, 7) + PreviewGirder(4021, 1316, 7) + PreviewGirder(3842, 1503, 3) + PreviewGirder(3899, 1409, 7) + PreviewGirder(3694, 1974, 7) + PreviewGirder(3809, 1858, 7) + PreviewGirder(3925, 1741, 7) + PreviewGirder(4022, 1613, 7) + PreviewGirder(2256, 1877, 4) + PreviewGirder(3046, 1728, 0) + PreviewGirder(501, 1777, 6) + PreviewGirder(572, 1868, 4) + PreviewGirder(3372, 771, 7) + PreviewGirder(3517, 715, 4) + PreviewGirder(3663, 774, 5) + PreviewGirder(3313, 923, 6) + PreviewGirder(3373, 1066, 5) + PreviewGirder(3518, 1128, 4) + PreviewGirder(3662, 1065, 7) + PreviewGirder(3723, 924, 6) + PreviewGirder(2474, 1373, 6) + PreviewGirder(2474, 1252, 2) + PreviewGirder(2507, 1200, 0) + PreviewGirder(2626, 1200, 4) + PreviewGirder(2716, 1270, 6) + PreviewGirder(2505, 1464, 0) + PreviewGirder(2625, 1464, 4) + PreviewGirder(2716, 1391, 6) + PreviewGirder(1544, 300, 7) + PreviewGirder(1691, 245, 4) + PreviewGirder(1838, 304, 5) + PreviewGirder(1487, 453, 6) + PreviewGirder(1548, 597, 5) + PreviewGirder(1692, 657, 4) + PreviewGirder(1835, 593, 7) + PreviewGirder(1900, 451, 6) + PreviewGirder(3527, 93, 6) + PreviewGirder(3586, 238, 5) + PreviewGirder(3703, 354, 5) + PreviewGirder(3820, 471, 5) + PreviewGirder(3938, 588, 5) + PreviewGirder(4044, 651, 0) + PreviewGirder(3618, 22, 4) + PreviewGirder(3779, 22, 4) + PreviewGirder(3939, 22, 4) + PreviewGirder(4047, 22, 0) + PreviewGirder(936, 1198, 7) + PreviewGirder(1080, 1143, 4) + PreviewGirder(1225, 1202, 5) + PreviewGirder(1278, 1352, 6) + PreviewGirder(881, 1351, 6) + PreviewGirder(943, 1496, 5) + PreviewGirder(1219, 1495, 7) + PreviewGirder(1160, 1645, 6) + PreviewGirder(998, 1649, 6) + PreviewGirder(1160, 1766, 2) + PreviewGirder(998, 1770, 2) + PreviewGirder(1077, 1824, 4) + PreviewGirder(1824, 1138, 6) + PreviewGirder(834, 606, 7) + PreviewGirder(950, 593, 5) + PreviewGirder(1035, 683, 1) + PreviewGirder(748, 696, 3) + PreviewGirder(764, 780, 5) + PreviewGirder(850, 870, 1) + PreviewGirder(937, 850, 7) + PreviewGirder(1018, 768, 7) + PreviewGirder(2589, 444, 7) + PreviewGirder(2704, 329, 7) + PreviewGirder(2604, 560, 5) + PreviewGirder(2719, 675, 5) + PreviewGirder(2832, 689, 7) + PreviewGirder(2947, 573, 7) + PreviewGirder(2820, 317, 5) + PreviewGirder(2936, 433, 5) + PreviewGirder(2987, 489, 1) + PreviewGirder(338, 559, 4) + + PreviewPlacedGear(548, 1844) + PreviewPlacedGear(595, 1844) + PreviewPlacedGear(642, 1844) + PreviewPlacedGear(1314, 1845) + PreviewPlacedGear(1362, 1845) + PreviewPlacedGear(1419, 1845) + PreviewPlacedGear(2208, 1853) + PreviewPlacedGear(2264, 1853) + PreviewPlacedGear(2318, 1853) + PreviewPlacedGear(3027, 1704) + PreviewPlacedGear(3072, 1704) + PreviewPlacedGear(1822, 1042) + PreviewPlacedGear(313, 535) + PreviewPlacedGear(365, 535) + PreviewPlacedGear(313, 504) + PreviewPlacedGear(339, 478) + PreviewPlacedGear(365, 504) + PreviewPlacedGear(3517, 995) + PreviewPlacedGear(3448, 858) + PreviewPlacedGear(3582, 848) + PreviewPlacedGear(3758, 158) + PreviewPlacedGear(3964, 297) + PreviewPlacedGear(2772, 506) + PreviewPlacedGear(2602, 1339) + PreviewPlacedGear(1638, 370) + PreviewPlacedGear(1743, 522) + PreviewPlacedGear(894, 726) + PreviewPlacedGear(1080, 1690) + elseif mapID == 5 then + PreviewWayPoint(3761, 428) + PreviewWayPoint(750, 1801) + PreviewWayPoint(511, 1232) + PreviewWayPoint(1579, 297) + PreviewWayPoint(2007, 1618) + PreviewWayPoint(3642, 1601) + PreviewRubber(3776, 447, 3) + PreviewRubber(3629, 503, 0) + PreviewRubber(3486, 446, 1) + PreviewRubber(3234, 889, 1) + PreviewRubber(3084, 838, 0) + PreviewRubber(2943, 909, 3) + PreviewRubber(2665, 507, 3) + PreviewRubber(2520, 557, 0) + PreviewRubber(2377, 496, 1) + PreviewRubber(2507, 1263, 1) + PreviewRubber(2355, 1212, 0) + PreviewRubber(2206, 1269, 3) + PreviewRubber(1902, 1270, 1) + PreviewRubber(1749, 1221, 0) + PreviewRubber(1607, 1288, 3) + PreviewRubber(1781, 1659, 1) + PreviewRubber(1927, 1706, 0) + PreviewRubber(2089, 1702, 0) + PreviewRubber(2234, 1649, 3) + PreviewRubber(3413, 1631, 1) + PreviewRubber(3558, 1676, 0) + PreviewRubber(3718, 1673, 0) + PreviewRubber(3866, 1616, 3) + PreviewRubber(807, 803, 2) + PreviewRubber(806, 1131, 2) + PreviewRubber(732, 1273, 3) + PreviewRubber(583, 1324, 0) + PreviewRubber(420, 1324, 0) + PreviewRubber(272, 1274, 1) + PreviewRubber(222, 1121, 2) + PreviewRubber(221, 956, 2) + PreviewRubber(221, 792, 2) + PreviewRubber(271, 644, 3) + PreviewRubber(420, 589, 0) + PreviewRubber(584, 588, 0) + PreviewRubber(730, 658, 1) + PreviewRubber(612, 1846, 1) + PreviewRubber(758, 1896, 0) + PreviewRubber(903, 1835, 3) + PreviewRubber(1051, 1781, 0) + PreviewRubber(1210, 1780, 0) + PreviewRubber(1356, 1845, 1) + PreviewRubber(1501, 1891, 0) + PreviewRubber(1438, 431, 3) + PreviewRubber(1589, 378, 0) + PreviewRubber(1736, 448, 1) + + PreviewPlacedGear(397, 1295) + PreviewPlacedGear(461, 1295) + PreviewPlacedGear(555, 1295) + PreviewPlacedGear(621, 1295) + PreviewPlacedGear(759, 1867) + PreviewPlacedGear(1504, 1862) + PreviewPlacedGear(2521, 528) + PreviewPlacedGear(3639, 474) + PreviewPlacedGear(3078, 809) + PreviewPlacedGear(1752, 1192) + PreviewPlacedGear(2349, 1183) + PreviewPlacedGear(1582, 349) + PreviewPlacedGear(3560, 1647) + PreviewPlacedGear(3711, 1644) + PreviewPlacedGear(433, 560) + PreviewPlacedGear(568, 559) + PreviewPlacedGear(1935, 1677) + PreviewPlacedGear(2084, 1673) + PreviewPlacedGear(1018, 1752) + PreviewPlacedGear(1086, 1752) + PreviewPlacedGear(1176, 1751) + PreviewPlacedGear(1238, 1751) + PreviewPlacedGear(2009, 1668) + PreviewPlacedGear(3641, 1639) + PreviewPlacedGear(3580, 469) + PreviewPlacedGear(3700, 467) + PreviewPlacedGear(2458, 523) + PreviewPlacedGear(2595, 521) + elseif mapID == 6 then + PreviewWayPoint(438, 278) + PreviewWayPoint(1870, 1354) + PreviewWayPoint(892, 1119) + PreviewGirder(419, 298, 4) + PreviewGirder(348, 387, 6) + PreviewGirder(521, 359, 0) + PreviewGirder(459, 385, 3) + PreviewGirder(570, 387, 6) + PreviewGirder(601, 298, 0) + PreviewGirder(348, 547, 6) + PreviewGirder(570, 547, 6) + PreviewGirder(348, 707, 6) + PreviewGirder(570, 707, 6) + PreviewGirder(397, 466, 0) + PreviewGirder(458, 491, 1) + PreviewGirder(521, 592, 0) + PreviewGirder(458, 620, 3) + PreviewGirder(397, 713, 0) + PreviewGirder(459, 740, 1) + PreviewGirder(348, 867, 6) + PreviewGirder(570, 866, 6) + PreviewGirder(641, 1038, 4) + PreviewGirder(800, 1038, 4) + PreviewGirder(959, 1038, 4) + PreviewGirder(482, 1038, 4) + PreviewGirder(323, 1038, 4) + PreviewGirder(163, 1038, 4) + PreviewGirder(48, 1038, 0) + PreviewGirder(813, 1126, 6) + PreviewGirder(989, 1127, 6) + PreviewGirder(989, 1288, 6) + PreviewGirder(989, 1449, 6) + PreviewGirder(813, 1287, 6) + PreviewGirder(813, 1448, 6) + PreviewGirder(900, 1214, 4) + PreviewGirder(989, 1570, 2) + PreviewGirder(813, 1569, 2) + PreviewGirder(813, 1690, 6) + PreviewGirder(521, 844, 0) + PreviewGirder(457, 870, 3) + PreviewGirder(392, 941, 1) + PreviewGirder(813, 1851, 6) + PreviewGirder(813, 1972, 2) + PreviewGirder(989, 1690, 6) + PreviewGirder(1044, 1817, 5) + PreviewGirder(901, 1979, 4) + PreviewGirder(1002, 2005, 1) + PreviewGirder(1176, 1873, 4) + PreviewGirder(1333, 1873, 4) + PreviewGirder(1491, 1873, 4) + PreviewGirder(1625, 1815, 7) + PreviewGirder(1680, 1688, 6) + PreviewGirder(1669, 1980, 7) + PreviewGirder(1762, 1929, 0) + PreviewGirder(1811, 1853, 6) + PreviewGirder(1811, 1692, 6) + PreviewGirder(1708, 1735, 3) + PreviewGirder(1776, 1734, 1) + PreviewGirder(1680, 1527, 6) + PreviewGirder(1811, 1532, 6) + PreviewGirder(1608, 1437, 4) + PreviewGirder(1883, 1443, 4) + PreviewGirder(1955, 1354, 6) + PreviewGirder(1883, 1264, 4) + PreviewGirder(1723, 1264, 4) + PreviewGirder(1562, 1264, 4) + PreviewGirder(1519, 1354, 6) + PreviewRubber(210, 958, 1) + PreviewRubber(98, 844, 1) + + PreviewPlacedGear(1740, 1905) + PreviewPlacedGear(1780, 1905) + PreviewPlacedGear(1782, 1874) + PreviewPlacedGear(1782, 1843) + PreviewPlacedGear(368, 274) + PreviewPlacedGear(526, 568) + PreviewPlacedGear(474, 1014) + PreviewPlacedGear(906, 1955) + PreviewPlacedGear(837, 1570) + PreviewPlacedGear(835, 1361) + PreviewPlacedGear(836, 1425) + PreviewPlacedGear(833, 1495) + PreviewPlacedGear(967, 1566) + PreviewPlacedGear(970, 1354) + PreviewPlacedGear(967, 1422) + PreviewPlacedGear(968, 1493) + elseif mapID == 7 then + PreviewWayPoint(3820, 342) + PreviewWayPoint(3343, 1612) + PreviewWayPoint(272, 351) + PreviewWayPoint(159, 1774) + PreviewWayPoint(2248, 1573) + PreviewWayPoint(1379, 1192) + PreviewGirder(3699, 436, 0) + PreviewGirder(934, 806, 6) + PreviewGirder(934, 969, 6) + PreviewGirder(1233, 1342, 5) + PreviewGirder(1377, 1403, 4) + PreviewGirder(1497, 1376, 3) + PreviewGirder(2816, 1284, 7) + PreviewGirder(2698, 1401, 7) + PreviewGirder(2640, 1552, 6) + PreviewGirder(2640, 1718, 6) + PreviewGirder(2641, 1881, 6) + PreviewGirder(2643, 2007, 2) + PreviewGirder(3823, 363, 0) + PreviewGirder(233, 596, 6) + PreviewGirder(288, 446, 7) + PreviewGirder(79, 642, 6) + PreviewGirder(80, 479, 6) + PreviewGirder(140, 335, 7) + PreviewGirder(281, 268, 4) + PreviewGirder(343, 334, 2) + PreviewGirder(57, 747, 3) + PreviewGirder(32, 852, 6) + PreviewGirder(33, 1015, 6) + PreviewGirder(33, 1179, 6) + PreviewGirder(34, 1342, 6) + PreviewGirder(1346, 1939, 6) + PreviewGirder(1347, 1774, 6) + PreviewGirder(1294, 1636, 5) + PreviewGirder(1180, 1522, 5) + PreviewGirder(1067, 1410, 5) + PreviewGirder(931, 1357, 4) + PreviewGirder(772, 1358, 4) + PreviewGirder(96, 1303, 5) + PreviewGirder(236, 1362, 4) + PreviewGirder(396, 1363, 4) + PreviewGirder(520, 1364, 0) + PreviewGirder(696, 1450, 6) + PreviewGirder(556, 1454, 6) + PreviewGirder(489, 1598, 7) + PreviewGirder(697, 1574, 2) + PreviewGirder(639, 1681, 7) + PreviewGirder(520, 1798, 7) + PreviewGirder(369, 1715, 7) + PreviewGirder(243, 1716, 5) + PreviewGirder(128, 1735, 7) + PreviewGirder(133, 1870, 5) + PreviewGirder(251, 1987, 5) + PreviewGirder(402, 1915, 7) + PreviewGirder(276, 1938, 4) + PreviewGirder(95, 140, 4) + PreviewGirder(257, 140, 4) + PreviewGirder(419, 140, 4) + PreviewGirder(581, 140, 4) + PreviewGirder(742, 140, 4) + PreviewGirder(903, 140, 4) + PreviewGirder(1064, 141, 4) + PreviewGirder(1157, 90, 6) + PreviewRubber(3433, 237, 3) + PreviewRubber(3581, 185, 0) + PreviewRubber(3741, 182, 0) + PreviewRubber(3879, 257, 1) + PreviewRubber(3921, 411, 2) + PreviewRubber(3844, 555, 3) + PreviewRubber(3692, 615, 0) + PreviewRubber(3529, 618, 0) + PreviewRubber(3381, 555, 1) + PreviewRubber(3282, 289, 0) + PreviewRubber(3223, 514, 0) + PreviewRubber(3111, 289, 0) + PreviewRubber(3058, 516, 0) + PreviewRubber(2947, 287, 0) + PreviewRubber(2889, 515, 0) + PreviewRubber(2785, 288, 0) + PreviewRubber(2788, 578, 2) + PreviewRubber(2790, 741, 2) + PreviewRubber(2862, 884, 1) + PreviewRubber(2749, 1073, 1) + PreviewRubber(2865, 1186, 1) + PreviewRubber(2979, 990, 1) + PreviewRubber(3123, 1036, 0) + PreviewRubber(3188, 934, 2) + PreviewRubber(3010, 1234, 0) + PreviewRubber(3175, 1230, 0) + PreviewRubber(3339, 1226, 0) + PreviewRubber(3345, 949, 2) + PreviewRubber(3405, 804, 3) + PreviewRubber(3531, 702, 3) + PreviewRubber(3444, 1007, 0) + PreviewRubber(3499, 1221, 0) + PreviewRubber(3604, 1002, 0) + PreviewRubber(3755, 1038, 1) + PreviewRubber(3802, 1186, 2) + PreviewRubber(3741, 1342, 3) + PreviewRubber(3626, 1456, 3) + PreviewRubber(3510, 1314, 3) + PreviewRubber(3392, 1435, 3) + PreviewRubber(3506, 1577, 3) + PreviewRubber(2637, 348, 3) + PreviewRubber(2583, 496, 2) + PreviewRubber(2633, 952, 1) + PreviewRubber(2573, 803, 2) + PreviewRubber(2474, 556, 0) + PreviewRubber(2468, 742, 0) + PreviewRubber(2335, 476, 1) + PreviewRubber(2214, 358, 1) + PreviewRubber(2322, 812, 3) + PreviewRubber(2202, 936, 3) + PreviewRubber(2060, 305, 0) + PreviewRubber(1898, 304, 0) + PreviewRubber(1736, 304, 0) + PreviewRubber(2085, 1049, 3) + PreviewRubber(1966, 1161, 3) + PreviewRubber(1818, 1209, 0) + PreviewRubber(1657, 1212, 0) + PreviewRubber(1947, 685, 3) + PreviewRubber(1801, 735, 0) + PreviewRubber(1659, 677, 1) + PreviewRubber(1491, 902, 3) + PreviewRubber(1346, 955, 0) + PreviewRubber(1210, 881, 1) + PreviewRubber(1576, 305, 0) + PreviewRubber(1414, 304, 0) + PreviewRubber(1253, 302, 0) + PreviewRubber(1108, 374, 3) + PreviewRubber(991, 491, 3) + PreviewRubber(1557, 1273, 2) + PreviewRubber(938, 639, 2) + PreviewRubber(999, 1117, 1) + PreviewRubber(847, 1079, 0) + PreviewRubber(831, 702, 0) + PreviewRubber(667, 702, 0) + PreviewRubber(687, 1084, 0) + PreviewRubber(1115, 1230, 1) + PreviewRubber(566, 764, 2) + PreviewRubber(525, 1083, 0) + PreviewRubber(422, 1024, 2) + PreviewRubber(464, 703, 0) + PreviewRubber(302, 704, 0) + PreviewRubber(297, 795, 2) + PreviewRubber(316, 1089, 0) + PreviewRubber(1559, 1436, 2) + PreviewRubber(1560, 1598, 2) + PreviewRubber(1560, 1759, 2) + PreviewRubber(1561, 1920, 2) + PreviewRubber(1620, 2022, 0) + PreviewRubber(3388, 1688, 3) + PreviewRubber(3276, 1546, 3) + + PreviewPlacedGear(1757, 706) + PreviewPlacedGear(1838, 706) + PreviewPlacedGear(1319, 926) + PreviewPlacedGear(1389, 926) + PreviewPlacedGear(3184, 839) + PreviewPlacedGear(3185, 808) + PreviewPlacedGear(3677, 412) + PreviewPlacedGear(3079, 1007) + PreviewPlacedGear(3138, 1007) + PreviewPlacedGear(420, 929) + PreviewPlacedGear(3195, 1621) + PreviewPlacedGear(3155, 1655) + PreviewPlacedGear(3112, 1691) + PreviewPlacedGear(3078, 1730) + PreviewPlacedGear(3044, 1764) + PreviewPlacedGear(3011, 1805) + PreviewPlacedGear(2998, 1843) + PreviewPlacedGear(2986, 1886) + PreviewPlacedGear(2978, 1937) + PreviewPlacedGear(733, 1753) + PreviewPlacedGear(3345, 1773) + PreviewPlacedGear(3332, 1806) + PreviewPlacedGear(3317, 1840) + PreviewPlacedGear(3302, 1873) + PreviewPlacedGear(3262, 1902) + PreviewPlacedGear(3237, 1937) + PreviewPlacedGear(3225, 1978) + PreviewPlacedGear(1272, 1839) + PreviewPlacedGear(863, 1776) + PreviewPlacedGear(712, 1902) + PreviewPlacedGear(2361, 1922) + PreviewPlacedGear(2360, 1877) + PreviewPlacedGear(2362, 1825) + PreviewPlacedGear(2364, 1772) + PreviewPlacedGear(2364, 1723) + PreviewPlacedGear(2362, 1670) + PreviewPlacedGear(2395, 1645) + PreviewPlacedGear(2426, 1600) + PreviewPlacedGear(2434, 1543) + PreviewPlacedGear(2435, 1480) + PreviewPlacedGear(2406, 1431) + PreviewPlacedGear(2362, 1392) + PreviewPlacedGear(2313, 1368) + PreviewPlacedGear(2249, 1359) + PreviewPlacedGear(2202, 1386) + PreviewPlacedGear(2151, 1434) + PreviewPlacedGear(1039, 1861) + PreviewPlacedGear(2154, 1946) + PreviewPlacedGear(2156, 1902) + PreviewPlacedGear(2155, 1840) + PreviewPlacedGear(2152, 1777) + PreviewPlacedGear(2161, 1724) + PreviewPlacedGear(2128, 1681) + PreviewPlacedGear(2094, 1442) + PreviewPlacedGear(2036, 1448) + PreviewPlacedGear(1976, 1450) + PreviewPlacedGear(1924, 1454) + PreviewPlacedGear(2082, 1685) + PreviewPlacedGear(2046, 1692) + PreviewPlacedGear(1999, 1696) + PreviewPlacedGear(1961, 1701) + PreviewPlacedGear(1939, 1737) + PreviewPlacedGear(1925, 1783) + PreviewPlacedGear(1916, 1821) + PreviewPlacedGear(1904, 1864) + PreviewPlacedGear(1888, 1913) + PreviewPlacedGear(1870, 1961) + PreviewPlacedGear(1100, 1660) + PreviewPlacedGear(1876, 1486) + PreviewPlacedGear(1826, 1533) + PreviewPlacedGear(1799, 1580) + PreviewPlacedGear(1784, 1637) + PreviewPlacedGear(1765, 1681) + PreviewPlacedGear(1755, 1718) + PreviewPlacedGear(1726, 1779) + PreviewPlacedGear(1718, 1836) + PreviewPlacedGear(1705, 1885) + PreviewPlacedGear(1696, 1934) + PreviewPlacedGear(1685, 1975) + PreviewPlacedGear(859, 1569) + + else + + PreviewWayPoint(383, 1595) + PreviewWayPoint(605, 1157) + PreviewWayPoint(2296, 517) + PreviewWayPoint(2841, 497) + PreviewWayPoint(3209, 1286) + PreviewWayPoint(3708, 1945) + PreviewWayPoint(4075, 1887) + PreviewGirder(430, 1871, 2) + PreviewGirder(1249, 1914, 4) + PreviewGirder(1394, 1849, 7) + PreviewGirder(1522, 1848, 5) + PreviewGirder(1578, 1959, 2) + PreviewGirder(1545, 2011, 0) + PreviewGirder(430, 1749, 6) + PreviewGirder(430, 1589, 6) + PreviewGirder(358, 1499, 4) + PreviewGirder(198, 1499, 4) + PreviewGirder(72, 1571, 7) + PreviewGirder(339, 1618, 4) + PreviewGirder(520, 1499, 4) + PreviewGirder(680, 1499, 4) + PreviewGirder(839, 1499, 4) + PreviewGirder(1000, 1499, 4) + PreviewGirder(1404, 1730, 5) + PreviewGirder(1288, 1613, 5) + PreviewGirder(1200, 1529, 1) + PreviewGirder(1125, 1495, 0) + PreviewGirder(1667, 2011, 4) + PreviewGirder(1812, 1951, 7) + PreviewGirder(1964, 2024, 0) + PreviewGirder(1957, 1892, 4) + PreviewGirder(2103, 1949, 5) + PreviewGirder(2242, 2017, 4) + PreviewGirder(2404, 2017, 4) + PreviewGirder(2548, 1955, 7) + PreviewGirder(2635, 1871, 3) + PreviewGirder(2749, 1836, 4) + PreviewGirder(2751, 1999, 2) + PreviewGirder(2749, 1947, 0) + PreviewGirder(2865, 1870, 1) + PreviewGirder(2954, 1954, 5) + PreviewGirder(3061, 2017, 0) + PreviewGirder(3137, 1984, 3) + PreviewGirder(3169, 1864, 6) + PreviewGirder(3169, 1702, 6) + PreviewGirder(3170, 1540, 6) + PreviewGirder(3170, 1418, 2) + PreviewGirder(3138, 1339, 1) + PreviewGirder(3107, 1260, 2) + PreviewGirder(3153, 1194, 3) + PreviewGirder(3230, 1163, 0) + PreviewGirder(3305, 1201, 1) + PreviewGirder(3334, 1277, 2) + PreviewGirder(3227, 1540, 6) + PreviewGirder(3228, 1419, 2) + PreviewGirder(3334, 1358, 2) + PreviewGirder(3280, 1387, 0) + PreviewGirder(3227, 1702, 6) + PreviewGirder(3227, 1864, 6) + PreviewGirder(3253, 1981, 1) + PreviewGirder(3366, 2017, 4) + PreviewGirder(3528, 2018, 4) + PreviewGirder(3689, 2018, 4) + PreviewGirder(246, 1262, 4) + PreviewGirder(407, 1262, 4) + PreviewGirder(568, 1262, 4) + PreviewGirder(731, 1262, 4) + PreviewGirder(894, 1261, 4) + PreviewGirder(1056, 1261, 4) + PreviewGirder(1179, 1262, 0) + PreviewGirder(1288, 1314, 5) + PreviewGirder(1406, 1433, 5) + PreviewGirder(1525, 1549, 5) + PreviewGirder(1642, 1666, 5) + PreviewGirder(1749, 1728, 0) + PreviewGirder(1956, 1802, 6) + PreviewGirder(1956, 1640, 6) + PreviewGirder(1782, 1638, 6) + PreviewGirder(1835, 1487, 7) + PreviewGirder(1942, 1430, 0) + PreviewGirder(2051, 1486, 5) + PreviewGirder(2109, 1639, 6) + PreviewGirder(2177, 1778, 5) + PreviewGirder(2323, 1840, 4) + PreviewGirder(49, 1029, 0) + PreviewGirder(499, 1172, 6) + PreviewGirder(527, 1054, 3) + PreviewGirder(604, 1026, 0) + PreviewGirder(680, 1056, 1) + PreviewGirder(719, 1168, 6) + PreviewGirder(89, 728, 4) + PreviewGirder(251, 728, 4) + PreviewGirder(412, 728, 4) + PreviewGirder(572, 728, 4) + PreviewGirder(733, 728, 4) + PreviewGirder(894, 728, 4) + PreviewGirder(1016, 728, 0) + PreviewGirder(1067, 799, 6) + PreviewGirder(1139, 891, 4) + PreviewGirder(1067, 1171, 6) + PreviewGirder(1067, 1049, 2) + PreviewGirder(1136, 999, 4) + PreviewGirder(1005, 854, 2) + PreviewGirder(972, 803, 0) + PreviewGirder(920, 780, 2) + PreviewGirder(891, 1206, 2) + PreviewGirder(887, 1150, 0) + PreviewGirder(3018, 1311, 4) + PreviewGirder(2871, 1369, 7) + PreviewGirder(2809, 1523, 6) + PreviewGirder(2809, 1647, 2) + PreviewGirder(2469, 1777, 7) + PreviewGirder(2612, 1715, 4) + PreviewGirder(2809, 1702, 0) + PreviewGirder(2727, 1694, 0) + PreviewGirder(3334, 1481, 6) + PreviewGirder(3334, 1643, 6) + PreviewGirder(3334, 1804, 6) + PreviewGirder(3403, 1940, 5) + PreviewGirder(1120, 944, 2) + PreviewGirder(1163, 945, 2) + PreviewGirder(1141, 781, 5) + PreviewGirder(81, 629, 1) + PreviewGirder(102, 498, 3) + PreviewGirder(81, 373, 1) + PreviewGirder(179, 453, 6) + PreviewGirder(100, 260, 3) + PreviewGirder(179, 330, 2) + PreviewGirder(249, 544, 4) + PreviewGirder(410, 545, 4) + PreviewGirder(571, 543, 4) + PreviewGirder(731, 543, 4) + PreviewGirder(891, 544, 4) + PreviewGirder(1014, 544, 0) + PreviewGirder(1779, 1321, 6) + PreviewGirder(1779, 1159, 6) + PreviewGirder(1779, 997, 6) + PreviewGirder(1779, 836, 6) + PreviewGirder(1722, 684, 5) + PreviewGirder(1137, 545, 4) + PreviewGirder(1298, 545, 4) + PreviewGirder(1460, 546, 4) + PreviewGirder(1608, 600, 5) + PreviewGirder(1508, 1005, 4) + PreviewGirder(160, 246, 1) + PreviewGirder(1821, 1356, 3) + PreviewGirder(1938, 1323, 4) + PreviewGirder(2086, 1381, 5) + PreviewGirder(4004, 2018, 4) + PreviewGirder(3934, 1926, 6) + PreviewGirder(3965, 1835, 0) + PreviewGirder(4015, 1763, 6) + PreviewGirder(4015, 1603, 6) + PreviewGirder(4015, 1442, 6) + PreviewGirder(4015, 1280, 6) + PreviewGirder(4014, 1118, 6) + PreviewGirder(4014, 956, 6) + PreviewGirder(4014, 793, 6) + PreviewGirder(4014, 632, 6) + PreviewGirder(4014, 469, 6) + PreviewGirder(3981, 351, 1) + PreviewGirder(3985, 204, 3) + PreviewGirder(4045, 156, 0) + PreviewGirder(3667, 344, 0) + PreviewGirder(4016, 1925, 6) + PreviewGirder(3998, 1926, 6) + PreviewGirder(3980, 1925, 6) + PreviewGirder(3957, 1926, 6) + PreviewGirder(3843, 1832, 4) + PreviewGirder(3682, 1832, 4) + PreviewGirder(3561, 1833, 0) + PreviewGirder(3484, 1796, 1) + PreviewGirder(3455, 1675, 6) + PreviewGirder(3455, 1513, 6) + PreviewGirder(3455, 1351, 6) + PreviewGirder(1601, 476, 7) + PreviewGirder(1706, 421, 0) + PreviewGirder(1888, 366, 6) + PreviewGirder(3997, 1743, 6) + PreviewGirder(3979, 1742, 6) + PreviewGirder(3962, 1741, 6) + PreviewGirder(3943, 1741, 6) + PreviewGirder(2199, 393, 7) + PreviewGirder(2304, 337, 0) + PreviewGirder(2409, 392, 5) + PreviewGirder(2470, 502, 2) + PreviewGirder(2412, 606, 7) + PreviewGirder(2308, 673, 0) + PreviewGirder(2202, 612, 5) + PreviewGirder(2138, 507, 2) + PreviewGirder(2739, 378, 7) + PreviewGirder(2847, 322, 0) + PreviewGirder(2953, 378, 5) + PreviewGirder(2680, 489, 2) + PreviewGirder(3012, 489, 2) + PreviewGirder(2736, 594, 5) + PreviewGirder(2841, 657, 0) + PreviewGirder(2949, 594, 7) + PreviewGirder(2448, 837, 7) + PreviewGirder(2594, 779, 4) + PreviewGirder(2739, 836, 5) + PreviewGirder(2390, 950, 2) + PreviewGirder(2789, 950, 2) + PreviewGirder(2593, 904, 4) + PreviewGirder(2727, 1056, 7) + PreviewGirder(2452, 1058, 5) + PreviewGirder(2510, 1215, 6) + PreviewGirder(2663, 1208, 6) + PreviewGirder(2510, 1378, 6) + PreviewGirder(2664, 1369, 6) + PreviewGirder(300, 275, 0) + PreviewGirder(439, 274, 0) + PreviewGirder(628, 273, 4) + PreviewGirder(811, 271, 0) + PreviewGirder(737, 373, 4) + PreviewGirder(934, 440, 0) + PreviewGirder(1075, 439, 0) + PreviewGirder(1209, 438, 0) + PreviewGirder(1383, 439, 4) + PreviewGirder(3547, 344, 4) + PreviewGirder(3584, 254, 6) + PreviewGirder(3508, 132, 5) + PreviewGirder(3335, 1117, 6) + PreviewGirder(3335, 956, 6) + PreviewGirder(3335, 795, 6) + PreviewGirder(3335, 634, 6) + PreviewGirder(3335, 513, 2) + PreviewGirder(3401, 404, 7) + PreviewGirder(3455, 1190, 6) + PreviewGirder(3455, 1029, 6) + PreviewGirder(3455, 868, 6) + PreviewGirder(3455, 705, 6) + PreviewGirder(3455, 582, 2) + PreviewGirder(3485, 503, 3) + PreviewGirder(3601, 475, 4) + PreviewGirder(3719, 444, 3) + PreviewGirder(3094, 828, 5) + PreviewGirder(2064, 947, 7) + PreviewGirder(1826, 512, 7) + PreviewGirder(3420, 49, 1) + PreviewGirder(410, 682, 3) + PreviewGirder(528, 653, 4) + PreviewGirder(688, 653, 4) + PreviewGirder(805, 684, 1) + PreviewGirder(528, 672, 4) + PreviewGirder(688, 672, 4) + PreviewGirder(500, 696, 4) + PreviewGirder(701, 696, 4) + + PreviewPlacedGear(889, 1126) + PreviewPlacedGear(1211, 975) + PreviewPlacedGear(3619, 451) + PreviewPlacedGear(304, 1594) + PreviewPlacedGear(1538, 1987) + PreviewPlacedGear(1958, 2000) + PreviewPlacedGear(2744, 1923) + PreviewPlacedGear(3283, 1363) + PreviewPlacedGear(2749, 1812) + PreviewPlacedGear(970, 779) + PreviewPlacedGear(3284, 1332) + PreviewPlacedGear(1082, 975) + PreviewPlacedGear(1547, 981) + PreviewPlacedGear(1707, 397) + PreviewPlacedGear(2309, 649) + PreviewPlacedGear(1116, 867) + PreviewPlacedGear(2559, 880) + PreviewPlacedGear(2630, 880) + PreviewPlacedGear(1951, 1406) + PreviewPlacedGear(3536, 320) + PreviewPlacedGear(3582, 1994) + PreviewPlacedGear(682, 349) + PreviewPlacedGear(2842, 633) + PreviewPlacedGear(506, 1034) + PreviewPlacedGear(556, 1002) + PreviewPlacedGear(615, 1002) + PreviewPlacedGear(676, 1010) + PreviewPlacedGear(716, 1050) + PreviewPlacedGear(67, 1005) + + + end + + FlushPoints() +end + +function LoadMap(mID) + + techX = {} + techY = {} + techCount = 1 + + if mID == 1 then + + --AddCaption("don't load any map, ermagherd, why are you even?") + -- use this when you want to load a hand-drawn map with special points, I guess? + + --[[elseif mID == "1" then + + --simple testmap, the first of its kind + --currently broken due to being old + ------ GIRDER LIST ------ + LoadSprite(306, 530, sprAmGirder, 7) + LoadSprite(451, 474, sprAmGirder, 4) + LoadSprite(595, 531, sprAmGirder, 5) + LoadSprite(245, 679, sprAmGirder, 6) + LoadSprite(305, 822, sprAmGirder, 5) + LoadSprite(449, 887, sprAmGirder, 4) + LoadSprite(593, 825, sprAmGirder, 7) + LoadSprite(657, 681, sprAmGirder, 6) + LoadSprite(1063, 682, sprAmGirder, 6) + LoadSprite(1121, 532, sprAmGirder, 7) + LoadSprite(1266, 476, sprAmGirder, 4) + LoadSprite(1411, 535, sprAmGirder, 5) + LoadSprite(1472, 684, sprAmGirder, 6) + LoadSprite(1415, 828, sprAmGirder, 7) + LoadSprite(1271, 892, sprAmGirder, 4) + LoadSprite(1126, 827, sprAmGirder, 5) + LoadSprite(841, 1079, sprAmGirder, 4) + LoadSprite(709, 1153, sprAmGirder, 7) + LoadSprite(975, 1154, sprAmGirder, 5) + LoadSprite(653, 1265, sprAmGirder, 2) + LoadSprite(1021, 1266, sprAmGirder, 2) + LoadSprite(713, 1369, sprAmGirder, 5) + LoadSprite(960, 1371, sprAmGirder, 7) + LoadSprite(835, 1454, sprAmGirder, 4) + LoadSprite(185, 1617, sprAmGirder, 2) + LoadSprite(1317, 1399, sprAmGirder, 2) + LoadSprite(1711, 1811, sprAmGirder, 2) + LoadSprite(2087, 1424, sprAmGirder, 2) + LoadSprite(2373, 1804, sprAmGirder, 2) + LoadSprite(2646, 1434, sprAmGirder, 2) + LoadSprite(1876, 667, sprAmGirder, 6) + LoadSprite(1934, 517, sprAmGirder, 7) + LoadSprite(2079, 461, sprAmGirder, 4) + LoadSprite(2224, 519, sprAmGirder, 5) + LoadSprite(1935, 810, sprAmGirder, 5) + LoadSprite(2080, 875, sprAmGirder, 4) + LoadSprite(2224, 811, sprAmGirder, 7) + LoadSprite(2370, 582, sprAmGirder, 4) + LoadSprite(2370, 759, sprAmGirder, 4) + LoadSprite(2530, 582, sprAmGirder, 4) + LoadSprite(2690, 582, sprAmGirder, 4) + LoadSprite(2530, 759, sprAmGirder, 4) + LoadSprite(2690, 759, sprAmGirder, 4) + LoadSprite(2836, 634, sprAmGirder, 5) + LoadSprite(2835, 822, sprAmGirder, 5) + LoadSprite(2951, 751, sprAmGirder, 5) + LoadSprite(2950, 939, sprAmGirder, 5) + LoadSprite(2964, 1054, sprAmGirder, 7) + LoadSprite(2978, 1172, sprAmGirder, 5) + LoadSprite(3095, 1185, sprAmGirder, 7) + LoadSprite(3211, 1069, sprAmGirder, 7) + LoadSprite(3038, 843, sprAmGirder, 1) + LoadSprite(3126, 825, sprAmGirder, 7) + LoadSprite(3271, 768, sprAmGirder, 4) + LoadSprite(3357, 1014, sprAmGirder, 4) + LoadSprite(3416, 826, sprAmGirder, 5) + LoadSprite(3454, 969, sprAmGirder, 6) + LoadSprite(3439, 369, sprAmGirder, 6) + LoadSprite(3500, 220, sprAmGirder, 7) + LoadSprite(3502, 513, sprAmGirder, 5) + LoadSprite(3646, 162, sprAmGirder, 4) + LoadSprite(3791, 224, sprAmGirder, 5) + LoadSprite(3851, 374, sprAmGirder, 6) + LoadSprite(3792, 518, sprAmGirder, 7) + LoadSprite(3994, 1731, sprAmGirder, 7) + LoadSprite(3877, 1848, sprAmGirder, 7) + LoadSprite(3789, 1942, sprAmGirder, 3) + LoadSprite(3986, 1929, sprAmGirder, 2) + LoadSprite(2837, 1937, sprAmGirder, 4) + LoadSprite(2997, 1938, sprAmGirder, 4) + LoadSprite(3157, 1938, sprAmGirder, 4) + LoadSprite(1152, 1844, sprAmGirder, 4) + LoadSprite(1299, 1898, sprAmGirder, 5) + LoadSprite(1005, 1900, sprAmGirder, 7) + LoadSprite(3578, 575, sprAmGirder, 6) + LoadSprite(3714, 576, sprAmGirder, 6) + LoadSprite(3579, 740, sprAmGirder, 6) + LoadSprite(3714, 741, sprAmGirder, 6) + LoadSprite(3580, 903, sprAmGirder, 6) + LoadSprite(3715, 904, sprAmGirder, 6) + LoadSprite(3552, 452, sprAmGirder, 1) + LoadSprite(3528, 370, sprAmGirder, 2) + LoadSprite(3568, 297, sprAmGirder, 3) + LoadSprite(3736, 455, sprAmGirder, 3) + LoadSprite(3757, 378, sprAmGirder, 2) + LoadSprite(3725, 299, sprAmGirder, 1) + LoadSprite(3646, 261, sprAmGirder, 0) + LoadSprite(3648, 997, sprAmGirder, 4) + LoadSprite(3649, 1275, sprAmGirder, 2) + LoadSprite(3514, 1750, sprAmGirder, 0) + + ------ AMMO CRATE LIST ------ + tempG = SpawnAmmoCrate(1707, 1755, amBazooka) + tempG = SpawnAmmoCrate(3983, 1873, amBazooka) + tempG = SpawnAmmoCrate(184, 1561, amBazooka) + tempG = SpawnAmmoCrate(2644, 1378, amBazooka) + tempG = SpawnAmmoCrate(2914, 865, amBazooka) + + ------ MINE LIST ------ + SetTimer(AddGear(2340, 580, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2399, 580, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2448, 580, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2517, 579, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2575, 581, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2647, 582, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2720, 582, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2760, 581, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2331, 757, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2409, 758, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2477, 758, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2545, 759, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2613, 760, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2679, 758, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2744, 757, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2813, 610, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2855, 650, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2887, 686, gtMine, 0, 0, 0, 0), 1) +]] + elseif mID == 2 then + + -- more detailed landflag test map, should hopefully work now + -- probably my second favorite techracer map + + ------ GIRDER LIST ------ + LoadSprite(402, 1863, sprAmGirder, 0, 16448250, nil, nil, nil, lfIce) + LoadSprite(442, 1863, sprAmGirder, 4, 16448250, nil, nil, nil, lfIce) + LoadSprite(2067, 1945, sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(1943, 1653, sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(1999, 1504, sprAmGirder, 7, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(2143, 1445, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(2432, 1565, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(2593, 1565, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(2752, 1565, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(2206, 1949, sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(2262, 1800, sprAmGirder, 7, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(2407, 1745, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(2569, 1745, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(2005, 1797, sprAmGirder, 5, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(2288, 1503, sprAmGirder, 5, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(2715, 1802, sprAmGirder, 5, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(2898, 1624, sprAmGirder, 5, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(3014, 1740, sprAmGirder, 5, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(2830, 1919, sprAmGirder, 5, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(3131, 1856, sprAmGirder, 5, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(3191, 1968, sprAmGirder, 2, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(3264, 2021, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(2840, 2006, sprAmGirder, 3, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(396, 665, sprAmGirder, 1, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(619, 665, sprAmGirder, 3, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(696, 635, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(319, 637, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(268, 604, sprAmGirder, 2, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(746, 603, sprAmGirder, 2, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(325, 495, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(689, 493, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(504, 422, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(595, 422, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(412, 422, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(320, 696, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(249, 786, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(249, 948, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(191, 785, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(191, 946, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(191, 1107, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(249, 1109, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(130, 1251, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(306, 1251, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(72, 1360, sprAmGirder, 2, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(364, 1360, sprAmGirder, 2, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(132, 1462, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(304, 1463, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(182, 1616, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(255, 1613, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(217, 1796, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(221, 1381, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(154, 669, sprAmGirder, 1, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(124, 553, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(326, 467, sprAmGirder, 3, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(223, 592, sprAmGirder, 3, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(638, 791, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(752, 907, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(866, 1022, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1505, 395, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1445, 544, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1506, 686, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1650, 339, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1797, 397, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1857, 547, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1797, 688, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1652, 754, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3326, 863, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3474, 921, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3180, 921, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3120, 1071, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3183, 1214, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3536, 1071, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3480, 1214, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3330, 1279, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1481, 1133, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1626, 1078, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1772, 1135, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1422, 1280, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1831, 1286, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1773, 1429, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1627, 1492, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1482, 1427, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(587, 855, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(425, 855, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(302, 822, sprAmGirder, 1, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2502, 556, sprAmGirder, 7, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(2601, 634, sprAmGirder, 7, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(2616, 441, sprAmGirder, 7, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(2716, 519, sprAmGirder, 7, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(3469, 556, sprAmGirder, 7, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(3696, 763, sprAmGirder, 7, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(2756, 379, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(2862, 466, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(2918, 379, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(3023, 467, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(3080, 378, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(3616, 503, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(3552, 828, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(3172, 527, sprAmGirder, 5, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(3232, 428, sprAmGirder, 5, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(3289, 647, sprAmGirder, 5, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(3350, 545, sprAmGirder, 5, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(3406, 764, sprAmGirder, 5, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(3708, 575, sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(3705, 680, sprAmGirder, 1, 2516582650, nil, nil, nil, lfIndestructible) + + ------ RUBBER BAND LIST ------ + LoadSprite(505, 708, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(175, 451, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(822, 1693, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(982, 1691, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(1142, 1688, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(1302, 1684, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(1450, 1750, sprAmRubber, 1, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(1566, 1860, sprAmRubber, 1, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(1680, 1973, sprAmRubber, 1, 4294967295, nil, nil, nil, lfBouncy) + + ------ WAYPOINT LIST ------ + AddWayPoint(387, 621) + AddWayPoint(215, 1748) + AddWayPoint(1617, 1313) + AddWayPoint(1642, 562) + AddWayPoint(3318, 1102) + AddWayPoint(3554, 684) + AddWayPoint(2142, 1674) + + ------ AMMO CRATE LIST ------ + tempG = SpawnAmmoCrate(324, 613, amFirePunch) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents", "amFirePunch") + tempG = SpawnAmmoCrate(2361, 1721, amBazooka) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents", "amBazooka") + tempG = SpawnAmmoCrate(2430, 1721, amBazooka) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents", "amBazooka") + tempG = SpawnAmmoCrate(2510, 1721, amBazooka) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents", "amBazooka") + tempG = SpawnAmmoCrate(2581, 1721, amBazooka) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents", "amBazooka") + tempG = SpawnAmmoCrate(405, 1839, amSineGun) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents", "amSineGun") + tempG = SpawnAmmoCrate(481, 1839, amSineGun) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents", "amSineGun") + + ------ UTILITY CRATE LIST ------ + tempG = SpawnUtilityCrate(696, 611, amParachute) + setGearValue(tempG,"caseType", "util") + setGearValue(tempG,"contents", "amParachute") + tempG = SpawnUtilityCrate(825, 1664, amJetpack) + setGearValue(tempG,"caseType", "util") + setGearValue(tempG,"contents", "amJetpack") + tempG = SpawnUtilityCrate(919, 1657, amJetpack) + setGearValue(tempG,"caseType", "util") + setGearValue(tempG,"contents", "amJetpack") + tempG = SpawnUtilityCrate(1015, 1662, amJetpack) + setGearValue(tempG,"caseType", "util") + setGearValue(tempG,"contents", "amJetpack") + tempG = SpawnUtilityCrate(1095, 1654, amJetpack) + setGearValue(tempG,"caseType", "util") + setGearValue(tempG,"contents", "amJetpack") + tempG = SpawnUtilityCrate(1166, 1659, amJetpack) + setGearValue(tempG,"caseType", "util") + setGearValue(tempG,"contents", "amJetpack") + tempG = SpawnUtilityCrate(1250, 1650, amJetpack) + setGearValue(tempG,"caseType", "util") + setGearValue(tempG,"contents", "amJetpack") + tempG = SpawnUtilityCrate(1335, 1655, amJetpack) + setGearValue(tempG,"caseType", "util") + setGearValue(tempG,"contents", "amJetpack") + + ------ MINE LIST ------ + SetTimer(AddGear(221, 1373, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(609, 661, gtMine, 0, 0, 0, 0), 3000) + + ------ STICKY MINE LIST ------ + tempG = AddGear(190, 756, gtSMine, 0, 0, 0, 0) + tempG = AddGear(191, 810, gtSMine, 0, 0, 0, 0) + tempG = AddGear(189, 868, gtSMine, 0, 0, 0, 0) + tempG = AddGear(190, 923, gtSMine, 0, 0, 0, 0) + tempG = AddGear(192, 984, gtSMine, 0, 0, 0, 0) + tempG = AddGear(192, 1045, gtSMine, 0, 0, 0, 0) + tempG = AddGear(189, 1097, gtSMine, 0, 0, 0, 0) + tempG = AddGear(192, 1159, gtSMine, 0, 0, 0, 0) + tempG = AddGear(248, 753, gtSMine, 0, 0, 0, 0) + tempG = AddGear(248, 808, gtSMine, 0, 0, 0, 0) + tempG = AddGear(249, 868, gtSMine, 0, 0, 0, 0) + tempG = AddGear(250, 921, gtSMine, 0, 0, 0, 0) + tempG = AddGear(246, 982, gtSMine, 0, 0, 0, 0) + tempG = AddGear(247, 1041, gtSMine, 0, 0, 0, 0) + tempG = AddGear(249, 1094, gtSMine, 0, 0, 0, 0) + tempG = AddGear(249, 1156, gtSMine, 0, 0, 0, 0) + tempG = AddGear(2571, 665, gtSMine, 0, 0, 0, 0) + tempG = AddGear(2614, 623, gtSMine, 0, 0, 0, 0) + tempG = AddGear(2658, 580, gtSMine, 0, 0, 0, 0) + tempG = AddGear(2704, 533, gtSMine, 0, 0, 0, 0) + tempG = AddGear(2751, 484, gtSMine, 0, 0, 0, 0) + tempG = AddGear(2830, 466, gtSMine, 0, 0, 0, 0) + tempG = AddGear(2912, 465, gtSMine, 0, 0, 0, 0) + tempG = AddGear(2992, 465, gtSMine, 0, 0, 0, 0) + tempG = AddGear(3072, 468, gtSMine, 0, 0, 0, 0) + tempG = AddGear(2465, 592, gtSMine, 0, 0, 0, 0) + tempG = AddGear(2518, 540, gtSMine, 0, 0, 0, 0) + tempG = AddGear(2580, 477, gtSMine, 0, 0, 0, 0) + tempG = AddGear(2635, 425, gtSMine, 0, 0, 0, 0) + tempG = AddGear(2713, 381, gtSMine, 0, 0, 0, 0) + tempG = AddGear(2796, 378, gtSMine, 0, 0, 0, 0) + tempG = AddGear(2892, 379, gtSMine, 0, 0, 0, 0) + tempG = AddGear(2988, 379, gtSMine, 0, 0, 0, 0) + tempG = AddGear(3061, 377, gtSMine, 0, 0, 0, 0) + tempG = AddGear(3136, 377, gtSMine, 0, 0, 0, 0) + tempG = AddGear(627, 770, gtSMine, 0, 0, 0, 0) + tempG = AddGear(661, 804, gtSMine, 0, 0, 0, 0) + tempG = AddGear(705, 850, gtSMine, 0, 0, 0, 0) + tempG = AddGear(754, 899, gtSMine, 0, 0, 0, 0) + tempG = AddGear(805, 950, gtSMine, 0, 0, 0, 0) + tempG = AddGear(850, 996, gtSMine, 0, 0, 0, 0) + tempG = AddGear(902, 1048, gtSMine, 0, 0, 0, 0) + tempG = AddGear(888, 1034, gtSMine, 0, 0, 0, 0) + tempG = AddGear(788, 933, gtSMine, 0, 0, 0, 0) + tempG = AddGear(839, 985, gtSMine, 0, 0, 0, 0) + tempG = AddGear(736, 881, gtSMine, 0, 0, 0, 0) + tempG = AddGear(686, 829, gtSMine, 0, 0, 0, 0) + tempG = AddGear(649, 792, gtSMine, 0, 0, 0, 0) + + elseif mID == 3 then + + --Helix airmine map + ufoFuel = 2000 + ------ GIRDER LIST ------ + LoadSprite(3703, 157, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3846, 100, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3991, 162, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(4049, 311, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3648, 308, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3988, 454, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3843, 515, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3616, 429, sprAmGirder, 3, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3725, 548, sprAmGirder, 3, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1155, 95, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1067, 167, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(906, 167, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(747, 167, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(586, 167, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(426, 167, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(266, 166, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(105, 166, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + + ------ WAYPOINT LIST ------ + AddWayPoint(3892, 478) + AddWayPoint(1146, 413) + AddWayPoint(934, 1459) + AddWayPoint(2635, 1459) + AddWayPoint(2656, 523) + AddWayPoint(1958, 834) + AddWayPoint(555, 864) + + ------ UTILITY CRATE LIST ------ + tempG = SpawnUtilityCrate(3801, 491, amJetpack) + setGearValue(tempG,"caseType", "util") + setGearValue(tempG,"contents", "amJetpack") + tempG = SpawnUtilityCrate(3803, 460, amJetpack) + setGearValue(tempG,"caseType", "util") + setGearValue(tempG,"contents", "amJetpack") + tempG = SpawnUtilityCrate(3799, 429, amJetpack) + setGearValue(tempG,"caseType", "util") + setGearValue(tempG,"contents", "amJetpack") + tempG = SpawnUtilityCrate(3846, 491, amJetpack) + setGearValue(tempG,"caseType", "util") + setGearValue(tempG,"contents", "amJetpack") + tempG = SpawnUtilityCrate(3845, 460, amJetpack) + setGearValue(tempG,"caseType", "util") + setGearValue(tempG,"contents", "amJetpack") + tempG = SpawnUtilityCrate(3845, 429, amJetpack) + setGearValue(tempG,"caseType", "util") + setGearValue(tempG,"contents", "amJetpack") + + ------ AIR MINE LIST ------ + SetTimer(AddGear(3684, 595, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3648, 641, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3613, 695, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3575, 733, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3537, 781, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3505, 829, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3476, 881, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3447, 930, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3418, 979, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3388, 1021, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3356, 1072, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3561, 469, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3528, 500, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3496, 545, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3467, 584, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3444, 619, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3404, 656, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3373, 693, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3351, 726, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3329, 756, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3306, 798, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3339, 1115, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3321, 1163, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3298, 1206, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3281, 1250, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3259, 1302, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3238, 1343, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3220, 1397, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3269, 810, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3225, 788, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3188, 762, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3149, 735, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3106, 709, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3064, 682, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3023, 652, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2983, 619, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3135, 980, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3143, 1029, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3130, 1077, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3122, 1127, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3100, 1174, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3069, 1226, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3042, 1287, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3178, 1440, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3125, 1480, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3088, 1521, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2988, 1326, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2944, 1357, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2884, 1356, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2813, 1356, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2755, 1356, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2677, 1347, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2610, 1356, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2532, 1354, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3045, 1553, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2974, 1588, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2901, 1584, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2850, 1569, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2782, 1570, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2708, 1577, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2648, 1579, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2585, 1576, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2525, 1581, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2490, 1338, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2435, 1306, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2386, 1283, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2344, 1242, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3126, 942, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3070, 919, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3005, 897, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2962, 865, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2907, 838, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2858, 803, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2807, 769, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2764, 741, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2714, 703, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2665, 671, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2613, 629, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2557, 591, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2513, 545, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2450, 537, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2390, 569, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2341, 603, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2299, 649, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2255, 684, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2218, 714, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2173, 756, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2125, 801, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2084, 864, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2113, 933, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2154, 974, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2191, 1016, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2223, 1061, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2257, 1113, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2283, 1153, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2316, 1202, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2479, 1553, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2422, 1513, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2363, 1477, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2302, 1446, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2243, 1388, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2188, 1335, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2136, 1273, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2086, 1204, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2033, 1132, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1992, 1085, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1967, 1022, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2943, 560, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2890, 511, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2834, 477, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2774, 451, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2710, 428, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2652, 410, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2578, 375, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2482, 342, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2380, 335, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2302, 359, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2256, 409, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2183, 469, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2111, 513, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2049, 558, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1986, 586, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1742, 412, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1684, 376, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1627, 344, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1566, 325, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1505, 298, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1727, 695, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1917, 1067, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1874, 1122, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1923, 557, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1863, 501, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1796, 447, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1829, 1158, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1778, 1201, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1732, 1244, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1700, 1290, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1652, 1333, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1599, 1380, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1550, 1425, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1493, 1483, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1443, 1519, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1381, 1557, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1304, 1590, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1237, 1613, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1176, 1621, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1104, 1626, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1032, 1630, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(964, 1628, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(886, 1615, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(813, 1584, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(750, 1524, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(697, 1473, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(645, 1410, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(602, 1351, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(557, 1284, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(506, 1230, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(467, 1144, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(449, 1066, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(421, 980, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(425, 876, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(422, 789, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(434, 699, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(439, 625, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(481, 551, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(537, 494, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(586, 444, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(633, 393, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(674, 360, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(745, 332, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1786, 816, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1768, 744, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1765, 875, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1711, 936, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1629, 1016, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1579, 1072, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1520, 1123, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1462, 1185, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1415, 1238, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1361, 1288, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1298, 1318, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1230, 1345, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1161, 1357, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1097, 1367, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1033, 1373, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(971, 1333, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(900, 1291, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(840, 1225, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(795, 1156, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(744, 1076, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(706, 995, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(674, 927, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(687, 859, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(719, 781, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(742, 720, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(801, 297, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(880, 280, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(954, 275, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1020, 268, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1093, 265, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1174, 258, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1270, 257, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1338, 262, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1433, 260, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(779, 657, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(824, 624, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(879, 592, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(928, 564, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(995, 544, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1055, 541, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1121, 540, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1184, 534, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1252, 536, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1317, 542, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1380, 553, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1448, 567, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1521, 582, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1580, 600, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1633, 626, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1683, 651, gtAirMine, 0, 0, 0, 0), 1) + + elseif mID == 4 then + + ---nice rope and airmines landflag testmap + ------ GIRDER LIST ------ + + LoadSprite(194, 388, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(338, 334, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(484, 390, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(139, 543, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(544, 540, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(201, 687, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(485, 684, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(259, 839, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(426, 837, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(259, 999, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(426, 998, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(259, 1159, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(426, 1158, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(259, 1318, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(426, 1318, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(426, 1478, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(259, 1478, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(515, 1477, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(659, 1537, sprAmGirder, 5, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(774, 1652, sprAmGirder, 5, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(836, 1799, sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(907, 1890, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(1067, 1890, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(1212, 1823, sprAmGirder, 7, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(1359, 1764, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(1504, 1822, sprAmGirder, 5, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(1647, 1886, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(1807, 1886, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(1362, 1869, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1968, 1885, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(2111, 1823, sprAmGirder, 7, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(2257, 1769, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(2403, 1825, sprAmGirder, 5, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(2549, 1887, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(2709, 1887, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(2868, 1887, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(2958, 1854, sprAmGirder, 2, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(2928, 1773, sprAmGirder, 1, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(2898, 1692, sprAmGirder, 2, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(2928, 1613, sprAmGirder, 3, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(3045, 1584, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(3162, 1619, sprAmGirder, 1, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(3192, 1697, sprAmGirder, 2, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(3160, 1777, sprAmGirder, 3, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(3128, 1857, sprAmGirder, 2, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(3218, 1886, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(3379, 1885, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(3524, 1818, sprAmGirder, 7, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(3641, 1702, sprAmGirder, 7, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(3756, 1585, sprAmGirder, 7, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(4021, 1316, sprAmGirder, 7, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(3842, 1503, sprAmGirder, 3, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(3899, 1409, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3694, 1974, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3809, 1858, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3925, 1741, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(4022, 1613, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2256, 1877, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3046, 1728, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(501, 1777, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(572, 1868, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3372, 771, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3517, 715, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3663, 774, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3313, 923, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3373, 1066, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3518, 1128, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3662, 1065, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3723, 924, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2474, 1373, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2474, 1252, sprAmGirder, 2, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2507, 1200, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2626, 1200, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2716, 1270, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2505, 1464, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2625, 1464, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2716, 1391, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1544, 300, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1691, 245, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1838, 304, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1487, 453, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1548, 597, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1692, 657, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1835, 593, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1900, 451, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3527, 93, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3586, 238, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3703, 354, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3820, 471, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3938, 588, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(4044, 651, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3618, 22, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3779, 22, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3939, 22, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(4047, 22, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(936, 1198, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1080, 1143, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1225, 1202, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1278, 1352, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(881, 1351, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(943, 1496, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1219, 1495, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1160, 1645, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(998, 1649, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1160, 1766, sprAmGirder, 2, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(998, 1770, sprAmGirder, 2, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1077, 1824, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1824, 1138, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(834, 606, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(950, 593, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1035, 683, sprAmGirder, 1, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(748, 696, sprAmGirder, 3, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(764, 780, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(850, 870, sprAmGirder, 1, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(937, 850, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1018, 768, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2589, 444, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2704, 329, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2604, 560, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2719, 675, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2832, 689, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2947, 573, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2820, 317, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2936, 433, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2987, 489, sprAmGirder, 1, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(338, 559, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + + ------ WAYPOINT LIST ------ + AddWayPoint(337, 533) + AddWayPoint(1069, 1367) + AddWayPoint(884, 729) + AddWayPoint(1682, 464) + AddWayPoint(2773, 505) + AddWayPoint(3512, 929) + AddWayPoint(4002, 106) + AddWayPoint(3964, 1520) + AddWayPoint(2592, 1334) + + ------ AMMO CRATE LIST ------ + tempG = SpawnAmmoCrate(548, 1844, amBazooka) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents", "amBazooka") + tempG = SpawnAmmoCrate(595, 1844, amBazooka) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents", "amBazooka") + tempG = SpawnAmmoCrate(642, 1844, amBazooka) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents", "amBazooka") + tempG = SpawnAmmoCrate(1314, 1845, amBazooka) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents", "amBazooka") + tempG = SpawnAmmoCrate(1362, 1845, amBazooka) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents", "amBazooka") + tempG = SpawnAmmoCrate(1419, 1845, amBazooka) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents", "amBazooka") + tempG = SpawnAmmoCrate(2208, 1853, amBazooka) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents", "amBazooka") + tempG = SpawnAmmoCrate(2264, 1853, amBazooka) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents", "amBazooka") + tempG = SpawnAmmoCrate(2318, 1853, amBazooka) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents", "amBazooka") + tempG = SpawnAmmoCrate(3027, 1704, amBazooka) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents", "amBazooka") + tempG = SpawnAmmoCrate(3072, 1704, amBazooka) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents", "amBazooka") + tempG = SpawnAmmoCrate(1822, 1042, amBazooka) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents", "amBazooka") + + ------ UTILITY CRATE LIST ------ + tempG = SpawnUtilityCrate(313, 535, amRope) + setGearValue(tempG,"caseType", "util") + setGearValue(tempG,"contents", "amRope") + tempG = SpawnUtilityCrate(365, 535, amRope) + setGearValue(tempG,"caseType", "util") + setGearValue(tempG,"contents", "amRope") + tempG = SpawnUtilityCrate(313, 504, amRope) + setGearValue(tempG,"caseType", "util") + setGearValue(tempG,"contents", "amRope") + tempG = SpawnUtilityCrate(339, 478, amRope) + setGearValue(tempG,"caseType", "util") + setGearValue(tempG,"contents", "amRope") + tempG = SpawnUtilityCrate(365, 504, amRope) + setGearValue(tempG,"caseType", "util") + setGearValue(tempG,"contents", "amRope") + + ------ AIR MINE LIST ------ + SetTimer(AddGear(3517, 995, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3448, 858, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3582, 848, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3758, 158, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3964, 297, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2772, 506, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2602, 1339, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1638, 370, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1743, 522, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(894, 726, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1080, 1690, gtAirMine, 0, 0, 0, 0), 1) + + elseif mID == 5 then + -- gimmicky bounce map, probably not possible at the moment due + -- to only having a single land flag and techracer forbidding + -- indestructible landflag + + ------ RUBBER BAND LIST ------ + LoadSprite(3776, 447, sprAmRubber, 3, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(3629, 503, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(3486, 446, sprAmRubber, 1, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(3234, 889, sprAmRubber, 1, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(3084, 838, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(2943, 909, sprAmRubber, 3, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(2665, 507, sprAmRubber, 3, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(2520, 557, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(2377, 496, sprAmRubber, 1, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(2507, 1263, sprAmRubber, 1, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(2355, 1212, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(2206, 1269, sprAmRubber, 3, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(1902, 1270, sprAmRubber, 1, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(1749, 1221, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(1607, 1288, sprAmRubber, 3, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(1781, 1659, sprAmRubber, 1, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(1927, 1706, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(2089, 1702, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(2234, 1649, sprAmRubber, 3, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(3413, 1631, sprAmRubber, 1, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(3558, 1676, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(3718, 1673, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(3866, 1616, sprAmRubber, 3, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(807, 803, sprAmRubber, 2, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(806, 1131, sprAmRubber, 2, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(732, 1273, sprAmRubber, 3, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(583, 1324, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(420, 1324, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(272, 1274, sprAmRubber, 1, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(222, 1121, sprAmRubber, 2, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(221, 956, sprAmRubber, 2, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(221, 792, sprAmRubber, 2, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(271, 644, sprAmRubber, 3, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(420, 589, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(584, 588, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(730, 658, sprAmRubber, 1, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(612, 1846, sprAmRubber, 1, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(758, 1896, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(903, 1835, sprAmRubber, 3, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(1051, 1781, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(1210, 1780, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(1356, 1845, sprAmRubber, 1, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(1501, 1891, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(1438, 431, sprAmRubber, 3, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(1589, 378, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(1736, 448, sprAmRubber, 1, 4294967295, nil, nil, nil, lfBouncy) + + ------ WAYPOINT LIST ------ + AddWayPoint(3761, 428) + AddWayPoint(750, 1801) + AddWayPoint(511, 1232) + AddWayPoint(1579, 297) + AddWayPoint(2007, 1618) + AddWayPoint(3642, 1601) + + ------ AMMO CRATE LIST ------ + tempG = SpawnAmmoCrate(397, 1295, amSineGun) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents","amSineGun") + tempG = SpawnAmmoCrate(461, 1295, amSineGun) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents","amSineGun") + tempG = SpawnAmmoCrate(555, 1295, amSineGun) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents","amSineGun") + tempG = SpawnAmmoCrate(621, 1295, amSineGun) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents","amSineGun") + tempG = SpawnAmmoCrate(759, 1867, amSineGun) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents","amSineGun") + tempG = SpawnAmmoCrate(1504, 1862, amSineGun) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents","amSineGun") + tempG = SpawnAmmoCrate(2521, 528, amSineGun) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents","amSineGun") + tempG = SpawnAmmoCrate(3639, 474, amSineGun) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents","amSineGun") + tempG = SpawnAmmoCrate(3078, 809, amSineGun) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents","amSineGun") + tempG = SpawnAmmoCrate(1752, 1192, amSineGun) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents","amSineGun") + tempG = SpawnAmmoCrate(2349, 1183, amSineGun) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents","amSineGun") + tempG = SpawnAmmoCrate(1582, 349, amSineGun) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents","amSineGun") + tempG = SpawnAmmoCrate(3560, 1647, amSineGun) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents","amSineGun") + tempG = SpawnAmmoCrate(3711, 1644, amSineGun) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents","amSineGun") + tempG = SpawnAmmoCrate(433, 560, amSineGun) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents","amSineGun") + tempG = SpawnAmmoCrate(568, 559, amSineGun) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents","amSineGun") + tempG = SpawnAmmoCrate(1935, 1677, amSineGun) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents","amSineGun") + tempG = SpawnAmmoCrate(2084, 1673, amSineGun) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents","amSineGun") + tempG = SpawnAmmoCrate(1018, 1752, amSineGun) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents","amSineGun") + tempG = SpawnAmmoCrate(1086, 1752, amSineGun) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents","amSineGun") + tempG = SpawnAmmoCrate(1176, 1751, amSineGun) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents","amSineGun") + tempG = SpawnAmmoCrate(1238, 1751, amSineGun) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents","amSineGun") + tempG = SpawnAmmoCrate(2009, 1668, amSineGun) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents","amSineGun") + tempG = SpawnAmmoCrate(3641, 1639, amSineGun) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents","amSineGun") + tempG = SpawnAmmoCrate(3580, 469, amSineGun) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents","amSineGun") + tempG = SpawnAmmoCrate(3700, 467, amSineGun) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents","amSineGun") + tempG = SpawnAmmoCrate(2458, 523, amSineGun) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents","amSineGun") + tempG = SpawnAmmoCrate(2595, 521, amSineGun) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents","amSineGun") + + + elseif mID == 6 then + --incomplete challenge, still working on this map + + ------ GIRDER LIST ------ + LoadSprite(419, 298, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(348, 387, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(521, 359, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(459, 385, sprAmGirder, 3, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(570, 387, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(601, 298, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(348, 547, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(570, 547, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(348, 707, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(570, 707, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(397, 466, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(458, 491, sprAmGirder, 1, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(521, 592, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(458, 620, sprAmGirder, 3, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(397, 713, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(459, 740, sprAmGirder, 1, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(348, 867, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(570, 866, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(641, 1038, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(800, 1038, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(959, 1038, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(482, 1038, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(323, 1038, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(163, 1038, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(48, 1038, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(813, 1126, sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(989, 1127, sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(989, 1288, sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(989, 1449, sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(813, 1287, sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(813, 1448, sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(900, 1214, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(989, 1570, sprAmGirder, 2, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(813, 1569, sprAmGirder, 2, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(813, 1690, sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(521, 844, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(457, 870, sprAmGirder, 3, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(392, 941, sprAmGirder, 1, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(813, 1851, sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(813, 1972, sprAmGirder, 2, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(989, 1690, sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(1044, 1817, sprAmGirder, 5, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(901, 1979, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1002, 2005, sprAmGirder, 1, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1176, 1873, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(1333, 1873, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(1491, 1873, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(1649, 1873, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(1808, 1873, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(1898, 1800, sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(1942, 1798, sprAmGirder, 3, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2010, 1798, sprAmGirder, 1, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2054, 1804, sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(2054, 1925, sprAmGirder, 2, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(1898, 1639, sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(2054, 1643, sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(2125, 1553, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(2197, 1464, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2126, 1374, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(1965, 1374, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(1804, 1374, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(1733, 1464, sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(1823, 1547, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(2023, 1976, sprAmGirder, 0, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(1961, 2003, sprAmGirder, 3, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(2216, 1464, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2234, 1464, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2252, 1464, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2270, 1464, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2245, 1553, sprAmGirder, 0, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(2246, 1374, sprAmGirder, 0, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(2351, 1310, sprAmGirder, 7, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(2350, 1490, sprAmGirder, 7, 2516582650, nil, nil, nil, lfIndestructible) + + ------ RUBBER BAND LIST ------ + LoadSprite(210, 958, sprAmRubber, 1, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(98, 844, sprAmRubber, 1, 4294967295, nil, nil, nil, lfBouncy) + + ------ LAND SPRITE LIST ------ + + ------ WAYPOINT LIST ------ + AddWayPoint(438, 278) + AddWayPoint(1870, 1354) + AddWayPoint(892, 1100) + + ------ HEALTH CRATE LIST ------ + + ------ AMMO CRATE LIST ------ + tempG = SpawnAmmoCrate(1943, 1978, amBazooka) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents", "amBazooka") + tempG = SpawnAmmoCrate(2002, 1952, amSineGun) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents", "amSineGun") + tempG = SpawnAmmoCrate(2002, 1890, amSineGun) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents", "amSineGun") + tempG = SpawnAmmoCrate(2002, 1921, amSineGun) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents", "amSineGun") + tempG = SpawnAmmoCrate(1998, 1859, amSineGun) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents", "amSineGun") + + ------ UTILITY CRATE LIST ------ + tempG = SpawnUtilityCrate(368, 274, amPickHammer) + setGearValue(tempG,"caseType", "util") + setGearValue(tempG,"contents", "amPickHammer") + tempG = SpawnUtilityCrate(526, 568, amExtraTime) + setGearValue(tempG,"caseType", "util") + setGearValue(tempG,"contents", "amExtraTime") + tempG = SpawnUtilityCrate(474, 1014, amExtraTime) + setGearValue(tempG,"caseType", "util") + setGearValue(tempG,"contents", "amExtraTime") + tempG = SpawnUtilityCrate(906, 1955, amRope) + setGearValue(tempG,"caseType", "util") + setGearValue(tempG,"contents", "amRope") + tempG = SpawnUtilityCrate(2127, 1529, amBlowTorch) + setGearValue(tempG,"caseType", "util") + setGearValue(tempG,"contents", "amBlowTorch") + + ------ BARREL LIST ------ + SetHealth(AddGear(1860, 1523, gtExplosives, 0, 0, 0, 0), 1) + SetHealth(AddGear(1817, 1523, gtExplosives, 0, 0, 0, 0), 1) + SetHealth(AddGear(1836, 1493, gtExplosives, 0, 0, 0, 0), 1) + SetHealth(AddGear(1769, 1523, gtExplosives, 0, 0, 0, 0), 1) + SetHealth(AddGear(1792, 1494, gtExplosives, 0, 0, 0, 0), 1) + + ------ MINE LIST ------ + SetTimer(AddGear(318, 1028, gtMine, 0, 0, 0, 0), 1) + + ------ STICKY MINE LIST ------ + tempG = AddGear(1767, 1506, gtSMine, 0, 0, 0, 0) + tempG = AddGear(1792, 1477, gtSMine, 0, 0, 0, 0) + tempG = AddGear(1813, 1506, gtSMine, 0, 0, 0, 0) + tempG = AddGear(1837, 1476, gtSMine, 0, 0, 0, 0) + tempG = AddGear(1858, 1506, gtSMine, 0, 0, 0, 0) + tempG = AddGear(1882, 1537, gtSMine, 0, 0, 0, 0) + tempG = AddGear(1748, 1537, gtSMine, 0, 0, 0, 0) + + ------ AIR MINE LIST ------ + SetTimer(AddGear(837, 1570, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(835, 1361, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(836, 1425, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(833, 1495, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(967, 1566, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(970, 1354, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(967, 1422, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(968, 1493, gtAirMine, 0, 0, 0, 0), 1) + + --[[------ GIRDER LIST ------ + LoadSprite(419, 298, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(348, 387, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(521, 359, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(459, 385, sprAmGirder, 3, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(570, 387, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(601, 298, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(348, 547, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(570, 547, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(348, 707, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(570, 707, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(397, 466, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(458, 491, sprAmGirder, 1, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(521, 592, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(458, 620, sprAmGirder, 3, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(397, 713, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(459, 740, sprAmGirder, 1, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(348, 867, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(570, 866, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(641, 1038, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(800, 1038, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(959, 1038, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(482, 1038, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(323, 1038, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(163, 1038, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(48, 1038, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(813, 1126, sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(989, 1127, sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(989, 1288, sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(989, 1449, sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(813, 1287, sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(813, 1448, sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(900, 1214, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(989, 1570, sprAmGirder, 2, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(813, 1569, sprAmGirder, 2, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(813, 1690, sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(521, 844, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(457, 870, sprAmGirder, 3, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(392, 941, sprAmGirder, 1, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(813, 1851, sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(813, 1972, sprAmGirder, 2, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(989, 1690, sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(1044, 1817, sprAmGirder, 5, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(901, 1979, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1002, 2005, sprAmGirder, 1, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1176, 1873, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(1333, 1873, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(1491, 1873, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(1625, 1815, sprAmGirder, 7, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(1680, 1688, sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(1669, 1980, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1762, 1929, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1811, 1853, sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(1811, 1692, sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(1708, 1735, sprAmGirder, 3, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1776, 1734, sprAmGirder, 1, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1680, 1527, sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(1811, 1532, sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(1608, 1437, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(1883, 1443, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(1955, 1354, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1883, 1264, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1723, 1264, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1562, 1264, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1519, 1354, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + + ------ RUBBER BAND LIST ------ + LoadSprite(210, 958, sprAmRubber, 1, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(98, 844, sprAmRubber, 1, 4294967295, nil, nil, nil, lfBouncy) + + ------ WAYPOINT LIST ------ + AddWayPoint(438, 278) + AddWayPoint(1870, 1354) + AddWayPoint(892, 1119) + + ------ AMMO CRATE LIST ------ + tempG = SpawnAmmoCrate(1740, 1905, amBazooka) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents", "amBazooka") + tempG = SpawnAmmoCrate(1780, 1905, amSineGun) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents", "amSineGun") + tempG = SpawnAmmoCrate(1782, 1874, amSineGun) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents", "amSineGun") + tempG = SpawnAmmoCrate(1782, 1843, amSineGun) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents", "amSineGun") + + ------ UTILITY CRATE LIST ------ + tempG = SpawnUtilityCrate(368, 274, amPickHammer) + setGearValue(tempG,"caseType", "util") + setGearValue(tempG,"contents", "amPickHammer") + tempG = SpawnUtilityCrate(526, 568, amExtraTime) + setGearValue(tempG,"caseType", "util") + setGearValue(tempG,"contents", "amExtraTime") + tempG = SpawnUtilityCrate(474, 1014, amExtraTime) + setGearValue(tempG,"caseType", "util") + setGearValue(tempG,"contents", "amExtraTime") + tempG = SpawnUtilityCrate(906, 1955, amRope) + setGearValue(tempG,"caseType", "util") + setGearValue(tempG,"contents", "amRope") + + ------ STICKY MINE LIST ------ + tempG = AddGear(341, 893, gtSMine, 0, 0, 0, 0) + tempG = AddGear(341, 845, gtSMine, 0, 0, 0, 0) + tempG = AddGear(340, 794, gtSMine, 0, 0, 0, 0) + tempG = AddGear(340, 747, gtSMine, 0, 0, 0, 0) + tempG = AddGear(340, 694, gtSMine, 0, 0, 0, 0) + tempG = AddGear(340, 642, gtSMine, 0, 0, 0, 0) + + ------ AIR MINE LIST ------ + SetTimer(AddGear(837, 1570, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(835, 1361, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(836, 1425, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(833, 1495, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(967, 1566, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(970, 1354, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(967, 1422, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(968, 1493, gtAirMine, 0, 0, 0, 0), 1)]] + + elseif mID == 7 then + --Bouncy UFO MAP + -- should be played with infinite fuel + + ufoFuel = 2000 + ------ GIRDER LIST ------ + LoadSprite(3699, 436, sprAmGirder, 0, 16448250, nil, nil, nil, lfIce) + LoadSprite(934, 806, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(934, 969, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1233, 1342, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1377, 1403, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1497, 1376, sprAmGirder, 3, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2816, 1284, sprAmGirder, 7, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(2698, 1401, sprAmGirder, 7, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(2640, 1552, sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(2640, 1718, sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(2641, 1881, sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(2643, 2007, sprAmGirder, 2, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(3823, 363, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(233, 596, sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(288, 446, sprAmGirder, 7, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(79, 642, sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(80, 479, sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(140, 335, sprAmGirder, 7, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(281, 268, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(343, 334, sprAmGirder, 2, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(57, 747, sprAmGirder, 3, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(32, 852, sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(33, 1015, sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(33, 1179, sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(34, 1342, sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(1346, 1939, sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(1347, 1774, sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(1294, 1636, sprAmGirder, 5, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(1180, 1522, sprAmGirder, 5, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(1067, 1410, sprAmGirder, 5, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(931, 1357, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(772, 1358, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(96, 1303, sprAmGirder, 5, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(236, 1362, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(396, 1363, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(520, 1364, sprAmGirder, 0, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(696, 1450, sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(556, 1454, sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(489, 1598, sprAmGirder, 7, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(697, 1574, sprAmGirder, 2, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(639, 1681, sprAmGirder, 7, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(520, 1798, sprAmGirder, 7, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(369, 1715, sprAmGirder, 7, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(243, 1716, sprAmGirder, 5, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(128, 1735, sprAmGirder, 7, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(133, 1870, sprAmGirder, 5, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(251, 1987, sprAmGirder, 5, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(402, 1915, sprAmGirder, 7, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(276, 1938, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(95, 140, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(257, 140, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(419, 140, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(581, 140, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(742, 140, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(903, 140, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(1064, 141, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(1157, 90, sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + + ------ RUBBER BAND LIST ------ + LoadSprite(3433, 237, sprAmRubber, 3, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(3581, 185, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(3741, 182, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(3879, 257, sprAmRubber, 1, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(3921, 411, sprAmRubber, 2, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(3844, 555, sprAmRubber, 3, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(3692, 615, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(3529, 618, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(3381, 555, sprAmRubber, 1, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(3282, 289, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(3223, 514, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(3111, 289, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(3058, 516, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(2947, 287, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(2889, 515, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(2785, 288, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(2788, 578, sprAmRubber, 2, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(2790, 741, sprAmRubber, 2, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(2862, 884, sprAmRubber, 1, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(2749, 1073, sprAmRubber, 1, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(2865, 1186, sprAmRubber, 1, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(2979, 990, sprAmRubber, 1, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(3123, 1036, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(3188, 934, sprAmRubber, 2, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(3010, 1234, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(3175, 1230, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(3339, 1226, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(3345, 949, sprAmRubber, 2, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(3405, 804, sprAmRubber, 3, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(3531, 702, sprAmRubber, 3, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(3444, 1007, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(3499, 1221, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(3604, 1002, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(3755, 1038, sprAmRubber, 1, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(3802, 1186, sprAmRubber, 2, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(3741, 1342, sprAmRubber, 3, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(3626, 1456, sprAmRubber, 3, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(3510, 1314, sprAmRubber, 3, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(3392, 1435, sprAmRubber, 3, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(3506, 1577, sprAmRubber, 3, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(2637, 348, sprAmRubber, 3, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(2583, 496, sprAmRubber, 2, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(2633, 952, sprAmRubber, 1, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(2573, 803, sprAmRubber, 2, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(2474, 556, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(2468, 742, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(2335, 476, sprAmRubber, 1, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(2214, 358, sprAmRubber, 1, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(2322, 812, sprAmRubber, 3, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(2202, 936, sprAmRubber, 3, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(2060, 305, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(1898, 304, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(1736, 304, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(2085, 1049, sprAmRubber, 3, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(1966, 1161, sprAmRubber, 3, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(1818, 1209, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(1657, 1212, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(1947, 685, sprAmRubber, 3, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(1801, 735, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(1659, 677, sprAmRubber, 1, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(1491, 902, sprAmRubber, 3, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(1346, 955, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(1210, 881, sprAmRubber, 1, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(1576, 305, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(1414, 304, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(1253, 302, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(1108, 374, sprAmRubber, 3, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(991, 491, sprAmRubber, 3, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(1557, 1273, sprAmRubber, 2, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(938, 639, sprAmRubber, 2, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(999, 1117, sprAmRubber, 1, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(847, 1079, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(831, 702, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(667, 702, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(687, 1084, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(1115, 1230, sprAmRubber, 1, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(566, 764, sprAmRubber, 2, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(525, 1083, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(422, 1024, sprAmRubber, 2, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(464, 703, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(302, 704, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(297, 795, sprAmRubber, 2, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(316, 1089, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(1559, 1436, sprAmRubber, 2, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(1560, 1598, sprAmRubber, 2, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(1560, 1759, sprAmRubber, 2, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(1561, 1920, sprAmRubber, 2, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(1620, 2022, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(3388, 1688, sprAmRubber, 3, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(3276, 1546, sprAmRubber, 3, 4294967295, nil, nil, nil, lfBouncy) + + ------ WAYPOINT LIST ------ + AddWayPoint(3820, 342) + AddWayPoint(3343, 1612) + AddWayPoint(272, 351) + AddWayPoint(159, 1774) + AddWayPoint(2248, 1573) + AddWayPoint(1379, 1192) + + ------ AMMO CRATE LIST ------ + tempG = SpawnAmmoCrate(1757, 706, amBazooka) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents", "amBazooka") + tempG = SpawnAmmoCrate(1838, 706, amBazooka) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents", "amBazooka") + tempG = SpawnAmmoCrate(1319, 926, amBazooka) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents", "amBazooka") + tempG = SpawnAmmoCrate(1389, 926, amBazooka) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents", "amBazooka") + tempG = SpawnAmmoCrate(3184, 839, amBazooka) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents", "amBazooka") + tempG = SpawnAmmoCrate(3185, 808, amBazooka) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents", "amBazooka") + + ------ UTILITY CRATE LIST ------ + tempG = SpawnUtilityCrate(3677, 412, amJetpack) + setGearValue(tempG,"caseType", "util") + setGearValue(tempG,"contents", "amJetpack") + tempG = SpawnUtilityCrate(3079, 1007, amExtraTime) + setGearValue(tempG,"caseType", "util") + setGearValue(tempG,"contents", "amExtraTime") + tempG = SpawnUtilityCrate(3138, 1007, amExtraTime) + setGearValue(tempG,"caseType", "util") + setGearValue(tempG,"contents", "amExtraTime") + tempG = SpawnUtilityCrate(420, 929, amExtraTime) + setGearValue(tempG,"caseType", "util") + setGearValue(tempG,"contents", "amExtraTime") + + ------ BARREL LIST ------ + + ------ MINE LIST ------ + SetTimer(AddGear(481, 1603, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(485, 1835, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(325, 1759, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(244, 1941, gtMine, 0, 0, 0, 0), 1) + + ------ STICKY MINE LIST ------ + tempG = AddGear(226, 270, gtSMine, 0, 0, 0, 0) + tempG = AddGear(264, 269, gtSMine, 0, 0, 0, 0) + tempG = AddGear(309, 268, gtSMine, 0, 0, 0, 0) + tempG = AddGear(340, 268, gtSMine, 0, 0, 0, 0) + tempG = AddGear(175, 296, gtSMine, 0, 0, 0, 0) + tempG = AddGear(148, 325, gtSMine, 0, 0, 0, 0) + tempG = AddGear(121, 356, gtSMine, 0, 0, 0, 0) + tempG = AddGear(100, 381, gtSMine, 0, 0, 0, 0) + tempG = AddGear(202, 1352, gtSMine, 0, 0, 0, 0) + tempG = AddGear(280, 1352, gtSMine, 0, 0, 0, 0) + tempG = AddGear(359, 1353, gtSMine, 0, 0, 0, 0) + tempG = AddGear(439, 1353, gtSMine, 0, 0, 0, 0) + tempG = AddGear(531, 1354, gtSMine, 0, 0, 0, 0) + tempG = AddGear(744, 1348, gtSMine, 0, 0, 0, 0) + tempG = AddGear(833, 1348, gtSMine, 0, 0, 0, 0) + tempG = AddGear(931, 1347, gtSMine, 0, 0, 0, 0) + tempG = AddGear(990, 1347, gtSMine, 0, 0, 0, 0) + + ------ AIR MINE LIST ------ + SetTimer(AddGear(3195, 1621, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3155, 1655, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3112, 1691, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3078, 1730, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3044, 1764, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3011, 1805, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2998, 1843, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2986, 1886, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2978, 1937, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(733, 1753, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3345, 1773, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3332, 1806, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3317, 1840, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3302, 1873, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3262, 1902, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3237, 1937, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3225, 1978, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1272, 1839, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(863, 1776, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(712, 1902, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2361, 1922, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2360, 1877, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2362, 1825, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2364, 1772, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2364, 1723, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2362, 1670, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2395, 1645, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2426, 1600, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2434, 1543, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2435, 1480, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2406, 1431, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2362, 1392, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2313, 1368, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2249, 1359, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2202, 1386, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2151, 1434, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1039, 1861, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2154, 1946, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2156, 1902, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2155, 1840, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2152, 1777, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2161, 1724, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2128, 1681, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2094, 1442, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2036, 1448, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1976, 1450, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1924, 1454, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2082, 1685, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2046, 1692, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1999, 1696, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1961, 1701, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1939, 1737, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1925, 1783, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1916, 1821, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1904, 1864, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1888, 1913, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1870, 1961, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1100, 1660, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1876, 1486, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1826, 1533, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1799, 1580, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1784, 1637, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1765, 1681, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1755, 1718, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1726, 1779, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1718, 1836, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1705, 1885, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1696, 1934, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1685, 1975, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(859, 1569, gtAirMine, 0, 0, 0, 0), 1) + + +--IF NEEDED, YOU CAN PASTE THIS DATA INTO HWMAP CONVERTER +--[[ + + 3699 436 116 + 934 806 106 + 934 969 106 + 1233 1342 105 + 1377 1403 104 + 1497 1376 103 + 2816 1284 115 + 2698 1401 115 + 2640 1552 114 + 2640 1718 114 + 2641 1881 114 + 2643 2007 110 + 3823 363 100 + 233 596 114 + 288 446 115 + 79 642 114 + 80 479 114 + 140 335 115 + 281 268 112 + 343 334 110 + 57 747 111 + 32 852 114 + 33 1015 114 + 33 1179 114 + 34 1342 114 + 1346 1939 114 + 1347 1774 114 + 1294 1636 113 + 1180 1522 113 + 1067 1410 113 + 931 1357 112 + 772 1358 112 + 96 1303 113 + 236 1362 112 + 396 1363 112 + 520 1364 108 + 696 1450 114 + 556 1454 114 + 489 1598 115 + 697 1574 110 + 639 1681 115 + 520 1798 115 + 369 1715 115 + 243 1716 113 + 128 1735 115 + 133 1870 113 + 251 1987 113 + 402 1915 115 + 276 1938 112 + 95 140 112 + 257 140 112 + 419 140 112 + 581 140 112 + 742 140 112 + 903 140 112 + 1064 141 112 + 1157 90 114 + 3433 237 127 + 3581 185 124 + 3741 182 124 + 3879 257 125 + 3921 411 126 + 3844 555 127 + 3692 615 124 + 3529 618 124 + 3381 555 125 + 3282 289 124 + 3223 514 124 + 3111 289 124 + 3058 516 124 + 2947 287 124 + 2889 515 124 + 2785 288 124 + 2788 578 126 + 2790 741 126 + 2862 884 125 + 2749 1073 125 + 2865 1186 125 + 2979 990 125 + 3123 1036 124 + 3188 934 126 + 3010 1234 124 + 3175 1230 124 + 3339 1226 124 + 3345 949 126 + 3405 804 127 + 3531 702 127 + 3444 1007 124 + 3499 1221 124 + 3604 1002 124 + 3755 1038 125 + 3802 1186 126 + 3741 1342 127 + 3626 1456 127 + 3510 1314 127 + 3392 1435 127 + 3506 1577 127 + 2637 348 127 + 2583 496 126 + 2633 952 125 + 2573 803 126 + 2474 556 124 + 2468 742 124 + 2335 476 125 + 2214 358 125 + 2322 812 127 + 2202 936 127 + 2060 305 124 + 1898 304 124 + 1736 304 124 + 2085 1049 127 + 1966 1161 127 + 1818 1209 124 + 1657 1212 124 + 1947 685 127 + 1801 735 124 + 1659 677 125 + 1491 902 127 + 1346 955 124 + 1210 881 125 + 1576 305 124 + 1414 304 124 + 1253 302 124 + 1108 374 127 + 991 491 127 + 1557 1273 126 + 938 639 126 + 999 1117 125 + 847 1079 124 + 831 702 124 + 667 702 124 + 687 1084 124 + 1115 1230 125 + 566 764 126 + 525 1083 124 + 422 1024 126 + 464 703 124 + 302 704 124 + 297 795 126 + 316 1089 124 + 1559 1436 126 + 1560 1598 126 + 1560 1759 126 + 1561 1920 126 + 1620 2022 124 + 3388 1688 127 + 3276 1546 127 + 3820 342 0 + 3343 1612 0 + 272 351 0 + 159 1774 0 + 2248 1573 0 + 1379 1192 0 + 1757 706 20 + 1838 706 20 + 1319 926 20 + 1389 926 20 + 3184 839 20 + 3185 808 20 + 3677 412 67 + 3079 1007 73 + 3138 1007 73 + 420 929 73 + 481 1603 1 + 485 1835 1 + 325 1759 1 + 244 1941 1 + 226 270 7 + 264 269 7 + 309 268 7 + 340 268 7 + 175 296 7 + 148 325 7 + 121 356 7 + 100 381 7 + 202 1352 7 + 280 1352 7 + 359 1353 7 + 439 1353 7 + 531 1354 7 + 744 1348 7 + 833 1348 7 + 931 1347 7 + 990 1347 7 + 3195 1621 8 + 3155 1655 8 + 3112 1691 8 + 3078 1730 8 + 3044 1764 8 + 3011 1805 8 + 2998 1843 8 + 2986 1886 8 + 2978 1937 8 + 733 1753 8 + 3345 1773 8 + 3332 1806 8 + 3317 1840 8 + 3302 1873 8 + 3262 1902 8 + 3237 1937 8 + 3225 1978 8 + 1272 1839 8 + 863 1776 8 + 712 1902 8 + 2361 1922 8 + 2360 1877 8 + 2362 1825 8 + 2364 1772 8 + 2364 1723 8 + 2362 1670 8 + 2395 1645 8 + 2426 1600 8 + 2434 1543 8 + 2435 1480 8 + 2406 1431 8 + 2362 1392 8 + 2313 1368 8 + 2249 1359 8 + 2202 1386 8 + 2151 1434 8 + 1039 1861 8 + 2154 1946 8 + 2156 1902 8 + 2155 1840 8 + 2152 1777 8 + 2161 1724 8 + 2128 1681 8 + 2094 1442 8 + 2036 1448 8 + 1976 1450 8 + 1924 1454 8 + 2082 1685 8 + 2046 1692 8 + 1999 1696 8 + 1961 1701 8 + 1939 1737 8 + 1925 1783 8 + 1916 1821 8 + 1904 1864 8 + 1888 1913 8 + 1870 1961 8 + 1100 1660 8 + 1876 1486 8 + 1826 1533 8 + 1799 1580 8 + 1784 1637 8 + 1765 1681 8 + 1755 1718 8 + 1726 1779 8 + 1718 1836 8 + 1705 1885 8 + 1696 1934 8 + 1685 1975 8 + 859 1569 8]] + + else + + -- the first test epic multi map + -- default to this crazy shit + ---------- GIRDER LIST--------- + LoadSprite(430, 1871, sprAmGirder, 2, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1249, 1914, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1394, 1849, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1522, 1848, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1578, 1959, sprAmGirder, 2, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1545, 2011, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(430, 1749, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(430, 1589, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(358, 1499, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(198, 1499, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(72, 1571, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(339, 1618, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(520, 1499, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(680, 1499, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(839, 1499, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1000, 1499, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1404, 1730, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1288, 1613, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1200, 1529, sprAmGirder, 1, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1125, 1495, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1667, 2011, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1812, 1951, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1964, 2024, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1957, 1892, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2103, 1949, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2242, 2017, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2404, 2017, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2548, 1955, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2635, 1871, sprAmGirder, 3, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2749, 1836, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2751, 1999, sprAmGirder, 2, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2749, 1947, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2865, 1870, sprAmGirder, 1, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2954, 1954, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3061, 2017, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3137, 1984, sprAmGirder, 3, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3169, 1864, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3169, 1702, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3170, 1540, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3170, 1418, sprAmGirder, 2, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3138, 1339, sprAmGirder, 1, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3107, 1260, sprAmGirder, 2, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3153, 1194, sprAmGirder, 3, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3230, 1163, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3305, 1201, sprAmGirder, 1, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3334, 1277, sprAmGirder, 2, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3227, 1540, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3228, 1419, sprAmGirder, 2, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3334, 1358, sprAmGirder, 2, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3280, 1387, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3227, 1702, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3227, 1864, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3253, 1981, sprAmGirder, 1, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3366, 2017, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3528, 2018, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3689, 2018, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(246, 1262, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(407, 1262, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(568, 1262, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(731, 1262, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(894, 1261, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1056, 1261, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1179, 1262, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1288, 1314, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1406, 1433, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1525, 1549, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1642, 1666, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1749, 1728, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1956, 1802, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1956, 1640, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1782, 1638, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1835, 1487, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1942, 1430, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2051, 1486, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2109, 1639, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2177, 1778, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2323, 1840, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(49, 1029, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(499, 1172, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(527, 1054, sprAmGirder, 3, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(604, 1026, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(680, 1056, sprAmGirder, 1, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(719, 1168, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(89, 728, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(251, 728, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(412, 728, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(572, 728, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(733, 728, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(894, 728, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1016, 728, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1067, 799, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1139, 891, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1067, 1171, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1067, 1049, sprAmGirder, 2, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1136, 999, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1005, 854, sprAmGirder, 2, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(972, 803, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(920, 780, sprAmGirder, 2, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(891, 1206, sprAmGirder, 2, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(887, 1150, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3018, 1311, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2871, 1369, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2809, 1523, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2809, 1647, sprAmGirder, 2, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2469, 1777, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2612, 1715, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2809, 1702, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2727, 1694, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + + LoadSprite(3334, 1481, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3334, 1643, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3334, 1804, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3403, 1940, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1120, 944, sprAmGirder, 2, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1163, 945, sprAmGirder, 2, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1141, 781, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(81, 629, sprAmGirder, 1, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(102, 498, sprAmGirder, 3, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(81, 373, sprAmGirder, 1, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(179, 453, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(100, 260, sprAmGirder, 3, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(179, 330, sprAmGirder, 2, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(249, 544, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(410, 545, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(571, 543, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(731, 543, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(891, 544, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1014, 544, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1779, 1321, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1779, 1159, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1779, 997, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1779, 836, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1722, 684, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1137, 545, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1298, 545, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1460, 546, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1608, 600, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1508, 1005, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(160, 246, sprAmGirder, 1, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1821, 1356, sprAmGirder, 3, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1938, 1323, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2086, 1381, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(4004, 2018, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3934, 1926, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3965, 1835, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(4015, 1763, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(4015, 1603, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(4015, 1442, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(4015, 1280, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(4014, 1118, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(4014, 956, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(4014, 793, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(4014, 632, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(4014, 469, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3981, 351, sprAmGirder, 1, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3985, 204, sprAmGirder, 3, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(4045, 156, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3667, 344, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(4016, 1925, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3998, 1926, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3980, 1925, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3957, 1926, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3843, 1832, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3682, 1832, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3561, 1833, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3484, 1796, sprAmGirder, 1, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3455, 1675, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3455, 1513, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3455, 1351, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1601, 476, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1706, 421, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1888, 366, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + + LoadSprite(3997, 1743, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3979, 1742, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3962, 1741, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3943, 1741, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2199, 393, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2304, 337, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2409, 392, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2470, 502, sprAmGirder, 2, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2412, 606, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2308, 673, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2202, 612, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2138, 507, sprAmGirder, 2, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2739, 378, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2847, 322, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2953, 378, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2680, 489, sprAmGirder, 2, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3012, 489, sprAmGirder, 2, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2736, 594, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2841, 657, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2949, 594, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2448, 837, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2594, 779, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2739, 836, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2390, 950, sprAmGirder, 2, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2789, 950, sprAmGirder, 2, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2593, 904, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2727, 1056, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2452, 1058, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2510, 1215, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2663, 1208, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2510, 1378, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2664, 1369, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(300, 275, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(439, 274, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(628, 273, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(811, 271, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(737, 373, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(934, 440, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1075, 439, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1209, 438, sprAmGirder, 0, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1383, 439, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3547, 344, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3584, 254, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3508, 132, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3335, 1117, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3335, 956, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3335, 795, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3335, 634, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3335, 513, sprAmGirder, 2, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3401, 404, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3455, 1190, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3455, 1029, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3455, 868, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3455, 705, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3455, 582, sprAmGirder, 2, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3485, 503, sprAmGirder, 3, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3601, 475, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3719, 444, sprAmGirder, 3, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3094, 828, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(2064, 947, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1826, 512, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + + LoadSprite(3420, 49, sprAmGirder, 1, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(410, 682, sprAmGirder, 3, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(528, 653, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(688, 653, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(805, 684, sprAmGirder, 1, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(528, 672, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(688, 672, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(500, 696, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(701, 696, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + + ------ WAYPOINT LIST ------ + AddWayPoint(383, 1595) + AddWayPoint(605, 1157) + AddWayPoint(2296, 517) + AddWayPoint(2841, 497) + AddWayPoint(3209, 1286) + AddWayPoint(3708, 1945) + AddWayPoint(4075, 1887) + + ------ AMMO CRATE LIST ------ + tempG = SpawnAmmoCrate(889, 1126, amBaseballBat) + tempG = SpawnAmmoCrate(1211, 975, amSineGun) + tempG = SpawnAmmoCrate(3619, 451, amFirePunch) + + ------ UTILITY CRATE LIST ------ + tempG = SpawnUtilityCrate(304, 1594, amRope) + tempG = SpawnUtilityCrate(1538, 1987, amJetpack) + tempG = SpawnUtilityCrate(1958, 2000, amExtraTime) + tempG = SpawnUtilityCrate(2744, 1923, amJetpack) + tempG = SpawnUtilityCrate(3283, 1363, amParachute) + tempG = SpawnUtilityCrate(2749, 1812, amRope) + tempG = SpawnUtilityCrate(970, 779, amJetpack) + + tempG = SpawnUtilityCrate(3284, 1332, amExtraTime) + tempG = SpawnUtilityCrate(1082, 975, amBlowTorch) + tempG = SpawnUtilityCrate(1547, 981, amJetpack) + tempG = SpawnUtilityCrate(1707, 397, amRope) + tempG = SpawnUtilityCrate(2309, 649, amExtraTime) + tempG = SpawnUtilityCrate(1116, 867, amExtraTime) + + ------ AMMO CRATE LIST ------ + tempG = SpawnAmmoCrate(2559, 880, amBazooka) + tempG = SpawnAmmoCrate(2630, 880, amBazooka) + tempG = SpawnAmmoCrate(1951, 1406, amGrenade) + + ------ UTILITY CRATE LIST ------ + tempG = SpawnUtilityCrate(3536, 320, amBlowTorch) + tempG = SpawnUtilityCrate(3582, 1994, amJetpack) + tempG = SpawnUtilityCrate(682, 349, amExtraTime) + tempG = SpawnUtilityCrate(2842, 633, amExtraTime) + + ------ BARREL LIST ------ + SetHealth(AddGear(506, 1034, gtExplosives, 0, 0, 0, 0), 1) + SetHealth(AddGear(556, 1002, gtExplosives, 0, 0, 0, 0), 1) + SetHealth(AddGear(615, 1002, gtExplosives, 0, 0, 0, 0), 1) + SetHealth(AddGear(676, 1010, gtExplosives, 0, 0, 0, 0), 1) + SetHealth(AddGear(716, 1050, gtExplosives, 0, 0, 0, 0), 1) + SetHealth(AddGear(67, 1005, gtExplosives, 0, 0, 0, 0), 50) + + ------ MINE LIST ------ + SetTimer(AddGear(1187, 1908, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1235, 1908, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1283, 1908, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1323, 1908, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1361, 1875, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1399, 1837, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1426, 1810, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(234, 1493, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(308, 1493, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(377, 1493, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(460, 1493, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(550, 1493, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(633, 1493, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(722, 1493, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(795, 1493, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(881, 1493, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(975, 1493, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1060, 1493, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1127, 1489, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1207, 1526, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1261, 1580, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1315, 1634, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1372, 1692, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1416, 1736, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1465, 1792, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1518, 1838, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1566, 1886, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1623, 2005, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1686, 2005, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1799, 1957, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1839, 1917, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1902, 1886, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1933, 1886, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2076, 1916, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2138, 1978, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2221, 2011, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2305, 2011, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2390, 2011, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2578, 1918, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2494, 2002, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1758, 1728, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1683, 1707, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1635, 1657, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1572, 1596, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1517, 1542, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1447, 1477, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1401, 1432, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1338, 1365, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1290, 1310, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1230, 1266, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1149, 1260, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1054, 1257, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(978, 1257, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(895, 1258, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(819, 1257, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(753, 1258, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(671, 1260, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(599, 1260, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(526, 1259, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(466, 1259, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(408, 1261, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(336, 1260, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(290, 1259, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(218, 1260, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1777, 1263, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1776, 1198, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1778, 1141, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1781, 1078, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1778, 1027, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1778, 985, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1779, 925, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1777, 882, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(4052, 2010, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3965, 226, gtMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3962, 326, gtMine, 0, 0, 0, 0), 1) + + ------ STICKY MINE LIST ------ + tempG = AddGear(3170, 1907, gtSMine, 0, 0, 0, 0) + tempG = AddGear(3170, 1860, gtSMine, 0, 0, 0, 0) + tempG = AddGear(3169, 1809, gtSMine, 0, 0, 0, 0) + tempG = AddGear(3170, 1761, gtSMine, 0, 0, 0, 0) + tempG = AddGear(3170, 1711, gtSMine, 0, 0, 0, 0) + tempG = AddGear(3172, 1668, gtSMine, 0, 0, 0, 0) + tempG = AddGear(3170, 1624, gtSMine, 0, 0, 0, 0) + tempG = AddGear(3169, 1579, gtSMine, 0, 0, 0, 0) + tempG = AddGear(3171, 1526, gtSMine, 0, 0, 0, 0) + tempG = AddGear(3168, 1469, gtSMine, 0, 0, 0, 0) + tempG = AddGear(3171, 1418, gtSMine, 0, 0, 0, 0) + tempG = AddGear(3227, 1416, gtSMine, 0, 0, 0, 0) + tempG = AddGear(3226, 1465, gtSMine, 0, 0, 0, 0) + tempG = AddGear(3225, 1523, gtSMine, 0, 0, 0, 0) + tempG = AddGear(3224, 1576, gtSMine, 0, 0, 0, 0) + tempG = AddGear(3225, 1624, gtSMine, 0, 0, 0, 0) + tempG = AddGear(3228, 1667, gtSMine, 0, 0, 0, 0) + tempG = AddGear(3228, 1707, gtSMine, 0, 0, 0, 0) + tempG = AddGear(3230, 1757, gtSMine, 0, 0, 0, 0) + tempG = AddGear(3228, 1803, gtSMine, 0, 0, 0, 0) + tempG = AddGear(3229, 1856, gtSMine, 0, 0, 0, 0) + tempG = AddGear(3228, 1910, gtSMine, 0, 0, 0, 0) + tempG = AddGear(258, 534, gtSMine, 0, 0, 0, 0) + tempG = AddGear(329, 534, gtSMine, 0, 0, 0, 0) + tempG = AddGear(410, 535, gtSMine, 0, 0, 0, 0) + tempG = AddGear(482, 535, gtSMine, 0, 0, 0, 0) + tempG = AddGear(565, 533, gtSMine, 0, 0, 0, 0) + tempG = AddGear(670, 533, gtSMine, 0, 0, 0, 0) + tempG = AddGear(763, 533, gtSMine, 0, 0, 0, 0) + tempG = AddGear(858, 534, gtSMine, 0, 0, 0, 0) + tempG = AddGear(917, 534, gtSMine, 0, 0, 0, 0) + tempG = AddGear(1012, 534, gtSMine, 0, 0, 0, 0) + tempG = AddGear(1147, 535, gtSMine, 0, 0, 0, 0) + tempG = AddGear(1102, 535, gtSMine, 0, 0, 0, 0) + tempG = AddGear(1220, 535, gtSMine, 0, 0, 0, 0) + tempG = AddGear(1293, 535, gtSMine, 0, 0, 0, 0) + tempG = AddGear(1368, 535, gtSMine, 0, 0, 0, 0) + tempG = AddGear(1440, 536, gtSMine, 0, 0, 0, 0) + tempG = AddGear(223, 534, gtSMine, 0, 0, 0, 0) + tempG = AddGear(814, 534, gtSMine, 0, 0, 0, 0) + tempG = AddGear(3909, 1822, gtSMine, 0, 0, 0, 0) + tempG = AddGear(3867, 1822, gtSMine, 0, 0, 0, 0) + tempG = AddGear(3824, 1822, gtSMine, 0, 0, 0, 0) + tempG = AddGear(3784, 1822, gtSMine, 0, 0, 0, 0) + tempG = AddGear(3732, 1822, gtSMine, 0, 0, 0, 0) + tempG = AddGear(3682, 1822, gtSMine, 0, 0, 0, 0) + tempG = AddGear(3627, 1822, gtSMine, 0, 0, 0, 0) + tempG = AddGear(3557, 1823, gtSMine, 0, 0, 0, 0) + end + + +end + + --[[ + ----------------------------------------------------------------- + -- not really a racing map, just a simple testmap that contains + -- a bunch of different stuff to test HWMAP conversion + --still lacks waypoints + -- currently disabled because it's only really used to test stuff + ------ GIRDER LIST ------ + LoadSprite(366, 540, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(312, 696, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(377, 837, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(513, 485, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(657, 550, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(712, 704, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(655, 848, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(512, 913, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(1044, 530, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(968, 623, sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(1125, 623, sprAmGirder, 6, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(1042, 716, sprAmGirder, 4, 2516582650, nil, nil, nil, lfIndestructible) + LoadSprite(844, 613, sprAmGirder, 4, 16448250, nil, nil, nil, lfIce) + LoadSprite(118, 425, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + + ------ RUBBER BAND LIST ------ + LoadSprite(688, 957, sprAmRubber, 1, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(804, 1070, sprAmRubber, 1, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(921, 1182, sprAmRubber, 1, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(1036, 1299, sprAmRubber, 1, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(1184, 1349, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(1348, 1345, sprAmRubber, 0, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(1490, 1278, sprAmRubber, 3, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(1601, 1161, sprAmRubber, 3, 4294967295, nil, nil, nil, lfBouncy) + LoadSprite(1712, 1044, sprAmRubber, 3, 4294967295, nil, nil, nil, lfBouncy) + + ------ LAND SPRITE LIST ------ + + ------ HEALTH CRATE LIST ------ + SetHealth(SpawnHealthCrate(694, 553), 25) + + ------ AMMO CRATE LIST ------ + tempG = SpawnAmmoCrate(463, 461, amBazooka) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents", "amBazooka") + tempG = SpawnAmmoCrate(579, 461, amWatermelon) + setGearValue(tempG,"caseType", "ammo") + setGearValue(tempG,"contents", "amWatermelon") + + ------ UTILITY CRATE LIST ------ + tempG = SpawnUtilityCrate(367, 500, amBlowTorch) + setGearValue(tempG,"caseType", "util") + setGearValue(tempG,"contents", "amBlowTorch") + tempG = SpawnUtilityCrate(638, 493, amExtraTime) + setGearValue(tempG,"caseType", "util") + setGearValue(tempG,"contents", "amExtraTime") + + ------ BARREL LIST ------ + SetHealth(AddGear(140, 409, gtExplosives, 0, 0, 0, 0), 1) + + ------ MINE LIST ------ + SetTimer(AddGear(1016, 520, gtMine, 0, 0, 0, 0), 3000) + SetTimer(AddGear(1057, 520, gtMine, 0, 0, 0, 0), 3000) + SetTimer(AddGear(1104, 520, gtMine, 0, 0, 0, 0), 3000) + + ------ STICKY MINE LIST ------ + tempG = AddGear(311, 651, gtSMine, 0, 0, 0, 0) + tempG = AddGear(311, 686, gtSMine, 0, 0, 0, 0) + tempG = AddGear(308, 729, gtSMine, 0, 0, 0, 0) + + ------ AIR MINE LIST ------ + SetTimer(AddGear(1023, 600, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1073, 657, gtAirMine, 0, 0, 0, 0), 1) + + ------ TARGET LIST ------ + tempG = AddGear(485, 895, gtTarget, 0, 0, 0, 0) + + ------ CLEAVER LIST ------ + tempG = AddGear(560, 898, gtKnife, 0, 0, 0, 0)]] + + + + + + + --[[ + ------------------------------------------ + -- tiny airmine explosion knock concept test + -- currently won't play nicely with others + -- removed because it is small and boring + ------ GIRDER LIST ------ + LoadSprite(3942, 116, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3999, 270, sprAmGirder, 6, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3925, 407, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3777, 470, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3791, 65, sprAmGirder, 4, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3644, 121, sprAmGirder, 7, 4294967295, nil, nil, nil, lfNormal) + LoadSprite(3629, 413, sprAmGirder, 5, 4294967295, nil, nil, nil, lfNormal) + + ------ AMMO CRATE LIST ------ + tempG = SpawnAmmoCrate(3772, 446, amWatermelon) + tempG = SpawnAmmoCrate(3769, 415, amWatermelon) + tempG = SpawnAmmoCrate(3773, 384, amWatermelon) + tempG = SpawnAmmoCrate(3771, 353, amWatermelon) + tempG = SpawnAmmoCrate(3770, 322, amWatermelon) + tempG = SpawnAmmoCrate(3775, 291, amWatermelon) + tempG = SpawnAmmoCrate(3776, 260, amWatermelon) + tempG = SpawnAmmoCrate(3775, 229, amWatermelon) + tempG = SpawnAmmoCrate(3772, 198, amWatermelon) + tempG = SpawnAmmoCrate(3776, 167, amWatermelon) + + ------ UTILITY CRATE LIST ------ + tempG = SpawnUtilityCrate(3723, 446, amJetpack) + tempG = SpawnUtilityCrate(3725, 415, amJetpack) + tempG = SpawnUtilityCrate(3814, 446, amJetpack) + tempG = SpawnUtilityCrate(3814, 415, amJetpack) + tempG = SpawnUtilityCrate(3815, 384, amJetpack) + tempG = SpawnUtilityCrate(3728, 384, amJetpack) + + ------ AIR MINE LIST ------ + SetTimer(AddGear(3489, 110, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3509, 366, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3399, 114, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3438, 383, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3322, 113, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3369, 384, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3290, 379, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3253, 112, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3178, 111, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3228, 375, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3173, 384, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3115, 118, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3039, 126, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2954, 139, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3121, 404, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2918, 414, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2880, 144, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2815, 146, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2731, 140, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2867, 408, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2802, 394, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2733, 392, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2661, 392, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2672, 147, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2608, 144, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2558, 117, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2495, 86, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2425, 49, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2373, 79, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2313, 104, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2256, 156, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2218, 226, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2205, 318, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2218, 419, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2255, 479, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2290, 522, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2343, 557, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2413, 540, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2500, 514, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2572, 471, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2618, 436, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2926, 478, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2926, 548, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2924, 615, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3126, 472, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3128, 553, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3136, 623, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3139, 683, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2927, 657, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2919, 720, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3132, 746, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2920, 771, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3137, 798, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2926, 820, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3140, 848, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(945, 441, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(900, 477, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(899, 540, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(915, 631, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1013, 616, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(970, 533, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1062, 458, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1060, 537, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1094, 640, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1029, 692, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(928, 718, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(831, 592, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(860, 666, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(823, 493, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1032, 427, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(953, 351, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(845, 375, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1101, 326, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1128, 565, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1126, 446, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1208, 703, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1139, 726, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1024, 777, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(918, 775, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(812, 758, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3171, 887, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3222, 939, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3273, 977, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3330, 1011, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3401, 1051, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2928, 899, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2935, 966, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2959, 1021, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2999, 1077, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3050, 1136, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3108, 1184, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3159, 1221, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3214, 1243, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3289, 1279, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3453, 1087, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3515, 1136, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3566, 1202, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3604, 1275, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3618, 1345, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3608, 1436, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3582, 1505, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3528, 1565, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3456, 1610, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3368, 1651, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3289, 1666, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3205, 1668, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3132, 1672, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3270, 1325, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3192, 1346, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3140, 1346, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3067, 1359, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2997, 1373, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2918, 1391, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2839, 1406, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3078, 1672, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(3019, 1659, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2936, 1667, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(2859, 1675, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(975, 722, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(967, 636, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1078, 687, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(868, 740, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(863, 453, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1010, 494, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1080, 590, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(869, 589, gtAirMine, 0, 0, 0, 0), 1) + SetTimer(AddGear(1013, 569, gtAirMine, 0, 0, 0, 0), 1)]] diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Shaders/CMakeLists.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Shaders/CMakeLists.txt Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,7 @@ +file(GLOB vertshaders *.vs) +file(GLOB fragshaders *.fs) + +install(FILES + ${vertshaders} + ${fragshaders} + DESTINATION ${SHAREPATH}Data/Shaders) diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Shaders/default.fs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Shaders/default.fs Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,15 @@ +uniform sampler2D tex0; +uniform vec4 tint; +uniform bool enableTexture; + +varying vec2 tex; + + +void main() +{ + if(enableTexture){ + gl_FragColor = texture2D(tex0, tex) * tint; + }else{ + gl_FragColor = tint; + } +} diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Shaders/default.vs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Shaders/default.vs Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,16 @@ + + +attribute vec2 vertex; +attribute vec2 texcoord; +attribute vec4 colors; + +varying vec2 tex; + +uniform mat4 mvp; + +void main() +{ + vec4 p = mvp * vec4(vertex, 0.0, 1.0); + gl_Position = p; + tex = texcoord; +} diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Shaders/water.fs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Shaders/water.fs Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,8 @@ + +varying vec4 vcolor; + + +void main() +{ + gl_FragColor = vcolor; +} diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Shaders/water.vs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Shaders/water.vs Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,15 @@ + + +attribute vec2 vertex; +attribute vec4 color; + +varying vec4 vcolor; + +uniform mat4 mvp; + +void main() +{ + vec4 p = mvp * vec4(vertex, 0.0, 1.0); + gl_Position = p; + vcolor = color; +} diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Sounds/voices/Default_ru/Hello.ogg Binary file share/hedgewars/Data/Sounds/voices/Default_ru/Hello.ogg has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Sounds/voices/Default_ru/Hurry.ogg Binary file share/hedgewars/Data/Sounds/voices/Default_ru/Hurry.ogg has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Sounds/voices/Default_ru/Jump1.ogg Binary file share/hedgewars/Data/Sounds/voices/Default_ru/Jump1.ogg has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Sounds/voices/Default_ru/Jump2.ogg Binary file share/hedgewars/Data/Sounds/voices/Default_ru/Jump2.ogg has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Sounds/voices/Default_ru/Jump3.ogg Binary file share/hedgewars/Data/Sounds/voices/Default_ru/Jump3.ogg has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Art/BlueWater.png Binary file share/hedgewars/Data/Themes/Art/BlueWater.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Art/Border.png Binary file share/hedgewars/Data/Themes/Art/Border.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Art/Droplet.png Binary file share/hedgewars/Data/Themes/Art/Droplet.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Art/Girder.png Binary file share/hedgewars/Data/Themes/Art/Girder.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Art/LandBackTex.png Binary file share/hedgewars/Data/Themes/Art/LandBackTex.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Art/Sky.png Binary file share/hedgewars/Data/Themes/Art/Sky.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Art/horizont.png Binary file share/hedgewars/Data/Themes/Art/horizont.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Art/icon.png Binary file share/hedgewars/Data/Themes/Art/icon.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Art/theme.cfg --- a/share/hedgewars/Data/Themes/Art/theme.cfg Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Themes/Art/theme.cfg Tue Nov 10 20:43:13 2015 +0100 @@ -1,5 +1,5 @@ -sky = 7, 13, 40 -border = 13, 17, 22 +sky = 23, 8, 33 +border = 7, 72, 102 water-top = $01, $3b, $66 water-bottom = $01, $3b, $66 water-opacity = $80 diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Bamboo/Border.png Binary file share/hedgewars/Data/Themes/Bamboo/Border.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Bamboo/Chunk.png Binary file share/hedgewars/Data/Themes/Bamboo/Chunk.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Bamboo/Flake.png Binary file share/hedgewars/Data/Themes/Bamboo/Flake.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Bamboo/SkyL.png Binary file share/hedgewars/Data/Themes/Bamboo/SkyL.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Bamboo/horizont.png Binary file share/hedgewars/Data/Themes/Bamboo/horizont.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Bamboo/icon.png Binary file share/hedgewars/Data/Themes/Bamboo/icon.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Bath/Border.png Binary file share/hedgewars/Data/Themes/Bath/Border.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Bath/Bubble.png Binary file share/hedgewars/Data/Themes/Bath/Bubble.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Bath/Chunk.png Binary file share/hedgewars/Data/Themes/Bath/Chunk.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Bath/Flake.png Binary file share/hedgewars/Data/Themes/Bath/Flake.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Bath/Sky.png Binary file share/hedgewars/Data/Themes/Bath/Sky.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Bath/horizont.png Binary file share/hedgewars/Data/Themes/Bath/horizont.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Bath/horizontL.png Binary file share/hedgewars/Data/Themes/Bath/horizontL.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Bath/horizontR.png Binary file share/hedgewars/Data/Themes/Bath/horizontR.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Bath/icon.png Binary file share/hedgewars/Data/Themes/Bath/icon.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Beach/theme.cfg --- a/share/hedgewars/Data/Themes/Beach/theme.cfg Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Themes/Beach/theme.cfg Tue Nov 10 20:43:13 2015 +0100 @@ -15,4 +15,4 @@ spray = SprayObject29, 3 spray = SprayObject36, 2 spray = SprayObject4, 1 -flakes = 20, 1, 99999999, 0, 10 +flakes = 20, 1, 0, 0, 10 diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Blox/Border.png Binary file share/hedgewars/Data/Themes/Blox/Border.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Blox/LandBackTex.png Binary file share/hedgewars/Data/Themes/Blox/LandBackTex.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Blox/LandTex.png Binary file share/hedgewars/Data/Themes/Blox/LandTex.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Blox/horizont.png Binary file share/hedgewars/Data/Themes/Blox/horizont.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Blox/tmp.png Binary file share/hedgewars/Data/Themes/Blox/tmp.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Brick/BlueWater.png Binary file share/hedgewars/Data/Themes/Brick/BlueWater.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Brick/Droplet.png Binary file share/hedgewars/Data/Themes/Brick/Droplet.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Brick/LandBackTex.png Binary file share/hedgewars/Data/Themes/Brick/LandBackTex.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Brick/LandTex.png Binary file share/hedgewars/Data/Themes/Brick/LandTex.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Brick/Sky.png Binary file share/hedgewars/Data/Themes/Brick/Sky.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Brick/horizont.png Binary file share/hedgewars/Data/Themes/Brick/horizont.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Brick/icon.png Binary file share/hedgewars/Data/Themes/Brick/icon.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Brick/plant5.png Binary file share/hedgewars/Data/Themes/Brick/plant5.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Brick/spray2.png Binary file share/hedgewars/Data/Themes/Brick/spray2.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/CMakeLists.txt --- a/share/hedgewars/Data/Themes/CMakeLists.txt Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Themes/CMakeLists.txt Tue Nov 10 20:43:13 2015 +0100 @@ -21,6 +21,7 @@ Golf Halloween Hell + Hoggywood Island Jungle Nature diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cake/BlueWater.png Binary file share/hedgewars/Data/Themes/Cake/BlueWater.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cake/BlueWater.svg diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cake/Border.png Binary file share/hedgewars/Data/Themes/Cake/Border.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cake/CandyCane.png Binary file share/hedgewars/Data/Themes/Cake/CandyCane.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cake/Cherry.png Binary file share/hedgewars/Data/Themes/Cake/Cherry.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cake/Cherry.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Themes/Cake/Cherry.svg Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,311 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cake/Chunk.png Binary file share/hedgewars/Data/Themes/Cake/Chunk.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cake/Chunk.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Themes/Cake/Chunk.svg Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,12078 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cake/Clouds.png Binary file share/hedgewars/Data/Themes/Cake/Clouds.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cake/Clouds.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Themes/Cake/Clouds.svg Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,280 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cake/CupCake.png Binary file share/hedgewars/Data/Themes/Cake/CupCake.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cake/Droplet.png Binary file share/hedgewars/Data/Themes/Cake/Droplet.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cake/Droplet.svg diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cake/Flake.png Binary file share/hedgewars/Data/Themes/Cake/Flake.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cake/Flake.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Themes/Cake/Flake.svg Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,155 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cake/Gingerbread.png Binary file share/hedgewars/Data/Themes/Cake/Gingerbread.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cake/Gingerbread.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Themes/Cake/Gingerbread.svg Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,940 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cake/Girder.png Binary file share/hedgewars/Data/Themes/Cake/Girder.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cake/Girder.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Themes/Cake/Girder.svg Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,138 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cake/IceCream.png Binary file share/hedgewars/Data/Themes/Cake/IceCream.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cake/IceCream.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Themes/Cake/IceCream.svg Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,2110 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cake/LandBackTex.png Binary file share/hedgewars/Data/Themes/Cake/LandBackTex.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cake/LandTex.png Binary file share/hedgewars/Data/Themes/Cake/LandTex.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cake/LandTex.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Themes/Cake/LandTex.svg Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,7229 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cake/Lollipop.png Binary file share/hedgewars/Data/Themes/Cake/Lollipop.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cake/Lollipop.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Themes/Cake/Lollipop.svg Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,265 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cake/Oreo.png Binary file share/hedgewars/Data/Themes/Cake/Oreo.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cake/Oreo.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Themes/Cake/Oreo.svg Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,721 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cake/Oreo2.png Binary file share/hedgewars/Data/Themes/Cake/Oreo2.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cake/SDDroplet.png Binary file share/hedgewars/Data/Themes/Cake/SDDroplet.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cake/SDDroplet.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Themes/Cake/SDDroplet.svg Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,981 @@ + + + + + + + + image/svg+xml + + + + + Carlos Vives B. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cake/SDSplash.png Binary file share/hedgewars/Data/Themes/Cake/SDSplash.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cake/SDSplash.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Themes/Cake/SDSplash.svg Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,1004 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cake/SDWater.png Binary file share/hedgewars/Data/Themes/Cake/SDWater.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cake/SDWater.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Themes/Cake/SDWater.svg Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,595 @@ + + + + + + + + image/svg+xml + + + + + + Carlos Vives B. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cake/Sky.png Binary file share/hedgewars/Data/Themes/Cake/Sky.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cake/Sky.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Themes/Cake/Sky.svg Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,888 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cake/Snowball.png Binary file share/hedgewars/Data/Themes/Cake/Snowball.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cake/Snowball.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Themes/Cake/Snowball.svg Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,80 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cake/Splash.png Binary file share/hedgewars/Data/Themes/Cake/Splash.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cake/amSnowball.png Binary file share/hedgewars/Data/Themes/Cake/amSnowball.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cake/amSnowball.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Themes/Cake/amSnowball.svg Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,96 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cake/horizont.png Binary file share/hedgewars/Data/Themes/Cake/horizont.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cake/icon.png Binary file share/hedgewars/Data/Themes/Cake/icon.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cake/icon@2x.png Binary file share/hedgewars/Data/Themes/Cake/icon@2x.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cake/icon@2x.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Themes/Cake/icon@2x.svg Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,3063 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cake/plant1.png Binary file share/hedgewars/Data/Themes/Cake/plant1.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cake/plant2.png Binary file share/hedgewars/Data/Themes/Cake/plant2.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cake/plant3.png Binary file share/hedgewars/Data/Themes/Cake/plant3.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cake/plant3.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Themes/Cake/plant3.svg Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,496 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cake/theme.cfg --- a/share/hedgewars/Data/Themes/Cake/theme.cfg Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Themes/Cake/theme.cfg Tue Nov 10 20:43:13 2015 +0100 @@ -1,11 +1,19 @@ -sky = 0, 0, 51 +sky = 14, 5, 36 border = 255, 200, 90 water-top = $FF, $DF, $E1 water-bottom = $FF, $DF, $E1 water-opacity = $80 +sd-water-top = 92, 5, 0 +sd-water-bottom = 75, 6, 2 +sd-water-opacity = 125 music = snow.ogg clouds = 9 -object = plant1, 3, 83, 215, 92, 35, 1, 0, 0, 250, 190 -object = plant2, 3, 118, 115, 41, 20, 1, 0, 0, 159, 110 -object = plant3, 3, 0, 115, 70, 40, 1, 8, 0, 60, 100 -flakes = 20, 100, 0, 30, 250 +object = Cherry, 1, 12, 181, 108, 9, 1, 3, 1, 124, 168 +object = Gingerbread, 3, 11, 173, 116, 11, 1, 6, 1, 123, 160 +object = CandyCane, 2, 0, 85, 25, 25, 2, 0, 0, 170, 70, 50, 70, 120, 40 +object = CupCake, 1, 20, 179, 121, 12, 1, 2, 1, 155, 171 +object = IceCream, 2, 0, 257, 45, 12, 1, 8, 1, 150, 236 +object = Lollipop, 2, 222, 120, 43, 15, 1, 0, 0, 220, 111 +spray = Oreo, 2 +spray = Oreo2, 2 +flakes = 55, 40, 99999999, 30, 200 diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Castle/Axe.png Binary file share/hedgewars/Data/Themes/Castle/Axe.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Castle/BlueWater.png Binary file share/hedgewars/Data/Themes/Castle/BlueWater.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Castle/Border.png Binary file share/hedgewars/Data/Themes/Castle/Border.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Castle/Chunk.png Binary file share/hedgewars/Data/Themes/Castle/Chunk.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Castle/Droplet.png Binary file share/hedgewars/Data/Themes/Castle/Droplet.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Castle/Girder.png Binary file share/hedgewars/Data/Themes/Castle/Girder.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Castle/LandBackTex.png Binary file share/hedgewars/Data/Themes/Castle/LandBackTex.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Castle/Shield.png Binary file share/hedgewars/Data/Themes/Castle/Shield.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Castle/Sky.png Binary file share/hedgewars/Data/Themes/Castle/Sky.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Castle/SkyL.png Binary file share/hedgewars/Data/Themes/Castle/SkyL.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Castle/SkyR.png Binary file share/hedgewars/Data/Themes/Castle/SkyR.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Castle/Spear.png Binary file share/hedgewars/Data/Themes/Castle/Spear.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Castle/Sword.png Binary file share/hedgewars/Data/Themes/Castle/Sword.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Castle/horizont.png Binary file share/hedgewars/Data/Themes/Castle/horizont.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Castle/icon.png Binary file share/hedgewars/Data/Themes/Castle/icon.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Castle/theme.cfg --- a/share/hedgewars/Data/Themes/Castle/theme.cfg Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Themes/Castle/theme.cfg Tue Nov 10 20:43:13 2015 +0100 @@ -9,4 +9,4 @@ object = Shield, 3, 0, 165, 163, 2, 1, 0, 0, 163, 140 object = Sword, 3, 240, 22, 17, 43, 1, 8, 21, 227, 80 object = Axe, 3, 25, 195, 90, 65, 1, 40, 5, 195, 175 -flakes = 25, 3, 99999999, 0, 750 +flakes = 25, 3, 0, 0, 750 diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cave/Girder.png Binary file share/hedgewars/Data/Themes/Cave/Girder.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cave/Sky.png Binary file share/hedgewars/Data/Themes/Cave/Sky.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cave/SkyL.png Binary file share/hedgewars/Data/Themes/Cave/SkyL.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cave/Stalactite_mask.png Binary file share/hedgewars/Data/Themes/Cave/Stalactite_mask.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cave/Stalagmite01_mask.png Binary file share/hedgewars/Data/Themes/Cave/Stalagmite01_mask.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cave/Stalagmite02_mask.png Binary file share/hedgewars/Data/Themes/Cave/Stalagmite02_mask.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cave/theme.cfg --- a/share/hedgewars/Data/Themes/Cave/theme.cfg Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Themes/Cave/theme.cfg Tue Nov 10 20:43:13 2015 +0100 @@ -13,4 +13,4 @@ spray = CrystalSpray01, 2 spray = CrystalSpray02, 3 spray = CrystalSpray03, 4 -flakes = 8, 2, 99999999, 0, 1700 +flakes = 8, 2, 0, 0, 1700 diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cheese/Border.png Binary file share/hedgewars/Data/Themes/Cheese/Border.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cheese/Chunk.png Binary file share/hedgewars/Data/Themes/Cheese/Chunk.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cheese/Sky.png Binary file share/hedgewars/Data/Themes/Cheese/Sky.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cheese/cheese_mask.png Binary file share/hedgewars/Data/Themes/Cheese/cheese_mask.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cheese/horizont.png Binary file share/hedgewars/Data/Themes/Cheese/horizont.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Cheese/icon.png Binary file share/hedgewars/Data/Themes/Cheese/icon.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Christmas/Border.png Binary file share/hedgewars/Data/Themes/Christmas/Border.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Christmas/Chunk.png Binary file share/hedgewars/Data/Themes/Christmas/Chunk.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Christmas/Dust.png Binary file share/hedgewars/Data/Themes/Christmas/Dust.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Christmas/Flake.png Binary file share/hedgewars/Data/Themes/Christmas/Flake.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Christmas/Sky.png Binary file share/hedgewars/Data/Themes/Christmas/Sky.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Christmas/Skytrees.png Binary file share/hedgewars/Data/Themes/Christmas/Skytrees.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Christmas/Snowball.png Binary file share/hedgewars/Data/Themes/Christmas/Snowball.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Christmas/amSnowball.png Binary file share/hedgewars/Data/Themes/Christmas/amSnowball.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Christmas/holly.png Binary file share/hedgewars/Data/Themes/Christmas/holly.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Christmas/plant4.png Binary file share/hedgewars/Data/Themes/Christmas/plant4.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Christmas/theme.cfg --- a/share/hedgewars/Data/Themes/Christmas/theme.cfg Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Themes/Christmas/theme.cfg Tue Nov 10 20:43:13 2015 +0100 @@ -13,6 +13,6 @@ object = Snowman, 1, 38, 283, 119, 14, 1, 38, 21, 124, 216 spray = holly, 4 spray = holly2, 4 -flakes = 100, 3, 99999999, 100, 300 +flakes = 100, 3, 0, 100, 300 ice = yes snow = yes diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/City/Border.png Binary file share/hedgewars/Data/Themes/City/Border.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/City/Chunk.png Binary file share/hedgewars/Data/Themes/City/Chunk.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/City/Flake.png Binary file share/hedgewars/Data/Themes/City/Flake.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/City/LandBackTex.png Binary file share/hedgewars/Data/Themes/City/LandBackTex.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/City/icon.png Binary file share/hedgewars/Data/Themes/City/icon.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Compost/BlueWater.png Binary file share/hedgewars/Data/Themes/Compost/BlueWater.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Compost/Border.png Binary file share/hedgewars/Data/Themes/Compost/Border.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Compost/Chunk.png Binary file share/hedgewars/Data/Themes/Compost/Chunk.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Compost/Droplet.png Binary file share/hedgewars/Data/Themes/Compost/Droplet.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Compost/Flake.png Binary file share/hedgewars/Data/Themes/Compost/Flake.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Compost/Girder.png Binary file share/hedgewars/Data/Themes/Compost/Girder.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Compost/LandBackTex.png Binary file share/hedgewars/Data/Themes/Compost/LandBackTex.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Compost/Sky.png Binary file share/hedgewars/Data/Themes/Compost/Sky.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Compost/Snowball.png Binary file share/hedgewars/Data/Themes/Compost/Snowball.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Compost/amSnowball.png Binary file share/hedgewars/Data/Themes/Compost/amSnowball.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Compost/icon.png Binary file share/hedgewars/Data/Themes/Compost/icon.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/CrazyMission/BlueWater.png Binary file share/hedgewars/Data/Themes/CrazyMission/BlueWater.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/CrazyMission/Droplet.png Binary file share/hedgewars/Data/Themes/CrazyMission/Droplet.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/CrazyMission/Sky.png Binary file share/hedgewars/Data/Themes/CrazyMission/Sky.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/CrazyMission/SkyL.png Binary file share/hedgewars/Data/Themes/CrazyMission/SkyL.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Deepspace/BlueWater.png Binary file share/hedgewars/Data/Themes/Deepspace/BlueWater.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Deepspace/Border.png Binary file share/hedgewars/Data/Themes/Deepspace/Border.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Deepspace/Droplet.png Binary file share/hedgewars/Data/Themes/Deepspace/Droplet.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Deepspace/Flake.png Binary file share/hedgewars/Data/Themes/Deepspace/Flake.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Deepspace/Sky.png Binary file share/hedgewars/Data/Themes/Deepspace/Sky.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Desert/BlueWater.png Binary file share/hedgewars/Data/Themes/Desert/BlueWater.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Desert/Border.png Binary file share/hedgewars/Data/Themes/Desert/Border.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Desert/Chunk.png Binary file share/hedgewars/Data/Themes/Desert/Chunk.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Desert/Droplet.png Binary file share/hedgewars/Data/Themes/Desert/Droplet.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Desert/LandBackTex.png Binary file share/hedgewars/Data/Themes/Desert/LandBackTex.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Desert/LandTex.png Binary file share/hedgewars/Data/Themes/Desert/LandTex.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Desert/Sky.png Binary file share/hedgewars/Data/Themes/Desert/Sky.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Desert/buzzard.png Binary file share/hedgewars/Data/Themes/Desert/buzzard.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Desert/cactus.png Binary file share/hedgewars/Data/Themes/Desert/cactus.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Desert/horizont.png Binary file share/hedgewars/Data/Themes/Desert/horizont.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Desert/icon.png Binary file share/hedgewars/Data/Themes/Desert/icon.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Desert/rock2.png Binary file share/hedgewars/Data/Themes/Desert/rock2.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/EarthRise/Border.png Binary file share/hedgewars/Data/Themes/EarthRise/Border.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/EarthRise/Flake.png Binary file share/hedgewars/Data/Themes/EarthRise/Flake.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/EarthRise/LandBackTex.png Binary file share/hedgewars/Data/Themes/EarthRise/LandBackTex.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/EarthRise/RockShort.png Binary file share/hedgewars/Data/Themes/EarthRise/RockShort.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/EarthRise/RockShort_mask.png Binary file share/hedgewars/Data/Themes/EarthRise/RockShort_mask.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/EarthRise/Rock_mask.png Binary file share/hedgewars/Data/Themes/EarthRise/Rock_mask.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/EarthRise/Sky.png Binary file share/hedgewars/Data/Themes/EarthRise/Sky.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/EarthRise/SkyL.png Binary file share/hedgewars/Data/Themes/EarthRise/SkyL.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/EarthRise/horizont.png Binary file share/hedgewars/Data/Themes/EarthRise/horizont.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/EarthRise/horizontL.png Binary file share/hedgewars/Data/Themes/EarthRise/horizontL.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/EarthRise/horizontR.png Binary file share/hedgewars/Data/Themes/EarthRise/horizontR.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Eyes/BlueWater.png Binary file share/hedgewars/Data/Themes/Eyes/BlueWater.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Eyes/Droplet.png Binary file share/hedgewars/Data/Themes/Eyes/Droplet.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Eyes/Flake.png Binary file share/hedgewars/Data/Themes/Eyes/Flake.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Eyes/horizont.png Binary file share/hedgewars/Data/Themes/Eyes/horizont.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Freeway/AppleDirt.png Binary file share/hedgewars/Data/Themes/Freeway/AppleDirt.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Freeway/AppleSmall.png Binary file share/hedgewars/Data/Themes/Freeway/AppleSmall.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Freeway/Border.png Binary file share/hedgewars/Data/Themes/Freeway/Border.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Freeway/Chunk.png Binary file share/hedgewars/Data/Themes/Freeway/Chunk.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Freeway/Clouds.png Binary file share/hedgewars/Data/Themes/Freeway/Clouds.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Freeway/FishDirt.png Binary file share/hedgewars/Data/Themes/Freeway/FishDirt.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Freeway/Flake.png Binary file share/hedgewars/Data/Themes/Freeway/Flake.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Freeway/LandBackTex.png Binary file share/hedgewars/Data/Themes/Freeway/LandBackTex.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Freeway/Sky.png Binary file share/hedgewars/Data/Themes/Freeway/Sky.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Freeway/icon.png Binary file share/hedgewars/Data/Themes/Freeway/icon.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Fruit/BlueWater.png Binary file share/hedgewars/Data/Themes/Fruit/BlueWater.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Fruit/Border.png Binary file share/hedgewars/Data/Themes/Fruit/Border.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Fruit/Droplet.png Binary file share/hedgewars/Data/Themes/Fruit/Droplet.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Fruit/LandBackTex.png Binary file share/hedgewars/Data/Themes/Fruit/LandBackTex.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Fruit/Sky.png Binary file share/hedgewars/Data/Themes/Fruit/Sky.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Fruit/SkyL.png Binary file share/hedgewars/Data/Themes/Fruit/SkyL.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Fruit/Snowball.png Binary file share/hedgewars/Data/Themes/Fruit/Snowball.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Fruit/Watermelon_mask.png Binary file share/hedgewars/Data/Themes/Fruit/Watermelon_mask.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Fruit/amSnowball.png Binary file share/hedgewars/Data/Themes/Fruit/amSnowball.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Fruit/icon.png Binary file share/hedgewars/Data/Themes/Fruit/icon.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Fruit/theme.cfg --- a/share/hedgewars/Data/Themes/Fruit/theme.cfg Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Themes/Fruit/theme.cfg Tue Nov 10 20:43:13 2015 +0100 @@ -10,4 +10,4 @@ object = Watermelon, 1, 87, 272, 77, 10, 1, 21, 2, 242, 219 object = Banana1, 1, 152, 191, 37, 24, 1, 2, 1, 163, 174 object = Banana2, 1, 1, 190, 37, 24, 1, 22, 0, 163, 174 -flakes = 20, 3, 999999999, 100, 260 +flakes = 20, 3, 0, 100, 260 diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Golf/Balldirt.png Binary file share/hedgewars/Data/Themes/Golf/Balldirt.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Golf/BlueWater.png Binary file share/hedgewars/Data/Themes/Golf/BlueWater.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Golf/Border.png Binary file share/hedgewars/Data/Themes/Golf/Border.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Golf/Club2.png Binary file share/hedgewars/Data/Themes/Golf/Club2.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Golf/Flag2.png Binary file share/hedgewars/Data/Themes/Golf/Flag2.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Golf/Flake.png Binary file share/hedgewars/Data/Themes/Golf/Flake.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Golf/Hole.png Binary file share/hedgewars/Data/Themes/Golf/Hole.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Golf/Sky.png Binary file share/hedgewars/Data/Themes/Golf/Sky.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Golf/Tee.png Binary file share/hedgewars/Data/Themes/Golf/Tee.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Golf/horizont.png Binary file share/hedgewars/Data/Themes/Golf/horizont.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Golf/theme.cfg --- a/share/hedgewars/Data/Themes/Golf/theme.cfg Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Themes/Golf/theme.cfg Tue Nov 10 20:43:13 2015 +0100 @@ -1,23 +1,23 @@ -sky = 34, 67, 135 -border = 38, 114, 35 -water-top = 72, 105, 127 -water-bottom = 37, 76, 91 -water-opacity = 128 -music = Golf.ogg -clouds = 9 -object = Hole, 2, 0, 31, 123, 1, 1, 31, 0, 40, 27 -object = Car, 1, 78, 320, 80, 30, 1, 0, 0, 330, 220 -object = Club, 3, 180, 175, 5, 1, 2, 189, 155, 15, 20, 0, 0, 100, 100 -object = Club2, 1, 126, 26, 1, 1, 2, 0, 0, 20, 30, 240, 23, 15, 10 -object = Flag1, 1, 0, 305, 15, 5, 1, 20, 0, 103, 260 -object = Flag2, 1, 40, 305, 10, 4, 1, 0, 0, 53, 270 -object = Flag3, 1, 0, 280, 12, 7, 1, 30, 0, 112, 260 -object = Flag4, 1, 275, 145, 8, 12, 1, 0, 0, 250, 158 -object = Tee, 2, 6, 20, 2, 2, 1, 0, 0, 12, 15 -object = Ball, 4, 8, 15, 2, 1, 1, 0, 0, 16, 8 -object = Ball, 3, 0, 0, 6, 16, 1, 10, 0, 6, 16 -object = Ball, 3, 10, 0, 6, 16, 1, 0, 0, 6, 16 -object = Bag, 1, 65, 0, 129, 44, 1, 0, 71, 234, 81 -spray = Balldirt, 5 -flakes = 55, 40, 99999999, 30, 200 - +sky = 34, 67, 135 +border = 38, 114, 35 +water-top = 72, 105, 127 +water-bottom = 37, 76, 91 +water-opacity = 128 +music = Golf.ogg +clouds = 9 +object = Hole, 2, 0, 31, 123, 1, 1, 31, 0, 40, 27 +object = Car, 1, 78, 320, 80, 30, 1, 0, 0, 330, 220 +object = Club, 3, 180, 175, 5, 1, 2, 189, 155, 15, 20, 0, 0, 100, 100 +object = Club2, 1, 126, 26, 1, 1, 2, 0, 0, 20, 30, 240, 23, 15, 10 +object = Flag1, 1, 0, 305, 15, 5, 1, 20, 0, 103, 260 +object = Flag2, 1, 40, 305, 10, 4, 1, 0, 0, 53, 270 +object = Flag3, 1, 0, 280, 12, 7, 1, 30, 0, 112, 260 +object = Flag4, 1, 275, 145, 8, 12, 1, 0, 0, 250, 158 +object = Tee, 2, 6, 20, 2, 2, 1, 0, 0, 12, 15 +object = Ball, 4, 8, 15, 2, 1, 1, 0, 0, 16, 8 +object = Ball, 3, 0, 0, 6, 16, 1, 10, 0, 6, 16 +object = Ball, 3, 10, 0, 6, 16, 1, 0, 0, 6, 16 +object = Bag, 1, 65, 0, 129, 44, 1, 0, 71, 234, 81 +spray = Balldirt, 5 +flakes = 55, 40, 0, 30, 200 + diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Halloween/BlueWater.png Binary file share/hedgewars/Data/Themes/Halloween/BlueWater.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Halloween/Border.png Binary file share/hedgewars/Data/Themes/Halloween/Border.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Halloween/Chunk.png Binary file share/hedgewars/Data/Themes/Halloween/Chunk.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Halloween/Droplet.png Binary file share/hedgewars/Data/Themes/Halloween/Droplet.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Halloween/Flake.png Binary file share/hedgewars/Data/Themes/Halloween/Flake.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Halloween/Girder.png Binary file share/hedgewars/Data/Themes/Halloween/Girder.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Halloween/LandBackTex.png Binary file share/hedgewars/Data/Themes/Halloween/LandBackTex.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Halloween/SkyL.png Binary file share/hedgewars/Data/Themes/Halloween/SkyL.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Halloween/icon.png Binary file share/hedgewars/Data/Themes/Halloween/icon.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Hell/BlueWater.png Binary file share/hedgewars/Data/Themes/Hell/BlueWater.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Hell/Border.png Binary file share/hedgewars/Data/Themes/Hell/Border.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Hell/Chunk.png Binary file share/hedgewars/Data/Themes/Hell/Chunk.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Hell/Droplet.png Binary file share/hedgewars/Data/Themes/Hell/Droplet.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Hell/Flake.png Binary file share/hedgewars/Data/Themes/Hell/Flake.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Hell/Sky.png Binary file share/hedgewars/Data/Themes/Hell/Sky.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Hell/horizont.png Binary file share/hedgewars/Data/Themes/Hell/horizont.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Hell/icon.png Binary file share/hedgewars/Data/Themes/Hell/icon.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Hell/plant4.png Binary file share/hedgewars/Data/Themes/Hell/plant4.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Hoggywood/Border.png Binary file share/hedgewars/Data/Themes/Hoggywood/Border.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Hoggywood/CMakeLists.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Themes/Hoggywood/CMakeLists.txt Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,6 @@ +file(GLOB images *.png) + +install(FILES + theme.cfg + ${images} + DESTINATION ${SHAREPATH}Data/Themes/Hoggywood) diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Hoggywood/Clouds.png Binary file share/hedgewars/Data/Themes/Hoggywood/Clouds.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Hoggywood/Flake.png Binary file share/hedgewars/Data/Themes/Hoggywood/Flake.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Hoggywood/Girder.png Binary file share/hedgewars/Data/Themes/Hoggywood/Girder.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Hoggywood/LandBackTex.png Binary file share/hedgewars/Data/Themes/Hoggywood/LandBackTex.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Hoggywood/LandTex.png Binary file share/hedgewars/Data/Themes/Hoggywood/LandTex.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Hoggywood/SDClouds.png Binary file share/hedgewars/Data/Themes/Hoggywood/SDClouds.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Hoggywood/SignL.png Binary file share/hedgewars/Data/Themes/Hoggywood/SignL.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Hoggywood/SignR.png Binary file share/hedgewars/Data/Themes/Hoggywood/SignR.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Hoggywood/Sky.png Binary file share/hedgewars/Data/Themes/Hoggywood/Sky.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Hoggywood/SkyL.png Binary file share/hedgewars/Data/Themes/Hoggywood/SkyL.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Hoggywood/SkyR.png Binary file share/hedgewars/Data/Themes/Hoggywood/SkyR.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Hoggywood/camera.png Binary file share/hedgewars/Data/Themes/Hoggywood/camera.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Hoggywood/clapper.png Binary file share/hedgewars/Data/Themes/Hoggywood/clapper.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Hoggywood/hogscar.png Binary file share/hedgewars/Data/Themes/Hoggywood/hogscar.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Hoggywood/horizont.png Binary file share/hedgewars/Data/Themes/Hoggywood/horizont.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Hoggywood/horizontL.png Binary file share/hedgewars/Data/Themes/Hoggywood/horizontL.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Hoggywood/icon.png Binary file share/hedgewars/Data/Themes/Hoggywood/icon.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Hoggywood/icon@2x.png Binary file share/hedgewars/Data/Themes/Hoggywood/icon@2x.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Hoggywood/palm.png Binary file share/hedgewars/Data/Themes/Hoggywood/palm.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Hoggywood/reel.png Binary file share/hedgewars/Data/Themes/Hoggywood/reel.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Hoggywood/reel2.png Binary file share/hedgewars/Data/Themes/Hoggywood/reel2.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Hoggywood/star1.png Binary file share/hedgewars/Data/Themes/Hoggywood/star1.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Hoggywood/star2.png Binary file share/hedgewars/Data/Themes/Hoggywood/star2.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Hoggywood/star3.png Binary file share/hedgewars/Data/Themes/Hoggywood/star3.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Hoggywood/star4.png Binary file share/hedgewars/Data/Themes/Hoggywood/star4.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Hoggywood/star5.png Binary file share/hedgewars/Data/Themes/Hoggywood/star5.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Hoggywood/theme.cfg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Themes/Hoggywood/theme.cfg Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,22 @@ +sky = 100, 180, 220 +border = 71, 74, 93 +water-top = $54, $5C, $9D +water-bottom = $34, $3C, $7D +water-opacity = $80 +music = Rock.ogg +sd-music = hell.ogg +clouds = 32 +object = palm, 4, 169, 467, 61, 6, 2, 0, 0, 333, 238, 168, 237, 55, 92 +object = hogscar, 1, 20, 159, 70, 1, 1, 0, 0, 132, 140 +object = camera, 1, 25, 285, 92, 25, 1, 0, 0, 123, 222 +object = clapper, 1, 52, 227, 18, 5, 1, 0, 0, 263, 209 +object = reel, 1, 64, 128, 1, 1, 2, 0, 0, 150, 90, 170, 90, 49, 40 +object = reel2, 1, 40, 0, 20, 5, 1, 0, 45, 140, 175 +object = SignL, 1, 177, 15, 4, 39, 1, 0, 0, 160, 54 +object = SignR, 1, 0, 17, 5, 39, 1, 23, 0, 158, 56 +;spray = star1, 1 +;spary = star2, 1 +;spray = star3, 1 +spray = star4, 1 +spray = star5, 1 +flakes = 100, 3, 99999999, 10, 20 diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Island/Border.png Binary file share/hedgewars/Data/Themes/Island/Border.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Island/Chunk.png Binary file share/hedgewars/Data/Themes/Island/Chunk.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Island/Flake.png Binary file share/hedgewars/Data/Themes/Island/Flake.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Island/LandTex.png Binary file share/hedgewars/Data/Themes/Island/LandTex.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Island/Sky.png Binary file share/hedgewars/Data/Themes/Island/Sky.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Island/SkyL.png Binary file share/hedgewars/Data/Themes/Island/SkyL.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Island/icon.png Binary file share/hedgewars/Data/Themes/Island/icon.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Jungle/BlueWater.png Binary file share/hedgewars/Data/Themes/Jungle/BlueWater.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Jungle/Border.png Binary file share/hedgewars/Data/Themes/Jungle/Border.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Jungle/Droplet.png Binary file share/hedgewars/Data/Themes/Jungle/Droplet.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Jungle/SkyL.png Binary file share/hedgewars/Data/Themes/Jungle/SkyL.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Jungle/icon.png Binary file share/hedgewars/Data/Themes/Jungle/icon.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Nature/Border.png Binary file share/hedgewars/Data/Themes/Nature/Border.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Nature/Chunk.png Binary file share/hedgewars/Data/Themes/Nature/Chunk.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Nature/Flake.png Binary file share/hedgewars/Data/Themes/Nature/Flake.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Nature/Girder.png Binary file share/hedgewars/Data/Themes/Nature/Girder.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Nature/Sky.png Binary file share/hedgewars/Data/Themes/Nature/Sky.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Nature/butterfly.png Binary file share/hedgewars/Data/Themes/Nature/butterfly.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Nature/icon.png Binary file share/hedgewars/Data/Themes/Nature/icon.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Nature/plant2.png Binary file share/hedgewars/Data/Themes/Nature/plant2.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Nature/theme.cfg --- a/share/hedgewars/Data/Themes/Nature/theme.cfg Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Themes/Nature/theme.cfg Tue Nov 10 20:43:13 2015 +0100 @@ -16,4 +16,4 @@ object = snail, 3, 51, 94, 52, 3, 1, 0, 0, 135, 87 object = mushroom, 3, 14, 77, 24, 2, 1, 0, 0, 76, 73 object = mushroom2, 3, 24, 78, 48, 7, 2, 0, 0, 80, 36, 15, 38, 57, 30 -flakes = 55, 40, 99999999, 30, 200 +flakes = 55, 40, 0, 30, 200 diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Olympics/Border.png Binary file share/hedgewars/Data/Themes/Olympics/Border.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Olympics/Chunk.png Binary file share/hedgewars/Data/Themes/Olympics/Chunk.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Olympics/Column01.png Binary file share/hedgewars/Data/Themes/Olympics/Column01.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Olympics/Column02.png Binary file share/hedgewars/Data/Themes/Olympics/Column02.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Olympics/Column03.png Binary file share/hedgewars/Data/Themes/Olympics/Column03.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Olympics/Sky.png Binary file share/hedgewars/Data/Themes/Olympics/Sky.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Olympics/SkyL.png Binary file share/hedgewars/Data/Themes/Olympics/SkyL.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Olympics/horizont.png Binary file share/hedgewars/Data/Themes/Olympics/horizont.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Olympics/icon.png Binary file share/hedgewars/Data/Themes/Olympics/icon.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Olympics/theme.cfg --- a/share/hedgewars/Data/Themes/Olympics/theme.cfg Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Themes/Olympics/theme.cfg Tue Nov 10 20:43:13 2015 +0100 @@ -4,6 +4,7 @@ water-bottom = $34, $3C, $7D water-opacity = $80 music = Olympics.ogg +sd-music = olympics_sd.ogg clouds = 9 object = Statue, 3, 42, 258, 115, 2, 1, 0, 0, 165, 240 object = Column01, 3, 21, 258, 80, 2, 1, 0, 0, 110, 240 diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Planes/Sky.png Binary file share/hedgewars/Data/Themes/Planes/Sky.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Sheep/Border.png Binary file share/hedgewars/Data/Themes/Sheep/Border.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Sheep/Chunk.png Binary file share/hedgewars/Data/Themes/Sheep/Chunk.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Sheep/Clouds.png Binary file share/hedgewars/Data/Themes/Sheep/Clouds.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Sheep/Flake.png Binary file share/hedgewars/Data/Themes/Sheep/Flake.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Sheep/Sky.png Binary file share/hedgewars/Data/Themes/Sheep/Sky.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Sheep/barriere.png Binary file share/hedgewars/Data/Themes/Sheep/barriere.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Sheep/fleurland.png Binary file share/hedgewars/Data/Themes/Sheep/fleurland.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Sheep/fleurland2.png Binary file share/hedgewars/Data/Themes/Sheep/fleurland2.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Sheep/fleurland3.png Binary file share/hedgewars/Data/Themes/Sheep/fleurland3.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Sheep/fleurland4.png Binary file share/hedgewars/Data/Themes/Sheep/fleurland4.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Sheep/grass.png Binary file share/hedgewars/Data/Themes/Sheep/grass.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Sheep/grass2.png Binary file share/hedgewars/Data/Themes/Sheep/grass2.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Sheep/grassp.png Binary file share/hedgewars/Data/Themes/Sheep/grassp.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Sheep/grassp2.png Binary file share/hedgewars/Data/Themes/Sheep/grassp2.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Sheep/horizont.png Binary file share/hedgewars/Data/Themes/Sheep/horizont.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Sheep/icon.png Binary file share/hedgewars/Data/Themes/Sheep/icon.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Sheep/mouton1.png Binary file share/hedgewars/Data/Themes/Sheep/mouton1.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Sheep/mouton2.png Binary file share/hedgewars/Data/Themes/Sheep/mouton2.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Sheep/mouton3.png Binary file share/hedgewars/Data/Themes/Sheep/mouton3.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Sheep/mouton4.png Binary file share/hedgewars/Data/Themes/Sheep/mouton4.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Sheep/rocher.png Binary file share/hedgewars/Data/Themes/Sheep/rocher.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Snow/Border.png Binary file share/hedgewars/Data/Themes/Snow/Border.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Snow/Chunk.png Binary file share/hedgewars/Data/Themes/Snow/Chunk.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Snow/Dust.png Binary file share/hedgewars/Data/Themes/Snow/Dust.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Snow/Flake.png Binary file share/hedgewars/Data/Themes/Snow/Flake.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Snow/Girder.png Binary file share/hedgewars/Data/Themes/Snow/Girder.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Snow/Sky.png Binary file share/hedgewars/Data/Themes/Snow/Sky.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Snow/Snowball.png Binary file share/hedgewars/Data/Themes/Snow/Snowball.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Snow/amSnowball.png Binary file share/hedgewars/Data/Themes/Snow/amSnowball.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Snow/icon.png Binary file share/hedgewars/Data/Themes/Snow/icon.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Snow/plant4.png Binary file share/hedgewars/Data/Themes/Snow/plant4.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Snow/theme.cfg --- a/share/hedgewars/Data/Themes/Snow/theme.cfg Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Themes/Snow/theme.cfg Tue Nov 10 20:43:13 2015 +0100 @@ -9,6 +9,6 @@ object = plant2, 3, 0, 85, 25, 25, 2, 0, 0, 170, 70, 50, 70, 120, 40 object = plant3, 3, 26, 0, 48, 1, 1, 25, 15, 50, 60 object = plant4, 3, 45, 4, 1, 45, 1, 20, 45, 20, 60 -flakes = 100, 3, 99999999, 100, 300 +flakes = 100, 3, 0, 100, 300 ice = yes snow = yes diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Stage/BlueWater.png Binary file share/hedgewars/Data/Themes/Stage/BlueWater.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Stage/Border.png Binary file share/hedgewars/Data/Themes/Stage/Border.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Stage/Chunk.png Binary file share/hedgewars/Data/Themes/Stage/Chunk.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Stage/Droplet.png Binary file share/hedgewars/Data/Themes/Stage/Droplet.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Stage/Flake.png Binary file share/hedgewars/Data/Themes/Stage/Flake.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Stage/Girder.png Binary file share/hedgewars/Data/Themes/Stage/Girder.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Stage/Sky.png Binary file share/hedgewars/Data/Themes/Stage/Sky.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Stage/SkyL.png Binary file share/hedgewars/Data/Themes/Stage/SkyL.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Stage/icon.png Binary file share/hedgewars/Data/Themes/Stage/icon.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Stage/theme.cfg --- a/share/hedgewars/Data/Themes/Stage/theme.cfg Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/Themes/Stage/theme.cfg Tue Nov 10 20:43:13 2015 +0100 @@ -15,4 +15,4 @@ spray = poster2, 2 spray = poster3, 2 spray = poster4, 2 -flakes = 100, 3, 99999999, 10, 20 +flakes = 100, 3, 0, 10, 20 diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Underwater/BlueWater.png Binary file share/hedgewars/Data/Themes/Underwater/BlueWater.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Underwater/Border.png Binary file share/hedgewars/Data/Themes/Underwater/Border.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Underwater/Droplet.png Binary file share/hedgewars/Data/Themes/Underwater/Droplet.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Underwater/SDFlake.png Binary file share/hedgewars/Data/Themes/Underwater/SDFlake.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Underwater/Sky.png Binary file share/hedgewars/Data/Themes/Underwater/Sky.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Underwater/Snowball.png Binary file share/hedgewars/Data/Themes/Underwater/Snowball.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Underwater/amSnowball.png Binary file share/hedgewars/Data/Themes/Underwater/amSnowball.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Underwater/horizont.png Binary file share/hedgewars/Data/Themes/Underwater/horizont.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/Themes/Underwater/icon.png Binary file share/hedgewars/Data/Themes/Underwater/icon.png has changed diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/misc/CMakeLists.txt --- a/share/hedgewars/Data/misc/CMakeLists.txt Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/misc/CMakeLists.txt Tue Nov 10 20:43:13 2015 +0100 @@ -5,5 +5,6 @@ file(GLOB miscfiles *.xml *.desktop) install(FILES ${miscfiles} DESTINATION ${SHAREPATH}/Data/misc) + install(FILES hedgewars.xpm DESTINATION ${CMAKE_INSTALL_PREFIX}/share/pixmaps) endif() diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/misc/hedgewars-mimeinfo.xml --- a/share/hedgewars/Data/misc/hedgewars-mimeinfo.xml Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/misc/hedgewars-mimeinfo.xml Tue Nov 10 20:43:13 2015 +0100 @@ -7,7 +7,7 @@ --> Hedgewars Demo - Hedgewars Demo + Hedgewars-Wiederholung Demo de Hedgewars Démonstration d'Hedgewars Demo di Hedgewars @@ -29,7 +29,7 @@ Hedgewars Save - Hedgewars gespeichertes Spiel + Hedgewars-Spielstand Partida guardada de Hedgewars Parties enregistrées d'Hedgewars 헤즈와스 저장된 게임 diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/misc/hedgewars.desktop --- a/share/hedgewars/Data/misc/hedgewars.desktop Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/misc/hedgewars.desktop Tue Nov 10 20:43:13 2015 +0100 @@ -2,6 +2,7 @@ Type=Application Version=1.0 Name=Hedgewars +Keywords=game;strategy; GenericName=Fighting Hedgehogs GenericName[de]=Kämpfende Igel GenericName[es]=Batallas entre erizos @@ -20,5 +21,5 @@ Exec=hedgewars %U Terminal=false StartupNotify=false -Categories=Application;Game;StrategyGame; +Categories=Game;StrategyGame; MimeType=x-scheme-handler/hwplay; diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/misc/hedgewars.xpm --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/misc/hedgewars.xpm Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,239 @@ +/* XPM */ +static char *Icon___x__x__[] = { +/* columns rows colors chars-per-pixel */ +"32 32 201 2", +" c #010101", +". c #0A0709", +"X c #1A1A1A", +"o c #454545", +"O c #94005E", +"+ c #AE005D", +"@ c #970063", +"# c #9B0064", +"$ c #94066D", +"% c #9D036A", +"& c #9E086E", +"* c #880873", +"= c #960E74", +"- c #980D73", +"; c #8C1578", +": c #8C1A7D", +"> c #9D1075", +", c #9D177C", +"< c #91187D", +"1 c #9B1C7D", +"2 c #A20065", +"3 c #AA0067", +"4 c #A3046B", +"5 c #A0096F", +"6 c #A20C73", +"7 c #AD0B72", +"8 c #A41276", +"9 c #AD1074", +"0 c #A61479", +"q c #A81C7B", +"w c #7B2083", +"e c #772E8F", +"r c #7D2C8E", +"t c #732F91", +"y c #6B3596", +"u c #653B9B", +"i c #6D3A9B", +"p c #743294", +"a c #783092", +"s c #713899", +"d c #5641A1", +"f c #504BA9", +"g c #5A4EAD", +"h c #4D5AB6", +"j c #5652B0", +"k c #5058B5", +"l c #6444A3", +"z c #7C4CA8", +"x c #7654B2", +"c c #4363BF", +"v c #3D67C3", +"b c #3A69C5", +"n c #3C73CE", +"m c #2C77D1", +"M c #237CD6", +"N c #2C78D2", +"B c #2F7ED8", +"V c #3E7BD5", +"C c #5F71CC", +"Z c #6F6ECA", +"A c #627FD6", +"S c #6C7ED6", +"D c #617ED9", +"F c #6F7ED9", +"G c #881F82", +"H c #A11F83", +"J c #AC1D82", +"K c #872386", +"L c #8A2387", +"P c #8D2689", +"I c #8A2C8F", +"U c #952388", +"Y c #812F91", +"T c #873595", +"R c #8D3192", +"E c #8A3799", +"W c #84399A", +"Q c #AE2285", +"! c #A32488", +"~ c #A92D8D", +"^ c #B1258A", +"/ c #B32C8C", +"( c #BD298E", +") c #B5308E", +"_ c #B72E91", +"` c #BE2C91", +"' c #BA3495", +"] c #BA3895", +"[ c #BC3C9A", +"{ c #BF3BA0", +"} c #C32E93", +"| c #C23391", +" . c #CF3D9D", +".. c #C13DA2", +"X. c #CA3BA0", +"o. c #BE419C", +"O. c #8148A4", +"+. c #8152B0", +"@. c #C0439E", +"#. c #C345A3", +"$. c #C54EA5", +"%. c #CE4AA3", +"&. c #C645AA", +"*. c #C74EA9", +"=. c #C94AAE", +"-. c #D045AA", +";. c #D04BAF", +":. c #C750A8", +">. c #CC59AB", +",. c #CB4DB1", +"<. c #CC51B4", +"1. c #CD5AB0", +"2. c #D45CBF", +"3. c #D363BA", +"4. c #D65FC3", +"5. c #D769C0", +"6. c #DB6CC3", +"7. c #DE66C9", +"8. c #DE6BCE", +"9. c #DB74C5", +"0. c #DE76CB", +"q. c #DF6DD0", +"w. c #E068CC", +"e. c #EA7FCF", +"r. c #E06FD1", +"t. c #E274D5", +"y. c #E47BD6", +"u. c #E376D8", +"i. c #E479D9", +"p. c #E87FDE", +"a. c #1E83DC", +"s. c #2482DB", +"d. c #2B80DA", +"f. c #3682DC", +"g. c #1B8BE3", +"h. c #3187E0", +"j. c #3D8BE4", +"k. c #2790E8", +"l. c #3594EC", +"z. c #3D94EC", +"x. c #4C90EA", +"c. c #5494EB", +"v. c #469CF4", +"b. c #4C98F1", +"n. c #5A97F1", +"m. c #529AF2", +"M. c #5A9FF8", +"N. c #6B87E1", +"B. c #49A1F9", +"V. c #59A3F6", +"C. c #52A6FE", +"Z. c #5DA7FE", +"A. c #56AFFF", +"S. c #5CABFF", +"D. c #56B4FF", +"F. c #58B5FF", +"G. c #54BBFF", +"H. c #898989", +"J. c #8A918D", +"K. c #949394", +"L. c #9C9B9C", +"P. c #B5B4B5", +"I. c #E483D2", +"U. c #E789D6", +"Y. c #E781DA", +"T. c #E985DC", +"R. c #EA89DC", +"E. c #EC91DE", +"W. c #EE9BDA", +"Q. c #EC87E2", +"!. c #EC8CE2", +"~. c #EE93E1", +"^. c #F195E6", +"/. c #F29BE7", +"(. c #F49EE9", +"). c #F4A6E5", +"_. c #F5A2EB", +"`. c #F9A6EF", +"'. c #F6AAED", +"]. c #F5B2EC", +"[. c #F6A2F0", +"{. c #FAA6F1", +"}. c #FAAAF3", +"|. c #FBB7F5", +" X c #FEB1F8", +".X c #C8C7C8", +"XX c #CBCBCC", +"oX c #CDD1CF", +"OX c #F3D2EB", +"+X c #F7C6F0", +"@X c #F8C1F1", +"#X c #F8CAF2", +"$X c #FFD1FC", +"%X c #FDDBFB", +"&X c #F9E6F7", +"*X c #FDE5FA", +"=X c #FDEDFB", +"-X c #F3FCF5", +";X c #FCF3FA", +":X c #FEFEFE", +">X c None", +/* pixels */ +">X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X", +">X>X>X>X>X>X>X>X>X>X>X= & >X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X", +">X>X>X>X>X>X>X>X>X>X>Xp v : >X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X", +">X>X>X>X>X>X>X>X>X>X>Xr k.f.u 4 >X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X", +">X>X>X>X>X>X>X>X>X>X>Xt z.Z.l.c : 3 >X>X>X>X>X>X>X>X>X>X>X>X>X>X", +">X>X>X>X>X>X>X>X>X>X>Xy l.Z.Z.B.h.l > >X>X>X>X>X>X>X>X>X>X>X>X>X", +">X>X>X>X4 >X>X>X>X>X>Xt j.Z.A.S.n.C f * % >X>X>X>X>X>X>X>X>X>X>X", +">X>X>X4 l g l i p r K : T P L R ~ ] [ ] ^ 8 O >X>X>X>X>X>X>X>X>X", +">X>X>X>Xs g.s.s.s.M M s.d 8 %.I.(._.{.`._.E.3.Q # >X>X>X>X>X>X>X", +">X>X>X>X4 D C.m.m.b.v.p ' E.}._.(././.(./._.`._.1.& >X>X>X>X>X>X", +">X>X>X>X>XT A.Z.D.D.W .}._././.(._.(.(././.^./.}.6.6 >X>X>X>X>X", +">X>X>X>X>X2 A D.N.W ( _._./.(.(.(.(.(./.'.+X@X_.].$X9.# >X>X>X>X", +">X>X>X>X>X>X1 E ; 7 i._.(.(.(.(.(._./.].:X:X:X;X:X:X:X$.>X>X>X>X", +">X>X>X>X4 < i b y -.!.(.(.(._.(.(.(./.*X:X:X:X:X:X:X-XOX6 >X>X>X", +">X>X6 r k m a.m ! 7.!._.(.(.(.(.(./._.:X:X:XL.P.:XH. XX>.>X>X>X", +">X* n a.M B z.C ( t.R._.(.(.(.(.(./.'.;X:X.X X :Xo J.W.# >X>X", +">X# a V v.V.G.z X.t.R._./._.(./.(.(.(.=X:X.X X :XK.. oX).% >X>X", +">X>X>X0 F G.S 2 ,.t.Y._./.(.(._.(._.^.#X:X:XK.P.:X:X-X=X~.8 >X>X", +">X>X>X>X4 x I w ,.u.y.(.(._.(.(._.(.(./.&X:X:X:X=X+X%X'.U.) ] >X", +">X>X>X>X>X+ h f .t.7.~.(./.(.(./.(.(.(._.#X&X*X|.{.3.U.U.] ^.q ", +">X>X>X>X>Xp g.h ` i.t.Q.}._./.(.(.(.(.(./.(.~.6.3.@.$.}.3.#. X) ", +">X>X>X>X: m d.c.! 7.,...3.E.`./.(._.(.(./._./.| @.r._.}.' 3.U.q ", +">X>X>X4 c M x.F.O.7 [ :.o.Q 3.{./.(.(._.(./._.{. X_._.R.^ r.J >X", +">X>X4 j g.z.F.V.U 6.}.}.}.E.Q 9.`./.(./.(.(.(././.).[.] 8 6 >X>X", +">X>X- l g Z N.x } [.(././.}.9._ (.(.(._._.(.(.(.^.^.,.% >X>X>X>X", +">X>X>X>X>X4 4 2 &.Q.(.(./._.T.Q t.y.R.~.~.~.Q.Q.Y.=.- >X>X>X>X>X", +">X>X>X>X>X>X>X>X^ u.R./.(.{.*.[ i.q.8.8.q.r.i.q.' & >X>X>X>X>X>X", +">X>X>X>X>X>X>X>X% _ 4.r.8.#.& ,.q.t.t.t.q.4.| J | 0 >X>X>X>X>X>X", +">X>X>X>X>X>X>X>X>X>X6 0 6 - &.' Q ^ ^ ^ Q / *.U. X[ >X>X>X>X>X>X", +">X>X>X>X>X>X>X>X>X>X>X>X>X6 q.!.~.I.U.*.] }.}._.}.@.>X>X>X>X>X>X", +">X>X>X>X>X>X>X>X>X>X>X>X>X>X' u.Q.^.~.Q &.Q.~.(.r.8 >X>X>X>X>X>X", +">X>X>X>X>X>X>X>X>X>X>X>X>X>X% ^ ,.&.J % 0 ..,...6 >X>X>X>X>X>X>X" +}; diff -r 31570b766315 -r ed5a6478e710 share/hedgewars/Data/misc/hwengine.desktop.in --- a/share/hedgewars/Data/misc/hwengine.desktop.in Tue Nov 10 18:16:35 2015 +0100 +++ b/share/hedgewars/Data/misc/hwengine.desktop.in Tue Nov 10 20:43:13 2015 +0100 @@ -3,7 +3,7 @@ Version=1.0 Name=Hedgewars Engine GenericName=Hedgewars engine, for playback of saves and demos -GenericName[de]=Hedgewars engine, für die Wiedergabe von gespeicherten Spielen und Demos +GenericName[de]=Hedgewars-Engine, für die Wiedergabe von gespeicherten Spielen und Demos GenericName[es]=Motor del juego Hedgewars, reproduce demos y partidas guardadas GenericName[fr]=Moteur graphique d'Hedgewars, pour revoir les parties enregistrées et de démonstration. GenericName[it]=Motore grafico di Hedgewars, riproduce le demo e riprende le partite salvate diff -r 31570b766315 -r ed5a6478e710 tests/lua/drillrockets_boom.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/lua/drillrockets_boom.lua Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,162 @@ + +local ta_pointsize = 63 +local ta_radius = (ta_pointsize * 10 + 6) / 2 + +local sqrttwo = math.sqrt(2) + +-- creates round test area +function AddTestArea(testarea) + step = 100 + xstep = step * testarea["xdir"] + ystep = step * testarea["ydir"] + x = testarea["x"] + y = testarea["y"] + if xstep * ystep ~= 0 then + xstep = math.floor(xstep / sqrttwo) + ystep = math.floor(ystep / sqrttwo) + end + AddPoint(x, y, ta_pointsize); + AddPoint(x + xstep, y + ystep, ta_pointsize, true); +end + +-- vertical test areas +local taa_v1 = {x= 350, y= 400, xdir= 0, ydir= 1} +local taa_v2 = {x= 350, y=1500, xdir= 0, ydir=-1} +-- horizontal test areas +local taa_h1 = {x=1150, y= 400, xdir= 1, ydir= 0} +local taa_h2 = {x=1200, y=1100, xdir=-1, ydir= 0} +-- diagonal test areas +local taa_d1 = {x=2200, y= 400, xdir= 1, ydir= 1} +local taa_d2 = {x=2000, y=1500, xdir= 1, ydir=-1} +local taa_d3 = {x=3300, y= 400, xdir=-1, ydir= 1} +local taa_d4 = {x=3300, y=1500, xdir=-1, ydir=-1} + +-- fail counter +local nfailed = 0 +local nspawned = 0 +local ndied = 0 + +function onGameInit() + -- At first we have to overwrite/set some global variables + -- that define the map, the game has to load, as well as + -- other things such as the game rules to use, etc. + -- Things we don't modify here will use their default values. + + -- The base number for the random number generator + Seed = 1 + -- The map to be played + MapGen = mgDrawn + -- The theme to be used + Theme = "Bamboo" + -- Game settings and rules + EnableGameFlags(gfOneClanMode, gfDisableWind, gfDisableLandObjects, gfDisableGirders, gfSolidLand) + CaseFreq = 0 + MinesNum = 0 + Explosives = 0 + + -- No damage please + DamagePercent = 1 + + -- Draw Map + -- AddPoint(10,30,0) -- hog spawn platform + -- test areas + AddTestArea(taa_v1) + AddTestArea(taa_v2) + AddTestArea(taa_h1) + AddTestArea(taa_h2) + AddTestArea(taa_d1) + AddTestArea(taa_d2) + AddTestArea(taa_d3) + AddTestArea(taa_d4) + + FlushPoints() + + -- Create the player team + AddTeam("'Zooka Team", 14483456, "Simple", "Island", "Default") + -- And add a hog to it + player = AddHog("Hunter", 0, 1, "NoHat") + -- place it on how spawn platform + SetGearPosition(player, 10, 10) +end + +-- xdir/ydir is direction in which to fire the drills +function SpawnDrillRocketArray(testarea) + xdir = testarea["xdir"] + ydir = testarea["ydir"] + centerx = testarea["x"] + centery = testarea["y"] + distance = 23 + d = distance + radius = ta_radius + speed = 900000; + local xmin, xmax, ymin, ymax + if (xdir ~= 0) and (ydir ~= 0) then + d = d / sqrttwo + radius = radius / sqrttwo + speed = math.floor(speed / sqrttwo) + end + centerx = centerx - (xdir * (radius + 20)) + centery = centery - (ydir * (radius + 20)) + radius = radius - 6 + xn = ydir + yn = -xdir + startx = centerx - (radius * xn) + starty = centery - (radius * yn) + endx = centerx + (radius * xn) + endy = centery + (radius * yn) + + -- spawn loop + x = startx + y = starty + xd = d * xn + yd = d * yn + if (xd < 0) and (startx < endx) then x = endx end + if (yd < 0) and (starty < endy) then y = endy end + nsteps = math.floor(math.max(math.abs(startx - endx),math.abs(starty - endy)) / d) + for i = 1, nsteps, 1 do + AddGear(math.floor(x), math.floor(y), gtDrill, gsttmpFlag * (i % 2), speed * xdir, speed * ydir, 0) + nspawned = nspawned + 1 + x = x + xd + y = y + yd + end +end + +function onGearDelete(gear) + if GetGearType(gear) == gtDrill then + -- the way to check state will change in API at some point + if band(GetState(gear), gsttmpFlag) == 0 then + -- regular drill rocket + if (GetTimer(gear) < 2000) or (GetTimer(gear) > 3000) then + nfailed = nfailed + 1 + end + else + -- airstrike drill rocket + if GetTimer(gear) > 0 then + nfailed = nfailed + 1 + end + end + ndied = ndied + 1 + if ndied == nspawned then + WriteLnToConsole('TESTRESULT: ' .. nfailed .. ' of ' .. nspawned .. ' drill rockets did not explode as expected') + if (nfailed > 0) then + EndLuaTest(TEST_FAILED) + else + EndLuaTest(TEST_SUCCESSFUL) + end + end + end +end + +function onGameStart() + SetGravity(1) + + SpawnDrillRocketArray(taa_h1) + SpawnDrillRocketArray(taa_h2) + SpawnDrillRocketArray(taa_v1) + SpawnDrillRocketArray(taa_v2) + SpawnDrillRocketArray(taa_d1) + SpawnDrillRocketArray(taa_d2) + SpawnDrillRocketArray(taa_d3) + SpawnDrillRocketArray(taa_d4) +end + diff -r 31570b766315 -r ed5a6478e710 tests/lua/drillrockets_drill.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/lua/drillrockets_drill.lua Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,149 @@ + +local ta_pointsize = 63 +local ta_radius = (ta_pointsize * 10 + 6) / 2 + +-- creates round test area +function AddTestArea(testarea) + step = 200 + xstep = step * testarea["xdir"] + ystep = step * testarea["ydir"] + x = testarea["x"] + y = testarea["y"] + AddPoint(x, y, ta_pointsize); + AddPoint(x + xstep, y + ystep); +end + +-- vertical test areas +local taa_v1 = {x= 350, y= 400, xdir= 0, ydir= 1} +local taa_v2 = {x= 350, y=1500, xdir= 0, ydir=-1} +-- horizontal test areas +local taa_h1 = {x=1150, y= 400, xdir= 1, ydir= 0} +local taa_h2 = {x=1200, y=1100, xdir=-1, ydir= 0} +-- diagonal test areas +local taa_d1 = {x=2200, y= 400, xdir= 1, ydir= 1} +local taa_d2 = {x=2000, y=1500, xdir= 1, ydir=-1} +local taa_d3 = {x=3300, y= 400, xdir=-1, ydir= 1} +local taa_d4 = {x=3300, y=1500, xdir=-1, ydir=-1} + +-- fail counter +local nfailed = 0 +local nspawned = 0 +local ndied = 0 + +function onGameInit() + -- At first we have to overwrite/set some global variables + -- that define the map, the game has to load, as well as + -- other things such as the game rules to use, etc. + -- Things we don't modify here will use their default values. + + -- The base number for the random number generator + Seed = 1 + -- The map to be played + MapGen = mgDrawn + -- The theme to be used + Theme = "Bamboo" + -- Game settings and rules + EnableGameFlags(gfOneClanMode, gfDisableWind, gfDisableLandObjects, gfDisableGirders, gfSolidLand) + CaseFreq = 0 + MinesNum = 0 + Explosives = 0 + + -- No damage please + DamagePercent = 1 + + -- Draw Map + AddPoint(10,30,0) -- hog spawn platform + -- test areas + AddTestArea(taa_v1) + AddTestArea(taa_v2) + AddTestArea(taa_h1) + AddTestArea(taa_h2) + AddTestArea(taa_d1) + AddTestArea(taa_d2) + AddTestArea(taa_d3) + AddTestArea(taa_d4) + + FlushPoints() + + -- Create the player team + AddTeam("'Zooka Team", 14483456, "Simple", "Island", "Default") + -- And add a hog to it + player = AddHog("Hunter", 0, 1, "NoHat") + -- place it on how spawn platform + SetGearPosition(player, 10, 10) +end + +-- xdir/ydir is direction in which to fire the drills +function SpawnDrillRocketArray(testarea) + xdir = testarea["xdir"] + ydir = testarea["ydir"] + centerx = testarea["x"] + centery = testarea["y"] + distance = 23 + d = distance + radius = ta_radius + local xmin, xmax, ymin, ymax + speed = 900000; + local xmin, xmax, ymin, ymax + if (xdir ~= 0) and (ydir ~= 0) then + sqrttwo = math.sqrt(2) + d = d / sqrttwo + radius = radius / sqrttwo + speed = math.floor(speed / sqrttwo) + end + centerx = centerx - (xdir * (radius + 20)) + centery = centery - (ydir * (radius + 20)) + radius = radius - 6 + xn = ydir + yn = -xdir + startx = centerx - (radius * xn) + starty = centery - (radius * yn) + endx = centerx + (radius * xn) + endy = centery + (radius * yn) + + -- spawn loop + x = startx + y = starty + xd = d * xn + yd = d * yn + if (xd < 0) and (startx < endx) then x = endx end + if (yd < 0) and (starty < endy) then y = endy end + nsteps = math.floor(math.max(math.abs(startx - endx),math.abs(starty - endy)) / d) + for i = 1, nsteps, 1 do + AddGear(math.floor(x), math.floor(y), gtDrill, 0, speed * xdir, speed * ydir, 0) + nspawned = nspawned + 1 + x = x + xd + y = y + yd + end +end + +function onGearDelete(gear) + if GetGearType(gear) == gtDrill then + if GetTimer(gear) > 0 then + nfailed = nfailed + 1 + end + ndied = ndied + 1 + if ndied == nspawned then + WriteLnToConsole('TESTRESULT: ' .. nfailed .. ' of ' .. nspawned .. ' drill rockets exploded prematurely') + if (nfailed > 0) then + EndLuaTest(TEST_FAILED) + else + EndLuaTest(TEST_SUCCESSFUL) + end + end + end +end + +function onGameStart() + SetGravity(1) + + SpawnDrillRocketArray(taa_h1) + SpawnDrillRocketArray(taa_h2) + SpawnDrillRocketArray(taa_v1) + SpawnDrillRocketArray(taa_v2) + SpawnDrillRocketArray(taa_d1) + SpawnDrillRocketArray(taa_d2) + SpawnDrillRocketArray(taa_d3) + SpawnDrillRocketArray(taa_d4) +end + diff -r 31570b766315 -r ed5a6478e710 tests/lua/hellfire_burns.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/lua/hellfire_burns.lua Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,80 @@ + +local ta_pointsize = 63 +local ta_radius = (ta_pointsize * 10 + 6) / 2 + +local sqrttwo = math.sqrt(2) + +-- creates round test area +function AddTestArea(testarea) + step = 100 + xstep = step * testarea["xdir"] + ystep = step * testarea["ydir"] + x = testarea["x"] + y = testarea["y"] + if xstep * ystep ~= 0 then + xstep = math.floor(xstep / sqrttwo) + ystep = math.floor(ystep / sqrttwo) + end + AddPoint(x, y, ta_pointsize); + AddPoint(x + xstep, y + ystep, ta_pointsize, true); +end + +-- vertical test area +local taa_v2 = {x= 350, y=1500, xdir= 0, ydir=-1} + +-- fail counter +local nfailed = 0 +local nspawned = 0 +local ndied = 0 + +function onGameInit() + -- At first we have to overwrite/set some global variables + -- that define the map, the game has to load, as well as + -- other things such as the game rules to use, etc. + -- Things we don't modify here will use their default values. + + -- The base number for the random number generator + Seed = 1 + -- The map to be played + MapGen = mgDrawn + -- The theme to be used + Theme = "Bamboo" + -- Game settings and rules + EnableGameFlags(gfOneClanMode, gfDisableWind, gfDisableLandObjects, gfDisableGirders) + CaseFreq = 0 + MinesNum = 0 + Explosives = 0 + + -- No damage please + DamagePercent = 1 + + -- Draw Map + AddPoint(10,30,0) -- hog spawn platform + -- test areas + AddTestArea(taa_v2) + + FlushPoints() + + -- Create the player team + AddTeam("'Zooka Team", 14483456, "Simple", "Island", "Default") + -- And add a hog to it + player = AddHog("Hunter", 0, 1, "NoHat") + -- place it on how spawn platform + SetGearPosition(player, 10, 10) +end + +function onNewTurn() + if not TestRectForObstacle(300, 1500, 400, 1900, true) then + WriteLnToConsole('HOLE DETECTED') + EndLuaTest(TEST_SUCCESSFUL) + else + WriteLnToConsole('FIRE DID NOT BURN THROUGH!') + EndLuaTest(TEST_FAILED) + end +end + + +function onGameStart() + AddGear(350, 1500, gtHellishBomb, 0, 0, 0, 0) +end + diff -r 31570b766315 -r ed5a6478e710 tests/lua/luaAPI/gravity_get_set.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/lua/luaAPI/gravity_get_set.lua Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,109 @@ + + +-- * let grenade fall +-- * after a second capture fall distance +-- * change gravity value every second and see if the fall distance in the +-- following second is about what we'd expect it to be + +local spawnX = 10 +local spawnY = -500 + +local defaultG = nil +local currentG = nil + +local defaultDY = nil +local expectedY = nil + +local testGs = nil + +local nFails = 0 + +function onGameInit() + + + -- The base number for the random number generator + Seed = 1 + -- The map to be played + Map = "Ruler" + -- The theme to be used + Theme = "Bamboo" + -- Game settings and rules + EnableGameFlags(gfOneClanMode, gfInvulnerable) + CaseFreq = 0 + MinesNum = 0 + Explosives = 0 + + -- Create the player team + AddTeam("O_o", 14483456, "Simple", "Island", "Default") + -- And add a hog to it + player = AddHog("o_O", 0, 1, "NoHat") + SetGearPosition(player, 100, 100) +end + +local tol = 0 + +function IsKindaSame(a, b) + tol = 1 + math.max(1,math.abs(currentG) / 100) + return (a >= b-tol) and (a <= b+tol) +end + +function SpawnGrenade() + AddGear(spawnX, spawnY, gtGrenade, 0, 0, 0, 1000) +end + +local gIdx = 1 + +function onGearDelete(gear) + if GetGearType(gear) ~= gtGrenade then + return + end + + -- catch initial measuring drop + if defaultDY == nil then + defaultDY = GetY(gear) - spawnY + elseif not IsKindaSame(GetY(gear), expectedY) then + nFails = nFails + 1 + WriteLnToConsole("FAIL: Unexpected Y position! " .. GetY(gear) .. " returned, expected " .. expectedY .. ' (max tolerated difference = ' .. tol .. ')') + else + WriteLnToConsole("Y position OK! " .. GetY(gear) .. " returned, expected " .. expectedY .. ' (max tolerated difference = ' .. tol .. ')') + end + + returnedG = GetGravity() + if (returnedG ~= currentG) then + WriteLnToConsole("GetGravity did not return the value that we used with SetGravity! " .. returnedG .. " returned, expected " .. currentG) + nFails = nFails + 1 + end + + currentG = testGs[gIdx] + gIdx = gIdx + 1 + -- after last test + if currentG == nil then + if (nFails > 0) then + EndLuaTest(TEST_FAILED) + else + EndLuaTest(TEST_SUCCESSFUL) + end + end + + WriteLnToConsole("SetGravity(" .. currentG .. ") ...") + SetGravity(currentG) + + SpawnGrenade() + expectedY = spawnY + math.floor(currentG * defaultDY / 100) +end + +function onGameStart() + currentG = 100 + defaultG = GetGravity() + if (defaultG ~= 100) then + WriteLnToConsole("GetGravity did not return 100 at game start") + nFails = 1 + end + + SpawnGrenade() + + -- for current testing method don't use values over 400 + -- (values > 400 will cause speed cap in under 1 sec) + testGs = {150, 200, 300, 10, 1, 13, 15, 0, 27, -350, -10, nil} +end + diff -r 31570b766315 -r ed5a6478e710 tests/lua/luaAPI/zoom_get_set.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/lua/luaAPI/zoom_get_set.lua Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,68 @@ + +-- This function is called before the game loads its +-- resources. +-- It's one of the predefined function names that will +-- be called by the game. They give you entry points +-- where you're able to call your own code using either +-- provided instructions or custom functions. +function onGameInit() + -- At first we have to overwrite/set some global variables + -- that define the map, the game has to load, as well as + -- other things such as the game rules to use, etc. + -- Things we don't modify here will use their default values. + + -- The base number for the random number generator + Seed = 1 + -- The map to be played + Map = "Bamboo" + -- The theme to be used + Theme = "Bamboo" + -- Game settings and rules + EnableGameFlags(gfOneClanMode) + + -- Create the player team + AddTeam("'Zooka Team", 14483456, "Simple", "Island", "Default") + -- And add a hog to it + player = AddHog("Hunter", 0, 1, "NoHat") + SetGearPosition(player, 936, 136) +end + +-- from lua API wiki: +local minZoom = 1.0; +local maxZoom = 3.0; +local defaultZoom = 2.0; + +local nFails = 0; + +function TestZoom(value) + exp = math.max(minZoom, math.min(maxZoom, value)) + SetZoom(value) + z = GetZoom() + -- compare with some tolerance - because of float inprecision + if (z > exp + 0.01) or (z < exp - 0.01) then + WriteLnToConsole("Expected zoom value " .. exp .. " (after setting go zoom to " .. value .. "), but got: " .. z ) + nFails = nFails + 1 + end +end + +function onGameStart() + if (GetZoom() ~= defaultZoom) then + WriteLnToConsole("Game did not start with zoom level of " .. defaultZoom) + nFails = 1 + end + + TestZoom(0) + TestZoom(1) + TestZoom(0.5) + TestZoom(3.5) + TestZoom(7) + TestZoom(2.0) + TestZoom(2.2) + + if (nFails > 0) then + EndLuaTest(TEST_FAILED) + else + EndLuaTest(TEST_SUCCESSFUL) + end +end + diff -r 31570b766315 -r ed5a6478e710 tests/lua/twothousandmines.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/lua/twothousandmines.lua Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,85 @@ + +local ta_pointsize = 63 +local ta_radius = (ta_pointsize * 10 + 6) / 2 + +local sqrttwo = math.sqrt(2) + +-- creates round test area +function AddTestArea(testarea) + step = 100 + xstep = step * testarea["xdir"] + ystep = step * testarea["ydir"] + x = testarea["x"] + y = testarea["y"] + if xstep * ystep ~= 0 then + xstep = math.floor(xstep / sqrttwo) + ystep = math.floor(ystep / sqrttwo) + end + AddPoint(x, y, ta_pointsize); + AddPoint(x + xstep, y + ystep, ta_pointsize, true); +end + +-- vertical test area +local taa_v2 = {x= 350, y=1500, xdir= 0, ydir=-1} + +-- fail counter +local nfailed = 0 +local nspawned = 0 +local ndied = 0 + +function onGameInit() + -- At first we have to overwrite/set some global variables + -- that define the map, the game has to load, as well as + -- other things such as the game rules to use, etc. + -- Things we don't modify here will use their default values. + + -- The base number for the random number generator + Seed = 1 + -- The map to be played + MapGen = mgDrawn + -- The theme to be used + Theme = "Bamboo" + -- Game settings and rules + EnableGameFlags(gfOneClanMode, gfDisableWind, gfDisableLandObjects, gfDisableGirders, gfSolidLand) + CaseFreq = 0 + MinesNum = 0 + Explosives = 0 + + -- No damage please + DamagePercent = 1 + + -- Draw Map + AddPoint(10,30,0) -- hog spawn platform + -- test areas + AddTestArea(taa_v2) + + FlushPoints() + + -- Create the player team + AddTeam("'Zooka Team", 14483456, "Simple", "Island", "Default") + -- And add a hog to it + player = AddHog("Hunter", 0, 1, "NoHat") + -- place it on how spawn platform + SetGearPosition(player, 10, 10) +end + +local pass = 0 +local nMines = 0 +local maxMines = 2000 + +function onGameStart() + local maxPass = maxMines / 25 + for pass = 1, maxPass, 1 do + pass = pass + 1 + -- spawn 25 mines + for i = 0, 480, 20 do + AddGear(110 + i, 1000 - i - (pass * 30), gtMine, 0, 0, 0, 0) + nMines = nMines + 1 + end + end +end + +function onNewTurn() + WriteLnToConsole('Engine succeessfully dealt with ' .. nMines .. ' mines!') + EndLuaTest(TEST_SUCCESSFUL) +end diff -r 31570b766315 -r ed5a6478e710 tools/CMakeLists.txt --- a/tools/CMakeLists.txt Tue Nov 10 18:16:35 2015 +0100 +++ b/tools/CMakeLists.txt Tue Nov 10 20:43:13 2015 +0100 @@ -1,4 +1,4 @@ -if (NOT APPLE) +if(NOT APPLE) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY) @@ -6,27 +6,20 @@ add_custom_target(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake") endif() -if (APPLE) +if(APPLE AND NOT SKIPBUNDLE) find_package(Qt4 REQUIRED QUIET) - if(${NOSDL2}) - find_package(SDL REQUIRED) - find_package(SDL_image REQUIRED) - find_package(SDL_net REQUIRED) - find_package(SDL_ttf REQUIRED) - find_package(SDL_mixer REQUIRED) - find_package(OggVorbis REQUIRED) - else(${NOSDL2}) - find_package(SDL2 REQUIRED) - find_package(SDL2_image REQUIRED) - find_package(SDL2_net REQUIRED) - find_package(SDL2_ttf REQUIRED) - find_package(SDL2_mixer REQUIRED) - endif(${NOSDL2}) + find_package(SDL2 REQUIRED) + find_package(SDL2_image REQUIRED) + find_package(SDL2_net REQUIRED) + find_package(SDL2_ttf REQUIRED) + find_package(SDL2_mixer REQUIRED) + + find_package(PNG REQUIRED) if(NOT NOAUTOUPDATE) find_package(Sparkle) #needed for SPARKLE_FOUND variable #needed because the 'if' clause in the script prints silly policy warnings - if(${SPARKLE_FOUND}) + if(SPARKLE_FOUND) set(SPARKLE_FOUND 1) else() set(SPARKLE_FOUND 0) @@ -38,12 +31,12 @@ #remove the ";-framework Cocoa" from the SDL_LIBRARY variable string(REGEX REPLACE "(.*);-.*" "\\1" sdl_library_only "${SDL_LIBRARY}") + #remove the "libSDLmain.a" from the SDL_LIBRARY variable + string(REGEX REPLACE ".*;(.*)" "\\1" sdl_library_only "${sdl_library_only}") - if(NOT NOPNG) - #get the neme of the library (harmelss if it is static) - string(REGEX REPLACE ".*/(.*)$" "\\1" PNG_LIBNAME "${PNG_LIBRARY}") - string(REGEX REPLACE ".*/(.*)$" "\\1" ZLIB_LIBNAME "${ZLIB_LIBRARY}") - endif() + #get the neme of the library (harmelss if it is static) + string(REGEX REPLACE ".*/(.*)$" "\\1" PNG_LIBNAME "${PNG_LIBRARY}") + string(REGEX REPLACE ".*/(.*)$" "\\1" ZLIB_LIBNAME "${ZLIB_LIBRARY}") set(frameworks_dir ${CMAKE_INSTALL_PREFIX}/${target_library_install_dir}) if(${BUILD_ENGINE_LIBRARY}) @@ -66,7 +59,7 @@ #create the .dmg for deployment #first make sure .app exists, then remove any old .dmg with same name, finally run the script - add_custom_target(dmg COMMAND if [ ! -a Hedgewars.app ]; then make install\; fi; + add_custom_target(dmg COMMAND make install COMMAND rm -f ${CMAKE_BINARY_DIR}/Hedgewars-${HEDGEWARS_VERSION}.dmg COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/create-dmg.sh --volname "Hedgewars ${HEDGEWARS_VERSION}" diff -r 31570b766315 -r ed5a6478e710 tools/CreateMacBundle.cmake.in --- a/tools/CreateMacBundle.cmake.in Tue Nov 10 18:16:35 2015 +0100 +++ b/tools/CreateMacBundle.cmake.in Tue Nov 10 20:43:13 2015 +0100 @@ -19,16 +19,18 @@ endif() if(doBundle EQUAL 1) - execute_process(COMMAND cp -pPR ${sdl_library_only} ${frameworks_dir}/SDL.framework) - execute_process(COMMAND cp -pPR ${SDLIMAGE_LIBRARY} ${frameworks_dir}/SDL_image.framework) - execute_process(COMMAND cp -pPR ${SDLNET_LIBRARY} ${frameworks_dir}/SDL_net.framework) - execute_process(COMMAND cp -pPR ${SDLTTF_LIBRARY} ${frameworks_dir}/SDL_ttf.framework) - execute_process(COMMAND cp -pPR ${SDLMIXER_LIBRARY} ${frameworks_dir}/SDL_mixer.framework) - execute_process(COMMAND cp -pPR ${OGG_LIBRARY} ${frameworks_dir}/Ogg.framework) - execute_process(COMMAND cp -pPR ${VORBIS_LIBRARY} ${frameworks_dir}/Vorbis.framework) + execute_process(COMMAND cp ${PNG_LIBRARY} ${frameworks_dir}) + + execute_process(COMMAND cp -pPR ${sdl_library_only} ${frameworks_dir}) + execute_process(COMMAND cp -pPR ${SDLIMAGE_LIBRARY} ${frameworks_dir}) + execute_process(COMMAND cp -pPR ${SDLNET_LIBRARY} ${frameworks_dir}) + execute_process(COMMAND cp -pPR ${SDLTTF_LIBRARY} ${frameworks_dir}) + execute_process(COMMAND cp -pPR ${SDLMIXER_LIBRARY} ${frameworks_dir}) + execute_process(COMMAND cp -pPR ${OGG_LIBRARY} ${frameworks_dir}) + execute_process(COMMAND cp -pPR ${VORBIS_LIBRARY} ${frameworks_dir}) if(${SPARKLE_FOUND}) - execute_process(COMMAND cp -pPR ${SPARKLE_LIBRARY} ${frameworks_dir}/Sparkle.framework) + execute_process(COMMAND cp -pPR ${SPARKLE_LIBRARY} ${frameworks_dir}) endif() message(STATUS "Frameworks and libraries successfully copied...") else() diff -r 31570b766315 -r ed5a6478e710 tools/build_windows.bat --- a/tools/build_windows.bat Tue Nov 10 18:16:35 2015 +0100 +++ b/tools/build_windows.bat Tue Nov 10 20:43:13 2015 +0100 @@ -1,65 +1,65 @@ -@echo off -::edit these variables if you need -set PASCAL=C:\FPC\2.6.0\bin\i386-win32\ -set QTDIR=C:\QtSDK\Desktop\Qt\4.7.4\mingw\bin -set PATH=%PATH%;%PASCAL% -set BUILD_TYPE="Debug" - -:setup -set CURRDIR="%CD%" -cd .. - -echo Fetching all DLLs... -if %BUILD_TYPE%=="Debug" ( - for %%G in (QtCored4 QtGuid4 QtNetworkd4) do xcopy /d/y %QTDIR%\%%G.dll %CD%\bin\ -) -:: should you libgcc dynamically you should try adding libgcc_s_dw2-1 and mingwm10 -for %%G in (QtCore4 QtGui4 QtNetwork4) do ( - xcopy /d/y %QTDIR%\%%G.dll %CD%\bin\ -) - -if not exist %CD%\misc\winutils\bin\ mkdir %CD%\misc\winutils\bin\ -if not exist %CD%\misc\winutils\bin\SDL.dll cscript %CD%\tools\w32DownloadUnzip.vbs http://www.libsdl.org/release/SDL-1.2.15-win32.zip %CD%\misc\winutils\bin -if not exist %CD%\misc\winutils\bin\SDL_image.dll cscript %CD%\tools\w32DownloadUnzip.vbs http://www.libsdl.org/projects/SDL_image/release/SDL_image-1.2.12-win32.zip %CD%\misc\winutils\bin -if not exist %CD%\misc\winutils\bin\SDL_net.dll cscript %CD%\tools\w32DownloadUnzip.vbs http://www.libsdl.org/projects/SDL_net/release/SDL_net-1.2.8-win32.zip %CD%\misc\winutils\bin -if not exist %CD%\misc\winutils\bin\SDL_mixer.dll cscript %CD%\tools\w32DownloadUnzip.vbs http://www.libsdl.org/projects/SDL_mixer/release/SDL_mixer-1.2.12-win32.zip %CD%\misc\winutils\bin -if not exist %CD%\misc\winutils\bin\SDL_ttf.dll cscript %CD%\tools\w32DownloadUnzip.vbs http://www.libsdl.org/projects/SDL_ttf/release/SDL_ttf-2.0.11-win32.zip %CD%\misc\winutils\bin - -::for video recording -if not exist %CD%\misc\winutils\bin\avformat-54.dll cscript %CD%\tools\w32DownloadUnzip.vbs http://hedgewars.googlecode.com/files/libav-win32-20121022-dll.zip %CD%\misc\winutils\bin -if not exist %CD%\misc\winutils\bin\glut32.dll cscript %CD%\tools\w32DownloadUnzip.vbs https://user.xmission.com/~nate/glut/glut-3.7.6-bin.zip %CD%\misc\winutils\bin -copy /y %CD%\misc\winutils\bin\glut-3.7.6-bin\glut32.dll %CD%\misc\winutils\bin\glut32.dll - -::this is needed because fpc png unit hardcodes libpng-1.2.12 -if not exist %CD%\misc\winutils\bin\libpng13.dll copy /y %CD%\misc\winutils\bin\libpng15-15.dll %CD%\misc\winutils\bin\libpng13.dll - -xcopy /d/y %CD%\misc\winutils\bin\*.dll %CD%\bin\ - -::setting up the environment... -call %QTDIR%\qtenv2.bat - -echo Running cmake... -set ERRORLEVEL= -cmake . -G "MinGW Makefiles" -DPNG_LIBRARY="%CD%\misc\winutils\bin\libpng13.dll" -DCMAKE_BUILD_TYPE="%BUILD_TYPE%" -DCMAKE_PREFIX_PATH="%CD%\misc\winutils\\" -:: prefix should be last - -if %ERRORLEVEL% NEQ 0 goto exitpoint - -echo Running make... -set ERRORLEVEL= -mingw32-make VERBOSE=1 -if %ERRORLEVEL% NEQ 0 goto exitpoint - -echo Installing... -set ERRORLEVEL= -mingw32-make install > nul -if %ERRORLEVEL% NEQ 0 goto exitpoint - -echo Creating commodity shortcut... -copy /y %CD%\misc\winutils\Hedgewars.lnk C:%HOMEPATH%\Desktop\Hedgewars.lnk - -echo ALL DONE, Hedgewars has been successfully compiled and installed - -:exitpoint -cd %CURRDIR% -pause +@echo off +::edit these variables if you need +set PASCAL=C:\FPC\2.6.0\bin\i386-win32\ +set QTDIR=C:\QtSDK\Desktop\Qt\4.7.4\mingw\bin +set PATH=%PATH%;%PASCAL% +set BUILD_TYPE="Debug" + +:setup +set CURRDIR="%CD%" +cd .. + +echo Fetching all DLLs... +if %BUILD_TYPE%=="Debug" ( + for %%G in (QtCored4 QtGuid4 QtNetworkd4) do xcopy /d/y %QTDIR%\%%G.dll %CD%\bin\ +) +:: should you libgcc dynamically you should try adding libgcc_s_dw2-1 and mingwm10 +for %%G in (QtCore4 QtGui4 QtNetwork4) do ( + xcopy /d/y %QTDIR%\%%G.dll %CD%\bin\ +) + +if not exist %CD%\misc\winutils\bin\ mkdir %CD%\misc\winutils\bin\ +if not exist %CD%\misc\winutils\bin\SDL.dll cscript %CD%\tools\w32DownloadUnzip.vbs http://www.libsdl.org/release/SDL-1.2.15-win32.zip %CD%\misc\winutils\bin +if not exist %CD%\misc\winutils\bin\SDL_image.dll cscript %CD%\tools\w32DownloadUnzip.vbs http://www.libsdl.org/projects/SDL_image/release/SDL_image-1.2.12-win32.zip %CD%\misc\winutils\bin +if not exist %CD%\misc\winutils\bin\SDL_net.dll cscript %CD%\tools\w32DownloadUnzip.vbs http://www.libsdl.org/projects/SDL_net/release/SDL_net-1.2.8-win32.zip %CD%\misc\winutils\bin +if not exist %CD%\misc\winutils\bin\SDL_mixer.dll cscript %CD%\tools\w32DownloadUnzip.vbs http://www.libsdl.org/projects/SDL_mixer/release/SDL_mixer-1.2.12-win32.zip %CD%\misc\winutils\bin +if not exist %CD%\misc\winutils\bin\SDL_ttf.dll cscript %CD%\tools\w32DownloadUnzip.vbs http://www.libsdl.org/projects/SDL_ttf/release/SDL_ttf-2.0.11-win32.zip %CD%\misc\winutils\bin + +::for video recording +if not exist %CD%\misc\winutils\bin\avformat-54.dll cscript %CD%\tools\w32DownloadUnzip.vbs http://hedgewars.googlecode.com/files/libav-win32-20121022-dll.zip %CD%\misc\winutils\bin +if not exist %CD%\misc\winutils\bin\glut32.dll cscript %CD%\tools\w32DownloadUnzip.vbs https://user.xmission.com/~nate/glut/glut-3.7.6-bin.zip %CD%\misc\winutils\bin +copy /y %CD%\misc\winutils\bin\glut-3.7.6-bin\glut32.dll %CD%\misc\winutils\bin\glut32.dll + +::this is needed because fpc png unit hardcodes libpng-1.2.12 +if not exist %CD%\misc\winutils\bin\libpng13.dll copy /y %CD%\misc\winutils\bin\libpng15-15.dll %CD%\misc\winutils\bin\libpng13.dll + +xcopy /d/y %CD%\misc\winutils\bin\*.dll %CD%\bin\ + +::setting up the environment... +call %QTDIR%\qtenv2.bat + +echo Running cmake... +set ERRORLEVEL= +cmake . -G "MinGW Makefiles" -DPNG_LIBRARY="%CD%\misc\winutils\bin\libpng13.dll" -DCMAKE_BUILD_TYPE="%BUILD_TYPE%" -DCMAKE_PREFIX_PATH="%CD%\misc\winutils\\" +:: prefix should be last + +if %ERRORLEVEL% NEQ 0 goto exitpoint + +echo Running make... +set ERRORLEVEL= +mingw32-make VERBOSE=1 +if %ERRORLEVEL% NEQ 0 goto exitpoint + +echo Installing... +set ERRORLEVEL= +mingw32-make install > nul +if %ERRORLEVEL% NEQ 0 goto exitpoint + +echo Creating commodity shortcut... +copy /y %CD%\misc\winutils\Hedgewars.lnk C:%HOMEPATH%\Desktop\Hedgewars.lnk + +echo ALL DONE, Hedgewars has been successfully compiled and installed + +:exitpoint +cd %CURRDIR% +pause diff -r 31570b766315 -r ed5a6478e710 tools/confuse.hs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/confuse.hs Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,41 @@ +{-# LANGUAGE OverloadedStrings #-} +module Confuse where + +import Numeric +import Data.Char +import Control.Monad +import qualified Data.ByteString as B +import qualified Data.ByteString.UTF8 as UTF8 +import qualified Data.Map as Map + +hx :: [Char] -> String +hx cs = let ch = (chr . fst . last . readHex $ cs) in + case ch of + '\'' -> "''" + '\\' -> "\\\\" + c -> c : [] + +conv :: String -> B.ByteString +conv s = B.concat ["('", UTF8.fromString i, "', '", UTF8.fromString r, "')"] + where + i :: String + i = hx s + r :: String + r = concatMap hx . words . takeWhile ((/=) ';') . tail $ dropWhile ((/=) '\t') s + +convRules :: (B.ByteString, [B.ByteString]) -> B.ByteString +convRules (a, b) = B.concat ["", u a, "\n", B.concat $ map u b, ""] + where + u a = B.concat ["\\","u",a] + +toPair :: String -> (B.ByteString, [B.ByteString]) +toPair s = (UTF8.fromString $ takeWhile isHexDigit s, map UTF8.fromString . words . takeWhile ((/=) ';') . tail $ dropWhile ((/=) '\t') s) + + +main = do + ll <- liftM (filter (isHexDigit . head) . filter (not . null) . lines) $ readFile "confusables.txt" + B.writeFile "rules.txt" . B.intercalate "\n" . map convRules . Map.toList . Map.fromList . filter notTooLong . filter fits16bit . map toPair $ ll + where + notTooLong = (>) 6 . length . snd + fits16bit (a, b) = let f = (>) 5 . B.length in all f $ a:b + diff -r 31570b766315 -r ed5a6478e710 tools/darkMagic.hs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/darkMagic.hs Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,159 @@ +module Main where + +import System.Directory +import Control.Monad +import Data.List +import Text.Parsec +import Control.Monad.IO.Class +import Data.Maybe + +data LuaCode = + Comments String + | LuaLocString LuaCode LuaCode + | LuaString String LuaCode + | CodeChunk String LuaCode + | LuaOp String LuaCode + | BlocksList Char [LuaCode] + | NoCode + deriving (Show, Eq) + +toChunk a = CodeChunk a NoCode + +isLuaString LuaLocString{} = True +isLuaString LuaString{} = True +isLuaString _ = False + +isLocString (BlocksList _ blocks) = or $ map isLocString blocks +isLocString LuaLocString{} = True +isLocString (LuaString _ lc) = isLocString lc +isLocString (CodeChunk _ lc) = isLocString lc +isLocString (LuaOp _ lc) = isLocString lc +isLocString _ = False + +many1Till :: (Stream s m t) => ParsecT s u m a -> ParsecT s u m end -> ParsecT s u m [a] +many1Till p end = do + res <- scan + if null res then unexpected "many1Till" else return res + where + scan = do{ end; return [] } + <|> + do{ x <- p; xs <- scan; return (x:xs) } + +processScript :: String -> IO [LuaCode] +processScript fileName = do + r <- runParserT processFile () "" "" + case r of + (Left a) -> do + putStrLn $ "Error: " ++ (show a) + return [] + (Right a) -> return a + + where + processFile = do + --liftIO $ putStrLn $ "Processing: " ++ fileName + f <- liftIO (readFile fileName) + setInput f + process + + comment :: ParsecT String u IO LuaCode + comment = liftM Comments $ choice [ + (try $ string "--[[") >> manyTill anyChar (try $ string "]]") >>= \s -> return $ "--[[" ++ s ++ "]]" + , (try $ string "--") >> manyTill anyChar (try newline) >>= \s -> return $ "--" ++ s ++ "\n" + ] + + stringConcat :: ParsecT String u IO () + stringConcat = try $ string ".." >> spaces + + locString :: ParsecT String u IO LuaCode + locString = do + s <- (try $ optional stringConcat >> string "loc(") >> luaString >>= \s -> char ')' >> return s + subString <- liftM (fromMaybe NoCode) . optionMaybe . try $ spaces >> string ".." >> spaces >> codeBlock + return $ LuaLocString s subString + + luaString :: ParsecT String u IO LuaCode + luaString = do + s <- choice[ + (try $ optional stringConcat >> char '\'') >> many (noneOf "'\n") >>= \s -> char '\'' >> return s + , (try $ optional stringConcat >> char '"') >> many (noneOf "\"\n") >>= \s -> char '"' >> return s + ] + subString <- liftM (fromMaybe NoCode) . optionMaybe . try $ spaces >> string ".." >> spaces >> codeBlock + return $ LuaString s subString + + luaOp :: ParsecT String u IO LuaCode + luaOp = do + s <- many1Till anyChar (lookAhead $ (oneOf "=-.,()[]{}'\"" >> return ()) <|> (try (string "end") >> return ())) + subCode <- liftM (fromMaybe NoCode) . optionMaybe . try $ codeBlock + return $ LuaOp s subCode + + codeBlock :: ParsecT String u IO LuaCode + codeBlock = do + s <- choice [ + comment + , liftM toChunk $ many1 space + , locString + , luaString + , luaOp + , liftM (BlocksList '[') . brackets $ commaSep luaOp + , liftM (BlocksList '{') . braces $ commaSep luaOp + , liftM (BlocksList '(') . parens $ commaSep luaOp + ] + + return s + + brackets = between (char '[') (char ']') + braces = between (char '{') (char '}') + parens = between (char '(') (char ')') + commaSep p = p `sepBy` (char ',') + + otherStuff :: ParsecT String u IO LuaCode + otherStuff = liftM (\s -> CodeChunk s NoCode) $ manyTill anyChar (try $ lookAhead codeBlock) + + process :: ParsecT String u IO [LuaCode] + process = do + codes <- many $ try $ do + a <- otherStuff + b <- liftM (fromMaybe (CodeChunk "" NoCode)) $ optionMaybe $ try codeBlock + return [a, b] + liftIO . putStrLn . unlines . map (renderLua . processLocString) . filter isLocString $ concat codes + return $ concat codes + +listFilesRecursively :: FilePath -> IO [FilePath] +listFilesRecursively dir = do + fs <- liftM (map (\d -> dir ++ ('/' : d)) . filter ((/=) '.' . head)) $ getDirectoryContents dir + dirs <- filterM doesDirectoryExist fs + recfs <- mapM listFilesRecursively dirs + return . concat $ fs : recfs + +renderLua :: LuaCode -> String +renderLua (Comments str) = str +renderLua (LuaLocString lc1 lc2) = let r = renderLua lc2 in "loc(" ++ renderLua lc1 ++ ")" ++ r +renderLua (LuaString str lc) = let r = renderLua lc in "\"" ++ str ++ "\"" ++ r +renderLua (CodeChunk str lc) = str ++ renderLua lc +renderLua (LuaOp str lc) = str ++ renderLua lc +renderLua (BlocksList t lcs) = t : (concat . intersperse "," . map renderLua) lcs ++ [mirror t] +renderLua NoCode = "" + +processLocString :: LuaCode -> LuaCode +processLocString lcode = let (str, params) = pp lcode in + LuaLocString (LuaString str NoCode) + (if null params then NoCode else (CodeChunk ".format" $ BlocksList '(' params)) + where + pp (Comments _) = ("", []) + pp (LuaLocString lc1 lc2) = let (s1, p1) = pp lc1; (s2, p2) = pp lc2 in (s1 ++ s2, p1 ++ p2) + pp (LuaString str lc) = let (s, p) = pp lc in (str ++ s, p) + pp (CodeChunk str lc) = let (s, p) = pp lc in ("%s" ++ s, p) + pp (LuaOp str lc) = let (s, p) = pp lc in ("%s" ++ s, [LuaOp str (head $ p ++ [NoCode])]) + pp (BlocksList t lcs) = ("", [BlocksList t lcs]) + pp NoCode = ("", []) + +mirror '(' = ')' +mirror '[' = ']' +mirror '{' = '}' + +main = do + (l18ns, scripts) <- liftM (partition (isPrefixOf "share/hedgewars/Data/Locale") . filter (isSuffixOf ".lua")) + $ listFilesRecursively "share/hedgewars/Data" + + mapM_ processScript scripts + + --putStrLn $ unlines l18ns \ No newline at end of file diff -r 31570b766315 -r ed5a6478e710 tools/docgen.sh --- a/tools/docgen.sh Tue Nov 10 18:16:35 2015 +0100 +++ b/tools/docgen.sh Tue Nov 10 20:43:13 2015 +0100 @@ -25,10 +25,13 @@ branch=$(hg identify -b) rev=$(hg identify -rdefault -i) -branchurl="${branch}" -revurl="${rev}" +#branchurl="${branch}" +#revurl="${rev}" -export PROJECT_NUMBER="${branchurl} as of ${revurl}" +branchurl="$branch" +revurl="$rev" + +export PROJECT_NUMBER="${branchurl} branch, ${revurl}" export OUTPUT_DIRECTORY fi diff -r 31570b766315 -r ed5a6478e710 tools/hwmap.hs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/hwmap.hs Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,164 @@ +module Main where + +import qualified Data.ByteString.Char8 as B +import qualified Data.ByteString as BW +import qualified Data.ByteString.Lazy as BL +import qualified Codec.Binary.Base64 as Base64 +import Data.Word +import Data.Int +import Data.Binary +import Data.Binary.Put +import Data.Bits +import Control.Monad +import qualified Codec.Compression.Zlib as Z + +data LineType = Solid | Erasing + deriving Eq + +data Chunk = SpecialPoints [(Int16, Int16)] + | Line LineType Word8 [(Int16, Int16)] + +transform :: ((Int16, Int16) -> (Int16, Int16)) -> [Chunk] -> [Chunk] +transform f = map tf + where + tf (SpecialPoints p) = SpecialPoints $ map f p + tf (Line t r p) = Line t r $ map f p + +scale f = transform (\(a, b) -> (a * f, b * f)) +mirror = transform (\(a, b) -> (4095 - a, b)) +flip' = transform (\(a, b) -> (a, 2047 - b)) +translate dx dy = transform (\(a, b) -> (a + dx, b + dy)) + +instance Binary Chunk where + put (SpecialPoints p) = do + forM_ p $ \(x, y) -> do + put x + put y + putWord8 0 + put (Line lt r ((x1, y1):ps)) = do + let flags = r .|. (if lt == Solid then 0 else (1 `shift` 6)) + put x1 + put y1 + putWord8 $ flags .|. (1 `shift` 7) + forM_ ps $ \(x, y) -> do + put x + put y + putWord8 flags + get = undefined + +compressWithLength :: BL.ByteString -> BL.ByteString +compressWithLength b = BL.drop 8 . encode . runPut $ do + put $ ((fromIntegral $ BL.length b)::Word32) + mapM_ putWord8 $ BW.unpack $ BL.toStrict $ Z.compress b + +mapString :: B.ByteString +mapString = B.pack . Base64.encode . BW.unpack . BL.toStrict . compressWithLength . BL.drop 8 . encode $ drawnMap05 + +main = B.writeFile "out.hwmap" mapString + +drawnMap01 = translate (-3) (-3) $ sp ++ mirror sp ++ base ++ mirror base + where + sp = translate 128 128 . scale 256 $ [SpecialPoints [ + (6, 0) + , (1, 4) + , (4, 7) + , (7, 5) + ]] + base = scale 256 $ [ + l [(5, 0), (5, 1)] + , l [(7, 0), (7, 1)] + , l [(8, 1), (6, 1), (6, 4)] + , l [(8, 1), (8, 6), (6, 6), (6, 7), (8, 7)] + , l [(7, 2), (7, 5), (5, 5)] + , l [(5, 3), (5, 8)] + , l [(6, 2), (4, 2)] + , l [(1, 1), (4, 1), (4, 7)] + , l [(3, 5), (3, 7), (2, 7), (2, 8)] + , l [(2, 1), (2, 2)] + , l [(0, 2), (1, 2), (1, 3), (3, 3), (3, 2)] + , l [(0, 5), (1, 5)] + , l [(1, 4), (4, 4)] + , l [(2, 4), (2, 6), (1, 6), (1, 7)] + , l [(0, 8), (8, 8)] + ] + l = Line Solid 0 + +drawnMap02 = translate (-3) (-3) $ sp ++ mirror sp ++ base ++ mirror base + where + sp = translate 128 128 . scale 256 $ [SpecialPoints [ + (7, 0) + , (7, 7) + ]] + base = scale 256 $ [ + l [(8, 0), (8, 1), (1, 1)] + , l [(2, 1), (2, 2), (3, 2), (3, 3), (4, 3), (4, 4), (5, 4), (5, 5), (6, 5), (6, 6), (7, 6), (7, 7), (7, 1)] + , l [(0, 2), (1, 2), (1, 3), (2, 3), (2, 4), (3, 4), (3, 5), (4, 5), (4, 6), (5, 6), (5, 7), (6, 7), (6, 8), (8, 8), (8, 2)] + ] + l = Line Solid 0 + + +drawnMap03 = translate (-3) (-3) $ sp ++ mirror sp ++ base ++ mirror base + where + sp = translate 128 128 . scale 256 $ [SpecialPoints [ + (3, 1) + , (2, 4) + ]] + base = scale 256 $ [ + l [(6, 0), (6, 1)] + , l [(1, 1), (5, 1)] + , l [(4, 1), (4, 2), (3, 2)] + , l [(0, 2), (1, 2), (1, 4)] + , l [(0, 4), (3, 4), (3, 3), (5, 3), (5, 2), (7, 2)] + , l [(7, 1), (7, 3)] + , l [(8, 0), (8, 4), (4, 4), (4, 5), (1, 5), (1, 6)] + , l [(6, 3), (6, 4)] + , l [(0, 8), (8, 8)] + , l [(1, 7), (1, 8)] + , l [(2, 7), (2, 5)] + , l [(3, 6), (3, 5)] + , l [(3, 7), (3, 8)] + , l [(4, 6), (4, 8)] + , l [(5, 4), (5, 6)] + , l [(5, 7), (5, 8)] + , l [(6, 5), (6, 8)] + , l [(7, 4), (7, 6)] + , l [(7, 7), (7, 8)] + , l [(8, 5), (8, 8)] + ] + l = Line Solid 0 + +drawnMap04 = translate (-3) (-3) $ sp ++ fm sp ++ base ++ fm base + where + sp = translate 128 128 . scale 256 $ [SpecialPoints [ + (7, 7) +-- , (6, 6) + , (3, 3) + , (0, 6) + , (3, 6) + ]] + base = scale 256 $ [ + l [(1, 2), (3, 2), (3, 1), (4, 1), (4, 2), (6, 2), (6, 4), (7, 4), (7, 5), (8, 5), (8, 8)] + , l [(0, 0), (16, 0)] + , l [(1, 5), (3, 5), (3, 7), (1, 7), (1, 5)] + , l [(4, 5), (6, 5), (6, 7), (4, 7), (4, 5)] + , l [(0, 4), (2, 4), (2, 3), (5, 3), (5, 4)] + , l [(6, 1), (6, 2), (7, 2)] + , l [(7, 1), (8, 1)] + , l [(7, 3), (8, 3)] + , l [(3, 4), (4, 4)] + , l [(7, 6), (7, 8)] + , l [(2, 0), (2, 1)] + , l [(5, 0), (5, 1)] + ] + l = Line Solid 0 + fm = flip' . mirror + +drawnMap05 = sp ++ fullFill ++ lW + where + w = 320 + sh = 420 + basePoints = [(w, w), (1024 + w `div` 2, 2048 - w), (2048, w), (3072 - w `div` 2, 2048 - w), (4096 - w, w)] + lW = [Line Erasing 60 basePoints] + sp = [SpecialPoints $ basePoints ++ [(1024 + w `div` 2, 2048 - w - sh), (3072 - w `div` 2, 2048 - w - sh), (2048, w + sh)]] + +fullFill = scale 256 $ [Line Solid 63 [(0, 1), (16, 1), (16, 3), (0, 3), (0, 5), (16, 5), (16, 7), (0, 7)]] diff -r 31570b766315 -r ed5a6478e710 tools/hwmap2txt/hwmapconverter/README --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/hwmap2txt/hwmapconverter/README Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,23 @@ + +This tool allows editing the contents of .hwmap files as human-readable text. + + +Dependencies: +------------- + +Needs Qt / qmake to build + + +Instructions: +------------- + +Build with these 2 commands: + +qmake hwmapconverter.pro +make + + +If compiled successfully, run with: + +./hwmapconverter + diff -r 31570b766315 -r ed5a6478e710 tools/hwmap2txt/hwmapconverter/hwmapconverter.pro --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/hwmap2txt/hwmapconverter/hwmapconverter.pro Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,20 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2015-05-07T16:38:43 +# +#------------------------------------------------- + +QT += core gui + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +TARGET = hwmapconverter +TEMPLATE = app + + +SOURCES += main.cpp\ + mainwindow.cpp + +HEADERS += mainwindow.h + +FORMS += mainwindow.ui diff -r 31570b766315 -r ed5a6478e710 tools/hwmap2txt/hwmapconverter/main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/hwmap2txt/hwmapconverter/main.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,11 @@ +#include "mainwindow.h" +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + MainWindow w; + w.show(); + + return a.exec(); +} diff -r 31570b766315 -r ed5a6478e710 tools/hwmap2txt/hwmapconverter/mainwindow.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/hwmap2txt/hwmapconverter/mainwindow.cpp Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,137 @@ +#include +#include +#include +#include +#include + +#include "mainwindow.h" +#include "ui_mainwindow.h" + +MainWindow::MainWindow(QWidget *parent) : + QMainWindow(parent), + ui(new Ui::MainWindow) +{ + ui->setupUi(this); +} + +MainWindow::~MainWindow() +{ + delete ui; +} + +void MainWindow::on_pbLoad_clicked() +{ + QString fileName = QFileDialog::getOpenFileName(this, QString(), QString(), "Hedgewars drawn maps (*.hwmap);;All files (*.*)"); + + if(!fileName.isEmpty()) + { + QFile f(fileName); + + if(f.open(QFile::ReadOnly)) + { + QByteArray data = qUncompress(QByteArray::fromBase64(f.readAll())); + + QStringList decoded; + + bool isSpecial = true; + while(data.size() >= 5) + { + qint16 px = qFromBigEndian(*(qint16 *)data.data()); + data.remove(0, 2); + qint16 py = qFromBigEndian(*(qint16 *)data.data()); + data.remove(0, 2); + quint8 flags = *(quint8 *)data.data(); + data.remove(0, 1); + + if(flags & 0x80) + { + if(isSpecial && !decoded.isEmpty()) + decoded << "// drawings"; + + isSpecial = false; + + quint8 penWidth = flags & 0x3f; + bool isErasing = flags & 0x40; + decoded << QString("%1 %2 %3 %4") + .arg(px, 5).arg(py, 6) + .arg(isErasing ? "e" : "s") + .arg(penWidth, 2); + } else + if(isSpecial) + { + if(decoded.isEmpty()) + decoded << "// special points (these are always before all drawings!)"; + + decoded << QString("%1 %2 %3") + .arg(px, 5).arg(py, 6) + .arg(flags); + } else + { + decoded << QString("%1 %2") + .arg(px, 5).arg(py, 6); + } + } + + ui->textEdit->setPlainText(decoded.join("\n")); + ui->statusBar->showMessage("Load OK"); + } else + ui->statusBar->showMessage(QString("Can't open file %1").arg(fileName)); + } +} + +void MainWindow::on_pbSave_clicked() +{ + QRegExp rxSP("^\\s*(-?\\d+)\\s*(-?\\d+)\\s*(\\d+)\\s*$"); + QRegExp rxLS("^\\s*(-?\\d+)\\s*(-?\\d+)\\s*([es])\\s*(\\d+)\\s*$"); + QRegExp rxP("^\\s*(-?\\d+)\\s*(-?\\d+)\\s*$"); + + QString fileName = QFileDialog::getSaveFileName(this, QString(), QString(), "Hedgewars drawn maps (*.hwmap);;All files (*.*)"); + + QFile file(fileName); + if(file.open(QFile::WriteOnly)) + { + QByteArray b; + QStringList sl = ui->textEdit->toPlainText().split('\n'); + bool isSpecial = true; + + foreach(const QString & line, sl) + if(!line.startsWith("//")) + { + if(rxLS.indexIn(line) != -1) + { + isSpecial = false; + qint16 px = qToBigEndian((qint16)rxLS.cap(1).toInt()); + qint16 py = qToBigEndian((qint16)rxLS.cap(2).toInt()); + quint8 flags = 0x80; + if(rxLS.cap(3) == "e") flags |= 0x40; + flags = flags + rxLS.cap(4).toUInt(); + b.append((const char *)&px, 2); + b.append((const char *)&py, 2); + b.append((const char *)&flags, 1); + } else + if(isSpecial && (rxSP.indexIn(line) != -1)) + { + qint16 px = qToBigEndian((qint16)rxSP.cap(1).toInt()); + qint16 py = qToBigEndian((qint16)rxSP.cap(2).toInt()); + quint8 flags = rxSP.cap(3).toUInt(); + + b.append((const char *)&px, 2); + b.append((const char *)&py, 2); + b.append((const char *)&flags, 1); + } else + if(rxP.indexIn(line) != -1) + { + isSpecial = false; + qint16 px = qToBigEndian((qint16)rxP.cap(1).toInt()); + qint16 py = qToBigEndian((qint16)rxP.cap(2).toInt()); + quint8 flags = 0; + b.append((const char *)&px, 2); + b.append((const char *)&py, 2); + b.append((const char *)&flags, 1); + } else + ui->statusBar->showMessage(QString("Can't parse or misplaced special point: %1").arg(line)); + } + + file.write(qCompress(b).toBase64()); + } +} diff -r 31570b766315 -r ed5a6478e710 tools/hwmap2txt/hwmapconverter/mainwindow.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/hwmap2txt/hwmapconverter/mainwindow.h Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,27 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include + +namespace Ui { +class MainWindow; +} + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + explicit MainWindow(QWidget *parent = 0); + ~MainWindow(); + +private slots: + void on_pbLoad_clicked(); + + void on_pbSave_clicked(); + +private: + Ui::MainWindow *ui; +}; + +#endif // MAINWINDOW_H diff -r 31570b766315 -r ed5a6478e710 tools/hwmap2txt/hwmapconverter/mainwindow.ui --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/hwmap2txt/hwmapconverter/mainwindow.ui Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,62 @@ + + + MainWindow + + + + 0 + 0 + 400 + 300 + + + + MainWindow + + + + + + + Load + + + + + + + Save + + + + + + + Qt::Horizontal + + + + 217 + 20 + + + + + + + + + Liberation Mono + 10 + + + + + + + + + + + + diff -r 31570b766315 -r ed5a6478e710 tools/pas2c/CMakeLists.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/pas2c/CMakeLists.txt Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,31 @@ +find_package(GHC REQUIRED) + +set(pas2c_sources + Main.hs + PascalBasics.hs + PascalParser.hs + PascalPreprocessor.hs + PascalUnitSyntaxTree.hs + Pas2C.hs + ) + +set(pas2c_main ${CMAKE_SOURCE_DIR}/tools/pas2c/Main.hs) + +set(ghc_flags + --make ${pas2c_main} + -i${CMAKE_SOURCE_DIR}/tools/pas2c/ + -o ${EXECUTABLE_OUTPUT_PATH}/pas2c${CMAKE_EXECUTABLE_SUFFIX} + -odir ${CMAKE_CURRENT_BINARY_DIR} + -hidir ${CMAKE_CURRENT_BINARY_DIR} + ${haskell_flags} + ) + +add_custom_command(OUTPUT "${EXECUTABLE_OUTPUT_PATH}/pas2c${CMAKE_EXECUTABLE_SUFFIX}" + COMMAND "${GHC_EXECUTABLE}" + ARGS ${ghc_flags} + MAIN_DEPENDENCY ${hwserv_main} + DEPENDS ${hwserver_sources} + ) + +add_custom_target(pas2c ALL DEPENDS "${EXECUTABLE_OUTPUT_PATH}/pas2c${CMAKE_EXECUTABLE_SUFFIX}") + diff -r 31570b766315 -r ed5a6478e710 tools/pas2c/Main.hs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/pas2c/Main.hs Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,82 @@ +module Main( main ) where + +import System.Console.GetOpt +import System.Environment +import System.Exit +import System.IO +import Data.Maybe( fromMaybe, isJust, fromJust ) +import Data.List (find, intercalate) +import Control.Monad +import Pas2C + +main = do + args <- getArgs + if length args == 0 + then do + name <- getProgName + hPutStrLn stderr $ usageInfo header options + exitFailure + else do + case getOpt RequireOrder options args of + (flags, [], []) | enoughFlags flags -> do + let m = flag flags isName + let i = flag flags isInput + let o = flag flags isOutput + let a = fromMaybe o $ liftM extractString $ find isAlt flags + let symbols = ["PAS2C", "FPC"] ++ (map extractString $ filter isSymbol flags) + hPutStrLn stdout $ "--------Pas2C Config--------" + hPutStrLn stdout $ "Main module: " ++ m + hPutStrLn stdout $ "Input path : " ++ i + hPutStrLn stdout $ "Output path: " ++ o + hPutStrLn stdout $ "Altern path: " ++ a + hPutStrLn stdout $ "Symbols defined: " ++ (intercalate ", " symbols) + hPutStrLn stdout $ "----------------------------" + pas2C m (i++"/") (o++"/") (a++"/") symbols + hPutStrLn stdout $ "----------------------------" + | otherwise -> error $ usageInfo header options + (_, nonOpts, []) -> error $ "unrecognized arguments: " ++ unwords nonOpts + (_, _, msgs) -> error $ usageInfo header options + where + header = "Freepascal to C conversion! Please specify -n -i -o options.\n" + enoughFlags f = and $ map (isJust . flip find f) [isName, isInput, isOutput] + flag f = extractString . fromJust . flip find f + + +data Flag = HelpMessage + | Name String + | Input String + | Output String + | Alternate String + | Symbol String + + +extractString :: Flag -> String +extractString (Name s) = s +extractString (Input s) = s +extractString (Output s) = s +extractString (Alternate s) = s +extractString (Symbol s) = s +extractString _ = undefined + +isName, isInput, isOutput, isAlt, isSymbol :: Flag -> Bool +isName (Name _) = True +isName _ = False +isInput (Input _) = True +isInput _ = False +isOutput (Output _) = True +isOutput _ = False +isAlt (Alternate _) = True +isAlt _ = False +isSymbol (Symbol _) = True +isSymbol _ = False + +options :: [OptDescr Flag] +options = [ + Option ['h'] ["help"] (NoArg HelpMessage) "print this help message", + Option ['n'] ["name"] (ReqArg Name "MAIN") "name of the main Pascal module", + Option ['i'] ["input"] (ReqArg Input "DIR") "input directory, where .pas files will be read", + Option ['o'] ["output"] (ReqArg Output "DIR") "output directory, where .c/.h files will be written", + Option ['a'] ["alternate"] (ReqArg Alternate "DIR") "alternate input directory, for out of source builds", + Option ['d'] ["define"] (ReqArg Symbol "SYMBOL") "define symbol" + ] + diff -r 31570b766315 -r ed5a6478e710 tools/pas2c/Pas2C.hs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/pas2c/Pas2C.hs Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,1243 @@ +{-# LANGUAGE ScopedTypeVariables #-} +module Pas2C where + +import Text.PrettyPrint.HughesPJ +import Data.Maybe +import Data.Char +import Text.Parsec.Prim hiding (State) +import Control.Monad.State +import System.IO +import PascalPreprocessor +import Control.Exception +import System.IO.Error +import qualified Data.Map as Map +import qualified Data.Set as Set +import Data.List (find) +import Numeric + +import PascalParser +import PascalUnitSyntaxTree + + +data InsertOption = + IOInsert + | IOInsertWithType Doc + | IOLookup + | IOLookupLast + | IOLookupFunction Int + | IODeferred + +data Record = Record + { + lcaseId :: String, + baseType :: BaseType, + typeDecl :: Doc + } + deriving Show +type Records = Map.Map String [Record] +data RenderState = RenderState + { + currentScope :: Records, + lastIdentifier :: String, + lastType :: BaseType, + isFunctionType :: Bool, -- set to true if the current function parameter is functiontype + lastIdTypeDecl :: Doc, + stringConsts :: [(String, String)], + uniqCounter :: Int, + toMangle :: Set.Set String, + enums :: [(String, [String])], -- store all declared enums + currentUnit :: String, + currentFunctionResult :: String, + namespaces :: Map.Map String Records + } + +rec2Records :: [(String, BaseType)] -> [Record] +rec2Records = map (\(a, b) -> Record a b empty) + +emptyState :: Map.Map String Records -> RenderState +emptyState = RenderState Map.empty "" BTUnknown False empty [] 0 Set.empty [] "" "" + +getUniq :: State RenderState Int +getUniq = do + i <- gets uniqCounter + modify(\s -> s{uniqCounter = uniqCounter s + 1}) + return i + +addStringConst :: String -> State RenderState Doc +addStringConst str = do + strs <- gets stringConsts + let a = find ((==) str . snd) strs + if isJust a then + do + modify (\s -> s{lastType = BTString}) + return . text . fst . fromJust $ a + else + do + i <- getUniq + let sn = "__str" ++ show i + modify (\s -> s{lastType = BTString, stringConsts = (sn, str) : strs}) + return $ text sn + +escapeStr :: String -> String +escapeStr = foldr escapeChar [] + +escapeChar :: Char -> ShowS +escapeChar '"' s = "\\\"" ++ s +escapeChar '\\' s = "\\\\" ++ s +escapeChar a s = a : s + +strInit :: String -> Doc +strInit a = text "STRINIT" <> parens (doubleQuotes (text $ escapeStr a)) + +renderStringConsts :: State RenderState Doc +renderStringConsts = liftM (vcat . map (\(a, b) -> text "static const string255" <+> (text a) <+> text "=" <+> strInit b <> semi)) + $ gets stringConsts + +docToLower :: Doc -> Doc +docToLower = text . map toLower . render + +pas2C :: String -> String -> String -> String -> [String] -> IO () +pas2C fn inputPath outputPath alternateInputPath symbols = do + s <- flip execStateT initState $ f fn + renderCFiles s outputPath + where + printLn = liftIO . hPutStrLn stdout + print' = liftIO . hPutStr stdout + initState = Map.empty + f :: String -> StateT (Map.Map String PascalUnit) IO () + f fileName = do + processed <- gets $ Map.member fileName + unless processed $ do + print' ("Preprocessing '" ++ fileName ++ ".pas'... ") + fc' <- liftIO + $ tryJust (guard . isDoesNotExistError) + $ preprocess inputPath alternateInputPath (fileName ++ ".pas") symbols + case fc' of + (Left _) -> do + modify (Map.insert fileName (System [])) + printLn "doesn't exist" + (Right fc) -> do + print' "ok, parsing... " + let ptree = parse pascalUnit fileName fc + case ptree of + (Left a) -> do + liftIO $ writeFile (outputPath ++ fileName ++ "preprocess.out") fc + printLn $ show a ++ "\nsee preprocess.out for preprocessed source" + fail "stop" + (Right a) -> do + printLn "ok" + modify (Map.insert fileName a) + mapM_ f (usesFiles a) + + +renderCFiles :: Map.Map String PascalUnit -> String -> IO () +renderCFiles units outputPath = 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) + --writeFile "pas2c.log" $ unlines . map (\t -> show (fst t) ++ "\n" ++ (unlines . map ((:) '\t' . show) . snd $ t)) . Map.toList $ nss + mapM_ (toCFiles outputPath nss) u + where + toNamespace :: Map.Map String Records -> PascalUnit -> Records + toNamespace nss (System tvs) = + currentScope $ execState f (emptyState nss) + where + f = do + checkDuplicateFunDecls tvs + mapM_ (tvar2C True False True False) tvs + toNamespace nss (Redo tvs) = -- functions that are re-implemented, add prefix to all of them + currentScope $ execState f (emptyState nss){currentUnit = "fpcrtl_"} + where + f = do + checkDuplicateFunDecls tvs + mapM_ (tvar2C True False True False) tvs + toNamespace _ (Program {}) = Map.empty + toNamespace nss (Unit (Identifier i _) interface _ _ _) = + currentScope $ execState (interface2C interface True) (emptyState nss){currentUnit = map toLower i ++ "_"} + +withState' :: (RenderState -> RenderState) -> State RenderState a -> State RenderState a +withState' f sf = do + st <- liftM f get + let (a, s) = runState sf st + modify(\st' -> st'{ + lastType = lastType s + , uniqCounter = uniqCounter s + , stringConsts = stringConsts s + }) + return a + +withLastIdNamespace :: State RenderState Doc -> State RenderState Doc +withLastIdNamespace f = do + li <- gets lastIdentifier + withState' (\st -> st{currentScope = fromMaybe Map.empty $ Map.lookup li (namespaces st)}) f + +withRecordNamespace :: String -> [Record] -> State RenderState Doc -> State RenderState Doc +withRecordNamespace _ [] = error "withRecordNamespace: empty record" +withRecordNamespace prefix recs = withState' f + where + f st = st{currentScope = Map.unionWith un records (currentScope st), currentUnit = ""} + records = Map.fromList $ map (\(Record a b d) -> (map toLower a, [Record (prefix ++ a) b d])) recs + un [a] b = a : b + un _ _ = error "withRecordNamespace un: pattern not matched" + +toCFiles :: String -> Map.Map String Records -> (String, PascalUnit) -> IO () +toCFiles _ _ (_, System _) = return () +toCFiles _ _ (_, Redo _) = return () +toCFiles outputPath ns pu@(fileName, _) = do + hPutStrLn stdout $ "Rendering '" ++ fileName ++ "'..." + toCFiles' pu + where + toCFiles' (fn, p@(Program {})) = writeFile (outputPath ++ fn ++ ".c") $ "#include \"fpcrtl.h\"\n" ++ (render2C initialState . pascal2C) p + toCFiles' (fn, (Unit unitId@(Identifier i _) interface implementation _ _)) = do + let (a, s) = runState (id2C IOInsert (setBaseType BTUnit unitId) >> interface2C interface True) initialState{currentUnit = map toLower i ++ "_"} + (a', _) = runState (id2C IOInsert (setBaseType BTUnit unitId) >> interface2C interface False) initialState{currentUnit = map toLower i ++ "_"} + enumDecl = (renderEnum2Strs (enums s) False) + enumImpl = (renderEnum2Strs (enums s) True) + writeFile (outputPath ++ fn ++ ".h") $ "#pragma once\n\n#include \"pas2c.h\"\n\n" ++ (render (a $+$ text "")) ++ "\n" ++ enumDecl + writeFile (outputPath ++ fn ++ ".c") $ "#include \"fpcrtl.h\"\n\n#include \"" ++ fn ++ ".h\"\n" ++ render (a' $+$ text "") ++ (render2C s . implementation2C) implementation ++ "\n" ++ enumImpl + toCFiles' _ = undefined -- just pleasing compiler to not warn us + initialState = emptyState ns + + render2C :: RenderState -> State RenderState Doc -> String + render2C st p = + let (a, _) = runState p st in + render a + +renderEnum2Strs :: [(String, [String])] -> Bool -> String +renderEnum2Strs enums' implement = + render $ foldl ($+$) empty $ map (\en -> let d = decl (fst en) in if implement then d $+$ enum2strBlock (snd en) else d <> semi) enums' + where + decl id' = text "string255 __attribute__((overloadable)) fpcrtl_GetEnumName" <> parens (text "int dummy, const" <+> text id' <+> text "enumvar") + enum2strBlock en = + text "{" + $+$ + (nest 4 $ + text "switch(enumvar){" + $+$ + (foldl ($+$) empty $ map (\e -> text "case" <+> text e <> colon $+$ (nest 4 $ text "return fpcrtl_make_string" <> (parens $ doubleQuotes $ text e) <> semi $+$ text "break;")) en) + $+$ + text "default: assert(0);" + $+$ + (nest 4 $ text "return fpcrtl_make_string(\"nonsense\");") + $+$ + text "}" + ) + $+$ + text "}" + +usesFiles :: PascalUnit -> [String] +usesFiles (Program _ (Implementation uses _) _) = ["pas2cSystem", "pas2cRedo"] ++ uses2List uses +usesFiles (Unit _ (Interface uses1 _) (Implementation uses2 _) _ _) = ["pas2cSystem", "pas2cRedo"] ++ uses2List uses1 ++ uses2List uses2 +usesFiles (System {}) = [] +usesFiles (Redo {}) = [] + +pascal2C :: PascalUnit -> State RenderState Doc +pascal2C (Unit _ interface implementation _ _) = + liftM2 ($+$) (interface2C interface True) (implementation2C implementation) + +pascal2C (Program _ implementation mainFunction) = do + impl <- implementation2C implementation + [main] <- tvar2C True False True True + (FunctionDeclaration (Identifier "main" (BTInt True)) False False False (SimpleType $ Identifier "int" (BTInt True)) + [VarDeclaration False False ([Identifier "argc" (BTInt True)], SimpleType (Identifier "Integer" (BTInt True))) Nothing + , VarDeclaration False False ([Identifier "argv" BTUnknown], SimpleType (Identifier "PPChar" BTUnknown)) Nothing] + (Just (TypesAndVars [], Phrases [mainResultInit, mainFunction]))) + + return $ impl $+$ main + +pascal2C _ = error "pascal2C: pattern not matched" + +-- the second bool indicates whether do normal interface translation or generate variable declarations +-- that will be inserted into implementation files +interface2C :: Interface -> Bool -> State RenderState Doc +interface2C (Interface uses tvars) True = do + u <- uses2C uses + tv <- typesAndVars2C True True True tvars + r <- renderStringConsts + return (u $+$ r $+$ tv) +interface2C (Interface uses tvars) False = do + void $ uses2C uses + tv <- typesAndVars2C True False False tvars + void $ renderStringConsts + return tv + +implementation2C :: Implementation -> State RenderState Doc +implementation2C (Implementation uses tvars) = do + u <- uses2C uses + tv <- typesAndVars2C True False True tvars + r <- renderStringConsts + return (u $+$ r $+$ tv) + +checkDuplicateFunDecls :: [TypeVarDeclaration] -> State RenderState () +checkDuplicateFunDecls tvs = + modify $ \s -> s{toMangle = Map.keysSet . Map.filter (> 1) . foldr ins initMap $ tvs} + where + initMap :: Map.Map String Int + initMap = Map.empty + --initMap = Map.fromList [("reset", 2)] + ins (FunctionDeclaration (Identifier i _) _ _ _ _ _ _) m = Map.insertWith (+) (map toLower i) 1 m + ins _ m = m + +-- the second bool indicates whether declare variable as extern or not +-- the third bool indicates whether include types or not + +typesAndVars2C :: Bool -> Bool -> Bool -> TypesAndVars -> State RenderState Doc +typesAndVars2C b externVar includeType(TypesAndVars ts) = do + checkDuplicateFunDecls ts + liftM (vcat . map (<> semi) . concat) $ mapM (tvar2C b externVar includeType False) ts + +setBaseType :: BaseType -> Identifier -> Identifier +setBaseType bt (Identifier i _) = Identifier i bt + +uses2C :: Uses -> State RenderState Doc +uses2C uses@(Uses unitIds) = do + + mapM_ injectNamespace (Identifier "pas2cSystem" undefined : unitIds) + mapM_ injectNamespace (Identifier "pas2cRedo" undefined : unitIds) + mapM_ (id2C IOInsert . setBaseType BTUnit) unitIds + return $ vcat . map (\i -> text $ "#include \"" ++ i ++ ".h\"") $ uses2List uses + where + injectNamespace (Identifier i _) = do + getNS <- gets (flip Map.lookup . namespaces) + modify (\s -> s{currentScope = Map.unionWith (++) (fromMaybe Map.empty (getNS i)) $ currentScope s}) + +uses2List :: Uses -> [String] +uses2List (Uses ids) = map (\(Identifier i _) -> i) ids + + +setLastIdValues :: Record -> RenderState -> RenderState +setLastIdValues vv = (\s -> s{lastType = baseType vv, lastIdentifier = lcaseId vv, lastIdTypeDecl = typeDecl vv}) + +id2C :: InsertOption -> Identifier -> State RenderState Doc +id2C IOInsert i = id2C (IOInsertWithType empty) i +id2C (IOInsertWithType d) (Identifier i t) = do + tom <- gets (Set.member n . toMangle) + cu <- gets currentUnit + let (i', t') = case (t, tom) of + (BTFunction _ e p _, True) -> ((if e then id else (++) cu) $ i ++ ('_' : show (length p)), t) + (BTFunction _ e _ _, _) -> ((if e then id else (++) cu) i, t) + (BTVarParam t'', _) -> ('(' : '*' : i ++ ")" , t'') + _ -> (i, t) + modify (\s -> s{currentScope = Map.insertWith (++) n [Record i' t' d] (currentScope s), lastIdentifier = n}) + return $ text i' + where + n = map toLower i + +id2C IOLookup i = id2CLookup head i +id2C IOLookupLast i = id2CLookup last i +id2C (IOLookupFunction params) (Identifier i _) = do + let i' = map toLower i + v <- gets $ Map.lookup i' . currentScope + lt <- gets lastType + if isNothing v then + error $ "Not defined: '" ++ i' ++ "'\n" ++ show lt ++ "\nwith num of params = " ++ show params ++ "\n" ++ show v + else + let vv = fromMaybe (head $ fromJust v) . find checkParam $ fromJust v in + modify (setLastIdValues vv) >> (return . text . lcaseId $ vv) + where + checkParam (Record _ (BTFunction _ _ p _) _) = (length p) == params + checkParam _ = False +id2C IODeferred (Identifier i _) = do + let i' = map toLower i + v <- gets $ Map.lookup i' . currentScope + if (isNothing v) then + modify (\s -> s{lastType = BTUnknown, lastIdentifier = i}) >> return (text i) + else + let vv = head $ fromJust v in modify (setLastIdValues vv) >> (return . text . lcaseId $ vv) + +id2CLookup :: ([Record] -> Record) -> Identifier -> State RenderState Doc +id2CLookup f (Identifier i _) = do + let i' = map toLower i + v <- gets $ Map.lookup i' . currentScope + lt <- gets lastType + if isNothing v then + error $ "Not defined: '" ++ i' ++ "'\n" ++ show lt + else + let vv = f $ fromJust v in modify (setLastIdValues vv) >> (return . text . lcaseId $ vv) + + + +id2CTyped :: TypeDecl -> Identifier -> State RenderState Doc +id2CTyped = id2CTyped2 Nothing + +id2CTyped2 :: Maybe Doc -> TypeDecl -> Identifier -> State RenderState Doc +id2CTyped2 md t (Identifier i _) = do + tb <- resolveType t + case (t, tb) of + (_, BTUnknown) -> do + error $ "id2CTyped: type BTUnknown for " ++ show i ++ "\ntype: " ++ show t + (SimpleType {}, BTRecord _ r) -> do + ts <- type2C t + id2C (IOInsertWithType $ ts empty) (Identifier i (BTRecord (render $ ts empty) r)) + (_, BTRecord _ r) -> do + ts <- type2C t + id2C (IOInsertWithType $ ts empty) (Identifier i (BTRecord i r)) + _ -> case md of + Nothing -> id2C IOInsert (Identifier i tb) + Just ts -> id2C (IOInsertWithType ts) (Identifier i tb) + +typeVarDecl2BaseType :: [TypeVarDeclaration] -> State RenderState [(Bool, BaseType)] +typeVarDecl2BaseType d = do + st <- get + result <- sequence $ concat $ map resolveType' d + put st -- restore state (not sure if necessary) + return result + where + resolveType' :: TypeVarDeclaration -> [State RenderState (Bool, BaseType)] + resolveType' (VarDeclaration isVar _ (ids, t) _) = replicate (length ids) (resolveTypeHelper' (resolveType t) isVar) + resolveType' _ = error "typeVarDecl2BaseType: not a VarDeclaration" + resolveTypeHelper' :: State RenderState BaseType -> Bool -> State RenderState (Bool, BaseType) + resolveTypeHelper' st b = do + bt <- st + return (b, bt) + +resolveType :: TypeDecl -> State RenderState BaseType +resolveType st@(SimpleType (Identifier i _)) = do + let i' = map toLower i + v <- gets $ Map.lookup i' . currentScope + if isJust v then return . baseType . head $ fromJust v else return $ f i' + where + f "uinteger" = BTInt False + f "integer" = BTInt True + f "pointer" = BTPointerTo BTVoid + f "boolean" = BTBool + f "float" = BTFloat + f "char" = BTChar + f "string" = BTString + f "ansistring" = BTAString + f _ = error $ "Unknown system type: " ++ show st +resolveType (PointerTo (SimpleType (Identifier i _))) = return . BTPointerTo $ BTUnresolved (map toLower i) +resolveType (PointerTo t) = liftM BTPointerTo $ resolveType t +resolveType (RecordType tv mtvs) = do + tvs <- mapM f (concat $ tv : fromMaybe [] mtvs) + return . BTRecord "" . concat $ tvs + where + f :: TypeVarDeclaration -> State RenderState [(String, BaseType)] + f (VarDeclaration _ _ (ids, td) _) = mapM (\(Identifier i _) -> liftM ((,) i) $ resolveType td) ids + f _ = error "resolveType f: pattern not matched" +resolveType (ArrayDecl (Just i) t) = do + t' <- resolveType t + return $ BTArray i (BTInt True) t' +resolveType (ArrayDecl Nothing t) = liftM (BTArray RangeInfinite (BTInt True)) $ resolveType t +resolveType (FunctionType t a) = do + bts <- typeVarDecl2BaseType a + liftM (BTFunction False False bts) $ resolveType t +resolveType (DeriveType (InitHexNumber _)) = return (BTInt True) +resolveType (DeriveType (InitNumber _)) = return (BTInt True) +resolveType (DeriveType (InitFloat _)) = return BTFloat +resolveType (DeriveType (InitString _)) = return BTString +resolveType (DeriveType (InitBinOp {})) = return (BTInt True) +resolveType (DeriveType (InitPrefixOp _ e)) = initExpr2C e >> gets lastType +resolveType (DeriveType (BuiltInFunction{})) = return (BTInt True) +resolveType (DeriveType (InitReference (Identifier{}))) = return BTBool -- TODO: derive from actual type +resolveType (DeriveType _) = return BTUnknown +resolveType String = return BTString +resolveType AString = return BTAString +resolveType VoidType = return BTVoid +resolveType (Sequence ids) = return $ BTEnum $ map (\(Identifier i _) -> map toLower i) ids +resolveType (RangeType _) = return $ BTVoid +resolveType (Set t) = liftM BTSet $ resolveType t +resolveType (VarParamType t) = liftM BTVarParam $ resolveType t + + +resolve :: String -> BaseType -> State RenderState BaseType +resolve s (BTUnresolved t) = do + v <- gets $ Map.lookup t . currentScope + if isJust v then + resolve s . baseType . head . fromJust $ v + else + error $ "Unknown type " ++ show t ++ "\n" ++ s +resolve _ t = return t + +fromPointer :: String -> BaseType -> State RenderState BaseType +fromPointer s (BTPointerTo t) = resolve s t +fromPointer s t = do + error $ "Dereferencing from non-pointer type " ++ show t ++ "\n" ++ s + + +functionParams2C :: [TypeVarDeclaration] -> State RenderState Doc +functionParams2C params = liftM (hcat . punctuate comma . concat) $ mapM (tvar2C False False True True) params + +numberOfDeclarations :: [TypeVarDeclaration] -> Int +numberOfDeclarations = sum . map cnt + where + cnt (VarDeclaration _ _ (ids, _) _) = length ids + cnt _ = 1 + +hasPassByReference :: [TypeVarDeclaration] -> Bool +hasPassByReference = or . map isVar + where + isVar (VarDeclaration v _ (_, _) _) = v + isVar _ = error $ "hasPassByReference called not on function parameters" + +toIsVarList :: [TypeVarDeclaration] -> [Bool] +toIsVarList = concatMap isVar + where + isVar (VarDeclaration v _ (p, _) _) = replicate (length p) v + isVar _ = error $ "toIsVarList called not on function parameters" + + +funWithVarsToDefine :: String -> [TypeVarDeclaration] -> Doc +funWithVarsToDefine n params = text "#define" <+> text n <> parens abc <+> text (n ++ "__vars") <> parens cparams + where + abc = hcat . punctuate comma . map (char . fst) $ ps + cparams = hcat . punctuate comma . map (\(c, v) -> if v then char '&' <> parens (char c) else char c) $ ps + ps = zip ['a'..] (toIsVarList params) + +fun2C :: Bool -> String -> TypeVarDeclaration -> State RenderState [Doc] +fun2C _ _ (FunctionDeclaration name _ overload external returnType params Nothing) = do + t <- type2C returnType + t'<- gets lastType + bts <- typeVarDecl2BaseType params + p <- withState' id $ functionParams2C params + n <- liftM render . id2C IOInsert $ setBaseType (BTFunction False external bts t') name + let decor = if overload then text "__attribute__((overloadable))" else empty + return [t empty <+> decor <+> text n <> parens p] + +fun2C True rv (FunctionDeclaration name@(Identifier i _) inline overload external returnType params (Just (tvars, phrase))) = do + let isVoid = case returnType of + VoidType -> True + _ -> False + + let res = docToLower $ text rv <> if isVoid then empty else text "_result" + t <- type2C returnType + t' <- gets lastType + + bts <- typeVarDecl2BaseType params + --cu <- gets currentUnit + notDeclared <- liftM isNothing . gets $ Map.lookup (map toLower i) . currentScope + + n <- liftM render . id2C IOInsert $ setBaseType (BTFunction hasVars external bts t') name + let resultId = if isVoid + then n -- void type doesn't have result, solving recursive procedure calls + else (render res) + + (p, ph) <- withState' (\st -> st{currentScope = Map.insertWith un (map toLower rv) [Record resultId (if isVoid then (BTFunction hasVars False bts t') else t') empty] $ currentScope st + , currentFunctionResult = if isVoid then [] else render res}) $ do + p <- functionParams2C params + ph <- liftM2 ($+$) (typesAndVars2C False False True tvars) (phrase2C' phrase) + return (p, ph) + + let isTrivialReturn = case phrase of + (Phrases (BuiltInFunctionCall _ (SimpleReference (Identifier "exit" BTUnknown)) : _)) -> True + _ -> False + let phrasesBlock = if isVoid || isTrivialReturn then ph else t empty <+> res <> semi $+$ ph $+$ text "return" <+> res <> semi + --let define = if hasVars then text "#ifndef" <+> text n $+$ funWithVarsToDefine n params $+$ text "#endif" else empty + let inlineDecor = if inline then case notDeclared of + True -> text "static inline" + False -> text "inline" + else empty + overloadDecor = if overload then text "__attribute__((overloadable))" else empty + return [ + --define + -- $+$ + --(if notDeclared && hasVars then funWithVarsToDefine n params else empty) $+$ + inlineDecor <+> t empty <+> overloadDecor <+> text n <> parens p + $+$ + text "{" + $+$ + nest 4 phrasesBlock + $+$ + text "}"] + where + phrase2C' (Phrases p) = liftM vcat $ mapM phrase2C p + phrase2C' p = phrase2C p + un [a] b = a : b + un _ _ = error "fun2C u: pattern not matched" + hasVars = hasPassByReference params + +fun2C False _ (FunctionDeclaration (Identifier name _) _ _ _ _ _ _) = error $ "nested functions not allowed: " ++ name +fun2C _ tv _ = error $ "fun2C: I don't render " ++ show tv + +-- the second bool indicates whether declare variable as extern or not +-- the third bool indicates whether include types or not +-- the fourth bool indicates whether ignore initialization or not (basically for dynamic arrays since we cannot do initialization in function params) +tvar2C :: Bool -> Bool -> Bool -> Bool -> TypeVarDeclaration -> State RenderState [Doc] +tvar2C b _ includeType _ f@(FunctionDeclaration (Identifier name _) _ _ _ _ _ _) = do + t <- fun2C b name f + if includeType then return t else return [] +tvar2C _ _ includeType _ (TypeDeclaration i' t) = do + i <- id2CTyped t i' + tp <- type2C t + let res = if includeType then [text "typedef" <+> tp i] else [] + case t of + (Sequence ids) -> do + modify(\s -> s{enums = (render i, map (\(Identifier id' _) -> id') ids) : enums s}) + return res + _ -> return res + +tvar2C _ _ _ _ (VarDeclaration True _ (ids, t) Nothing) = do + t' <- liftM ((empty <+>) . ) $ type2C t + liftM (map(\i -> t' i)) $ mapM (id2CTyped2 (Just $ t' empty) (VarParamType t)) ids + +tvar2C _ externVar includeType ignoreInit (VarDeclaration _ isConst (ids, t) mInitExpr) = do + t' <- liftM (((if isConst then text "static const" else if externVar + then text "extern" + else empty) + <+>) . ) $ type2C t + ie <- initExpr mInitExpr + lt <- gets lastType + case (isConst, lt, ids, mInitExpr) of + (True, BTInt _, [i], Just _) -> do + i' <- id2CTyped t i + return $ if includeType then [text "enum" <> braces (i' <+> ie)] else [] + (True, BTFloat, [i], Just e) -> do + i' <- id2CTyped t i + ie' <- initExpr2C e + return $ if includeType then [text "#define" <+> i' <+> parens ie' <> text "\n"] else [] + (_, BTFunction{}, _, Nothing) -> liftM (map(\i -> t' i)) $ mapM (id2CTyped t) ids + (_, BTArray r _ _, [i], _) -> do + i' <- id2CTyped t i + ie' <- return $ case (r, mInitExpr, ignoreInit) of + (RangeInfinite, Nothing, False) -> text "= NULL" -- force dynamic array to be initialized as NULL if not initialized at all + (_, _, _) -> ie + result <- liftM (map(\id' -> varDeclDecision isConst includeType (t' id') ie')) $ mapM (id2CTyped t) ids + case (r, ignoreInit) of + (RangeInfinite, False) -> + -- if the array is dynamic, add dimension info to it + return $ [dimDecl] ++ result + where + arrayDimStr = show $ arrayDimension t + arrayDimInitExp = text ("={" ++ ".dim = " ++ arrayDimStr ++ ", .a = {0, 0, 0, 0}}") + dimDecl = varDeclDecision isConst includeType (text "fpcrtl_dimension_t" <+> i' <> text "_dimension_info") arrayDimInitExp + + (_, _) -> return result + + _ -> liftM (map(\i -> varDeclDecision isConst includeType (t' i) ie)) $ mapM (id2CTyped2 (Just $ t' empty) t) ids + where + initExpr Nothing = return $ empty + initExpr (Just e) = liftM (text "=" <+>) (initExpr2C e) + varDeclDecision True True varStr expStr = varStr <+> expStr + varDeclDecision False True varStr expStr = if externVar then varStr else varStr <+> expStr + varDeclDecision False False varStr expStr = varStr <+> expStr + varDeclDecision True False _ _ = empty + arrayDimension a = case a of + ArrayDecl Nothing t' -> let a' = arrayDimension t' in + if a' > 3 then error "Dynamic array with dimension > 4 is not supported." else 1 + a' + ArrayDecl _ _ -> error "Mixed dynamic array and static array are not supported." + _ -> 0 + +tvar2C f _ _ _ (OperatorDeclaration op (Identifier i _) inline ret params body) = do + r <- op2CTyped op (extractTypes params) + fun2C f i (FunctionDeclaration r inline False False ret params body) + + +op2CTyped :: String -> [TypeDecl] -> State RenderState Identifier +op2CTyped op t = do + t' <- liftM (render . hcat . punctuate (char '_') . map (\txt -> txt empty)) $ mapM type2C t + bt <- gets lastType + return $ Identifier (t' ++ "_op_" ++ opStr) bt + where + opStr = case op of + "+" -> "add" + "-" -> "sub" + "*" -> "mul" + "/" -> "div" + "/(float)" -> "div" + "=" -> "eq" + "<" -> "lt" + ">" -> "gt" + "<>" -> "neq" + _ -> error $ "op2CTyped: unknown op '" ++ op ++ "'" + +extractTypes :: [TypeVarDeclaration] -> [TypeDecl] +extractTypes = concatMap f + where + f (VarDeclaration _ _ (ids, t) _) = replicate (length ids) t + f a = error $ "extractTypes: can't extract from " ++ show a + +initExpr2C, initExpr2C' :: InitExpression -> State RenderState Doc +initExpr2C (InitArray values) = liftM (braces . vcat . punctuate comma) $ mapM initExpr2C values +initExpr2C a = initExpr2C' a +initExpr2C' InitNull = return $ text "NULL" +initExpr2C' (InitAddress expr) = do + ie <- initExpr2C' expr + lt <- gets lastType + case lt of + BTFunction True _ _ _ -> return $ text "&" <> ie -- <> text "__vars" + _ -> return $ text "&" <> ie +initExpr2C' (InitPrefixOp op expr) = liftM (text (op2C op) <>) (initExpr2C' expr) +initExpr2C' (InitBinOp op expr1 expr2) = do + e1 <- initExpr2C' expr1 + e2 <- initExpr2C' expr2 + return $ parens $ e1 <+> text (op2C op) <+> e2 +initExpr2C' (InitNumber s) = do + modify(\st -> st{lastType = (BTInt True)}) + return $ text s +initExpr2C' (InitFloat s) = return $ text s +initExpr2C' (InitHexNumber s) = return $ text "0x" <> (text . map toLower $ s) +initExpr2C' (InitString [a]) = return . quotes $ text [a] +initExpr2C' (InitString s) = return $ strInit s +initExpr2C' (InitPChar s) = return $ doubleQuotes (text $ escapeStr s) +initExpr2C' (InitChar a) = return $ text "0x" <> text (showHex (read a) "") +initExpr2C' (InitReference i) = id2C IOLookup i +initExpr2C' (InitRecord fields) = do + (fs :: [Doc]) <- mapM (\(Identifier a _, b) -> liftM (text "." <> text a <+> equals <+>) $ initExpr2C b) fields + return $ lbrace $+$ (nest 4 . vcat . punctuate comma $ fs) $+$ rbrace +--initExpr2C' (InitArray [InitRecord fields]) = do +-- e <- initExpr2C $ InitRecord fields +-- return $ braces $ e +initExpr2C' r@(InitRange (Range i@(Identifier i' _))) = do + void $ id2C IOLookup i + t <- gets lastType + case t of + BTEnum s -> return . int $ length s + BTInt _ -> case i' of + "byte" -> return $ int 256 + _ -> error $ "InitRange identifier: " ++ i' + _ -> error $ "InitRange: " ++ show r +initExpr2C' (InitRange (RangeFromTo (InitNumber "0") r)) = initExpr2C $ BuiltInFunction "succ" [r] +initExpr2C' (InitRange (RangeFromTo (InitChar "0") (InitChar r))) = initExpr2C $ BuiltInFunction "succ" [InitNumber r] +initExpr2C' (InitRange a) = error $ show a --return $ text "<>" +initExpr2C' (InitSet []) = return $ text "0" +initExpr2C' (InitSet _) = return $ text "<>" +initExpr2C' (BuiltInFunction "low" [InitReference e]) = return $ + case e of + (Identifier "LongInt" _) -> int (-2^31) + (Identifier "SmallInt" _) -> int (-2^15) + _ -> error $ "BuiltInFunction 'low': " ++ show e +initExpr2C' (BuiltInFunction "high" [e]) = do + void $ initExpr2C e + t <- gets lastType + case t of + (BTArray i _ _) -> initExpr2C' $ BuiltInFunction "pred" [InitRange i] + a -> error $ "BuiltInFunction 'high': " ++ show a +initExpr2C' (BuiltInFunction "succ" [BuiltInFunction "pred" [e]]) = initExpr2C' e +initExpr2C' (BuiltInFunction "pred" [BuiltInFunction "succ" [e]]) = initExpr2C' e +initExpr2C' (BuiltInFunction "succ" [e]) = liftM (<> text " + 1") $ initExpr2C' e +initExpr2C' (BuiltInFunction "pred" [e]) = liftM (<> text " - 1") $ initExpr2C' e +initExpr2C' b@(BuiltInFunction _ _) = error $ show b +initExpr2C' (InitTypeCast t' i) = do + e <- initExpr2C i + t <- id2C IOLookup t' + return . parens $ parens t <> e +initExpr2C' a = error $ "initExpr2C: don't know how to render " ++ show a + + +range2C :: InitExpression -> State RenderState [Doc] +range2C (InitString [a]) = return [quotes $ text [a]] +range2C (InitRange (Range i)) = liftM (flip (:) []) $ id2C IOLookup i +range2C (InitRange (RangeFromTo (InitString [a]) (InitString [b]))) = return $ map (\i -> quotes $ text [i]) [a..b] +range2C a = liftM (flip (:) []) $ initExpr2C a + +baseType2C :: String -> BaseType -> Doc +baseType2C _ BTFloat = text "float" +baseType2C _ BTBool = text "bool" +baseType2C _ BTString = text "string255" +baseType2C _ BTAString = text "astring" +baseType2C s a = error $ "baseType2C: " ++ show a ++ "\n" ++ s + +type2C :: TypeDecl -> State RenderState (Doc -> Doc) +type2C (SimpleType i) = liftM (\i' a -> i' <+> a) $ id2C IOLookup i +type2C t = do + r <- type2C' t + rt <- resolveType t + modify (\st -> st{lastType = rt}) + return r + where + type2C' VoidType = return (text "void" <+>) + type2C' String = return (text "string255" <+>)--return (text ("string" ++ show l) <+>) + type2C' AString = return (text "astring" <+>) + type2C' (PointerTo (SimpleType i)) = do + i' <- id2C IODeferred i + lt <- gets lastType + case lt of + BTRecord _ _ -> return $ \a -> text "struct __" <> i' <+> text "*" <+> a + BTUnknown -> return $ \a -> text "struct __" <> i' <+> text "*" <+> a + _ -> return $ \a -> i' <+> text "*" <+> a + type2C' (PointerTo t) = liftM (\tx a -> tx (parens $ text "*" <> a)) $ type2C t + type2C' (RecordType tvs union) = do + t' <- withState' f $ mapM (tvar2C False False True False) tvs + u <- unions + return $ \i -> text "struct __" <> i <+> lbrace $+$ nest 4 ((vcat . map (<> semi) . concat $ t') $$ u) $+$ rbrace <+> i + where + f s = s{currentUnit = ""} + unions = case union of + Nothing -> return empty + Just a -> do + structs <- mapM struct2C a + return $ text "union" $+$ braces (nest 4 $ vcat structs) <> semi + struct2C stvs = do + txts <- withState' f $ mapM (tvar2C False False True False) stvs + return $ text "struct" $+$ braces (nest 4 (vcat . map (<> semi) . concat $ txts)) <> semi + type2C' (RangeType r) = return (text "int" <+>) + type2C' (Sequence ids) = do + is <- mapM (id2C IOInsert . setBaseType bt) ids + return (text "enum" <+> (braces . vcat . punctuate comma . map (\(a, b) -> a <+> equals <+> text "0x" <> text (showHex b "")) $ zip is [0..]) <+>) + where + bt = BTEnum $ map (\(Identifier i _) -> map toLower i) ids + type2C' (ArrayDecl Nothing t) = type2C (PointerTo t) + type2C' (ArrayDecl (Just r) t) = do + t' <- type2C t + lt <- gets lastType + ft <- case lt of + -- BTFunction {} -> type2C (PointerTo t) + _ -> return t' + r' <- initExpr2C (InitRange r) + return $ \i -> ft i <> brackets r' + type2C' (Set t) = return (text "<>" <+>) + type2C' (FunctionType returnType params) = do + t <- type2C returnType + p <- withState' id $ functionParams2C params + return (\i -> (t empty <> (parens $ text "*" <> i) <> parens p)) + type2C' (DeriveType (InitBinOp _ _ i)) = type2C' (DeriveType i) + type2C' (DeriveType (InitPrefixOp _ i)) = type2C' (DeriveType i) + type2C' (DeriveType (InitNumber _)) = return (text "int" <+>) + type2C' (DeriveType (InitHexNumber _)) = return (text "int" <+>) + type2C' (DeriveType (InitFloat _)) = return (text "float" <+>) + type2C' (DeriveType (BuiltInFunction {})) = return (text "int" <+>) + type2C' (DeriveType (InitString {})) = return (text "string255" <+>) + type2C' (DeriveType r@(InitReference {})) = do + initExpr2C r + t <- gets lastType + return (baseType2C (show r) t <+>) + type2C' (DeriveType a) = error $ "Can't derive type from " ++ show a + type2C' a = error $ "type2C: unknown type " ++ show a + +phrase2C :: Phrase -> State RenderState Doc +phrase2C (Phrases p) = do + ps <- mapM phrase2C p + return $ text "{" $+$ (nest 4 . vcat $ ps) $+$ text "}" +phrase2C (ProcCall f@(FunCall {}) []) = liftM (<> semi) $ ref2C f +phrase2C (ProcCall ref []) = liftM (<> semi) $ ref2CF ref True +phrase2C (ProcCall _ _) = error $ "ProcCall"{-do + r <- ref2C ref + ps <- mapM expr2C params + return $ r <> parens (hsep . punctuate (char ',') $ ps) <> semi -} +phrase2C (IfThenElse (expr) phrase1 mphrase2) = do + e <- expr2C expr + p1 <- (phrase2C . wrapPhrase) phrase1 + el <- elsePart + return $ + text "if" <> parens e $+$ p1 $+$ el + where + elsePart | isNothing mphrase2 = return $ empty + | otherwise = liftM (text "else" $$) $ (phrase2C . wrapPhrase) (fromJust mphrase2) +phrase2C asgn@(Assignment ref expr) = do + r <- ref2C ref + t <- gets lastType + case (t, expr) of + (_, Reference r') | ref == r' -> do + e <- ref2C r' + return $ text "UNUSED" <+> parens e <> semi + (BTFunction {}, (Reference r')) -> do + e <- ref2C r' + return $ r <+> text "=" <+> e <> semi + (BTString, _) -> do + void $ expr2C expr + lt <- gets lastType + case lt of + -- assume pointer to char for simplicity + BTPointerTo _ -> do + e <- expr2C $ Reference $ FunCall [Reference $ RefExpression expr] (SimpleReference (Identifier "pchar2str" BTUnknown)) + return $ r <+> text "=" <+> e <> semi + BTAString -> do + e <- expr2C $ Reference $ FunCall [Reference $ RefExpression expr] (SimpleReference (Identifier "astr2str" BTUnknown)) + return $ r <+> text "=" <+> e <> semi + BTString -> do + e <- expr2C expr + return $ r <+> text "=" <+> e <> semi + _ -> error $ "Assignment to string from " ++ show lt ++ "\n" ++ show asgn + (BTAString, _) -> do + void $ expr2C expr + lt <- gets lastType + case lt of + -- assume pointer to char for simplicity + BTPointerTo _ -> do + e <- expr2C $ Reference $ FunCall [Reference $ RefExpression expr] (SimpleReference (Identifier "pchar2astr" BTUnknown)) + return $ r <+> text "=" <+> e <> semi + BTString -> do + e <- expr2C $ Reference $ FunCall [Reference $ RefExpression expr] (SimpleReference (Identifier "str2astr" BTUnknown)) + return $ r <+> text "=" <+> e <> semi + BTAString -> do + e <- expr2C expr + return $ r <+> text "=" <+> e <> semi + _ -> error $ "Assignment to ansistring from " ++ show lt ++ "\n" ++ show asgn + (BTArray _ _ _, _) -> do + case expr of + Reference er -> do + void $ ref2C er + exprT <- gets lastType + case exprT of + BTArray RangeInfinite _ _ -> + return $ text "FIXME: assign a dynamic array to an array" + BTArray _ _ _ -> phrase2C $ + ProcCall (FunCall + [ + Reference $ ref + , Reference $ RefExpression expr + , Reference $ FunCall [expr] (SimpleReference (Identifier "sizeof" BTUnknown)) + ] + (SimpleReference (Identifier "memcpy" BTUnknown)) + ) [] + _ -> return $ text "FIXME: assign a non-specific value to an array" + + _ -> return $ text "FIXME: dynamic array assignment 2" + _ -> do + e <- expr2C expr + return $ r <+> text "=" <+> e <> semi +phrase2C (WhileCycle expr phrase) = do + e <- expr2C expr + p <- phrase2C $ wrapPhrase phrase + return $ text "while" <> parens e $$ p +phrase2C (SwitchCase expr cases mphrase) = do + e <- expr2C expr + cs <- mapM case2C cases + d <- dflt + return $ + text "switch" <> parens e $+$ braces (nest 4 . vcat $ cs ++ d) + where + case2C :: ([InitExpression], Phrase) -> State RenderState Doc + case2C (e, p) = do + ies <- mapM range2C e + ph <- phrase2C p + return $ + vcat (map (\i -> text "case" <+> i <> colon) . concat $ ies) <> nest 4 (ph $+$ text "break;") + dflt | isNothing mphrase = return [text "default: break;"] -- avoid compiler warning + | otherwise = do + ph <- mapM phrase2C $ fromJust mphrase + return [text "default:" <+> nest 4 (vcat ph)] + +phrase2C wb@(WithBlock ref p) = do + r <- ref2C ref + t <- gets lastType + case t of + (BTRecord _ rs) -> withRecordNamespace (render r ++ ".") (rec2Records rs) $ phrase2C $ wrapPhrase p + a -> do + error $ "'with' block referencing non-record type " ++ show a ++ "\n" ++ show wb +phrase2C (ForCycle i' e1' e2' p up) = do + i <- id2C IOLookup i' + iType <- gets lastIdTypeDecl + e1 <- expr2C e1' + e2 <- expr2C e2' + let iEnd = i <> text "__end__" + ph <- phrase2C $ wrapPhrase p + return . braces $ + i <+> text "=" <+> e1 <> semi + $$ + iType <+> iEnd <+> text "=" <+> e2 <> semi + $$ + text "if" <+> (parens $ i <+> text (if up then "<=" else ">=") <+> iEnd) <+> text "do" <+> ph <+> + text "while" <> parens (i <> text (if up then "++" else "--") <+> text "!=" <+> iEnd) <> semi + where + appendPhrase p (Phrases ps) = Phrases $ ps ++ [p] + appendPhrase _ _ = error "illegal appendPhrase call" +phrase2C (RepeatCycle e' p') = do + e <- expr2C e' + p <- phrase2C (Phrases p') + return $ text "do" <+> p <+> text "while" <> parens (text "!" <> parens e) <> semi + +phrase2C NOP = return $ text ";" + +phrase2C (BuiltInFunctionCall [] (SimpleReference (Identifier "exit" BTUnknown))) = do + f <- gets currentFunctionResult + if null f then + return $ text "return" <> semi + else + return $ text "return" <+> text f <> semi +phrase2C (BuiltInFunctionCall [] (SimpleReference (Identifier "break" BTUnknown))) = return $ text "break" <> semi +phrase2C (BuiltInFunctionCall [] (SimpleReference (Identifier "continue" BTUnknown))) = return $ text "continue" <> semi +phrase2C (BuiltInFunctionCall [e] (SimpleReference (Identifier "exit" BTUnknown))) = liftM (\e -> text "return" <+> e <> semi) $ expr2C e +phrase2C (BuiltInFunctionCall [e] (SimpleReference (Identifier "dec" BTUnknown))) = liftM (\e -> text "--" <> e <> semi) $ expr2C e +phrase2C (BuiltInFunctionCall [e1, e2] (SimpleReference (Identifier "dec" BTUnknown))) = liftM2 (\a b -> a <> text " -= " <> b <> semi) (expr2C e1) (expr2C e2) +phrase2C (BuiltInFunctionCall [e] (SimpleReference (Identifier "inc" BTUnknown))) = liftM (\e -> text "++" <> e <> semi) $ expr2C e +phrase2C (BuiltInFunctionCall [e1, e2] (SimpleReference (Identifier "inc" BTUnknown))) = liftM2 (\a b -> a <+> text "+=" <+> b <> semi) (expr2C e1) (expr2C e2) +phrase2C a = error $ "phrase2C: " ++ show a + +wrapPhrase p@(Phrases _) = p +wrapPhrase p = Phrases [p] + +expr2C :: Expression -> State RenderState Doc +expr2C (Expression s) = return $ text s +expr2C bop@(BinOp op expr1 expr2) = do + e1 <- expr2C expr1 + t1 <- gets lastType + e2 <- expr2C expr2 + t2 <- gets lastType + case (op2C op, t1, t2) of + ("+", BTAString, BTAString) -> expr2C $ BuiltInFunCall [expr1, expr2] (SimpleReference $ Identifier "_strconcatA" (fff t1 t2 BTString)) + ("+", BTAString, BTChar) -> expr2C $ BuiltInFunCall [expr1, expr2] (SimpleReference $ Identifier "_strappendA" (fff t1 t2 BTAString)) + ("!=", BTAString, BTAString) -> expr2C $ BuiltInFunCall [expr1, expr2] (SimpleReference $ Identifier "_strncompareA" (fff t1 t2 BTBool)) + (_, BTAString, _) -> error $ "unhandled bin op with ansistring on the left side: " ++ show bop + (_, _, BTAString) -> error $ "unhandled bin op with ansistring on the right side: " ++ show bop + ("+", BTString, BTString) -> expr2C $ BuiltInFunCall [expr1, expr2] (SimpleReference $ Identifier "_strconcat" (fff t1 t2 BTString)) + ("+", BTString, BTChar) -> expr2C $ BuiltInFunCall [expr1, expr2] (SimpleReference $ Identifier "_strappend" (fff t1 t2 BTString)) + ("+", BTChar, BTString) -> expr2C $ BuiltInFunCall [expr1, expr2] (SimpleReference $ Identifier "_strprepend" (fff t1 t2 BTString)) + ("+", BTChar, BTChar) -> expr2C $ BuiltInFunCall [expr1, expr2] (SimpleReference $ Identifier "_chrconcat" (fff t1 t2 BTString)) + ("==", BTString, BTChar) -> expr2C $ BuiltInFunCall [expr1, expr2] (SimpleReference $ Identifier "_strcomparec" (fff t1 t2 BTBool)) + + -- for function/procedure comparision + ("==", BTVoid, _) -> procCompare expr1 expr2 "==" + ("==", BTFunction _ _ _ _, _) -> procCompare expr1 expr2 "==" + + ("!=", BTVoid, _) -> procCompare expr1 expr2 "!=" + ("!=", BTFunction _ _ _ _, _) -> procCompare expr1 expr2 "!=" + + ("==", BTString, BTString) -> expr2C $ BuiltInFunCall [expr1, expr2] (SimpleReference $ Identifier "_strcompare" (fff t1 t2 BTBool)) + ("!=", BTString, _) -> expr2C $ BuiltInFunCall [expr1, expr2] (SimpleReference $ Identifier "_strncompare" (fff t1 t2 BTBool)) + ("&", BTBool, _) -> return $ parens e1 <+> text "&&" <+> parens e2 + ("|", BTBool, _) -> return $ parens e1 <+> text "||" <+> parens e2 + (_, BTRecord t1 _, BTRecord t2 _) -> do + i <- op2CTyped op [SimpleType (Identifier t1 undefined), SimpleType (Identifier t2 undefined)] + ref2C $ FunCall [expr1, expr2] (SimpleReference i) + (_, BTRecord t1 _, BTInt _) -> do + -- aw, "LongInt" here is hwengine-specific hack + i <- op2CTyped op [SimpleType (Identifier t1 undefined), SimpleType (Identifier "LongInt" undefined)] + ref2C $ FunCall [expr1, expr2] (SimpleReference i) + ("in", _, _) -> + case expr2 of + SetExpression set -> do + ids <- mapM (id2C IOLookup) set + modify(\s -> s{lastType = BTBool}) + return . parens . hcat . punctuate (text " || ") . map (\i -> parens $ e1 <+> text "==" <+> i) $ ids + _ -> error "'in' against not set expression" + (o, _, _) | o `elem` boolOps -> do + modify(\s -> s{lastType = BTBool}) + return $ parens e1 <+> text o <+> parens e2 + | otherwise -> do + o' <- return $ case o of + "/(float)" -> text "/(float)" -- pascal returns real value + _ -> text o + e1' <- return $ case (o, t1, t2) of + ("-", BTInt False, BTInt False) -> parens $ text "(int64_t)" <+> parens e1 + _ -> parens e1 + e2' <- return $ case (o, t1, t2) of + ("-", BTInt False, BTInt False) -> parens $ text "(int64_t)" <+> parens e2 + _ -> parens e2 + return $ e1' <+> o' <+> e2' + where + fff t1 t2 = BTFunction False False [(False, t1), (False, t2)] + boolOps = ["==", "!=", "<", ">", "<=", ">="] + procCompare expr1 expr2 op = + case (expr1, expr2) of + (Reference r1, Reference r2) -> do + id1 <- ref2C r1 + id2 <- ref2C r2 + return $ (parens id1) <+> text op <+> (parens id2) + (_, _) -> error $ "Two non reference type vars are compared but they have type of BTVoid or BTFunction\n" ++ show expr1 ++ "\n" ++ show expr2 + +expr2C (NumberLiteral s) = do + modify(\s -> s{lastType = BTInt True}) + return $ text s +expr2C (FloatLiteral s) = return $ text s +expr2C (HexNumber s) = return $ text "0x" <> (text . map toLower $ s) +{-expr2C (StringLiteral [a]) = do + modify(\s -> s{lastType = BTChar}) + return . quotes . text $ escape a + where + escape '\'' = "\\\'" + escape a = [a]-} +expr2C (StringLiteral s) = addStringConst s +expr2C (PCharLiteral s) = return . doubleQuotes $ text s +expr2C (Reference ref) = do + isfunc <- gets isFunctionType + modify(\s -> s{isFunctionType = False}) -- reset + if isfunc then ref2CF ref False else ref2CF ref True +expr2C (PrefixOp op expr) = do + e <- expr2C expr + lt <- gets lastType + case lt of + BTRecord t _ -> do + i <- op2CTyped op [SimpleType (Identifier t undefined)] + ref2C $ FunCall [expr] (SimpleReference i) + BTBool -> do + o <- return $ case op of + "not" -> text "!" + _ -> text (op2C op) + return $ o <> parens e + _ -> return $ text (op2C op) <> parens e +expr2C Null = return $ text "NULL" +expr2C (CharCode a) = do + modify(\s -> s{lastType = BTChar}) + return $ text "0x" <> text (showHex (read a) "") +expr2C (HexCharCode a) = if length a <= 2 then return $ quotes $ text "\\x" <> text (map toLower a) else expr2C $ HexNumber a +expr2C (SetExpression ids) = mapM (id2C IOLookup) ids >>= return . parens . hcat . punctuate (text " | ") + +expr2C (BuiltInFunCall [e] (SimpleReference (Identifier "low" _))) = do + e' <- liftM (map toLower . render) $ expr2C e + lt <- gets lastType + case lt of + BTEnum _-> return $ int 0 + BTInt _ -> case e' of + "longint" -> return $ int (-2147483648) + BTArray {} -> return $ int 0 + _ -> error $ "BuiltInFunCall 'low' from " ++ show e ++ "\ntype: " ++ show lt +expr2C (BuiltInFunCall [e] (SimpleReference (Identifier "high" _))) = do + e' <- liftM (map toLower . render) $ expr2C e + lt <- gets lastType + case lt of + BTEnum a -> return . int $ length a - 1 + BTInt _ -> case e' of + "longint" -> return $ int (2147483647) + BTString -> return $ int 255 + BTArray (RangeFromTo _ n) _ _ -> initExpr2C n + _ -> error $ "BuiltInFunCall 'high' from " ++ show e ++ "\ntype: " ++ show lt +expr2C (BuiltInFunCall [e] (SimpleReference (Identifier "ord" _))) = liftM parens $ expr2C e +expr2C (BuiltInFunCall [e] (SimpleReference (Identifier "succ" _))) = liftM (<> text " + 1") $ expr2C e +expr2C (BuiltInFunCall [e] (SimpleReference (Identifier "pred" _))) = do + e'<- expr2C e + return $ text "(int)" <> parens e' <> text " - 1" +expr2C (BuiltInFunCall [e] (SimpleReference (Identifier "length" _))) = do + e' <- expr2C e + lt <- gets lastType + modify (\s -> s{lastType = BTInt True}) + case lt of + BTString -> return $ text "fpcrtl_Length" <> parens e' + BTAString -> return $ text "fpcrtl_LengthA" <> parens e' + BTArray RangeInfinite _ _ -> error $ "length() called on variable size array " ++ show e' + BTArray (RangeFromTo _ n) _ _ -> initExpr2C (BuiltInFunction "succ" [n]) + _ -> error $ "length() called on " ++ show lt +expr2C (BuiltInFunCall [e, e1, e2] (SimpleReference (Identifier "copy" _))) = do + e1' <- expr2C e1 + e2' <- expr2C e2 + e' <- expr2C e + lt <- gets lastType + let f name = return $ text name <> parens (hsep $ punctuate (char ',') [e', e1', e2']) + case lt of + BTString -> f "fpcrtl_copy" + BTAString -> f "fpcrtl_copyA" + _ -> error $ "copy() called on " ++ show lt + +expr2C (BuiltInFunCall params ref) = do + r <- ref2C ref + t <- gets lastType + ps <- mapM expr2C params + case t of + BTFunction _ _ _ t' -> do + modify (\s -> s{lastType = t'}) + _ -> error $ "BuiltInFunCall lastType: " ++ show t + return $ + r <> parens (hsep . punctuate (char ',') $ ps) +expr2C a = error $ "Don't know how to render " ++ show a + +ref2CF :: Reference -> Bool -> State RenderState Doc +ref2CF (SimpleReference name) addParens = do + i <- id2C IOLookup name + t <- gets lastType + case t of + BTFunction _ _ _ rt -> do + modify(\s -> s{lastType = rt}) + return $ if addParens then i <> parens empty else i --xymeng: removed parens + _ -> return $ i +ref2CF r@(RecordField (SimpleReference _) (SimpleReference _)) addParens = do + i <- ref2C r + t <- gets lastType + case t of + BTFunction _ _ _ rt -> do + modify(\s -> s{lastType = rt}) + return $ if addParens then i <> parens empty else i + _ -> return $ i +ref2CF r _ = ref2C r + +ref2C :: Reference -> State RenderState Doc +-- rewrite into proper form +ref2C (RecordField ref1 (ArrayElement exprs ref2)) = ref2C $ ArrayElement exprs (RecordField ref1 ref2) +ref2C (RecordField ref1 (Dereference ref2)) = ref2C $ Dereference (RecordField ref1 ref2) +ref2C (RecordField ref1 (RecordField ref2 ref3)) = ref2C $ RecordField (RecordField ref1 ref2) ref3 +ref2C (RecordField ref1 (FunCall params ref2)) = ref2C $ FunCall params (RecordField ref1 ref2) +ref2C (ArrayElement (a:b:xs) ref) = ref2C $ ArrayElement (b:xs) (ArrayElement [a] ref) +-- conversion routines +ref2C ae@(ArrayElement [expr] ref) = do + e <- expr2C expr + r <- ref2C ref + t <- gets lastType + case t of + (BTArray _ _ t') -> modify (\st -> st{lastType = t'}) +-- (BTFunctionReturn _ (BTArray _ _ t')) -> modify (\st -> st{lastType = t'}) +-- (BTFunctionReturn _ (BTString)) -> modify (\st -> st{lastType = BTChar}) + BTString -> modify (\st -> st{lastType = BTChar}) + BTAString -> modify (\st -> st{lastType = BTChar}) + (BTPointerTo t) -> do + t'' <- fromPointer (show t) =<< gets lastType + case t'' of + BTChar -> modify (\st -> st{lastType = BTChar}) + a -> error $ "Getting element of " ++ show a ++ "\nReference: " ++ show ae + a -> error $ "Getting element of " ++ show a ++ "\nReference: " ++ show ae + case t of + BTString -> return $ r <> text ".s" <> brackets e + BTAString -> return $ r <> text ".s" <> brackets e + _ -> return $ r <> brackets e +ref2C (SimpleReference name) = id2C IOLookup name +ref2C rf@(RecordField (Dereference ref1) ref2) = do + r1 <- ref2C ref1 + t <- fromPointer (show ref1) =<< gets lastType + r2 <- case t of + BTRecord _ rs -> withRecordNamespace "" (rec2Records rs) $ ref2C ref2 + BTUnit -> error "What??" + a -> error $ "dereferencing from " ++ show a ++ "\n" ++ show rf + return $ + r1 <> text "->" <> r2 +ref2C rf@(RecordField ref1 ref2) = do + r1 <- ref2C ref1 + t <- gets lastType + case t of + BTRecord _ rs -> do + r2 <- withRecordNamespace "" (rec2Records rs) $ ref2C ref2 + return $ r1 <> text "." <> r2 + BTUnit -> withLastIdNamespace $ ref2C ref2 + a -> error $ "dereferencing from " ++ show a ++ "\n" ++ show rf +ref2C d@(Dereference ref) = do + r <- ref2C ref + t <- fromPointer (show d) =<< gets lastType + modify (\st -> st{lastType = t}) + return $ (parens $ text "*" <> r) +ref2C f@(FunCall params ref) = do + r <- fref2C ref + t <- gets lastType + case t of + BTFunction _ _ bts t' -> do + ps <- liftM (parens . hsep . punctuate (char ',')) $ + if (length params) == (length bts) -- hot fix for pas2cSystem and pas2cRedo functions since they don't have params + then + mapM expr2CHelper (zip params bts) + else mapM expr2C params + modify (\s -> s{lastType = t'}) + return $ r <> ps + _ -> case (ref, params) of + (SimpleReference i, [p]) -> ref2C $ TypeCast i p + _ -> error $ "ref2C FunCall erroneous type cast detected: " ++ show f ++ "\nType detected: " ++ show t ++ "\n" ++ show ref ++ "\n" ++ show params ++ "\n" ++ show t + where + fref2C (SimpleReference name) = id2C (IOLookupFunction $ length params) name + fref2C a = ref2C a + expr2CHelper :: (Expression, (Bool, BaseType)) -> State RenderState Doc + expr2CHelper (e, (_, BTFunction _ _ _ _)) = do + modify (\s -> s{isFunctionType = True}) + expr2C e + expr2CHelper (e, (isVar, _)) = if isVar then liftM (((<>) $ text "&") . parens) $ (expr2C e) else expr2C e + +ref2C (Address ref) = do + r <- ref2C ref + lt <- gets lastType + case lt of + BTFunction True _ _ _ -> return $ text "&" <> parens r + _ -> return $ text "&" <> parens r +ref2C (TypeCast t'@(Identifier i _) expr) = do + lt <- expr2C expr >> gets lastType + case (map toLower i, lt) of + ("pchar", BTString) -> ref2C $ FunCall [expr] (SimpleReference (Identifier "_pchar" $ BTPointerTo BTChar)) + ("pchar", BTAString) -> ref2C $ FunCall [expr] (SimpleReference (Identifier "_pcharA" $ BTPointerTo BTChar)) + ("shortstring", BTAString) -> ref2C $ FunCall [expr] (SimpleReference (Identifier "astr2str" $ BTString)) + ("shortstring", BTPointerTo _) -> ref2C $ FunCall [expr] (SimpleReference (Identifier "pchar2str" $ BTString)) + ("ansistring", BTPointerTo _) -> ref2C $ FunCall [expr] (SimpleReference (Identifier "pchar2astr" $ BTAString)) + ("ansistring", BTString) -> ref2C $ FunCall [expr] (SimpleReference (Identifier "str2astr" $ BTAString)) + (a, _) -> do + e <- expr2C expr + t <- id2C IOLookup t' + return . parens $ parens t <> e +ref2C (RefExpression expr) = expr2C expr + + +op2C :: String -> String +op2C "or" = "|" +op2C "and" = "&" +op2C "not" = "~" +op2C "xor" = "^" +op2C "div" = "/" +op2C "mod" = "%" +op2C "shl" = "<<" +op2C "shr" = ">>" +op2C "<>" = "!=" +op2C "=" = "==" +op2C "/" = "/(float)" +op2C a = a + diff -r 31570b766315 -r ed5a6478e710 tools/pas2c/PascalBasics.hs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/pas2c/PascalBasics.hs Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,85 @@ +{-# LANGUAGE FlexibleContexts, NoMonomorphismRestriction #-} +module PascalBasics where + +import Text.Parsec.Combinator +import Text.Parsec.Char +import Text.Parsec.Prim +import Text.Parsec.Token +import Text.Parsec.Language +import Data.Char +import Control.Monad +import Data.Functor.Identity + +char' :: Char -> Parsec String u () +char' = void . char + +string' :: String -> Parsec String u () +string' = void . string + +builtin :: [String] +builtin = ["succ", "pred", "low", "high", "ord", "inc", "dec", "exit", "break", "continue", "length", "copy"] + +pascalLanguageDef :: GenLanguageDef String u Identity +pascalLanguageDef + = emptyDef + { commentStart = "(*" + , commentEnd = "*)" + , commentLine = "//" + , nestedComments = False + , identStart = letter <|> oneOf "_" + , identLetter = alphaNum <|> oneOf "_" + , opLetter = letter + , reservedNames = [ + "begin", "end", "program", "unit", "interface" + , "implementation", "and", "or", "xor", "shl" + , "shr", "while", "do", "repeat", "until", "case", "of" + , "type", "var", "const", "out", "array", "packed" + , "procedure", "function", "with", "for", "to" + , "downto", "div", "mod", "record", "set", "nil" + , "cdecl", "external", "if", "then", "else" + ] -- ++ builtin + , caseSensitive = False + } + +preprocessorSwitch :: Stream String Identity Char => Parsec String u String +preprocessorSwitch = do + try $ string' "{$" + s <- manyTill (noneOf "\n") $ char '}' + return s + +caseInsensitiveString :: Stream String Identity Char => String -> Parsec String u String +caseInsensitiveString s = do + mapM_ (\a -> satisfy (\b -> toUpper a == toUpper b)) s s + return s + +pas :: GenTokenParser String u Identity +pas = patch $ makeTokenParser pascalLanguageDef + where + patch tp = tp {stringLiteral = stringL} + +comment :: Stream String Identity Char => Parsec String u String +comment = choice [ + char '{' >> notFollowedBy (char '$') >> manyTill anyChar (try $ char '}') + , (try $ string "(*") >> manyTill anyChar (try $ string "*)") + , (try $ string "//") >> manyTill anyChar (try newline) + ] + +comments :: Parsec String u () +comments = do + spaces + skipMany $ do + void $ preprocessorSwitch <|> comment + spaces + +stringL :: Parsec String u String +stringL = do + char' '\'' + s <- (many $ noneOf "'") + char' '\'' + ss <- many $ do + char' '\'' + s' <- (many $ noneOf "'") + char' '\'' + return $ '\'' : s' + comments + return $ concat (s:ss) diff -r 31570b766315 -r ed5a6478e710 tools/pas2c/PascalParser.hs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/pas2c/PascalParser.hs Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,723 @@ +module PascalParser ( + pascalUnit, + mainResultInit + ) + where + +import Text.Parsec +import Text.Parsec.Token +import Text.Parsec.Expr +import Control.Monad +import Data.Maybe +import Data.Char + +import PascalBasics +import PascalUnitSyntaxTree + + +mainResultInit :: Phrase +mainResultInit = (\(Right a) -> a) $ parse phrase "" "main:= 0;" + +knownTypes :: [String] +knownTypes = ["shortstring", "ansistring", "char", "byte"] + +pascalUnit :: Parsec String u PascalUnit +pascalUnit = do + comments + u <- choice [program, unit, systemUnit, redoUnit] + comments + return u + +iD :: Parsec String u Identifier +iD = do + i <- identifier pas + comments + when (i == "not") $ unexpected "'not' used as an identifier" + return $ Identifier i BTUnknown + +unit :: Parsec String u PascalUnit +unit = do + string' "unit" >> comments + name <- iD + void $ semi pas + comments + int <- interface + impl <- implementation + comments + return $ Unit name int impl Nothing Nothing + + +reference :: Parsec String u Reference +reference = term "reference" + where + term = comments >> choice [ + parens pas (liftM RefExpression expression >>= postfixes) >>= postfixes + , try $ typeCast >>= postfixes + , char' '@' >> liftM Address reference >>= postfixes + , liftM SimpleReference iD >>= postfixes + ] "simple reference" + + postfixes r = many postfix >>= return . foldl (flip ($)) r + postfix = choice [ + parens pas (option [] parameters) >>= return . FunCall + , char' '^' >> return Dereference + , (brackets pas) (commaSep1 pas $ expression) >>= return . ArrayElement + , (char' '.' >> notFollowedBy (char' '.')) >> liftM (flip RecordField) reference + ] + + typeCast = do + t <- choice $ map (\s -> try $ caseInsensitiveString s >>= \i -> notFollowedBy alphaNum >> return i) knownTypes + e <- parens pas expression + comments + return $ TypeCast (Identifier t BTUnknown) e + +varsDecl1, varsDecl :: Bool -> Parsec String u [TypeVarDeclaration] +varsDecl1 = varsParser sepEndBy1 +varsDecl = varsParser sepEndBy + +varsParser :: + (Parsec String u TypeVarDeclaration + -> Parsec String u String + -> Parsec + String u [TypeVarDeclaration]) + -> Bool + -> Parsec + String u [TypeVarDeclaration] +varsParser m endsWithSemi = do + vs <- m (aVarDecl endsWithSemi) (semi pas) + return vs + +aVarDecl :: Bool -> Parsec String u TypeVarDeclaration +aVarDecl endsWithSemi = do + isVar <- liftM (\i -> i == Just "var" || i == Just "out") $ + if not endsWithSemi then + optionMaybe $ choice [ + try $ string "var" + , try $ string "const" + , try $ string "out" + ] + else + return Nothing + comments + ids <- do + i <- (commaSep1 pas) $ (try iD "variable declaration") + char' ':' + return i + comments + t <- typeDecl "variable type declaration" + comments + initialization <- option Nothing $ do + char' '=' + comments + e <- initExpression + comments + return (Just e) + return $ VarDeclaration isVar False (ids, t) initialization + +constsDecl :: Parsec String u [TypeVarDeclaration] +constsDecl = do + vs <- many1 (try (aConstDecl >>= \i -> semi pas >> return i) >>= \i -> comments >> return i) + comments + return vs + where + aConstDecl = do + comments + i <- iD + t <- optionMaybe $ do + char' ':' + comments + t <- typeDecl + comments + return t + char' '=' + comments + e <- initExpression + comments + return $ VarDeclaration False (isNothing t) ([i], fromMaybe (DeriveType e) t) (Just e) + +typeDecl :: Parsec String u TypeDecl +typeDecl = choice [ + char' '^' >> typeDecl >>= return . PointerTo + , try (string' "shortstring") >> return String + , try (string' "string") >> optionMaybe (brackets pas $ integer pas) >> return String + , try (string' "ansistring") >> optionMaybe (brackets pas $ integer pas) >> return AString + , arrayDecl + , recordDecl + , setDecl + , functionType + , sequenceDecl >>= return . Sequence + , try iD >>= return . SimpleType + , rangeDecl >>= return . RangeType + ] "type declaration" + where + arrayDecl = do + try $ do + optional $ (try $ string' "packed") >> comments + string' "array" + comments + r <- option [] $ do + char' '[' + r <- commaSep pas rangeDecl + char' ']' + comments + return r + string' "of" + comments + t <- typeDecl + if null r then + return $ ArrayDecl Nothing t + else + return $ foldr (\a b -> ArrayDecl (Just a) b) (ArrayDecl (Just $ head r) t) (tail r) + recordDecl = do + try $ do + optional $ (try $ string' "packed") >> comments + string' "record" + comments + vs <- varsDecl True + union <- optionMaybe $ do + string' "case" + comments + void $ iD + comments + string' "of" + comments + many unionCase + string' "end" + return $ RecordType vs union + setDecl = do + try $ string' "set" >> void space + comments + string' "of" + comments + liftM Set typeDecl + unionCase = do + void $ try $ commaSep pas $ (void $ iD) <|> (void $ integer pas) + char' ':' + comments + u <- parens pas $ varsDecl True + char' ';' + comments + return u + sequenceDecl = (parens pas) $ (commaSep pas) (iD >>= \i -> optional (spaces >> char' '=' >> spaces >> integer pas) >> return i) + functionType = do + fp <- try (string "function") <|> try (string "procedure") + comments + vs <- option [] $ parens pas $ varsDecl False + comments + ret <- if (fp == "function") then do + char' ':' + comments + ret <- typeDecl + comments + return ret + else + return VoidType + optional $ try $ char' ';' >> comments >> string' "cdecl" + comments + return $ FunctionType ret vs + +typesDecl :: Parsec String u [TypeVarDeclaration] +typesDecl = many (aTypeDecl >>= \t -> comments >> return t) + where + aTypeDecl = do + i <- try $ do + i <- iD "type declaration" + comments + char' '=' + return i + comments + t <- typeDecl + comments + void $ semi pas + comments + return $ TypeDeclaration i t + +rangeDecl :: Parsec String u Range +rangeDecl = choice [ + try $ rangeft + , iD >>= return . Range + ] "range declaration" + where + rangeft = do + e1 <- initExpression + string' ".." + e2 <- initExpression + return $ RangeFromTo e1 e2 + +typeVarDeclaration :: Bool -> Parsec String u [TypeVarDeclaration] +typeVarDeclaration isImpl = (liftM concat . many . choice) [ + varSection, + constSection, + typeSection, + funcDecl, + operatorDecl + ] + where + + fixInit v = concat $ map (\x -> case x of + VarDeclaration a b (ids, t) c -> + let typeId = (Identifier ((\(Identifier i _) -> i) (head ids) ++ "_tt") BTUnknown) in + let res = [TypeDeclaration typeId t, VarDeclaration a b (ids, (SimpleType typeId)) c] in + case t of + RecordType _ _ -> res -- create a separated type declaration + ArrayDecl _ _ -> res + _ -> [x] + _ -> error ("checkInit:\n" ++ (show v))) v + + varSection = do + try $ string' "var" + comments + v <- varsDecl1 True "variable declaration" + comments + return $ fixInit v + + constSection = do + try $ string' "const" + comments + c <- constsDecl "const declaration" + comments + return $ fixInit c + + typeSection = do + try $ string' "type" + comments + t <- typesDecl "type declaration" + comments + return t + + operatorDecl = do + try $ string' "operator" + comments + i <- manyTill anyChar space + comments + vs <- parens pas $ varsDecl False + comments + rid <- iD + comments + char' ':' + comments + ret <- typeDecl + comments + -- return ret + -- ^^^^^^^^^^ wth was this??? + char' ';' + comments + forward <- liftM isJust $ optionMaybe (try (string' "forward;") >> comments) + inline <- liftM (any (== "inline;")) $ many functionDecorator + b <- if isImpl && (not forward) then + liftM Just functionBody + else + return Nothing + return $ [OperatorDeclaration i rid inline ret vs b] + + + funcDecl = do + fp <- try (string "function") <|> try (string "procedure") + comments + i <- iD + vs <- option [] $ parens pas $ varsDecl False + comments + ret <- if (fp == "function") then do + char' ':' + comments + ret <- typeDecl + comments + return ret + else + return VoidType + char' ';' + comments + forward <- liftM isJust $ optionMaybe (try (string "forward;") >> comments) + decorators <- many functionDecorator + let inline = any (== "inline;") decorators + overload = any (== "overload;") decorators + external = any (== "external;") decorators + -- TODO: don't mangle external functions names (and remove fpcrtl.h defines hacks) + b <- if isImpl && (not forward) && (not external) then + liftM Just functionBody + else + return Nothing + return $ [FunctionDeclaration i inline overload external ret vs b] + + functionDecorator = do + d <- choice [ + try $ string "inline;" + , try $ caseInsensitiveString "cdecl;" + , try $ string "overload;" + , try $ string "export;" + , try $ string "varargs;" + , try (string' "external") >> comments >> iD >> comments >> + optional (string' "name" >> comments >> stringLiteral pas) >> string' ";" >> return "external;" + ] + comments + return d + + +program :: Parsec String u PascalUnit +program = do + string' "program" + comments + name <- iD + (char' ';') + comments + comments + u <- uses + comments + tv <- typeVarDeclaration True + comments + p <- phrase + comments + char' '.' + comments + return $ Program name (Implementation u (TypesAndVars tv)) p + +interface :: Parsec String u Interface +interface = do + string' "interface" + comments + u <- uses + comments + tv <- typeVarDeclaration False + comments + return $ Interface u (TypesAndVars tv) + +implementation :: Parsec String u Implementation +implementation = do + string' "implementation" + comments + u <- uses + comments + tv <- typeVarDeclaration True + string' "end." + comments + return $ Implementation u (TypesAndVars tv) + +expression :: Parsec String u Expression +expression = do + buildExpressionParser table term "expression" + where + term = comments >> choice [ + builtInFunction expression >>= \(n, e) -> return $ BuiltInFunCall e (SimpleReference (Identifier n BTUnknown)) + , try (parens pas expression >>= \e -> notFollowedBy (comments >> char' '.') >> return e) + , brackets pas (commaSep pas iD) >>= return . SetExpression + , try $ integer pas >>= \i -> notFollowedBy (char' '.') >> (return . NumberLiteral . show) i + , float pas >>= return . FloatLiteral . show + , try $ integer pas >>= return . NumberLiteral . show + , try (string' "_S" >> stringLiteral pas) >>= return . StringLiteral + , try (string' "_P" >> stringLiteral pas) >>= return . PCharLiteral + , stringLiteral pas >>= return . strOrChar + , try (string' "#$") >> many hexDigit >>= \c -> comments >> return (HexCharCode c) + , char' '#' >> many digit >>= \c -> comments >> return (CharCode c) + , char' '$' >> many hexDigit >>= \h -> comments >> return (HexNumber h) + --, char' '-' >> expression >>= return . PrefixOp "-" + , char' '-' >> reference >>= return . PrefixOp "-" . Reference + , (try $ string' "not" >> notFollowedBy comments) >> unexpected "'not'" + , try $ string' "nil" >> return Null + , reference >>= return . Reference + ] "simple expression" + + table = [ + [ Prefix (reservedOp pas "not">> return (PrefixOp "not")) + , Prefix (try (char' '-') >> return (PrefixOp "-"))] + , + [ Infix (char' '*' >> return (BinOp "*")) AssocLeft + , Infix (char' '/' >> return (BinOp "/")) AssocLeft + , Infix (try (string' "div") >> return (BinOp "div")) AssocLeft + , Infix (try (string' "mod") >> return (BinOp "mod")) AssocLeft + , Infix (try (string' "in") >> return (BinOp "in")) AssocNone + , Infix (try $ string' "and" >> return (BinOp "and")) AssocLeft + , Infix (try $ string' "shl" >> return (BinOp "shl")) AssocLeft + , Infix (try $ string' "shr" >> return (BinOp "shr")) AssocLeft + ] + , [ Infix (char' '+' >> return (BinOp "+")) AssocLeft + , Infix (char' '-' >> return (BinOp "-")) AssocLeft + , Infix (try $ string' "or" >> return (BinOp "or")) AssocLeft + , Infix (try $ string' "xor" >> return (BinOp "xor")) AssocLeft + ] + , [ Infix (try (string' "<>") >> return (BinOp "<>")) AssocNone + , Infix (try (string' "<=") >> return (BinOp "<=")) AssocNone + , Infix (try (string' ">=") >> return (BinOp ">=")) AssocNone + , Infix (char' '<' >> return (BinOp "<")) AssocNone + , Infix (char' '>' >> return (BinOp ">")) AssocNone + ] + {-, [ Infix (try $ string' "shl" >> return (BinOp "shl")) AssocNone + , Infix (try $ string' "shr" >> return (BinOp "shr")) AssocNone + ] + , [ + Infix (try $ string' "or" >> return (BinOp "or")) AssocLeft + , Infix (try $ string' "xor" >> return (BinOp "xor")) AssocLeft + ]-} + , [ + Infix (char' '=' >> return (BinOp "=")) AssocNone + ] + ] + strOrChar [a] = CharCode . show . ord $ a + strOrChar a = StringLiteral a + +phrasesBlock :: Parsec String u Phrase +phrasesBlock = do + try $ string' "begin" + comments + p <- manyTill phrase (try $ string' "end" >> notFollowedBy alphaNum) + comments + return $ Phrases p + +phrase :: Parsec String u Phrase +phrase = do + o <- choice [ + phrasesBlock + , ifBlock + , whileCycle + , repeatCycle + , switchCase + , withBlock + , forCycle + , (try $ reference >>= \r -> string' ":=" >> return r) >>= \r -> comments >> expression >>= return . Assignment r + , builtInFunction expression >>= \(n, e) -> return $ BuiltInFunctionCall e (SimpleReference (Identifier n BTUnknown)) + , procCall + , char' ';' >> comments >> return NOP + ] + optional $ char' ';' + comments + return o + +ifBlock :: Parsec String u Phrase +ifBlock = do + try $ string "if" >> notFollowedBy (alphaNum <|> char '_') + comments + e <- expression + comments + string' "then" + comments + o1 <- phrase + comments + o2 <- optionMaybe $ do + try $ string' "else" >> void space + comments + o <- option NOP phrase + comments + return o + return $ IfThenElse e o1 o2 + +whileCycle :: Parsec String u Phrase +whileCycle = do + try $ string' "while" + comments + e <- expression + comments + string' "do" + comments + o <- phrase + return $ WhileCycle e o + +withBlock :: Parsec String u Phrase +withBlock = do + try $ string' "with" >> void space + comments + rs <- (commaSep1 pas) reference + comments + string' "do" + comments + o <- phrase + return $ foldr WithBlock o rs + +repeatCycle :: Parsec String u Phrase +repeatCycle = do + try $ string' "repeat" >> void space + comments + o <- many phrase + string' "until" + comments + e <- expression + comments + return $ RepeatCycle e o + +forCycle :: Parsec String u Phrase +forCycle = do + try $ string' "for" >> void space + comments + i <- iD + comments + string' ":=" + comments + e1 <- expression + comments + up <- liftM (== Just "to") $ + optionMaybe $ choice [ + try $ string "to" + , try $ string "downto" + ] + --choice [string' "to", string' "downto"] + comments + e2 <- expression + comments + string' "do" + comments + p <- phrase + comments + return $ ForCycle i e1 e2 p up + +switchCase :: Parsec String u Phrase +switchCase = do + try $ string' "case" + comments + e <- expression + comments + string' "of" + comments + cs <- many1 aCase + o2 <- optionMaybe $ do + try $ string' "else" >> notFollowedBy alphaNum + comments + o <- many phrase + comments + return o + string' "end" + comments + return $ SwitchCase e cs o2 + where + aCase = do + e <- (commaSep pas) $ (liftM InitRange rangeDecl <|> initExpression) + comments + char' ':' + comments + p <- phrase + comments + return (e, p) + +procCall :: Parsec String u Phrase +procCall = do + r <- reference + p <- option [] $ (parens pas) parameters + return $ ProcCall r p + +parameters :: Parsec String u [Expression] +parameters = (commaSep pas) expression "parameters" + +functionBody :: Parsec String u (TypesAndVars, Phrase) +functionBody = do + tv <- typeVarDeclaration True + comments + p <- phrasesBlock + char' ';' + comments + return (TypesAndVars tv, p) + +uses :: Parsec String u Uses +uses = liftM Uses (option [] u) + where + u = do + string' "uses" + comments + ulist <- (iD >>= \i -> comments >> return i) `sepBy1` (char' ',' >> comments) + char' ';' + comments + return ulist + +initExpression :: Parsec String u InitExpression +initExpression = buildExpressionParser table term "initialization expression" + where + term = comments >> choice [ + liftM (uncurry BuiltInFunction) $ builtInFunction initExpression + , try $ brackets pas (commaSep pas $ initExpression) >>= return . InitSet + , try $ parens pas (commaSep pas $ initExpression) >>= \ia -> when ((notRecord $ head ia) && (null $ tail ia)) mzero >> return (InitArray ia) + , try $ parens pas (sepEndBy recField (char' ';' >> comments)) >>= return . InitRecord + , parens pas initExpression + , try $ integer pas >>= \i -> notFollowedBy (char' '.') >> (return . InitNumber . show) i + , try $ float pas >>= return . InitFloat . show + , try $ integer pas >>= return . InitNumber . show + , try (string' "_S" >> stringLiteral pas) >>= return . InitString + , try (string' "_P" >> stringLiteral pas) >>= return . InitPChar + , stringLiteral pas >>= return . InitString + , char' '#' >> many digit >>= \c -> comments >> return (InitChar c) + , char' '$' >> many hexDigit >>= \h -> comments >> return (InitHexNumber h) + , char' '@' >> initExpression >>= \c -> comments >> return (InitAddress c) + , try $ string' "nil" >> return InitNull + , try itypeCast + , iD >>= return . InitReference + ] + + notRecord (InitRecord _) = False + notRecord _ = True + + recField = do + i <- iD + spaces + char' ':' + spaces + e <- initExpression + spaces + return (i ,e) + + table = [ + [ + Prefix (char' '-' >> return (InitPrefixOp "-")) + ,Prefix (try (string' "not") >> return (InitPrefixOp "not")) + ] + , [ Infix (char' '*' >> return (InitBinOp "*")) AssocLeft + , Infix (char' '/' >> return (InitBinOp "/")) AssocLeft + , Infix (try (string' "div") >> return (InitBinOp "div")) AssocLeft + , Infix (try (string' "mod") >> return (InitBinOp "mod")) AssocLeft + , Infix (try $ string' "and" >> return (InitBinOp "and")) AssocLeft + , Infix (try $ string' "shl" >> return (InitBinOp "shl")) AssocNone + , Infix (try $ string' "shr" >> return (InitBinOp "shr")) AssocNone + ] + , [ Infix (char' '+' >> return (InitBinOp "+")) AssocLeft + , Infix (char' '-' >> return (InitBinOp "-")) AssocLeft + , Infix (try $ string' "or" >> return (InitBinOp "or")) AssocLeft + , Infix (try $ string' "xor" >> return (InitBinOp "xor")) AssocLeft + ] + , [ Infix (try (string' "<>") >> return (InitBinOp "<>")) AssocNone + , Infix (try (string' "<=") >> return (InitBinOp "<=")) AssocNone + , Infix (try (string' ">=") >> return (InitBinOp ">=")) AssocNone + , Infix (char' '<' >> return (InitBinOp "<")) AssocNone + , Infix (char' '>' >> return (InitBinOp ">")) AssocNone + , Infix (char' '=' >> return (InitBinOp "=")) AssocNone + ] + {--, [ Infix (try $ string' "and" >> return (InitBinOp "and")) AssocLeft + , Infix (try $ string' "or" >> return (InitBinOp "or")) AssocLeft + , Infix (try $ string' "xor" >> return (InitBinOp "xor")) AssocLeft + ] + , [ Infix (try $ string' "shl" >> return (InitBinOp "shl")) AssocNone + , Infix (try $ string' "shr" >> return (InitBinOp "shr")) AssocNone + ]--} + --, [Prefix (try (string' "not") >> return (InitPrefixOp "not"))] + ] + + itypeCast = do + --t <- choice $ map (\s -> try $ caseInsensitiveString s >>= \i -> notFollowedBy alphaNum >> return i) knownTypes + t <- iD + i <- parens pas initExpression + comments + return $ InitTypeCast t i + +builtInFunction :: Parsec String u a -> Parsec String u (String, [a]) +builtInFunction e = do + name <- choice $ map (\s -> try $ caseInsensitiveString s >>= \i -> notFollowedBy alphaNum >> return i) builtin + spaces + exprs <- option [] $ parens pas $ option [] $ commaSep1 pas $ e + spaces + return (name, exprs) + +systemUnit :: Parsec String u PascalUnit +systemUnit = do + string' "system;" + comments + string' "type" + comments + t <- typesDecl + string' "var" + v <- varsDecl True + return $ System (t ++ v) + +redoUnit :: Parsec String u PascalUnit +redoUnit = do + string' "redo;" + comments + string' "type" + comments + t <- typesDecl + string' "var" + v <- varsDecl True + return $ Redo (t ++ v) + diff -r 31570b766315 -r ed5a6478e710 tools/pas2c/PascalPreprocessor.hs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/pas2c/PascalPreprocessor.hs Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,138 @@ +{-# LANGUAGE ScopedTypeVariables #-} +module PascalPreprocessor where + +import Text.Parsec +import Control.Monad.IO.Class +import Control.Monad +import System.IO +import qualified Data.Map as Map +import qualified Control.Exception as E + +char' :: Char -> ParsecT String u IO () +char' = void . char + +string' :: String -> ParsecT String u IO () +string' = void . string + +-- comments are removed +comment :: ParsecT String u IO String +comment = choice [ + char '{' >> notFollowedBy (char '$') >> manyTill anyChar (try $ char '}') >> return "" + , (try $ string "(*") >> manyTill anyChar (try $ string "*)") >> return "" + , (try $ string "//") >> manyTill anyChar (try newline) >> return "\n" + ] + +preprocess :: String -> String -> String -> [String] -> IO String +preprocess inputPath alternateInputPath fn symbols = do + r <- runParserT (preprocessFile (inputPath ++ fn)) (Map.fromList $ map (\s -> (s, "")) symbols, [True]) "" "" + case r of + (Left a) -> do + hPutStrLn stderr (show a) + return "" + (Right a) -> return a + + where + preprocessFile fn' = do + f <- liftIO (readFile fn') + setInput f + preprocessor + + preprocessor, codeBlock, switch :: ParsecT String (Map.Map String String, [Bool]) IO String + + preprocessor = chainr codeBlock (return (++)) "" + + codeBlock = do + s <- choice [ + switch + , comment + , char '\'' >> many (noneOf "'\n") >>= \s -> char '\'' >> return ('\'' : s ++ "'") + , identifier >>= replace + , noneOf "{" >>= \a -> return [a] + ] + (_, ok) <- getState + return $ if and ok then s else "" + + --otherChar c = c `notElem` "{/('_" && not (isAlphaNum c) + identifier = do + c <- letter <|> oneOf "_" + s <- many (alphaNum <|> oneOf "_") + return $ c:s + + switch = do + try $ string' "{$" + s <- choice [ + include + , ifdef + , if' + , elseSwitch + , endIf + , define + , unknown + ] + return s + + include = do + try $ string' "INCLUDE" + spaces + (char' '"') + ifn <- many1 $ noneOf "\"\n" + char' '"' + spaces + char' '}' + f <- liftIO (readFile (inputPath ++ ifn) + `E.catch` (\(_ :: E.IOException) -> readFile (alternateInputPath ++ ifn) + `E.catch` (\(_ :: E.IOException) -> error $ "File not found: " ++ ifn) + ) + ) + c <- getInput + setInput $ f ++ c + return "" + + ifdef = do + s <- try (string "IFDEF") <|> try (string "IFNDEF") + let f = if s == "IFNDEF" then not else id + + ds <- (spaces >> identifier) `sepBy` (spaces >> string "OR") + spaces + char' '}' + + updateState $ \(m, b) -> + (m, (f $ any (flip Map.member m) ds) : b) + + return "" + + if' = do + try (string' "IF" >> notFollowedBy alphaNum) + + void $ manyTill anyChar (char' '}') + --char '}' + + updateState $ \(m, b) -> + (m, False : b) + + return "" + + elseSwitch = do + try $ string' "ELSE}" + updateState $ \(m, b:bs) -> (m, (not b):bs) + return "" + endIf = do + try $ string' "ENDIF}" + updateState $ \(m, _:bs) -> (m, bs) + return "" + define = do + try $ string' "DEFINE" + spaces + i <- identifier + d <- ((string ":=" >> return ()) <|> spaces) >> many (noneOf "}") + char' '}' + updateState $ \(m, b) -> (if (and b) && (head i /= '_') then Map.insert i d m else m, b) + return "" + replace s = do + (m, _) <- getState + return $ Map.findWithDefault s s m + + unknown = do + un <- many1 $ noneOf "}\n" + char' '}' + return $ "{$" ++ un ++ "}" diff -r 31570b766315 -r ed5a6478e710 tools/pas2c/PascalUnitSyntaxTree.hs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/pas2c/PascalUnitSyntaxTree.hs Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,119 @@ +module PascalUnitSyntaxTree where + +data PascalUnit = + Program Identifier Implementation Phrase + | Unit Identifier Interface Implementation (Maybe Initialize) (Maybe Finalize) + | System [TypeVarDeclaration] + | Redo [TypeVarDeclaration] + deriving (Show, Eq) +data Interface = Interface Uses TypesAndVars + deriving (Show, Eq) +data Implementation = Implementation Uses TypesAndVars + deriving (Show, Eq) +data Identifier = Identifier String BaseType + deriving (Show, Eq) +data TypesAndVars = TypesAndVars [TypeVarDeclaration] + deriving (Show, Eq) +data TypeVarDeclaration = TypeDeclaration Identifier TypeDecl + | VarDeclaration Bool Bool ([Identifier], TypeDecl) (Maybe InitExpression) + | FunctionDeclaration Identifier Bool Bool Bool TypeDecl [TypeVarDeclaration] (Maybe (TypesAndVars, Phrase)) + | OperatorDeclaration String Identifier Bool TypeDecl [TypeVarDeclaration] (Maybe (TypesAndVars, Phrase)) + deriving (Show, Eq) +data TypeDecl = SimpleType Identifier + | RangeType Range + | Sequence [Identifier] + | ArrayDecl (Maybe Range) TypeDecl + | RecordType [TypeVarDeclaration] (Maybe [[TypeVarDeclaration]]) + | PointerTo TypeDecl + | String + | AString + | Set TypeDecl + | FunctionType TypeDecl [TypeVarDeclaration] + | DeriveType InitExpression + | VoidType + | VarParamType TypeDecl -- this is a hack + deriving (Show, Eq) +data Range = Range Identifier + | RangeFromTo InitExpression InitExpression + | RangeInfinite + deriving (Show, Eq) +data Initialize = Initialize String + deriving (Show, Eq) +data Finalize = Finalize String + deriving (Show, Eq) +data Uses = Uses [Identifier] + deriving (Show, Eq) +data Phrase = ProcCall Reference [Expression] + | IfThenElse Expression Phrase (Maybe Phrase) + | WhileCycle Expression Phrase + | RepeatCycle Expression [Phrase] + | ForCycle Identifier Expression Expression Phrase Bool -- The last Boolean indicates wether it's up or down counting + | WithBlock Reference Phrase + | Phrases [Phrase] + | SwitchCase Expression [([InitExpression], Phrase)] (Maybe [Phrase]) + | Assignment Reference Expression + | BuiltInFunctionCall [Expression] Reference + | NOP + deriving (Show, Eq) +data Expression = Expression String + | BuiltInFunCall [Expression] Reference + | PrefixOp String Expression + | PostfixOp String Expression + | BinOp String Expression Expression + | StringLiteral String + | PCharLiteral String + | CharCode String + | HexCharCode String + | NumberLiteral String + | FloatLiteral String + | HexNumber String + | Reference Reference + | SetExpression [Identifier] + | Null + deriving (Show, Eq) +data Reference = ArrayElement [Expression] Reference + | FunCall [Expression] Reference + | TypeCast Identifier Expression + | SimpleReference Identifier + | Dereference Reference + | RecordField Reference Reference + | Address Reference + | RefExpression Expression + deriving (Show, Eq) +data InitExpression = InitBinOp String InitExpression InitExpression + | InitPrefixOp String InitExpression + | InitReference Identifier + | InitArray [InitExpression] + | InitRecord [(Identifier, InitExpression)] + | InitFloat String + | InitNumber String + | InitHexNumber String + | InitString String + | InitPChar String + | InitChar String + | BuiltInFunction String [InitExpression] + | InitSet [InitExpression] + | InitAddress InitExpression + | InitNull + | InitRange Range + | InitTypeCast Identifier InitExpression + deriving (Show, Eq) + +data BaseType = BTUnknown + | BTChar + | BTString + | BTAString + | BTInt Bool -- second param indicates whether signed or not + | BTBool + | BTFloat + | BTRecord String [(String, BaseType)] + | BTArray Range BaseType BaseType + | BTFunction Bool Bool [(Bool, BaseType)] BaseType -- in (Bool, BaseType), Bool indiciates whether var or not + | BTPointerTo BaseType + | BTUnresolved String + | BTSet BaseType + | BTEnum [String] + | BTVoid + | BTUnit + | BTVarParam BaseType + deriving (Show, Eq) diff -r 31570b766315 -r ed5a6478e710 tools/pas2c/unitCycles.hs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/pas2c/unitCycles.hs Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,46 @@ +module Main where + +import PascalParser +import System +import Control.Monad +import Data.Either +import Data.List +import Data.Graph +import Data.Maybe + +unident :: Identificator -> String +unident (Identificator s) = s + +extractUnits :: PascalUnit -> (String, [String]) +extractUnits (Program (Identificator name) (Implementation (Uses idents) _ _) _) = ("program " ++ name, map unident idents) +extractUnits (Unit (Identificator name) (Interface (Uses idents1) _) (Implementation (Uses idents2) _ _) _ _) = (name, map unident $ idents1 ++ idents2) + +f :: [(String, [String])] -> String +f = unlines . map showSCC . stronglyConnComp . map (\(a, b) -> (a, a, b)) + where + showSCC (AcyclicSCC v) = v + showSCC (CyclicSCC vs) = intercalate ", " vs + +myf :: [(String, [String])] -> String +myf d = unlines . map (findCycle . fst) $ d + where + findCycle :: String -> String + findCycle searched = searched ++ ": " ++ (intercalate ", " $ fc searched []) + where + fc :: String -> [String] -> [String] + fc curSearch visited = let uses = curSearch `lookup` d; res = dropWhile null . map t $ fromJust uses in if isNothing uses || null res then [] else head res + where + t u = + if u == searched then + [u] + else + if u `elem` visited then + [] + else + let chain = fc u (u:visited) in if null chain then [] else u:chain + + +main = do + fileNames <- getArgs + files <- mapM readFile fileNames + putStrLn . myf . map extractUnits . rights . map parsePascalUnit $ files diff -r 31570b766315 -r ed5a6478e710 tools/rgit2hg.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/rgit2hg.sh Tue Nov 10 20:43:13 2015 +0100 @@ -0,0 +1,62 @@ +#!/bin/sh + +#HW_HG= + +if [ -z "$1" ]; then + echo 'You have to supply at least one hedgewars git revision as parameter!' >&2 + exit +fi + +if [ -z "$HW_HG" ]; then + HW_HG="$PWD" +fi + +if [ ! -d "$HW_HG/.hg" ]; then + echo 'You have to set HW_HG (inside script or env) to a repo clone OR call this script from inside the repository!' >&2 + exit +fi + +while [ ! -z "$1" ]; do + echo + echo + echo '---------------------------------------------------------------' + echo "$1" + echo '---------------------------------------------------------------' + url="https://github.com/hedgewars/hw/commit/$1" + echo "Checking $url ..." + echo + page=$(wget -q -O- "$url") + author=$(echo "$page" | sed -rn 's/^.*"author-name">(<[^>]*>)*([^ <]*).*/\2/ p') + if [ -z "$author" ]; then + echo 'Couldn'\''t find author! Skipping '"$1"' ...' >&2 + shift + continue + fi + echo 'Found author: '"$author" + date=$(echo "$page" | sed -rn 's/^.*