# HG changeset patch # User unc0rr # Date 1447703844 -10800 # Node ID b894922d58cc809058d6afd9ddce2102f6550587 # Parent fcbdee9cdd74e96a441fae4e7caa1d918ecb2e3c# Parent bea08a303cb72e3c50ab8114073108fee0005845 Merge default (add a bunch of FIXMEs) diff -r fcbdee9cdd74 -r b894922d58cc .hgignore --- a/.hgignore Tue Sep 08 19:20:58 2015 +0300 +++ b/.hgignore Mon Nov 16 22:57:24 2015 +0300 @@ -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/ @@ -72,4 +72,14 @@ 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 fcbdee9cdd74 -r b894922d58cc .hgtags --- a/.hgtags Tue Sep 08 19:20:58 2015 +0300 +++ b/.hgtags Mon Nov 16 22:57:24 2015 +0300 @@ -63,3 +63,14 @@ 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 +7e55468ffe384a3065524c483eb5e3cdb1658fd5 fab746a3597e +0000000000000000000000000000000000000000 fab746a3597e +d9622394ec9c2974a84b9b4d9e6c0ac26c4060ff 0.9.22-RC +0000000000000000000000000000000000000000 0.9.22-RC diff -r fcbdee9cdd74 -r b894922d58cc .travis.yml --- a/.travis.yml Tue Sep 08 19:20:58 2015 +0300 +++ b/.travis.yml Mon Nov 16 22:57:24 2015 +0300 @@ -6,24 +6,18 @@ - gcc - clang env: - # Default build. Release. - BUILD_ARGS="-DCMAKE_BUILD_TYPE=Release" - # Debug build - BUILD_ARGS="-DCMAKE_BUILD_TYPE=Debug" - # Everything that's optional - - BUILD_ARGS="-DBUILD_ENGINE_C=1" - - BUILD_ARGS="-DNOPNG=1" - - BUILD_ARGS="-DNOVIDEOREC=1" - - BUILD_ARGS="-DNOSERVER=1" - - BUILD_ARGS="-DLUA_SYSTEM=0" - - BUILD_ARGS="-DPHYSFS_SYSTEM=0" - - BUILD_ARGS="-DGL2=1" + - 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 add-apt-repository -y ppa:zoogie/sdl2-snapshots - 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 + - sudo apt-get install debhelper cmake dpkg-dev libqt4-dev qt4-qmake libphysfs-dev libsdl2-dev libsdl2-ttf-dev libsdl2-mixer-dev libsdl2-image-dev libsdl2-net-dev bzip2 ghc libghc-mtl-dev libghc-parsec3-dev libghc-bytestring-show-dev libghc-vector-dev libghc-zlib-dev libghc-random-dev libghc-stm-dev libghc-network-dev libghc-dataenc-dev libghc-hslogger-dev libghc-utf8-string-dev libghc-sha-dev libghc-entropy-dev liblua5.1-0-dev imagemagick fpc fp-compiler fp-units-misc libpng-dev fp-units-gfx libavcodec-dev libavformat-dev libglew1.6-dev script: - mkdir build && cd build && cmake $BUILD_ARGS .. && make VERBOSE=1 && make test_verbose notifications: diff -r fcbdee9cdd74 -r b894922d58cc CMakeLists.txt --- a/CMakeLists.txt Tue Sep 08 19:20:58 2015 +0300 +++ b/CMakeLists.txt Mon Nov 16 22:57:24 2015 +0300 @@ -8,6 +8,12 @@ endif() endforeach() +foreach(hwpolicy CMP0026) + if(POLICY ${hwpolicy}) + cmake_policy(SET ${hwpolicy} OLD) + endif() +endforeach() + set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake_modules") include(${CMAKE_MODULE_PATH}/utils.cmake) @@ -52,13 +58,15 @@ #versioning set(CPACK_PACKAGE_VERSION_MAJOR 0) set(CPACK_PACKAGE_VERSION_MINOR 9) -set(CPACK_PACKAGE_VERSION_PATCH 22) -set(HEDGEWARS_PROTO_VER 50) +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) message(STATUS "Building ${HEDGEWARS_VERSION}-r${HEDGEWARS_REVISION} (${HEDGEWARS_HASH})") +#io library paths +include(${CMAKE_MODULE_PATH}/paths.cmake) #general utilities include(${CMAKE_MODULE_PATH}/utils.cmake) #paths initialization @@ -110,18 +118,18 @@ endif() endif() -list(APPEND haskell_flags ${ghflags_parsed} "-O2") #get BUILD_TYPE and enable/disable optimisation message(STATUS "Using ${CMAKE_BUILD_TYPE} configuration") if(CMAKE_BUILD_TYPE MATCHES "DEBUG") list(APPEND haskell_flags "-Wall" # all warnings "-debug" # debug mode - "-dcore-lint" # internal sanity check "-fno-warn-unused-do-bind" + "-O0" ) else() list(APPEND haskell_flags "-w" # no warnings + "-O2" ) endif() diff -r fcbdee9cdd74 -r b894922d58cc ChangeLog.txt --- a/ChangeLog.txt Tue Sep 08 19:20:58 2015 +0300 +++ b/ChangeLog.txt Mon Nov 16 22:57:24 2015 +0300 @@ -1,22 +1,40 @@ + features * bugfixes +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 - + Small improvements to the interface and in-game chat - + Divided teams options will now just be ignored when more/less than 2 teams, instead of displaying a fatal error + + 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. diff -r fcbdee9cdd74 -r b894922d58cc INSTALL --- a/INSTALL Tue Sep 08 19:20:58 2015 +0300 +++ b/INSTALL Mon Nov 16 22:57:24 2015 +0300 @@ -2,10 +2,10 @@ - CMake >= 2.6.0 - FreePascal >= 2.2.4 - Qt >= 4.7.0 - - SDL >= 1.2.5 - - SDL_net >= 1.2.5 - - SDL_mixer >= 1.2 - - SDL_image >= 1.2 + - 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.0.0 @@ -16,7 +16,6 @@ - hslogger package For videorecording: - FFmpeg or LibAV - - GLUT (when SDL < 2) For compressed screenshots: - libpng diff -r fcbdee9cdd74 -r b894922d58cc QTfrontend/CMakeLists.txt --- a/QTfrontend/CMakeLists.txt Tue Sep 08 19:20:58 2015 +0300 +++ b/QTfrontend/CMakeLists.txt Mon Nov 16 22:57:24 2015 +0300 @@ -20,8 +20,10 @@ message(FATAL_ERROR "This version of Qt is known *not* to work, please update or use a lower version") endif() -find_package(SDL1or2) #video in SDLInteraction -find_package(SDL_mixer REQUIRED) #audio in SDLInteraction +find_package(SDL2 REQUIRED) +find_package(SDL2_mixer REQUIRED) #audio in SDLInteraction +include_directories(${SDL2_INCLUDE_DIR}) +include_directories(${SDL2MIXER_INCLUDE_DIR}) if(LIBAV_FOUND) add_definitions(-DVIDEOREC -D__STDC_CONSTANT_MACROS) @@ -60,8 +62,6 @@ 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(${SDL_INCLUDE_DIR}) -include_directories(${SDLMIXER_INCLUDE_DIR}) include_directories(BEFORE ${PHYSFS_INCLUDE_DIR}) include_directories(BEFORE ${PHYSLAYER_INCLUDE_DIR}) include_directories(${LUA_INCLUDE_DIR}) #brought by physlayer hwpacksmounter.h @@ -204,13 +204,16 @@ list(APPEND HW_LINK_LIBS physfs physlayer ${QT_LIBRARIES} - ${SDL_LIBRARY} - ${SDLMIXER_LIBRARY} + ) + +list(APPEND HW_LINK_LIBS + ${SDL2_LIBRARY} + ${SDL2MIXER_LIBRARY} ) if(WIN32 AND NOT UNIX) - if(NOT SDL_LIBRARY) - list(APPEND HW_LINK_LIBS SDL) + if(NOT SDL2_LIBRARY) + list(APPEND HW_LINK_LIBS SDL2) endif() list(APPEND HW_LINK_LIBS diff -r fcbdee9cdd74 -r b894922d58cc QTfrontend/game.cpp --- a/QTfrontend/game.cpp Tue Sep 08 19:20:58 2015 +0300 +++ b/QTfrontend/game.cpp Mon Nov 16 22:57:24 2015 +0300 @@ -17,7 +17,6 @@ */ #include -#include #include #include @@ -261,18 +260,6 @@ .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))); diff -r fcbdee9cdd74 -r b894922d58cc QTfrontend/gameuiconfig.cpp --- a/QTfrontend/gameuiconfig.cpp Tue Sep 08 19:20:58 2015 +0300 +++ b/QTfrontend/gameuiconfig.cpp Mon Nov 16 22:57:24 2015 +0300 @@ -86,10 +86,11 @@ else Form->ui.pageOptions->CBResolution->setCurrentIndex(t); // Default the windowed resolution to 5/6 of the screen size - int screenWidth = SDL_GetVideoInfo()->current_w * 5 / 6; - int screenHeight = SDL_GetVideoInfo()->current_h * 5 / 6; - QString widthStr; widthStr.setNum(screenWidth); - QString heightStr; heightStr.setNum(screenHeight); + QSize screenSize = SDLInteraction::instance().getCurrentResolution(); + screenSize *= 5.0 / 6; + + QString widthStr = QString::number(screenSize.width()); + QString heightStr = QString::number(screenSize.height()); QString wWidth = value("video/windowedWidth", widthStr).toString(); QString wHeight = value("video/windowedHeight", heightStr).toString(); // If left blank reset the resolution to the default diff -r fcbdee9cdd74 -r b894922d58cc QTfrontend/main.cpp --- a/QTfrontend/main.cpp Tue Sep 08 19:20:58 2015 +0300 +++ b/QTfrontend/main.cpp Mon Nov 16 22:57:24 2015 +0300 @@ -37,6 +37,8 @@ #include "FileEngine.h" #include "MessageDialog.h" +#include "SDLInteraction.h" + #ifdef _WIN32 #include #elif defined __APPLE__ @@ -154,6 +156,8 @@ cocoaInit = new CocoaInitializer(); // Creates the autoreleasepool preventing cocoa object leaks on OS X. #endif + SDLInteraction::instance(); + HWApplication app(argc, argv); app.setAttribute(Qt::AA_DontShowIconsInMenus,false); diff -r fcbdee9cdd74 -r b894922d58cc QTfrontend/res/html/about.html --- a/QTfrontend/res/html/about.html Tue Sep 08 19:20:58 2015 +0300 +++ b/QTfrontend/res/html/about.html Mon Nov 16 22:57:24 2015 +0300 @@ -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:

@@ -82,7 +83,7 @@ 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 fcbdee9cdd74 -r b894922d58cc QTfrontend/ui/widget/about.cpp --- a/QTfrontend/ui/widget/about.cpp Tue Sep 08 19:20:58 2015 +0300 +++ b/QTfrontend/ui/widget/about.cpp Mon Nov 16 22:57:24 2015 +0300 @@ -101,14 +101,17 @@ libinfo.append(QString(tr("Unknown Compiler")).arg(__VERSION__) + QString("
")); #endif - const SDL_version *sdl_ver = SDL_Linked_Version(); - libinfo.append(QString("SDL version: %1.%2.%3
") + const SDL_version *sdl_ver; + SDL_version sdl_version; + SDL_GetVersion(&sdl_version); + sdl_ver = &sdl_version; + libinfo.append(QString("SDL2 version: %1.%2.%3
") .arg(sdl_ver->major) .arg(sdl_ver->minor) .arg(sdl_ver->patch)); const SDL_version *sdlmixer_ver = Mix_Linked_Version(); - libinfo.append(QString("SDL_mixer version: %1.%2.%3
") + libinfo.append(QString("SDL2_mixer version: %1.%2.%3
") .arg(sdlmixer_ver->major) .arg(sdlmixer_ver->minor) .arg(sdlmixer_ver->patch)); diff -r fcbdee9cdd74 -r b894922d58cc QTfrontend/util/LibavInteraction.cpp --- a/QTfrontend/util/LibavInteraction.cpp Tue Sep 08 19:20:58 2015 +0300 +++ b/QTfrontend/util/LibavInteraction.cpp Mon Nov 16 22:57:24 2015 +0300 @@ -21,7 +21,9 @@ #if VIDEOREC extern "C" { +#include "libavcodec/avcodec.h" #include "libavformat/avformat.h" +#include "libavutil/avutil.h" } #include @@ -30,13 +32,28 @@ #include "HWApplication.h" -#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54, 25, 0) -#define CodecID AVCodecID +// compatibility section +#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54, 8, 0) +#define av_codec_is_encoder(x) x->encode +#endif + +#if LIBAVCODEC_VERSION_MAJOR < 55 +#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 +73,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 +93,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 +119,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 +134,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 +287,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 +321,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 fcbdee9cdd74 -r b894922d58cc QTfrontend/util/SDLInteraction.cpp --- a/QTfrontend/util/SDLInteraction.cpp Tue Sep 08 19:20:58 2015 +0300 +++ b/QTfrontend/util/SDLInteraction.cpp Mon Nov 16 22:57:24 2015 +0300 @@ -85,19 +85,15 @@ { QStringList result; - SDL_Rect **modes; + int modesNumber = SDL_GetNumDisplayModes(0); + SDL_DisplayMode mode; - modes = SDL_ListModes(NULL, SDL_FULLSCREEN); - - if((modes == (SDL_Rect **)0) || (modes == (SDL_Rect **)-1)) + for(int i = 0; i < modesNumber; ++i) { - result << "640x480"; - } - else - { - for(int i = 0; modes[i]; ++i) - if ((modes[i]->w >= 640) && (modes[i]->h >= 480)) - result << QString("%1x%2").arg(modes[i]->w).arg(modes[i]->h); + SDL_GetDisplayMode(0, i, &mode); + + if ((mode.w >= 640) && (mode.h >= 480)) + result << QString("%1x%2").arg(mode.w).arg(mode.h); } return result; @@ -108,6 +104,9 @@ { QStringList result; +#if SDL_VERSION_ATLEAST(2, 0, 0) +// TODO or not TODO? +#else int i = 0; while(i < 1024 && sdlkeys[i][1][0] != '\0') i++; @@ -181,7 +180,8 @@ // Terminate the list sdlkeys[i][0][0] = '\0'; - sdlkeys[i][1][0] = '\0'; + sdlkeys[i][1][0] = '\0'; +#endif } @@ -243,7 +243,7 @@ if (!m_audioInitialized) return; if (m_music == NULL) - m_music = Mix_LoadMUS_RW(PHYSFSRWOPS_openRead(m_musicTrack.toLocal8Bit().constData())); + m_music = Mix_LoadMUS_RW(PHYSFSRWOPS_openRead(m_musicTrack.toLocal8Bit().constData()), 0); Mix_VolumeMusic(MIX_MAX_VOLUME/4); Mix_FadeInMusic(m_music, -1, 1750); @@ -264,3 +264,12 @@ m_isPlayingMusic = false; } + +QSize SDLInteraction::getCurrentResolution() +{ + SDL_DisplayMode mode; + + SDL_GetDesktopDisplayMode(0, &mode); + + return QSize(mode.w, mode.h); +} diff -r fcbdee9cdd74 -r b894922d58cc QTfrontend/util/SDLInteraction.h --- a/QTfrontend/util/SDLInteraction.h Tue Sep 08 19:20:58 2015 +0300 +++ b/QTfrontend/util/SDLInteraction.h Mon Nov 16 22:57:24 2015 +0300 @@ -27,7 +27,15 @@ #include #include +#include +// workaround some strange Qt and SLD2 interaction +#ifdef Q_OS_MAC +# ifdef MAC_OS_X_VERSION_MIN_REQUIRED +# undef MAC_OS_X_VERSION_MIN_REQUIRED +# define MAC_OS_X_VERSION_MIN_REQUIRED MAC_OS_X_VERSION_10_6 +# endif +#endif #include "SDL_mixer.h" /** @@ -103,6 +111,8 @@ /// Fades out and stops the background music (if playing). void stopMusic(); + + QSize getCurrentResolution(); }; diff -r fcbdee9cdd74 -r b894922d58cc README --- a/README Tue Sep 08 19:20:58 2015 +0300 +++ b/README Mon Nov 16 22:57:24 2015 +0300 @@ -1,46 +1,1 @@ -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: 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 fcbdee9cdd74 -r b894922d58cc README.md --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/README.md Mon Nov 16 22:57:24 2015 +0300 @@ -0,0 +1,48 @@ +Hedgewars - a turn based strategy game. +======================================= + +[![Build Status](https://travis-ci.org/hedgewars/hw.svg)](https://travis-ci.org/hedgewars/hw) + +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 fcbdee9cdd74 -r b894922d58cc cmake_modules/CheckHaskellModuleExists.cmake --- a/cmake_modules/CheckHaskellModuleExists.cmake Tue Sep 08 19:20:58 2015 +0300 +++ b/cmake_modules/CheckHaskellModuleExists.cmake Mon Nov 16 22:57:24 2015 +0300 @@ -11,7 +11,7 @@ macro(CHECK_HASKELL_MODULE_EXISTS MODULE FUNCTION PARAMCOUNT LIBRARY) set(VARIABLE "HS_MODULE_${LIBRARY}_${FUNCTION}") - if("${VARIABLE}" MATCHES "^${VARIABLE}$") + if(${VARIABLE} MATCHES ^${VARIABLE}$) message(STATUS "Looking for ${FUNCTION} in ${MODULE}") set(PARAMETERS "") diff -r fcbdee9cdd74 -r b894922d58cc cmake_modules/FindSDL1or2.cmake --- a/cmake_modules/FindSDL1or2.cmake Tue Sep 08 19:20:58 2015 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -find_package(SDL QUIET) - -if(NOT SDL_FOUND) - find_package(SDL2 REQUIRED) - set(SDL_INCLUDE_DIR ${SDL2_INCLUDE_DIR}) - set(SDL_LIBRARY ${SDL2_LIBRARY}) -endif() - -if(NOT SDL_VERSION) - #find which version of SDL we have - find_file(sdlversion_h SDL_version.h ${SDL_INCLUDE_DIR}) - if(sdlversion_h) - file(STRINGS ${sdlversion_h} sdl_majorversion_tmp REGEX "SDL_MAJOR_VERSION[\t' ']+[0-9]+") - file(STRINGS ${sdlversion_h} sdl_minorversion_tmp REGEX "SDL_MINOR_VERSION[\t' ']+[0-9]+") - file(STRINGS ${sdlversion_h} sdl_patchversion_tmp REGEX "SDL_PATCHLEVEL[\t' ']+[0-9]+") - string(REGEX MATCH "([0-9]+)" sdl_majorversion "${sdl_majorversion_tmp}") - string(REGEX MATCH "([0-9]+)" sdl_minorversion "${sdl_minorversion_tmp}") - string(REGEX MATCH "([0-9]+)" sdl_patchversion "${sdl_patchversion_tmp}") - set(SDL_VERSION "${sdl_majorversion}.${sdl_minorversion}.${sdl_patchversion}") - endif() -endif() - -mark_as_advanced(sdlversion_h sdl_majorversion sdl_minorversion sdl_patchversion) - diff -r fcbdee9cdd74 -r b894922d58cc cmake_modules/FindSDL2_image.cmake --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cmake_modules/FindSDL2_image.cmake Mon Nov 16 22:57:24 2015 +0300 @@ -0,0 +1,88 @@ +# - Locate SDL2_image library +# This module defines: +# SDL2_IMAGE_LIBRARIES, the name of the library to link against +# SDL2_IMAGE_INCLUDE_DIRS, where to find the headers +# SDL2_IMAGE_FOUND, if false, do not try to link against +# SDL2_IMAGE_VERSION_STRING - human-readable string containing the version of SDL2_image +# +# For backward compatiblity the following variables are also set: +# SDL2IMAGE_LIBRARY (same value as SDL2_IMAGE_LIBRARIES) +# SDL2IMAGE_INCLUDE_DIR (same value as SDL2_IMAGE_INCLUDE_DIRS) +# SDL2IMAGE_FOUND (same value as SDL2_IMAGE_FOUND) +# +# $SDL2DIR is an environment variable that would +# correspond to the ./configure --prefix=$SDL2DIR +# used in building SDL2. +# +# Created by Eric Wing. This was influenced by the FindSDL2.cmake +# module, but with modifications to recognize OS X frameworks and +# additional Unix paths (FreeBSD, etc). + +#============================================================================= +# Copyright 2005-2009 Kitware, Inc. +# Copyright 2012 Benjamin Eikel +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) + +if(NOT SDL2_IMAGE_INCLUDE_DIR AND SDL2IMAGE_INCLUDE_DIR) + set(SDL2_IMAGE_INCLUDE_DIR ${SDL2IMAGE_INCLUDE_DIR} CACHE PATH "directory cache +entry initialized from old variable name") +endif() +find_path(SDL2_IMAGE_INCLUDE_DIR SDL_image.h + HINTS + ENV SDL2IMAGEDIR + ENV SDL2DIR + PATH_SUFFIXES include/SDL2 include +) + +if(NOT SDL2_IMAGE_LIBRARY AND SDL2IMAGE_LIBRARY) + set(SDL2_IMAGE_LIBRARY ${SDL2IMAGE_LIBRARY} CACHE FILEPATH "file cache entry +initialized from old variable name") +endif() +find_library(SDL2_IMAGE_LIBRARY + NAMES SDL2_image + HINTS + ENV SDL2IMAGEDIR + ENV SDL2DIR + PATH_SUFFIXES lib +) + +if(SDL2_IMAGE_INCLUDE_DIR AND EXISTS "${SDL2_IMAGE_INCLUDE_DIR}/SDL2_image.h") + file(STRINGS "${SDL2_IMAGE_INCLUDE_DIR}/SDL2_image.h" SDL2_IMAGE_VERSION_MAJOR_LINE REGEX "^#define[ \t]+SDL2_IMAGE_MAJOR_VERSION[ \t]+[0-9]+$") + file(STRINGS "${SDL2_IMAGE_INCLUDE_DIR}/SDL2_image.h" SDL2_IMAGE_VERSION_MINOR_LINE REGEX "^#define[ \t]+SDL2_IMAGE_MINOR_VERSION[ \t]+[0-9]+$") + file(STRINGS "${SDL2_IMAGE_INCLUDE_DIR}/SDL2_image.h" SDL2_IMAGE_VERSION_PATCH_LINE REGEX "^#define[ \t]+SDL2_IMAGE_PATCHLEVEL[ \t]+[0-9]+$") + string(REGEX REPLACE "^#define[ \t]+SDL2_IMAGE_MAJOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_IMAGE_VERSION_MAJOR "${SDL2_IMAGE_VERSION_MAJOR_LINE}") + string(REGEX REPLACE "^#define[ \t]+SDL2_IMAGE_MINOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_IMAGE_VERSION_MINOR "${SDL2_IMAGE_VERSION_MINOR_LINE}") + string(REGEX REPLACE "^#define[ \t]+SDL2_IMAGE_PATCHLEVEL[ \t]+([0-9]+)$" "\\1" SDL2_IMAGE_VERSION_PATCH "${SDL2_IMAGE_VERSION_PATCH_LINE}") + set(SDL2_IMAGE_VERSION_STRING ${SDL2_IMAGE_VERSION_MAJOR}.${SDL2_IMAGE_VERSION_MINOR}.${SDL2_IMAGE_VERSION_PATCH}) + unset(SDL2_IMAGE_VERSION_MAJOR_LINE) + unset(SDL2_IMAGE_VERSION_MINOR_LINE) + unset(SDL2_IMAGE_VERSION_PATCH_LINE) + unset(SDL2_IMAGE_VERSION_MAJOR) + unset(SDL2_IMAGE_VERSION_MINOR) + unset(SDL2_IMAGE_VERSION_PATCH) +endif() + +set(SDL2_IMAGE_LIBRARIES ${SDL2_IMAGE_LIBRARY}) +set(SDL2_IMAGE_INCLUDE_DIRS ${SDL2_IMAGE_INCLUDE_DIR}) + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2_image + REQUIRED_VARS SDL2_IMAGE_LIBRARIES SDL2_IMAGE_INCLUDE_DIRS + VERSION_VAR SDL2_IMAGE_VERSION_STRING) + +# for backward compatiblity +set(SDL2IMAGE_LIBRARY ${SDL2_IMAGE_LIBRARIES}) +set(SDL2IMAGE_INCLUDE_DIR ${SDL2_IMAGE_INCLUDE_DIRS}) +set(SDL2IMAGE_FOUND ${SDL2_IMAGE_FOUND}) + +mark_as_advanced(SDL2_IMAGE_LIBRARY SDL2_IMAGE_INCLUDE_DIR) diff -r fcbdee9cdd74 -r b894922d58cc cmake_modules/FindSDL2_mixer.cmake --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cmake_modules/FindSDL2_mixer.cmake Mon Nov 16 22:57:24 2015 +0300 @@ -0,0 +1,88 @@ +# - Locate SDL2_mixer library +# This module defines: +# SDL2_MIXER_LIBRARIES, the name of the library to link against +# SDL2_MIXER_INCLUDE_DIRS, where to find the headers +# SDL2_MIXER_FOUND, if false, do not try to link against +# SDL2_MIXER_VERSION_STRING - human-readable string containing the version of SDL2_mixer +# +# For backward compatiblity the following variables are also set: +# SDL2MIXER_LIBRARY (same value as SDL2_MIXER_LIBRARIES) +# SDL2MIXER_INCLUDE_DIR (same value as SDL2_MIXER_INCLUDE_DIRS) +# SDL2MIXER_FOUND (same value as SDL2_MIXER_FOUND) +# +# $SDL2DIR is an environment variable that would +# correspond to the ./configure --prefix=$SDL2DIR +# used in building SDL2. +# +# Created by Eric Wing. This was influenced by the FindSDL2.cmake +# module, but with modifications to recognize OS X frameworks and +# additional Unix paths (FreeBSD, etc). + +#============================================================================= +# Copyright 2005-2009 Kitware, Inc. +# Copyright 2012 Benjamin Eikel +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) + +if(NOT SDL2_MIXER_INCLUDE_DIR AND SDL2MIXER_INCLUDE_DIR) + set(SDL2_MIXER_INCLUDE_DIR ${SDL2MIXER_INCLUDE_DIR} CACHE PATH "directory cache +entry initialized from old variable name") +endif() +find_path(SDL2_MIXER_INCLUDE_DIR SDL_mixer.h + HINTS + ENV SDL2MIXERDIR + ENV SDL2DIR + PATH_SUFFIXES include/SDL2 include +) + +if(NOT SDL2_MIXER_LIBRARY AND SDL2MIXER_LIBRARY) + set(SDL2_MIXER_LIBRARY ${SDL2MIXER_LIBRARY} CACHE FILEPATH "file cache entry +initialized from old variable name") +endif() +find_library(SDL2_MIXER_LIBRARY + NAMES SDL2_mixer + HINTS + ENV SDL2MIXERDIR + ENV SDL2DIR + PATH_SUFFIXES lib +) + +if(SDL2_MIXER_INCLUDE_DIR AND EXISTS "${SDL2_MIXER_INCLUDE_DIR}/SDL2_mixer.h") + file(STRINGS "${SDL2_MIXER_INCLUDE_DIR}/SDL2_mixer.h" SDL2_MIXER_VERSION_MAJOR_LINE REGEX "^#define[ \t]+SDL2_MIXER_MAJOR_VERSION[ \t]+[0-9]+$") + file(STRINGS "${SDL2_MIXER_INCLUDE_DIR}/SDL2_mixer.h" SDL2_MIXER_VERSION_MINOR_LINE REGEX "^#define[ \t]+SDL2_MIXER_MINOR_VERSION[ \t]+[0-9]+$") + file(STRINGS "${SDL2_MIXER_INCLUDE_DIR}/SDL2_mixer.h" SDL2_MIXER_VERSION_PATCH_LINE REGEX "^#define[ \t]+SDL2_MIXER_PATCHLEVEL[ \t]+[0-9]+$") + string(REGEX REPLACE "^#define[ \t]+SDL2_MIXER_MAJOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_MIXER_VERSION_MAJOR "${SDL2_MIXER_VERSION_MAJOR_LINE}") + string(REGEX REPLACE "^#define[ \t]+SDL2_MIXER_MINOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_MIXER_VERSION_MINOR "${SDL2_MIXER_VERSION_MINOR_LINE}") + string(REGEX REPLACE "^#define[ \t]+SDL2_MIXER_PATCHLEVEL[ \t]+([0-9]+)$" "\\1" SDL2_MIXER_VERSION_PATCH "${SDL2_MIXER_VERSION_PATCH_LINE}") + set(SDL2_MIXER_VERSION_STRING ${SDL2_MIXER_VERSION_MAJOR}.${SDL2_MIXER_VERSION_MINOR}.${SDL2_MIXER_VERSION_PATCH}) + unset(SDL2_MIXER_VERSION_MAJOR_LINE) + unset(SDL2_MIXER_VERSION_MINOR_LINE) + unset(SDL2_MIXER_VERSION_PATCH_LINE) + unset(SDL2_MIXER_VERSION_MAJOR) + unset(SDL2_MIXER_VERSION_MINOR) + unset(SDL2_MIXER_VERSION_PATCH) +endif() + +set(SDL2_MIXER_LIBRARIES ${SDL2_MIXER_LIBRARY}) +set(SDL2_MIXER_INCLUDE_DIRS ${SDL2_MIXER_INCLUDE_DIR}) + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2_mixer + REQUIRED_VARS SDL2_MIXER_LIBRARIES SDL2_MIXER_INCLUDE_DIRS + VERSION_VAR SDL2_MIXER_VERSION_STRING) + +# for backward compatiblity +set(SDL2MIXER_LIBRARY ${SDL2_MIXER_LIBRARIES}) +set(SDL2MIXER_INCLUDE_DIR ${SDL2_MIXER_INCLUDE_DIRS}) +set(SDL2MIXER_FOUND ${SDL2_MIXER_FOUND}) + +mark_as_advanced(SDL2_MIXER_LIBRARY SDL2_MIXER_INCLUDE_DIR) diff -r fcbdee9cdd74 -r b894922d58cc cmake_modules/FindSDL2_net.cmake --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cmake_modules/FindSDL2_net.cmake Mon Nov 16 22:57:24 2015 +0300 @@ -0,0 +1,88 @@ +# - Locate SDL2_net library +# This module defines: +# SDL2_NET_LIBRARIES, the name of the library to link against +# SDL2_NET_INCLUDE_DIRS, where to find the headers +# SDL2_NET_FOUND, if false, do not try to link against +# SDL2_NET_VERSION_STRING - human-readable string containing the version of SDL2_net +# +# For backward compatiblity the following variables are also set: +# SDL2NET_LIBRARY (same value as SDL2_NET_LIBRARIES) +# SDL2NET_INCLUDE_DIR (same value as SDL2_NET_INCLUDE_DIRS) +# SDL2NET_FOUND (same value as SDL2_NET_FOUND) +# +# $SDL2DIR is an environment variable that would +# correspond to the ./configure --prefix=$SDL2DIR +# used in building SDL2. +# +# Created by Eric Wing. This was influenced by the FindSDL2.cmake +# module, but with modifications to recognize OS X frameworks and +# additional Unix paths (FreeBSD, etc). + +#============================================================================= +# Copyright 2005-2009 Kitware, Inc. +# Copyright 2012 Benjamin Eikel +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) + +if(NOT SDL2_NET_INCLUDE_DIR AND SDL2NET_INCLUDE_DIR) + set(SDL2_NET_INCLUDE_DIR ${SDL2NET_INCLUDE_DIR} CACHE PATH "directory cache +entry initialized from old variable name") +endif() +find_path(SDL2_NET_INCLUDE_DIR SDL_net.h + HINTS + ENV SDL2NETDIR + ENV SDL2DIR + PATH_SUFFIXES include/SDL2 include +) + +if(NOT SDL2_NET_LIBRARY AND SDL2NET_LIBRARY) + set(SDL2_NET_LIBRARY ${SDL2NET_LIBRARY} CACHE FILEPATH "file cache entry +initialized from old variable name") +endif() +find_library(SDL2_NET_LIBRARY + NAMES SDL2_net + HINTS + ENV SDL2NETDIR + ENV SDL2DIR + PATH_SUFFIXES lib +) + +if(SDL2_NET_INCLUDE_DIR AND EXISTS "${SDL2_NET_INCLUDE_DIR}/SDL2_net.h") + file(STRINGS "${SDL2_NET_INCLUDE_DIR}/SDL2_net.h" SDL2_NET_VERSION_MAJOR_LINE REGEX "^#define[ \t]+SDL2_NET_MAJOR_VERSION[ \t]+[0-9]+$") + file(STRINGS "${SDL2_NET_INCLUDE_DIR}/SDL2_net.h" SDL2_NET_VERSION_MINOR_LINE REGEX "^#define[ \t]+SDL2_NET_MINOR_VERSION[ \t]+[0-9]+$") + file(STRINGS "${SDL2_NET_INCLUDE_DIR}/SDL2_net.h" SDL2_NET_VERSION_PATCH_LINE REGEX "^#define[ \t]+SDL2_NET_PATCHLEVEL[ \t]+[0-9]+$") + string(REGEX REPLACE "^#define[ \t]+SDL2_NET_MAJOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_NET_VERSION_MAJOR "${SDL2_NET_VERSION_MAJOR_LINE}") + string(REGEX REPLACE "^#define[ \t]+SDL2_NET_MINOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_NET_VERSION_MINOR "${SDL2_NET_VERSION_MINOR_LINE}") + string(REGEX REPLACE "^#define[ \t]+SDL2_NET_PATCHLEVEL[ \t]+([0-9]+)$" "\\1" SDL2_NET_VERSION_PATCH "${SDL2_NET_VERSION_PATCH_LINE}") + set(SDL2_NET_VERSION_STRING ${SDL2_NET_VERSION_MAJOR}.${SDL2_NET_VERSION_MINOR}.${SDL2_NET_VERSION_PATCH}) + unset(SDL2_NET_VERSION_MAJOR_LINE) + unset(SDL2_NET_VERSION_MINOR_LINE) + unset(SDL2_NET_VERSION_PATCH_LINE) + unset(SDL2_NET_VERSION_MAJOR) + unset(SDL2_NET_VERSION_MINOR) + unset(SDL2_NET_VERSION_PATCH) +endif() + +set(SDL2_NET_LIBRARIES ${SDL2_NET_LIBRARY}) +set(SDL2_NET_INCLUDE_DIRS ${SDL2_NET_INCLUDE_DIR}) + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2_net + REQUIRED_VARS SDL2_NET_LIBRARIES SDL2_NET_INCLUDE_DIRS + VERSION_VAR SDL2_NET_VERSION_STRING) + +# for backward compatiblity +set(SDL2NET_LIBRARY ${SDL2_NET_LIBRARIES}) +set(SDL2NET_INCLUDE_DIR ${SDL2_NET_INCLUDE_DIRS}) +set(SDL2NET_FOUND ${SDL2_NET_FOUND}) + +mark_as_advanced(SDL2_NET_LIBRARY SDL2_NET_INCLUDE_DIR) diff -r fcbdee9cdd74 -r b894922d58cc cmake_modules/FindSDL2_ttf.cmake --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cmake_modules/FindSDL2_ttf.cmake Mon Nov 16 22:57:24 2015 +0300 @@ -0,0 +1,88 @@ +# - Locate SDL2_ttf library +# This module defines: +# SDL2_TTF_LIBRARIES, the name of the library to link against +# SDL2_TTF_INCLUDE_DIRS, where to find the headers +# SDL2_TTF_FOUND, if false, do not try to link against +# SDL2_TTF_VERSION_STRING - human-readable string containing the version of SDL2_ttf +# +# For backward compatiblity the following variables are also set: +# SDL2TTF_LIBRARY (same value as SDL2_TTF_LIBRARIES) +# SDL2TTF_INCLUDE_DIR (same value as SDL2_TTF_INCLUDE_DIRS) +# SDL2TTF_FOUND (same value as SDL2_TTF_FOUND) +# +# $SDL2DIR is an environment variable that would +# correspond to the ./configure --prefix=$SDL2DIR +# used in building SDL2. +# +# Created by Eric Wing. This was influenced by the FindSDL2.cmake +# module, but with modifications to recognize OS X frameworks and +# additional Unix paths (FreeBSD, etc). + +#============================================================================= +# Copyright 2005-2009 Kitware, Inc. +# Copyright 2012 Benjamin Eikel +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) + +if(NOT SDL2_TTF_INCLUDE_DIR AND SDL2TTF_INCLUDE_DIR) + set(SDL2_TTF_INCLUDE_DIR ${SDL2TTF_INCLUDE_DIR} CACHE PATH "directory cache +entry initialized from old variable name") +endif() +find_path(SDL2_TTF_INCLUDE_DIR SDL_ttf.h + HINTS + ENV SDL2TTFDIR + ENV SDL2DIR + PATH_SUFFIXES include/SDL2 include +) + +if(NOT SDL2_TTF_LIBRARY AND SDL2TTF_LIBRARY) + set(SDL2_TTF_LIBRARY ${SDL2TTF_LIBRARY} CACHE FILEPATH "file cache entry +initialized from old variable name") +endif() +find_library(SDL2_TTF_LIBRARY + NAMES SDL2_ttf + HINTS + ENV SDL2TTFDIR + ENV SDL2DIR + PATH_SUFFIXES lib +) + +if(SDL2_TTF_INCLUDE_DIR AND EXISTS "${SDL2_TTF_INCLUDE_DIR}/SDL2_ttf.h") + file(STRINGS "${SDL2_TTF_INCLUDE_DIR}/SDL2_ttf.h" SDL2_TTF_VERSION_MAJOR_LINE REGEX "^#define[ \t]+SDL2_TTF_MAJOR_VERSION[ \t]+[0-9]+$") + file(STRINGS "${SDL2_TTF_INCLUDE_DIR}/SDL2_ttf.h" SDL2_TTF_VERSION_MINOR_LINE REGEX "^#define[ \t]+SDL2_TTF_MINOR_VERSION[ \t]+[0-9]+$") + file(STRINGS "${SDL2_TTF_INCLUDE_DIR}/SDL2_ttf.h" SDL2_TTF_VERSION_PATCH_LINE REGEX "^#define[ \t]+SDL2_TTF_PATCHLEVEL[ \t]+[0-9]+$") + string(REGEX REPLACE "^#define[ \t]+SDL2_TTF_MAJOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_TTF_VERSION_MAJOR "${SDL2_TTF_VERSION_MAJOR_LINE}") + string(REGEX REPLACE "^#define[ \t]+SDL2_TTF_MINOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_TTF_VERSION_MINOR "${SDL2_TTF_VERSION_MINOR_LINE}") + string(REGEX REPLACE "^#define[ \t]+SDL2_TTF_PATCHLEVEL[ \t]+([0-9]+)$" "\\1" SDL2_TTF_VERSION_PATCH "${SDL2_TTF_VERSION_PATCH_LINE}") + set(SDL2_TTF_VERSION_STRING ${SDL2_TTF_VERSION_MAJOR}.${SDL2_TTF_VERSION_MINOR}.${SDL2_TTF_VERSION_PATCH}) + unset(SDL2_TTF_VERSION_MAJOR_LINE) + unset(SDL2_TTF_VERSION_MINOR_LINE) + unset(SDL2_TTF_VERSION_PATCH_LINE) + unset(SDL2_TTF_VERSION_MAJOR) + unset(SDL2_TTF_VERSION_MINOR) + unset(SDL2_TTF_VERSION_PATCH) +endif() + +set(SDL2_TTF_LIBRARIES ${SDL2_TTF_LIBRARY}) +set(SDL2_TTF_INCLUDE_DIRS ${SDL2_TTF_INCLUDE_DIR}) + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2_ttf + REQUIRED_VARS SDL2_TTF_LIBRARIES SDL2_TTF_INCLUDE_DIRS + VERSION_VAR SDL2_TTF_VERSION_STRING) + +# for backward compatiblity +set(SDL2TTF_LIBRARY ${SDL2_TTF_LIBRARIES}) +set(SDL2TTF_INCLUDE_DIR ${SDL2_TTF_INCLUDE_DIRS}) +set(SDL2TTF_FOUND ${SDL2_TTF_FOUND}) + +mark_as_advanced(SDL2_TTF_LIBRARY SDL2_TTF_INCLUDE_DIR) diff -r fcbdee9cdd74 -r b894922d58cc cmake_modules/paths.cmake --- a/cmake_modules/paths.cmake Tue Sep 08 19:20:58 2015 +0300 +++ b/cmake_modules/paths.cmake Mon Nov 16 22:57:24 2015 +0300 @@ -15,7 +15,7 @@ #resource paths if(UNIX AND NOT APPLE) set(target_binary_install_dir "bin" CACHE PATH "install dest for binaries") - set(target_library_install_dir "lib" CACHE PATH "install dest for libs") + set(target_library_install_dir "lib${LIB_SUFFIX}" CACHE PATH "install dest for libs") string(SUBSTRING "${DATA_INSTALL_DIR}" 0 1 sharepath_start) if(${sharepath_start} MATCHES "/") diff -r fcbdee9cdd74 -r b894922d58cc cmake_modules/platform.cmake diff -r fcbdee9cdd74 -r b894922d58cc gameServer/Actions.hs --- a/gameServer/Actions.hs Tue Sep 08 19:20:58 2015 +0300 +++ b/gameServer/Actions.hs Mon Nov 16 22:57:24 2015 +0300 @@ -744,10 +744,6 @@ 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 (isJust cinfo) $ mapM_ processAction [ @@ -757,15 +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 p (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) diff -r fcbdee9cdd74 -r b894922d58cc gameServer/CoreTypes.hs --- a/gameServer/CoreTypes.hs Tue Sep 08 19:20:58 2015 +0300 +++ b/gameServer/CoreTypes.hs Mon Nov 16 22:57:24 2015 +0300 @@ -16,7 +16,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. \-} -{-# LANGUAGE CPP, OverloadedStrings, DeriveDataTypeable #-} +{-# LANGUAGE CPP, OverloadedStrings, DeriveDataTypeable, GeneralizedNewtypeDeriving #-} module CoreTypes where import Control.Concurrent @@ -119,7 +119,8 @@ CheckInfo { recordFileName :: String, - recordTeams :: [TeamInfo] + recordTeams :: [TeamInfo], + details :: Maybe GameDetails } data ClientInfo = @@ -303,8 +304,8 @@ ServerInfo True "

http://www.hedgewars.org/

" - "

Hedgewars 0.9.19 is out! Please update.

Download page here" - 47 -- latestReleaseVersion + "

Hedgewars 0.9.22 is out! Please update.

Download page here" + 51 -- latestReleaseVersion 41 -- earliestCompatibleVersion 46631 "" @@ -345,10 +346,21 @@ CheckAccount ClientIndex Int B.ByteString B.ByteString | ClearCache | SendStats Int Int - | StoreAchievements Word16 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 fcbdee9cdd74 -r b894922d58cc gameServer/EngineInteraction.hs --- a/gameServer/EngineInteraction.hs Tue Sep 08 19:20:58 2015 +0300 +++ b/gameServer/EngineInteraction.hs Mon Nov 16 22:57:24 2015 +0300 @@ -100,8 +100,8 @@ -> Map.Map B.ByteString B.ByteString -> Map.Map B.ByteString [B.ByteString] -> [B.ByteString] - -> [B.ByteString] -replayToDemo ti mParams prms msgs = if not sane then [] else 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 @@ -117,7 +117,7 @@ , concatMap teamSetup ti , msgs , [em "!"] - ] + ]) where keys1, keys2 :: Set.Set B.ByteString keys1 = Set.fromList ["FEATURE_SIZE", "MAP", "MAPGEN", "MAZE_SIZE", "SEED", "TEMPLATE"] @@ -126,8 +126,10 @@ && 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+"] - maybeScript = let s = head . fromMaybe ["Normal"] $ Map.lookup "SCRIPT" prms in if s == "Normal" then [] else [eml ["escript Scripts/Multiplayer/", s, ".lua"]] + 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" @@ -161,6 +163,10 @@ ]) $ 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 = @@ -190,6 +196,7 @@ , ("e$minesnum", 1) , ("e$minedudpct", 1) , ("e$explosives", 1) + , ("e$airmines", 1) , ("e$healthprob", 1) , ("e$hcaseamount", 1) , ("e$waterrise", 1) diff -r fcbdee9cdd74 -r b894922d58cc gameServer/OfficialServer/GameReplayStore.hs --- a/gameServer/OfficialServer/GameReplayStore.hs Tue Sep 08 19:20:58 2015 +0300 +++ b/gameServer/OfficialServer/GameReplayStore.hs Mon Nov 16 22:57:24 2015 +0300 @@ -16,7 +16,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. \-} -{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE ScopedTypeVariables, OverloadedStrings #-} module OfficialServer.GameReplayStore where import Data.Time @@ -38,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 () @@ -70,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 (Just $ CheckInfo fileName [], [])) $ 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) - , let d = replayToDemo teams (Map.fromList params1) (Map.fromList params2) (reverse roundMsgs) in d `deepseq` d + 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 fcbdee9cdd74 -r b894922d58cc gameServer/OfficialServer/Glicko2.hs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gameServer/OfficialServer/Glicko2.hs Mon Nov 16 22:57:24 2015 +0300 @@ -0,0 +1,70 @@ +{- + Glicko2, as described in http://www.glicko.net/glicko/glicko2.pdf +-} + +module OfficialServer.Glicko2 where + +data RatingData = RatingData { + ratingValue + , rD + , volatility :: Double + } +data GameData = GameData { + opponentRating :: RatingData, + gameScore :: Double + } + +τ, ε :: Double +τ = 0.2 +ε = 0.000001 + +g_φ :: Double -> Double +g_φ φ = 1 / sqrt (1 + 3 * φ^2 / pi^2) + +calcE :: RatingData -> GameData -> (Double, Double, Double) +calcE oldRating (GameData oppRating s) = ( + 1 / (1 + exp (g_φᵢ * (μᵢ - μ))) + , g_φᵢ + , s + ) + where + μ = (ratingValue oldRating - 1500) / 173.7178 + φ = rD oldRating / 173.7178 + μᵢ = (ratingValue oppRating - 1500) / 173.7178 + φᵢ = rD oppRating / 173.7178 + g_φᵢ = g_φ φᵢ + + +calcNewRating :: RatingData -> [GameData] -> (Int, RatingData) +calcNewRating oldRating [] = (0, RatingData (ratingValue oldRating) (173.7178 * sqrt (φ ^ 2 + σ ^ 2)) σ) + where + φ = rD oldRating / 173.7178 + σ = volatility oldRating + +calcNewRating oldRating games = (length games, RatingData (173.7178 * μ' + 1500) (173.7178 * sqrt φ'sqr) σ') + where + _Es = map (calcE oldRating) games + υ = 1 / sum (map υ_p _Es) + υ_p (_Eᵢ, g_φᵢ, _) = g_φᵢ ^ 2 * _Eᵢ * (1 - _Eᵢ) + _Δ = υ * part1 + part1 = sum (map _Δ_p _Es) + _Δ_p (_Eᵢ, g_φᵢ, sᵢ) = g_φᵢ * (sᵢ - _Eᵢ) + + μ = (ratingValue oldRating - 1500) / 173.7178 + φ = rD oldRating / 173.7178 + σ = volatility oldRating + + a = log (σ ^ 2) + f :: Double -> Double + f x = exp x * (_Δ ^ 2 - φ ^ 2 - υ - exp x) / 2 / (φ ^ 2 + υ + exp x) ^ 2 - (x - a) / τ ^ 2 + + _A = a + _B = if _Δ ^ 2 > φ ^ 2 + υ then log (_Δ ^ 2 - φ ^ 2 - υ) else head . dropWhile ((>) 0 . f) . map (\k -> a - k * τ) $ [1 ..] + fA = f _A + fB = f _B + σ' = (\(_A, _, _, _) -> exp (_A / 2)) . head . dropWhile (\(_A, _, _B, _) -> abs (_B - _A) > ε) $ iterate step5 (_A, fA, _B, fB) + step5 (_A, fA, _B, fB) = let _C = _A + (_A - _B) * fA / (fB - fA); fC = f _C in + if fC * fB < 0 then (_B, fB, _C, fC) else (_A, fA / 2, _C, fC) + + φ'sqr = 1 / (1 / (φ ^ 2 + σ' ^ 2) + 1 / υ) + μ' = μ + φ'sqr * part1 diff -r fcbdee9cdd74 -r b894922d58cc gameServer/OfficialServer/checker.hs --- a/gameServer/OfficialServer/checker.hs Tue Sep 08 19:20:58 2015 +0300 +++ b/gameServer/OfficialServer/checker.hs Mon Nov 16 22:57:24 2015 +0300 @@ -54,7 +54,7 @@ deriving Show serverAddress = "netserver.hedgewars.org" -protocolNumber = "49" +protocolNumber = "51" getLines :: Handle -> IO [B.ByteString] getLines h = g diff -r fcbdee9cdd74 -r b894922d58cc gameServer/OfficialServer/extdbinterface.hs --- a/gameServer/OfficialServer/extdbinterface.hs Tue Sep 08 19:20:58 2015 +0300 +++ b/gameServer/OfficialServer/extdbinterface.hs Mon Nov 16 22:57:24 2015 +0300 @@ -28,9 +28,10 @@ import Database.MySQL.Simple import Database.MySQL.Simple.QueryResults import Database.MySQL.Simple.Result -import Data.List (lookup) +import Data.List (lookup, elem) import qualified Data.ByteString.Char8 as B import Data.Word +import Data.Int -------------------------- import CoreTypes import Utils @@ -50,6 +51,15 @@ \ 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 = ?" @@ -83,36 +93,54 @@ SendStats clients rooms -> void $ execute dbConn dbQueryStats (clients, rooms) - StoreAchievements p fileName teams info -> - mapM_ (execute dbConn dbQueryAchievement) $ (parseStats p fileName teams) info + 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 = B.take 19 . B.drop 8 parseStats :: - Word16 + Connection + -> Word16 -> B.ByteString -> [(B.ByteString, B.ByteString)] - -> [B.ByteString] - -> [(B.ByteString, B.ByteString, B.ByteString, Int, B.ByteString, B.ByteString, Int)] -parseStats p fileName teams = ps + -> 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) = + 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 + , (readInt_ value) :: Int , fileName , location - , fromIntegral p + , (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 :: SomeException) -> hPutStrLn stderr $ show e) $ diff -r fcbdee9cdd74 -r b894922d58cc gameServer/OfficialServer/updateRating.hs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gameServer/OfficialServer/updateRating.hs Mon Nov 16 22:57:24 2015 +0300 @@ -0,0 +1,103 @@ +{-# LANGUAGE ScopedTypeVariables, OverloadedStrings #-} +module Main where + +import Data.Maybe +import Data.TConfig +import qualified Data.ByteString.Char8 as B +import Database.MySQL.Simple +import Database.MySQL.Simple.QueryResults +import Database.MySQL.Simple.Result +import Control.Monad +import Control.Exception +import System.IO +import qualified Data.Map as Map +import Data.Time.Clock +------ +import OfficialServer.Glicko2 + + +queryEpochDates = "SELECT epoch, todatetime, todatetime + INTERVAL 1 week FROM rating_epochs WHERE epoch = (SELECT MAX(epoch) FROM rating_epochs)" +queryPreviousRatings = "SELECT v.userid, v.rating, v.rd, v.volatility FROM rating_values as v WHERE (v.epoch = (SELECT MAX(epoch) FROM rating_epochs))" +queryGameResults = + "SELECT \ + \ p.userid \ + \ , p.place \ + \ , COALESCE(vp.rating, 1500) \ + \ , COALESCE(vp.rd, 350) \ + \ , COALESCE(vp.volatility, 0.06) \ + \ , COALESCE(vo.rating, 1500) \ + \ , COALESCE(vo.rd, 350) \ + \ , COALESCE(vo.volatility, 0.06) \ + \ FROM \ + \ (SELECT epoch, todatetime FROM rating_epochs WHERE epoch = (SELECT MAX(epoch) FROM rating_epochs)) as e \ + \ JOIN rating_games as g ON (g.time BETWEEN e.todatetime AND e.todatetime + INTERVAL 1 WEEK - INTERVAL 1 SECOND) \ + \ JOIN rating_players as p ON (p.gameid = g.id) \ + \ JOIN rating_players as o ON (p.gameid = o.gameid AND p.userid <> o.userid AND (p.place = 0 OR (p.place <> o.place))) \ + \ LEFT OUTER JOIN rating_values as vp ON (vp.epoch = e.epoch AND vp.userid = p.userid) \ + \ LEFT OUTER JOIN rating_values as vo ON (vo.epoch = e.epoch AND vo.userid = o.userid) \ + \ GROUP BY p.userid, p.gameid, p.place \ + \ ORDER BY p.userid" +insertNewRatings = "INSERT INTO rating_values (userid, epoch, rating, rd, volatility, games) VALUES (?, ?, ?, ?, ?, ?)" +insertNewEpoch = "INSERT INTO rating_epochs (epoch, todatetime) VALUES (?, ?)" + +mergeRatingData :: Map.Map Int (RatingData, [GameData]) -> [(Int, (RatingData, [GameData]))] -> Map.Map Int (RatingData, [GameData]) +mergeRatingData m s = foldr (uncurry (Map.insertWith mf)) m s + where + mf (rd, gds) (_, gds2) = (rd, gds ++ gds2) + +calculateRatings dbConn = do + [(epochNum :: Int, fromDate :: UTCTime, toDate :: UTCTime)] <- query_ dbConn queryEpochDates + initRatingData <- (Map.fromList . map fromDBrating) `fmap` query_ dbConn queryPreviousRatings + gameData <- map fromGameResult `fmap` query_ dbConn queryGameResults + let mData = map getNewRating . Map.toList $ mergeRatingData initRatingData gameData + executeMany dbConn insertNewRatings $ map (toInsert epochNum) mData + execute dbConn insertNewEpoch (epochNum + 1, toDate) + return () + where + toInsert e (i, (g, RatingData r rd v)) = (i, e + 1, r, rd, v, g) + getNewRating (a, d) = (a, uncurry calcNewRating d) + convPlace :: Int -> Double + convPlace 0 = 0.5 + convPlace 1 = 1.0 + convPlace 2 = 0.0 + convPlace _ = error "Incorrect place value" + fromDBrating (a, b, c, d) = (a, (RatingData b c d, [])) + fromGameResult (pid, place, prating, pRD, pvol, orating, oRD, ovol) = + (pid, + (RatingData prating pRD pvol + , [GameData (RatingData orating oRD ovol) $ convPlace place])) + + +data DBConnectInfo = DBConnectInfo { + dbHost + , dbName + , dbLogin + , dbPassword :: B.ByteString + } + +cfgFileName :: String +cfgFileName = "hedgewars-server.ini" + + +readServerConfig :: ConnectInfo -> IO ConnectInfo +readServerConfig ci = do + cfg <- readConfig cfgFileName + return $ ci{ + connectHost = value "dbHost" cfg + , connectDatabase = value "dbName" cfg + , connectUser = value "dbLogin" cfg + , connectPassword = value "dbPassword" cfg + } + where + value n c = fromJust2 n $ getValue n c + fromJust2 n Nothing = error $ "Missing config entry " ++ n + fromJust2 _ (Just a) = a + +dbConnectionLoop mySQLConnectionInfo = + Control.Exception.handle (\(e :: SomeException) -> hPutStrLn stderr $ show e) $ + bracket + (connect mySQLConnectionInfo) + close + calculateRatings + +main = readServerConfig defaultConnectInfo >>= dbConnectionLoop diff -r fcbdee9cdd74 -r b894922d58cc gameServer/Utils.hs --- a/gameServer/Utils.hs Tue Sep 08 19:20:58 2015 +0300 +++ b/gameServer/Utils.hs Mon Nov 16 22:57:24 2015 +0300 @@ -115,6 +115,8 @@ , (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 diff -r fcbdee9cdd74 -r b894922d58cc hedgewars/ArgParsers.pas --- a/hedgewars/ArgParsers.pas Tue Sep 08 19:20:58 2015 +0300 +++ b/hedgewars/ArgParsers.pas Mon Nov 16 22:57:24 2015 +0300 @@ -321,7 +321,7 @@ var tmpInt: LongInt; begin - paramIndex:= 1; + paramIndex:= {$IFDEF HWLIBRARY}0{$ELSE}1{$ENDIF}; paramTotal:= ParamCount; //-1 because pascal enumeration is inclusive WriteLn(stdout, 'total parameters: ' + inttostr(paramTotal)); diff -r fcbdee9cdd74 -r b894922d58cc hedgewars/CMakeLists.txt --- a/hedgewars/CMakeLists.txt Tue Sep 08 19:20:58 2015 +0300 +++ b/hedgewars/CMakeLists.txt Mon Nov 16 22:57:24 2015 +0300 @@ -1,8 +1,10 @@ -find_package(SDL1or2) -find_package(SDL_image) -find_package(SDL_net) -find_package(SDL_ttf) -find_package(SDL_mixer) +enable_language(Pascal) + +find_package(SDL2 REQUIRED) +find_package(SDL2_image REQUIRED) +find_package(SDL2_net REQUIRED) +find_package(SDL2_ttf REQUIRED) +find_package(SDL2_mixer REQUIRED) include(CheckLibraryExists) include(${CMAKE_MODULE_PATH}/utils.cmake) @@ -136,22 +138,16 @@ #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) + string(FIND "${SDL2_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") + add_flag_append(CMAKE_Pascal_FLAGS "-k-lsdl2 -k-lsdl2_image -k-lsdl2_mixer -k-lsdl2_ttf -k-lsdl2_net") else() - add_flag_append(CMAKE_Pascal_FLAGS "-k-framework -kSDL -k-framework -kSDL_image -k-framework -k SDL_mixer -k-framework -k SDL_net -k-framework -kSDL_net") + add_flag_append(CMAKE_Pascal_FLAGS "-k-framework -kSDL2 -k-framework -kSDL2_image -k-framework -kSDL2_mixer -k-framework -kSDL2_net -k-framework -kSDL2_net -k-framework -kSDL2_ttf") endif() endif() @@ -159,8 +155,6 @@ add_subdirectory(avwrapper) list(APPEND HW_LINK_LIBS avwrapper) add_definitions(-dUSE_VIDEO_RECORDING) - #only for SDL < 2, linking carried out by fpc - find_package_or_disable_msg(GLUT NOVIDEOREC "Video recording will not be built") endif() find_package_or_disable_msg(PNG NOPNG "Screenshots will be saved in BMP") @@ -198,22 +192,6 @@ list(APPEND HW_LINK_LIBS physlayer) -#Mix_Init/Mix_Quit from SDL_mixer 1.2.10 -check_library_exists(${SDLMIXER_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(${SDLIMAGE_LIBRARY} IMG_Init "" HAVE_IMGINIT) -if(HAVE_IMGINIT) - add_definitions(-dSDL_IMAGE_NEWER) -endif(HAVE_IMGINIT) - -if(${SDL_VERSION} VERSION_GREATER 1.3) - add_definitions(-dSDL2) -endif() - #opengl 2 IF(GL2) add_definitions(-dGL2) diff -r fcbdee9cdd74 -r b894922d58cc hedgewars/SDLh.pas --- a/hedgewars/SDLh.pas Tue Sep 08 19:20:58 2015 +0300 +++ b/hedgewars/SDLh.pas Mon Nov 16 22:57:24 2015 +0300 @@ -57,17 +57,17 @@ (* SDL *) const {$IFDEF WIN32} - SDLLibName = 'SDL.dll'; - SDL_TTFLibName = 'SDL_ttf.dll'; - SDL_MixerLibName = 'SDL_mixer.dll'; - SDL_ImageLibName = 'SDL_image.dll'; - SDL_NetLibName = 'SDL_net.dll'; + SDLLibName = 'SDL2.dll'; + SDL_TTFLibName = 'SDL2_ttf.dll'; + SDL_MixerLibName = 'SDL2_mixer.dll'; + SDL_ImageLibName = 'SDL2_image.dll'; + SDL_NetLibName = 'SDL2_net.dll'; {$ELSE} - SDLLibName = 'libSDL'; - SDL_TTFLibName = 'libSDL_ttf'; - SDL_MixerLibName = 'libSDL_mixer'; - SDL_ImageLibName = 'libSDL_image'; - SDL_NetLibName = 'libSDL_net'; + SDLLibName = 'libSDL2'; + SDL_TTFLibName = 'libSDL2_ttf'; + SDL_MixerLibName = 'libSDL2_mixer'; + SDL_ImageLibName = 'libSDL2_image'; + SDL_NetLibName = 'libSDL2_net'; {$ENDIF} ///////////////////////////////////////////////////////////////// @@ -79,14 +79,9 @@ SDL_INIT_AUDIO = $00000010; SDL_INIT_VIDEO = $00000020; // implies SDL_INIT_EVENTS (sdl2) SDL_INIT_JOYSTICK = $00000200; // implies SDL_INIT_EVENTS (sdl2) -{$IFDEF SDL2} SDL_INIT_HAPTIC = $00001000; SDL_INIT_GAMECONTROLLER = $00002000; // implies SDL_INIT_JOYSTICK SDL_INIT_EVENTS = $00004000; -{$ELSE} - SDL_INIT_CDROM = $00000100; - SDL_INIT_EVENTTHREAD = $01000000; -{$ENDIF} SDL_INIT_NOPARACHUTE = $00100000; //SDL_INIT_EVERYTHING // unsafe, init subsystems one at a time @@ -100,7 +95,9 @@ SDL_BUTTON_WHEELDOWN = 5; -{$IFDEF SDL2} + SDL_TEXTEDITINGEVENT_TEXT_SIZE = 32; + SDL_TEXTINPUTEVENT_TEXT_SIZE = 32; + // SDL_Event types // pascal does not support unions as is, so we list here every possible event // and later associate a struct type each @@ -193,39 +190,6 @@ SDL_WINDOWEVENT_FOCUS_GAINED = 12; //*< Window has gained keyboard focus SDL_WINDOWEVENT_FOCUS_LOST = 13; //*< Window has lost keyboard focus SDL_WINDOWEVENT_CLOSE = 14; //*< The window manager requests that the window be closed */ -{$ELSE} - // SDL_Event types - SDL_NOEVENT = 0; - SDL_ACTIVEEVENT = 1; - SDL_KEYDOWN = 2; - SDL_KEYUP = 3; - SDL_MOUSEMOTION = 4; - SDL_MOUSEBUTTONDOWN = 5; - SDL_MOUSEBUTTONUP = 6; - SDL_JOYAXISMOTION = 7; - SDL_JOYBALLMOTION = 8; - SDL_JOYHATMOTION = 9; - SDL_JOYBUTTONDOWN = 10; - SDL_JOYBUTTONUP = 11; - SDL_QUITEV = 12; - SDL_VIDEORESIZE = 16; - - // SDL_Surface flags - SDL_SWSURFACE = $00000000; - SDL_HWSURFACE = $00000001; - SDL_OPENGL = $00000002; - SDL_ASYNCBLIT = $00000004; - SDL_RESIZABLE = $00000010; - SDL_NOFRAME = $00000020; - SDL_HWACCEL = $00000100; - SDL_SRCCOLORKEY = $00001000; - SDL_RLEACCEL = $00004000; - SDL_SRCALPHA = $00010000; - SDL_ANYFORMAT = $00100000; - SDL_HWPALETTE = $20000000; - SDL_DOUBLEBUF = $40000000; - SDL_FULLSCREEN = $80000000; -{$ENDIF} {$IFDEF ENDIAN_LITTLE} RMask = $000000FF; @@ -261,11 +225,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; @@ -288,7 +254,8 @@ IMG_INIT_PNG = $00000002; IMG_INIT_TIF = $00000004; - {* SDL_keysym *} + {* SDL_keycode *} + SDLK_UNKNOWN = 0; SDLK_BACKSPACE = 8; SDLK_RETURN = 13; SDLK_ESCAPE = 27; @@ -309,6 +276,250 @@ SDLK_PAGEUP = 280; SDLK_PAGEDOWN = 281; + // special keycodes (for modifier keys etc. will have this bit set) + SDLK_SCANCODE_MASK = (1 shl 30); + + SDL_SCANCODE_UNKNOWN = 0; + SDL_SCANCODE_A = 4; + SDL_SCANCODE_B = 5; + SDL_SCANCODE_C = 6; + SDL_SCANCODE_D = 7; + SDL_SCANCODE_E = 8; + SDL_SCANCODE_F = 9; + SDL_SCANCODE_G = 10; + SDL_SCANCODE_H = 11; + SDL_SCANCODE_I = 12; + SDL_SCANCODE_J = 13; + SDL_SCANCODE_K = 14; + SDL_SCANCODE_L = 15; + SDL_SCANCODE_M = 16; + SDL_SCANCODE_N = 17; + SDL_SCANCODE_O = 18; + SDL_SCANCODE_P = 19; + SDL_SCANCODE_Q = 20; + SDL_SCANCODE_R = 21; + SDL_SCANCODE_S = 22; + SDL_SCANCODE_T = 23; + SDL_SCANCODE_U = 24; + SDL_SCANCODE_V = 25; + SDL_SCANCODE_W = 26; + SDL_SCANCODE_X = 27; + SDL_SCANCODE_Y = 28; + SDL_SCANCODE_Z = 29; + SDL_SCANCODE_1 = 30; + SDL_SCANCODE_2 = 31; + SDL_SCANCODE_3 = 32; + SDL_SCANCODE_4 = 33; + SDL_SCANCODE_5 = 34; + SDL_SCANCODE_6 = 35; + SDL_SCANCODE_7 = 36; + SDL_SCANCODE_8 = 37; + SDL_SCANCODE_9 = 38; + SDL_SCANCODE_0 = 39; + SDL_SCANCODE_RETURN = 40; + SDL_SCANCODE_ESCAPE = 41; + SDL_SCANCODE_BACKSPACE = 42; + SDL_SCANCODE_TAB = 43; + SDL_SCANCODE_SPACE = 44; + SDL_SCANCODE_MINUS = 45; + SDL_SCANCODE_EQUALS = 46; + SDL_SCANCODE_LEFTBRACKET = 47; + SDL_SCANCODE_RIGHTBRACKET = 48; + SDL_SCANCODE_BACKSLASH = 49; + SDL_SCANCODE_NONUSHASH = 50; + SDL_SCANCODE_SEMICOLON = 51; + SDL_SCANCODE_APOSTROPHE = 52; + SDL_SCANCODE_GRAVE = 53; + SDL_SCANCODE_COMMA = 54; + SDL_SCANCODE_PERIOD = 55; + SDL_SCANCODE_SLASH = 56; + SDL_SCANCODE_CAPSLOCK = 57; + SDL_SCANCODE_F1 = 58; + SDL_SCANCODE_F2 = 59; + SDL_SCANCODE_F3 = 60; + SDL_SCANCODE_F4 = 61; + SDL_SCANCODE_F5 = 62; + SDL_SCANCODE_F6 = 63; + SDL_SCANCODE_F7 = 64; + SDL_SCANCODE_F8 = 65; + SDL_SCANCODE_F9 = 66; + SDL_SCANCODE_F10 = 67; + SDL_SCANCODE_F11 = 68; + SDL_SCANCODE_F12 = 69; + SDL_SCANCODE_PRINTSCREEN = 70; + SDL_SCANCODE_SCROLLLOCK = 71; + SDL_SCANCODE_PAUSE = 72; + SDL_SCANCODE_INSERT = 73; + SDL_SCANCODE_HOME = 74; + SDL_SCANCODE_PAGEUP = 75; + SDL_SCANCODE_DELETE = 76; + SDL_SCANCODE_END = 77; + SDL_SCANCODE_PAGEDOWN = 78; + SDL_SCANCODE_RIGHT = 79; + SDL_SCANCODE_LEFT = 80; + SDL_SCANCODE_DOWN = 81; + SDL_SCANCODE_UP = 82; + SDL_SCANCODE_NUMLOCKCLEAR = 83; + SDL_SCANCODE_KP_DIVIDE = 84; + SDL_SCANCODE_KP_MULTIPLY = 85; + SDL_SCANCODE_KP_MINUS = 86; + SDL_SCANCODE_KP_PLUS = 87; + SDL_SCANCODE_KP_ENTER = 88; + SDL_SCANCODE_KP_1 = 89; + SDL_SCANCODE_KP_2 = 90; + SDL_SCANCODE_KP_3 = 91; + SDL_SCANCODE_KP_4 = 92; + SDL_SCANCODE_KP_5 = 93; + SDL_SCANCODE_KP_6 = 94; + SDL_SCANCODE_KP_7 = 95; + SDL_SCANCODE_KP_8 = 96; + SDL_SCANCODE_KP_9 = 97; + SDL_SCANCODE_KP_0 = 98; + SDL_SCANCODE_KP_PERIOD = 99; + SDL_SCANCODE_NONUSBACKSLASH = 100; + SDL_SCANCODE_APPLICATION = 101; + SDL_SCANCODE_POWER = 102; + SDL_SCANCODE_KP_EQUALS = 103; + SDL_SCANCODE_F13 = 104; + SDL_SCANCODE_F14 = 105; + SDL_SCANCODE_F15 = 106; + SDL_SCANCODE_F16 = 107; + SDL_SCANCODE_F17 = 108; + SDL_SCANCODE_F18 = 109; + SDL_SCANCODE_F19 = 110; + SDL_SCANCODE_F20 = 111; + SDL_SCANCODE_F21 = 112; + SDL_SCANCODE_F22 = 113; + SDL_SCANCODE_F23 = 114; + SDL_SCANCODE_F24 = 115; + SDL_SCANCODE_EXECUTE = 116; + SDL_SCANCODE_HELP = 117; + SDL_SCANCODE_MENU = 118; + SDL_SCANCODE_SELECT = 119; + SDL_SCANCODE_STOP = 120; + SDL_SCANCODE_AGAIN = 121; + SDL_SCANCODE_UNDO = 122; + SDL_SCANCODE_CUT = 123; + SDL_SCANCODE_COPY = 124; + SDL_SCANCODE_PASTE = 125; + SDL_SCANCODE_FIND = 126; + SDL_SCANCODE_MUTE = 127; + SDL_SCANCODE_VOLUMEUP = 128; + SDL_SCANCODE_VOLUMEDOWN = 129; + SDL_SCANCODE_KP_COMMA = 133; + SDL_SCANCODE_KP_EQUALSAS400 = 134; + SDL_SCANCODE_INTERNATIONAL1 = 135; + SDL_SCANCODE_INTERNATIONAL2 = 136; + SDL_SCANCODE_INTERNATIONAL3 = 137; + SDL_SCANCODE_INTERNATIONAL4 = 138; + SDL_SCANCODE_INTERNATIONAL5 = 139; + SDL_SCANCODE_INTERNATIONAL6 = 140; + SDL_SCANCODE_INTERNATIONAL7 = 141; + SDL_SCANCODE_INTERNATIONAL8 = 142; + SDL_SCANCODE_INTERNATIONAL9 = 143; + SDL_SCANCODE_LANG1 = 144; (*< Hangul/English toggle *) + SDL_SCANCODE_LANG2 = 145; (*< Hanja conversion *) + SDL_SCANCODE_LANG3 = 146; (*< Katakana *) + SDL_SCANCODE_LANG4 = 147; (*< Hiragana *) + SDL_SCANCODE_LANG5 = 148; (*< Zenkaku/Hankaku *) + SDL_SCANCODE_LANG6 = 149; (*< reserved *) + SDL_SCANCODE_LANG7 = 150; (*< reserved *) + SDL_SCANCODE_LANG8 = 151; (*< reserved *) + SDL_SCANCODE_LANG9 = 152; (*< reserved *) + SDL_SCANCODE_ALTERASE = 153; + SDL_SCANCODE_SYSREQ = 154; + SDL_SCANCODE_CANCEL = 155; + SDL_SCANCODE_CLEAR = 156; + SDL_SCANCODE_PRIOR = 157; + SDL_SCANCODE_RETURN2 = 158; + SDL_SCANCODE_SEPARATOR = 159; + SDL_SCANCODE_OUT = 160; + SDL_SCANCODE_OPER = 161; + SDL_SCANCODE_CLEARAGAIN = 162; + SDL_SCANCODE_CRSEL = 163; + SDL_SCANCODE_EXSEL = 164; + SDL_SCANCODE_KP_00 = 176; + SDL_SCANCODE_KP_000 = 177; + SDL_SCANCODE_THOUSANDSSEPARATOR = 178; + SDL_SCANCODE_DECIMALSEPARATOR = 179; + SDL_SCANCODE_CURRENCYUNIT = 180; + SDL_SCANCODE_CURRENCYSUBUNIT = 181; + SDL_SCANCODE_KP_LEFTPAREN = 182; + SDL_SCANCODE_KP_RIGHTPAREN = 183; + SDL_SCANCODE_KP_LEFTBRACE = 184; + SDL_SCANCODE_KP_RIGHTBRACE = 185; + SDL_SCANCODE_KP_TAB = 186; + SDL_SCANCODE_KP_BACKSPACE = 187; + SDL_SCANCODE_KP_A = 188; + SDL_SCANCODE_KP_B = 189; + SDL_SCANCODE_KP_C = 190; + SDL_SCANCODE_KP_D = 191; + SDL_SCANCODE_KP_E = 192; + SDL_SCANCODE_KP_F = 193; + SDL_SCANCODE_KP_XOR = 194; + SDL_SCANCODE_KP_POWER = 195; + SDL_SCANCODE_KP_PERCENT = 196; + SDL_SCANCODE_KP_LESS = 197; + SDL_SCANCODE_KP_GREATER = 198; + SDL_SCANCODE_KP_AMPERSAND = 199; + SDL_SCANCODE_KP_DBLAMPERSAND = 200; + SDL_SCANCODE_KP_VERTICALBAR = 201; + SDL_SCANCODE_KP_DBLVERTICALBAR = 202; + SDL_SCANCODE_KP_COLON = 203; + SDL_SCANCODE_KP_HASH = 204; + SDL_SCANCODE_KP_SPACE = 205; + SDL_SCANCODE_KP_AT = 206; + SDL_SCANCODE_KP_EXCLAM = 207; + SDL_SCANCODE_KP_MEMSTORE = 208; + SDL_SCANCODE_KP_MEMRECALL = 209; + SDL_SCANCODE_KP_MEMCLEAR = 210; + SDL_SCANCODE_KP_MEMADD = 211; + SDL_SCANCODE_KP_MEMSUBTRACT = 212; + SDL_SCANCODE_KP_MEMMULTIPLY = 213; + SDL_SCANCODE_KP_MEMDIVIDE = 214; + SDL_SCANCODE_KP_PLUSMINUS = 215; + SDL_SCANCODE_KP_CLEAR = 216; + SDL_SCANCODE_KP_CLEARENTRY = 217; + SDL_SCANCODE_KP_BINARY = 218; + SDL_SCANCODE_KP_OCTAL = 219; + SDL_SCANCODE_KP_DECIMAL = 220; + SDL_SCANCODE_KP_HEXADECIMAL = 221; + SDL_SCANCODE_LCTRL = 224; + SDL_SCANCODE_LSHIFT = 225; + SDL_SCANCODE_LALT = 226; + SDL_SCANCODE_LGUI = 227; + SDL_SCANCODE_RCTRL = 228; + SDL_SCANCODE_RSHIFT = 229; + SDL_SCANCODE_RALT = 230; + SDL_SCANCODE_RGUI = 231; + SDL_SCANCODE_MODE = 257; + SDL_SCANCODE_AUDIONEXT = 258; + SDL_SCANCODE_AUDIOPREV = 259; + SDL_SCANCODE_AUDIOSTOP = 260; + SDL_SCANCODE_AUDIOPLAY = 261; + SDL_SCANCODE_AUDIOMUTE = 262; + SDL_SCANCODE_MEDIASELECT = 263; + SDL_SCANCODE_WWW = 264; + SDL_SCANCODE_MAIL = 265; + SDL_SCANCODE_CALCULATOR = 266; + SDL_SCANCODE_COMPUTER = 267; + SDL_SCANCODE_AC_SEARCH = 268; + SDL_SCANCODE_AC_HOME = 269; + SDL_SCANCODE_AC_BACK = 270; + SDL_SCANCODE_AC_FORWARD = 271; + SDL_SCANCODE_AC_STOP = 272; + SDL_SCANCODE_AC_REFRESH = 273; + SDL_SCANCODE_AC_BOOKMARKS = 274; + SDL_SCANCODE_BRIGHTNESSDOWN = 275; + SDL_SCANCODE_BRIGHTNESSUP = 276; + SDL_SCANCODE_DISPLAYSWITCH = 277; + SDL_SCANCODE_KBDILLUMTOGGLE = 278; + SDL_SCANCODE_KBDILLUMDOWN = 279; + SDL_SCANCODE_KBDILLUMUP = 280; + SDL_SCANCODE_EJECT = 281; + SDL_SCANCODE_SLEEP = 282; + SDL_SCANCODE_APP1 = 283; + SDL_SCANCODE_APP2 = 284; ///////////////////////////////////////////////////////////////// /////////////////////// TYPE DEFINITIONS /////////////////////// @@ -319,25 +530,20 @@ // http://www.freepascal.org/docs-html/prog/progsu144.html type -{$IFDEF SDL2} PSDL_Window = Pointer; PSDL_Renderer = Pointer; PSDL_Texture = Pointer; PSDL_GLContext= Pointer; TSDL_TouchId = Int64; -{$ENDIF} TSDL_FingerId = Int64; + TSDL_Keycode = LongInt; + TSDL_Scancode = LongInt; TSDL_eventaction = (SDL_ADDEVENT, SDL_PEEPEVENT, SDL_GETEVENT); PSDL_Rect = ^TSDL_Rect; TSDL_Rect = record -{$IFDEF SDL2} x, y, w, h: LongInt; -{$ELSE} - x, y: SmallInt; - w, h: Word; -{$ENDIF} end; TPoint = record @@ -346,7 +552,6 @@ PSDL_PixelFormat = ^TSDL_PixelFormat; TSDL_PixelFormat = record -{$IFDEF SDL2} format: LongWord; palette: Pointer; BitsPerPixel : Byte; @@ -366,25 +571,6 @@ Ashift: Byte; refcount: LongInt; next: PSDL_PixelFormat; -{$ELSE} - palette: Pointer; - BitsPerPixel : Byte; - BytesPerPixel: Byte; - Rloss : Byte; - Gloss : Byte; - Bloss : Byte; - Aloss : Byte; - Rshift: Byte; - Gshift: Byte; - Bshift: Byte; - Ashift: Byte; - RMask : LongWord; - GMask : LongWord; - BMask : LongWord; - AMask : LongWord; - colorkey: LongWord; - alpha: Byte; -{$ENDIF} end; PSDL_Surface = ^TSDL_Surface; @@ -392,7 +578,7 @@ flags : LongWord; format: PSDL_PixelFormat; w, h : LongInt; - pitch : {$IFDEF SDL2}LongInt{$ELSE}Word{$ENDIF}; + pitch : LongInt; pixels: Pointer; {$IFDEF PAS2C} hwdata : Pointer; @@ -404,16 +590,12 @@ refcount : LongInt; offset : LongInt; {$ELSE} -{$IFDEF SDL2} userdata : Pointer; locked : LongInt; lock_data : Pointer; clip_rect : TSDL_Rect; map : Pointer; refcount : LongInt; -{$ELSE} - offset : LongInt; -{$ENDIF} {$ENDIF} end; @@ -429,18 +611,14 @@ (* SDL_RWops and friends *) PSDL_RWops = ^TSDL_RWops; -{$IFDEF SDL2} TSize = function( context: PSDL_RWops): Int64; cdecl; TSeek = function( context: PSDL_RWops; offset: Int64; whence: LongInt ): Int64; cdecl; -{$ELSE} - TSeek = function( context: PSDL_RWops; offset: LongInt; whence: LongInt ): LongInt; cdecl; -{$ENDIF} TRead = function( context: PSDL_RWops; Ptr: Pointer; size: LongInt; maxnum : LongInt ): LongInt; cdecl; TWrite = function( context: PSDL_RWops; Ptr: Pointer; size: LongInt; num: LongInt ): LongInt; cdecl; TClose = function( context: PSDL_RWops ): LongInt; cdecl; TStdio = record - autoclose: {$IFDEF SDL2}Boolean{$ELSE}LongInt{$ENDIF}; + autoclose: Boolean; fp: Pointer; end; @@ -452,9 +630,7 @@ TUnknown = record data1: Pointer; -{$IFDEF SDL2} data2: Pointer; -{$ENDIF} end; {$IFDEF ANDROID} @@ -471,7 +647,7 @@ size, left: LongInt; end; TWindowsio = record - append : {$IFDEF SDL2}Boolean{$ELSE}LongInt{$ENDIF}; + append : Boolean; h : Pointer; buffer : TWinbuffer; end; @@ -479,9 +655,7 @@ {$ENDIF} TSDL_RWops = record -{$IFDEF SDL2} size: TSize; -{$ENDIF} seek: TSeek; read: TRead; write: TWrite; @@ -503,10 +677,9 @@ {* SDL_Event type definition *} -{$IFDEF SDL2} TSDL_Keysym = record - scancode: LongInt; - sym: LongInt; + scancode: TSDL_Scancode; + sym: TSDL_Keycode; modifier: Word; unused: LongWord; end; @@ -520,21 +693,20 @@ data1, data2: LongInt; end; - // available in sdl12 but not exposed TSDL_TextEditingEvent = record - type_: LongWord; - timestamp: LongWord; - windowID: LongWord; - text: array[0..31] of Byte; - start, lenght: LongInt; + type_: Longword; + timestamp: Longword; + windowID: Longword; + text: array [0..SDL_TEXTEDITINGEVENT_TEXT_SIZE - 1] of char; + start: LongInt; + length: LongInt; end; - // available in sdl12 but not exposed TSDL_TextInputEvent = record - type_: LongWord; - timestamp: LongWord; - windowID: LongWord; - text: array[0..31] of Byte; + type_: Longword; + timestamp: Longword; + windowID: Longword; + text: array [0..SDL_TEXTINPUTEVENT_TEXT_SIZE - 1] of char; end; TSDL_TouchFingerEvent = record @@ -605,167 +777,92 @@ end; TSDL_OSEvent = TSDL_CommonEvent; -{$ELSE} - TSDL_KeySym = record - scancode: Byte; - sym: LongWord; - modifier: LongWord; - unicode: Word; - end; - - TSDL_ActiveEvent = record - type_: Byte; - gain: Byte; - state: Byte; - end; - - TSDL_ResizeEvent = record - type_: Byte; - w, h: LongInt; - end; -{$ENDIF} TSDL_KeyboardEvent = record -{$IFDEF SDL2} type_: LongWord; timestamp: LongWord; windowID: LongWord; state, repeat_, padding2, padding3: Byte; -{$ELSE} - type_, which, state: Byte; -{$ENDIF} keysym: TSDL_Keysym; end; TSDL_MouseMotionEvent = record -{$IFDEF SDL2} type_: LongWord; timestamp: LongWord; windowID: LongWord; which, state: LongWord; x, y, xrel, yrel: LongInt; -{$ELSE} - type_, which, state: Byte; - x, y, xrel, yrel: Word; -{$ENDIF} end; TSDL_MouseButtonEvent = record -{$IFDEF SDL2} type_: LongWord; timestamp: LongWord; windowID: LongWord; which: LongWord; button, state, padding1, padding2: Byte; x, y: LongInt; -{$ELSE} - type_, which, button, state: Byte; - x, y: Word; -{$ENDIF} end; TSDL_MouseWheelEvent = record type_: LongWord; -{$IFDEF SDL2} timestamp: LongWord; windowID: LongWord; which: LongWord; -{$ELSE} - which: Byte; -{$ENDIF} x, y: LongInt; end; TSDL_JoyAxisEvent = record -{$IFDEF SDL2} type_: LongWord; timestamp: LongWord; which: LongWord; -{$ELSE} - type_: Byte; - which: Byte; -{$ENDIF} axis: Byte; -{$IFDEF SDL2} padding1, padding2, padding3: Byte; value: LongInt; padding4: Word; -{$ELSE} - value: SmallInt; -{$ENDIF} end; TSDL_JoyBallEvent = record -{$IFDEF SDL2} type_: LongWord; timestamp: LongWord; which: LongWord; -{$ELSE} - type_: Byte; - which: Byte; -{$ENDIF} ball: Byte; -{$IFDEF SDL2} padding1, padding2, padding3: Byte; -{$ENDIF} xrel, yrel: SmallInt; end; TSDL_JoyHatEvent = record -{$IFDEF SDL2} type_: LongWord; timestamp: LongWord; which: LongWord; -{$ELSE} - type_: Byte; - which: Byte; -{$ENDIF} hat: Byte; value: Byte; -{$IFDEF SDL2} padding1, padding2: Byte; -{$ENDIF} end; TSDL_JoyButtonEvent = record -{$IFDEF SDL2} type_: LongWord; timestamp: LongWord; -{$ELSE} - type_: Byte; -{$ENDIF} which: Byte; button: Byte; state: Byte; -{$IFDEF SDL2} padding1: Byte; -{$ENDIF} end; TSDL_QuitEvent = record -{$IFDEF SDL2} type_: LongWord; timestamp: LongWord; -{$ELSE} - type_: Byte; -{$ENDIF} end; TSDL_UserEvent = record -{$IFDEF SDL2} type_: LongWord; timestamp: LongWord; windowID: LongWord; -{$ELSE} - type_: Byte; -{$ENDIF} code: LongInt; data1, data2: Pointer; end; PSDL_Event = ^TSDL_Event; TSDL_Event = record -{$IFDEF SDL2} case LongInt of SDL_FIRSTEVENT: (type_: LongWord); SDL_COMMONDEVENT: (common: TSDL_CommonEvent); @@ -773,7 +870,7 @@ SDL_KEYDOWN, SDL_KEYUP: (key: TSDL_KeyboardEvent); SDL_TEXTEDITING: (edit: TSDL_TextEditingEvent); - SDL_TEXTINPUT: (tedit: TSDL_TextInputEvent); + SDL_TEXTINPUT: (text: TSDL_TextInputEvent); SDL_MOUSEMOTION: (motion: TSDL_MouseMotionEvent); SDL_MOUSEBUTTONDOWN, SDL_MOUSEBUTTONUP: (button: TSDL_MouseButtonEvent); @@ -801,25 +898,6 @@ SDL_DOLLARGESTURE: (dgesture: TSDL_DollarGestureEvent); SDL_DROPFILE: (drop: TSDL_DropEvent); SDL_ALLEVENTS: (foo: shortstring); -{$ELSE} - case Byte of - SDL_NOEVENT: (type_: Byte); - SDL_ACTIVEEVENT: (active: TSDL_ActiveEvent); - SDL_KEYDOWN, - SDL_KEYUP: (key: TSDL_KeyboardEvent); - SDL_MOUSEMOTION: (motion: TSDL_MouseMotionEvent); - SDL_MOUSEBUTTONDOWN, - SDL_MOUSEBUTTONUP: (button: TSDL_MouseButtonEvent); - SDL_JOYAXISMOTION: (jaxis: TSDL_JoyAxisEvent); - SDL_JOYHATMOTION: (jhat: TSDL_JoyHatEvent); - SDL_JOYBALLMOTION: (jball: TSDL_JoyBallEvent); - SDL_JOYBUTTONDOWN, - SDL_JOYBUTTONUP: (jbutton: TSDL_JoyButtonEvent); - SDL_QUITEV: (quit: TSDL_QuitEvent); - //SDL_SYSWMEVENT,SDL_EVENT_RESERVEDA,SDL_EVENT_RESERVEDB - SDL_VIDEORESIZE: (resize: TSDL_ResizeEvent); - SDL_ALLEVENTS: (foo: shortstring); -{$ENDIF} end; TSDL_EventFilter = function( event : PSDL_Event ): Integer; cdecl; @@ -852,7 +930,6 @@ SDL_GL_MULTISAMPLEBUFFERS, SDL_GL_MULTISAMPLESAMPLES, SDL_GL_ACCELERATED_VISUAL, -{$IFDEF SDL2} SDL_GL_RETAINED_BACKING, SDL_GL_CONTEXT_MAJOR_VERSION, SDL_GL_CONTEXT_MINOR_VERSION, @@ -860,12 +937,8 @@ SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_SHARE_WITH_CURRENT_CONTEXT -{$ELSE} - SDL_GL_SWAP_CONTROL -{$ENDIF} ); -{$IFDEF SDL2} TSDL_ArrayByteOrder = ( // array component order, low Byte -> high Byte SDL_ARRAYORDER_NONE, SDL_ARRAYORDER_RGB, @@ -875,7 +948,6 @@ SDL_ARRAYORDER_BGRA, SDL_ARRAYORDER_ABGR ); -{$ENDIF} // Joystick/Controller support PSDL_Joystick = ^TSDL_Joystick; @@ -947,6 +1019,8 @@ function SDL_InitSubSystem(flags: LongWord): LongInt; cdecl; external SDLLibName; procedure SDL_Quit; cdecl; external SDLLibName; +procedure SDL_free(mem: Pointer); cdecl; external SDLLibName; + procedure SDL_Delay(msec: LongWord); cdecl; external SDLLibName; function SDL_GetTicks: LongWord; cdecl; external SDLLibName; @@ -980,8 +1054,9 @@ function SDL_RWFromFile(filename, mode: PChar): PSDL_RWops; cdecl; external SDLLibName; function SDL_SaveBMP_RW(surface: PSDL_Surface; dst: PSDL_RWops; freedst: LongInt): LongInt; cdecl; external SDLLibName; -{$IFDEF SDL2} function SDL_CreateWindow(title: PChar; x,y,w,h: LongInt; flags: LongWord): PSDL_Window; cdecl; external SDLLibName; +procedure SDL_SetWindowIcon(window: PSDL_Window; icon: PSDL_Surface); cdecl; external SDLLibName; + function SDL_CreateRenderer(window: PSDL_Window; index: LongInt; flags: LongWord): PSDL_Renderer; cdecl; external SDLLibName; function SDL_DestroyWindow(window: PSDL_Window): LongInt; cdecl; external SDLLibName; function SDL_DestroyRenderer(renderer: PSDL_Renderer): LongInt; cdecl; external SDLLibName; @@ -990,7 +1065,7 @@ function SDL_GL_CreateContext(window: PSDL_Window): PSDL_GLContext; cdecl; external SDLLibName; procedure SDL_GL_DeleteContext(context: PSDL_GLContext); cdecl; external SDLLibName; -function SDL_GL_SwapWindow(window: PSDL_Window): LongInt; cdecl; external SDLLibName; +procedure SDL_GL_SwapWindow(window: PSDL_Window); cdecl; external SDLLibName; function SDL_GL_SetSwapInterval(interval: LongInt): LongInt; cdecl; external SDLLibName; procedure SDL_VideoQuit; cdecl; external SDLLibName; @@ -1011,25 +1086,19 @@ procedure SDL_WarpMouseInWindow(window: PSDL_Window; x, y: LongInt); cdecl; external SDLLibName; function SDL_SetHint(name, value: PChar): Boolean; cdecl; external SDLLibName; procedure SDL_StartTextInput; cdecl; external SDLLibName; +procedure SDL_StopTextInput; cdecl; external SDLLibName; function SDL_PeepEvents(event: PSDL_Event; numevents: LongInt; action: TSDL_eventaction; minType, maxType: LongWord): LongInt; cdecl; external SDLLibName; function SDL_AllocFormat(format: LongWord): PSDL_PixelFormat; cdecl; external SDLLibName; procedure SDL_FreeFormat(pixelformat: PSDL_PixelFormat); cdecl; external SDLLibName; -{$ELSE} -function SDL_PeepEvents(event: PSDL_Event; numevents: LongInt; action: TSDL_eventaction; mask: LongWord): LongInt; cdecl; external SDLLibName; - -function SDL_EnableUNICODE(enable: LongInt): LongInt; cdecl; external SDLLibName; -function SDL_EnableKeyRepeat(timedelay, interval: LongInt): LongInt; cdecl; external SDLLibName; -function SDL_VideoDriverName(namebuf: PChar; maxlen: LongInt): PChar; cdecl; external SDLLibName; -{$ENDIF} function SDL_GetMouseState(x, y: PLongInt): Byte; cdecl; external SDLLibName; -function SDL_GetKeyName(key: LongWord): PChar; cdecl; external SDLLibName; -function SDL_GetScancodeName(key: LongWord): PChar; cdecl; external SDLLibName; -function SDL_GetKeyFromScancode(key: LongWord): LongInt; cdecl; external SDLLibName; - +function SDL_GetKeyName(key: TSDL_Keycode): PChar; cdecl; external SDLLibName; +function SDL_GetScancodeName(key: TSDL_Scancode): PChar; cdecl; external SDLLibName; +function SDL_GetKeyFromScancode(key: TSDL_Scancode): TSDL_Keycode; cdecl; external SDLLibName; +// SDL2 functions has some additional functions (not listed here) for keycode/scancode translation procedure SDL_PumpEvents; cdecl; external SDLLibName; function SDL_PollEvent(event: PSDL_Event): LongInt; cdecl; external SDLLibName; @@ -1037,8 +1106,9 @@ procedure SDL_SetEventFilter(filter: TSDL_EventFilter); cdecl; external SDLLibName; function SDL_ShowCursor(toggle: LongInt): LongInt; cdecl; external SDLLibName; -procedure SDL_WarpMouse(x, y: Word); {$IFDEF SDL2}inline{$ELSE}cdecl; external SDLLibName{$ENDIF}; -function SDL_GetKeyState(numkeys: PLongInt): PByteArray; cdecl; external SDLLibName {$IFDEF SDL2} name 'SDL_GetKeyboardState'{$ENDIF}; +procedure SDL_WarpMouse(x, y: Word); inline; + +function SDL_GetKeyboardState(numkeys: PLongInt): PByteArray; cdecl; external SDLLibName; procedure SDL_WM_SetIcon(icon: PSDL_Surface; mask : Byte); cdecl; external SDLLibName; procedure SDL_WM_SetCaption(title: PChar; icon: PChar); cdecl; external SDLLibName; @@ -1047,14 +1117,13 @@ (* remember to mark the threaded functions as 'cdecl; export;' (or have fun debugging nil arguments) *) -function SDL_CreateThread(fn: Pointer; {$IFDEF SDL2}name: PChar;{$ENDIF} data: Pointer): PSDL_Thread; cdecl; external SDLLibName; +function SDL_CreateThread(fn: Pointer; name: PChar; data: Pointer): PSDL_Thread; cdecl; external SDLLibName; procedure SDL_WaitThread(thread: PSDL_Thread; status: PLongInt); cdecl; external SDLLibName; -procedure SDL_KillThread(thread: PSDL_Thread); cdecl; external SDLLibName; function SDL_CreateMutex: PSDL_mutex; cdecl; external SDLLibName; procedure SDL_DestroyMutex(mutex: PSDL_mutex); cdecl; external SDLLibName; -function SDL_LockMutex(mutex: PSDL_mutex): LongInt; cdecl; external SDLLibName {$IFNDEF SDL2}name 'SDL_mutexP'{$ENDIF}; -function SDL_UnlockMutex(mutex: PSDL_mutex): LongInt; cdecl; external SDLLibName {$IFNDEF SDL2}name 'SDL_mutexV'{$ENDIF}; +function SDL_LockMutex(mutex: PSDL_mutex): LongInt; cdecl; external SDLLibName; +function SDL_UnlockMutex(mutex: PSDL_mutex): LongInt; cdecl; external SDLLibName; function SDL_CreateCond: PSDL_cond; cdecl; external SDLLibName; procedure SDL_DestroyCond(cond: PSDL_cond); cdecl; external SDLLibName; @@ -1117,8 +1186,8 @@ 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}; -procedure Mix_Quit; {$IFDEF SDL_MIXER_NEWER}cdecl; external SDL_MixerLibName{$ELSE}inline{$ENDIF}; +function Mix_Init(flags: LongInt): LongInt; cdecl; external SDL_MixerLibName; +procedure Mix_Quit; cdecl; external SDL_MixerLibName; function Mix_OpenAudio(frequency: LongInt; format: Word; channels: LongInt; chunksize: LongInt): LongInt; cdecl; external SDL_MixerLibName; procedure Mix_CloseAudio; cdecl; external SDL_MixerLibName; @@ -1153,8 +1222,8 @@ procedure Mix_SetPostMix( mix_func: TPostMix; arg: Pointer); cdecl; external SDL_MixerLibName; (* SDL_image *) -function IMG_Init(flags: LongInt): LongInt; {$IFDEF SDL_IMAGE_NEWER}cdecl; external SDL_ImageLibName{$ELSE}inline{$ENDIF}; -procedure IMG_Quit; {$IFDEF SDL_IMAGE_NEWER}cdecl; external SDL_ImageLibName{$ELSE}inline{$ENDIF}; +function IMG_Init(flags: LongInt): LongInt; cdecl; external SDL_ImageLibName; +procedure IMG_Quit; cdecl; external SDL_ImageLibName; function IMG_Load(const _file: PChar): PSDL_Surface; cdecl; external SDL_ImageLibName; function IMG_Load_RW(rwop: PSDL_RWops; freesrc: LongBool): PSDL_Surface; cdecl; external SDL_ImageLibName; @@ -1176,6 +1245,12 @@ function SDLNet_AddSocket(_set: PSDLNet_SocketSet; sock: PTCPSocket): LongInt; cdecl; external SDL_NetLibName; function SDLNet_CheckSockets(_set: PSDLNet_SocketSet; timeout: LongInt): LongInt; cdecl; external SDL_NetLibName; +// SDL 2 clipboard functions +function SDL_HasClipboardText(): Boolean; cdecl; external SDLLibName; +// returns nil if memory for clipboard contents copy couldn't be allocated +function SDL_GetClipboardText(): PChar; cdecl; external SDLLibName; +// returns 0 on success or negative error number on failure +function SDL_SetClipboardText(const text: PChar): LongInt; cdecl; external SDLLibName; procedure SDLNet_Write16(value: Word; buf: Pointer); procedure SDLNet_Write32(value: LongWord; buf: Pointer); @@ -1183,7 +1258,6 @@ function SDLNet_Read32(buf: Pointer): LongWord; implementation -{$IFDEF SDL2} uses uStore; // for sdl1.2 we directly call SDL_WarpMouse() @@ -1194,40 +1268,13 @@ begin WarpMouse(x, y); end; -{$ENDIF} function SDL_MustLock(Surface: PSDL_Surface): Boolean; begin SDL_MustLock:= -{$IFDEF SDL2} ((surface^.flags and SDL_RLEACCEL) <> 0) -{$ELSE} - ( surface^.offset <> 0 ) or (( surface^.flags and (SDL_HWSURFACE or SDL_ASYNCBLIT or SDL_RLEACCEL)) <> 0) -{$ENDIF} -end; - -{$IFNDEF SDL_MIXER_NEWER} -function Mix_Init(flags: LongInt): LongInt; inline; -begin - Mix_Init:= flags; end; -procedure Mix_Quit; inline; -begin -end; -{$ENDIF} - -{$IFNDEF SDL_IMAGE_NEWER} -function IMG_Init(flags: LongInt): LongInt; inline; -begin - IMG_Init:= flags; -end; - -procedure IMG_Quit; inline; -begin -end; -{$ENDIF} - procedure SDLNet_Write16(value: Word; buf: Pointer); begin PByteArray(buf)^[1]:= value; @@ -1256,5 +1303,6 @@ (PByteArray(buf)^[0] shl 24) end; + end. diff -r fcbdee9cdd74 -r b894922d58cc hedgewars/avwrapper/CMakeLists.txt --- a/hedgewars/avwrapper/CMakeLists.txt Tue Sep 08 19:20:58 2015 +0300 +++ b/hedgewars/avwrapper/CMakeLists.txt Mon Nov 16 22:57:24 2015 +0300 @@ -1,9 +1,5 @@ #libraries have already been searched in main CMakeLists.txt -# TODO: this check is only for SDL < 2 -# fpc will take care of linking but we need to have this library installed -find_package(GLUT REQUIRED) - include_directories(${LIBAV_INCLUDE_DIR}) add_library(avwrapper avwrapper.c) diff -r fcbdee9cdd74 -r b894922d58cc hedgewars/avwrapper/avwrapper.c --- a/hedgewars/avwrapper/avwrapper.c Tue Sep 08 19:20:58 2015 +0300 +++ b/hedgewars/avwrapper/avwrapper.c Mon Nov 16 22:57:24 2015 +0300 @@ -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,11 +56,55 @@ 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 +#define av_packet_rescale_ts rescale_ts + +static void rescale_ts(AVPacket *pkt, AVRational ctb, AVRational stb) +{ + if (pkt->pts != AV_NOPTS_VALUE) + pkt->pts = av_rescale_q(pkt->pts, ctb, stb); + if (pkt->dts != AV_NOPTS_VALUE) + pkt->dts = av_rescale_q(pkt->dts, ctb, stb); + if (pkt->duration > 0) + pkt->duration = av_rescale_q(pkt->duration, ctb, stb); +} +#endif + +#ifndef AV_CODEC_CAP_DELAY +#define AV_CODEC_CAP_DELAY CODEC_CAP_DELAY +#endif +#ifndef AV_CODEC_CAP_VARIABLE_FRAME_SIZE +#define AV_CODEC_CAP_VARIABLE_FRAME_SIZE CODEC_CAP_VARIABLE_FRAME_SIZE +#endif +#ifndef AV_CODEC_FLAG_GLOBAL_HEADER +#define AV_CODEC_FLAG_GLOBAL_HEADER CODEC_FLAG_GLOBAL_HEADER +#endif +#ifndef AV_CODEC_FLAG_QSCALE +#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); @@ -105,11 +148,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"); @@ -127,30 +166,30 @@ g_pAudio->sample_rate = g_Frequency; g_pAudio->channels = g_Channels; + // set time base as invers of sample rate + g_pAudio->time_base.den = g_pAStream->time_base.den = g_Frequency; + g_pAudio->time_base.num = g_pAStream->time_base.num = 1; + // set quality 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 +197,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"); @@ -172,8 +211,10 @@ if (!g_pAStream) return 0; - AVPacket Packet = { 0 }; + AVPacket Packet; av_init_packet(&Packet); + Packet.data = NULL; + Packet.size = 0; int NumSamples = fread(g_pSamples, 2*g_Channels, g_NumSamples, g_pSoundFile); @@ -192,6 +233,8 @@ return FatalError("avcodec_encode_audio2 failed"); if (!got_packet) return 0; + + av_packet_rescale_ts(&Packet, g_pAudio->time_base, g_pAStream->time_base); #else if (NumSamples == 0) return 0; @@ -217,11 +260,7 @@ // add a video output stream 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) return FatalError("Could not allocate video stream"); @@ -238,23 +277,23 @@ of which frame timestamps are represented. for fixed-fps content, timebase should be 1/framerate and timestamp increments should be identically 1. */ - 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->time_base.den = g_pVStream->time_base.den = g_Framerate.num; + g_pVideo->time_base.num = g_pVStream->time_base.num = g_Framerate.den; + + 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,21 +327,16 @@ #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, &pDict) < 0) -#else - if (avcodec_open(g_pVideo, g_pVCodec) < 0) -#endif + if (avcodec_open2(g_pVideo, g_pVCodec, NULL) < 0) return FatalError("Could not open video codec %s", g_pVCodec->long_name); - g_pVFrame = avcodec_alloc_frame(); + g_pVFrame = av_frame_alloc(); if (!g_pVFrame) return FatalError("Could not allocate frame"); + g_pVFrame->width = g_Width; + g_pVFrame->height = g_Height; + g_pVFrame->format = AV_PIX_FMT_YUV420P; g_pVFrame->linesize[0] = g_Width; g_pVFrame->linesize[1] = g_Width/2; g_pVFrame->linesize[2] = g_Width/2; @@ -317,10 +351,10 @@ // 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; + AudioTime = (double)g_pAFrame->pts * g_pAStream->time_base.num/g_pAStream->time_base.den; ret = WriteAudioFrame(); } while (AudioTime < VideoTime && ret); @@ -337,6 +371,7 @@ Packet.size = 0; g_pVFrame->pts++; +#if LIBAVCODEC_VERSION_MAJOR < 58 if (g_pFormat->flags & AVFMT_RAWPICTURE) { /* raw video case. The API will change slightly in the near @@ -351,6 +386,7 @@ return 0; } else +#endif { #if LIBAVCODEC_VERSION_MAJOR >= 54 int got_packet; @@ -359,10 +395,7 @@ if (!got_packet) return 0; - if (Packet.pts != AV_NOPTS_VALUE) - Packet.pts = av_rescale_q(Packet.pts, g_pVideo->time_base, g_pVStream->time_base); - if (Packet.dts != AV_NOPTS_VALUE) - Packet.dts = av_rescale_q(Packet.dts, g_pVideo->time_base, g_pVStream->time_base); + av_packet_rescale_ts(&Packet, g_pVideo->time_base, g_pVStream->time_base); #else Packet.size = avcodec_encode_video(g_pVideo, g_OutBuffer, OUTBUFFER_SIZE, pFrame); if (Packet.size < 0) @@ -496,11 +529,11 @@ { int ret; // output buffered frames - if (g_pVCodec->capabilities & CODEC_CAP_DELAY) + if (g_pVCodec->capabilities & AV_CODEC_CAP_DELAY) { do ret = WriteFrame(NULL); - while (ret >= 0); + while (ret > 0); if (ret < 0) return ret; } @@ -509,7 +542,7 @@ { ret = WriteAudioFrame(); } - while(ret >= 0); + while(ret > 0); if (ret < 0) return ret; @@ -526,14 +559,14 @@ 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); } diff -r fcbdee9cdd74 -r b894922d58cc hedgewars/hwLibrary.pas diff -r fcbdee9cdd74 -r b894922d58cc hedgewars/hwengine.pas --- a/hedgewars/hwengine.pas Tue Sep 08 19:20:58 2015 +0300 +++ b/hedgewars/hwengine.pas Mon Nov 16 22:57:24 2015 +0300 @@ -25,7 +25,7 @@ unit hwengine; interface -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, uRender @@ -143,11 +143,7 @@ var event: TSDL_Event; PrevTime, CurrTime: LongWord; isTerminated: boolean; -{$IFDEF SDL2} previousGameState: TGameState; -{$ELSE} - prevFocusState: boolean; -{$ENDIF} begin isTerminated:= false; PrevTime:= SDL_GetTicks; @@ -155,15 +151,14 @@ begin SDL_PumpEvents(); - while SDL_PeepEvents(@event, 1, SDL_GETEVENT, {$IFDEF SDL2}SDL_FIRSTEVENT, SDL_LASTEVENT{$ELSE}SDL_ALLEVENTS{$ENDIF}) > 0 do + while SDL_PeepEvents(@event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT) > 0 do begin case event.type_ of -{$IFDEF SDL2} SDL_KEYDOWN: 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); + KeyPressChat(event.key.keysym); end else if GameState >= gsGame then ProcessKey(event.key); @@ -171,6 +166,20 @@ if (GameState <> gsChat) and (GameState >= gsGame) then ProcessKey(event.key); + SDL_MOUSEBUTTONDOWN: + if GameState = gsConfirm then + ParseCommand('quit', true) + else + if (GameState >= gsGame) then ProcessMouse(event.button, true); + + SDL_MOUSEBUTTONUP: + if (GameState >= gsGame) then ProcessMouse(event.button, false); + + SDL_MOUSEWHEEL: + ProcessMouseWheel(event.wheel.x, event.wheel.y); + + SDL_TEXTINPUT: uChat.TextInput(event.text); + SDL_WINDOWEVENT: if event.window.event = SDL_WINDOWEVENT_SHOWN then begin @@ -206,45 +215,6 @@ SDL_FINGERUP: onTouchUp(event.tfinger.x, event.tfinger.y, event.tfinger.fingerId); {$ENDIF} -{$ELSE} - SDL_KEYDOWN: - if GameState = gsChat then - KeyPressChat(event.key.keysym.unicode, event.key.keysym.sym, event.key.keysym.modifier) - else - if GameState >= gsGame then ProcessKey(event.key); - SDL_KEYUP: - if (GameState <> gsChat) and (GameState >= gsGame) then - ProcessKey(event.key); - - SDL_MOUSEBUTTONDOWN: - if GameState = gsConfirm then - ParseCommand('quit', true) - else - if (GameState >= gsGame) then ProcessMouse(event.button, true); - - SDL_MOUSEBUTTONUP: - if (GameState >= gsGame) then ProcessMouse(event.button, false); - - SDL_ACTIVEEVENT: - if (event.active.state and SDL_APPINPUTFOCUS) <> 0 then - begin - prevFocusState:= cHasFocus; - cHasFocus:= event.active.gain = 1; - if prevFocusState xor cHasFocus then - onFocusStateChanged() - end; - - SDL_VIDEORESIZE: - begin - // using lower values than cMinScreenWidth or cMinScreenHeight causes widget overlap and off-screen widget parts - // Change by sheepluva: - // Let's only use even numbers for custom width/height since I ran into scaling issues with odd width values. - // Maybe just fixes the symptom not the actual cause(?), I'm too tired to find out :P - cNewScreenWidth:= max(2 * (event.resize.w div 2), cMinScreenWidth); - cNewScreenHeight:= max(2 * (event.resize.h div 2), cMinScreenHeight); - cScreenResizeDelay:= RealTicks+500; - end; -{$ENDIF} SDL_JOYAXISMOTION: ControllerAxisEvent(event.jaxis.which, event.jaxis.axis, event.jaxis.value); SDL_JOYHATMOTION: @@ -340,20 +310,16 @@ AddFileLog(inttostr(i) + ': ' + ParamStr(i)); WriteToConsole('Init SDL... '); - if not cOnlyStats then SDLTry(SDL_Init(SDL_INIT_VIDEO or SDL_INIT_NOPARACHUTE) >= 0, true); + if not cOnlyStats then SDLTry(SDL_Init(SDL_INIT_VIDEO or SDL_INIT_NOPARACHUTE) >= 0, 'SDL_Init', true); WriteLnToConsole(msgOK); -{$IFDEF SDL2} - SDL_StartTextInput(); -{$ELSE} - SDL_EnableUNICODE(1); -{$ENDIF} + //SDL_StartTextInput(); SDL_ShowCursor(0); if not cOnlyStats then begin WriteToConsole('Init SDL_ttf... '); - SDLTry(TTF_Init() <> -1, true); + SDLTry(TTF_Init() <> -1, 'TTF_Init', true); WriteLnToConsole(msgOK); end; @@ -527,7 +493,11 @@ /////////////////////////////////////////////////////////////////////////////// procedure GenLandPreview; +{$IFDEF MOBILE} +var Preview: TPreview; +{$ELSE} var Preview: TPreviewAlpha; +{$ENDIF} begin initEverything(false); @@ -535,7 +505,11 @@ 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)); @@ -570,7 +544,7 @@ RunEngine:= HaltUsageError else begin - SDL_CreateThread(@EngineThread{$IFDEF SDL2}, 'engine'{$ENDIF}, nil); + SDL_CreateThread(@EngineThread, 'engine', nil); RunEngine:= 0 end end; diff -r fcbdee9cdd74 -r b894922d58cc hedgewars/options.inc --- a/hedgewars/options.inc Tue Sep 08 19:20:58 2015 +0300 +++ b/hedgewars/options.inc Mon Nov 16 22:57:24 2015 +0300 @@ -60,10 +60,6 @@ {$ENDIF} {$ENDIF} -{$IFDEF USE_TOUCH_INTERFACE} - {$DEFINE SDL2} -{$ENDIF} - {$DEFINE _S:=} {$DEFINE _P:=} diff -r fcbdee9cdd74 -r b894922d58cc hedgewars/sdlmain/CMakeLists.txt --- a/hedgewars/sdlmain/CMakeLists.txt Tue Sep 08 19:20:58 2015 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,7 +0,0 @@ -find_package(SDL REQUIRED) - -include_directories(${SDL_INCLUDE_DIR}) - -add_library (SDLmain STATIC SDLMain.m) - - diff -r fcbdee9cdd74 -r b894922d58cc hedgewars/sdlmain/SDLMain.h --- a/hedgewars/sdlmain/SDLMain.h Tue Sep 08 19:20:58 2015 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,16 +0,0 @@ -/* SDLMain.m - main entry point for our Cocoa-ized SDL app - Initial Version: Darrell Walisser - Non-NIB-Code & other changes: Max Horn - - Feel free to customize this file to suit your needs -*/ - -#ifndef _SDLMain_h_ -#define _SDLMain_h_ - -#import - -@interface SDLMain : NSObject -@end - -#endif /* _SDLMain_h_ */ diff -r fcbdee9cdd74 -r b894922d58cc hedgewars/sdlmain/SDLMain.m --- a/hedgewars/sdlmain/SDLMain.m Tue Sep 08 19:20:58 2015 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,385 +0,0 @@ -/* SDLMain.m - main entry point for our Cocoa-ized SDL app - Initial Version: Darrell Walisser - Non-NIB-Code & other changes: Max Horn - - Feel free to customize this file to suit your needs -*/ - -#include "SDL.h" -#include "SDLMain.h" -#include /* for MAXPATHLEN */ -#include - -/* For some reaon, Apple removed setAppleMenu from the headers in 10.4, - but the method still is there and works. To avoid warnings, we declare - it ourselves here. */ -@interface NSApplication(SDL_Missing_Methods) -- (void)setAppleMenu:(NSMenu *)menu; -@end - -/* Use this flag to determine whether we use SDLMain.nib or not */ -#define SDL_USE_NIB_FILE 0 - -/* Use this flag to determine whether we use CPS (docking) or not */ -#define SDL_USE_CPS 1 -#ifdef SDL_USE_CPS -/* Portions of CPS.h */ -typedef struct CPSProcessSerNum -{ - 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); - -#endif /* SDL_USE_CPS */ - -static int gArgc; -static char **gArgv; -static BOOL gFinderLaunch; -static BOOL gCalledAppMainline = FALSE; - -static NSString *getApplicationName(void) -{ - const NSDictionary *dict; - NSString *appName = 0; - - /* Determine the application name */ - dict = (const NSDictionary *)CFBundleGetInfoDictionary(CFBundleGetMainBundle()); - if (dict) - appName = [dict objectForKey: @"CFBundleName"]; - - if (![appName length]) - appName = [[NSProcessInfo processInfo] processName]; - - return appName; -} - -#if SDL_USE_NIB_FILE -/* A helper category for NSString */ -@interface NSString (ReplaceSubString) -- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString; -@end -#endif - -@interface SDLApplication : NSApplication -@end - -@implementation SDLApplication -/* Invoked from the Quit menu item */ -- (void)terminate:(id)sender -{ - /* Post a SDL_QUIT event */ - SDL_Event event; - event.type = SDL_QUIT; - SDL_PushEvent(&event); -} -@end - -/* The main class of the application, the application's delegate */ -@implementation SDLMain - -/* Set the working directory to the .app's parent directory */ -- (void) setupWorkingDirectory:(BOOL)shouldChdir -{ - if (shouldChdir) - { - char parentdir[MAXPATHLEN]; - CFURLRef url = CFBundleCopyBundleURL(CFBundleGetMainBundle()); - CFURLRef url2 = CFURLCreateCopyDeletingLastPathComponent(0, url); - if (CFURLGetFileSystemRepresentation(url2, 1, (UInt8 *)parentdir, MAXPATHLEN)) { - chdir(parentdir); /* chdir to the binary app's parent */ - } - CFRelease(url); - CFRelease(url2); - } -} - -#if SDL_USE_NIB_FILE - -/* Fix menu to contain the real app name instead of "SDL App" */ -- (void)fixMenu:(NSMenu *)aMenu withAppName:(NSString *)appName -{ - NSRange aRange; - NSEnumerator *enumerator; - NSMenuItem *menuItem; - - aRange = [[aMenu title] rangeOfString:@"SDL App"]; - if (aRange.length != 0) - [aMenu setTitle: [[aMenu title] stringByReplacingRange:aRange with:appName]]; - - enumerator = [[aMenu itemArray] objectEnumerator]; - while ((menuItem = [enumerator nextObject])) - { - aRange = [[menuItem title] rangeOfString:@"SDL App"]; - if (aRange.length != 0) - [menuItem setTitle: [[menuItem title] stringByReplacingRange:aRange with:appName]]; - if ([menuItem hasSubmenu]) - [self fixMenu:[menuItem submenu] withAppName:appName]; - } - [ aMenu sizeToFit ]; -} - -#else - -static void setApplicationMenu(void) -{ - /* warning: this code is very odd */ - NSMenu *appleMenu; - NSMenuItem *menuItem; - NSString *title; - NSString *appName; - - appName = getApplicationName(); - appleMenu = [[NSMenu alloc] initWithTitle:@""]; - - /* Add menu items */ - title = [@"About " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""]; - - [appleMenu addItem:[NSMenuItem separatorItem]]; - - title = [@"Hide " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"]; - - menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"]; - [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)]; - - [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""]; - - [appleMenu addItem:[NSMenuItem separatorItem]]; - - title = [@"Quit " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"]; - - - /* Put menu into the menubar */ - menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]; - [menuItem setSubmenu:appleMenu]; - [[NSApp mainMenu] addItem:menuItem]; - - /* Tell the application object that this is now the application menu */ - [NSApp setAppleMenu:appleMenu]; - - /* Finally give up our references to the objects */ - [appleMenu release]; - [menuItem release]; -} - -/* Create a window menu */ -static void setupWindowMenu(void) -{ - NSMenu *windowMenu; - NSMenuItem *windowMenuItem; - NSMenuItem *menuItem; - - windowMenu = [[NSMenu alloc] initWithTitle:@"Window"]; - - /* "Minimize" item */ - menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"]; - [windowMenu addItem:menuItem]; - [menuItem release]; - - /* Put menu into the menubar */ - windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""]; - [windowMenuItem setSubmenu:windowMenu]; - [[NSApp mainMenu] addItem:windowMenuItem]; - - /* Tell the application object that this is now the window menu */ - [NSApp setWindowsMenu:windowMenu]; - - /* Finally give up our references to the objects */ - [windowMenu release]; - [windowMenuItem release]; -} - -/* Replacement for NSApplicationMain */ -static void CustomApplicationMain (int argc, char **argv) -{ - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - SDLMain *sdlMain; - - /* Ensure the application object is initialised */ - [SDLApplication sharedApplication]; - -#ifdef SDL_USE_CPS - { - CPSProcessSerNum PSN; - /* Tell the dock about us */ - if (!CPSGetCurrentProcess(&PSN)) - if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103)) - if (!CPSSetFrontProcess(&PSN)) - [SDLApplication sharedApplication]; - } -#endif /* SDL_USE_CPS */ - - /* Set up the menubar */ - NSMenu *menu = [[NSMenu alloc] init]; - [NSApp setMainMenu:menu]; - setApplicationMenu(); - setupWindowMenu(); - [menu release]; - - /* Create SDLMain and make it the app delegate */ - sdlMain = [[SDLMain alloc] init]; - [NSApp setDelegate:sdlMain]; - - /* Start the main event loop */ - [NSApp run]; - - [sdlMain release]; - [pool release]; -} - -#endif - - -/* - * Catch document open requests...this lets us notice files when the app - * was launched by double-clicking a document, or when a document was - * dragged/dropped on the app's icon. You need to have a - * CFBundleDocumentsType section in your Info.plist to get this message, - * apparently. - * - * Files are added to gArgv, so to the app, they'll look like command line - * arguments. Previously, apps launched from the finder had nothing but - * an argv[0]. - * - * This message may be received multiple times to open several docs on launch. - * - * This message is ignored once the app's mainline has been called. - */ -- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename -{ - const char *temparg; - size_t arglen; - char *arg; - char **newargv; - - if (!gFinderLaunch) /* MacOS is passing command line args. */ - return FALSE; - - if (gCalledAppMainline) /* app has started, ignore this document. */ - return FALSE; - - temparg = [filename UTF8String]; - arglen = SDL_strlen(temparg) + 1; - arg = (char *) SDL_malloc(arglen); - if (arg == NULL) - return FALSE; - - newargv = (char **) realloc(gArgv, sizeof (char *) * (gArgc + 2)); - if (newargv == NULL) - { - SDL_free(arg); - return FALSE; - } - gArgv = newargv; - - SDL_strlcpy(arg, temparg, arglen); - gArgv[gArgc++] = arg; - gArgv[gArgc] = NULL; - return TRUE; -} - - -/* Called when the internal event loop has just started running */ -- (void) applicationDidFinishLaunching: (NSNotification *) note -{ - int status; - - /* Set the working directory to the .app's parent directory */ - [self setupWorkingDirectory:gFinderLaunch]; - -#if SDL_USE_NIB_FILE - /* Set the main menu to contain the real app name instead of "SDL App" */ - [self fixMenu:[NSApp mainMenu] withAppName:getApplicationName()]; -#endif - - /* Hand off to main application code */ - gCalledAppMainline = TRUE; - status = SDL_main (gArgc, gArgv); - - /* We're done, thank you for playing */ - exit(status); -} -@end - - -@implementation NSString (ReplaceSubString) - -- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString -{ - unsigned int bufferSize; - unsigned int selfLen = [self length]; - unsigned int aStringLen = [aString length]; - unichar *buffer; - NSRange localRange; - NSString *result; - - bufferSize = selfLen + aStringLen - aRange.length; - buffer = (unichar *)NSAllocateMemoryPages(bufferSize*sizeof(unichar)); - - /* Get first part into buffer */ - localRange.location = 0; - localRange.length = aRange.location; - [self getCharacters:buffer range:localRange]; - - /* Get middle part into buffer */ - localRange.location = 0; - localRange.length = aStringLen; - [aString getCharacters:(buffer+aRange.location) range:localRange]; - - /* Get last part into buffer */ - localRange.location = aRange.location + aRange.length; - localRange.length = selfLen - localRange.location; - [self getCharacters:(buffer+aRange.location+aStringLen) range:localRange]; - - /* Build output string */ - result = [NSString stringWithCharacters:buffer length:bufferSize]; - - NSDeallocateMemoryPages(buffer, bufferSize); - - return result; -} - -@end - - - -#ifdef main -# undef main -#endif - - -/* Main entry point to executable - should *not* be SDL_main! */ -int main (int argc, char **argv) -{ - /* Copy the arguments into a global variable */ - /* This is passed if we are launched by double-clicking */ - if ( argc >= 2 && strncmp (argv[1], "-psn", 4) == 0 ) { - gArgv = (char **) SDL_malloc(sizeof (char *) * 2); - gArgv[0] = argv[0]; - gArgv[1] = NULL; - gArgc = 1; - gFinderLaunch = YES; - } else { - int i; - gArgc = argc; - gArgv = (char **) SDL_malloc(sizeof (char *) * (argc+1)); - for (i = 0; i <= argc; i++) - gArgv[i] = argv[i]; - gFinderLaunch = NO; - } - -#if SDL_USE_NIB_FILE - [SDLApplication poseAsClass:[NSApplication class]]; - NSApplicationMain (argc, argv); -#else - CustomApplicationMain (argc, argv); -#endif - return 0; -} - diff -r fcbdee9cdd74 -r b894922d58cc hedgewars/uAI.pas --- a/hedgewars/uAI.pas Tue Sep 08 19:20:58 2015 +0300 +++ b/hedgewars/uAI.pas Mon Nov 16 22:57:24 2015 +0300 @@ -530,7 +530,7 @@ FillBonuses(((Me^.State and gstAttacked) <> 0) and (not isInMultiShoot)); SDL_LockMutex(ThreadLock); -ThinkThread:= SDL_CreateThread(@Think{$IFDEF SDL2}, 'think'{$ENDIF}, Me); +ThinkThread:= SDL_CreateThread(@Think, PChar('think'), Me); SDL_UnlockMutex(ThreadLock); end; diff -r fcbdee9cdd74 -r b894922d58cc hedgewars/uChat.pas --- a/hedgewars/uChat.pas Tue Sep 08 19:20:58 2015 +0300 +++ b/hedgewars/uChat.pas Mon Nov 16 22:57:24 2015 +0300 @@ -21,6 +21,7 @@ unit uChat; interface +uses SDLh; procedure initModule; procedure freeModule; @@ -28,12 +29,13 @@ procedure CleanupInput; procedure AddChatString(s: shortstring); procedure DrawChat; -procedure KeyPressChat(Key, Sym: Longword; Modifier: Word); +procedure KeyPressChat(keysym: TSDL_Keysym); procedure SendHogSpeech(s: shortstring); procedure CopyToClipboard(var newContent: shortstring); +procedure TextInput(var event: TSDL_TextInputEvent); implementation -uses SDLh, uInputHandler, uTypes, uVariables, uCommands, uUtils, uTextures, uRender, uIO, uScript, uRenderUtils; +uses uInputHandler, uTypes, uVariables, uCommands, uUtils, uTextures, uRender, uIO, uScript, uRenderUtils; const MaxStrIndex = 27; MaxInputStrLen = 200; @@ -267,8 +269,6 @@ inc(visibleCount) end; -procedure CheckPasteBuffer(); forward; - procedure UpdateInputLinePrefix(); begin if liveLua then @@ -302,7 +302,6 @@ // draw chat input line first and under all other lines if (GameState = gsChat) and (InputStr.Tex <> nil) then begin - CheckPasteBuffer(); if InputLinePrefix.Tex = nil then RenderChatLineTex(InputLinePrefix, InputLinePrefix.s); @@ -571,9 +570,8 @@ begin FreezeEnterKey; history:= 0; -{$IFNDEF SDL2} - SDL_EnableKeyRepeat(0,0); -{$ENDIF} + SDL_StopTextInput(); + //SDL_EnableKeyRepeat(0,0); GameState:= gsGame; ResetKbd; end; @@ -728,7 +726,8 @@ procedure CopyToClipboard(var newContent: shortstring); begin - SendIPC(_S'y' + copy(newContent, 1, 253) + #0); + // SDL2 clipboard + SDL_SetClipboardText(Str2PChar(newContent)); end; procedure CopySelectionToClipboard(); @@ -782,39 +781,41 @@ end; procedure PasteFromClipboard(); +var clip: PChar; begin - SendIPC(_S'Y'); -end; - -procedure CheckPasteBuffer(); -begin - if Length(ChatPasteBuffer) > 0 then + // use SDL2 clipboard functions + if SDL_HasClipboardText() then begin - InsertIntoInputStr(ChatPasteBuffer); - ChatPasteBuffer:= ''; + clip:= SDL_GetClipboardText(); + // returns NULL if not enough memory for a copy of clipboard content + if clip <> nil then + begin + InsertIntoInputStr(shortstring(clip)); + SDL_free(Pointer(clip)); + end; end; end; -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, selMode, ctrl, ctrlonly: boolean; +procedure KeyPressChat(keysym: TSDL_Keysym); +const nonStateMask = (not (KMOD_NUM or KMOD_CAPS)); +var i, index: integer; + selMode, ctrl, ctrlonly: boolean; skip: TCharSkip; + Scancode: TSDL_Scancode; + Modifier: Word; begin + Scancode:= keysym.scancode; + Modifier:= keysym.modifier; + 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: + case Scancode of + SDL_SCANCODE_BACKSPACE: begin if selectedPos < 0 then begin @@ -831,7 +832,7 @@ DeleteSelected(); UpdateCursorCoords(); end; - SDLK_DELETE: + SDL_SCANCODE_DELETE: begin if selectedPos < 0 then begin @@ -848,7 +849,7 @@ DeleteSelected(); UpdateCursorCoords(); end; - SDLK_ESCAPE: + SDL_SCANCODE_ESCAPE: begin if Length(InputStr.s) > 0 then begin @@ -857,7 +858,7 @@ end else CleanupInput end; - SDLK_RETURN, SDLK_KP_ENTER: + SDL_SCANCODE_RETURN, SDL_SCANCODE_KP_ENTER: begin if Length(InputStr.s) > 0 then begin @@ -867,10 +868,10 @@ end; CleanupInput end; - SDLK_UP, SDLK_DOWN: + SDL_SCANCODE_UP, SDL_SCANCODE_DOWN: begin - if (Sym = SDLK_UP) and (history < localLastStr) then inc(history); - if (Sym = SDLK_DOWN) and (history > 0) then dec(history); + if (Scancode = SDL_SCANCODE_UP) and (history < localLastStr) then inc(history); + if (Scancode = SDL_SCANCODE_DOWN) and (history > 0) then dec(history); index:= localLastStr - history + 1; if (index > localLastStr) then begin @@ -884,7 +885,7 @@ ResetSelection(); UpdateCursorCoords(); end; - SDLK_HOME: + SDL_SCANCODE_HOME: begin if cursorPos > 0 then begin @@ -896,7 +897,7 @@ UpdateCursorCoords(); end; - SDLK_END: + SDL_SCANCODE_END: begin i:= Length(InputStr.s); if cursorPos < i then @@ -909,7 +910,7 @@ UpdateCursorCoords(); end; - SDLK_LEFT: + SDL_SCANCODE_LEFT: begin if cursorPos > 0 then begin @@ -938,7 +939,7 @@ UpdateCursorCoords(); end; - SDLK_RIGHT: + SDL_SCANCODE_RIGHT: begin if cursorPos < Length(InputStr.s) then begin @@ -963,11 +964,12 @@ UpdateCursorCoords(); end; - SDLK_PAGEUP, SDLK_PAGEDOWN: + SDL_SCANCODE_PAGEUP, SDL_SCANCODE_PAGEDOWN: begin // ignore me!!! end; - SDLK_a: + // TODO: figure out how to determine those keys better + SDL_SCANCODE_a: begin // select all if ctrlonly then @@ -978,18 +980,14 @@ cursorPos:= Length(InputStr.s); UpdateCursorCoords(); end - else - action:= false; end; - SDLK_c: + SDL_SCANCODE_c: begin // copy if ctrlonly then CopySelectionToClipboard() - else - action:= false; end; - SDLK_v: + SDL_SCANCODE_v: begin // paste if ctrlonly then @@ -997,10 +995,8 @@ DeleteSelected(); PasteFromClipboard(); end - else - action:= false; end; - SDLK_x: + SDL_SCANCODE_x: begin // cut if ctrlonly then @@ -1008,51 +1004,32 @@ CopySelectionToClipboard(); DeleteSelected(); end - else - action:= false; end; - else - action:= false; end; - if not action and (Key <> 0) then - begin - DeleteSelected(); +end; - if (Key < $80) then - btw:= 1 - else if (Key < $800) then - btw:= 2 - else if (Key < $10000) then - btw:= 3 - else - btw:= 4; - - utf8:= ''; +procedure TextInput(var event: TSDL_TextInputEvent); +var s: shortstring; + l: byte; +begin + DeleteSelected(); - for i:= btw downto 2 do - begin - utf8:= char((Key or $80) and $BF) + utf8; - Key:= Key shr 6 - end; - - utf8:= char(Key or firstByteMark[Pred(btw)]) + utf8; - - if Length(InputStr.s) + btw > MaxInputStrLen then - exit; + l:= 0; + while event.text[l] <> #0 do + begin + s[l + 1]:= event.text[l]; + inc(l) + end; - // if speech bubble quotes are used as first input, add the closing quote and place cursor inbetween - if (Length(InputStr.s) = 0) and (Length(utf8) = 1) and (charIsForHogSpeech(utf8[1])) then - begin - InsertIntoInputStr(utf8); - InsertIntoInputStr(utf8); - cursorPos:= 1; - UpdateCursorCoords(); - end - else - InsertIntoInputStr(utf8); + if l > 0 then + begin + if byte(InputStr.s[0]) + l > 240 then exit; + s[0]:= char(l); + InsertIntoInputStr(s); end end; + procedure chChatMessage(var s: shortstring); begin AddChatString(s) @@ -1098,9 +1075,9 @@ begin s:= s; // avoid compiler hint GameState:= gsChat; -{$IFNDEF SDL2} - SDL_EnableKeyRepeat(200,45); -{$ENDIF} + SDL_StopTextInput(); + SDL_StartTextInput(); + //SDL_EnableKeyRepeat(200,45); if length(s) = 0 then SetLine(InputStr, '', true) else @@ -1140,6 +1117,7 @@ LastKeyPressTick:= 0; ResetCursor(); + SDL_StopTextInput(); end; procedure freeModule; diff -r fcbdee9cdd74 -r b894922d58cc hedgewars/uCollisions.pas --- a/hedgewars/uCollisions.pas Tue Sep 08 19:20:58 2015 +0300 +++ b/hedgewars/uCollisions.pas Mon Nov 16 22:57:24 2015 +0300 @@ -211,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; @@ -274,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; diff -r fcbdee9cdd74 -r b894922d58cc hedgewars/uDebug.pas --- a/hedgewars/uDebug.pas Tue Sep 08 19:20:58 2015 +0300 +++ b/hedgewars/uDebug.pas Mon Nov 16 22:57:24 2015 +0300 @@ -24,7 +24,7 @@ procedure OutError(Msg: shortstring; isFatalError: boolean); procedure TryDo(Assert: boolean; Msg: shortstring; isFatal: boolean); inline; -procedure SDLTry(Assert: boolean; isFatal: boolean); +procedure SDLTry(Assert: boolean; Msg: shortstring; isFatal: boolean); implementation uses SDLh, uConsole, uCommands, uConsts; @@ -42,13 +42,13 @@ OutError(Msg, isFatal) end; -procedure SDLTry(Assert: boolean; isFatal: boolean); +procedure SDLTry(Assert: boolean; Msg: shortstring; isFatal: boolean); var s: shortstring; begin if not Assert then begin s:= SDL_GetError(); - OutError(s, isFatal) + OutError(Msg + ': ' + s, isFatal) end end; diff -r fcbdee9cdd74 -r b894922d58cc hedgewars/uFLIPC.pas --- a/hedgewars/uFLIPC.pas Tue Sep 08 19:20:58 2015 +0300 +++ b/hedgewars/uFLIPC.pas Mon Nov 16 22:57:24 2015 +0300 @@ -192,14 +192,14 @@ begin callbackPointerF:= p; callbackFunctionF:= f; - callbackListenerThreadF:= SDL_CreateThread(@engineListener{$IFDEF SDL2}, 'engineListener'{$ENDIF}, nil); + callbackListenerThreadF:= SDL_CreateThread(@engineListener, 'engineListener', nil); end; procedure registerNetCallback(p: pointer; f: TIPCCallback); begin callbackPointerN:= p; callbackFunctionN:= f; - callbackListenerThreadN:= SDL_CreateThread(@netListener{$IFDEF SDL2}, 'netListener'{$ENDIF}, nil); + callbackListenerThreadN:= SDL_CreateThread(@netListener, 'netListener', nil); end; procedure initIPC; @@ -224,8 +224,8 @@ procedure freeIPC; begin - SDL_KillThread(callbackListenerThreadF); - SDL_KillThread(callbackListenerThreadN); + //FIXME SDL_KillThread(callbackListenerThreadF); + //FIXME SDL_KillThread(callbackListenerThreadN); SDL_DestroyMutex(mutFrontend); SDL_DestroyMutex(mutEngine); SDL_DestroyMutex(mutNet); diff -r fcbdee9cdd74 -r b894922d58cc hedgewars/uFLNet.pas --- a/hedgewars/uFLNet.pas Tue Sep 08 19:20:58 2015 +0300 +++ b/hedgewars/uFLNet.pas Mon Nov 16 22:57:24 2015 +0300 @@ -218,7 +218,7 @@ if SDLNet_ResolveHost(ipaddr, PChar('netserver.hedgewars.org'), 46631) = 0 then sock:= SDLNet_TCP_Open(ipaddr); - SDL_CreateThread(@netWriter{$IFDEF SDL2}, 'netWriter'{$ENDIF}, sock); + SDL_CreateThread(@netWriter, 'netWriter', sock); repeat c:= getNextChar; @@ -276,7 +276,7 @@ state.l:= 0; state.netState:= netConnecting; - netReaderThread:= SDL_CreateThread(@netReader{$IFDEF SDL2}, 'netReader'{$ENDIF}, nil); + netReaderThread:= SDL_CreateThread(@netReader, 'netReader', nil); end; procedure initModule; diff -r fcbdee9cdd74 -r b894922d58cc hedgewars/uGears.pas --- a/hedgewars/uGears.pas Tue Sep 08 19:20:58 2015 +0300 +++ b/hedgewars/uGears.pas Mon Nov 16 22:57:24 2015 +0300 @@ -320,6 +320,7 @@ Ammoz[amTardis].Probability:= 0; end; AddCaption(trmsg[sidSuddenDeath], cWhiteColor, capgrpGameState); + ScriptCall('onSuddenDeath'); playSound(sndSuddenDeath); StopMusic; if SDMusicFN <> '' then PlayMusic diff -r fcbdee9cdd74 -r b894922d58cc hedgewars/uGearsHandlersMess.pas --- a/hedgewars/uGearsHandlersMess.pas Tue Sep 08 19:20:58 2015 +0300 +++ b/hedgewars/uGearsHandlersMess.pas Mon Nov 16 22:57:24 2015 +0300 @@ -343,7 +343,7 @@ // might need some testing/adjustments - just to avoid projectiles to fly forever (accelerated by wind/skips) if (gX < min(LAND_WIDTH div -2, -2048)) or (gX > max(LAND_WIDTH * 3 div 2, 6144)) then - Gear^.State := Gear^.State or gstCollision; + Gear^.Message := Gear^.Message or gmDestroy; if Gear^.dY.isNegative then begin @@ -464,11 +464,12 @@ if Gear^.AdvBounce > 1 then dec(Gear^.AdvBounce); - if isFalling then - begin - if Gear^.State and gstNoGravity = 0 then - Gear^.dY := Gear^.dY + cGravity; - if (GameFlags and gfMoreWind) <> 0 then + if isFalling and (Gear^.State and gstNoGravity = 0) then + begin + Gear^.dY := Gear^.dY + cGravity; + if (GameFlags and gfMoreWind <> 0) and + ((xland or land) = 0) and + ((Gear^.dX.QWordValue + Gear^.dY.QWordValue) > _0_02.QWordValue) then Gear^.dX := Gear^.dX + cWindSpeed / Gear^.Density end; @@ -482,10 +483,7 @@ 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 @@ -1094,6 +1092,7 @@ 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); @@ -1959,7 +1958,7 @@ 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 + 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 @@ -2649,7 +2648,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; @@ -2675,7 +2678,7 @@ //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); @@ -2708,7 +2711,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 @@ -2718,7 +2721,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); @@ -3535,7 +3537,7 @@ begin AllInactive := false; - if (Gear^.State and gsttmpFlag) = 0 then + if (Gear^.State and gsttmpFlag = 0) and (GameFlags and gfMoreWind = 0) then Gear^.dX := Gear^.dX + cWindSpeed; oldDx := Gear^.dX; @@ -3677,7 +3679,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 @@ -5191,7 +5200,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); @@ -5247,13 +5258,12 @@ d:= 2 else d:= 3; - // always round up - if dmg mod d > 0 then - dmg:= dmg div d + 1 - else - dmg:= dmg div d; - - ApplyDamage(tmp, CurrentHedgehog, dmg, dsUnknown); + + // always rounding down + dmg:= dmg div d; + + if dmg > 0 then + ApplyDamage(tmp, CurrentHedgehog, dmg, dsUnknown); end; end; @@ -5423,7 +5433,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; @@ -5785,9 +5795,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. *) diff -r fcbdee9cdd74 -r b894922d58cc hedgewars/uGearsHandlersRope.pas --- a/hedgewars/uGearsHandlersRope.pas Tue Sep 08 19:20:58 2015 +0300 +++ b/hedgewars/uGearsHandlersRope.pas Mon Nov 16 22:57:24 2015 +0300 @@ -42,7 +42,8 @@ OutError('ERROR: doStepRopeAfterAttack called while HHGear = nil', IsNilHHFatal); DeleteGear(Gear); exit() - end; + end + else if not CurrentTeam^.ExtDriven and (FollowGear <> nil) then FollowGear := HHGear; tX:= HHGear^.X; if WorldWrap(HHGear) and (WorldEdge = weWrap) and @@ -137,7 +138,8 @@ OutError('ERROR: doStepRopeWork called while HHGear = nil', IsNilHHFatal); DeleteGear(Gear); exit() - end; + end + else if not CurrentTeam^.ExtDriven and (FollowGear <> nil) then FollowGear := HHGear; if ((HHGear^.State and gstHHDriven) = 0) or (CheckGearDrowning(HHGear)) or (Gear^.PortalCounter <> 0) then @@ -425,6 +427,7 @@ HHGear: PGear; tx, ty, tt: hwFloat; begin + Gear^.X := Gear^.X - Gear^.dX; Gear^.Y := Gear^.Y - Gear^.dY; Gear^.Elasticity := Gear^.Elasticity + _1; @@ -435,7 +438,8 @@ OutError('ERROR: doStepRopeAttach called while HHGear = nil', IsNilHHFatal); DeleteGear(Gear); exit() - end; + end + else if not CurrentTeam^.ExtDriven and (FollowGear <> nil) then FollowGear := HHGear; DeleteCI(HHGear); diff -r fcbdee9cdd74 -r b894922d58cc hedgewars/uGearsHedgehog.pas --- a/hedgewars/uGearsHedgehog.pas Tue Sep 08 19:20:58 2015 +0300 +++ b/hedgewars/uGearsHedgehog.pas Mon Nov 16 22:57:24 2015 +0300 @@ -451,7 +451,7 @@ if CurAmmoType = amAirMine then newGear^.Hedgehog:= nil; if ((CurAmmoType = amMine) or (CurAmmoType = amSMine) or (CurAmmoType = amAirMine)) and (GameFlags and gfInfAttack <> 0) then - newGear^.FlightTime:= GameTicks + 1000 + 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 @@ -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 @@ -906,6 +910,7 @@ end; Gear^.State:= Gear^.State or gstMoving; 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? diff -r fcbdee9cdd74 -r b894922d58cc hedgewars/uGearsList.pas --- a/hedgewars/uGearsList.pas Tue Sep 08 19:20:58 2015 +0300 +++ b/hedgewars/uGearsList.pas Mon Nov 16 22:57:24 2015 +0300 @@ -23,6 +23,7 @@ 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); @@ -164,11 +165,16 @@ function AddGear(X, Y: LongInt; Kind: TGearType; State: Longword; dX, dY: hwFloat; Timer: LongWord): PGear; +begin +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 -inc(GCounter); +if newUid = 0 then + inc(GCounter); AddFileLog('AddGear: #' + inttostr(GCounter) + ' (' + inttostr(x) + ',' + inttostr(y) + '), d(' + floattostr(dX) + ',' + floattostr(dY) + ') type = ' + EnumToStr(Kind)); @@ -186,7 +192,9 @@ 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; @@ -466,6 +474,8 @@ gear^.Tag:= Y end; gtAirAttack: begin + gear^.Health:= 6; + gear^.Damage:= 30; gear^.Z:= cHHZ+2; gear^.Tint:= gear^.Hedgehog^.Team^.Clan^.Color shl 8 or $FF end; diff -r fcbdee9cdd74 -r b894922d58cc hedgewars/uGearsRender.pas --- a/hedgewars/uGearsRender.pas Tue Sep 08 19:20:58 2015 +0300 +++ b/hedgewars/uGearsRender.pas Mon Nov 16 22:57:24 2015 +0300 @@ -728,7 +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(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 diff -r fcbdee9cdd74 -r b894922d58cc hedgewars/uGearsUtils.pas --- a/hedgewars/uGearsUtils.pas Tue Sep 08 19:20:58 2015 +0300 +++ b/hedgewars/uGearsUtils.pas Mon Nov 16 22:57:24 2015 +0300 @@ -829,7 +829,7 @@ 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; @@ -850,9 +850,10 @@ 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) - Gear^.Radius shl 1; while y < cWaterLine do @@ -901,9 +902,10 @@ ar2[cnt2].x:= x; ar2[cnt2].y:= y; inc(cnt2) - end - 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); diff -r fcbdee9cdd74 -r b894922d58cc hedgewars/uIO.pas --- a/hedgewars/uIO.pas Tue Sep 08 19:20:58 2015 +0300 +++ b/hedgewars/uIO.pas Mon Nov 16 22:57:24 2015 +0300 @@ -143,7 +143,6 @@ ParseChatCommand('chatmsg ' + #4, s, 2) else isProcessed:= false; - 'Y': ChatPasteBuffer:= copy(s, 2, Length(s) - 1); else isProcessed:= false; end; diff -r fcbdee9cdd74 -r b894922d58cc hedgewars/uInputHandler.pas --- a/hedgewars/uInputHandler.pas Tue Sep 08 19:20:58 2015 +0300 +++ b/hedgewars/uInputHandler.pas Mon Nov 16 22:57:24 2015 +0300 @@ -30,6 +30,7 @@ //procedure MaskModifier(var code: LongInt; modifier: LongWord); procedure MaskModifier(Modifier: shortstring; var code: LongInt); procedure ProcessMouse(event: TSDL_MouseButtonEvent; ButtonDown: boolean); +procedure ProcessMouseWheel(x, y: LongInt); procedure ProcessKey(event: TSDL_KeyboardEvent); inline; procedure ProcessKey(code: LongInt; KeyDown: boolean); @@ -82,8 +83,8 @@ var code: LongInt; begin name:= LowerCase(name); - code:= cKeyMaxIndex; - while (code > 0) and (KeyNames[code] <> name) do dec(code); + code:= 0; + while (code <= cKeyMaxIndex) and (KeyNames[code] <> name) do inc(code); MaskModifier(Modifier, code); KeyNameToCode:= code; @@ -168,7 +169,13 @@ if CurrentBinds[code][0] <> #0 then begin - if (code > 3) and KeyDown and (not ((CurrentBinds[code] = 'put')) or (CurrentBinds[code] = 'ammomenu') or (CurrentBinds[code] = '+cur_u') or (CurrentBinds[code] = '+cur_d') or (CurrentBinds[code] = '+cur_l') or (CurrentBinds[code] = '+cur_r')) and (CurrentTeam <> nil) and (not CurrentTeam^.ExtDriven) then bShowAmmoMenu:= false; + if (code < cKeyMaxIndex - 2) // means not mouse buttons + and KeyDown + and (not ((CurrentBinds[code] = 'put')) or (CurrentBinds[code] = 'ammomenu') or (CurrentBinds[code] = '+cur_u') or (CurrentBinds[code] = '+cur_d') or (CurrentBinds[code] = '+cur_l') or (CurrentBinds[code] = '+cur_r')) + and (CurrentTeam <> nil) + and (not CurrentTeam^.ExtDriven) + then bShowAmmoMenu:= false; + if KeyDown then begin Trusted:= Trusted and (not isPaused); //releasing keys during pause should be allowed on the other hand @@ -203,25 +210,36 @@ procedure ProcessKey(event: TSDL_KeyboardEvent); inline; var code: LongInt; begin - code:= event.keysym.sym; - //MaskModifier(code, event.keysym.modifier); + // TODO + code:= LongInt(event.keysym.scancode); + //writelntoconsole('[KEY] '+inttostr(code)+ ' -> ''' +KeyNames[code] + ''', type = '+inttostr(event.type_)); ProcessKey(code, event.type_ = SDL_KEYDOWN); end; procedure ProcessMouse(event: TSDL_MouseButtonEvent; ButtonDown: boolean); begin -case event.button of - SDL_BUTTON_LEFT: - ProcessKey(KeyNameToCode('mousel'), ButtonDown); - SDL_BUTTON_MIDDLE: - ProcessKey(KeyNameToCode('mousem'), ButtonDown); - SDL_BUTTON_RIGHT: - ProcessKey(KeyNameToCode('mouser'), ButtonDown); - SDL_BUTTON_WHEELDOWN: - ProcessKey(KeyNameToCode('wheeldown'), ButtonDown); - SDL_BUTTON_WHEELUP: - ProcessKey(KeyNameToCode('wheelup'), ButtonDown); - end; + //writelntoconsole('[MOUSE] '+inttostr(event.button)); + case event.button of + SDL_BUTTON_LEFT: + ProcessKey(KeyNameToCode('mousel'), ButtonDown); + SDL_BUTTON_MIDDLE: + ProcessKey(KeyNameToCode('mousem'), ButtonDown); + SDL_BUTTON_RIGHT: + ProcessKey(KeyNameToCode('mouser'), ButtonDown); + SDL_BUTTON_WHEELDOWN: + ProcessKey(KeyNameToCode('wheeldown'), ButtonDown); + SDL_BUTTON_WHEELUP: + ProcessKey(KeyNameToCode('wheelup'), ButtonDown); + end; +end; + +procedure ProcessMouseWheel(x, y: LongInt); +begin + //writelntoconsole('[MOUSEWHEEL] '+inttostr(x)+', '+inttostr(y)); + if y > 0 then + ProcessKey(KeyNameToCode('wheelup'), true) + else if y < 0 then + ProcessKey(KeyNameToCode('wheeldown'), true); end; procedure ResetKbd; @@ -232,125 +250,131 @@ ProcessKey(t, False); end; + +procedure InitDefaultBinds; +var i: Longword; +begin + DefaultBinds[KeyNameToCode('escape')]:= 'quit'; + DefaultBinds[KeyNameToCode(_S'`')]:= 'history'; + DefaultBinds[KeyNameToCode('delete')]:= 'rotmask'; + + //numpad + //DefaultBinds[265]:= '+volup'; + //DefaultBinds[256]:= '+voldown'; + + DefaultBinds[KeyNameToCode(_S'0')]:= '+volup'; + DefaultBinds[KeyNameToCode(_S'9')]:= '+voldown'; + DefaultBinds[KeyNameToCode(_S'8')]:= 'mute'; + DefaultBinds[KeyNameToCode(_S'c')]:= 'capture'; + DefaultBinds[KeyNameToCode(_S'r')]:= 'record'; + DefaultBinds[KeyNameToCode(_S'h')]:= 'findhh'; + DefaultBinds[KeyNameToCode(_S'p')]:= 'pause'; + DefaultBinds[KeyNameToCode(_S's')]:= '+speedup'; + DefaultBinds[KeyNameToCode(_S't')]:= 'chat'; + DefaultBinds[KeyNameToCode(_S'y')]:= 'confirm'; + + DefaultBinds[KeyNameToCode('mousem')]:= 'zoomreset'; + DefaultBinds[KeyNameToCode('wheelup')]:= 'zoomin'; + DefaultBinds[KeyNameToCode('wheeldown')]:= 'zoomout'; + + DefaultBinds[KeyNameToCode('f12')]:= 'fullscr'; + + + DefaultBinds[KeyNameToCode('mousel')]:= '/put'; + DefaultBinds[KeyNameToCode('mouser')]:= 'ammomenu'; + DefaultBinds[KeyNameToCode('backspace')]:= 'hjump'; + DefaultBinds[KeyNameToCode('tab')]:= 'switch'; + DefaultBinds[KeyNameToCode('return')]:= 'ljump'; + DefaultBinds[KeyNameToCode('space')]:= '+attack'; + DefaultBinds[KeyNameToCode('up')]:= '+up'; + DefaultBinds[KeyNameToCode('down')]:= '+down'; + DefaultBinds[KeyNameToCode('left')]:= '+left'; + DefaultBinds[KeyNameToCode('right')]:= '+right'; + DefaultBinds[KeyNameToCode('left_shift')]:= '+precise'; + + + DefaultBinds[KeyNameToCode('j0a0u')]:= '+left'; + DefaultBinds[KeyNameToCode('j0a0d')]:= '+right'; + DefaultBinds[KeyNameToCode('j0a1u')]:= '+up'; + DefaultBinds[KeyNameToCode('j0a1d')]:= '+down'; + for i:= 1 to 10 do DefaultBinds[KeyNameToCode('f'+IntToStr(i))]:= 'slot '+IntToStr(i); + for i:= 1 to 5 do DefaultBinds[KeyNameToCode(IntToStr(i))]:= 'timer '+IntToStr(i); + + loadBinds('dbind', cPathz[ptData] + '/settings.ini'); +end; + + procedure InitKbdKeyTable; var i, j, k, t: LongInt; s: string[15]; begin -//TODO in sdl13 this overrides some values (A and B) change indices to some other values at the back perhaps? -KeyNames[1]:= 'mousel'; -KeyNames[2]:= 'mousem'; -KeyNames[3]:= 'mouser'; -KeyNames[4]:= 'wheelup'; -KeyNames[5]:= 'wheeldown'; + KeyNames[cKeyMaxIndex ]:= 'mousel'; + KeyNames[cKeyMaxIndex - 1]:= 'mousem'; + KeyNames[cKeyMaxIndex - 2]:= 'mouser'; + KeyNames[cKeyMaxIndex - 3]:= 'wheelup'; + KeyNames[cKeyMaxIndex - 4]:= 'wheeldown'; -for i:= 6 to cKeyMaxIndex do - begin - s:= shortstring(sdl_getkeyname(i)); - //WriteLnToConsole('uInputHandler - ' + IntToStr(i) + ': ' + s + ' ' + IntToStr(cKeyMaxIndex)); - if s = 'unknown key' then KeyNames[i]:= '' - else + for i:= 0 to cKeyMaxIndex - 5 do begin + s:= shortstring(SDL_GetScancodeName(TSDL_Scancode(i))); + for t:= 1 to Length(s) do if s[t] = ' ' then s[t]:= '_'; KeyNames[i]:= LowerCase(s) end; - end; -// get the size of keyboard array -SDL_GetKeyState(@k); + // get the size of keyboard array + SDL_GetKeyboardState(@k); -// Controller(s) -for j:= 0 to Pred(ControllerNumControllers) do - begin - for i:= 0 to Pred(ControllerNumAxes[j]) do + // Controller(s) + for j:= 0 to Pred(ControllerNumControllers) do begin - keynames[k + 0]:= 'j' + IntToStr(j) + 'a' + IntToStr(i) + 'u'; - keynames[k + 1]:= 'j' + IntToStr(j) + 'a' + IntToStr(i) + 'd'; - inc(k, 2); - end; - for i:= 0 to Pred(ControllerNumHats[j]) do - begin - keynames[k + 0]:= 'j' + IntToStr(j) + 'h' + IntToStr(i) + 'u'; - keynames[k + 1]:= 'j' + IntToStr(j) + 'h' + IntToStr(i) + 'r'; - keynames[k + 2]:= 'j' + IntToStr(j) + 'h' + IntToStr(i) + 'd'; - keynames[k + 3]:= 'j' + IntToStr(j) + 'h' + IntToStr(i) + 'l'; - inc(k, 4); - end; - for i:= 0 to Pred(ControllerNumButtons[j]) do - begin - keynames[k]:= 'j' + IntToStr(j) + 'b' + IntToStr(i); - inc(k, 1); + for i:= 0 to Pred(ControllerNumAxes[j]) do + begin + KeyNames[k + 0]:= 'j' + IntToStr(j) + 'a' + IntToStr(i) + 'u'; + KeyNames[k + 1]:= 'j' + IntToStr(j) + 'a' + IntToStr(i) + 'd'; + inc(k, 2); + end; + for i:= 0 to Pred(ControllerNumHats[j]) do + begin + KeyNames[k + 0]:= 'j' + IntToStr(j) + 'h' + IntToStr(i) + 'u'; + KeyNames[k + 1]:= 'j' + IntToStr(j) + 'h' + IntToStr(i) + 'r'; + KeyNames[k + 2]:= 'j' + IntToStr(j) + 'h' + IntToStr(i) + 'd'; + KeyNames[k + 3]:= 'j' + IntToStr(j) + 'h' + IntToStr(i) + 'l'; + inc(k, 4); + end; + for i:= 0 to Pred(ControllerNumButtons[j]) do + begin + KeyNames[k]:= 'j' + IntToStr(j) + 'b' + IntToStr(i); + inc(k, 1); + end; end; - end; -DefaultBinds[KeyNameToCode('escape')]:= 'quit'; -DefaultBinds[KeyNameToCode(_S'`')]:= 'history'; -DefaultBinds[KeyNameToCode('delete')]:= 'rotmask'; - -//numpad -//DefaultBinds[265]:= '+volup'; -//DefaultBinds[256]:= '+voldown'; - -DefaultBinds[KeyNameToCode(_S'0')]:= '+volup'; -DefaultBinds[KeyNameToCode(_S'9')]:= '+voldown'; -DefaultBinds[KeyNameToCode(_S'8')]:= 'mute'; -DefaultBinds[KeyNameToCode(_S'c')]:= 'capture'; -DefaultBinds[KeyNameToCode(_S'r')]:= 'record'; -DefaultBinds[KeyNameToCode(_S'h')]:= 'findhh'; -DefaultBinds[KeyNameToCode(_S'p')]:= 'pause'; -DefaultBinds[KeyNameToCode(_S's')]:= '+speedup'; -DefaultBinds[KeyNameToCode(_S't')]:= 'chat'; -DefaultBinds[KeyNameToCode(_S'y')]:= 'confirm'; - -DefaultBinds[KeyNameToCode('mousem')]:= 'zoomreset'; -DefaultBinds[KeyNameToCode('wheelup')]:= 'zoomin'; -DefaultBinds[KeyNameToCode('wheeldown')]:= 'zoomout'; - -DefaultBinds[KeyNameToCode('f12')]:= 'fullscr'; + InitDefaultBinds +end; -DefaultBinds[KeyNameToCode('mousel')]:= '/put'; -DefaultBinds[KeyNameToCode('mouser')]:= 'ammomenu'; -DefaultBinds[KeyNameToCode('backspace')]:= 'hjump'; -DefaultBinds[KeyNameToCode('tab')]:= 'switch'; -DefaultBinds[KeyNameToCode('return')]:= 'ljump'; -DefaultBinds[KeyNameToCode('space')]:= '+attack'; -DefaultBinds[KeyNameToCode('up')]:= '+up'; -DefaultBinds[KeyNameToCode('down')]:= '+down'; -DefaultBinds[KeyNameToCode('left')]:= '+left'; -DefaultBinds[KeyNameToCode('right')]:= '+right'; -DefaultBinds[KeyNameToCode('left_shift')]:= '+precise'; - -DefaultBinds[KeyNameToCode('j0a0u')]:= '+left'; -DefaultBinds[KeyNameToCode('j0a0d')]:= '+right'; -DefaultBinds[KeyNameToCode('j0a1u')]:= '+up'; -DefaultBinds[KeyNameToCode('j0a1d')]:= '+down'; -for i:= 1 to 10 do DefaultBinds[KeyNameToCode('f'+IntToStr(i))]:= 'slot '+char(i+48); -for i:= 1 to 5 do DefaultBinds[KeyNameToCode(IntToStr(i))]:= 'timer '+IntToStr(i); - -loadBinds('dbind', cPathz[ptConfig] + '/settings.ini'); -end; - +{$IFNDEF MOBILE} procedure SetBinds(var binds: TBinds); -{$IFNDEF MOBILE} var t: LongInt; -{$ENDIF} begin -{$IFDEF MOBILE} - binds:= binds; // avoid hint - CurrentBinds:= DefaultBinds; -{$ELSE} for t:= 0 to cKbdMaxIndex do if (CurrentBinds[t] <> binds[t]) and tkbd[t] then ProcessKey(t, False); CurrentBinds:= binds; +end; +{$ELSE} +procedure SetBinds(var binds: TBinds); +begin + binds:= binds; // avoid hint + CurrentBinds:= DefaultBinds; +end; {$ENDIF} -end; procedure SetDefaultBinds; begin @@ -438,7 +462,7 @@ var k: LongInt; begin - SDL_GetKeyState(@k); + SDL_GetKeyboardState(@k); k:= k + joy * (ControllerNumAxes[joy]*2 + ControllerNumHats[joy]*4 + ControllerNumButtons[joy]*2); ProcessKey(k + axis*2, value > 20000); ProcessKey(k + (axis*2)+1, value < -20000); @@ -448,7 +472,7 @@ var k: LongInt; begin - SDL_GetKeyState(@k); + SDL_GetKeyboardState(@k); k:= k + joy * (ControllerNumAxes[joy]*2 + ControllerNumHats[joy]*4 + ControllerNumButtons[joy]*2); ProcessKey(k + ControllerNumAxes[joy]*2 + hat*4 + 0, (value and SDL_HAT_UP) <> 0); ProcessKey(k + ControllerNumAxes[joy]*2 + hat*4 + 1, (value and SDL_HAT_RIGHT)<> 0); @@ -460,7 +484,7 @@ var k: LongInt; begin - SDL_GetKeyState(@k); + SDL_GetKeyboardState(@k); k:= k + joy * (ControllerNumAxes[joy]*2 + ControllerNumHats[joy]*4 + ControllerNumButtons[joy]*2); ProcessKey(k + ControllerNumAxes[joy]*2 + ControllerNumHats[joy]*4 + button, pressed); end; diff -r fcbdee9cdd74 -r b894922d58cc hedgewars/uLand.pas --- a/hedgewars/uLand.pas Tue Sep 08 19:20:58 2015 +0300 +++ b/hedgewars/uLand.pas Mon Nov 16 22:57:24 2015 +0300 @@ -263,7 +263,7 @@ TryDo(Surface <> nil, 'Assert (LandSurface <> nil) failed', true); if SDL_MustLock(Surface) then - SDLTry(SDL_LockSurface(Surface) >= 0, true); + SDLTry(SDL_LockSurface(Surface) >= 0, 'SDL_LockSurface', true); p:= Surface^.pixels; for y:= 0 to LAND_HEIGHT - 1 do @@ -451,7 +451,7 @@ cpX:= (LAND_WIDTH - tmpsurf^.w) div 2; cpY:= LAND_HEIGHT - tmpsurf^.h; if SDL_MustLock(tmpsurf) then - SDLTry(SDL_LockSurface(tmpsurf) >= 0, true); + SDLTry(SDL_LockSurface(tmpsurf) >= 0, 'SDL_LockSurface', true); p:= tmpsurf^.pixels; for y:= 0 to Pred(tmpsurf^.h) do diff -r fcbdee9cdd74 -r b894922d58cc hedgewars/uLandGenTemplateBased.pas --- a/hedgewars/uLandGenTemplateBased.pas Tue Sep 08 19:20:58 2015 +0300 +++ b/hedgewars/uLandGenTemplateBased.pas Mon Nov 16 22:57:24 2015 +0300 @@ -9,7 +9,7 @@ var minDistance, dabDiv: LongInt; // different details size implementation -uses uVariables, uConsts, uFloat, uLandUtils, uRandom, SDLh, math; +uses uVariables, uTypes, uConsts, uFloat, uLandUtils, uRandom, SDLh, math; procedure SetPoints(var Template: TEdgeTemplate; var pa: TPixAr; fps: PPointArray); @@ -327,6 +327,9 @@ DivideEdges(Template.FillPointsCount, pa) until i = pa.Count; +{$IFDEF IPHONEOS} + if GameType <> gmtLandPreview then +{$ENDIF} // make it smooth BezierizeEdge(pa, _0_2); end; diff -r fcbdee9cdd74 -r b894922d58cc hedgewars/uLandGraphics.pas --- a/hedgewars/uLandGraphics.pas Tue Sep 08 19:20:58 2015 +0300 +++ b/hedgewars/uLandGraphics.pas Mon Nov 16 22:57:24 2015 +0300 @@ -716,7 +716,7 @@ col:= Frame div numFramesFirstCol; if SDL_MustLock(Image) then - SDLTry(SDL_LockSurface(Image) >= 0, true); + SDLTry(SDL_LockSurface(Image) >= 0, 'TryPlaceOnLand', true); bpp:= Image^.format^.BytesPerPixel; TryDo(bpp = 4, 'It should be 32 bpp sprite', true); @@ -835,7 +835,7 @@ col:= Frame div numFramesFirstCol; if SDL_MustLock(Image) then - SDLTry(SDL_LockSurface(Image) >= 0, true); + SDLTry(SDL_LockSurface(Image) >= 0, 'EraseLand', true); bpp:= Image^.format^.BytesPerPixel; TryDo(bpp = 4, 'It should be 32 bpp sprite', true); @@ -918,7 +918,7 @@ col:= Frame div numFramesFirstCol; if SDL_MustLock(Image) then - SDLTry(SDL_LockSurface(Image) >= 0, true); + SDLTry(SDL_LockSurface(Image) >= 0, 'SDL_LockSurface', true); bpp:= Image^.format^.BytesPerPixel; TryDo(bpp = 4, 'It should be 32 bpp sprite', true); @@ -930,7 +930,7 @@ TryDo(finalSurface <> nil, 'GetPlaceCollisionTex: fail to create surface', true); if SDL_MustLock(finalSurface) then - SDLTry(SDL_LockSurface(finalSurface) >= 0, true); + SDLTry(SDL_LockSurface(finalSurface) >= 0, 'GetPlaceCollisionTex', true); p:= PLongWordArray(@(PLongWordArray(Image^.pixels)^[ (Image^.pitch div 4) * row * h + col * w ])); pt:= PLongWordArray(finalSurface^.pixels); diff -r fcbdee9cdd74 -r b894922d58cc hedgewars/uLandObjects.pas --- a/hedgewars/uLandObjects.pas Tue Sep 08 19:20:58 2015 +0300 +++ b/hedgewars/uLandObjects.pas Mon Nov 16 22:57:24 2015 +0300 @@ -109,7 +109,7 @@ WriteToConsole('Generating collision info... '); if SDL_MustLock(Image) then - SDLTry(SDL_LockSurface(Image) >= 0, true); + SDLTry(SDL_LockSurface(Image) >= 0, 'SDL_LockSurface', true); bpp:= Image^.format^.BytesPerPixel; TryDo(bpp = 4, 'Land object should be 32bit', true); @@ -160,7 +160,7 @@ WriteToConsole('Generating collision info... '); if SDL_MustLock(Image) then - SDLTry(SDL_LockSurface(Image) >= 0, true); + SDLTry(SDL_LockSurface(Image) >= 0, 'SDL_LockSurface', true); bpp:= Image^.format^.BytesPerPixel; TryDo(bpp = 4, 'Land object should be 32bit', true); @@ -208,8 +208,8 @@ procedure InitRects; begin -RectCount:= 0; -New(Rects) + RectCount:= 0; + New(Rects) end; procedure FreeRects; @@ -365,7 +365,7 @@ CheckCanPlace:= bRes; end; -function TryPut(var Obj: TThemeObject): boolean; overload; +function TryPut(var Obj: TThemeObject): boolean; const MaxPointsIndex = 2047; var x, y: Longword; ar: array[0..MaxPointsIndex] of TPoint; @@ -386,12 +386,12 @@ begin ar[cnt].x:= x; ar[cnt].y:= y; - inc(cnt); - if cnt > MaxPointsIndex then // buffer is full, do not check the rest land + if cnt >= MaxPointsIndex then // buffer is full, do not check the rest land begin y:= LAND_HEIGHT; x:= LAND_WIDTH; end + else inc(cnt); end; inc(y, 3); until y >= LAND_HEIGHT - Height; @@ -412,7 +412,7 @@ TryPut:= bRes; end; -function TryPut(var Obj: TSprayObject; Surface: PSDL_Surface): boolean; overload; +function TryPut2(var Obj: TSprayObject; Surface: PSDL_Surface): boolean; const MaxPointsIndex = 8095; var x, y: Longword; ar: array[0..MaxPointsIndex] of TPoint; @@ -420,7 +420,7 @@ r: TSDL_Rect; bRes: boolean; begin -TryPut:= false; +TryPut2:= false; cnt:= 0; with Obj do begin @@ -439,18 +439,19 @@ begin ar[cnt].x:= x; ar[cnt].y:= y; - inc(cnt); - if cnt > MaxPointsIndex then // buffer is full, do not check the rest land + if cnt >= MaxPointsIndex then // buffer is full, do not check the rest land begin - y:= 5000; - x:= 5000; + y:= $FF000000; + x:= $FF000000; end + else inc(cnt); end; inc(y, 12); until y >= LAND_HEIGHT - Height - 8; inc(x, getrandom(12) + 12) until x >= LAND_WIDTH - Width; bRes:= cnt <> 0; +AddFileLog('CHECKPOINT 004'); if bRes then begin i:= getrandom(cnt); @@ -464,7 +465,7 @@ end else Maxcnt:= 0 end; -TryPut:= bRes; +TryPut2:= bRes; end; @@ -845,13 +846,13 @@ exit; WriteLnToConsole('Adding theme objects...'); - for i:=0 to ThemeObjects.Count do + for i:=0 to Pred(ThemeObjects.Count) do ThemeObjects.objs[i].Maxcnt := max(1, (ThemeObjects.objs[i].Maxcnt * MaxHedgehogs) div 18); // Maxcnt is proportional to map size, but allow objects to span even if we're on a tiny map repeat t := getrandom(ThemeObjects.Count); b := false; - for i:=0 to ThemeObjects.Count do + for i:= 0 to Pred(ThemeObjects.Count) do begin ii := (i+t) mod ThemeObjects.Count; @@ -869,18 +870,18 @@ exit; WriteLnToConsole('Adding spray objects...'); - for i:=0 to SprayObjects.Count do + for i:= 0 to Pred(SprayObjects.Count) do SprayObjects.objs[i].Maxcnt := max(1, (SprayObjects.objs[i].Maxcnt * MaxHedgehogs) div 18); // Maxcnt is proportional to map size, but allow objects to span even if we're on a tiny map repeat t := getrandom(SprayObjects.Count); b := false; - for i:=0 to SprayObjects.Count do + for i:= 0 to Pred(SprayObjects.Count) do begin ii := (i+t) mod SprayObjects.Count; if SprayObjects.objs[ii].Maxcnt <> 0 then - b := b or TryPut(SprayObjects.objs[ii], Surface) + b := b or TryPut2(SprayObjects.objs[ii], Surface) end; until not b; end; @@ -915,7 +916,6 @@ procedure AddOnLandObjects(Surface: PSDL_Surface); begin InitRects; -//AddSprayObjects(Surface, SprayObjects, 12); AddSprayObjects(Surface, SprayObjects); FreeRects end; diff -r fcbdee9cdd74 -r b894922d58cc hedgewars/uLandTexture.pas diff -r fcbdee9cdd74 -r b894922d58cc hedgewars/uLocale.pas --- a/hedgewars/uLocale.pas Tue Sep 08 19:20:58 2015 +0300 +++ b/hedgewars/uLocale.pas Mon Nov 16 22:57:24 2015 +0300 @@ -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 @@ -133,9 +133,20 @@ end; {$IFDEF HWLIBRARY} -procedure LoadLocaleWrapper(str: pchar); cdecl; export; +procedure LoadLocaleWrapper(path: pchar; filename: pchar); cdecl; export; begin - LoadLocale(Strpas(str)); +// FIXME +{ PathPrefix := Strpas(path); + + uUtils.initModule(false); + uVariables.initModule; + uPhysFSLayer.initModule; +} + LoadLocale(Strpas(filename)); +{ + uPhysFSLayer.freeModule; + uVariables.freeModule; + uUtils.freeModule;} end; {$ENDIF} diff -r fcbdee9cdd74 -r b894922d58cc hedgewars/uMatrix.pas diff -r fcbdee9cdd74 -r b894922d58cc hedgewars/uMisc.pas --- a/hedgewars/uMisc.pas Tue Sep 08 19:20:58 2015 +0300 +++ b/hedgewars/uMisc.pas Mon Nov 16 22:57:24 2015 +0300 @@ -30,11 +30,7 @@ function doSurfaceConversion(tmpsurf: PSDL_Surface): PSDL_Surface; function MakeScreenshot(filename: shortstring; k: LongInt; dump: LongWord): boolean; function GetTeamStatString(p: PTeam): shortstring; -{$IFDEF SDL2} function SDL_RectMake(x, y, width, height: LongInt): TSDL_Rect; inline; -{$ELSE} -function SDL_RectMake(x, y: SmallInt; width, height: Word): TSDL_Rect; inline; -{$ENDIF} implementation uses SysUtils, uVariables, uUtils @@ -304,7 +300,7 @@ image^.size:= size; image^.buffer:= p; -SDL_CreateThread(@SaveScreenshot{$IFDEF SDL2}, 'snapshot'{$ENDIF}, image); +SDL_CreateThread(@SaveScreenshot, PChar('snapshot'), image); MakeScreenshot:= true; // possibly it is not true but we will not wait for thread to terminate end; @@ -322,11 +318,7 @@ end; end; -{$IFDEF SDL2} function SDL_RectMake(x, y, width, height: LongInt): TSDL_Rect; inline; -{$ELSE} -function SDL_RectMake(x, y: SmallInt; width, height: Word): TSDL_Rect; inline; -{$ENDIF} begin SDL_RectMake.x:= x; SDL_RectMake.y:= y; @@ -341,32 +333,15 @@ GetTeamStatString:= s; end; -{$IFDEF SDL2} -// FIXME - pretty sure this is not handling endianness correctly like the SDL1 is +procedure initModule; const SDL_PIXELFORMAT_ABGR8888 = (1 shl 28) or (6 shl 24) or (7 shl 20) or (6 shl 16) or (32 shl 8) or 4; -{$ELSE} -const format: TSDL_PixelFormat = ( - palette: nil; BitsPerPixel: 32; BytesPerPixel: 4; - Rloss: 0; Gloss: 0; Bloss: 0; Aloss: 0; - Rshift: RShift; Gshift: GShift; Bshift: BShift; Ashift: AShift; - RMask: RMask; GMask: GMask; BMask: BMask; AMask: AMask; - colorkey: 0; alpha: 255); -{$ENDIF} - -procedure initModule; begin -{$IFDEF SDL2} conversionFormat:= SDL_AllocFormat(SDL_PIXELFORMAT_ABGR8888); -{$ELSE} - conversionFormat:= @format; -{$ENDIF} end; procedure freeModule; begin -{$IFDEF SDL2} SDL_FreeFormat(conversionFormat); -{$ENDIF} end; end. diff -r fcbdee9cdd74 -r b894922d58cc hedgewars/uPhysFSLayer.pas --- a/hedgewars/uPhysFSLayer.pas Tue Sep 08 19:20:58 2015 +0300 +++ b/hedgewars/uPhysFSLayer.pas Mon Nov 16 22:57:24 2015 +0300 @@ -171,7 +171,9 @@ procedure initModule(localPrefix, userPrefix: PChar); var i: LongInt; cPhysfsId: shortstring; +{$IFNDEF MOBILE} fp: PChar; +{$ENDIF} begin //TODO: http://icculus.org/pipermail/physfs/2011-August/001006.html cPhysfsId:= GetCurrentDir() + {$IFDEF DARWIN}{$IFNDEF IPHONEOS}'/Hedgewars.app/Contents/MacOS/' + {$ENDIF}{$ENDIF} ' hedgewars'; @@ -179,6 +181,7 @@ i:= PHYSFS_init(Str2PChar(cPhysfsId)); //AddFileLog('[PhysFS] init: ' + inttostr(i)); +{$IFNDEF MOBILE} // mount system fonts paths first for i:= low(cFontsPaths) to high(cFontsPaths) do begin @@ -186,6 +189,7 @@ if fp <> nil then pfsMount(ansistring(fp), PChar('/Fonts')); end; +{$ENDIF} pfsMountAtRoot(localPrefix); pfsMountAtRoot(userPrefix + ansistring('/Data')); diff -r fcbdee9cdd74 -r b894922d58cc hedgewars/uRender.pas --- a/hedgewars/uRender.pas Tue Sep 08 19:20:58 2015 +0300 +++ b/hedgewars/uRender.pas Mon Nov 16 22:57:24 2015 +0300 @@ -358,25 +358,29 @@ {$ENDIF} function glLoadExtension(extension : shortstring) : boolean; +var logmsg: shortstring; begin -//TODO: pas2c does not handle {$IF (GLunit = gles11) OR DEFINED(PAS2C)} -{$IFNDEF PAS2C} -{$IF GLunit = gles11} - // FreePascal doesnt come with OpenGL ES 1.1 Extension headers extension:= extension; // avoid hint glLoadExtension:= false; - AddFileLog('OpenGL - "' + extension + '" skipped') -{$ELSE} + 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 - AddFileLog('OpenGL - "' + extension + '" loaded') + logmsg:= 'OpenGL - "' + extension + '" loaded' else - AddFileLog('OpenGL - "' + extension + '" failed to load'); -{$ENDIF} + logmsg:= 'OpenGL - "' + extension + '" failed to load'; -{$ELSE} // pas2c part - glLoadExtension:= false; +{$ENDIF} {$ENDIF} +{$ENDIF} + AddFileLog(logmsg); end; {$IFDEF USE_S3D_RENDERING OR USE_VIDEO_RECORDING} @@ -427,17 +431,6 @@ tmpint: LongInt; tmpn: LongInt; begin -{$IFDEF MOBILE} - // 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); - //SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); - if SDLGLcontext = nil then - SDLGLcontext:= SDL_GL_CreateContext(SDLwindow); - SDLTry(SDLGLcontext <> nil, true); - SDL_GL_SetSwapInterval(1); -{$ENDIF} - // suppress hint/warning AuxBufNum:= AuxBufNum; diff -r fcbdee9cdd74 -r b894922d58cc hedgewars/uRenderUtils.pas --- a/hedgewars/uRenderUtils.pas Tue Sep 08 19:20:58 2015 +0300 +++ b/hedgewars/uRenderUtils.pas Mon Nov 16 22:57:24 2015 +0300 @@ -99,7 +99,7 @@ tmpsurf:= TTF_RenderUTF8_Blended(Fontz[Font].Handle, PChar(s), clr); finalRect.x:= X + cFontBorder + 2; finalRect.y:= Y + cFontBorder; - SDLTry(tmpsurf <> nil, true); + SDLTry(tmpsurf <> nil, 'TTF_RenderUTF8_Blended', true); SDL_UpperBlit(tmpsurf, @textRect, Surface, @finalRect); SDL_FreeSurface(tmpsurf); finalRect.x:= X; @@ -522,7 +522,7 @@ 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, true); + SDLTry(tmpsurf <> nil, 'TTF_Init', true); SDL_UpperBlit(tmpsurf, nil, finalSurface, @rect); SDL_FreeSurface(tmpsurf); inc(line); diff -r fcbdee9cdd74 -r b894922d58cc hedgewars/uScript.pas --- a/hedgewars/uScript.pas Tue Sep 08 19:20:58 2015 +0300 +++ b/hedgewars/uScript.pas Mon Nov 16 22:57:24 2015 +0300 @@ -628,7 +628,9 @@ 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); + if gear <> nil then + lua_pushinteger(L, gear^.uid) + else lua_pushnil(L) end else lua_pushnil(L); @@ -642,7 +644,9 @@ 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); + if gear <> nil then + lua_pushinteger(L, gear^.uid) + else lua_pushnil(L) end else lua_pushnil(L); @@ -656,7 +660,9 @@ 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); + if gear <> nil then + lua_pushinteger(L, gear^.uid) + else lua_pushnil(L) end else lua_pushnil(L); @@ -675,9 +681,8 @@ 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); + lua_pushinteger(L, gear^.uid) + else lua_pushnil(L); end else lua_pushnil(L); @@ -694,9 +699,8 @@ 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); + lua_pushinteger(L, gear^.uid) + else lua_pushnil(L); end else lua_pushnil(L); @@ -713,9 +717,8 @@ 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); + lua_pushinteger(L, gear^.uid) + else lua_pushnil(L); end else lua_pushnil(L); @@ -917,29 +920,30 @@ 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^.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); 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); lua_pushnil(L) end; - lc_getgearvalues:= 11 + lc_getgearvalues:= 12 end; function lc_setgearvalues(L : Plua_State) : LongInt; Cdecl; var gear : PGear; begin -// Currently allows 1-12 params -// if CheckLuaParamCount(L, 12, 'SetGearValues', 'gearUid, Angle, Power, WDTimer, Radius, Density, Karma, DirAngle, AdvBounce, ImpactSound, # ImpactSounds, Tint') then +// 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 @@ -965,7 +969,9 @@ 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) + gear^.Tint := lua_tointeger(L, 12); + if not lua_isnoneornil(L, 13) then + gear^.Damage := lua_tointeger(L, 13); end; // end // else @@ -2885,6 +2891,12 @@ 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; diff -r fcbdee9cdd74 -r b894922d58cc hedgewars/uSound.pas --- a/hedgewars/uSound.pas Tue Sep 08 19:20:58 2015 +0300 +++ b/hedgewars/uSound.pas Mon Nov 16 22:57:24 2015 +0300 @@ -301,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 @@ -322,7 +322,7 @@ end; WriteToConsole('Init SDL_mixer... '); - SDLTry(Mix_Init(MIX_INIT_OGG) <> 0, true); + SDLTry(Mix_Init(MIX_INIT_OGG) <> 0, 'Mix_Init', true); WriteLnToConsole(msgOK); Mix_AllocateChannels(Succ(chanTPU)); @@ -424,7 +424,7 @@ s:= cPathz[Soundz[snd].Path] + '/' + Soundz[snd].FileName; WriteToConsole(msgLoading + s + ' '); defVoicepack^.chunks[snd]:= Mix_LoadWAV_RW(rwopsOpenRead(s), 1); - SDLTry(defVoicepack^.chunks[snd] <> nil, true); + SDLTry(defVoicepack^.chunks[snd] <> nil, 'Mix_LoadWAV_RW', true); WriteLnToConsole(msgOK); end; lastChan[snd]:= Mix_PlayChannelTimed(-1, defVoicepack^.chunks[snd], 0, -1) @@ -523,7 +523,7 @@ s:= cPathz[Soundz[snd].Path] + '/' + Soundz[snd].FileName; WriteToConsole(msgLoading + s + ' '); defVoicepack^.chunks[snd]:= Mix_LoadWAV_RW(rwopsOpenRead(s), 1); - SDLTry(defVoicepack^.chunks[snd] <> nil, true); + SDLTry(defVoicepack^.chunks[snd] <> nil, 'Mix_LoadWAV_RW', true); WriteLnToConsole(msgOK); end; if fadems > 0 then @@ -574,10 +574,10 @@ WriteToConsole(msgLoading + s + ' '); Mus:= Mix_LoadMUS_RW(rwopsOpenRead(s)); - SDLTry(Mus <> nil, false); + SDLTry(Mus <> nil, 'Mix_LoadMUS_RW', false); WriteLnToConsole(msgOK); - SDLTry(Mix_FadeInMusic(Mus, -1, 3000) <> -1, false) + SDLTry(Mix_FadeInMusic(Mus, -1, 3000) <> -1, 'Mix_FadeInMusic', false) end; procedure SetVolume(vol: LongInt); diff -r fcbdee9cdd74 -r b894922d58cc hedgewars/uStore.pas --- a/hedgewars/uStore.pas Tue Sep 08 19:20:58 2015 +0300 +++ b/hedgewars/uStore.pas Mon Nov 16 22:57:24 2015 +0300 @@ -55,25 +55,20 @@ procedure InitOffscreenOpenGL; {$ENDIF} -{$IFDEF SDL2} procedure WarpMouse(x, y: Word); inline; -{$ENDIF} procedure SwapBuffers; {$IFDEF USE_VIDEO_RECORDING}cdecl{$ELSE}inline{$ENDIF}; procedure SetSkyColor(r, g, b: real); implementation uses uMisc, uConsole, uVariables, uUtils, uTextures, uRender, uRenderUtils, uCommands, uPhysFSLayer, uDebug - {$IFDEF USE_CONTEXT_RESTORE}, uWorld{$ENDIF} - {$IF NOT DEFINED(SDL2) AND DEFINED(USE_VIDEO_RECORDING)}, glut {$ENDIF}; + {$IFDEF USE_CONTEXT_RESTORE}, uWorld{$ENDIF}; -var -{$IFDEF SDL2} +//type TGPUVendor = (gvUnknown, gvNVIDIA, gvATI, gvIntel, gvApple); + +var SDLwindow: PSDL_Window; SDLGLcontext: PSDL_GLContext; -{$ELSE} - SDLPrimSurface: PSDL_Surface; -{$ENDIF} squaresize : LongInt; numsquares : LongInt; ProgrTex: PTexture; @@ -117,9 +112,9 @@ clr.g:= (Color shr 8) and $FF; clr.b:= Color and $FF; tmpsurf:= TTF_RenderUTF8_Blended(Fontz[Font].Handle, s, clr); -SDLTry(tmpsurf <> nil, true); +SDLTry(tmpsurf <> nil, 'TTF_RenderUTF8_Blended', true); tmpsurf:= doSurfaceConversion(tmpsurf); -SDLTry(tmpsurf <> nil, true); +SDLTry(tmpsurf <> nil, 'TTF_RenderUTF8_Blended, doSurfaceConversion', true); SDL_UpperBlit(tmpsurf, nil, Surface, @finalRect); SDL_FreeSurface(tmpsurf); finalRect.x:= X; @@ -361,7 +356,7 @@ s:= cPathz[ptFonts] + '/' + Name; WriteToConsole(msgLoading + s + ' (' + inttostr(Height) + 'pt)... '); Handle:= TTF_OpenFontRW(rwopsOpenRead(s), true, Height); - SDLTry(Handle <> nil, true); + SDLTry(Handle <> nil, 'TTF_OpenFontRW', true); TTF_SetFontStyle(Handle, style); WriteLnToConsole(msgOK) end; @@ -370,7 +365,11 @@ begin MakeCrossHairs; LoadGraves; +{$IFDEF IPHONEOS} + tmpHatSurf:= LoadDataImage(ptHats, 'chef', ifNone); +{$ELSE} tmpHatSurf:= LoadDataImage(ptHats, 'Reserved/chef', ifNone); +{$ENDIF} ChefHatTexture:= Surface2Tex(tmpHatSurf, true); freeTmpHatSurf(); end; @@ -606,7 +605,7 @@ // anounce that loading failed OutError(msgFailed, false); - SDLTry(false, (imageFlags and ifCritical) <> 0); + SDLTry(false, 'LoadImage', (imageFlags and ifCritical) <> 0); // rwops was already freed by IMG_Load_RW rwops:= nil; end else @@ -719,12 +718,12 @@ {$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} -{$IFNDEF SDL2} // vsync is default in SDL2 - SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, LongInt((cReducedQuality and rqDesyncVBlank) = 0)); -{$ENDIF} SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 6); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5); @@ -737,38 +736,22 @@ procedure SetupOpenGL; var buf: array[byte] of char; begin + AddFileLog('Setting up OpenGL (using driver: ' + shortstring(SDL_GetCurrentVideoDriver()) + ')'); -{$IFDEF SDL2} - AddFileLog('Setting up OpenGL (using driver: ' + shortstring(SDL_GetCurrentVideoDriver()) + ')'); -{$ELSE} - buf[0]:= char(0); // avoid compiler hint - AddFileLog('Setting up OpenGL (using driver: ' + shortstring(SDL_VideoDriverName(buf, sizeof(buf))) + ')'); -{$ENDIF} + // 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); + //SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); + if SDLGLcontext = nil then + SDLGLcontext:= SDL_GL_CreateContext(SDLwindow); + SDLTry(SDLGLcontext <> nil, 'SDLGLcontext', true); + SDLTry(SDL_GL_SetSwapInterval(1) = 0, 'SDL_GL_SetSwapInterval', true); RendererSetup(); + +// gl2 init/matrix code was here, but removed end; -(* -procedure UpdateProjection; -var - s: GLfloat; -begin - s:=cScaleFactor; - mProjection[0,0]:= s/cScreenWidth; mProjection[0,1]:= 0.0; mProjection[0,2]:=0.0; mProjection[0,3]:= 0.0; - mProjection[1,0]:= 0.0; mProjection[1,1]:= -s/cScreenHeight; mProjection[1,2]:=0.0; mProjection[1,3]:= 0.0; - mProjection[2,0]:= 0.0; mProjection[2,1]:= 0.0; mProjection[2,2]:=1.0; mProjection[2,3]:= 0.0; - mProjection[3,0]:= cStereoDepth; mProjection[3,1]:= s/2; mProjection[3,2]:=0.0; mProjection[3,3]:= 1.0; - -{$IFDEF GL2} - UpdateModelviewProjection; -{$ELSE} - glMatrixMode(GL_PROJECTION); - glLoadMatrixf(@mProjection[0, 0]); - glMatrixMode(GL_MODELVIEW); -{$ENDIF} -end; -*) - //////////////////////////////////////////////////////////////////////////////// procedure AddProgress; var r: TSDL_Rect; @@ -998,41 +981,23 @@ end; {$IFDEF USE_VIDEO_RECORDING} -{$IFDEF SDL2} procedure InitOffscreenOpenGL; begin // create hidden window - SDLwindow:= SDL_CreateWindow('hedgewars video rendering (SDL2 hidden window)', + SDLwindow:= SDL_CreateWindow(PChar('hedgewars video rendering (SDL2 hidden window)'), SDL_WINDOWPOS_CENTERED_MASK, SDL_WINDOWPOS_CENTERED_MASK, cScreenWidth, cScreenHeight, SDL_WINDOW_HIDDEN or SDL_WINDOW_OPENGL); - SDLTry(SDLwindow <> nil, true); + SDLTry(SDLwindow <> nil, 'SDL_CreateWindow', true); SetupOpenGL(); end; -{$ELSE} -procedure InitOffscreenOpenGL; -var ArgCount: LongInt; - PrgName: pchar; -begin - ArgCount:= 1; - PrgName:= 'hwengine'; - glutInit(@ArgCount, @PrgName); - glutInitWindowSize(cScreenWidth, cScreenHeight); - // we do not need a window, but without this call OpenGL will not initialize - glutCreateWindow('hedgewars video rendering (glut hidden window)'); - glutHideWindow(); - // we do not need to set this callback, but it is required for GLUT3 compat - glutDisplayFunc(@SwapBuffers); - RendererSetup(); -end; -{$ENDIF} // SDL2 {$ENDIF} // USE_VIDEO_RECORDING procedure chFullScr(var s: shortstring); var flags: Longword = 0; reinit: boolean = false; {$IFNDEF DARWIN}ico: PSDL_Surface;{$ENDIF} - {$IFDEF SDL2}x, y: LongInt;{$ENDIF} + x, y: LongInt; begin if cOnlyStats then begin @@ -1055,28 +1020,12 @@ end; AddFileLog('Preparing to change video parameters...'); -{$IFDEF SDL2} if SDLwindow = nil then -{$ELSE} - if SDLPrimSurface = nil then -{$ENDIF} begin // set window title - {$IFNDEF SDL2} - SDL_WM_SetCaption(_P'Hedgewars', nil); - {$ENDIF} WriteToConsole('Init SDL_image... '); - SDLTry(IMG_Init(IMG_INIT_PNG) <> 0, true); + SDLTry(IMG_Init(IMG_INIT_PNG) <> 0, 'IMG_Init', true); WriteLnToConsole(msgOK); - // load engine icon - {$IFNDEF DARWIN} - ico:= LoadDataImage(ptGraphics, 'hwengine', ifIgnoreCaps); - if ico <> nil then - begin - SDL_WM_SetIcon(ico, 0); - SDL_FreeSurface(ico) - end; - {$ENDIF} end else begin @@ -1101,10 +1050,6 @@ //uTextures.freeModule; //DEBUG ONLY {$ENDIF} AddFileLog('Freeing old primary surface...'); - {$IFNDEF SDL2} - SDL_FreeSurface(SDLPrimSurface); - SDLPrimSurface:= nil; - {$ENDIF} {$ENDIF} end; @@ -1118,7 +1063,6 @@ *) SetupOpenGLAttributes(); {$ENDIF} -{$IFDEF SDL2} // these values in x and y make the window appear in the center x:= SDL_WINDOWPOS_CENTERED_MASK; y:= SDL_WINDOWPOS_CENTERED_MASK; @@ -1137,26 +1081,18 @@ flags:= flags or SDL_WINDOW_FULLSCREEN; if SDLwindow = nil then - SDLwindow:= SDL_CreateWindow('Hedgewars', x, y, cScreenWidth, cScreenHeight, flags); - SDLTry(SDLwindow <> nil, true); -{$ELSE} - flags:= SDL_OPENGL or SDL_RESIZABLE; - if cFullScreen then - flags:= flags or SDL_FULLSCREEN; - if not cOnlyStats then + SDLwindow:= SDL_CreateWindow(PChar('Hedgewars'), x, y, cScreenWidth, cScreenHeight, flags); + SDLTry(SDLwindow <> nil, 'SDL_CreateWindow', true); + + // load engine ico + {$IFNDEF DARWIN} + ico:= LoadDataImage(ptGraphics, 'hwengine', ifIgnoreCaps); + if ico <> nil then begin - {$IFDEF WIN32} - s:= SDL_getenv('SDL_VIDEO_CENTERED'); - SDL_putenv('SDL_VIDEO_CENTERED=1'); + SDL_SetWindowIcon(SDLwindow, ico); + SDL_FreeSurface(ico); + end; {$ENDIF} - SDLPrimSurface:= SDL_SetVideoMode(cScreenWidth, cScreenHeight, 0, flags); - SDLTry(SDLPrimSurface <> nil, true); - {$IFDEF WIN32} - SDL_putenv(str2pchar('SDL_VIDEO_CENTERED=' + s)); - {$ENDIF} - end; -{$ENDIF} - SetupOpenGL(); if reinit then @@ -1179,7 +1115,6 @@ end; end; -{$IFDEF SDL2} // for sdl1.2 we directly call SDL_WarpMouse() // for sdl2 we provide a SDL_WarpMouse() which just calls this function // this has the advantage of reducing 'uses' and 'ifdef' statements @@ -1188,17 +1123,12 @@ begin SDL_WarpMouseInWindow(SDLwindow, x, y); end; -{$ENDIF} procedure SwapBuffers; {$IFDEF USE_VIDEO_RECORDING}cdecl{$ELSE}inline{$ENDIF}; begin if GameType = gmtRecord then exit; -{$IFDEF SDL2} SDL_GL_SwapWindow(SDLwindow); -{$ELSE} - SDL_GL_SwapBuffers(); -{$ENDIF} end; procedure SetSkyColor(r, g, b: real); @@ -1226,12 +1156,8 @@ // init all count texture pointers for i:= Low(CountTexz) to High(CountTexz) do CountTexz[i] := nil; -{$IFDEF SDL2} SDLwindow:= nil; SDLGLcontext:= nil; -{$ELSE} - SDLPrimSurface:= nil; -{$ENDIF} prevHat:= 'NoHat'; tmpHatSurf:= nil; @@ -1253,10 +1179,8 @@ end; TTF_Quit(); -{$IFDEF SDL2} SDL_GL_DeleteContext(SDLGLcontext); SDL_DestroyWindow(SDLwindow); -{$ENDIF} SDL_Quit(); end; end. diff -r fcbdee9cdd74 -r b894922d58cc hedgewars/uTeams.pas --- a/hedgewars/uTeams.pas Tue Sep 08 19:20:58 2015 +0300 +++ b/hedgewars/uTeams.pas Mon Nov 16 22:57:24 2015 +0300 @@ -604,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; diff -r fcbdee9cdd74 -r b894922d58cc hedgewars/uTextures.pas --- a/hedgewars/uTextures.pas Tue Sep 08 19:20:58 2015 +0300 +++ b/hedgewars/uTextures.pas Mon Nov 16 22:57:24 2015 +0300 @@ -236,7 +236,7 @@ glBindTexture(GL_TEXTURE_2D, Surface2Tex^.id); if SDL_MustLock(surf) then - SDLTry(SDL_LockSurface(surf) >= 0, true); + SDLTry(SDL_LockSurface(surf) >= 0, 'Lock surface', true); fromP4:= Surf^.pixels; diff -r fcbdee9cdd74 -r b894922d58cc hedgewars/uTouch.pas --- a/hedgewars/uTouch.pas Tue Sep 08 19:20:58 2015 +0300 +++ b/hedgewars/uTouch.pas Mon Nov 16 22:57:24 2015 +0300 @@ -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; diff -r fcbdee9cdd74 -r b894922d58cc hedgewars/uTypes.pas --- a/hedgewars/uTypes.pas Tue Sep 08 19:20:58 2015 +0300 +++ b/hedgewars/uTypes.pas Mon Nov 16 22:57:24 2015 +0300 @@ -61,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, @@ -88,7 +89,7 @@ sprBulletHit, sprSnowball, sprHandSnowball, sprSnow, sprSDFlake, sprSDWater, sprSDCloud, sprSDSplash, sprSDDroplet, sprTardis, sprSlider, sprBotlevels, sprHandKnife, sprKnife, sprStar, sprIceTexture, sprIceGun, - sprFrozenHog, sprAmRubber, sprBoing, sprCustom1, sprCustom2, sprAirMine + sprFrozenHog, sprAmRubber, sprBoing, sprCustom1, sprCustom2, sprAirMine, sprHandAirMine ); // Gears that interact with other Gears and/or Land @@ -455,7 +456,7 @@ sidConfirm, sidSuddenDeath, sidRemaining, sidFuel, sidSync, sidNoEndTurn, sidNotYetAvailable, sidRoundSD, sidRoundsSD, sidReady, sidBounce1, sidBounce2, sidBounce3, sidBounce4, sidBounce5, sidBounce, - sidMute, sidAFK, sidAutoCameraOff, sidAutoCameraOn); + sidMute, sidAFK, sidAutoCameraOff, sidAutoCameraOn, sidPressTarget); // Events that are important for the course of the game or at least interesting for other reasons TEventId = (eidDied, eidDrowned, eidRoundStart, eidRoundWin, eidRoundDraw, diff -r fcbdee9cdd74 -r b894922d58cc hedgewars/uVariables.pas --- a/hedgewars/uVariables.pas Tue Sep 08 19:20:58 2015 +0300 +++ b/hedgewars/uVariables.pas Mon Nov 16 22:57:24 2015 +0300 @@ -21,7 +21,7 @@ unit uVariables; interface -uses SDLh, uTypes, uFloat, GLunit, uConsts, Math, uUtils, uMatrix; +uses SDLh, uTypes, uFloat, GLunit, uConsts, Math, uUtils{$IFDEF GL2}, uMatrix{$ENDIF}; var /////// init flags /////// @@ -235,14 +235,12 @@ LuaTemplateNumber : LongWord; - LastVoice : TVoice = ( snd: sndNone; voicepack: nil ); + LastVoice : TVoice; mobileRecord: TMobileRecord; MaxTextureSize: LongInt; - ChatPasteBuffer: shortstring; - ///////////////////////////////////// //Buttons {$IFDEF USE_TOUCH_INTERFACE} @@ -256,7 +254,10 @@ 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 '/Graphics', // ptGraphics @@ -284,7 +285,10 @@ ); var - Fontz: array[THWFont] of THHFont = ( + Fontz: array[THWFont] of THHFont; + +const + FontzInit: array[THWFont] of THHFont = ( (Handle: nil; Height: 12; style: TTF_STYLE_NORMAL; @@ -314,7 +318,10 @@ ); var - SpritesData: array[TSprite] of TSpriteData = ( + 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; @@ -416,13 +423,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 @@ -430,10 +437,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 @@ -711,7 +720,9 @@ (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 + 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 @@ -732,8 +743,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; @@ -746,7 +757,13 @@ 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; @@ -1344,7 +1361,7 @@ NameTex: nil; Probability: 100; NumberInCase: 4; - Ammo: (Propz: 0; + Ammo: (Propz: ammoprop_NeedUpDown; Count: 4; NumPerTurn: 0; Timer: 0; @@ -2135,6 +2152,7 @@ NumberInCase: 1; Ammo: (Propz: ammoprop_Power or ammoprop_AltUse or + ammoprop_NeedUpDown or ammoprop_NoRoundEnd; Count: 2; NumPerTurn: 0; @@ -2216,6 +2234,7 @@ Probability: 20; NumberInCase: 1; Ammo: (Propz: ammoprop_NoRoundEnd or + ammoprop_NeedUpDown or ammoprop_Utility; Count: 1; NumPerTurn: 0; @@ -2488,7 +2507,19 @@ procedure initModule; var s: shortstring; + i: integer; begin + // 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, '.'); @@ -2669,8 +2700,13 @@ 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; @@ -2696,7 +2732,42 @@ 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 fcbdee9cdd74 -r b894922d58cc hedgewars/uWorld.pas --- a/hedgewars/uWorld.pas Tue Sep 08 19:20:58 2015 +0300 +++ b/hedgewars/uWorld.pas Mon Nov 16 22:57:24 2015 +0300 @@ -1148,7 +1148,7 @@ procedure ShiftWorld(Dir: LongInt); inline; begin preShiftWorldDx:= WorldDx; - WorldDx:= WorldDx + Dir * LongInt(playWidth); + WorldDx:= WorldDx + LongInt(Dir * LongInt(playWidth)); end; @@ -1737,7 +1737,7 @@ CursorPoint.X:= (prevPoint.X * 7 + dstX) div 8; end; - if isPhone() or (cScreenHeight < 600) or ((FollowGear^.dY * z).Round < 10) then + 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; @@ -1930,7 +1930,7 @@ 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); @@ -1942,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 diff -r fcbdee9cdd74 -r b894922d58cc misc/liblua/Xcode/Lua.xcodeproj/project.pbxproj --- a/misc/liblua/Xcode/Lua.xcodeproj/project.pbxproj Tue Sep 08 19:20:58 2015 +0300 +++ b/misc/liblua/Xcode/Lua.xcodeproj/project.pbxproj Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc misc/libphysfs/CMakeLists.txt --- a/misc/libphysfs/CMakeLists.txt Tue Sep 08 19:20:58 2015 +0300 +++ b/misc/libphysfs/CMakeLists.txt Mon Nov 16 22:57:24 2015 +0300 @@ -148,7 +148,7 @@ if(WINDOWS) set(PHYSFS_HAVE_CDROM_SUPPORT TRUE) set(PHYSFS_HAVE_THREAD_SUPPORT TRUE) - list(APPEND OTHER_LDFLAGS ${SDL_LIBRARY}) + list(APPEND OTHER_LDFLAGS ${SDL2_LIBRARY}) endif(WINDOWS) if(NOT PHYSFS_HAVE_CDROM_SUPPORT) diff -r fcbdee9cdd74 -r b894922d58cc misc/libphysfs/Xcode/Physfs.xcodeproj/project.pbxproj --- a/misc/libphysfs/Xcode/Physfs.xcodeproj/project.pbxproj Tue Sep 08 19:20:58 2015 +0300 +++ b/misc/libphysfs/Xcode/Physfs.xcodeproj/project.pbxproj Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc misc/libphyslayer/CMakeLists.txt --- a/misc/libphyslayer/CMakeLists.txt Tue Sep 08 19:20:58 2015 +0300 +++ b/misc/libphyslayer/CMakeLists.txt Mon Nov 16 22:57:24 2015 +0300 @@ -1,7 +1,7 @@ +find_package(SDL2 REQUIRED) -find_package(SDL1or2) +include_directories(${SDL2_INCLUDE_DIR}) include_directories(${PHYSFS_INCLUDE_DIR}) -include_directories(${SDL_INCLUDE_DIR}) include_directories(${LUA_INCLUDE_DIR}) @@ -15,7 +15,7 @@ #compiles and links actual library add_library (physlayer ${PHYSLAYER_SRCS}) #TODO: find good VERSION and SOVERSION values -target_link_libraries(physlayer ${SDL_LIBRARY} lua physfs) +target_link_libraries(physlayer ${SDL2_LIBRARY} lua physfs) install(TARGETS physlayer RUNTIME DESTINATION ${target_binary_install_dir} LIBRARY DESTINATION ${target_library_install_dir} ARCHIVE DESTINATION ${target_library_install_dir}) diff -r fcbdee9cdd74 -r b894922d58cc misc/libphyslayer/Xcode/Physlayer.xcodeproj/project.pbxproj --- a/misc/libphyslayer/Xcode/Physlayer.xcodeproj/project.pbxproj Tue Sep 08 19:20:58 2015 +0300 +++ b/misc/libphyslayer/Xcode/Physlayer.xcodeproj/project.pbxproj Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc misc/winutils/include/GL/glut.h --- a/misc/winutils/include/GL/glut.h Tue Sep 08 19:20:58 2015 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,716 +0,0 @@ -#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 fcbdee9cdd74 -r b894922d58cc project_files/Android-build/SDL-android-project/assets/Data/Graphics/Buttons/switchbutton.png Binary file project_files/Android-build/SDL-android-project/assets/Data/Graphics/Buttons/switchbutton.png has changed diff -r fcbdee9cdd74 -r b894922d58cc project_files/Android-build/SDL-android-project/assets/Data/Graphics/Buttons/targetbutton.png Binary file project_files/Android-build/SDL-android-project/assets/Data/Graphics/Buttons/targetbutton.png has changed diff -r fcbdee9cdd74 -r b894922d58cc project_files/Android-build/SDL-android-project/assets/Data/Graphics/Buttons/timerbutton.png Binary file project_files/Android-build/SDL-android-project/assets/Data/Graphics/Buttons/timerbutton.png has changed diff -r fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/AboutViewController.m --- a/project_files/HedgewarsMobile/Classes/AboutViewController.m Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/AboutViewController.m Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/Appirater.h --- a/project_files/HedgewarsMobile/Classes/Appirater.h Tue Sep 08 19:20:58 2015 +0300 +++ /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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/Appirater.m --- a/project_files/HedgewarsMobile/Classes/Appirater.m Tue Sep 08 19:20:58 2015 +0300 +++ /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 fcbdee9cdd74 -r b894922d58cc 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 Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc 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 Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc 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 Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc 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 Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc 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 Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc 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 Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc 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 Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc 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 Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc 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 Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc 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 Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc 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 Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc 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 Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc 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 Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc 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 Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc 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 Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc 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 Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc 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 Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc 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 Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc 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 Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc 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 Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc 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 Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc 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 Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc 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 Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc 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 Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc 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 Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc 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 Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc 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 Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc 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 Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc 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 Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc 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 Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc 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 Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc 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 Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc 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 Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc 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 Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc 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 Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/CreationChamber.m --- a/project_files/HedgewarsMobile/Classes/CreationChamber.m Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/CreationChamber.m Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/EditableCellView.m --- a/project_files/HedgewarsMobile/Classes/EditableCellView.m Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/EditableCellView.m Mon Nov 16 22:57:24 2015 +0300 @@ -18,7 +18,7 @@ #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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/EngineProtocolNetwork.m --- a/project_files/HedgewarsMobile/Classes/EngineProtocolNetwork.m Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/EngineProtocolNetwork.m Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/ExtraCategories.h --- a/project_files/HedgewarsMobile/Classes/ExtraCategories.h Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/ExtraCategories.h Mon Nov 16 22:57:24 2015 +0300 @@ -50,6 +50,9 @@ -(id) initWithFrame:(CGRect) frame andTitle:(NSString *)title; +- (void)applyBlackQuickStyle; +- (void)applyDarkBlueQuickStyle; + @end diff -r fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/ExtraCategories.m --- a/project_files/HedgewarsMobile/Classes/ExtraCategories.m Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/ExtraCategories.m Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/FlagsViewController.m --- a/project_files/HedgewarsMobile/Classes/FlagsViewController.m Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/FlagsViewController.m Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/FortsViewController.m --- a/project_files/HedgewarsMobile/Classes/FortsViewController.m Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/FortsViewController.m Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/GameConfigViewController-iPad.xib --- a/project_files/HedgewarsMobile/Classes/GameConfigViewController-iPad.xib Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/GameConfigViewController-iPad.xib Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/GameConfigViewController-iPhone.xib --- a/project_files/HedgewarsMobile/Classes/GameConfigViewController-iPhone.xib Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/GameConfigViewController-iPhone.xib Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/GameConfigViewController.h --- a/project_files/HedgewarsMobile/Classes/GameConfigViewController.h Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/GameConfigViewController.h Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/GameConfigViewController.m --- a/project_files/HedgewarsMobile/Classes/GameConfigViewController.m Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/GameConfigViewController.m Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/GameInterfaceBridge.m --- a/project_files/HedgewarsMobile/Classes/GameInterfaceBridge.m Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/GameInterfaceBridge.m Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/GameLogViewController.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/GameLogViewController.h Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/GameLogViewController.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/GameLogViewController.m Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/GeneralSettingsViewController.h --- a/project_files/HedgewarsMobile/Classes/GeneralSettingsViewController.h Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/GeneralSettingsViewController.h Mon Nov 16 22:57:24 2015 +0300 @@ -18,9 +18,9 @@ #import - +#import "TableViewControllerWithDoneButton.h" -@interface GeneralSettingsViewController : UITableViewController { +@interface GeneralSettingsViewController : TableViewControllerWithDoneButton { } diff -r fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/GeneralSettingsViewController.m --- a/project_files/HedgewarsMobile/Classes/GeneralSettingsViewController.m Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/GeneralSettingsViewController.m Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/GravesViewController.m --- a/project_files/HedgewarsMobile/Classes/GravesViewController.m Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/GravesViewController.m Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/HWUtils.h --- a/project_files/HedgewarsMobile/Classes/HWUtils.h Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/HWUtils.h Mon Nov 16 22:57:24 2015 +0300 @@ -41,6 +41,7 @@ +(NSInteger) randomPort; +(void) freePort:(NSInteger) port; +(BOOL) isNetworkReachable; ++(NSString *) languageID; //+(UIView *)mainSDLViewInstance; @end diff -r fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/HWUtils.m --- a/project_files/HedgewarsMobile/Classes/HWUtils.m Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/HWUtils.m Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/HedgewarsAppDelegate.m --- a/project_files/HedgewarsMobile/Classes/HedgewarsAppDelegate.m Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/HedgewarsAppDelegate.m Mon Nov 16 22:57:24 2015 +0300 @@ -19,7 +19,7 @@ #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 fcbdee9cdd74 -r b894922d58cc 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 Mon Nov 16 22:57:24 2015 +0300 @@ -0,0 +1,320 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r fcbdee9cdd74 -r b894922d58cc 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 Mon Nov 16 22:57:24 2015 +0300 @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/HelpPageLobbyViewController.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/HelpPageLobbyViewController.h Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/HelpPageLobbyViewController.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/HelpPageLobbyViewController.m Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/HogHatViewController.h --- a/project_files/HedgewarsMobile/Classes/HogHatViewController.h Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/HogHatViewController.h Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/HogHatViewController.m --- a/project_files/HedgewarsMobile/Classes/HogHatViewController.m Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/HogHatViewController.m Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/HoldTableViewCell.m --- a/project_files/HedgewarsMobile/Classes/HoldTableViewCell.m Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/HoldTableViewCell.m Mon Nov 16 22:57:24 2015 +0300 @@ -18,7 +18,7 @@ #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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/LabelWithIBLocalization.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/LabelWithIBLocalization.h Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/LabelWithIBLocalization.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/LabelWithIBLocalization.m Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/LevelViewController.m --- a/project_files/HedgewarsMobile/Classes/LevelViewController.m Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/LevelViewController.m Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/MGSplitViewController/MGSplitCornersView.h --- a/project_files/HedgewarsMobile/Classes/MGSplitViewController/MGSplitCornersView.h Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/MGSplitViewController/MGSplitCornersView.h Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/MGSplitViewController/MGSplitCornersView.m --- a/project_files/HedgewarsMobile/Classes/MGSplitViewController/MGSplitCornersView.m Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/MGSplitViewController/MGSplitCornersView.m Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/MGSplitViewController/MGSplitDividerView.h --- a/project_files/HedgewarsMobile/Classes/MGSplitViewController/MGSplitDividerView.h Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/MGSplitViewController/MGSplitDividerView.h Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/MGSplitViewController/MGSplitDividerView.m --- a/project_files/HedgewarsMobile/Classes/MGSplitViewController/MGSplitDividerView.m Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/MGSplitViewController/MGSplitDividerView.m Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/MGSplitViewController/MGSplitViewController.h --- a/project_files/HedgewarsMobile/Classes/MGSplitViewController/MGSplitViewController.h Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/MGSplitViewController/MGSplitViewController.h Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/MGSplitViewController/MGSplitViewController.m --- a/project_files/HedgewarsMobile/Classes/MGSplitViewController/MGSplitViewController.m Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/MGSplitViewController/MGSplitViewController.m Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/MXAudioPlayerFadeOperation.m --- a/project_files/HedgewarsMobile/Classes/MXAudioPlayerFadeOperation.m Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/MXAudioPlayerFadeOperation.m Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/MainMenuViewController-iPad.xib --- a/project_files/HedgewarsMobile/Classes/MainMenuViewController-iPad.xib Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/MainMenuViewController-iPad.xib Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/MainMenuViewController-iPhone.xib --- a/project_files/HedgewarsMobile/Classes/MainMenuViewController-iPhone.xib Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/MainMenuViewController-iPhone.xib Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/MainMenuViewController.h --- a/project_files/HedgewarsMobile/Classes/MainMenuViewController.h Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/MainMenuViewController.h Mon Nov 16 22:57:24 2015 +0300 @@ -19,29 +19,7 @@ #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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/MainMenuViewController.m --- a/project_files/HedgewarsMobile/Classes/MainMenuViewController.m Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/MainMenuViewController.m Mon Nov 16 22:57:24 2015 +0300 @@ -20,7 +20,8 @@ #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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/MapConfigViewController-iPhone.xib --- a/project_files/HedgewarsMobile/Classes/MapConfigViewController-iPhone.xib Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/MapConfigViewController-iPhone.xib Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/MapConfigViewController.m --- a/project_files/HedgewarsMobile/Classes/MapConfigViewController.m Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/MapConfigViewController.m Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/MapPreviewButtonView.m --- a/project_files/HedgewarsMobile/Classes/MapPreviewButtonView.m Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/MapPreviewButtonView.m Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/MissionTrainingViewController-iPhone.xib --- a/project_files/HedgewarsMobile/Classes/MissionTrainingViewController-iPhone.xib Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/MissionTrainingViewController-iPhone.xib Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/MissionTrainingViewController.h --- a/project_files/HedgewarsMobile/Classes/MissionTrainingViewController.h Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/MissionTrainingViewController.h Mon Nov 16 22:57:24 2015 +0300 @@ -20,18 +20,12 @@ #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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/MissionTrainingViewController.m --- a/project_files/HedgewarsMobile/Classes/MissionTrainingViewController.m Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/MissionTrainingViewController.m Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/PascalImports.h --- a/project_files/HedgewarsMobile/Classes/PascalImports.h Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/PascalImports.h Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/RestoreViewController-iPad.xib --- a/project_files/HedgewarsMobile/Classes/RestoreViewController-iPad.xib Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/RestoreViewController-iPad.xib Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/RestoreViewController-iPhone.xib --- a/project_files/HedgewarsMobile/Classes/RestoreViewController-iPhone.xib Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/RestoreViewController-iPhone.xib Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/RestoreViewController.m --- a/project_files/HedgewarsMobile/Classes/RestoreViewController.m Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/RestoreViewController.m Mon Nov 16 22:57:24 2015 +0300 @@ -20,6 +20,11 @@ #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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/SavedGamesViewController.h --- a/project_files/HedgewarsMobile/Classes/SavedGamesViewController.h Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/SavedGamesViewController.h Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/SavedGamesViewController.m --- a/project_files/HedgewarsMobile/Classes/SavedGamesViewController.m Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/SavedGamesViewController.m Mon Nov 16 22:57:24 2015 +0300 @@ -20,9 +20,12 @@ #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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/SavedGamesViewController.xib --- a/project_files/HedgewarsMobile/Classes/SavedGamesViewController.xib Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/SavedGamesViewController.xib Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/SchemeSettingsViewController.h --- a/project_files/HedgewarsMobile/Classes/SchemeSettingsViewController.h Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/SchemeSettingsViewController.h Mon Nov 16 22:57:24 2015 +0300 @@ -18,13 +18,10 @@ #import - - -@class SingleSchemeViewController; +#import "TableViewControllerWithDoneButton.h" -@interface SchemeSettingsViewController : UITableViewController { +@interface SchemeSettingsViewController : TableViewControllerWithDoneButton { NSMutableArray *listOfSchemes; - SingleSchemeViewController *childController; } @property (nonatomic, retain) NSMutableArray *listOfSchemes; diff -r fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/SchemeSettingsViewController.m --- a/project_files/HedgewarsMobile/Classes/SchemeSettingsViewController.m Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/SchemeSettingsViewController.m Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/SchemeWeaponConfigViewController.m --- a/project_files/HedgewarsMobile/Classes/SchemeWeaponConfigViewController.m Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/SchemeWeaponConfigViewController.m Mon Nov 16 22:57:24 2015 +0300 @@ -20,6 +20,7 @@ #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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/ServerProtocolNetwork.m --- a/project_files/HedgewarsMobile/Classes/ServerProtocolNetwork.m Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/ServerProtocolNetwork.m Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/SettingsBaseViewController.h --- a/project_files/HedgewarsMobile/Classes/SettingsBaseViewController.h Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/SettingsBaseViewController.h Mon Nov 16 22:57:24 2015 +0300 @@ -19,29 +19,16 @@ #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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/SettingsBaseViewController.m --- a/project_files/HedgewarsMobile/Classes/SettingsBaseViewController.m Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/SettingsBaseViewController.m Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/SettingsContainerViewController.h --- a/project_files/HedgewarsMobile/Classes/SettingsContainerViewController.h Tue Sep 08 19:20:58 2015 +0300 +++ /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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/SettingsContainerViewController.m --- a/project_files/HedgewarsMobile/Classes/SettingsContainerViewController.m Tue Sep 08 19:20:58 2015 +0300 +++ /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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/SingleSchemeViewController.m --- a/project_files/HedgewarsMobile/Classes/SingleSchemeViewController.m Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/SingleSchemeViewController.m Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/SingleTeamViewController.h --- a/project_files/HedgewarsMobile/Classes/SingleTeamViewController.h Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/SingleTeamViewController.h Mon Nov 16 22:57:24 2015 +0300 @@ -19,14 +19,6 @@ #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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/SingleTeamViewController.m --- a/project_files/HedgewarsMobile/Classes/SingleTeamViewController.m Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/SingleTeamViewController.m Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/SingleWeaponViewController.m --- a/project_files/HedgewarsMobile/Classes/SingleWeaponViewController.m Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/SingleWeaponViewController.m Mon Nov 16 22:57:24 2015 +0300 @@ -19,6 +19,10 @@ #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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/SquareButtonView.m --- a/project_files/HedgewarsMobile/Classes/SquareButtonView.m Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/SquareButtonView.m Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/StatsPageViewController.m --- a/project_files/HedgewarsMobile/Classes/StatsPageViewController.m Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/StatsPageViewController.m Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/SupportViewController.h --- a/project_files/HedgewarsMobile/Classes/SupportViewController.h Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/SupportViewController.h Mon Nov 16 22:57:24 2015 +0300 @@ -18,9 +18,9 @@ #import - +#import "TableViewControllerWithDoneButton.h" -@interface SupportViewController : UITableViewController { +@interface SupportViewController : TableViewControllerWithDoneButton { NSArray *waysToSupport; } diff -r fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/SupportViewController.m --- a/project_files/HedgewarsMobile/Classes/SupportViewController.m Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/SupportViewController.m Mon Nov 16 22:57:24 2015 +0300 @@ -18,7 +18,7 @@ #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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/TableViewControllerWithDoneButton.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/TableViewControllerWithDoneButton.h Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/TableViewControllerWithDoneButton.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/TableViewControllerWithDoneButton.m Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/TeamConfigViewController.m --- a/project_files/HedgewarsMobile/Classes/TeamConfigViewController.m Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/TeamConfigViewController.m Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/TeamSettingsViewController.h --- a/project_files/HedgewarsMobile/Classes/TeamSettingsViewController.h Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/TeamSettingsViewController.h Mon Nov 16 22:57:24 2015 +0300 @@ -18,13 +18,10 @@ #import - - -@class SingleTeamViewController; +#import "TableViewControllerWithDoneButton.h" -@interface TeamSettingsViewController : UITableViewController { +@interface TeamSettingsViewController : TableViewControllerWithDoneButton { NSMutableArray *listOfTeams; - SingleTeamViewController *childController; } @property (nonatomic, retain) NSMutableArray *listOfTeams; diff -r fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/TeamSettingsViewController.m --- a/project_files/HedgewarsMobile/Classes/TeamSettingsViewController.m Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/TeamSettingsViewController.m Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc 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 Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc 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 Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/VoicesViewController.m --- a/project_files/HedgewarsMobile/Classes/VoicesViewController.m Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/VoicesViewController.m Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/WeaponCellView.m --- a/project_files/HedgewarsMobile/Classes/WeaponCellView.m Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/WeaponCellView.m Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/WeaponSettingsViewController.h --- a/project_files/HedgewarsMobile/Classes/WeaponSettingsViewController.h Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/WeaponSettingsViewController.h Mon Nov 16 22:57:24 2015 +0300 @@ -18,13 +18,10 @@ #import - - -@class SingleWeaponViewController; +#import "TableViewControllerWithDoneButton.h" -@interface WeaponSettingsViewController : UITableViewController { +@interface WeaponSettingsViewController : TableViewControllerWithDoneButton { NSMutableArray *listOfWeapons; - SingleWeaponViewController *childController; } @property (nonatomic, retain) NSMutableArray *listOfWeapons; diff -r fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Classes/WeaponSettingsViewController.m --- a/project_files/HedgewarsMobile/Classes/WeaponSettingsViewController.m Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Classes/WeaponSettingsViewController.m Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Default-568h@2x.png Binary file project_files/HedgewarsMobile/Default-568h@2x.png has changed diff -r fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Hedgewars.xcodeproj/project.pbxproj --- a/project_files/HedgewarsMobile/Hedgewars.xcodeproj/project.pbxproj Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Hedgewars.xcodeproj/project.pbxproj Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc 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 Mon Nov 16 22:57:24 2015 +0300 @@ -0,0 +1,7 @@ + + + + + diff -r fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Info.plist --- a/project_files/HedgewarsMobile/Info.plist Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Info.plist Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Locale/English.lproj/About.strings Binary file project_files/HedgewarsMobile/Locale/English.lproj/About.strings has changed diff -r fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Locale/English.lproj/Localizable.strings Binary file project_files/HedgewarsMobile/Locale/English.lproj/Localizable.strings has changed diff -r fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Locale/English.lproj/Scheme.strings Binary file project_files/HedgewarsMobile/Locale/English.lproj/Scheme.strings has changed diff -r fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Locale/Turkish.lproj/About.strings Binary file project_files/HedgewarsMobile/Locale/Turkish.lproj/About.strings has changed diff -r fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Locale/Turkish.lproj/Localizable.strings Binary file project_files/HedgewarsMobile/Locale/Turkish.lproj/Localizable.strings has changed diff -r fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Locale/Turkish.lproj/Scheme.strings Binary file project_files/HedgewarsMobile/Locale/Turkish.lproj/Scheme.strings has changed diff -r fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Locale/ru.lproj/About.strings Binary file project_files/HedgewarsMobile/Locale/ru.lproj/About.strings has changed diff -r fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Locale/ru.lproj/Localizable.strings Binary file project_files/HedgewarsMobile/Locale/ru.lproj/Localizable.strings has changed diff -r fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Locale/ru.lproj/Scheme.strings Binary file project_files/HedgewarsMobile/Locale/ru.lproj/Scheme.strings has changed diff -r fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Locale/tr.lproj/About.strings Binary file project_files/HedgewarsMobile/Locale/tr.lproj/About.strings has changed diff -r fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Locale/tr.lproj/Localizable.strings Binary file project_files/HedgewarsMobile/Locale/tr.lproj/Localizable.strings has changed diff -r fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Locale/tr.lproj/Scheme.strings Binary file project_files/HedgewarsMobile/Locale/tr.lproj/Scheme.strings has changed diff -r fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Resources/Frontend/Help Bubbles/helpabove.png Binary file project_files/HedgewarsMobile/Resources/Frontend/Help Bubbles/helpabove.png has changed diff -r fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Resources/Frontend/Help Bubbles/helpbottom.png Binary file project_files/HedgewarsMobile/Resources/Frontend/Help Bubbles/helpbottom.png has changed diff -r fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Resources/Frontend/Help Bubbles/helpleft.png Binary file project_files/HedgewarsMobile/Resources/Frontend/Help Bubbles/helpleft.png has changed diff -r fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Resources/Frontend/Help Bubbles/helpplain.png Binary file project_files/HedgewarsMobile/Resources/Frontend/Help Bubbles/helpplain.png has changed diff -r fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Resources/Frontend/Help Bubbles/helpright.png Binary file project_files/HedgewarsMobile/Resources/Frontend/Help Bubbles/helpright.png has changed diff -r fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Resources/Icons/Icon-60@2x.png Binary file project_files/HedgewarsMobile/Resources/Icons/Icon-60@2x.png has changed diff -r fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Resources/Icons/Icon-76.png Binary file project_files/HedgewarsMobile/Resources/Icons/Icon-76.png has changed diff -r fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Resources/Icons/Icon-76@2x.png Binary file project_files/HedgewarsMobile/Resources/Icons/Icon-76@2x.png has changed diff -r fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Resources/Icons/bullet.png Binary file project_files/HedgewarsMobile/Resources/Icons/bullet.png has changed diff -r fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Resources/Icons/bullet@2x.png Binary file project_files/HedgewarsMobile/Resources/Icons/bullet@2x.png has changed diff -r fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Resources/Icons/bullet_filled.png Binary file project_files/HedgewarsMobile/Resources/Icons/bullet_filled.png has changed diff -r fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Resources/Icons/bullet_filled@2x.png Binary file project_files/HedgewarsMobile/Resources/Icons/bullet_filled@2x.png has changed diff -r fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Resources/Icons/flower.png Binary file project_files/HedgewarsMobile/Resources/Icons/flower.png has changed diff -r fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Resources/Icons/flower@2x.png Binary file project_files/HedgewarsMobile/Resources/Icons/flower@2x.png has changed diff -r fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Resources/Icons/flower_filled.png Binary file project_files/HedgewarsMobile/Resources/Icons/flower_filled.png has changed diff -r fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Resources/Icons/flower_filled@2x.png Binary file project_files/HedgewarsMobile/Resources/Icons/flower_filled@2x.png has changed diff -r fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Resources/Icons/heart.png Binary file project_files/HedgewarsMobile/Resources/Icons/heart.png has changed diff -r fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Resources/Icons/heart@2x.png Binary file project_files/HedgewarsMobile/Resources/Icons/heart@2x.png has changed diff -r fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Resources/Icons/heart_filled.png Binary file project_files/HedgewarsMobile/Resources/Icons/heart_filled.png has changed diff -r fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Resources/Icons/heart_filled@2x.png Binary file project_files/HedgewarsMobile/Resources/Icons/heart_filled@2x.png has changed diff -r fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Resources/Icons/target.png Binary file project_files/HedgewarsMobile/Resources/Icons/target.png has changed diff -r fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Resources/Icons/target@2x.png Binary file project_files/HedgewarsMobile/Resources/Icons/target@2x.png has changed diff -r fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Resources/Icons/target_filled.png Binary file project_files/HedgewarsMobile/Resources/Icons/target_filled.png has changed diff -r fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Resources/Icons/target_filled@2x.png Binary file project_files/HedgewarsMobile/Resources/Icons/target_filled@2x.png has changed diff -r fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Resources/Icons/teams.png Binary file project_files/HedgewarsMobile/Resources/Icons/teams.png has changed diff -r fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Resources/Icons/teams@2x.png Binary file project_files/HedgewarsMobile/Resources/Icons/teams@2x.png has changed diff -r fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Resources/Icons/teams_filled.png Binary file project_files/HedgewarsMobile/Resources/Icons/teams_filled.png has changed diff -r fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Resources/Icons/teams_filled@2x.png Binary file project_files/HedgewarsMobile/Resources/Icons/teams_filled@2x.png has changed diff -r fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Resources/basicFlags.plist --- a/project_files/HedgewarsMobile/Resources/basicFlags.plist Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Resources/basicFlags.plist Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/HedgewarsMobile/Resources/credits.plist --- a/project_files/HedgewarsMobile/Resources/credits.plist Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/HedgewarsMobile/Resources/credits.plist Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc project_files/hedgewars.pro --- a/project_files/hedgewars.pro Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/hedgewars.pro Mon Nov 16 22:57:24 2015 +0300 @@ -277,8 +277,8 @@ } !macx { - LIBS += -lSDL -lSDL_mixer -lSDL_net + LIBS += -lSDL2 -lSDL2_mixer -lSDL2_net !win32 { - INCLUDEPATH += /usr/local/include/SDL /usr/include/SDL + INCLUDEPATH += /usr/local/include/SDL2 /usr/include/SDL2 } } diff -r fcbdee9cdd74 -r b894922d58cc project_files/hwc/CMakeLists.txt --- a/project_files/hwc/CMakeLists.txt Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/hwc/CMakeLists.txt Mon Nov 16 22:57:24 2015 +0300 @@ -1,11 +1,11 @@ #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) +find_package(SDL2 REQUIRED) +find_package(SDL2_mixer REQUIRED) +find_package(SDL2_net REQUIRED) +find_package(SDL2_image REQUIRED) +find_package(SDL2_ttf REQUIRED) #compile our rtl implementation include_directories(${GLEW_INCLUDE_DIR}) @@ -13,7 +13,7 @@ include_directories(${PHYSFS_INCLUDE_DIR}) include_directories(${PHYSLAYER_INCLUDE_DIR}) include_directories(${LUA_INCLUDE_DIR}) -include_directories(${SDL_INCLUDE_DIR}) +include_directories(${SDL2_INCLUDE_DIR}) add_subdirectory(rtl) # convert list into pascal array @@ -40,6 +40,7 @@ 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) @@ -82,20 +83,16 @@ target_link_libraries(hwengine fpcrtl ${LUA_LIBRARY} ${OPENGL_LIBRARY} - ${SDL_LIBRARY} - ${SDLMIXER_LIBRARY} - ${SDLNET_LIBRARY} - ${SDLIMAGE_LIBRARY} - ${SDLTTF_LIBRARY} + ${SDL2_LIBRARY} + ${SDL2_MIXER_LIBRARY} + ${SDL2_NET_LIBRARY} + ${SDL2_IMAGE_LIBRARY} + ${SDL2_TTF_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 fcbdee9cdd74 -r b894922d58cc project_files/hwc/rtl/fpcrtl.h --- a/project_files/hwc/rtl/fpcrtl.h Tue Sep 08 19:20:58 2015 +0300 +++ b/project_files/hwc/rtl/fpcrtl.h Mon Nov 16 22:57:24 2015 +0300 @@ -14,9 +14,6 @@ #include "pmath.h" #ifndef EMSCRIPTEN -#if __APPLE__ -#define main SDL_main -#endif #include "GL/glew.h" #endif @@ -110,6 +107,7 @@ #define sdlh_Mix_VolumeMusic stub_Mix_VolumeMusic #endif +#define sdlh_SDL_free SDL_free #define sdlh_SDL_ConvertSurface SDL_ConvertSurface #define sdlh_SDL_CreateRGBSurface SDL_CreateRGBSurface #define sdlh_SDL_CreateThread SDL_CreateThread @@ -120,7 +118,7 @@ #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_GetKeyboardState SDL_GetKeyboardState #define sdlh_SDL_GetMouseState SDL_GetMouseState #define sdlh_SDL_GetRGBA SDL_GetRGBA #define sdlh_SDL_GetTicks SDL_GetTicks @@ -148,8 +146,8 @@ #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 +#define sdlh_SDL_LockMutex SDL_LockMutex +#define sdlh_SDL_UnlockMutex SDL_UnlockMutex #ifndef EMSCRIPTEN #define sdlh_SDL_ShowCursor SDL_ShowCursor #else diff -r fcbdee9cdd74 -r b894922d58cc share/hedgewars.appdata.xml --- a/share/hedgewars.appdata.xml Tue Sep 08 19:20:58 2015 +0300 +++ b/share/hedgewars.appdata.xml Mon Nov 16 22:57:24 2015 +0300 @@ -1,7 +1,9 @@ hedgewars.desktop - GFDL + 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. diff -r fcbdee9cdd74 -r b894922d58cc share/hedgewars/Data/CMakeLists.txt --- a/share/hedgewars/Data/CMakeLists.txt Tue Sep 08 19:20:58 2015 +0300 +++ b/share/hedgewars/Data/CMakeLists.txt Mon Nov 16 22:57:24 2015 +0300 @@ -1,4 +1,17 @@ -foreach(dir "Fonts" "Forts" "Graphics" "Locale" "Maps" "Music" "Sounds" "Themes" "Missions" "Names" "misc" "Scripts") +foreach(dir + Fonts + Forts + Graphics + Locale + Maps + Missions + Music + Names + Scripts + Sounds + Themes + misc + ) add_subdirectory(${dir}) endforeach(dir) diff -r fcbdee9cdd74 -r b894922d58cc share/hedgewars/Data/Graphics/Hedgehog/amAirMine.png Binary file share/hedgewars/Data/Graphics/Hedgehog/amAirMine.png has changed diff -r fcbdee9cdd74 -r b894922d58cc share/hedgewars/Data/Locale/de.lua --- a/share/hedgewars/Data/Locale/de.lua Tue Sep 08 19:20:58 2015 +0300 +++ b/share/hedgewars/Data/Locale/de.lua Mon Nov 16 22:57:24 2015 +0300 @@ -1,776 +1,101 @@ locale = { [""]="", -["Feeble Resistance"]="Kraftloser Widerstand", -["Pathetic Hog #%d"]="Erbärmlicher Igel #%d", -["Cybernetic Empire"]="Kybernetisches Imperium", -["Unit 3378"]="Einheit 3378", -["Codename: Teamwork"]="Code-Name: Teamwork", -["- Eliminate Unit 3378 |- Feeble Resistance must survive"]="- Vernichte Einheit 3378 |- Kraftloser Widerstand muss überleben", -["|- Mines Time:"]="|- Minenzündzeit:", -["sec"]="s", -["T_T"]="T_T", -["Hmmm..."]="Hmmm …", -["MISSION SUCCESSFUL"]="MISSION ERFOLGREICH", -["Congratulations!"]="Gratulation!", -["MISSION FAILED"]="MISSION GESCHEITERT", -["Oh no! Just try again!"]="Oh nein! Versuch's nochmal!", -["Grenadier"]="Grenadier", -["Grenade Group"]="Granatengruppe", -["You have thrown %d grenades."]="Du hast %d Granaten geworfen.", -["Sniperz"]="Heckenschützen", -["Hunter"]="Jäger", -["Sniper Training"]="Scharfschützen-Training", -["Aiming Practice"]="Zielübung", -["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.", -["Time's up!"]="Die Zeit ist um!", -["Oh no! Time's up! Just try again."]="Oh nein! Die Zeit ist um! Versuche es nochmal.", -["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!", -["Congratulations! You've eliminated all targets|within the allowed time frame."]="Gratulation! Du hast alle Ziele innerhalb der|verfügbaren Zeit ausgeschaltet.", -["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).", -["You lose!"]="Du verlierst!", -["points"]="Punkte", -["Shotgun Team"]="Schrotflinten-Team", -["Shotgun Training"]="Schrotflinten-Training", -["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!", +["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!", -["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.", -["You have gained an achievement: %s"]="Du hast eine Errungenschaft erhalten: %s", -["Prestigious Pilot"]="Prestigeträchtiger Pilot", -["CHALLENGE COMPLETE"]="HERAUSFORDERUNG ABGESCHLOSSEN", -["Grenadiers"]="Grenadiere", -["Nade Boy"]="Granatenjunge", -["Grenade Training"]="Granatentraining", -["Zook"]="Zook", -["Team Zook"]="Team Zook", -["You have launched %d bazookas."]="Du hast %d Bazookas abgefeuert.", -["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?", -["Bloody Rookies"]="Blutige Anfänger", -["Toxic Team"]="Giftige Gegner", -["Poison"]="Gift", -["Operation Diver"]="Taucher", -["Eliminate Poison before the time runs out"]="Neutralisiere das Gift, bevor die Zeit abgelaufen ist.", -["Private Novak"]="Gefreiter Novak", -["Cluster Bomb Training"]="Splittergranatentraining", -["You have to destroy 12 targets in 180 seconds"]="Du musst 12 Ziele in 180 Sekunden zerstören", -["Cluster Bomb MASTER!"]="Clusterbombenmeister!", -["Congratulations! You needed only half of time|to eliminate all targets."]="Gratulation! Du hast nur die Hälfte der Zeig benötigt,|um alle Ziele zu eliminieren.", -["Oh no! You failed! Just try again."]="Oh nein! Du hast versagt! Versuch es nochmal.", -["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!", -["Private Nolak"]="Gefreiter Nolak", -["The Hogies"]="Die Igelinge", -["You have thrown %d cluster bombs."]="Du hast %d Splitterbomben geworfen.", -["Hero Team"]="Heldenteam", -["Good Dude"]="Guter Junge", -["Bad Team"]="Böses Team", -["The Great Escape"]="Gesprengte Ketten", -["Get out of there!"]="Geh weg!", -["Elimate your captor."]="Eliminiere deinen", -["'Zooka Team"]="Die Knalltüten", -["Bazooka Training"]="Bazooka-Training", -["Aiming practice"]="Zielübung", -["hits"]="Treffer", -["You have destroyed %d of %d targets."]="Du hast %d von %d Zielen zerstört.", -["Your accuracy was %.1f%%."]="Deine Treffgenauigkeit betrug %.1f%%.", -["%.1f seconds were remaining."]="Es verblieben %.1f.", -["Pathetic Resistance"]="Erbärmlicher Widerstand", -["Unit"]="Einheit", -["Newton's Hammock"]="Newtons Hängematte", -["User Challenge"]="Benutzerherausforderung", -["Eliminate the enemy before the time runs out"]="Vernichte den Feind, bevor die Zeit abgelaufen ist", -["Lonely Hog"]="Einsamer Igel", -["Climber"]="Kletterer", -["Water Gods"]="Wassergötter", -["Nameless Heroes"]="Namenlose Helden", -["Drowner"]="Absäufer", -["Clowns"]="Clowns", -["Nobody Laugh"]="Niemand darf lachen", -["Spooky Tree"]="Spukiger Baum", -["Eliminate all enemies"]="Vernichte alle Gegner", -["Good birdy......"]="Braver Vogel …", -["You have launched %d homing bees."]="Du hast %d zielsuchende Bienen abgefeuert.", -["Unit 835"]="Einheit 835", -["Bamboo Thicket"]="Bambusdickicht", -["Energetic Engineer"]="Energetischer Ingenieur", -["Wannabe Shoppsta"]="Möchtegernkäufer", -["Unsuspecting Louts"]="Nichtsahnende Lümmel", -["Unlucky Sods"]="Arme Schweine", -["ROPE-KNOCKING"]="SEILSCHUBSEN", -["MISSION SUCCESS"]="MISSIONSERFOLG", -["COMPLETION TIME"]="ZEIT", -["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!", -["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 …", -["Good luck out there!"]="Viel Glück da draußen!", -["That Sinking Feeling"]="Land unter", -["Save as many hapless hogs as possible!"]="Rette so viele glücklose Igel wie möglich!", -["The Nameless One"]="Der Namenlose", -["Hapless Hogs"]="Glücklose Igel", -["Sinky"]="Blubb", -["Heavy"]="Schwierig", -["Clumsy"]="Hoppla", -["Silly"]="Doofi", -["Careless"]="Achtlos", -["Sponge"]="Schwamm", -["Deadweight"]="Gravitus", -["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 …", -["A frozen adventure"]="Ein frostiges Abenteuer", -["Getting ready"]="Bereitmachen", -["Collect the icegun and get the device part from Thanta"]="Sammle die Eiskanone ein und besorge das Bauteil von Thanta", -["Win"]="Sieg", -["Congratulations, you collected the device part!"]="Gratulation, du hast das Bauteil eingesammelt!", -["Hog Solo"]="Igel Einsam", -["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!", -["Hog Solo lost, try again!"]="Igel Einsam hat verloren, versuch es nochmal!", -["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", -["Checkpoint reached!"]="Kontrollpunkt erreicht!", -["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 …", -["Finally you are here..."]="Endlich bist du hier …", -["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 ", -["A Space Adventure"]="Ein Weltraumabenteuer", -["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!", -["Prepare to fight"]="Bereitmachen zum Kämpfen", -["Go down and save these PAotH hogs!"]="Geh runter und rette diese PAdI-Igel!", -["The fight begins!"]="Die Schlacht beginnt!", -["Neutralize your enemies and be careful!"]="Neutralisiere deine Gegner und sei vorsichtig!", -["Joe"]="Sepp", -["Bruce"]="Brutus", -["Helena"]="Helena", -["Boris"]="Boris", -["Prof. Hogevil"]="Prof. Bösigel", -["Minion"]="Lakai", -["PAotH"]="PAdI", -["Minions"]="Lakaien", -["Professor"]="Professor", -["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!", -["Congratulations, 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!", -["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.", -["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.", -["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!", -["Use the saucer and fly to the moon"]="Benutze die Untertasse und flieg zum Mond.", -["Travel carefully as your fuel is limited"]="Reise vorsichtig, da dein Treibstoff begrenzt ist.", -["An unexpected event!"]="Ein unerwartetes Ereignis!", -["Use the saucer and fly away"]="Benutze die Untertasse und flieg davon!", -["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.", -["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.", -["Saving Hogera"]="Hogera retten", -["Fly to the meteorite and detonate the explosives"]="Fliege zum Meteroiten und sprenge die Bomben.", -["H"]="H", -["Dr.Cornelius"]="Dr. Cornelius", -["Bob"]="Bert", -["Sam"]="Steffen", -["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!", -["Getting to the device"]="Zum Greifen nah", -["Exploring the tunnel"]="Höhlenforscher", -["Search for the device with the help of the other hedgehogs "]="Such nach dem Gerät mit der Hilfe der anderen Igel.", -["Hog Solo has to reach the last crates"]="Igel Einsam muss die letzten Kisten erreichen.", -["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.", -["Return to the Surface"]="Zurück an die Oberfläche", -["Go to the surface!"]="Geh an die Oberfläche!", -["Attack Captain Lime before he attacks back"]="Greif Leutnant Limone an, bevor er angreift.", -["Attack the assassins before they attack back"]="Greif die Assassinen an, bevor sie angreifen.", -["Captain Lime"]="Leutnant Limone", -["Mister Pear"]="Herr Birne", -["Lady Mango"]="Frau Mango", -["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.", -["Good luck!"]="Viel Glück!", -["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.", -["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.", -["Challenge Objectives"]="Herausforderungsziele", -["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 last encounter"]="Das letzte Gefecht", -["The final part"]="Das letzte Bauteil", -["Defeat Professor Hogevil!"]="Besiege Professor Bösigel!", -["thug"]="Rowdy", -["To win the game you have to eliminate all your enemies"]="Um das Spiel zu gewinnen, musst du all deine Gegner eliminieren", -["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!", -["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 …", -["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.", -["Get him Spike!"]="Hol ihn, Stachel!", -["This is seems like a wealthy hedgehog, nice..."]="Das sieht wie ein reicher Igel aus, nett.", -["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!", -["Precise shooting"]="Präzisionsschießen", -["Use your available weapons in order to eliminate the enemies"]="Benutze deine verfügbaren Waffen, um die Gegner zu eliminieren.", -["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 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 ", -["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.", -["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.", -["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", -["Killing the specialists"]="Die Spezialisten töten", -["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.", -["Mortar"]="Mörser", -["Desert Eagle"]="Desert Eagle", -["Grenade"]="Granate", -["Shoryuken"]="Shoryuken", -["Bazooka"]="Bazooka", -["5 deadly hogs"]="5 tödliche Igel", -["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.", -["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!", -["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.", -["Brainiac"]="Hirni", -["Corpsemonger"]="Leichenschänder", -["Femur Lover"]="Schenkellieber", -["Glark"]="Glark", -["Bonely"]="Knochi", -["Rot Molester"]="Rottiger Störenfried", -["Bloodrocutor"]="Blutfrierer", -["Muscle Dissolver"]="Muskellöser", -["Bloodsucker"]="Blutsauger", -["The Shadow Falls"]="Die Schattenfälle", -["The Showdown"]="Das Showdown", -["Save Leaks A Lot!|Hint: The Switch utility might be of help to you."]="Rette Undichte Stelle!|Tipp: Die Igelwahl könnte behilflich sein.", -["Play with me!"]="Spiel mit mir!", -["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.", -["Why do you not like me?"]="Warum magst du mich nicht?", -["Obliterate them!|Hint: You might want to take cover..."]="Vernichte sie!|Tipp: Du solltest in Deckung gehen.", -["The Dilemma"]="Das Dilemma", -["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 walk of Fame"]="Die Ruhmesmeile", -["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 Individualist"]="Der Individualist", -["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.", -["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 wonder where Dense Cloud is..."]="Ich frag mich, wo Dichte Wolke ist.", -["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.", -["Natives"]="Eingeborene", -["Ramon"]="Ramon", +["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", -["Dense Cloud"]="Dichte Wolke", -["Spiky Cheese"]="Stachliger Käse", -["Weaklings"]="Schwächlinge", -["Stronglings"]="Stärklinge", -["011101001"]="011101001", -["Y3K1337"]="Y3K1337", -["Under Construction"]="Baustelle", -["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].", -["A little gift from the cyborgs"]="Ein kleines Geschenk von den Cyborgs", -["The guardian"]="Der Wächter", -["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.", -["...and so the cyborgs took over the world..."]="Und so eroberten die Cyborgs die Welt …", -["The First Encounter"]="Das erste Zusammentreffen", -["Survive!|Hint: Cinematics can be skipped with the [Precise] key."]="Überlebe!|Tipp: Zwischensequenzen können mit der [Genaues Zielen]-Taste übersprungen werden.", -["Fiery Water"]="Feuerwasser", +["Fell From Grace"]="Fiel in Ungnade", ["Raging Buffalo"]="Wütender Büffel", ["Righteous Beard"]="Redlicher Bart", -["Fell From Grace"]="Fiel in Ungnade", -["Wise Oak"]="Weise Eiche", ["Eagle Eye"]="Adlerauge", ["Flaming Worm"]="Flammenwurm", +["Wise Oak"]="Weise Eiche", +["Bone Jackson"]="Knochen-Ede", ["Brain Teaser"]="Hirnreiz", -["Bone Jackson"]="Knochen-Ede", ["Gimme Bones"]="Gib Knochen", +["Bloodpie"]="Blutkuchen", ["Hedgibal Lecter"]="Iglibal Lector", -["Bloodpie"]="Blutkuchen", ["Scalp Muncher"]="Skalpknabberer", ["Back Breaker"]="Rückenbrecher", ["Dahmer"]="Dahmer", ["Meiwes"]="Meiwes", ["Ear Sniffer"]="Ohrenschnüffler", +["Muriel"]="Muriel", ["Regurgitator"]="Hochwürger", -["Muriel"]="Muriel", ["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.", @@ -844,25 +169,27 @@ ["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 ", -["! You bastards!"]="! Ihr Bastarde!", ["! Why?!"]="! Wieso?", ["That was just mean!"]="Das war einfach nur gemein!", ["Oh no, not "]="Oh nein, nicht ", +["? Why?"]="? Warum", ["Why "]="Warum, ", -["? Why?"]="? Warum", -["What has "]="Was hat dir ", [" 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", -["Defeat the cannibals"]="Besiege die Kannibalen", ["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?", @@ -873,107 +200,21 @@ ["Assault Team"]="Sturmtruppe", ["Reinforcements"]="Verstärkung", ["Unit 334a$7%;.*"]="Einheit 334a$7%;,*", -["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", -["Hightime"]="Hoch hinaus", -["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.", -["Omnivore"]="Allesfresser", -["Get on the head of the mole"]="Geh auf den Kopf des Maulwurfs", -["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.", -["The Rising"]="Der Aufstieg", -["Do the deed"]="Tu deine Pflicht", -["The Slaughter"]="Die Schlachtung", -["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.", -["The Crate Frenzy"]="Der Kistenrausch", -["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 Ultimate Weapon"]="Die Ultimative Waffe", -["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 First Blood"]="Der erste Zusammenstoß", -["Kill the cannibal!"]="Töte den Kannibalen!", -["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.", -["The wasted youth"]="Die vergeudete Jugend", -["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!", -["After Leaks A Lot betrayed his tribe, he joined the cannibals..."]="Nachdem Undichte Stelle seinen Stamm betrogen hatte, trat er den Kannibalen bei.", -["Step By Step"]="Schritt für Schritt", -["Hint: Double Jump - Press [Backspace] twice"]="Tipp: Doppelsprung – Drück [Rücktaste] 2 Mal", -["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.", -["The Torment"]="Die Pein", -["Select difficulty: [Left] - easier or [Right] - harder"]="Wähl einen Schwierigkeitsgrad: [Links] – leichter oder [Rechts] – schwerer", -["Fell From Heaven"]="Fiel Vom Himmel", -["Cannibals"]="Kannibalen", -["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.", +["Jack"]="Jochen", +["Steve"]="Steffen", ["Zork"]="Zork", -["Steve"]="Steffen", -["Jack"]="Jochen", +["Elmo"]="Elmo", ["Lee"]="Leo", -["Elmo"]="Elmo", ["Rachel"]="Ramona", +["Jeremiah"]="Jeremias", +["Segmentation Paul"]="Se Gmentf Ehler", ["Syntax Errol"]="Syntaxfehlel", -["Segmentation Paul"]="Se Gmentf Ehler", ["Unexpected Igor"]="Ausnahmefelix", -["Jeremiah"]="Jeremias", -["Yeah, take that!"]="Jawohl, nimm das!", ["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 ", -[" to save the village."]=" ab, um das Dorf zu retten.", ["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?!", @@ -1002,14 +243,15 @@ ["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", -["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.|", ["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 ", -[" turns until Sudden Death! Better hurry!"]=" Züge bis zum Sudden Death! Beeilung!", ["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.|", @@ -1017,152 +259,15 @@ ["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", -["Find your tribe!|Cross the lake!"]="Finde deinen Stamm!|Überquere den Fluss!", ["Turns until Sudden Death: "]="Züge bis zum Sudden Death: ", -["John"]="Jonas", -["Flesh for Brainz"]="Fleisch gegen Hirn", -["Eye Chewer"]="Augenkauer", -["Torn Muscle"]="Loser Muskel", -["Nom-Nom"]="Mjam-Mjam", -["Vedgies"]="Früchties", -["Brain Blower"]="Hirnpuster", -["Gorkij"]="Gorkidsch", -["The Journey Back"]="Die Rückreise", -["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!", -["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", -["The Savior"]="Der Erlöser", -["Get Dense Cloud out of the pit!"]="Hol Dichte Wolke aus der Grube!", -["They never learn"]="Sie lernen es nie.", -["Free Dense Cloud and continue the mission!"]="Befrei Dichte Wolke und setze die Mission fort!", -["I just wonder where Ramon and Spiky disappeared..."]="Ich frage mich lediglich, wohin Ramon und Stachli verschwunden sind.", -["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.", -["The Tunnel Maker"]="Der Tunnelbauer", -["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 Moonwalk"]="Der Mondspaziergang", -["Hint: Select the LowGravity and press [Fire]."]="Tipp: Wähle die niedrige Schwerkraft und drücke [Feuern].", -["Slippery"]="Rutschig", -["You'd better watch your steps..."]="Pass besser auf, wohin du trittst.", -["Artur Detour"]="Artus Rück", -["Led Heart"]="Geführtes Herz", -["Orlando Boom!"]="Orlando Bumm!", -["Nilarian"]="Nilarian", -["Steel Eye"]="Stahlauge", -["Rusty Joe"]="Rostjonas", -["Hatless Jerry"]="Hutloser Igor", -["Gas Gargler"]="Gasgurgler", -["Leaderbot"]="Führboter", -["Nancy Screw"]="Lockere Schraube", -["Beep Loopers"]="Piepskreisler", -["Corporationals"]="Kapitalista", -["Name"]="Name", -["Olive"]="Olive", -["Brain Stu"]="Hirntopf", -["Brainila"]="Hirnilia", -["Salivaslurper"]="Speichelschlürfer", -["Spleenlover"]="Milzlieber", -["Thighlicker"]="Schenkelschlecker", -["NomNom"]="Mjamjam", -["Mindy"]="Intellekta", -["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.", -["United We Stand"]="Gemeinsam sind wir stark", -["Invasion"]="Invasion", -["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", -["Corpse Thrower"]="Leichenschmeißer", +["Ramon"]="Ramon", +["Spiky Cheese"]="Stachliger Käse", +["Honest Lee"]="Leo Ehrlich", +["Sirius Lee"]="Leo Ernst", +["Vegan Jack"]="Veganer-Jochen", ["Brutal Lily"]="Brutalo-Lilie", -["Hannibal"]="Hannibal", -["More Natives"]="Mehr Ureinwohner", -["Traitors"]="Verräter", -["Honest Lee"]="Leo Ehrlich", -["Vegan Jack"]="Veganer-Jochen", -["Sirius Lee"]="Leo Ernst", ["Smith 0.97"]="Smith 0.97", ["Smith 0.98"]="Smith 0.98", ["Smith 0.99a"]="Smith 0.99a", @@ -1227,18 +332,26 @@ ["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", -["Defeat the cyborgs!"]="Besiege die Cyborgs!", ["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", -["Hogminator"]="Iglinator", -["Carol"]="Karol", ["Blender"]="Blender", ["Elderbot"]="Altbot", ["Those aliens are destroying the island!"]="Diese Außerirdischen zerstören die Insel!", @@ -1267,110 +380,1074 @@ ["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", -["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.", ["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", -["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.", -["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?", -["%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.", -["%s wins!"]="%s gewinnt!", -["Team’s best heights per round"]="Die Besthöhen der Teams pro Runde", -["This round’s award for ulitmate 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.", -["Hedgewars-Basketball"]="Hedgewars-Basketball", -["Not So Friendly Match"]="Kein-so-Freundschaftsspiel", -["Bat your opponents through the|baskets and out of the map!"]="Schlage deine Widersacher durch|die Körbe und aus der Karte hinaus!", -["%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:", -["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: ", -["Control pillars to score points."]="Behalte die Kontrolle über die Säulen, um Punkte zu erhalten.", -["Goal"]="Ziel", -["Team Scores"]="Teampunktestand", -["GAME OVER!"]="SPIEL ZU ENDE!", -["Victory for the "]="Sieg für ", -["Hooray!"]="Hurra!", -["Flag respawned!"]="Fahne wieder erschienen!", -["You have SCORED!!"]="Du hast GEPUNKTET!", -["Opposing Team: "]="Gegnerisches Team: ", -["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!"]="Fahne erobert!", -["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", -["Hedgewars-Knockball"]="Hedgewars-Schlagball", -["Bat balls at your enemies and|push them into the sea!"]="Schlage Bälle auf deine Widersacher|und lass sie ins Meer fallen!", -["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).", -["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", -["Jumping is disabled"]="Sprünge sind deaktiviert!", +["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", -["weaponschemes"]="Waffenschemata", -["Unique new weapons"]="Einzigartige neue Waffen", ["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.", -["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 \"", +["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", -["key."]="Taste.", -["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.", +["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)", @@ -1385,39 +1462,33 @@ ["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)", -["North America"]="Nordamerika", +["- 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", -["Area"]="Gebiet", +["North America"]="Nordamerika", ["Population"]="Einwohnerzahl", -["- 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).", ["Special Weapons:"]="Sonderwaffen:", -["Shotgun"]="Schrotflinte", -["Sniper Rifle"]="Scharfschützengewehr", +["GasBomb"]="Gasbombe", +["MEDIUM"]="MITTEL", ["South America"]="Südamerika", -["MEDIUM"]="MITTEL", -["GasBomb"]="Gasbombe", ["Europe"]="Europa", ["Molotov"]="Molotowcocktail", ["Africa"]="Afrika", -["Seduction"]="Verführung", -["Sticky Mine"]="Haftmine", +["- Will give you a parachute every second turn."]="- Wird dir jeden 2. Zug einen Fallschirm geben", ["Asia"]="Asien", -["- Will give you a parachute every second turn."]="- Wird dir jeden 2. Zug einen Fallschirm geben", -["Parachute"]="Fallschirm", ["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", -["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", +["Duration"]="Dauer", ["Kerguelen"]="Kerguelen", -["Hammer"]="Hammer", -["Duration"]="Dauer", +["- 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", -["- Will Get 1-3 random weapons"]="- wird 1–3 zufällige Waffen erhalten", -["- Massive weapon bonus on first turn"]="- Großer Waffenbonus am ersten Zug", +["- 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", -["- 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)!", ["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", @@ -1427,28 +1498,15 @@ ["You are sabotaged, RUN!"]="Du wurdest sabotiert, LAUF!", ["WARNING: Sabotage detected!"]="WARNUNG: Sabotage erkannt!", ["Hogs in sight!"]="Igel in Sicht!", -["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: ", -["a Hedgewars mini-game"]="ein Hedgewars Mini-Spiel", -["Build a track and race."]="Konstruiere eine Strecke und mach ein Wettrennen.", -["Round Limit:"]="Rundenbegrenzung:", -["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.", -["GAME BEGUN!!!"]="SPIEL GESTARTET!!!", -["Complete the track as fast as you can!"]="Durchlaufe die Strecke so schnell du kannst!", -["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!", +["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", @@ -1456,19 +1514,151 @@ ["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", -["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", -["Mine"]="Mine", -["Teleport"]="Teleporter", -["Blowtorch"]="Schweißbrenner", -["Flying Saucer"]="Fliegende Untertasse", -["Low Gravity"]="Niedrige Schwerkraft", -["FRENZY"]="WAHNSINN", -["a frenetic Hedgewars mini-game"]="ein hektisches Hedgewars-Minispiel", +["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.", @@ -1497,6 +1687,32 @@ ["-------"]="-------", [" 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", @@ -1509,8 +1725,8 @@ ["Ammo Depleted!"]="Munition erschöpft!", ["Mine Deployer"]="Minenleger", ["Shield Depleted"]="Schild aufgebraucht!", +["Power Remaining"]="Verbleibende Energie", ["Shield ON:"]="Schild AN:", -["Power Remaining"]="Verbleibende Energie", ["Shield OFF:"]="Schild AUS:", ["Pings left:"]="Verbleibende Pings:", ["Destroy invaders to score points."]="Zerstöre die Angreifer um Punkte zu erhalten.", @@ -1546,35 +1762,13 @@ ["Kamikaze Expert!"]="Kamikazeexperte!", ["Depleted Kamikaze!"]="Munitionsloses Kamikaze!", ["Timed Kamikaze!"]="Pünktliches Kamikaze!", -["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", -["Waypoint placed."]="Wegpunkt gesetzt", -["Available points remaining: "]="Verfügbare Punkte verbleibend:", -["NOT ENOUGH WAYPOINTS"]="NICHT GENUG WEGPUNKTE", -["Place more waypoints using the 'Air Attack' weapon."]="Platziere mehr Wegpunkte durch Verwenden der »Luftangriff«-Waffe", +["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", -["Game Started!"]="Spiel gestartet!", -["CAPTURE THE FLAG"]="EROBERE DIE FAHNE", -["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)", ["ammo extended!"]="Munition aufgestockt!", ["Barrel Eater!"]="Fassfresser!", ["Mine Eater!"]="Minenfresser!", @@ -1592,84 +1786,39 @@ ["Killing spree!"]="Blutrausch!", ["Unstoppable!"]="Unaufhaltsam!", ["Friendly Fire!"]="Eigenbeschuss!", -["Each turn you get one random weapon"]="Du bekommst jede Runde eine zufällig gewählte Waffe.", -["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", -["Flamethrower"]="Flammenwerfer", -["Freezer"]="Eiskanone", -["Land Sprayer"]="Landkanone", -["Whip"]="Peitsche", -["Baseball Bat"]="Baseballschläger", -["Dynamite"]="Dynamit", -["Cake"]="Kuchen", -["Ballgun"]="Ballkanone", -["Cleaver"]="Hackebeil", -["Birdy"]="Birdy", -["Pickhammer"]="Presslufthammer", -["Personal Portal Device"]="Portalgerät", -["Rope"]="Seil", -["Invulnerable"]="Unverwundbar", -["Laser Sight"]="Laservisier", -["Vampirism"]="Vampirismus", -["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", -["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.", -["Teleporation Node"]="Teleporterstation", -["Allows free teleportation between other nodes."]="Ermöglicht kostenlose Teleportationen zwischen anderen Stationen.", -["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", -["Achievement obtained: Lively Lifeguard"]="Errungenschaft erhalten: Lebhafter Lebensretter", -["Challenge completed!"]="Herausforderung bewältigt!", -["Challenge"]="Herausforderung", -["%d Hapless Hogs left"]="%d Glücklose Igel verbleibend", -["Disqualified!"]="Disqualifiziert!", -["You haven't rescued anyone."]="Du hast niemanden gerettet.", -["You have obtained an achievement: Lively Lifeguard"]="Du hast eine Errungenschaft erhalten: Lebhafter Lebensretter", -["You must survive the flood in order to score."]="Du musst das Hochwasser überleben um zu punkten.", -["Your hedgehog died!"]="Dein Igel ist gestorben!", -["You saved %d of 8 Hapless Hogs."]="Du hast %d von 8 Glücklosen Igeln gerettet." +["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 fcbdee9cdd74 -r b894922d58cc share/hedgewars/Data/Locale/de.txt --- a/share/hedgewars/Data/Locale/de.txt Tue Sep 08 19:20:58 2015 +0300 +++ b/share/hedgewars/Data/Locale/de.txt Mon Nov 16 22:57:24 2015 +0300 @@ -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 @@ -41,7 +41,7 @@ 00:38=Scharfschützengewehr 00:39=Fliegende Untertasse 00:40=Molotowcocktail -00:41=Birdy +00:41=Vogli 00:42=Tragbares Portalgerät 00:43=Piano-Angriff 00:44=Alter Limburger @@ -538,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 @@ -568,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 @@ -587,66 +587,68 @@ 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|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 +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=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|Weitsprung: 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: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 -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. Es wird beim Aufschlag|mehrere kleine Bomben freisetzen.|Angriff: Mit voller Kraft feuern +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: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: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|Weitsprung: »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 …|Angriff: Aktivieren -04:34=Can’t touch me!|Angriff: 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.|Angriff: 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|Weitsprung: 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 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!|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: 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|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!|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.|Haftungsausschluss: Nicht funktionstüchtig, wenn in Sudden Death,|wenn du alleine bist – oder der König. -04:54=Versprühe einen Strahl klebriger Flocken.|Baue Brücken, begrabe Gegner, versiegle Tunnel.|Pass auf, dass du selbst nichts abbekommst! -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: Schießen +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 @@ -654,18 +656,18 @@ 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=Lebenspunkte aller Igel werden 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 diff -r fcbdee9cdd74 -r b894922d58cc share/hedgewars/Data/Locale/en.txt --- a/share/hedgewars/Data/Locale/en.txt Tue Sep 08 19:20:58 2015 +0300 +++ b/share/hedgewars/Data/Locale/en.txt Mon Nov 16 22:57:24 2015 +0300 @@ -86,6 +86,7 @@ 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 @@ -103,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 diff -r fcbdee9cdd74 -r b894922d58cc share/hedgewars/Data/Locale/missions_it.txt --- a/share/hedgewars/Data/Locale/missions_it.txt Tue Sep 08 19:20:58 2015 +0300 +++ b/share/hedgewars/Data/Locale/missions_it.txt Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc share/hedgewars/Data/Locale/missions_ru.txt --- a/share/hedgewars/Data/Locale/missions_ru.txt Tue Sep 08 19:20:58 2015 +0300 +++ b/share/hedgewars/Data/Locale/missions_ru.txt Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc share/hedgewars/Data/Locale/ru.lua --- a/share/hedgewars/Data/Locale/ru.lua Tue Sep 08 19:20:58 2015 +0300 +++ b/share/hedgewars/Data/Locale/ru.lua Mon Nov 16 22:57:24 2015 +0300 @@ -4,15 +4,18 @@ -- ["..."] = "", -- ["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 + ["+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 @@ -24,22 +27,23 @@ -- ["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 + ["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"] = "", -- Mutant + ["a Hedgewars tag game"] = "Ролевая игра в Hedgewars", -- Mutant -- ["AHHh, home sweet home. Made it in %d seconds."] = "", -- ClimbHome ["Aiming Practice"] = "Упражнение на точность", --Bazooka, Shotgun, SniperRifle --- ["Air Attack"] = "", -- Construction_Mode + ["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 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 + ["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!"] = "", @@ -62,51 +66,58 @@ -- ["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 --- ["Ballgun"] = "", -- Construction_Mode --- ["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 + ["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"] = "Упражнение с базукой", + ["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 + ["Bio-Filter"] = "Био-Фильтр", -- Construction_Mode -- ["Biomechanic Team"] = "", -- A_Classic_Fairytale:family --- ["Birdy"] = "", -- Construction_Mode + ["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 + ["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 @@ -114,8 +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 fortress and destroy your enemy."] = "", -- Construction_Mode --- ["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 @@ -125,64 +136,78 @@ -- ["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 +-- ["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 --- ["Cleaver"] = "", -- Construction_Mode + ["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"] = "", + ["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 + ["CONSTRUCTION MODE"] = "РЕЖИМ СТРОИТЕЛЬСТВА", -- Construction_Mode + ["Construction Station"] = "Станция Утилит", -- Construction_Mode -- ["Continental supplies"] = "", -- Continental_supplies --- ["Control pillars to score points."] = "", --- ["Core"] = "", -- Construction_Mode + ["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 --- ["Cost"] = "", -- Construction_Mode --- ["Crate Placement Tool"] = "", -- Construction_Mode - ["Crates Left:"] = "Осталось ящиков:", -- User_Mission_-_RCPlane_Challenge + ["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"] = "", + ["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 @@ -190,37 +215,43 @@ -- ["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!"] = "", + ["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!"] = "", --- ["Desert Eagle"] = "", -- Construction_Mode, A_Space_Adventure:death02 + ["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 + ["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"] = "", + ["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 @@ -231,27 +262,31 @@ -- ["Duration"] = "", -- Continental_supplies -- ["Dust storm: [Deals 15 damage to all enemies in the circle]"] = "", -- Continental_supplies --- ["Dynamite"] = "", -- Construction_Mode + ["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"] = "", + ["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 -- ["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 @@ -260,119 +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 --- ["Extra Damage"] = "", -- Construction_Mode --- ["Extra Time"] = "", -- Construction_Mode + ["Experienced beginner"] = "Продвинутый новичок", -- User_Mission_-_RCPlane_Challenge + ["Extra Damage"] = "Дополнительный урон", -- Construction_Mode + ["Extra Time"] = "Дополнительное время", -- Construction_Mode -- ["Eye Chewer"] = "", -- A_Classic_Fairytale:journey -- ["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 + ["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"] = "", -- ["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 + ["Flamethrower"] = "Огнемет", -- Construction_Mode -- ["Flaming Worm"] = "", -- A_Classic_Fairytale:backstab + ["Flawless victory!"] = "Безупречная победа!", -- User_Mission_-_RCPlane_Challenge -- ["Flesh for Brainz"] = "", -- A_Classic_Fairytale:journey --- ["Flying Saucer"] = "", -- Construction_Mode, Frenzy + ["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 + ["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 + ["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 + ["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 + ["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 + ["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 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!"] = "", --- ["Hammer"] = "", -- Construction_Mode, Continental_supplies + ["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 + ["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"] = "", + ["Hedgewars-Basketball"] = "Hedgewars Баскетбол", + ["Hedgewars-Knockball"] = "Hedgewars Вышибалы", -- ["Hedgibal Lecter"] = "", -- A_Classic_Fairytale:backstab --- ["Heh, it's not that bad."] = "", --- ["Hellish Handgrenade"] = "", -- Construction_Mode + ["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 @@ -382,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 @@ -396,17 +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 --- ["Homing Bee"] = "", -- Construction_Mode + ["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 @@ -415,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 @@ -426,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 @@ -438,6 +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 @@ -447,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 @@ -469,20 +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 + ["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 + ["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 @@ -495,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 @@ -521,7 +577,7 @@ -- ["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 @@ -529,8 +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 --- ["Land Sprayer"] = "", -- Construction_Mode --- ["Laser Sight"] = "", -- Construction_Mode + ["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 @@ -542,6 +599,7 @@ -- ["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 @@ -551,8 +609,8 @@ -- ["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!!"] = "", + ["Limburger"] = "Старый Лимбургер", -- Construction_Mode + ["Listen up, maggot!!"] = "Слушай сюда, щегол!!", -- ["Little did they know that this hunt will mark them forever..."] = "", -- A_Classic_Fairytale:shadow -- ["Lively Lifeguard"] = "", @@ -562,56 +620,63 @@ -- ["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 + ["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"] = "Мина", -- 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 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 --- ["Molotov Cocktail"] = "", -- Construction_Mode + ["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 + ["Mortar"] = "Миномёт", -- Construction_Mode, A_Space_Adventure:death02 -- ["Movement: [Up], [Down], [Left], [Right]"] = "", --- ["Mudball"] = "", -- Construction_Mode + ["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 + ["-------"] = "-------", -- 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 + ["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 --- ["Nobody Laugh"] = "", -- User_Mission_-_Nobody_Laugh + ["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 @@ -619,137 +684,155 @@ -- ["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 + ["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 + ["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 --- ["Other kills don't give you points."] = "", -- Mutant --- ["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"] = "", --- ["Personal Portal Device"] = "", -- Construction_Mode + ["Per-Hog Ammo"] = "У каждого ежа свое оружие", + ["Personal Portal Device"] = "Портальная Пушка", -- Construction_Mode -- ["Per team weapons"] = "", -- Continental_supplies -- ["Pfew! That was close!"] = "", -- A_Classic_Fairytale:shadow --- ["Piano Strike"] = "", -- Construction_Mode --- ["Pickhammer"] = "", -- Construction_Mode + ["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 + ["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"] = "", -- Mutant + ["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"] = "", + ["Predator"] = "Хищник", -- portal + ["Prepare yourself"] = "Готовься", -- ["presice"] = "", -- Continental_supplies --- ["Press [Enter] to accept this configuration."] = "", -- WxW + ["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"] = "", --- ["Prestigious Pilot"] = "", -- User_Mission_-_RCPlane_Challenge --- ["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 + ["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 + ["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 + ["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 -- ["REMOVED"] = "", -- Continental_supplies --- ["Respawner"] = "", -- Construction_Mode + ["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"] = "", + ["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"] = "", -- Construction_Mode --- ["ROPE-KNOCKING"] = "", -- User_Mission_-_Rope_Knock_Challenge + ["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 + ["Rope Training"] = "Тренировка с Верёвкой", -- Basic_Training_-_Rope -- ["Rot Molester"] = "", -- A_Classic_Fairytale:shadow --- ["Round Limit:"] = "", + ["Round Limit:"] = "Лимит Раундов:", -- ["Round Limit"] = "", --- ["Rounds Complete: "] = "", + ["Rounds Complete: "] = "Раундов Завершено: ", -- ["Rounds Complete"] = "", -- ["Rubber Band"] = "", -- Construction_Mode --- ["Rubber Placement Mode"] = "", -- Construction_Mode --- ["RULES"] = "", -- Frenzy, Mutant --- ["RULES OF THE GAME [Press ESC to view]"] = "", + ["Rubber Placement Mode"] = "Режим Размещения Батутов", -- Construction_Mode + ["RULES"] = "ПРАВИЛА", -- Frenzy, Mutant + ["RULES OF THE GAME [Press ESC to view]"] = "ПРАВИЛА ИГРЫ", -- ["Rusty Joe"] = "", -- A_Classic_Fairytale:queen -- ["s|"] = "", -- ["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 + ["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!"] = "Увидимся!", @@ -771,17 +854,19 @@ -- ["Shield OFF:"] = "", -- ["Shield ON:"] = "", -- ["Shield Seeker!"] = "", --- ["Shoryuken"] = "", -- Construction_Mode, Frenzy, A_Space_Adventure:death02 --- ["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"] = "", --- ["SineGun"] = "", -- Construction_Mode --- ["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 @@ -792,42 +877,46 @@ -- ["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"] = "", + ["Sponge"] = "Губка", + ["Spooky Tree"] = "Зловещее дерево", -- ["Sprite Placement Mode"] = "", -- Construction_Mode -- ["Sprite Testing Mode"] = "", -- Construction_Mode --- ["STATUS UPDATE"] = "", -- GaudyRacer, Space_Invasion + ["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 + ["Sticky Mine"] = "Мина-Липучка", -- Continental_supplies + ["Sticky Mine Placement Mode"] = "Режим Размещения Мин-Липучек", -- Construction_Mode -- ["Stronglings"] = "", -- A_Classic_Fairytale:shadow --- ["Structure Placement Mode"] = "", -- Construction_Mode --- ["Structure Placement Tool"] = "", -- Construction_Mode + ["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 + ["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 "] = "", + ["Switched to "] = "Выбран ", -- ["Switch Hog"] = "", -- Construction_Mode -- ["Syntax Errol"] = "", -- A_Classic_Fairytale:dragon -- ["tab"] = "", -- Continental_supplies @@ -835,14 +924,22 @@ -- ["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 --- ["Teleporation Node"] = "", -- Construction_Mode --- ["Teleportation Mode"] = "", -- Construction_Mode --- ["Teleportation Node"] = "", -- Construction_Mode + ["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 + ["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 @@ -852,43 +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 Bottom Feeder can score points by killing anyone."] = "", -- Mutant + ["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 first player to kill someone becomes the Mutant."] = "", -- Mutant --- ["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 Hog in the sky sees your sadness and grants you a boon."] = "", -- Construction_Mode + ["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 + ["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 + ["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 @@ -900,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 @@ -927,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"] = "", + ["Toxic Team"] = "Токсичные", -- User_Mission_-_Diver, User_Mission_-_Spooky_Tree, User_Mission_-_Teamwork + ["TRACK COMPLETED"] = "ТРЕК ЗАВЕРШЕН", --- ["training"] = "", -- portal + ["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!"] = "", @@ -958,53 +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 -- ["Unique new weapons"] = "", -- Continental_supplies --- ["Unit"] = "", + ["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"] = "", --- ["Use the air-attack weapons and the arrow keys to select structures."] = "", -- Construction_Mode + ["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 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 get from start to finish as fast as you can!"] = "", --- ["Utility Crate Placement Mode"] = "", -- Construction_Mode --- ["Vampirism"] = "", -- Construction_Mode + ["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 --- ["Watermelon Bomb"] = "", -- Construction_Mode --- ["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 --- ["Weapon Crate Placement Mode"] = "", -- Construction_Mode --- ["Weapon Filter"] = "", -- Construction_Mode + ["Weapon Crate Placement Mode"] = "Режим Размещения Ящиков с Оружием", -- Construction_Mode + ["Weapon Filter"] = "Фильтр Оружия", -- Construction_Mode -- ["weaponschemes"] = "", -- Continental_supplies --- ["Weapons Reset"] = "", --- ["Weapons reset."] = "", -- Highlander + ["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 @@ -1014,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 @@ -1037,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 @@ -1055,7 +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 + ["Whip"] = "Кнут", -- Construction_Mode -- ["? Why?"] = "", -- A_Classic_Fairytale:backstab -- ["Why "] = "", -- A_Classic_Fairytale:backstab -- ["! Why?!"] = "", -- A_Classic_Fairytale:backstab, A_Classic_Fairytale:united @@ -1067,14 +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 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: "] = "", + ["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 @@ -1095,26 +1205,48 @@ -- ["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 @@ -1122,33 +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 may only spawn 5 crates per turn."] = "", -- Construction_Mode --- ["You may only use 1 Extra Time per turn."] = "", -- Construction_Mode + ["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 fcbdee9cdd74 -r b894922d58cc share/hedgewars/Data/Locale/ru.txt --- a/share/hedgewars/Data/Locale/ru.txt Tue Sep 08 19:20:58 2015 +0300 +++ b/share/hedgewars/Data/Locale/ru.txt Mon Nov 16 22:57:24 2015 +0300 @@ -42,7 +42,7 @@ 00:39=Летающая тарелка 00:40=Коктейль Молотова 00:41=Птичка -00:42=Портативный телепорт +00:42=Портальная Пушка 00:43=Фортепьяновый удар 00:44=Старый Лимбургер 00:45=Синус-пушка (бета) @@ -59,6 +59,7 @@ 00:55=Замораживатель 00:56=Секач 00:57=Батут +00:58=Воздушная мина 01:00=Вперёд к победе! 01:01=Ничья @@ -83,6 +84,9 @@ 01:20=%1 отскок 01:21=Звук отключен 01:22=Режим отсутствия +01:23=Авто Камера Выкл. +01:24=Авто Камера Вкл. +01:25=Нажмите кнопку мишени для указания цели ; Event messages ; Hog (%1) died @@ -454,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: Установить таймер гранаты|Атака: Удерживай для более дальнего броска @@ -506,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 fcbdee9cdd74 -r b894922d58cc share/hedgewars/Data/Locale/stub.lua --- a/share/hedgewars/Data/Locale/stub.lua Tue Sep 08 19:20:58 2015 +0300 +++ b/share/hedgewars/Data/Locale/stub.lua Mon Nov 16 22:57:24 2015 +0300 @@ -10,8 +10,11 @@ -- ["+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 @@ -30,6 +33,7 @@ -- ["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 @@ -71,13 +75,16 @@ -- ["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 -- ["Ballgun"] = "", -- Construction_Mode --- ["Bamboo Thicket"] = "", +-- ["Bamboo Thicket"] = "", -- User_Mission_-_Bamboo_Thicket -- ["Barrel Eater!"] = "", -- ["Barrel Launcher"] = "", -- ["Barrel Placement Mode"] = "", -- Construction_Mode @@ -88,6 +95,8 @@ -- ["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 @@ -101,12 +110,14 @@ -- ["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 @@ -125,6 +136,8 @@ -- ["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 @@ -133,9 +146,13 @@ -- ["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 @@ -160,29 +177,36 @@ -- ["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 -- ["Cost"] = "", -- Construction_Mode -- ["Crate Placement Tool"] = "", -- Construction_Mode --- ["Crates Left:"] = "", -- User_Mission_-_RCPlane_Challenge +-- ["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"] = "", +-- ["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 @@ -191,20 +215,25 @@ -- ["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 @@ -220,7 +249,8 @@ -- ["Drone Hunter!"] = "", -- ["Drop a bomb: [Drop some heroic wind that will turn into a bomb on impact]"] = "", -- Continental_supplies --- ["Drowner"] = "", +-- ["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 @@ -239,6 +269,7 @@ -- ["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"] = "", @@ -250,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 @@ -260,6 +294,7 @@ -- ["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 @@ -288,10 +323,12 @@ -- ["Flamer"] = "", -- ["Flamethrower"] = "", -- Construction_Mode -- ["Flaming Worm"] = "", -- A_Classic_Fairytale:backstab +-- ["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 @@ -338,14 +375,18 @@ -- ["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 +-- ["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 @@ -355,7 +396,8 @@ -- ["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 @@ -363,6 +405,7 @@ -- ["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 @@ -372,6 +415,7 @@ -- ["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 @@ -389,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 @@ -396,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 @@ -406,7 +452,9 @@ -- ["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 @@ -438,6 +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 @@ -447,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 @@ -471,18 +521,23 @@ -- ["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 @@ -529,6 +584,7 @@ -- ["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!"] = "", @@ -542,6 +598,7 @@ -- ["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 @@ -562,7 +619,9 @@ -- ["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 @@ -571,6 +630,7 @@ -- ["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"] = "", @@ -579,8 +639,10 @@ -- ["|- 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 @@ -592,6 +654,7 @@ -- ["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 @@ -611,6 +674,7 @@ -- ["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 @@ -649,6 +713,7 @@ -- ["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 @@ -669,14 +734,15 @@ -- ["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:"] = "", -- 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 @@ -688,21 +754,28 @@ -- ["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 @@ -713,14 +786,21 @@ -- ["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 @@ -736,6 +816,7 @@ -- ["s|"] = "", -- ["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 @@ -749,6 +830,7 @@ -- ["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 +-- ["%.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 @@ -771,6 +853,8 @@ -- ["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"] = "", @@ -792,16 +876,19 @@ -- ["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"] = "", @@ -818,6 +905,7 @@ -- ["Structure Placement Mode"] = "", -- Construction_Mode -- ["Structure Placement Tool"] = "", -- Construction_Mode +-- ["Subject"] = "", -- portal -- ["Sundaland"] = "", -- Continental_supplies -- ["Super Weapons"] = "", -- WxW -- ["Support Station"] = "", -- Construction_Mode @@ -835,9 +923,17 @@ -- ["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 --- ["Teleporation Node"] = "", -- Construction_Mode +-- ["Team Zook"] = "", -- Target_Practice_-_Bazooka_easy, Target_Practice_-_Bazooka_hard -- ["Teleportation Mode"] = "", -- Construction_Mode -- ["Teleportation Node"] = "", -- Construction_Mode -- ["Teleport"] = "", -- Construction_Mode, Frenzy @@ -863,6 +959,7 @@ -- ["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!"] = "", @@ -871,11 +968,13 @@ -- ["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 @@ -929,15 +1028,18 @@ -- ["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 @@ -945,7 +1047,9 @@ -- ["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"] = "", @@ -962,25 +1066,28 @@ -- ["Under Construction"] = "", -- A_Classic_Fairytale:shadow -- ["Unexpected Igor"] = "", -- A_Classic_Fairytale:dragon -- ["Unique new weapons"] = "", -- Continental_supplies --- ["Unit"] = "", +-- ["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 @@ -988,6 +1095,7 @@ -- ["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 @@ -1067,6 +1175,7 @@ -- ["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 give you an airstrike every fifth turn."] = "", -- Continental_supplies -- ["- Will give you a parachute every second turn."] = "", -- Continental_supplies @@ -1100,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 @@ -1122,13 +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 @@ -1138,9 +1273,12 @@ -- ["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: "] = "", @@ -1149,6 +1287,8 @@ -- ["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 fcbdee9cdd74 -r b894922d58cc share/hedgewars/Data/Locale/tips_de.xml --- a/share/hedgewars/Data/Locale/tips_de.xml Tue Sep 08 19:20:58 2015 +0300 +++ b/share/hedgewars/Data/Locale/tips_de.xml Mon Nov 16 22:57:24 2015 +0300 @@ -6,15 +6,15 @@ 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 oder ein 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/. + 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. + 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. @@ -30,7 +30,7 @@ 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 [Genau zielen], um dich nach [links] oder [rechts], ohne dich tatsächlich zu bewegen, umzudrehen. + 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. @@ -48,6 +48,24 @@ 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. diff -r fcbdee9cdd74 -r b894922d58cc share/hedgewars/Data/Locale/tips_en.xml --- a/share/hedgewars/Data/Locale/tips_en.xml Tue Sep 08 19:20:58 2015 +0300 +++ b/share/hedgewars/Data/Locale/tips_en.xml Mon Nov 16 22:57:24 2015 +0300 @@ -8,10 +8,10 @@ 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—theyll offer different gameplay depending on the one you picked. + 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. 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. @@ -19,21 +19,20 @@ 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. + 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! - Especially while playing online be polite and always remember there might be some minors playing with or against you as well! + 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! - You should never install Hedgewars on computers you don’t own (school, university, work, etc.). Please ask the responsible person instead! + 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 Limbuger only causes a small explosion. However the wind affected smelly cloud can poison lots of hogs at once. + 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. @@ -48,7 +47,7 @@ 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 to much abuse! + 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. diff -r fcbdee9cdd74 -r b894922d58cc share/hedgewars/Data/Locale/tips_it.xml --- a/share/hedgewars/Data/Locale/tips_it.xml Tue Sep 08 19:20:58 2015 +0300 +++ b/share/hedgewars/Data/Locale/tips_it.xml Mon Nov 16 22:57:24 2015 +0300 @@ -6,52 +6,73 @@ 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 noi creiamo nel nostro tempo libero. Se hai problemi, chiedi nei nostri forum ma, per favore, non aspettarti un supporto 24/7! + 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 e con gli amici come più ti piace! - Di tanto in tanto ci saranno tornei ufficiali. Gli eventi saranno annunciati su http://www.hedgewars.org/ con qualche giorno di anticipo. + 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 - XP, Vista, 7 -, Mac OS X e Linux. + 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! - Durante il gioco dovresti fare una breve pausa almeno ogni ora. In caso di partite più lunghe, sospendi l'attività per almeno 30 minuti al termine del gioco! + 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! + 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. - Hedgewars è un programma Open Source e gratuito che creiamo nel nostro tempo libero. Se qualcuno ti ha venduto il gioco, dovresti chiedere un rimborso! - Collega uno o più gamepad prima di iniziare il gioco per poterli assegnare alle tue squadra. - Crea un account su %1 per evitare che altri possano usare il tuo nickname preferito mentre giochi sul server ufficiale. - Se la tua scheda grafica non è in grado di fornire OpenGL con accelerazione hardware, prova ad aggiornarne i driver. - Ci sono tre salti disponibili. Premi [salto in alto] due volte per eseguire un salto in alto all'indietro. + 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 ci sono anche delle grosse controindicazioni. - Le Mine Adesive sono lo strumento perfetto per creare piccole reazioni a catena e spingere i ricci nemici in situazioni difficili... o in acqua. + 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 %1 o seguici su %2! - Sentiti libero di disegnare tombe, cappelli, bandiere o anche mappe e temi personalizzati - lo puoi fare con TheGIMP! Ma nota che dovrai condividerli in qualche modo per usarli online. - Vuoi proprio un cappello specifico? Facci una piccola donazione e riceverai un cappello esclusivo a tua scelta! + 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. - Puoi trovare i file di configurazione del gioco in "Documenti\Hedgewars". Crea delle copie di sicurezza o prendi i file con te, ma non modificarli manualmente! - 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 Internet. - 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! - Puoi trovare i file di configurazione del gioco 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 del gioco in ".hedgewars" nella tua cartella home. Crea una copia di sicurezza o porta i file con te, ma non modificarli mai manualmente. - Usa la Bomba Molotov o il Lanciafiamme per impedire temporaneamente ai ricci di attraversari terreni pianeggianti, tunnel o collinette. - 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. + 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! - La versione Windows di Hedgewars supporta Xfire. Assicurati di aggiungere Hedgewars alla sua lista giochi, così i tuoi amici potranno vederti giocare. + 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 fcbdee9cdd74 -r b894922d58cc share/hedgewars/Data/Maps/Basketball/map.lua --- a/share/hedgewars/Data/Maps/Basketball/map.lua Tue Sep 08 19:20:58 2015 +0300 +++ b/share/hedgewars/Data/Maps/Basketball/map.lua Mon Nov 16 22:57:24 2015 +0300 @@ -54,3 +54,7 @@ end end end + +function onNewTurn() + SetWeapon(amBaseballBat) +end diff -r fcbdee9cdd74 -r b894922d58cc share/hedgewars/Data/Maps/Control/map.lua --- a/share/hedgewars/Data/Maps/Control/map.lua Tue Sep 08 19:20:58 2015 +0300 +++ b/share/hedgewars/Data/Maps/Control/map.lua Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc share/hedgewars/Data/Maps/Knockball/map.lua --- a/share/hedgewars/Data/Maps/Knockball/map.lua Tue Sep 08 19:20:58 2015 +0300 +++ b/share/hedgewars/Data/Maps/Knockball/map.lua Mon Nov 16 22:57:24 2015 +0300 @@ -68,3 +68,7 @@ end end end + +function onNewTurn() + SetWeapon(amBaseballBat) +end diff -r fcbdee9cdd74 -r b894922d58cc share/hedgewars/Data/Maps/ShoppaKing/map.png Binary file share/hedgewars/Data/Maps/ShoppaKing/map.png has changed diff -r fcbdee9cdd74 -r b894922d58cc share/hedgewars/Data/Maps/ShoppaKing/map.xcf Binary file share/hedgewars/Data/Maps/ShoppaKing/map.xcf has changed diff -r fcbdee9cdd74 -r b894922d58cc share/hedgewars/Data/Maps/TrophyRace/map.lua --- a/share/hedgewars/Data/Maps/TrophyRace/map.lua Tue Sep 08 19:20:58 2015 +0300 +++ b/share/hedgewars/Data/Maps/TrophyRace/map.lua Mon Nov 16 22:57:24 2015 +0300 @@ -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 @@ -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 fcbdee9cdd74 -r b894922d58cc share/hedgewars/Data/Maps/TrophyRace/map.png Binary file share/hedgewars/Data/Maps/TrophyRace/map.png has changed diff -r fcbdee9cdd74 -r b894922d58cc share/hedgewars/Data/Maps/TrophyRace/map.xcf Binary file share/hedgewars/Data/Maps/TrophyRace/map.xcf has changed diff -r fcbdee9cdd74 -r b894922d58cc share/hedgewars/Data/Missions/Training/Basic_Training_-_Bazooka.lua --- a/share/hedgewars/Data/Missions/Training/Basic_Training_-_Bazooka.lua Tue Sep 08 19:20:58 2015 +0300 +++ b/share/hedgewars/Data/Missions/Training/Basic_Training_-_Bazooka.lua Mon Nov 16 22:57:24 2015 +0300 @@ -141,7 +141,7 @@ 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) + 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 ... @@ -162,11 +162,11 @@ SendStat(siCustomAchievement, string.format(loc("Your accuracy was %.1f%%."), (score/shots)*100)) end if score == score_goal then - SendStat(siGameResult, "You have finished the bazooka training!") + 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, "You lose!") + SendStat(siGameResult, loc("You lose!")) end -- Finally we end the game ... @@ -224,7 +224,7 @@ 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) + ShowMission(loc("Bazooka Training") , loc("Aiming Practice"), loc("Oh no! You failed! Just try again."), -amSkip, 0) time_goal = 1 end diff -r fcbdee9cdd74 -r b894922d58cc share/hedgewars/Data/Missions/Training/Basic_Training_-_Grenade.lua --- a/share/hedgewars/Data/Missions/Training/Basic_Training_-_Grenade.lua Tue Sep 08 19:20:58 2015 +0300 +++ b/share/hedgewars/Data/Missions/Training/Basic_Training_-_Grenade.lua Mon Nov 16 22:57:24 2015 +0300 @@ -134,9 +134,9 @@ 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 diff -r fcbdee9cdd74 -r b894922d58cc share/hedgewars/Data/Missions/Training/Challenge_-_Speed_Shoppa_-_ShoppaKing.lua --- a/share/hedgewars/Data/Missions/Training/Challenge_-_Speed_Shoppa_-_ShoppaKing.lua Tue Sep 08 19:20:58 2015 +0300 +++ b/share/hedgewars/Data/Missions/Training/Challenge_-_Speed_Shoppa_-_ShoppaKing.lua Mon Nov 16 22:57:24 2015 +0300 @@ -1,7 +1,7 @@ HedgewarsScriptLoad("/Scripts/SpeedShoppa.lua") local params = {} -params.missionTitle = loc("The Customor is King") +params.missionTitle = loc("The Customer is King") params.teamName = loc("Shoppa Union") params.hogName = loc("King Customer") params.teamFlag = "cm_shoppa" diff -r fcbdee9cdd74 -r b894922d58cc share/hedgewars/Data/Missions/Training/Target_Practice_-_Bazooka_easy.lua --- a/share/hedgewars/Data/Missions/Training/Target_Practice_-_Bazooka_easy.lua Tue Sep 08 19:20:58 2015 +0300 +++ b/share/hedgewars/Data/Missions/Training/Target_Practice_-_Bazooka_easy.lua Mon Nov 16 22:57:24 2015 +0300 @@ -3,7 +3,7 @@ local params = { ammoType = amBazooka, gearType = gtShell, - missionTitle = "Target Practice: Bazooka (easy)", + missionTitle = loc("Target Practice: Bazooka (easy)"), wind = 50, solidLand = true, map = "Lonely_Island", diff -r fcbdee9cdd74 -r b894922d58cc share/hedgewars/Data/Missions/Training/Target_Practice_-_Bazooka_hard.lua --- a/share/hedgewars/Data/Missions/Training/Target_Practice_-_Bazooka_hard.lua Tue Sep 08 19:20:58 2015 +0300 +++ b/share/hedgewars/Data/Missions/Training/Target_Practice_-_Bazooka_hard.lua Mon Nov 16 22:57:24 2015 +0300 @@ -3,7 +3,7 @@ local params = { ammoType = amBazooka, gearType = gtShell, - missionTitle = "Target Practice: Bazooka (hard)", + missionTitle = loc("Target Practice: Bazooka (hard)"), wind = 20, solidLand = true, artillery = true, diff -r fcbdee9cdd74 -r b894922d58cc share/hedgewars/Data/Missions/Training/Target_Practice_-_Cluster_Bomb.lua --- a/share/hedgewars/Data/Missions/Training/Target_Practice_-_Cluster_Bomb.lua Tue Sep 08 19:20:58 2015 +0300 +++ b/share/hedgewars/Data/Missions/Training/Target_Practice_-_Cluster_Bomb.lua Mon Nov 16 22:57:24 2015 +0300 @@ -3,7 +3,7 @@ local params = { ammoType = amClusterBomb, gearType = gtClusterBomb, - missionTitle = "Cluster Bomb Training", + missionTitle = loc("Cluster Bomb Training"), solidLand = false, map = "Trash", theme = "Golf", diff -r fcbdee9cdd74 -r b894922d58cc share/hedgewars/Data/Missions/Training/Target_Practice_-_Grenade_easy.lua --- a/share/hedgewars/Data/Missions/Training/Target_Practice_-_Grenade_easy.lua Tue Sep 08 19:20:58 2015 +0300 +++ b/share/hedgewars/Data/Missions/Training/Target_Practice_-_Grenade_easy.lua Mon Nov 16 22:57:24 2015 +0300 @@ -3,7 +3,7 @@ local params = { ammoType = amGrenade, gearType = gtGrenade, - missionTitle = "Target Practice: Grenade (easy)", + missionTitle = loc("Target Practice: Grenade (easy)"), solidLand = true, artillery = true, map = "SB_Crystal", diff -r fcbdee9cdd74 -r b894922d58cc share/hedgewars/Data/Missions/Training/Target_Practice_-_Grenade_hard.lua --- a/share/hedgewars/Data/Missions/Training/Target_Practice_-_Grenade_hard.lua Tue Sep 08 19:20:58 2015 +0300 +++ b/share/hedgewars/Data/Missions/Training/Target_Practice_-_Grenade_hard.lua Mon Nov 16 22:57:24 2015 +0300 @@ -3,7 +3,7 @@ local params = { ammoType = amGrenade, gearType = gtGrenade, - missionTitle = "Target Practice: Grenade (hard)", + missionTitle = loc("Target Practice: Grenade (hard)"), solidLand = true, artillery = true, map = "SB_Crystal", diff -r fcbdee9cdd74 -r b894922d58cc share/hedgewars/Data/Missions/Training/Target_Practice_-_Homing_Bee.lua --- a/share/hedgewars/Data/Missions/Training/Target_Practice_-_Homing_Bee.lua Tue Sep 08 19:20:58 2015 +0300 +++ b/share/hedgewars/Data/Missions/Training/Target_Practice_-_Homing_Bee.lua Mon Nov 16 22:57:24 2015 +0300 @@ -3,7 +3,7 @@ local params = { ammoType = amBee, gearType = gtBee, - missionTitle = "Target Practice: Homing Bee", + missionTitle = loc("Target Practice: Homing Bee"), solidLand = true, map = "Hedgewars", theme = "Nature", diff -r fcbdee9cdd74 -r b894922d58cc share/hedgewars/Data/Missions/Training/Target_Practice_-_Shotgun.lua --- a/share/hedgewars/Data/Missions/Training/Target_Practice_-_Shotgun.lua Tue Sep 08 19:20:58 2015 +0300 +++ b/share/hedgewars/Data/Missions/Training/Target_Practice_-_Shotgun.lua Mon Nov 16 22:57:24 2015 +0300 @@ -3,7 +3,7 @@ local params = { ammoType = amShotgun, gearType = gtShotgunShot, - missionTitle = "Target Practice: Shotgun", + missionTitle = loc("Target Practice: Shotgun"), solidLand = false, map = "SB_Haunty", theme = "Halloween", diff -r fcbdee9cdd74 -r b894922d58cc share/hedgewars/Data/Missions/Training/User_Mission_-_Bamboo_Thicket.lua --- a/share/hedgewars/Data/Missions/Training/User_Mission_-_Bamboo_Thicket.lua Tue Sep 08 19:20:58 2015 +0300 +++ b/share/hedgewars/Data/Missions/Training/User_Mission_-_Bamboo_Thicket.lua Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc 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 Sep 08 19:20:58 2015 +0300 +++ b/share/hedgewars/Data/Missions/Training/User_Mission_-_Newton_and_the_Hammock.lua Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc share/hedgewars/Data/Missions/Training/User_Mission_-_Nobody_Laugh.lua --- a/share/hedgewars/Data/Missions/Training/User_Mission_-_Nobody_Laugh.lua Tue Sep 08 19:20:58 2015 +0300 +++ b/share/hedgewars/Data/Missions/Training/User_Mission_-_Nobody_Laugh.lua Mon Nov 16 22:57:24 2015 +0300 @@ -27,21 +27,21 @@ SetGearPosition(hhs[2], 1332, 451) AddTeam(loc("Clowns"), 1175851, "Duck2", "Tank", "Mobster", "cm_spider") - hhs[3] = AddHog("Poison", 5, 100, "WhySoSerious") + hhs[3] = AddHog(loc("Poison"), 5, 100, "WhySoSerious") SetGearPosition(hhs[3], 1133, 446) - hhs[4] = AddHog("Bobo", 5, 100, "clown") + hhs[4] = AddHog(loc("Bobo"), 5, 100, "clown") SetGearPosition(hhs[4], 1215, 553) - hhs[5] = AddHog("Copper", 5, 10, "clown-copper") + hhs[5] = AddHog(loc("Copper"), 5, 10, "clown-copper") SetGearPosition(hhs[5], 414, 376) - hhs[6] = AddHog("Derp", 5, 100, "clown-crossed") + hhs[6] = AddHog(loc("Derp"), 5, 100, "clown-crossed") SetGearPosition(hhs[6], 1590, 886) - hhs[7] = AddHog("Eckles", 5, 100, "clown-copper") + hhs[7] = AddHog(loc("Eckles"), 5, 100, "clown-copper") SetGearPosition(hhs[7], 772, 754) - hhs[8] = AddHog("Frank", 5, 50, "clown-copper") + hhs[8] = AddHog(loc("Frank"), 5, 50, "clown-copper") SetGearPosition(hhs[8], 1688, 714) - hhs[9] = AddHog("Harry", 5, 50, "clown-copper") + hhs[9] = AddHog(loc("Harry"), 5, 50, "clown-copper") SetGearPosition(hhs[9], 1932, 837) - hhs[10] = AddHog("Igmund", 5, 50, "WhySoSerious") + hhs[10] = AddHog(loc("Igmund"), 5, 50, "WhySoSerious") SetGearPosition(hhs[10], 1601, 733) end diff -r fcbdee9cdd74 -r b894922d58cc share/hedgewars/Data/Missions/Training/User_Mission_-_That_Sinking_Feeling.lua --- a/share/hedgewars/Data/Missions/Training/User_Mission_-_That_Sinking_Feeling.lua Tue Sep 08 19:20:58 2015 +0300 +++ b/share/hedgewars/Data/Missions/Training/User_Mission_-_That_Sinking_Feeling.lua Mon Nov 16 22:57:24 2015 +0300 @@ -216,10 +216,10 @@ if (waterPix >= 1615) and (GameOver == false) then GameOver = true - AddCaption("The flood has stopped! Challenge over.") + AddCaption(loc("The flood has stopped! Challenge over.")) SendStat(siGameResult, loc("Challenge completed!")) SendStat(siPlayerKills, tostring(hhCount), loc("Nameless Heroes")) - SendStat(siPointType, "rescues") + SendStat(siPointType, loc("rescues")) -- Do not count drowning hedgehogs local hhLeft = hhCount @@ -283,7 +283,7 @@ SendStat(siCustomAchievement, loc("You haven't rescued anyone.")) end SendStat(siPlayerKills, "0", loc("Nameless Heroes")) - SendStat(siPointType, "points") + SendStat(siPointType, loc("points")) SendStat(siGameResult, loc("Disqualified!")) GameOver = true diff -r fcbdee9cdd74 -r b894922d58cc share/hedgewars/Data/Missions/Training/User_Mission_-_The_Great_Escape.lua --- a/share/hedgewars/Data/Missions/Training/User_Mission_-_The_Great_Escape.lua Tue Sep 08 19:20:58 2015 +0300 +++ b/share/hedgewars/Data/Missions/Training/User_Mission_-_The_Great_Escape.lua Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc share/hedgewars/Data/Missions/Training/portal.lua --- a/share/hedgewars/Data/Missions/Training/portal.lua Tue Sep 08 19:20:58 2015 +0300 +++ b/share/hedgewars/Data/Missions/Training/portal.lua Mon Nov 16 22:57:24 2015 +0300 @@ -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 fcbdee9cdd74 -r b894922d58cc share/hedgewars/Data/Scripts/Multiplayer/Construction_Mode.lua --- a/share/hedgewars/Data/Scripts/Multiplayer/Construction_Mode.lua Tue Sep 08 19:20:58 2015 +0300 +++ b/share/hedgewars/Data/Scripts/Multiplayer/Construction_Mode.lua Mon Nov 16 22:57:24 2015 +0300 @@ -1517,7 +1517,7 @@ end - AddCaption(cat[cIndex],0xffba00ff,capgrpMessage) + AddCaption(loc(cat[cIndex]),0xffba00ff,capgrpMessage) AddCaption(pMode[pIndex],0xffba00ff,capgrpMessage2) wallsVisible = true else @@ -1791,7 +1791,7 @@ loc("Generator") .. ": " .. loc("Generates power.") .. "|" .. loc("Respawner") .. ": " .. loc("Resurrects dead hedgehogs.") .. "|" .. - loc("Teleporation Node") .. ": " .. loc("Allows free teleportation between other nodes.") .. "|" .. + 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.") .. "|" .. diff -r fcbdee9cdd74 -r b894922d58cc share/hedgewars/Data/Scripts/Multiplayer/Mutant.lua --- a/share/hedgewars/Data/Scripts/Multiplayer/Mutant.lua Tue Sep 08 19:20:58 2015 +0300 +++ b/share/hedgewars/Data/Scripts/Multiplayer/Mutant.lua Mon Nov 16 22:57:24 2015 +0300 @@ -302,7 +302,7 @@ if teams[i]~= nil then local curr_score = getTeamValue(teams[i], "Score") - showScore = showScore .. teams[i] .. ": " .. curr_score .. " (deaths: " .. getTeamValue(teams[i], "DeadHogs") .. ") " .. "|" + showScore = showScore .. teams[i] .. ": " .. curr_score .. " (" .. loc("deaths") .. ": " .. getTeamValue(teams[i], "DeadHogs") .. ") " .. "|" end end @@ -329,7 +329,7 @@ runOnHogsInTeam(removeFeeder, teams[i]) - showScore = showScore .. teams[i] ..": " .. curr_score .. " (deaths: " .. getTeamValue(teams[i], "DeadHogs") .. ") " .. "|" + showScore = showScore .. teams[i] ..": " .. curr_score .. " (" .. loc("deaths") .. ": " .. getTeamValue(teams[i], "DeadHogs") .. ") " .. "|" if curr_score >= winScore then gameOver = true @@ -421,7 +421,7 @@ function setFeeder(gear) if gear~= mutant and gear~= nil then - SetHogName(gear,"BOTTOM FEEDER") + SetHogName(gear, loc("BOTTOM FEEDER")) SetHogHat(gear, 'poke_slowpoke') setGearValue(gear,"Feeder", true) end @@ -430,7 +430,7 @@ function setMutantStuff(gear) mutant = gear - SetHogName(gear,"MUTANT") + SetHogName(gear, loc("MUTANT")) SetHogHat(gear,'WhySoSerious') SetHealth(gear, ( mutant_base_health + numhhs*25) ) SetEffect(gear, hePoisoned, 1) diff -r fcbdee9cdd74 -r b894922d58cc share/hedgewars/Data/Scripts/Multiplayer/The_Specialists.lua --- a/share/hedgewars/Data/Scripts/Multiplayer/The_Specialists.lua Tue Sep 08 19:20:58 2015 +0300 +++ b/share/hedgewars/Data/Scripts/Multiplayer/The_Specialists.lua Mon Nov 16 22:57:24 2015 +0300 @@ -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) diff -r fcbdee9cdd74 -r b894922d58cc share/hedgewars/Data/Scripts/Multiplayer/WxW.lua --- a/share/hedgewars/Data/Scripts/Multiplayer/WxW.lua Tue Sep 08 19:20:58 2015 +0300 +++ b/share/hedgewars/Data/Scripts/Multiplayer/WxW.lua Mon Nov 16 22:57:24 2015 +0300 @@ -158,9 +158,9 @@ function BoolToCfgTxt(p) if p == false then - return("Disabled") + return loc("Disabled") else - return("Enabled") + return loc("Enabled") end end diff -r fcbdee9cdd74 -r b894922d58cc share/hedgewars/Data/Shaders/CMakeLists.txt diff -r fcbdee9cdd74 -r b894922d58cc share/hedgewars/Data/Shaders/default.fs diff -r fcbdee9cdd74 -r b894922d58cc share/hedgewars/Data/Shaders/default.vs diff -r fcbdee9cdd74 -r b894922d58cc share/hedgewars/Data/Shaders/water.fs diff -r fcbdee9cdd74 -r b894922d58cc share/hedgewars/Data/Shaders/water.vs diff -r fcbdee9cdd74 -r b894922d58cc tools/CMakeLists.txt --- a/tools/CMakeLists.txt Tue Sep 08 19:20:58 2015 +0300 +++ b/tools/CMakeLists.txt Mon Nov 16 22:57:24 2015 +0300 @@ -8,13 +8,14 @@ if(APPLE AND NOT SKIPBUNDLE) find_package(Qt4 REQUIRED QUIET) + 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) - 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) + if(NOT NOAUTOUPDATE) find_package(Sparkle) #needed for SPARKLE_FOUND variable #needed because the 'if' clause in the script prints silly policy warnings @@ -58,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 fcbdee9cdd74 -r b894922d58cc tools/build_windows.bat --- a/tools/build_windows.bat Tue Sep 08 19:20:58 2015 +0300 +++ b/tools/build_windows.bat Mon Nov 16 22:57:24 2015 +0300 @@ -27,8 +27,6 @@ ::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 diff -r fcbdee9cdd74 -r b894922d58cc tools/pas2c/Pas2C.hs --- a/tools/pas2c/Pas2C.hs Tue Sep 08 19:20:58 2015 +0300 +++ b/tools/pas2c/Pas2C.hs Mon Nov 16 22:57:24 2015 +0300 @@ -1,4 +1,5 @@ {-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE FlexibleContexts #-} module Pas2C where import Text.PrettyPrint.HughesPJ diff -r fcbdee9cdd74 -r b894922d58cc tools/pas2c/PascalParser.hs --- a/tools/pas2c/PascalParser.hs Tue Sep 08 19:20:58 2015 +0300 +++ b/tools/pas2c/PascalParser.hs Mon Nov 16 22:57:24 2015 +0300 @@ -239,10 +239,10 @@ ] "range declaration" where rangeft = do - e1 <- initExpression - string' ".." - e2 <- initExpression - return $ RangeFromTo e1 e2 + e1 <- initExpression + string' ".." + e2 <- initExpression + return $ RangeFromTo e1 e2 typeVarDeclaration :: Bool -> Parsec String u [TypeVarDeclaration] typeVarDeclaration isImpl = (liftM concat . many . choice) [ diff -r fcbdee9cdd74 -r b894922d58cc tools/pas2c/pas2c.cabal --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/pas2c/pas2c.cabal Mon Nov 16 22:57:24 2015 +0300 @@ -0,0 +1,30 @@ +Name: pas2c +Version: 0.1 +Synopsis: pas2c +Description: pas2c +Homepage: http://www.hedgewars.org/ +License: GPL-2 +Author: unC0Rr +Maintainer: unC0Rr@hedgewars.org +Category: Converter +Build-type: Simple +Cabal-version: >=1.10 + + +Executable pas2c + main-is: Main.hs + + default-language: Haskell2010 + + build-depends: + base >= 4.3, + containers, + mtl >= 2, + parsec, + pretty, + transformers + + if !os(windows) + build-depends: unix + + ghc-options: -O2