Page MenuHomePhabricator (Chris)

No OneTemporary

Authored By
Unknown
Size
364 KB
Referenced Files
None
Subscribers
None
This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 29f565d..e2fa05f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,192 +1,193 @@
Project (meandmyshadow)
CMake_Minimum_Required (VERSION 3.1)
Set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")
+#Path options
+Set (BINDIR "bin" CACHE STRING "Where to install binaries")
+Set (DATAROOTDIR "${CMAKE_INSTALL_PREFIX}/share" CACHE STRING "Sets the root of data directories to a non-default location")
+Set (ICONDIR "${DATAROOTDIR}/icons" CACHE STRING "Sets the icon directory for desktop entry to a non-default location.")
+Set (DESKTOPDIR "${DATAROOTDIR}/applications" CACHE STRING "Sets the desktop file directory for desktop entry to a non-default location.")
+
+#Options
Option (DEBUG_MODE "Compile the game with debug mode enabled" OFF)
Option (DISABLED_DEBUG_STUFF "Enable this you'll see a lot of annoying script debug messages which will lag the game." OFF)
#Find the required libraries.
Find_Package (SDL2 REQUIRED)
Find_Package (SDL2_image REQUIRED)
Find_Package (Freetype REQUIRED)
Find_Package (SDL2_mixer REQUIRED)
Find_Package (CURL REQUIRED)
Find_Package (LibArchive REQUIRED)
Find_Package (Lua 5.3 REQUIRED)
if (NOT SDL2_FOUND)
message (FATAL_ERROR "SDL2 library could not be found!")
endif (NOT SDL2_FOUND)
if (NOT SDL2_IMAGE_FOUND)
message (FATAL_ERROR "SDL2_image library could not be found!")
endif (NOT SDL2_IMAGE_FOUND)
if (NOT FREETYPE_FOUND)
message (FATAL_ERROR "Freetype library could not be found!")
endif (NOT FREETYPE_FOUND)
if (NOT SDL2_MIXER_FOUND)
message (FATAL_ERROR "SDL2_mixer library could not be found!")
endif (NOT SDL2_MIXER_FOUND)
if (NOT CURL_FOUND)
message(FATAL_ERROR "CURL library could not be found!")
endif (NOT CURL_FOUND)
if (NOT LibArchive_FOUND)
message (FATAL_ERROR "LibArchive library could not be found!")
endif (NOT LibArchive_FOUND)
if (NOT LUA_FOUND)
message (FATAL_ERROR "Lua library could not be found!")
endif (NOT LUA_FOUND)
if (LUA_VERSION_STRING VERSION_LESS "5.3")
message (FATAL_ERROR "Lua version too old ${LUA_VERSION_STRING}, expected at least 5.3!")
endif ()
# check version from Globals.h
file(READ "${PROJECT_SOURCE_DIR}/src/Globals.h" GLOBALS_H)
string(REGEX MATCH "version[ ]*=[ ]*\"[^\"]*\"" MNMS_VERSION_STR ${GLOBALS_H})
string(REGEX REPLACE "^[^\"]*\"([^\"]*)\".*$" "\\1" MNMS_VERSION_STR ${MNMS_VERSION_STR})
message(STATUS "The version read from Globals.h is: ${MNMS_VERSION_STR}")
string(REGEX REPLACE "^V([0-9.]+).*$" "\\1" MNMS_VERSION_NUM ${MNMS_VERSION_STR})
set(MNMS_VERSION_NUM "${MNMS_VERSION_NUM}.0.0.0.0")
string(REGEX REPLACE "^([0-9]+)[.]([0-9]+)[.]([0-9]+)[.]([0-9]+).*$" "\\1,\\2,\\3,\\4" MNMS_VERSION_NUM ${MNMS_VERSION_NUM})
message(STATUS "which is: ${MNMS_VERSION_NUM}")
# check version from git
find_package(Git)
if(GIT_FOUND)
exec_program(${GIT_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR} ARGS "describe"
OUTPUT_VARIABLE MNMS_GIT_VERSION RETURN_VALUE GIT_RETURN_VALUE)
if(GIT_RETURN_VALUE STREQUAL "0")
set(MNMS_VERSION_STR "${MNMS_VERSION_STR} (${MNMS_GIT_VERSION})")
message(STATUS "The version read from git is: ${MNMS_GIT_VERSION}")
else()
# possibly there are no any tags
exec_program(${GIT_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR} ARGS "rev-parse --short HEAD"
OUTPUT_VARIABLE MNMS_GIT_VERSION RETURN_VALUE GIT_RETURN_VALUE)
if(GIT_RETURN_VALUE STREQUAL "0")
set(MNMS_VERSION_STR "${MNMS_VERSION_STR} (git ${MNMS_GIT_VERSION})")
message(STATUS "The version read from git is: ${MNMS_GIT_VERSION}")
endif()
endif()
endif()
# show version information on Windows
Set(WIN32_RESOURCES )
if(WIN32)
Configure_File (
"${PROJECT_SOURCE_DIR}/icons/windows-icon/res.rc.in"
"${PROJECT_BINARY_DIR}/res.rc"
)
Set(WIN32_RESOURCES ${PROJECT_BINARY_DIR}/res.rc)
Include_Directories(${PROJECT_SOURCE_DIR}/icons/windows-icon/)
SOURCE_GROUP("Source Files\\Resources" FILES ${WIN32_RESOURCES})
endif()
#Parse the configure file.
Configure_File (
"${PROJECT_SOURCE_DIR}/src/config.h.in"
"${PROJECT_BINARY_DIR}/config.h"
)
#Add some missing libraries to Windows.
if(WIN32)
include_directories(${PROJECT_SOURCE_DIR}/src/libs/dirent)
endif(WIN32)
#Disable some annoying warnings.
if(MSVC)
# warning C4996: '***': This function or variable may be unsafe
add_definitions(/wd4996)
# force the source code encoding to UTF-8 (which is available since VC2015)
if (NOT (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.0))
add_definitions(-utf-8)
endif()
else()
# Assume it's gcc or clang
# warning: '***' overrides a member function but is not marked 'override'
add_definitions(-Wno-inconsistent-missing-override)
endif()
#Define some debug stuff.
if(DEBUG_MODE)
add_definitions(-DDEBUG)
add_definitions(-D_DEBUG)
endif(DEBUG_MODE)
if(DISABLED_DEBUG_STUFF)
add_definitions(-DDISABLED_DEBUG_STUFF)
endif(DISABLED_DEBUG_STUFF)
#Add the include directories of the (found) libraries.
Include_Directories(
${PROJECT_BINARY_DIR}
${SDL2_INCLUDE_DIR}
${SDL2_IMAGE_INCLUDE_DIR}
${FREETYPE_INCLUDE_DIRS}
${SDL2_MIXER_INCLUDE_DIR}
${CURL_INCLUDE_DIR}
${LibArchive_INCLUDE_DIR}
${LUA_INCLUDE_DIR}
${PROJECT_SOURCE_DIR}/src/libs
${PROJECT_SOURCE_DIR}/src/libs/SDL2_ttf
)
#Set the output path and the source path.
Set (EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR})
Set (SRC_DIR ${PROJECT_SOURCE_DIR}/src)
#List the source files.
File (GLOB SOURCES ${SRC_DIR}/*.cpp)
File (GLOB TINYFORMAT ${SRC_DIR}/libs/tinyformat/*.cpp)
File (GLOB TINYGETTEXT ${SRC_DIR}/libs/tinygettext/*.cpp)
File (GLOB FINDLOCALE ${SRC_DIR}/libs/findlocale/*.cpp)
File (GLOB SDL2TTF ${SRC_DIR}/libs/SDL2_ttf/*.c)
#Always use SDL_iconv in tinygettext
add_definitions(-DHAVE_SDL)
SOURCE_GROUP("Source Files\\tinyformat" FILES ${TINYFORMAT})
SOURCE_GROUP("Source Files\\tinygettext" FILES ${TINYGETTEXT})
SOURCE_GROUP("Source Files\\findlocale" FILES ${FINDLOCALE})
SOURCE_GROUP("Source Files\\SDL2_ttf" FILES ${SDL2TTF})
Add_Executable (meandmyshadow ${SOURCES} ${TINYFORMAT} ${TINYGETTEXT} ${FINDLOCALE} ${WIN32_RESOURCES} ${SDL2TTF})
set_property(TARGET meandmyshadow PROPERTY CXX_STANDARD 11)
Target_Link_Libraries (
meandmyshadow
${SDL2_LIBRARY}
${SDL2_IMAGE_LIBRARY}
${FREETYPE_LIBRARIES}
${SDL2_MIXER_LIBRARY}
${SDL2MAIN_LIBRARY}
${CURL_LIBRARY}
${LibArchive_LIBRARY}
${LUA_LIBRARIES}
)
-#Path options
-Set (BINDIR "bin" CACHE STRING "Where to install binaries")
-Set (DATAROOTDIR "${CMAKE_INSTALL_PREFIX}/share" CACHE STRING "Sets the root of data directories to a non-default location")
-Set (ICONDIR "${DATAROOTDIR}/icons" CACHE STRING "Sets the icon directory for desktop entry to a non-default location.")
-Set (DESKTOPDIR "${DATAROOTDIR}/applications" CACHE STRING "Sets the desktop file directory for desktop entry to a non-default location.")
-
#Install locations
Install (DIRECTORY ${PROJECT_SOURCE_DIR}/data DESTINATION ${DATAROOTDIR}/meandmyshadow/)
Install (FILES AUTHORS DESTINATION ${DATAROOTDIR}/meandmyshadow/)
Install (TARGETS meandmyshadow RUNTIME DESTINATION ${BINDIR})
if ("${CMAKE_SYSTEM_NAME}" MATCHES "Linux")
Install (FILES meandmyshadow.desktop DESTINATION ${DESKTOPDIR})
Install (FILES icons/16x16/meandmyshadow.png DESTINATION ${ICONDIR}/hicolor/16x16/apps/)
Install (FILES icons/32x32/meandmyshadow.png DESTINATION ${ICONDIR}/hicolor/32x32/apps/)
Install (FILES icons/48x48/meandmyshadow.png DESTINATION ${ICONDIR}/hicolor/48x48/apps/)
Install (FILES icons/64x64/meandmyshadow.png DESTINATION ${ICONDIR}/hicolor/64x64/apps/)
endif ("${CMAKE_SYSTEM_NAME}" MATCHES "Linux")
diff --git a/ChangeLog b/ChangeLog
index b3598f4..a94df08 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,339 +1,350 @@
+Me and My Shadow V0.5a
+------------------------
+
+Minor bug fix release.
+
+* Define paths earlier in CMakeLists.txt, mainly for Linux package build
+* Don't use SDL_INIT_EVERYTHING which fails on systems which do not support SDL_INIT_HAPTIC
+* Update the target time from 6s to 6.5s of tutorial level 10
+* Update Hungarian (by SanskritFritz), Ukrainian (by burunduk and eugeneloza)
+ and Russian (by BoFFire, mesnevi and eugeneloza) translations which fixes some bugs
+
Me and My Shadow V0.5
------------------------
Brief list of changes:
* Switch to SDL2.
* Menu theme.
* Achievement and statistics system.
* Scripting with lua.
* Pushable block.
* Improved addon dialog.
* Improved level editor user interface.
* Sizable blocks.
* Scenery blocks.
* Undo/redo in level editor originally written by squarecross.
* Added 'visible' property to blocks.
* Custom appearance of blocks.
* Various other bug fixes and minor improvements.
Translations:
* Updated Simplified Chinese, German, Russian, French and Scottish Gaelic translations.
* Added Hungarian translation by SanskritFritz.
* Added Norwegian translation by Petter Reinholdtsen and Allan Nordhøy.
* Added Ukrainian translation by eugeneloza.
Known bugs and limitations:
* No proper IME support for text box, etc.
* OSX support is broken.
* The button specification in theme file is changed, old theme may render button incorrectly in new version.
* Some achievements are not realistic, and there is a typo in achievements.
* Invisible collectible is counted in total number of collectibles.
* The scenery layer naming convention is confusing.
* The target time for tutorial level 10 seems unbeatable. Needs further investigation.
* There seems to be a random crash bug when exiting the game.
Me and My Shadow V0.4
------------------------
* Fixed the .desktop file.
* Created a separate docs/ folder to contain the documentation files like Controls.txt, ThemeDescription.txt, etc...
* Implemented an OpenGL renderer as alternative for the SDLRenderer.
* Fixed a bug where escape in the options menu would exit both the options menu and the main menu.
* Updated all GUIs and menus to support different resolutions, making them dynamic.
* Extended the Game rendering to support different resolutions.
* Extended the CMakeLists.txt file to make paths configurable.
* Added the library tinygettext to the project to support localisation.
* Added the library tinyformat to allow easy string formatting.
* Made the internal string literals translatable.
* Added the library findlocale to detect the preferred localization.
* Updated the CMakeLists.txt to compile the bundled libraries.
* Added the font Droid Sans for languages that contain non-latin characters.
* Implemented a levelpack manager for preloading the levelpacks at the start.
* Made levelpacks translatable as well.
* Fixed a bug where the game would crash on translating the tooltip for levels of the 'Custom Levels' levelpack.
* Changed the number of levels per row in the LevelSelect screens to support multiple resolutions.
* Fixed a bug where levelpack translations weren't detected properly.
* Extended the LevelEditor to support different window sizes.
* Added language and resolution options in the Options menu.
* Made 800x600 the minimum resolution supported.
* Fixed a bug where the camera would move in the leveleditor even if the mouse was on top of the toolbar.
* Added support for different die animations, one for dying while looking right and one for looking left.
* Also changed the way the level is aligned when the screen is larger than the level, the bottom of the level will stay the bottom of the window/screen.
* Fixed a bug where the camera didn't scroll smooth to the left.
* Updated the Cloudscape theme to V2.1.
* Fixed some in-game tooltip memory leak.
* Warnings thrown by tinygettext are now suppressed.
* Fixed a bug in the the screen surface where the alpha mask wasn't configured properly when using the gl renderer.
* Added a python script for generating a .pot file by extracting the translatable strings out of a levelpack.
* Updated the time and recordings icons, they are now black and white.
* Fixed a bug where after restarting the inter level gui would appear.
* Fixed a bug where the player or the shadow got displaced when being squashed.
* Levels get centred in the leveleditor when smaller than the screen size.
* Updated the Cloudscape theme to V2.2.
* Fixed some bugs regarding the new levelpackmanager and installing/removing addons.
* Also applied a fix for TreeStorageNode.cpp to prevent some compile errors.
* Disabled the death animation when falling of the level.
* Fixed a bug where the player or the shadow would die when jumping on a block that has a spike behind it.
* The block configuration screens in the leveleditor are now centred.
* Added toolbox for easy selecting block types in the leveleditor.
* Level selection screen can now be controlled with only the keyboard or a gamepad.
* Added command line arguments for configuring resolution and window or fullscreen mode.
* Added collectables to the game.
* Made the sound and music options in the options menu a value instead of an on/off toggle.
* Added a new GUIObject for selecting a value inside a given range, GUISlider.
* Changing the sound or music in the options menu is now applied directly.
* Added command line options for configuring sound and music volume.
* Changed the addons menu to use a GUISingleLineListBox instead of three separate GUI?ObjectButtons.
* Fixed a bug where the music volume wasn't updated while adjusting it.
* Added caching support to GUIObjects, text is only rendered when changed or needed.
* Changing resolution or language doesn't require a restart any more.
* Fixed a bug where the chaching didn't update in GUISingleLineListBox.
* Fixed a bug where the player or shadow became immortal when standing on top of a moving block that moved through spikes.
* Added gravity and automatic width to the GUIObjectButton.
* Added resolution enumeration using SDL_ListModes(), filtering out resolutions smaller than the minimum (800x600).
* Fixed some bugs regarding the gravity parameter in the GUIObject which broke the GUISlider and GUIObjectCheckbox.
* Fixed some memory leaks when changing resolution.
* Added scaling support for themes to rescale instead of reloading the whole theme.
* The game window is now sizable.
* Fixed a bug in the leveleditor where the pressed mouse button was checked using event.type while not in handleEvent() but in logic().
* Removed some old copy code that could cause deletion of all levels in a levelpack.
* Fixed a memory bug when using openGL mode and resizing the window.
* Fixed the font size of single line list box and a memory leak in GUIObject.
* Fixed a memory leak in the MusicManager.
* Fixed a compile warning in the Main.cpp file regarding a translatable string.
* Updated the tutorial levelpack to include the new collectable.
* Fixed another memory leak in the MusicManager.
* Implemented a proper method for limiting the resizing of the window below 800x600 for Linux (X11) systems.
* Implemented a method for rearranging GUI elements upon resizing the window.
* Added a shell script to add the key names to the .pot file.
* Fixed a memory leak in font loading and window resizing.
* Added Compiling.txt file containing compiling instructions for Linux systems.
* Buttons in the options menu use a smaller font when there's not enough space.
* Fixed the constant invocation of onVideoResize() bug.
* Added a minimum window size limit (800x600) for Windows systems.
* Fixed a bug where the currentID would be incorrect after postLoad when there was a teleporter in the level which wasn't the last in the levelObjects vector with an id.
* Applied patch by worldcitizen, which fixes some compile issues when using gcc 4.7.
* Fixed a bug that Windows doesn't have stdint.h but source file tried to included it.
* Fixed a bug where key names weren't translated.
* Changed the notification block's message dialog size.
* Fixed Cloudscape as default theme.
* Fixed some issues with the rendering of the movingspeed text in the [[LevelEditor}leveleditor]].
* Cleaned up the Main.cpp, moving some initialisation stuff in the appropriate init method.
* Fixed an issue regarding arbitrary fullscreen resolutions.
* Made the help message for the command line untranslatable since the dictionary manager isn't and can't be loaded before showing it.
* Added a shortcut for toggling fullscreen (Alt+Enter).
* Fixed a bug where the user could restart the level while playing a recording.
* Cursor is now invisible during game-play, both in the game state and the play mode of the leveleditor.
* Changed the draw order of the player and the shadow, the player is now drawn last.
* Fixed translated time and recordings labels in the level select screen.
* Fixed a clipping issue with the knewave font.
* Added more music by Juho-Petteri Yliuntinen.
* Left clicking objects in the leveleditor with the configure tool will now show the properties dialog of that block, if any.
* Fixed some bugs with levelpack translations.
* Camera changes focus back to the player when the shadow dies.
* Fixed some issues with long strings in the level editor.
* Fixed some issues regarding resizing and GUIGravityCenter with GUILabels.
* Fixed a bug where the game stopped responding or gave a black screen when resizing the window with a dialog on top.
* Updated the Cloudscape theme with the new collectable made by Tedium.
* Added a sound for picking up collectables.
* Exit now has an open and a closed state.
* Updated collectable GUI to match Tedium's mockup
* Implemented GUIOverlays to solve the black background when resizing the window with a dialog on top.
* Fixed a bug with resizing in the leveleditor where the placement surface wasn't recreated.
* Fixed the enterLoop method of the GUIOverlay to also call the resize method of the parentState.
* Fixed the name convention of the GUIObjectRoot when using a GUIOverlay to improve readability of the code.
* The number of collectables collected in the HUD is now hidden in the leveleditor.
* Message boxes can now be closed by pressing escape, return or backspace.
* Fixed a bug where the player could shift in front of a moving block instead of getting squashed when standing on top of his shadow.
* Made the error messages in the Addons menu translatable.
* Fixed a bug where the configure dialog of switches and buttons didn't show the configured behaviour when using any language other than English.
* Fixed the .desktop file by removing a duplicate category, thanks to hasufell for pointing this out.
* Only the fonts are reloaded now when changing the language instead of reloading everything.
* Fixed the copyright notice at the top of each source file.
* Added the Credits file for the classic theme.
* Added an AUTHORS file, basically a copy of the wiki page Authors.
* Replaced the hit.wav and jump.wav files with sounds we know are free, made by odamite under CC0.
* Updated the credits file, there's now one central Credits.txt that contains all the licenses of the art used in meandmyshadow or pointers to that information.
* Added a license header to the source files in the tools folder.
* Removed the misc folder with the Empty.map.
* A new (empty) map is now created internally instead of loaded from an empty file.
* Changed the Name value in the .desktop file to match the name of the game with correct capitalisation.
* Changed the location the addons file is fetched from, the addons git repository instead of the project web.
* Implemented a Credits screen.
* Fixed bug where picked up collectables didn't save.
* The Credits menu is now filled with text from the files AUTHORS and Credits.txt.
* Added music credits to the credits screen.
* Fixed the Name field of the music files, there were no quites around the name which contained a space.
* Added horizontal scrollbar in the credits screen
* Fixed the graphics on a horizontal GUIScrollBar.
* Removed the Credits menu entry and added an icon to the lower right corner.
* Tried to fix a segfault in the LevelSelect screens when navigating with the keyboard.
* Added the translatable string credits and updated the translations by looking up the translation from other open source projects.
* Corrected the translation files' headers.
* Updated the credits icon.
* Updated the headers of the levelpack translations.
* Added a ChangeLog file.
Translations added:
* Russian translations for the game, default, tutorial and classic levelpack by KroArtem.
* Italian translations for the game, default, tutorial and classic levelpack by BioHazardX.
* Finnish translations for the game, default, tutorial and classic levelpack by odamite.
* Simplified Chinese for the game, default, tutorial and classic levelpack by acme_pjz.
* Traditional Chines for the game by ming.yan2.
* German translations for the game and tutorial levelpack by Wuzzy.
* Dutch translation for the game by Tedium.
Me and My Shadow V0.3
------------------------
* An input manager was added to allow the configuration of key bindings.
* The format of the progress files of levelpacks was changed to the POA format.
* Added a teleport option in the level editor to make testing easier, default key binding is F5.
* Fixed a bug where non-latin file and path names caused unexpected behaviour under Windows.
* The menu and GUI theme was changed to fit with the new default theme Cloudscape matching the mock-ups by odamite. (link)
* The name of the 14th level of the classic levelpack changed from 'Damn' to 'Headache'.
* Extension were automatically added to file names in save dialogs if not present.
* Separate levels can be played again through a special levelpack named Levels
* The shortcut Ctrl+s was removed which toggled the sound and music on and off.
* Save dialogs can now start with an empty filename field.
* Two level statistics where added: time and recordings.
* Medals can be earned by beating a set target time and recordings.
* Level names of levels inside a levelpack are now retrieved from the level file itself instead of the levelpack file.
* The game now recorded user input to be able to replay it later on.
* A carrot was added to the GUITextBox to allow easier editing.
* Joystick support has been added to the InputManager.
* MD5sum are used to link replays and statistics to levels.
* The CMakeLists.txt was updated to include openssl and crypto.
* Fixed a bug where the level statistics were always updated, now the best stays.
* The best time and best number of recordings replays are auto-saved.
* Level selection blocks updated to match the Cloudscape theme.
* Added animation for the arrows of the GUISingleLineListBox.
* All key bindings can now have a primary and alternative key.
* GUITextBox and GUITextArea now handle delete and backspace properly.
* A section at the bottom of the LevelSelect screen was added to show level and level statistic information.
* A method was made for drawing so named GUIBoxes.
* Target time and recordings can be configured in the leveleditor.
* Separate the up and jump key and the down and action keys in the input manager.
* Removed the non-free music that was there from the initial release.
* Replays are shown after completing a level.
* The help menu got removed and the entry in the main menu was replaced with the addons menu.
* The clear progress option was moved to the options menu.
* Added a music manager to add support for multiple music tracks.
* Sound and music is now separated in the options menu.
* A message box shows instead of a label to when a certain changes requires the user to restart the game.
* A bug was fixed in the md5 calculation of the TreeStorageNode.
* Changed the drawGUIBox to not use rounded rectangles to support older versions of SDL_gfx.
* Fixed a bug where an extension was added to a file dialog that was used for folders.
* Fixed a bug regarding the player holding the shadow whilst on a moving block.
* Added a LevelEditSelect screen to replace the old levelpackeditor.
* Target times and recordings added for the classic levelpack thanks to Tedium.
* Fixed a bug where the player could continue recording after he died.
* Menu theme music added, made by vaev (Juho-Petteri Yliuntinen).
* Extended the MusicManager to support a separate loop file as alternative to a loop start time.
* Added icons to the tooltips in the LevelSelect screen.
* Changing block type in the level editor is now a separate key binding.
* Added an interlevel popup to show the target time and recordings also shows the achieved medal.
* Made Me and My Shadow as XDG-compliant as possible by saving user data in ~/.local/share/ and config files in ~/.config/.
* Notifications aren't shown when the inter level popup is up.
* Fixed a bug where an empty levelpack could crash the game.
* Fixed the bug where the replay button of last level doesn't show up.
* Changed the way notification blocks are displayed, there's no popup any more, but a GUIBox at the bottom of the screen.
* Fixed a bug regarding the leveleditor crashing because of dangling pointer objNotificationBlock.
* Updated the Cloudscape theme made by Tedium.
* Changed colour of the '&'-sign in logo to match the updated background image.
* Fixed selection overlapping in the GUIListBox.
* Both the player and shadow can now get squashed when between a solid block and a moving block.
* Updated the Controls.txt to include all the (new) keybindings.
* Made it possible to configure the starting state of fragile blocks.
* Added check to prevent overwriting levels using the LevelEditSelect screen.
* Added notification for when the shadow dies.
* Updated the icons to match the latest Cloudscape version.
Me and My Shadow V0.2
------------------------
* The GUIScrollBar was added and used in the LevelSelect screen when there are too many levels to fit on the screen.
* The GUIListBox control was added and used in filedialogs.
* Support for levelpacks was added.
* An option was added to the LevelSelect screen to play custom levels made in the editor.
* Added a levelpack editor to the leveleditor.
* Added an options menu, with this came the settings file.
* A theme manager was added to support theming.
* The screen gets dimmed when a GUI is opened.
* Some improvements to the POAParser.
* The help menu graphics where updated by removing the dots in the background.
* Added an addon manager to allow downloadable themes, levelpacks and levels
* The data folder was structured more by separating levels from levelpacks and by adding a separate folder for themes.
* Libarchive became a dependency of Me and My Shadow because it is used in the Addons menu.
* The code underwent massive refactoring and documenting to match a set of code conventions.
* Bug fixed where the player or shadow could teleport by restarting a level whilst touching a moving block.
* The notification block was added to the game.
* Fixed a bug where the player could jump on a fragile block that was destroyed if the jump was timed correctly.
* An internet proxy option was added.
* The |leveleditor got a massive overhaul, basically being built up from scratch.
* Primitive drawing methods where added to the Functions.cpp file.
* Focus support was added to the GUIObjectTextBox.
* A [[GUITextArea] was added to support multiline text input.
* User created content was separated from main and addon content.
* A congratulation text was added when finishing a levelpack.
* Fixed a swap bug, causing the shadow the sink in the floor.
* The tutorial levelpack was added.
* The original levelpack was renamed to classic.
* The drawing of primitives was handed over to SDL_gfx
* A help screen system was introduced that consisted out of multiple slides explaining the certain aspects of the game.
* An icon indicating the recording status was added to the upper left corner of the screen.
* The tab key allows the player to switch the camera focus between the player and the shadow.
* Both the player and the shadow can be themed using the same system as blocks.
* Resetting doesn't reset the saved state any more, allowing the player to reload a checkpoint after resetting (by accident).
* A new default levelpack was added containing levels ranging from easy to medium difficulty.
* Jump and fall animation support was added.
* The Theme:Cloudscape became the default theme, the default theme is renamed to classic just like the levelpack.
* Tooltips where added to the toolbar in the leveleditor.
* An icon for the Windows build was added.
* CMake modules where bundled to make packaging easier for systems missing these modules.
* The order in which the blocks appear in the leveleditor have been changed, instead of using the order they appear internally.
* Some compiler warnings fixed, adding newlines to the end of each source file for example.
* Fixed a problem with older version of libarchive.
* Added a separate update button to the addons menu so that a user can uninstall an addon without being forced to update it first.
* Fixed a bug where the program wouldn't quit when in the leveleditor.
* The up and down arrow keys can now be used to navigate through the main menu.
Me and My Shadow V0.1.2
------------------------
* The POAParser was updated to handle non-existing files better.
* Some fixes were made to prevent a crash under Linux.
* Command line arguments added to change config and data paths.
* Automatic data path detection was added.
* Missing background music changed from an error to a warning.
* .desktop file and icon added.
* Tooltip added to levelblocks in the LevelSelect screen to show the level's name.
Me and My Shadow V0.1.1
------------------------
* The TitleMenu has been removed.
* The transition between states has been changed to a fade transition.
* The code was refactored (source files in src/ folder and header files per class)
* The background of both the menu and the game have been changed to remove the spots.
* The movement system has changed, in V0.1 the player would always record.
* Data files rearranged.
* Improved the blocks graphics using the Gem Jewel Diamond Glass set by Ville Seppanen <http://opengameart.org/content/gem-jewel-diamond-glass>.
* The leveleditor had been integrated in the game instead of being a separate program.
* Saving/loading has been implemented (used for checkpoints).
* CMake is now used.
* Transparency support for gfx.
* Checkpoints have been added.
* Menu for the leveleditor was made.
* The ImageManager has been added to prevent loading the same image twice.
* Swap block has been added.
* Fragile block has been added.
* New levelformat.
* Moving blocks and spikes have been added.
* Portal, Switch and Button added.
* Custom image support for blocks (never used and remove in MeAndMyShadow 0.3).
* Conveyor Belt added.
\ No newline at end of file
diff --git a/data/levelpacks/classic/locale/ru.po b/data/levelpacks/classic/locale/ru.po
index 47cdf9e..7e78d8c 100644
--- a/data/levelpacks/classic/locale/ru.po
+++ b/data/levelpacks/classic/locale/ru.po
@@ -1,126 +1,126 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-04-01 17:56+0300\n"
"PO-Revision-Date: 2018-09-29 21:34+0000\n"
"Last-Translator: mesnevi <shams@airpost.net>\n"
"Language-Team: Russian <https://hosted.weblate.org/projects/me-and-my-shadow/"
"levels-classic/ru/>\n"
"Language: ru\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
"n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || "
"(n%100>=11 && n%100<=14)? 2 : 3);\n"
"X-Generator: Weblate 3.2-dev\n"
#: classic\Tower.map:1
msgid "Tower"
msgstr "Башня"
#: classic\Credits.map:1
msgid "Credits"
msgstr "Благодарности"
#: classic\Lab.map:1
msgid "Lab"
msgstr "Лаборатория"
#: classic\Shadow.map:1
msgid "Shadow"
msgstr "Тень"
#: classic\ShadowBlocks.map:1
msgid "ShadowBlocks"
msgstr "Блоки для тени"
#: classic\levels.lst:1
msgid "classic"
-msgstr "классический"
+msgstr "Классический"
#: classic\Timing.map:1
msgid "Timing"
msgstr "На время"
#: classic\FreeFall.map:1
msgid "FreeFall"
msgstr "Свободное падение"
#: classic\SomeSpikes.map:1
msgid "SomeSpikes"
msgstr "Немножко шипов"
#: classic\BabySteps.map:1
msgid "BabySteps"
msgstr "Первые шаги"
#: classic\Tricky.map:1
msgid "Tricky"
msgstr "С подвохом"
#: classic\Road.map:1
msgid "Road"
msgstr "Дорога"
#: classic\Jumper.map:1
msgid "Jumper"
msgstr "Прыгун"
#: classic\FirstSpikes.map:1
msgid "FirstSpikes"
msgstr "Первые шипы"
#: classic\Jumping.map:1
msgid "Jumping"
msgstr "Прыг-скок"
#: classic\levels.lst:2
msgid "Default level pack"
msgstr "Набор уровней по умолчанию"
#: classic\LittleHelp.map:1
msgid "LittleHelp"
msgstr "Мало пользы"
#: classic\End.map:1
msgid "End"
msgstr "Конец"
#: classic\FreeFall2.map:1
msgid "FreeFall2"
msgstr "Свободное падение-2"
#: classic\Control.map:1
msgid "Control"
msgstr "Контроль"
#: classic\UpDown.map:1
msgid "UpDown"
msgstr "Вверх-вниз"
#: classic\Spiky.map:1
msgid "Spiky"
msgstr "Шипастый"
#: classic\Here.map:1
msgid "Here"
msgstr "Здесь"
#: classic\Carry.map:1
msgid "Carry"
msgstr "Ноша"
#: classic\LeftRight.map:1
msgid "LeftRight"
msgstr "Влево-вправо"
#: classic\Headache.map:1
msgid "Headache"
msgstr "Неприятность"
diff --git a/data/levelpacks/classic/locale/uk.po b/data/levelpacks/classic/locale/uk.po
index b1651de..893f0d0 100644
--- a/data/levelpacks/classic/locale/uk.po
+++ b/data/levelpacks/classic/locale/uk.po
@@ -1,125 +1,125 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-04-01 17:56+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Jz Pan <acme.pjz@gmail.com>, 2018\n"
"Language-Team: Ukrainian (https://www.transifex.com/acmepjz/teams/88148/uk/)\n"
"Language: uk\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n"
"%100>=11 && n%100<=14)? 2 : 3);\n"
#: classic\Tower.map:1
msgid "Tower"
msgstr "Вежа"
#: classic\Credits.map:1
msgid "Credits"
msgstr "Подяки"
#: classic\Lab.map:1
msgid "Lab"
msgstr "Лабораторія"
#: classic\Shadow.map:1
msgid "Shadow"
msgstr "Тінь"
#: classic\ShadowBlocks.map:1
msgid "ShadowBlocks"
msgstr "Блоки для тіні"
#: classic\levels.lst:1
msgid "classic"
-msgstr "класика"
+msgstr "Класичний"
#: classic\Timing.map:1
msgid "Timing"
msgstr "На швидкість"
#: classic\FreeFall.map:1
msgid "FreeFall"
msgstr "Вільне падіння"
#: classic\SomeSpikes.map:1
msgid "SomeSpikes"
msgstr "Трохи шипів"
#: classic\BabySteps.map:1
msgid "BabySteps"
msgstr "Перші кроки"
#: classic\Tricky.map:1
msgid "Tricky"
msgstr "Хитромудрий"
#: classic\Road.map:1
msgid "Road"
msgstr "Шлях"
#: classic\Jumper.map:1
msgid "Jumper"
msgstr "Стрибунець"
#: classic\FirstSpikes.map:1
msgid "FirstSpikes"
msgstr "Перші шипи"
#: classic\Jumping.map:1
msgid "Jumping"
msgstr "Стрибки"
#: classic\levels.lst:2
msgid "Default level pack"
msgstr "Звичайна збірка рівнів"
#: classic\LittleHelp.map:1
msgid "LittleHelp"
msgstr "Трохи допомоги"
#: classic\End.map:1
msgid "End"
msgstr "Кінець"
#: classic\FreeFall2.map:1
msgid "FreeFall2"
msgstr "Вільне падіння - 2"
#: classic\Control.map:1
msgid "Control"
msgstr "Керування"
#: classic\UpDown.map:1
msgid "UpDown"
msgstr "Вгору-вниз"
#: classic\Spiky.map:1
msgid "Spiky"
msgstr "Шипастий"
#: classic\Here.map:1
msgid "Here"
msgstr "Тут"
#: classic\Carry.map:1
msgid "Carry"
msgstr "Носій"
#: classic\LeftRight.map:1
msgid "LeftRight"
msgstr "Ліворуч-праворуч"
#: classic\Headache.map:1
msgid "Headache"
msgstr "Головний біль"
diff --git a/data/levelpacks/default/locale/ru.po b/data/levelpacks/default/locale/ru.po
index a671a83..a180656 100644
--- a/data/levelpacks/default/locale/ru.po
+++ b/data/levelpacks/default/locale/ru.po
@@ -1,106 +1,106 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-04-01 17:56+0300\n"
"PO-Revision-Date: 2018-09-29 21:34+0000\n"
"Last-Translator: mesnevi <shams@airpost.net>\n"
"Language-Team: Russian <https://hosted.weblate.org/projects/me-and-my-shadow/"
"levels-default/ru/>\n"
"Language: ru\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
"n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || "
"(n%100>=11 && n%100<=14)? 2 : 3);\n"
"X-Generator: Weblate 3.2-dev\n"
#: default\Regroup.map:1
msgid "Regroup"
msgstr "Перестройка"
#: default\3.map:1
msgid "Running in the Sky"
msgstr "Беги по небу"
#: default\4.map:1
msgid "Both Up and Down"
msgstr "И вверх, и вниз"
#: default\map02.map:1
msgid "Snail"
msgstr "Улитка"
#: default\Towers.map:1
msgid "Towers"
msgstr "Башни"
#: default\map01.map:1
msgid "Simple"
msgstr "Раз плюнуть"
#: default\map04.map:1
msgid "Double trouble"
msgstr "Дважды в дураках"
#: default\levels.lst:1
msgid "default"
-msgstr "стандартный"
+msgstr "Стандартный"
#: default\Skyscrapers.map:1
msgid "Skyscrapers"
msgstr "Небоскрёбы"
#: default\QuickSwap.map:1
msgid "Quick swap"
msgstr "Мигом"
#: default\5.map:1
msgid "stopping the spikes"
msgstr "Шипам — нет"
#: default\levels.lst:2
msgid "Default"
msgstr "Стандартный"
#: default\Remote.map:1
msgid "Remote control"
msgstr "Дистанционное управление"
#: default\map03.map:1
msgid "Spiky travel"
msgstr "Прогулки по шипам"
#: default\2.map:1
msgid "Tricky Jumping"
msgstr "Хитрое прыганье"
#: default\1.map:1
msgid "Building Teamwork"
msgstr "Построй команду"
#: default\Timing.map:1
msgid "Timing"
msgstr "На время"
#: default\Volcano.map:1
msgid "Volcano"
msgstr "Вулкан"
#: default\Sweeper.map:1
msgid "Sweeper"
msgstr "Дворник"
#: default\Switches.map:1
msgid "Switches"
msgstr "Выключатели"
#: default\map05.map:1
msgid "Wall breaking"
msgstr "Ломая стены"
diff --git a/data/levelpacks/default/locale/uk.po b/data/levelpacks/default/locale/uk.po
index 216bf29..87704a7 100644
--- a/data/levelpacks/default/locale/uk.po
+++ b/data/levelpacks/default/locale/uk.po
@@ -1,105 +1,105 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-04-01 17:56+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Jz Pan <acme.pjz@gmail.com>, 2018\n"
"Language-Team: Ukrainian (https://www.transifex.com/acmepjz/teams/88148/uk/)\n"
"Language: uk\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n"
"%100>=11 && n%100<=14)? 2 : 3);\n"
#: default\Regroup.map:1
msgid "Regroup"
msgstr "Перегрупування"
#: default\3.map:1
msgid "Running in the Sky"
msgstr "Небесні мандри"
#: default\4.map:1
msgid "Both Up and Down"
msgstr "І вгору, і вниз"
#: default\map02.map:1
msgid "Snail"
msgstr "Равлик"
#: default\Towers.map:1
msgid "Towers"
msgstr "Вежі"
#: default\map01.map:1
msgid "Simple"
msgstr "Просто"
#: default\map04.map:1
msgid "Double trouble"
msgstr "Подвійні проблеми"
#: default\levels.lst:1
msgid "default"
-msgstr "звичайний"
+msgstr "Звичайний"
#: default\Skyscrapers.map:1
msgid "Skyscrapers"
msgstr "Хмарочоси"
#: default\QuickSwap.map:1
msgid "Quick swap"
msgstr "Швидка зміна"
#: default\5.map:1
msgid "stopping the spikes"
msgstr "зупиняючи шипи"
#: default\levels.lst:2
msgid "Default"
msgstr "Звичайний"
#: default\Remote.map:1
msgid "Remote control"
msgstr "Дистанційне керування"
#: default\map03.map:1
msgid "Spiky travel"
msgstr "Мандрівка шипами"
#: default\2.map:1
msgid "Tricky Jumping"
msgstr "Стрибки ізпідвипідвертом"
#: default\1.map:1
msgid "Building Teamwork"
-msgstr "Побудова командної роботи"
+msgstr "Командна робота"
#: default\Timing.map:1
msgid "Timing"
msgstr "На швидкість"
#: default\Volcano.map:1
msgid "Volcano"
msgstr "Вулкан"
#: default\Sweeper.map:1
msgid "Sweeper"
msgstr "Прибиральник"
#: default\Switches.map:1
msgid "Switches"
msgstr "Вимикачі"
#: default\map05.map:1
msgid "Wall breaking"
msgstr "Ламаючи стіну"
diff --git a/data/levelpacks/tutorial/locale/ru.po b/data/levelpacks/tutorial/locale/ru.po
index 3404bea..8038eb9 100644
--- a/data/levelpacks/tutorial/locale/ru.po
+++ b/data/levelpacks/tutorial/locale/ru.po
@@ -1,478 +1,478 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-04-01 17:56+0300\n"
"PO-Revision-Date: 2018-09-29 22:36+0000\n"
"Last-Translator: mesnevi <shams@airpost.net>\n"
"Language-Team: Russian <https://hosted.weblate.org/projects/me-and-my-shadow/"
"levels-tut/ru/>\n"
"Language: ru\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
"n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || "
"(n%100>=11 && n%100<=14)? 2 : 3);\n"
"X-Generator: Weblate 3.2-dev\n"
#: tutorial\tut12.map:17
msgid "Now you'll need to help your shadow cross.\n"
msgstr "Теперь необходимо помочь тени перебраться на другую сторону.\n"
#: tutorial\tut10.map:19
msgid ""
"You can save your progress in a level with\n"
"checkpoints. You can restore them at any\n"
"time using the F3 button."
msgstr ""
"Прогресс на уровне можно сохранять с помощью\n"
"чекпоинтов. Чтобы начать сначала,\n"
"следует нажать клавишу F3."
#: tutorial\tut18.map:14
msgid ""
"This trigger will deactivate the moving block.\n"
"Try to stop it at the right moment.\n"
"You can only do this once, so if it fails you'll\n"
"have to reset the level with the 'R' key."
msgstr ""
"Этот триггер деактивирует движущийся блок.\n"
"Необходимо остановить его в подходящий момент.\n"
"Это можно сделать только один раз, поэтому если\n"
"не получится - придётся перезапустить уровень с помощью клавиши 'R'."
#: tutorial\tut21.map:49
msgid ""
"If your shadow falls down here you will have to restart.\n"
"Press 'R' to restart the level."
msgstr ""
"Если тень упадёт, придётся начать уровень сначала\n"
"с помощью клавиши 'R'."
#: tutorial\levels.lst:1
msgid "tutorial"
-msgstr "обучение"
+msgstr "Обучение"
#: tutorial\tut23.map:1
msgid "Collecting Keys"
msgstr "Собери ключи"
#: tutorial\tut10.map:46
msgid "You've chosen the right way."
msgstr "Правильным путём идёте, товарищи."
#: tutorial\tut22.map:1
msgid "Shadow swap"
msgstr "Поменяться с тенью"
#: tutorial\tut20.map:187
msgid ""
"A dead end, you'd better go back and choose\n"
"the other portal."
msgstr ""
"Здесь тупик, следует вернуться назад и выбрать\n"
"другой портал."
#: tutorial\tut03.map:13
msgid ""
"See those gaps over there?\n"
"Reach the finish without falling."
msgstr ""
"Впереди - пропасти.\n"
"Нужно добраться до финиша, не упав."
#: tutorial\tut07.map:33
msgid ""
"If your shadow dies you'll have to restart.\n"
"Restart the game by pressing the 'R' key."
msgstr ""
"Если тень умрёт, уровень придётся начать сначала\n"
"с помощью клавиши 'R'."
#: tutorial\tut02.map:18
msgid ""
"You can jump using the up key.\n"
"Try jumping over these blocks."
msgstr ""
"Придётся перепрыгнуть через эти блоки.\n"
"Прыгать можно с помощью клавиши 'вверх'."
#: tutorial\tut07.map:1
msgid "Shadow challenge"
msgstr "Испытание тенью"
#: tutorial\tut20.map:1
msgid "Portal mayhem"
msgstr "Суматоха с порталами"
#: tutorial\tut02.map:1
msgid "First jumps"
msgstr "Первые прыжки"
#: tutorial\tut20.map:16
msgid ""
"Portals point to another portal or to nothing.\n"
"Try to reach the exit in this portal mayhem."
msgstr ""
"Порталы ведут в другой портал (или на пустое место).\n"
"Придётся пробираться к выходу через эти дебри."
#: tutorial\tut05.map:32
msgid ""
"TIP:\n"
"Think what moves your shadow has to make.\n"
"Then let your character record those moves.\n"
"You can break it down into smaller recordings."
msgstr ""
"Подсказка:\n"
"Следует спланировать действия для тени,\n"
"а затем записать эти движения.\n"
"Можно разбить большую запись на несколько записей поменьше."
#: tutorial\tut11.map:17
msgid ""
"Until now the levels were static.\n"
"There are however moving blocks."
msgstr ""
"До сих пор все уровни были статичными.\n"
"Впрочем, существуют и подвижные блоки."
#: tutorial\tut10.map:32
msgid "Save your progress here."
msgstr "Здесь можно сохранить свой прогресс."
#: tutorial\tut13.map:1
msgid "Moving spikes"
msgstr "Шипы перемещаются"
#: tutorial\tut13.map:18
msgid "Watch out for the moving spikes."
-msgstr "Остерегайся движущихся шипов."
+msgstr "Берегись подвижных шипов!"
#: tutorial\tut16.map:1
msgid "The switch"
msgstr "Выключатель"
#: tutorial\tut25.map:13
msgid "The very best of luck!"
msgstr "Удачи!"
#: tutorial\tut20.map:156
msgid "Now choose one of the two."
-msgstr "Одно из двух."
+msgstr "А теперь придётся выбрать один из двух."
#: tutorial\tut19.map:42
msgid ""
"NOTE:\n"
"You can go back by entering this portal.\n"
"It is however a bit different, you don't have to\n"
"press the down key, it will activate when you walk in it."
msgstr ""
"КСТАТИ:\n"
"Зайдя в этот портал, можно вернуться обратно.\n"
-"Он устроен по-другому: нажимать на клавишу 'вниз' не надо.\n"
-"Он сработает, когда персонаж зайдёт в него."
+"Этот портал работает автоматически:\n"
+"он сработает, когда персонаж зайдёт в него."
#: tutorial\tut15.map:20
msgid ""
"This gap is impossible to jump over.\n"
"Step on the button next of you."
msgstr ""
"Через этот провал нельзя перепрыгнуть.\n"
"Попробуйте наступить на кнопку рядом."
#: tutorial\tut06.map:1
msgid "Shadow walk"
msgstr "Прогулка с тенью"
#: tutorial\tut10.map:54
msgid ""
"This is the wrong way.\n"
"Go back to the previous checkpoint by pressing F3."
msgstr ""
"Прохода нет!\n"
"Придётся вернуться предыдущему чекпоинту, нажав клавишу F3."
#: tutorial\tut25.map:318
msgid "You have made it!"
msgstr "Получилось!"
#: tutorial\tut17.map:1
msgid "Toggle trigger"
msgstr "Включай, запускай"
#: tutorial\tut24.map:1
msgid "Warning"
msgstr "Внимание"
#: tutorial\tut05.map:1
msgid "Shadow"
msgstr "Тень"
#: tutorial\tut06.map:23
msgid ""
"NOTE:\n"
"Although you can't jump on those blocks\n"
"you can record the jumps for your shadow."
msgstr ""
-"КСТАТИ:\n"
+"ЗАМЕТКА:\n"
"Хоть на эти блоки и невозможно запрыгнуть,\n"
"эти прыжки можно записать для тени."
#: tutorial\tut19.map:39
msgid ""
"Now it's time to check out the portals.\n"
"To get to the exit you'll have to take the portal.\n"
"Walk to it and press the down arrow to\n"
"activate."
msgstr ""
"Теперь время взглянуть на порталы.\n"
"Чтобы добраться до выхода,\n"
"придётся пройти через портал.\n"
"Они активируются с помощью клавиши 'вниз'."
#: tutorial\tut18.map:1
msgid "Stop trigger"
-msgstr "Помешай запуску"
+msgstr "Стоп в нужный момент"
#: tutorial\tut01.map:1
msgid "Walk in the park"
msgstr "Прогулка по парку"
#: tutorial\tut09.map:14
msgid ""
"Those blocks are fragile.\n"
"If you step on them too often they'll break."
msgstr ""
"Эти блоки хрупкие.\n"
"Если на них часто наступать, они разрушатся."
#: tutorial\tut19.map:1
msgid "First portals"
msgstr "Первые порталы"
#: tutorial\tut25.map:1
msgid "Final"
msgstr "Финишная прямая"
#: tutorial\tut04.map:1
msgid "First spikes"
msgstr "Первые шипы"
#: tutorial\tut12.map:1
msgid "Moving shadow blocks"
msgstr "Движущиеся блоки для тени"
#: tutorial\tut22.map:22
msgid ""
"You need your shadow to reach the exit.\n"
"Make use of the swapper to get him down (or \n"
"to get yourself down)."
msgstr ""
-"Нужно, чтобы тень добралась до выхода.\n"
-"Поменяйтесь местами, чтобы спустить тень вниз\n"
+"Без помощи тени не выйдет добраться до выхода.\n"
+"Поменяйтесь местами, чтобы спустить её вниз\n"
"(или спустить вниз игрока)."
#: tutorial\tut21.map:8
msgid ""
"Now it's time for something completely\n"
"different: swappoints. When you or your\n"
"shadow activate them you'll swap places."
msgstr ""
-"А теперь время для чего-то совершенно\n"
-"нового: точки перестановки. Если игрок или\n"
+"А теперь время для кое-чего новенького:\n"
+"точки перестановки. Если игрок или\n"
"тень активируют их, они поменяются местами."
#: tutorial\tut06.map:27
msgid ""
"Only your shadow can stand on those shadow\n"
"blocks. Try to get him up there."
msgstr ""
"Только тень может стоять на этих блоках.\n"
"Попробуйте взобраться на них тенью."
#: tutorial\tut17.map:14
msgid ""
"You've only seen triggers that activate other\n"
"blocks, but they can also deactivate or toggle\n"
"them."
msgstr ""
"Мы уже познакомились с триггерами, которые\n"
"активируют другие блоки, но они также могут\n"
"деактивировать или переключать их."
#: tutorial\tut14.map:68
msgid ""
"When standing on conveyor belts you'll\n"
"move without walking."
msgstr ""
"Конвеер постоянно перемещает всё,\n"
"что на нём находится."
#: tutorial\tut25.map:46
msgid ""
"TIP:\n"
"Try to get your shadow in front of the shadow\n"
"wall. If he falls down you'd better restart."
msgstr ""
"Подсказка:\n"
"Тенью необходимо стать перед стеной для тени.\n"
"Если тень упадёт, придётся начать сначала."
#: tutorial\tut22.map:33
msgid ""
"TIP:\n"
"When your shadow is trapped stand on the\n"
"right side of the shadow blocks. Now record \n"
"the down key and let your shadow mimic."
msgstr ""
"Подсказка:\n"
"Когда тень будет в ловушке, нужно стать справа\n"
"от блоков для тени, начать запись, нажать\n"
"клавишу 'вниз' и пусть тень повторит действия."
#: tutorial\tut08.map:1
msgid "Teamwork"
msgstr "Мы — команда"
#: tutorial\tut14.map:71
msgid ""
"Let the shadow finish the level by walking to\n"
"the finish. But don't stand still because your\n"
"shadow will move all the way back."
msgstr ""
"Пусть тень пройдёт уровень, добравшись до финиша.\n"
"Но стоять на месте тоже нельзя, потому что тень\n"
"будет смещаться назад на конвейере."
#: tutorial\tut21.map:1
msgid "Swappoints"
msgstr "Точки перестановки"
#: tutorial\tut23.map:18
msgid ""
"One thing you need to know before you're ready are keys.\n"
"Sometimes there are keys spread around the level.\n"
"The exit is locked until you get all the keys."
msgstr ""
"Ещё одна вещь перед тем, как закончить: ключи.\n"
"Иногда они распределены по всему уровню.\n"
"Выход закрыт до тех пор, пока не получится собрать все ключи."
#: tutorial\tut03.map:34
msgid "Good job!"
-msgstr "Молодец!"
+msgstr "Получилось!"
#: tutorial\tut16.map:14
msgid ""
"There's another type of trigger: the switch.\n"
"Use the switch to activate the elevator so that you\n"
"can reach the exit."
msgstr ""
"Есть ещё один вид триггера: переключатель.\n"
"Этот переключатель активирует подъёмник,\n"
"который поможет добраться до выхода."
#: tutorial\tut09.map:1
msgid "Fragile"
msgstr "Хрупкие блоки"
#: tutorial\tut24.map:18
msgid ""
"That's all there is.\n"
"Now it's time to put your skills to the test.\n"
"Enter the exit to go to the last level.\n"
"Good luck!"
msgstr ""
"Вот и всё.\n"
"Настало время проверить полученные навыки.\n"
"Нужно добраться до выхода, чтобы перейти на последний уровень.\n"
"Удачи!"
#: tutorial\tut25.map:459
msgid "Where could your shadow be?"
msgstr "Где же тень?"
#: tutorial\tut01.map:18
msgid ""
"Welcome to Me and My Shadow.\n"
"You can use the arrow keys to walk to the exit.\n"
"\n"
"Good luck!"
msgstr ""
-"Добро пожаловать в игру \"Me and My Shadow\".\n"
-"Используя стрелки для перемещения, необходимо до выхода.\n"
+"Добро пожаловать в игру \"Me and My Shadow\"!\n"
+"Используя стрелки для перемещения, необходимо дойти до выхода.\n"
"\n"
"Удачи!"
#: tutorial\tut15.map:1
msgid "Triggering"
msgstr "Триггер"
#: tutorial\tut03.map:1
msgid "Jumping around"
msgstr "Прыгая тут и там"
#: tutorial\tut10.map:1
msgid "Checkpoints"
msgstr "Чекпоинты"
#: tutorial\tut07.map:19
msgid ""
"Spikes are not only deadly for you,\n"
"but also for your shadow."
msgstr ""
"Шипы смертельны не только для игрока,\n"
"но и для тени."
#: tutorial\tut08.map:21
msgid ""
"You and your shadow need to work together.\n"
"Move your shadow towards the wall and jump\n"
"on him so that you can jump over the wall."
msgstr ""
"Игроку и тени надо работать сообща.\n"
"Нужно поставить тень около стены и запрыгнуть\n"
"на неё, чтобы перепрыгнуть через стену."
#: tutorial\tut04.map:19
msgid ""
"Spikes are deadly.\n"
"Don't touch them!"
msgstr ""
"Шипы смертельно опасны.\n"
-"Не прикасайся к ним!"
+"К ним нельзя прикасаться!"
#: tutorial\levels.lst:3
msgid "Step by step introduction"
msgstr "Пошаговое введение"
#: tutorial\tut11.map:1
msgid "Moving blocks"
msgstr "Движущиеся блоки"
#: tutorial\tut14.map:1
msgid "Conveyor madness"
msgstr "С ума сойти: конвейеры"
#: tutorial\tut05.map:29
msgid ""
"You can't reach the exit, but your shadow can.\n"
"Press space to record your moves.\n"
"Press space once again to let your shadow\n"
"mimic your recording."
msgstr ""
"Игрок не может добраться до выхода, а тень может.\n"
"Нажатие клавиши 'пробел' начнёт запись движений.\n"
"Повторное нажатие клавиши 'пробел' запустит\n"
"воспроизведение записи тенью."
#: tutorial\levels.lst:2
msgid "You have finished the tutorial!"
msgstr "Обучение завершено!"
diff --git a/data/levelpacks/tutorial/locale/uk.po b/data/levelpacks/tutorial/locale/uk.po
index 7cff3ae..4b77f22 100644
--- a/data/levelpacks/tutorial/locale/uk.po
+++ b/data/levelpacks/tutorial/locale/uk.po
@@ -1,477 +1,477 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-04-01 17:56+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Jz Pan <acme.pjz@gmail.com>, 2018\n"
"Language-Team: Ukrainian (https://www.transifex.com/acmepjz/teams/88148/uk/)\n"
"Language: uk\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n"
"%100>=11 && n%100<=14)? 2 : 3);\n"
#: tutorial\tut12.map:17
msgid "Now you'll need to help your shadow cross.\n"
msgstr "Тепер треба допомогти тіні пройти перешкоди."
#: tutorial\tut10.map:19
msgid ""
"You can save your progress in a level with\n"
"checkpoints. You can restore them at any\n"
"time using the F3 button."
msgstr ""
-"Можна зберегти прогрес рівня за допомогою\n"
-"чекпоінтів. Можна завантажити гру у будь-який\n"
+"Прогрес рівня можна зберегти за допомогою\n"
+"чекпоінтів. Гру можна завантажити у будь-який\n"
"момент, натиснувши клавішу F3."
#: tutorial\tut18.map:14
msgid ""
"This trigger will deactivate the moving block.\n"
"Try to stop it at the right moment.\n"
"You can only do this once, so if it fails you'll\n"
"have to reset the level with the 'R' key."
msgstr ""
"Цей вимикач деактивує рухомий блок.\n"
-"Спробуй зупинити його у потрібний момент.\n"
+"Необхідно зупинити його у влучний момент.\n"
"Увімкнути вимикач можливо лише один раз, тож, якщо не\n"
-"вийде, то доведеться перезапустити рівень за допомогою клавіші 'R'."
+"вийде, доведеться перезапустити рівень за допомогою клавіші 'R'."
#: tutorial\tut21.map:49
msgid ""
"If your shadow falls down here you will have to restart.\n"
"Press 'R' to restart the level."
msgstr ""
"Якщо тінь провалиться тут, доведеться проходити рівень знову.\n"
"Для цього треба натиснути клавішу 'R'."
#: tutorial\levels.lst:1
msgid "tutorial"
-msgstr "навчання"
+msgstr "Навчальний"
#: tutorial\tut23.map:1
msgid "Collecting Keys"
msgstr "Ключі"
#: tutorial\tut10.map:46
msgid "You've chosen the right way."
msgstr "Це є вірний шлях."
#: tutorial\tut22.map:1
msgid "Shadow swap"
-msgstr "Поміняйся із тінню"
+msgstr "Помінятися із тінню"
#: tutorial\tut20.map:187
msgid ""
"A dead end, you'd better go back and choose\n"
"the other portal."
msgstr ""
"Це глухий кут. Треба вернутися назад і обрати\n"
"інший портал."
#: tutorial\tut03.map:13
msgid ""
"See those gaps over there?\n"
"Reach the finish without falling."
msgstr ""
-"Бачиш ці провали попереду?\n"
-"Досягни фінішу і не впади."
+"Попереду - прірва.\n"
+"Треба досягнути фінішу, не впавши."
#: tutorial\tut07.map:33
msgid ""
"If your shadow dies you'll have to restart.\n"
"Restart the game by pressing the 'R' key."
msgstr ""
"Якщо тінь загине, доведеться перезапустити рівень.\n"
"Для цього треба буде натиснути клавішу 'R'."
#: tutorial\tut02.map:18
msgid ""
"You can jump using the up key.\n"
"Try jumping over these blocks."
msgstr ""
-"Можна стрибати за допомогою клавіші 'вгору'.\n"
-"Спробуй перестрибнути ці блоки."
+"Стрибки виконуються за допомогою клавіші 'вгору'.\n"
+"Потрібно перестрибнути ці блоки."
#: tutorial\tut07.map:1
msgid "Shadow challenge"
msgstr "Випробування для тіні"
#: tutorial\tut20.map:1
msgid "Portal mayhem"
msgstr "Портальне божевілля"
#: tutorial\tut02.map:1
msgid "First jumps"
msgstr "Перші пострибеньки"
#: tutorial\tut20.map:16
msgid ""
"Portals point to another portal or to nothing.\n"
"Try to reach the exit in this portal mayhem."
msgstr ""
"Портали телепортують до іншого порталу або у порожнє місце.\n"
-"Спробуй досягнути виходу через це портальне божевілля."
+"Доведеться досягнути виходу попри це портальне божевілля."
#: tutorial\tut05.map:32
msgid ""
"TIP:\n"
"Think what moves your shadow has to make.\n"
"Then let your character record those moves.\n"
"You can break it down into smaller recordings."
msgstr ""
"Підказка:\n"
-"Поміркуй, які рухи буде потрібно зробити тіні.\n"
+"Варто спланувати, які рухи буде потрібно зробити тіні.\n"
"Потім нехай гравець запише ці рухи.\n"
"Запис можна розділити на декілька невеличких записів."
#: tutorial\tut11.map:17
msgid ""
"Until now the levels were static.\n"
"There are however moving blocks."
msgstr ""
-"До цього рівні були нерухомими.\n"
+"До цього часу рівні були нерухомими.\n"
"Однак, бувають і рухомі блоки."
#: tutorial\tut10.map:32
msgid "Save your progress here."
msgstr "Тут можна зберегти прогресс рівня."
#: tutorial\tut13.map:1
msgid "Moving spikes"
msgstr "Рухомі шипи"
#: tutorial\tut13.map:18
msgid "Watch out for the moving spikes."
msgstr "Стережися рухомих шипів."
#: tutorial\tut16.map:1
msgid "The switch"
msgstr "Вимикач"
#: tutorial\tut25.map:13
msgid "The very best of luck!"
msgstr "Нехай щастить!"
#: tutorial\tut20.map:156
msgid "Now choose one of the two."
-msgstr "Обери щось одне."
+msgstr "Доведеться обрати один із двох."
#: tutorial\tut19.map:42
msgid ""
"NOTE:\n"
"You can go back by entering this portal.\n"
"It is however a bit different, you don't have to\n"
"press the down key, it will activate when you walk in it."
msgstr ""
"Примітка:\n"
"Можна повернутися назад, зайшовши у портал.\n"
-"Однак цей портал трохи інший - не потрібно натискати\n"
-"клавішу 'вниз', він активується якщо на нього наступити."
+"Цей портал - автоматичний, не потрібно натискати\n"
+"клавішу 'вниз' - він активується, якщо на нього наступити."
#: tutorial\tut15.map:20
msgid ""
"This gap is impossible to jump over.\n"
"Step on the button next of you."
msgstr ""
"Через цю прірву не перестрибнути.\n"
"Треба стати на кнопку поблизу."
#: tutorial\tut06.map:1
msgid "Shadow walk"
msgstr "Прогулянка тіні"
#: tutorial\tut10.map:54
msgid ""
"This is the wrong way.\n"
"Go back to the previous checkpoint by pressing F3."
msgstr ""
"Це не вірний шлях.\n"
"Треба повернутися до попереднього чекпоінту за допомогою клавіші F3."
#: tutorial\tut25.map:318
msgid "You have made it!"
msgstr "Вдалося!"
#: tutorial\tut17.map:1
msgid "Toggle trigger"
msgstr "Вимикач"
#: tutorial\tut24.map:1
msgid "Warning"
msgstr "Попередження"
#: tutorial\tut05.map:1
msgid "Shadow"
msgstr "Тінь"
#: tutorial\tut06.map:23
msgid ""
"NOTE:\n"
"Although you can't jump on those blocks\n"
"you can record the jumps for your shadow."
msgstr ""
"Примітка:\n"
"Хоч гравець не може застрибнути на ці блоки,\n"
"ці стрибки можна записати для тіні."
#: tutorial\tut19.map:39
msgid ""
"Now it's time to check out the portals.\n"
"To get to the exit you'll have to take the portal.\n"
"Walk to it and press the down arrow to\n"
"activate."
msgstr ""
"Настав час поглянути на портали уважніше.\n"
"Щоб досягнути фінішу, потрібно пройти через портал.\n"
-"Зайди у нього й натисни клавішу 'вниз',\n"
+"Зайшовши у нього слід натиснути клавішу 'вниз',\n"
"щоб телепортуватися."
#: tutorial\tut18.map:1
msgid "Stop trigger"
msgstr "Вимикач, що зупиняє"
#: tutorial\tut01.map:1
msgid "Walk in the park"
msgstr "Прогулянка парком"
#: tutorial\tut09.map:14
msgid ""
"Those blocks are fragile.\n"
"If you step on them too often they'll break."
msgstr ""
"Ці блоки крихкі.\n"
-"Якщо наступити на них кілька раз, вони зруйнуються."
+"Якщо наступити на них кілька разів, вони зруйнуються."
#: tutorial\tut19.map:1
msgid "First portals"
msgstr "Перші портали"
#: tutorial\tut25.map:1
msgid "Final"
msgstr "Фінал"
#: tutorial\tut04.map:1
msgid "First spikes"
msgstr "Перші шипи"
#: tutorial\tut12.map:1
msgid "Moving shadow blocks"
msgstr "Рухомі блоки для тіні"
#: tutorial\tut22.map:22
msgid ""
"You need your shadow to reach the exit.\n"
"Make use of the swapper to get him down (or \n"
"to get yourself down)."
msgstr ""
-"Необхідно, щоби тінь досягнула виходу.\n"
+"Без допомоги тіні виходу не досягнути.\n"
"Для цього буде потрібно помінятися місцями\n"
-"Щоб зпустити тінь (або гравця) донизу."
+"щоб перемістити тінь (або гравця) донизу."
#: tutorial\tut21.map:8
msgid ""
"Now it's time for something completely\n"
"different: swappoints. When you or your\n"
"shadow activate them you'll swap places."
msgstr ""
-"Настав час для чогось зовсім нового:\n"
+"Настав час побачити щось зовсім нове:\n"
"місця в яких можна помінятися місцями.\n"
-"Як тінь активує їх, вона поміняється місцями з гравцем."
+"Якщо активувати їх, тінь поміняється місцями із гравцем."
#: tutorial\tut06.map:27
msgid ""
"Only your shadow can stand on those shadow\n"
"blocks. Try to get him up there."
msgstr ""
"Лише тінь гравця може стояти на цих блоках.\n"
-"Спробуй допомогти їй забратися вище."
+"Необхідно допомогти їй забратися вище."
#: tutorial\tut17.map:14
msgid ""
"You've only seen triggers that activate other\n"
"blocks, but they can also deactivate or toggle\n"
"them."
msgstr ""
"Ми вже бачили вимикачі, які лише активують інші\n"
"блоки, однак вони також можуть деактивувати або\n"
"перемикати їх."
#: tutorial\tut14.map:68
msgid ""
"When standing on conveyor belts you'll\n"
"move without walking."
msgstr ""
"Конвеєр буде тягнути гравця або тінь\n"
"у напрямі свого руху."
#: tutorial\tut25.map:46
msgid ""
"TIP:\n"
"Try to get your shadow in front of the shadow\n"
"wall. If he falls down you'd better restart."
msgstr ""
"Підказка:\n"
-"Спробуй встати тінню перед стіною для тіні. Якщо вона впаде,\n"
-"краще буде розпочати все зпочатку."
+"Потрібно встати тінню перед стіною для тіні.\n"
+"Якщо вона впаде, краще буде розпочати все спочатку."
#: tutorial\tut22.map:33
msgid ""
"TIP:\n"
"When your shadow is trapped stand on the\n"
"right side of the shadow blocks. Now record \n"
"the down key and let your shadow mimic."
msgstr ""
"Підказка:\n"
"Коли тінь у пастці, треба стати праворуч блока тіні.\n"
"Тепер записати натиснення клавіші 'вниз'\n"
"і нехай тінь повторить дії гравця."
#: tutorial\tut08.map:1
msgid "Teamwork"
msgstr "Плідна співпраця"
#: tutorial\tut14.map:71
msgid ""
"Let the shadow finish the level by walking to\n"
"the finish. But don't stand still because your\n"
"shadow will move all the way back."
msgstr ""
"Тінь має дійти до фінішу рівня.\n"
-"Але не стій на місці, оскільки конвеєр\n"
-"буде тягнути тінь назад."
+"Але не можна стояти на місці,\n"
+"оскільки конвеєр буде тягнути тінь назад."
#: tutorial\tut21.map:1
msgid "Swappoints"
msgstr "Міняймося місцями"
#: tutorial\tut23.map:18
msgid ""
"One thing you need to know before you're ready are keys.\n"
"Sometimes there are keys spread around the level.\n"
"The exit is locked until you get all the keys."
msgstr ""
"Ще одна річ, яку треба знати - ключі.\n"
"Іноді ключі розподілені на рівні.\n"
"І вихід буде замкнений до того, як їх усі зібрати."
#: tutorial\tut03.map:34
msgid "Good job!"
msgstr "Відмінно спрацьовано!"
#: tutorial\tut16.map:14
msgid ""
"There's another type of trigger: the switch.\n"
"Use the switch to activate the elevator so that you\n"
"can reach the exit."
msgstr ""
"Є ще один вид вимикачів: перемикач.\n"
-"Використовуй перемикач, щоб активувати ліфт,\n"
+"Цей перемикач активує ліфт,\n"
"який допоможе досягнути виходу."
#: tutorial\tut09.map:1
msgid "Fragile"
msgstr "Крихкі блоки"
#: tutorial\tut24.map:18
msgid ""
"That's all there is.\n"
"Now it's time to put your skills to the test.\n"
"Enter the exit to go to the last level.\n"
"Good luck!"
msgstr ""
"Ось і все.\n"
"Час здавати екзамен.\n"
"Потрібно дістатися виходу, щоб перейти на останній рівень.\n"
"Щасливої дороги!"
#: tutorial\tut25.map:459
msgid "Where could your shadow be?"
-msgstr "Де ж твоя тінь?"
+msgstr "Де ж тінь?"
#: tutorial\tut01.map:18
msgid ""
"Welcome to Me and My Shadow.\n"
"You can use the arrow keys to walk to the exit.\n"
"\n"
"Good luck!"
msgstr ""
-"Ласкаво просимо до гри \"Me and My Shadow\".\n"
-"Використовуй клавіші праворуч-ліворуч, щоб дістатися виходу.\n"
+"Ласкаво просимо до гри \"Me and My Shadow\"!\n"
+"Користуючись клавішами праворуч-ліворуч, треба дістатися виходу.\n"
"\n"
-"Нехай щастить!"
+"Щасливої подорожі!"
#: tutorial\tut15.map:1
msgid "Triggering"
msgstr "Тригер"
#: tutorial\tut03.map:1
msgid "Jumping around"
msgstr "Стрибки довкола"
#: tutorial\tut10.map:1
msgid "Checkpoints"
msgstr "Чекпоінти"
#: tutorial\tut07.map:19
msgid ""
"Spikes are not only deadly for you,\n"
"but also for your shadow."
msgstr ""
"Шипи смертельно небезпечні не лише для гравця,\n"
"але й для тіні."
#: tutorial\tut08.map:21
msgid ""
"You and your shadow need to work together.\n"
"Move your shadow towards the wall and jump\n"
"on him so that you can jump over the wall."
msgstr ""
"Тут потрібно працювати разом із тінню.\n"
"Нехай тінь стане біля стіни, а гравець -\n"
"застрибне на неї, щоб перестрибнути стіну."
#: tutorial\tut04.map:19
msgid ""
"Spikes are deadly.\n"
"Don't touch them!"
msgstr ""
"Шипи небезпечні.\n"
"Стережися їх!"
#: tutorial\levels.lst:3
msgid "Step by step introduction"
msgstr "Крок-за-кроком"
#: tutorial\tut11.map:1
msgid "Moving blocks"
msgstr "Рухомі блоки"
#: tutorial\tut14.map:1
msgid "Conveyor madness"
msgstr "Конвеєри збожеволіли"
#: tutorial\tut05.map:29
msgid ""
"You can't reach the exit, but your shadow can.\n"
"Press space to record your moves.\n"
"Press space once again to let your shadow\n"
"mimic your recording."
msgstr ""
-"Гравець не може досягнути виходу, але тінь може це зробити.\n"
-"Натисни пробіл, щоб записати рухи гравця.\n"
-"Натисни пробіл ще раз, щоб тінь\n"
-"відтворила записані рухи."
+"Гравець не може досягнути виходу, але це може зробити тінь.\n"
+"Клавіша пробіл, запише рухи гравця.\n"
+"Повторне натискання клавіші пробіл\n"
+"дасть тіні можливість відтворити записані рухи."
#: tutorial\levels.lst:2
msgid "You have finished the tutorial!"
msgstr "Навчання завершено!"
diff --git a/data/levelpacks/tutorial/tut10.map b/data/levelpacks/tutorial/tut10.map
index aae2267..e81924d 100755
--- a/data/levelpacks/tutorial/tut10.map
+++ b/data/levelpacks/tutorial/tut10.map
@@ -1,71 +1,71 @@
name=Checkpoints
recordings=1
size=2900,600
-time=240
+time=260
tile(Block,150,300)
tile(Block,200,300)
tile(Block,250,300)
tile(Block,300,300)
tile(Block,350,300)
tile(Block,400,300)
tile(Block,450,350)
tile(Block,950,450)
tile(Block,1000,300)
tile(Block,1050,300)
tile(Exit,2650,150)
tile(ShadowStart,200,250)
tile(PlayerStart,250,250)
tile(NotificationBlock,300,250){
message="You can save your progress in a level with\ncheckpoints. You can restore them at any\ntime using the F3 button."
}
tile(Block,500,350)
tile(Block,650,350)
tile(Block,750,350)
tile(Block,700,350)
tile(Block,850,450)
tile(Block,800,250)
tile(Block,850,250)
tile(Block,900,250)
tile(Block,900,450)
tile(Checkpoint,500,150)
tile(NotificationBlock,450,150){
message="Save your progress here."
}
tile(Block,450,200)
tile(Block,500,200)
tile(Block,550,200)
tile(Block,400,200)
tile(Block,1050,500)
tile(Block,1150,500)
tile(Block,1100,500)
tile(Block,1100,300)
tile(Block,1200,250)
tile(Block,1250,250)
tile(Block,1300,250)
tile(NotificationBlock,1250,200){
message="You've chosen the right way."
}
tile(Teleporter,1300,200){
automatic=0
destination=4
id=1
}
tile(NotificationBlock,1100,450){
message="This is the wrong way.\nGo back to the previous checkpoint by pressing F3."
}
tile(Teleporter,1150,450){
automatic=0
id=3
}
tile(Block,2600,250)
tile(Block,2650,250)
tile(Block,2700,250)
tile(Block,2550,250)
tile(Teleporter,2600,200){
automatic=0
destination=1
id=4
}
tile(Block,2650,200)
tile(Block,550,150)
tile(Block,550,100)
diff --git a/data/locale/hu.po b/data/locale/hu.po
index 548414a..b84ec98 100644
--- a/data/locale/hu.po
+++ b/data/locale/hu.po
@@ -1,2106 +1,2106 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the meandmyshadow package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: meandmyshadow 0.5svn\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-09-09 16:18+0800\n"
-"PO-Revision-Date: 2018-09-21 08:31+0000\n"
+"PO-Revision-Date: 2018-10-10 05:55+0000\n"
"Last-Translator: SanskritFritz <SanskritFritz+github@gmail.com>\n"
"Language-Team: Hungarian <https://hosted.weblate.org/projects/"
"me-and-my-shadow/translations/hu/>\n"
"Language: hu\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 3.2-dev\n"
+"X-Generator: Weblate 3.2.1\n"
#: ../src/AchievementList.cpp:43
msgid "Newbie"
msgstr "Újonc"
#: ../src/AchievementList.cpp:43
msgid "Complete a level."
msgstr "Szint teljesítése."
#: ../src/AchievementList.cpp:44
msgid "Experienced player"
msgstr "Tapasztalt játékos"
#: ../src/AchievementList.cpp:44
msgid "Complete 50 levels."
msgstr "50 szint teljesítése."
#: ../src/AchievementList.cpp:45
msgid "Good job!"
msgstr "Szép volt!"
#: ../src/AchievementList.cpp:45
msgid "Receive a gold medal."
msgstr "Nyerj aranyérmet."
#: ../src/AchievementList.cpp:46
msgid "Expert"
msgstr "Szakértő"
#: ../src/AchievementList.cpp:46
msgid "Earn 50 gold medal."
msgstr "Nyerj 50 aranyérmet."
#: ../src/AchievementList.cpp:48
msgid "Graduate"
msgstr "Végzős"
#: ../src/AchievementList.cpp:48
msgid "Complete the tutorial level pack."
msgstr "Teljesítsd a oktató szintcsomagot."
#: ../src/AchievementList.cpp:49
msgid "Outstanding graduate"
msgstr "Kiváló végzős"
#: ../src/AchievementList.cpp:49
msgid "Complete the tutorial level pack with gold for all levels."
msgstr "Teljesítsd az oktató szintcsomagot aranyéremmel minden szinten."
#: ../src/AchievementList.cpp:51
msgid "Hooked"
msgstr "Ráharaptál"
#: ../src/AchievementList.cpp:51
msgid "Play Me and My Shadow for more than 2 hours."
msgstr "Több mint 2 óra Me and My Shadow játék."
#: ../src/AchievementList.cpp:52
msgid "Loyal fan of Me and My Shadow"
msgstr "A Me and My Shadow hű rajongója"
#: ../src/AchievementList.cpp:52
msgid "Play Me and My Shadow for more than 24 hours."
msgstr "Több mint 24 óra Me and My Shadow játék."
#: ../src/AchievementList.cpp:54
msgid "Constructor"
msgstr "Építész"
#: ../src/AchievementList.cpp:54
msgid "Use the level editor for more than 2 hours."
msgstr "Több mint 2 óra a szintszerkeszőben."
#: ../src/AchievementList.cpp:55
msgid "The creator"
msgstr "Az akotó"
#: ../src/AchievementList.cpp:55
msgid "Use the level editor for more than 24 hours."
msgstr "Több mint 24 óra a szintszerkeszőben."
#: ../src/AchievementList.cpp:57
msgid "Look, cute level!"
msgstr "Nocsak, cuki szint!"
#: ../src/AchievementList.cpp:57
msgid "Create a level for the first time."
msgstr "Új szint léthehozása első alkalommal."
#: ../src/AchievementList.cpp:58
msgid "The level museum"
msgstr "A szintmúzeum"
#: ../src/AchievementList.cpp:58
msgid "Create 50 levels."
msgstr "50 szint létrehozása."
#: ../src/AchievementList.cpp:60
msgid "Hello, World!"
msgstr "Szia világ!"
#: ../src/AchievementList.cpp:60
msgid "Write a script for the first time."
msgstr "Szkript írása első alkalommal."
#: ../src/AchievementList.cpp:62
msgid "Frog"
msgstr "Béka"
#: ../src/AchievementList.cpp:62
msgid "Jump 1000 times."
msgstr "1000 ugrás."
#: ../src/AchievementList.cpp:64
msgid "Wanderer"
msgstr "Vándor"
#: ../src/AchievementList.cpp:64
msgid "Travel 100 meters."
msgstr "100 méternyi utazás."
#: ../src/AchievementList.cpp:65
msgid "Runner"
msgstr "Futó"
#: ../src/AchievementList.cpp:65
msgid "Travel 1 kilometer."
msgstr "1 kilóméter utazás."
#: ../src/AchievementList.cpp:66
msgid "Long distance runner"
msgstr "Hosszútávfutó"
#: ../src/AchievementList.cpp:66
msgid "Travel 10 kilometers."
msgstr "10 kilóméter utazás."
#: ../src/AchievementList.cpp:67
msgid "Marathon runner"
msgstr "Maratonfutó"
#: ../src/AchievementList.cpp:67
msgid "Travel 42,195 meters."
msgstr "42 195 méternyi utazás."
#: ../src/AchievementList.cpp:69
msgid "Be careful!"
msgstr "Óvatosan!"
#: ../src/AchievementList.cpp:69
msgid "Die for the first time."
msgstr "Az első halál."
#: ../src/AchievementList.cpp:70
msgid "It doesn't matter..."
msgstr "Nem számít..."
#: ../src/AchievementList.cpp:70
msgid "Die 50 times."
msgstr "50 halál."
#: ../src/AchievementList.cpp:71
msgid "Expert of trial and error"
msgstr "A próbálgatás szakértője"
#: ../src/AchievementList.cpp:71
msgid "Die 1000 times."
msgstr "1000 halál."
#: ../src/AchievementList.cpp:73
msgid "Keep an eye for moving blocks!"
msgstr "Figyelj a mozgó tömbökre!"
#: ../src/AchievementList.cpp:73
msgid "Get squashed for the first time."
msgstr "Szétlapítva első alkalommal."
#: ../src/AchievementList.cpp:74
msgid "Potato masher"
msgstr "Krumplipüréző"
#: ../src/AchievementList.cpp:74
msgid "Get squashed 50 times."
msgstr "Szétlapítva 50 alkalommal."
#: ../src/AchievementList.cpp:76
msgid "Double kill"
msgstr "Kettős halál"
#: ../src/AchievementList.cpp:76
msgid "Get both the player and the shadow dead."
msgstr "Haljon meg a játékos és az árnyéka is."
#: ../src/AchievementList.cpp:78
msgid "Bad luck"
msgstr "Pech"
#: ../src/AchievementList.cpp:78
msgid "Die 5 times in under 5 seconds."
msgstr "Halj meg 5-ször 5 másodpercen belül."
#: ../src/AchievementList.cpp:79
msgid "This level is too dangerous"
msgstr "Ez a szint túl veszélyes"
#: ../src/AchievementList.cpp:79
msgid "Die 10 times in under 5 seconds."
msgstr "Halj meg 10-szer 5 másodpercen belül."
#: ../src/AchievementList.cpp:81
msgid "You forgot your friend"
msgstr "Megfeledkeztél a barátodról"
#: ../src/AchievementList.cpp:81
msgid "Finish the level with the player or the shadow dead."
msgstr "A szint befejezése úgy, hogy a játékos, vagy az árnyéka meghal."
#: ../src/AchievementList.cpp:82
msgid "Just in time"
msgstr "Épp időben"
#: ../src/AchievementList.cpp:82
msgid "Reach the exit with the player and the shadow simultaneously."
msgstr "A játékos és az árnyéka egyszerre érjenek a kijárathoz."
#: ../src/AchievementList.cpp:84
msgid "Recorder"
msgstr "Felvevő"
#: ../src/AchievementList.cpp:84
msgid "Record 100 times."
msgstr "100 felvétel készítése."
#: ../src/AchievementList.cpp:85
msgid "Shadowmaster"
msgstr "Árnyékmester"
#: ../src/AchievementList.cpp:85
msgid "Record 1000 times."
msgstr "1000 felvétel készítése."
#: ../src/AchievementList.cpp:87
msgid "Switch puller"
msgstr "Váltókezelő"
#: ../src/AchievementList.cpp:87
msgid "Pull the switch 100 times."
msgstr "Váltó meghúzása 100 alkalommal."
#: ../src/AchievementList.cpp:88
msgid "The switch is broken!"
msgstr "Elromlott a váltó!"
#: ../src/AchievementList.cpp:88
msgid "Pull the switch 1000 times."
msgstr "Váltó meghúzása 1000 alkalommal."
#: ../src/AchievementList.cpp:90
msgid "Swapper"
msgstr "Cserélő"
#: ../src/AchievementList.cpp:90
msgid "Swap 100 times."
msgstr "Csere 100 alkalommal."
#: ../src/AchievementList.cpp:91
msgid "Player to shadow to player to shadow..."
msgstr "Játékosból árnyék, árnyékból játékos..."
#: ../src/AchievementList.cpp:91
msgid "Swap 1000 times."
msgstr "Csere 1000 alkalommal."
#: ../src/AchievementList.cpp:93
msgid "Play it save"
msgstr "Biztos ami biztos"
#: ../src/AchievementList.cpp:93
msgid "Save 1000 times."
msgstr "Mentés 1000 alkalommal."
#: ../src/AchievementList.cpp:94
msgid "This game is too hard"
msgstr "Ez a játék túl nehéz"
#: ../src/AchievementList.cpp:94
msgid "Load the game 1000 times."
msgstr "Játék betöltése 1000 alkalommal."
#: ../src/AchievementList.cpp:96
msgid "No, thanks"
msgstr "Kösz, nem"
#: ../src/AchievementList.cpp:96
msgid "Complete a level with checkpoint, but without saving."
msgstr "Szint befejezése ellenőrző ponttal, de mentés nélkül."
#: ../src/AchievementList.cpp:98
msgid "Panic save"
msgstr "Pánik mentés"
#: ../src/AchievementList.cpp:98
msgid "Save twice in 1 second."
msgstr "2 mentés 1 másodpercen belül."
#: ../src/AchievementList.cpp:99
msgid "Panic load"
msgstr "Pánik betöltés"
#: ../src/AchievementList.cpp:99
msgid "Load twice in 1 second."
msgstr "2 betöltés 1 másodpercen belül."
#: ../src/AchievementList.cpp:101
msgid "Bad saving position"
msgstr "Rossz mentési pozíció"
#: ../src/AchievementList.cpp:101
msgid "Load the game and die within 1 second."
msgstr "Játék betöltése és halál 1 másodpercen belül."
#: ../src/AchievementList.cpp:102
msgid "This level is too hard"
msgstr "Ez a szint túl nehéz"
#: ../src/AchievementList.cpp:102
msgid "Load the same save and die 100 times."
msgstr "Adott mentés betöltése és halál 100 alkalommal."
#: ../src/AchievementList.cpp:104
msgid "Quick swap"
msgstr "Gyorsváltás"
#: ../src/AchievementList.cpp:104
msgid "Swap twice in under a second."
msgstr "Váltás kétszer egy másodpercen belül."
#: ../src/AchievementList.cpp:107
msgid "Horizontal confusion"
msgstr "Vízszintes összezavarodás"
#: ../src/AchievementList.cpp:107
msgid "Press left and right simultaneously."
msgstr "Nyomd meg egyszerre a balra és a jobbra gombot."
#: ../src/AchievementList.cpp:109
msgid "Cheater"
msgstr "Csaló"
#: ../src/AchievementList.cpp:109
msgid "Cheat in game."
msgstr "Csalás a játékban."
#: ../src/AchievementList.cpp:111
msgid "Programmer"
msgstr "Programozó"
#: ../src/AchievementList.cpp:111
msgid "Play the development version of Me and My Shadow."
msgstr "Játék a Me and My Shadow fejlesztői változatával."
#: ../src/Addons.cpp:44 ../src/LevelPackManager.cpp:108
msgid "Levels"
msgstr "Szintek"
#: ../src/Addons.cpp:44
msgid "Single level which usually contain demanding puzzles"
msgstr "Egyetlen szint, mely általában igényes rejtvényeket tartalmaz"
#: ../src/Addons.cpp:45
msgid "Levelpacks"
msgstr "Szintcsomagok"
#: ../src/Addons.cpp:45
msgid "Collection of levels with the same author or style"
msgstr "Szintek gyűjteménye, adott szerzőtől vagy stílusban"
#: ../src/Addons.cpp:46
msgid "Themes"
msgstr "Témák"
#: ../src/Addons.cpp:46
msgid "Give every block and background a new look and feel"
msgstr "A tömbök és a háttér új külalakot kap"
#: ../src/Addons.cpp:55 ../src/TitleMenu.cpp:46
msgid "Addons"
msgstr "Bővítmények"
#: ../src/Addons.cpp:87
msgid "Unable to initialize addon menu:"
msgstr "Nem tudtam az alábbi bővítmény-menüt elindítani:"
#: ../src/Addons.cpp:95 ../src/Addons.cpp:158 ../src/Addons.cpp:662
#: ../src/Addons.cpp:690 ../src/CreditsMenu.cpp:89 ../src/LevelSelect.cpp:168
#: ../src/StatisticsScreen.cpp:159
msgid "Back"
msgstr "Vissza"
#: ../src/Addons.cpp:169
msgid "ERROR: unable to download addons file!"
msgstr "HIBA: a bővítmények letöltése sikertelen!"
# TRANSLATORS: addon_list is the name of a file and should not be translated.
#: ../src/Addons.cpp:182
msgid "ERROR: unable to load addon_list file!"
msgstr "HIBA: az addon_list fájl letöltése sikertelen!"
#: ../src/Addons.cpp:193
msgid "ERROR: Invalid file format of addons file!"
msgstr "HIBA: a bővítmény fájl formátuma nem jó!"
#: ../src/Addons.cpp:205
msgid "ERROR: Addon list version is unsupported!"
msgstr "HIBA: nem támogatott addon_list verzió!"
# TRANSLATORS: installed_addons is the name of a file and should not be translated.
#: ../src/Addons.cpp:226
msgid "ERROR: Unable to create the installed_addons file."
msgstr "HIBA: az installed_addons fájl létrehozása sikertelen."
#: ../src/Addons.cpp:238
msgid "ERROR: Invalid file format of the installed_addons!"
msgstr "HIBA: az installed_addons fájl formátuma nem jó!"
# TRANSLATORS: indicates the author of an addon.
#: ../src/Addons.cpp:389 ../src/Addons.cpp:621
#, c-format
msgid "by %s"
msgstr "írta: %s"
#: ../src/Addons.cpp:397
msgid "Installed"
msgstr "Telepítve"
#: ../src/Addons.cpp:402
msgid "Updatable"
msgstr "Frissíthető"
#: ../src/Addons.cpp:412
msgid "Not installed"
msgstr "Nincs telepítve"
#: ../src/Addons.cpp:625
#, c-format
msgid "Version: %d\n"
msgstr "Verzió: %d\n"
#: ../src/Addons.cpp:627
#, c-format
msgid "Installed version: %d\n"
msgstr "Telepített verzió: %d\n"
#: ../src/Addons.cpp:630
#, c-format
msgid "License: %s\n"
msgstr "Licensz: %s\n"
#: ../src/Addons.cpp:633
#, c-format
msgid "Website: %s\n"
msgstr "Weboldal: %s\n"
#: ../src/Addons.cpp:637
msgid "(No descriptions provided)"
msgstr "(Nincs hozzá leírás)"
#: ../src/Addons.cpp:657 ../src/Addons.cpp:684
msgid "Remove"
msgstr "Eltávolítás"
#: ../src/Addons.cpp:673
msgid "Update"
msgstr "Frissítés"
#: ../src/Addons.cpp:679
msgid "Install"
msgstr "Telepítés"
#: ../src/Addons.cpp:774
#, c-format
msgid "This addon can't be removed because it's needed by %s."
msgstr "Ez a bővítményt nem lehet eltávolítani, mert szükséges ehhez: %s."
#: ../src/Addons.cpp:774 ../src/Addons.cpp:1051
msgid "Dependency"
msgstr "Függőség"
#: ../src/Addons.cpp:803
#, c-format
msgid "WARNING: File '%s' appears to have been removed already."
msgstr "FIGYELMEZTETÉS: úgy tűnik, '%s' már el lett távolítva."
#: ../src/Addons.cpp:803 ../src/Addons.cpp:810 ../src/Addons.cpp:818
#: ../src/Addons.cpp:825 ../src/Addons.cpp:834 ../src/Addons.cpp:840
#: ../src/Addons.cpp:859 ../src/Addons.cpp:866 ../src/Addons.cpp:893
#: ../src/Addons.cpp:900 ../src/Addons.cpp:907 ../src/Addons.cpp:918
#: ../src/Addons.cpp:947 ../src/Addons.cpp:952 ../src/Addons.cpp:962
#: ../src/Addons.cpp:968 ../src/Addons.cpp:981 ../src/Addons.cpp:986
#: ../src/Addons.cpp:1008 ../src/Addons.cpp:1014 ../src/Addons.cpp:1044
msgid "Addon error"
msgstr "Bővítmény hiba"
#: ../src/Addons.cpp:810
#, c-format
msgid "ERROR: Unable to remove file '%s'!"
msgstr "HIBA: nem sikerült törölni a '%s' fájlt!"
#: ../src/Addons.cpp:818
#, c-format
msgid "WARNING: Directory '%s' appears to have been removed already."
msgstr "FIGYELMEZTETÉS: A '%s' könyvtárat már törölték."
#: ../src/Addons.cpp:825
#, c-format
msgid "ERROR: Unable to remove directory '%s'!"
msgstr "HIBA: Nem sikerült törölni a '%s' könyvtárat!"
#: ../src/Addons.cpp:834
#, c-format
msgid "WARNING: Level '%s' appears to have been removed already."
msgstr "FIGYELMEZTETÉS: A '%s' szint már törölve van."
#: ../src/Addons.cpp:840
#, c-format
msgid "ERROR: Unable to remove level '%s'!"
msgstr "HIBA: Nem sikerült törölni a '%s' szintet!"
#: ../src/Addons.cpp:859
#, c-format
msgid "WARNING: Levelpack directory '%s' appears to have been removed already."
msgstr "FIGYELMEZTETÉS: A szintcsomag '%s' könyvtára már törölve van."
#: ../src/Addons.cpp:866
#, c-format
msgid "ERROR: Unable to remove levelpack directory '%s'!"
msgstr "HIBA: Nem sikerült törölni a szintcsomag '%s' könyvtárat!"
#: ../src/Addons.cpp:893
#, c-format
msgid "ERROR: Unable to download addon file %s."
msgstr "HIBA: Nem sikerült letölteni a '%s' bővítmény fájlt."
#: ../src/Addons.cpp:900
#, c-format
msgid "ERROR: Unable to extract addon file %s."
msgstr "HIBA: Nem sikerült kibontani a '%s' bővítmény fáljt."
#: ../src/Addons.cpp:907
msgid "ERROR: Addon is missing metadata!"
msgstr "HIBA: A bővítmény nem tartalmaz meta-adatokat!"
#: ../src/Addons.cpp:918
msgid "ERROR: Invalid file format for metadata file!"
msgstr "HIBA: Érvénytelen meta-adat fáljformátum!"
#: ../src/Addons.cpp:947
#, c-format
msgid "WARNING: File '%s' already exists, addon may be broken or not working!"
msgstr ""
"FIGYELMEZTETÉS: A '%s' fájl már létezik, a bővitmény hibás, vagy nem működik!"
#: ../src/Addons.cpp:952
#, c-format
msgid ""
"WARNING: Unable to copy file '%s' to '%s', addon may be broken or not "
"working!"
msgstr ""
"FIGYELMEZTETÉS: A '%s' fájlt nem sikerült ide másolni: '%s', a bővítmény "
"hibás vagy nem működik!"
#: ../src/Addons.cpp:962
#, c-format
msgid ""
"WARNING: Destination directory '%s' already exists, addon may be broken or "
"not working!"
msgstr ""
"FIGYELMEZTETÉS: A '%s' célkönyvtár már létezik, a bővitmény hibás, vagy nem "
"működik!"
#: ../src/Addons.cpp:968 ../src/Addons.cpp:1014
#, c-format
msgid ""
"WARNING: Unable to move directory '%s' to '%s', addon may be broken or not "
"working!"
msgstr ""
"FIGYELMEZTETÉS: A '%s' könyvtárt nem sikerült ide másolni: '%s', a "
"bővítmény hibás vagy nem működik!"
#: ../src/Addons.cpp:981
#, c-format
msgid "WARNING: Level '%s' already exists, addon may be broken or not working!"
msgstr ""
"FIGYELMEZTETÉS: A '%s' szint már létezik, a bővitmény hibás, vagy nem "
"működik!"
#: ../src/Addons.cpp:986
#, c-format
msgid ""
"WARNING: Unable to copy level '%s' to '%s', addon may be broken or not "
"working!"
msgstr ""
"FIGYELMEZTETÉS: A '%s' szintet nem sikerült ide másolni: '%s', a bővítmény "
"hibás vagy nem működik!"
#: ../src/Addons.cpp:1008
#, c-format
msgid ""
"WARNING: Levelpack directory '%s' already exists, addon may be broken or not "
"working!"
msgstr ""
"FIGYELMEZTETÉS: A '%s' szintcsomag könyvtára már létezik, a bővitmény hibás, "
"vagy nem működik!"
#: ../src/Addons.cpp:1044
#, c-format
msgid "ERROR: Addon requires another addon (%s) which can't be found!"
msgstr "HIBA: A bővítmény másik bővítményt (%s) igényel, de az nem található!"
#: ../src/Addons.cpp:1051
#, c-format
msgid "The addon %s is needed and will be installed now."
msgstr "A %s bővítményre szükség van, és telepítve lesz most."
#: ../src/Block.cpp:822 ../src/LevelEditor.cpp:265
msgid "On"
msgstr "Be"
#: ../src/Block.cpp:823 ../src/LevelEditor.cpp:266
msgid "Off"
msgstr "Ki"
#: ../src/CommandManager.cpp:41
#, c-format
msgid "Undo %s"
msgstr "%s visszavonása"
#: ../src/CommandManager.cpp:43
msgid "Can't undo"
msgstr "Nem tudom visszavonni"
#: ../src/CommandManager.cpp:49
#, c-format
msgid "Redo %s"
msgstr "%s újra"
#: ../src/CommandManager.cpp:51
msgid "Can't redo"
msgstr "Nem lehet újra csinálni"
# TRANSLATORS: Context: Undo/Redo ...
#: ../src/Commands.cpp:190
msgid "Resize level"
msgstr "Szint átméretezése"
# TRANSLATORS: Context: Undo/Redo ...
#: ../src/Commands.cpp:807
msgid "Modify level property"
msgstr "Szint tulajdonság módosítása"
# TRANSLATORS: Context: Undo/Redo ...
#: ../src/Commands.cpp:919
#, c-format
msgid "Add scenery layer %s"
msgstr "Táj réteg %s hozzáadása"
# TRANSLATORS: Context: Undo/Redo ...
#: ../src/Commands.cpp:921
#, c-format
msgid "Delete scenery layer %s"
msgstr "Táj réteg %s törlése"
# TRANSLATORS: Context: Undo/Redo ...
#: ../src/Commands.cpp:951
#, c-format
msgid "Modify the property of scenery layer %s"
msgstr "Táj réteg tulajdonság %s módosítása"
# TRANSLATORS: Context: Undo/Redo ...
#: ../src/Commands.cpp:1040
#, c-format
msgid "Move %d object from layer %s to layer %s"
msgid_plural "Move %d objects from layer %s to layer %s"
msgstr[0] "%d objektum átmozgatása %s rétegről %s rétegre"
msgstr[1] "%d objektum átmozgatása %s rétegről %s rétegre"
#: ../src/CreditsMenu.cpp:35 ../src/TitleMenu.cpp:53
msgid "Credits"
msgstr ""
# TRANSLATORS: Font used in GUI:
# - Use "knewave" for languages using Latin and Latin-derived alphabets
# - "DroidSansFallback" can be used for non-Latin writing systems
#: ../src/Functions.cpp:569 ../src/Functions.cpp:570 ../src/Functions.cpp:571
#: ../src/Functions.cpp:588
msgid "knewave"
msgstr "knewave"
# TRANSLATORS: Font used for normal text:
# - Use "Blokletters-Viltstift" for languages using Latin and Latin-derived alphabets
# - "DroidSansFallback" can be used for non-Latin writing systems
#: ../src/Functions.cpp:575
msgid "Blokletters-Viltstift"
msgstr "Blokletters-Viltstift"
#: ../src/Functions.cpp:674
msgid "Loading..."
msgstr "Betöltés..."
#: ../src/Functions.cpp:1243 ../src/Functions.cpp:1270
#: ../src/LevelEditor.cpp:559 ../src/LevelEditor.cpp:693
#: ../src/LevelEditor.cpp:758 ../src/LevelEditor.cpp:821
#: ../src/LevelEditor.cpp:908 ../src/LevelEditor.cpp:1033
#: ../src/LevelEditor.cpp:1083 ../src/LevelEditor.cpp:1180
#: ../src/LevelEditor.cpp:1244 ../src/LevelEditor.cpp:2923
#: ../src/LevelEditSelect.cpp:244 ../src/LevelEditSelect.cpp:277
#: ../src/LevelEditSelect.cpp:317
msgid "OK"
msgstr "OK"
#: ../src/Functions.cpp:1244 ../src/Functions.cpp:1256
#: ../src/Functions.cpp:1266 ../src/LevelEditor.cpp:565
#: ../src/LevelEditor.cpp:699 ../src/LevelEditor.cpp:764
#: ../src/LevelEditor.cpp:827 ../src/LevelEditor.cpp:914
#: ../src/LevelEditor.cpp:1039 ../src/LevelEditor.cpp:1089
#: ../src/LevelEditor.cpp:1186 ../src/LevelEditor.cpp:1250
#: ../src/LevelEditor.cpp:2929 ../src/LevelEditSelect.cpp:248
#: ../src/LevelEditSelect.cpp:281 ../src/LevelEditSelect.cpp:321
#: ../src/OptionsMenu.cpp:289
msgid "Cancel"
msgstr "Mégse"
#: ../src/Functions.cpp:1248
msgid "Abort"
msgstr "Megszakít"
#: ../src/Functions.cpp:1249 ../src/Functions.cpp:1265
msgid "Retry"
msgstr "Újra"
#: ../src/Functions.cpp:1250
msgid "Ignore"
msgstr "Mellőz"
#: ../src/Functions.cpp:1254 ../src/Functions.cpp:1260
msgid "Yes"
msgstr "Igen"
#: ../src/Functions.cpp:1255 ../src/Functions.cpp:1261
msgid "No"
msgstr "Nem"
# TRANSLATORS: Please do not remove %s or %d from your translation:
# - %d means the level number in a levelpack
# - %s means the name of current level
#: ../src/Game.cpp:280 ../src/Game.cpp:1236
#, c-format
msgid "Level %d %s"
msgstr "%d %s szint"
# TRANSLATORS: Please do not remove %s from your translation:
# - %s will be replaced with current action key
#: ../src/Game.cpp:915
#, c-format
msgid "Press %s key to save the game."
msgstr "Nyomd meg a %s gombot, hogy mentést készíts a játékról."
# TRANSLATORS: Please do not remove %s from your translation:
# - %s will be replaced with current action key
#: ../src/Game.cpp:920
#, c-format
msgid "Press %s key to swap the position of player and shadow."
msgstr "Nyomd meg a %s gombot, hogy a játékos és árnyéka helyet cseréljen."
# TRANSLATORS: Please do not remove %s from your translation:
# - %s will be replaced with current action key
#: ../src/Game.cpp:925
#, c-format
msgid "Press %s key to activate the switch."
msgstr "Nyomd meg a %s gombot, hogy a kapcsolót aktiváld."
# TRANSLATORS: Please do not remove %s from your translation:
# - %s will be replaced with current action key
#: ../src/Game.cpp:930
#, c-format
msgid "Press %s key to teleport."
msgstr "Nyomd meg a %s gombot a teleportáláshoz."
# TRANSLATORS: Please do not remove %s from your translation:
# - first %s means currently configured key to restart game
# - Second %s means configured key to load from last save
#: ../src/Game.cpp:972
#, c-format
msgid "Press %s to restart current level or press %s to load the game."
-msgstr ""
+msgstr "%s újraindítja a szintet, %s újratölti a játékot."
# TRANSLATORS: Please do not remove %s from your translation:
# - %s will be replaced with currently configured key to restart game
#: ../src/Game.cpp:983
#, c-format
msgid "Press %s to restart current level."
-msgstr ""
+msgstr "%s újraindítja a szintet."
#: ../src/Game.cpp:996
msgid "Your shadow has died."
-msgstr ""
+msgstr "Az árnyékod meghalt."
#: ../src/Game.cpp:1052
#, c-format
msgid "%d recording"
msgid_plural "%d recordings"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d felvétel"
+msgstr[1] "%d felvétel"
#: ../src/Game.cpp:1224
msgid "You've finished:"
-msgstr ""
+msgstr "Elvégezted:"
# TRANSLATORS: Please do not remove %-.2f from your translation:
# - %-.2f means time in seconds
# - s is shortened form of a second. Try to keep it so.
#: ../src/Game.cpp:1291
#, c-format
msgid "Time: %-.2fs"
-msgstr ""
+msgstr "Idő: %-.2f mp"
# TRANSLATORS: Please do not remove %-.2f from your translation:
# - %-.2f means time in seconds
# - s is shortened form of a second. Try to keep it so.
#: ../src/Game.cpp:1300
#, c-format
msgid "Best time: %-.2fs"
-msgstr ""
+msgstr "Legjobb idő: %-.2f mp"
#: ../src/Game.cpp:1311
#, c-format
msgid "Target time: %-.2fs"
-msgstr ""
+msgstr "Célidő: %-.2f mp"
# TRANSLATORS: Please do not remove %d from your translation:
# - %d means the number of recordings user has made
#: ../src/Game.cpp:1332
#, c-format
msgid "Recordings: %d"
-msgstr ""
+msgstr "Felvétel: %d"
# TRANSLATORS: Please do not remove %d from your translation:
# - %d means the number of recordings user has made
#: ../src/Game.cpp:1340
#, c-format
msgid "Best recordings: %d"
-msgstr ""
+msgstr "Legjobb felvételek: %d"
#: ../src/Game.cpp:1350
#, c-format
msgid "Target recordings: %d"
-msgstr ""
+msgstr "Célfelvétel: %d"
# TRANSLATORS: Please do not remove %s from your translation:
# - %s will be replaced with name of a prize medal (gold, silver or bronze)
#: ../src/Game.cpp:1363
#, c-format
msgid "You earned the %s medal"
-msgstr ""
+msgstr "Eddig %s medált nyertél"
#: ../src/Game.cpp:1363
msgid "GOLD"
-msgstr ""
+msgstr "ARANY"
#: ../src/Game.cpp:1363
msgid "SILVER"
-msgstr ""
+msgstr "EZÜST"
#: ../src/Game.cpp:1363
msgid "BRONZE"
-msgstr ""
+msgstr "BRONZ"
# TRANSLATORS: used as return to the level selector menu
#: ../src/Game.cpp:1390
msgid "Menu"
-msgstr ""
+msgstr "Menü"
# TRANSLATORS: used as restart level
#: ../src/Game.cpp:1397 ../src/InputManager.cpp:47
msgid "Restart"
-msgstr ""
+msgstr "Újraindítás"
# TRANSLATORS: used as next level
#: ../src/Game.cpp:1404
msgid "Next"
-msgstr ""
+msgstr "Következő"
#: ../src/Game.cpp:1430
msgid "Game replay is done."
-msgstr ""
+msgstr "Ismétlés vége."
#: ../src/Game.cpp:1430
msgid "Game Replay"
-msgstr ""
+msgstr "Ismétlés"
#: ../src/Game.cpp:1767 ../src/Game.cpp:1769
msgid "Congratulations"
-msgstr ""
+msgstr "Gratulálok"
#: ../src/Game.cpp:1769
msgid "You have finished the levelpack!"
-msgstr ""
+msgstr "Sikerült teljesítened a szintcsomagot!"
#: ../src/InputManager.cpp:46
msgid "Up (in menu)"
-msgstr ""
+msgstr "Fel (menüben)"
#: ../src/InputManager.cpp:46
msgid "Down (in menu)"
-msgstr ""
+msgstr "Le (menüben)"
#: ../src/InputManager.cpp:46
msgid "Left"
-msgstr ""
+msgstr "Balra"
#: ../src/InputManager.cpp:46
msgid "Right"
-msgstr ""
+msgstr "Jobbra"
#: ../src/InputManager.cpp:46
msgid "Jump"
-msgstr ""
+msgstr "Ugrás"
#: ../src/InputManager.cpp:46
msgid "Action"
-msgstr ""
+msgstr "Akció"
#: ../src/InputManager.cpp:46
msgid "Space (Record)"
-msgstr ""
+msgstr "Szóköz (Felvétel)"
#: ../src/InputManager.cpp:46
msgid "Cancel recording"
-msgstr ""
+msgstr "Felvétel megszakítása"
#: ../src/InputManager.cpp:47
msgid "Escape"
-msgstr ""
+msgstr "Megszakítás"
#: ../src/InputManager.cpp:47
msgid "Tab (View shadow/Level prop.)"
-msgstr ""
+msgstr "Tab (Árnyék mutatása/Szint tul.)"
#: ../src/InputManager.cpp:47
msgid "Save game (in editor)"
-msgstr ""
+msgstr "Játék mentése (a szerkesztőben)"
#: ../src/InputManager.cpp:47
msgid "Load game"
-msgstr ""
+msgstr "Játék betöltése"
#: ../src/InputManager.cpp:47
msgid "Swap (in editor)"
-msgstr ""
+msgstr "Csere (a szerkesztőben)"
#: ../src/InputManager.cpp:48
msgid "Teleport (in editor)"
-msgstr ""
+msgstr "Teleportálás (a szerkesztőben)"
#: ../src/InputManager.cpp:48
msgid "Suicide (in editor)"
-msgstr ""
+msgstr "Öngyilkosság (a szerkesztőben)"
#: ../src/InputManager.cpp:48
msgid "Shift (in editor)"
-msgstr ""
+msgstr "Futószalag (a szerkesztőben)"
#: ../src/InputManager.cpp:48
msgid "Next block type (in Editor)"
-msgstr ""
+msgstr "Következő blokktípus (a szerkesztőben)"
#: ../src/InputManager.cpp:49
msgid "Previous block type (in editor)"
-msgstr ""
+msgstr "Előző blokktípus (a szerkesztőben)"
#: ../src/InputManager.cpp:49
msgid "Select (in menu)"
-msgstr ""
+msgstr "Kiválasztás (a menüben)"
# TRANSLAOTRS: This is used when the name of the key code is not found.
#: ../src/InputManager.cpp:156
#, c-format
msgid "(Key %d)"
-msgstr ""
+msgstr "(%d billentyű)"
#: ../src/InputManager.cpp:163
#, c-format
msgid "Joystick axis %d %s"
-msgstr ""
+msgstr "Joystick tengely %d %s"
#: ../src/InputManager.cpp:166
#, c-format
msgid "Joystick button %d"
-msgstr ""
+msgstr "Joystick gomb %d"
#: ../src/InputManager.cpp:171
#, c-format
msgid "Joystick hat %d left"
-msgstr ""
+msgstr "Joystick kontroll %d balra"
#: ../src/InputManager.cpp:174
#, c-format
msgid "Joystick hat %d right"
-msgstr ""
+msgstr "Joystick kontroll %d jobbra"
#: ../src/InputManager.cpp:177
#, c-format
msgid "Joystick hat %d up"
-msgstr ""
+msgstr "Joystick kontroll %d fel"
#: ../src/InputManager.cpp:180
#, c-format
msgid "Joystick hat %d down"
-msgstr ""
+msgstr "Joystick kontroll %d le"
# TRANSLAOTRS: This is used when the JOYSTICK_HAT value is invalid.
#: ../src/InputManager.cpp:185
#, c-format
msgid "Joystick hat %d %d"
-msgstr ""
+msgstr "Joystick kontroll %d %d"
#: ../src/InputManager.cpp:202
msgid "OR"
-msgstr ""
+msgstr "VAGY"
#: ../src/InputManager.cpp:416
msgid "Select an item and press a key to change it."
-msgstr ""
+msgstr "Válassz ki egy elemet és nyomj meg egy gombot hogy megváltoztasd."
#: ../src/InputManager.cpp:419
msgid "Press backspace to clear the selected item."
-msgstr ""
+msgstr "Visszatörlés gombbal lehet törölni az adott elem tartalmát."
#: ../src/LevelEditor.cpp:56
msgid "Block"
-msgstr ""
+msgstr "Blokk"
#: ../src/LevelEditor.cpp:56
msgid "Player Start"
-msgstr ""
+msgstr "Játékos kezdőpont"
#: ../src/LevelEditor.cpp:56
msgid "Shadow Start"
-msgstr ""
+msgstr "Árnyék kezdőpont"
#: ../src/LevelEditor.cpp:57
msgid "Exit"
-msgstr ""
+msgstr "Kijárat"
#: ../src/LevelEditor.cpp:57
msgid "Shadow Block"
-msgstr ""
+msgstr "Árnyék blokk"
#: ../src/LevelEditor.cpp:57
msgid "Spikes"
-msgstr ""
+msgstr "Tüskék"
#: ../src/LevelEditor.cpp:58
msgid "Checkpoint"
-msgstr ""
+msgstr "Ellenőrző pont"
#: ../src/LevelEditor.cpp:58 ../src/LevelEditSelect.cpp:312
msgid "Swap"
-msgstr ""
+msgstr "Csere"
#: ../src/LevelEditor.cpp:58
msgid "Fragile"
msgstr ""
#: ../src/LevelEditor.cpp:59
msgid "Moving Block"
msgstr ""
#: ../src/LevelEditor.cpp:59
msgid "Moving Shadow Block"
msgstr ""
#: ../src/LevelEditor.cpp:59
msgid "Moving Spikes"
msgstr ""
#: ../src/LevelEditor.cpp:60
msgid "Teleporter"
msgstr ""
#: ../src/LevelEditor.cpp:60
msgid "Button"
msgstr ""
#: ../src/LevelEditor.cpp:60
msgid "Switch"
msgstr ""
#: ../src/LevelEditor.cpp:61
msgid "Conveyor Belt"
msgstr ""
#: ../src/LevelEditor.cpp:61
msgid "Shadow Conveyor Belt"
msgstr ""
#: ../src/LevelEditor.cpp:61
msgid "Notification Block"
msgstr ""
#: ../src/LevelEditor.cpp:61
msgid "Collectable"
msgstr ""
#: ../src/LevelEditor.cpp:61
msgid "Pushable"
msgstr ""
#: ../src/LevelEditor.cpp:65 ../src/LevelEditor.cpp:310
msgid "Select"
msgstr ""
#: ../src/LevelEditor.cpp:65
msgid "Add"
msgstr ""
#: ../src/LevelEditor.cpp:65 ../src/LevelEditor.cpp:311
msgid "Delete"
msgstr ""
#: ../src/LevelEditor.cpp:65 ../src/LevelPlaySelect.cpp:66
#: ../src/TitleMenu.cpp:43
msgid "Play"
msgstr ""
#: ../src/LevelEditor.cpp:65 ../src/LevelEditor.cpp:2852
msgid "Level settings"
msgstr ""
#: ../src/LevelEditor.cpp:65
msgid "Save level"
msgstr ""
#: ../src/LevelEditor.cpp:65
msgid "Back to menu"
msgstr ""
#: ../src/LevelEditor.cpp:65
msgid "Configure"
msgstr ""
#: ../src/LevelEditor.cpp:84
#, c-format
msgid "%s (Scenery)"
msgstr ""
#: ../src/LevelEditor.cpp:267
msgid "Toggle"
msgstr ""
#: ../src/LevelEditor.cpp:270
msgid "Complete"
msgstr ""
#: ../src/LevelEditor.cpp:271
msgid "One step"
msgstr ""
#: ../src/LevelEditor.cpp:272
msgid "Two steps"
msgstr ""
#: ../src/LevelEditor.cpp:273
msgid "Gone"
msgstr ""
#: ../src/LevelEditor.cpp:291
msgid "Negative infinity"
msgstr ""
#: ../src/LevelEditor.cpp:293
msgid "Zero"
msgstr ""
#: ../src/LevelEditor.cpp:295
msgid "Level size"
msgstr ""
#: ../src/LevelEditor.cpp:297
msgid "Positive infinity"
msgstr ""
#: ../src/LevelEditor.cpp:299
msgid "Default"
msgstr ""
#: ../src/LevelEditor.cpp:308
msgid "Deselect"
msgstr ""
#: ../src/LevelEditor.cpp:318 ../src/LevelEditor.cpp:1136
#, c-format
msgid "Horizontal repeat start: %s"
msgstr ""
#: ../src/LevelEditor.cpp:320 ../src/LevelEditor.cpp:1137
#, c-format
msgid "Horizontal repeat end: %s"
msgstr ""
#: ../src/LevelEditor.cpp:322 ../src/LevelEditor.cpp:1138
#, c-format
msgid "Vertical repeat start: %s"
msgstr ""
#: ../src/LevelEditor.cpp:324 ../src/LevelEditor.cpp:1139
#, c-format
msgid "Vertical repeat end: %s"
msgstr ""
#: ../src/LevelEditor.cpp:329 ../src/LevelEditor.cpp:1150
msgid "Custom scenery"
msgstr ""
#: ../src/LevelEditor.cpp:335 ../src/LevelEditor.cpp:600
#: ../src/LevelEditor.cpp:602
msgid "Visible"
msgstr ""
#: ../src/LevelEditor.cpp:344
msgid "Link"
msgstr ""
#: ../src/LevelEditor.cpp:345
msgid "Remove Links"
msgstr ""
#: ../src/LevelEditor.cpp:349 ../src/LevelEditor.cpp:624
#: ../src/LevelEditor.cpp:626
msgid "Automatic"
msgstr ""
#: ../src/LevelEditor.cpp:359 ../src/LevelEditor.cpp:649
#, c-format
msgid "Behavior: %s"
msgstr ""
#: ../src/LevelEditor.cpp:362
msgid "Path"
msgstr ""
#: ../src/LevelEditor.cpp:363
msgid "Remove Path"
msgstr ""
#: ../src/LevelEditor.cpp:365 ../src/LevelEditor.cpp:371
#: ../src/LevelEditor.cpp:587 ../src/LevelEditor.cpp:589
msgid "Activated"
msgstr ""
#: ../src/LevelEditor.cpp:366 ../src/LevelEditor.cpp:612
#: ../src/LevelEditor.cpp:614
msgid "Looping"
msgstr ""
#: ../src/LevelEditor.cpp:372 ../src/LevelEditor.cpp:3526
msgid "Speed"
msgstr ""
#: ../src/LevelEditor.cpp:378 ../src/LevelEditor.cpp:668
#, c-format
msgid "State: %s"
msgstr ""
#: ../src/LevelEditor.cpp:382 ../src/LevelEditor.cpp:3511
msgid "Message"
msgstr ""
#: ../src/LevelEditor.cpp:384 ../src/LevelEditor.cpp:1202
#: ../src/LevelEditor.cpp:3825
msgid "Appearance"
msgstr ""
#: ../src/LevelEditor.cpp:389 ../src/LevelEditor.cpp:431
#: ../src/LevelEditor.cpp:715
msgid "Scripting"
msgstr ""
#: ../src/LevelEditor.cpp:402 ../src/LevelEditor.cpp:867
#: ../src/LevelEditor.cpp:885
#, c-format
msgid "Background layer: %s"
msgstr ""
#: ../src/LevelEditor.cpp:409 ../src/LevelEditor.cpp:866
#: ../src/LevelEditor.cpp:884
msgid "Blocks layer"
msgstr ""
#: ../src/LevelEditor.cpp:417 ../src/LevelEditor.cpp:867
#: ../src/LevelEditor.cpp:885
#, c-format
msgid "Foreground layer: %s"
msgstr ""
#: ../src/LevelEditor.cpp:423
msgid "Add new layer"
msgstr ""
#: ../src/LevelEditor.cpp:424
msgid "Delete selected layer"
msgstr ""
#: ../src/LevelEditor.cpp:425
msgid "Configure selected layer"
msgstr ""
#: ../src/LevelEditor.cpp:426
msgid "Move selected object to layer"
msgstr ""
#: ../src/LevelEditor.cpp:430 ../src/OptionsMenu.cpp:55
msgid "Settings"
msgstr ""
#: ../src/LevelEditor.cpp:463
msgid ""
"NOTE: the layers are sorted by name alphabetically.\n"
"The layer is background layer if its name is < 'f'\n"
"by dictionary order, otherwise it's foreground layer."
msgstr ""
#: ../src/LevelEditor.cpp:539
msgid "Notification block"
msgstr ""
#: ../src/LevelEditor.cpp:545
msgid "Enter message here:"
msgstr ""
#: ../src/LevelEditor.cpp:646
msgid "Behavior"
msgstr ""
#: ../src/LevelEditor.cpp:665
msgid "State"
msgstr ""
#: ../src/LevelEditor.cpp:673
msgid "Conveyor belt speed"
msgstr ""
#: ../src/LevelEditor.cpp:679
msgid "Enter speed here:"
msgstr ""
#: ../src/LevelEditor.cpp:690
msgid "NOTE: 1 Speed = 0.08 block/s"
msgstr ""
#: ../src/LevelEditor.cpp:721
msgid "Id:"
msgstr ""
#: ../src/LevelEditor.cpp:787
msgid "Level Scripting"
msgstr ""
#: ../src/LevelEditor.cpp:892
msgid "Add layer"
msgstr ""
#: ../src/LevelEditor.cpp:898
msgid "Enter the layer name:"
msgstr ""
#: ../src/LevelEditor.cpp:943
#, c-format
msgid "Are you sure you want to delete layer '%s'?"
msgstr ""
#: ../src/LevelEditor.cpp:944
msgid "Delete layer"
msgstr ""
#: ../src/LevelEditor.cpp:968
msgid "Layer settings"
msgstr ""
#: ../src/LevelEditor.cpp:974
msgid "Layer name:"
msgstr ""
#: ../src/LevelEditor.cpp:989
msgid "Layer moving speed (1 speed = 0.8 block/s):"
msgstr ""
#: ../src/LevelEditor.cpp:1010
msgid "Speed of following camera:"
msgstr ""
#: ../src/LevelEditor.cpp:1062
msgid "Move to layer"
msgstr ""
#: ../src/LevelEditor.cpp:1068
msgid "Enter the layer name (create new layer if necessary):"
msgstr ""
#: ../src/LevelEditor.cpp:1132
msgid "Repeat mode"
msgstr ""
#: ../src/LevelEditor.cpp:1156
msgid "Custom scenery:"
msgstr ""
#: ../src/LevelEditor.cpp:1219
msgid "(Use the default appearance for this block)"
msgstr ""
# TRANSLATORS: Block name
# TRANSLATORS: Context: Resize/Move ...
# TRANSLATORS: Context: Add/Remove ...
# TRANSLATORS: Context: Undo/Redo ...
#: ../src/LevelEditor.cpp:1465 ../src/LevelEditor.cpp:1707
#: ../src/LevelEditor.cpp:1723 ../src/LevelEditor.cpp:1772
#: ../src/LevelEditor.cpp:4400
msgid "Custom scenery block"
msgstr ""
#: ../src/LevelEditor.cpp:1673
msgid "Toolbox"
msgstr ""
#: ../src/LevelEditor.cpp:1705
#, c-format
msgid "Resize %s"
msgstr ""
#: ../src/LevelEditor.cpp:1705
#, c-format
msgid "Move %s"
msgstr ""
# TRANSLATORS: Context: Undo/Redo ...
#: ../src/LevelEditor.cpp:1713
#, c-format
msgid "Move %d object"
msgid_plural "Move %d objects"
msgstr[0] ""
msgstr[1] ""
#: ../src/LevelEditor.cpp:1721
#, c-format
msgid "Add %s"
msgstr ""
#: ../src/LevelEditor.cpp:1721
#, c-format
msgid "Remove %s"
msgstr ""
# TRANSLATORS: Context: Undo/Redo ...
#: ../src/LevelEditor.cpp:1729
#, c-format
msgid "Add %d object"
msgid_plural "Add %d objects"
msgstr[0] ""
msgstr[1] ""
# TRANSLATORS: Context: Undo/Redo ...
#: ../src/LevelEditor.cpp:1731
#, c-format
msgid "Remove %d object"
msgid_plural "Remove %d objects"
msgstr[0] ""
msgstr[1] ""
# TRANSLATORS: Context: Undo/Redo ...
#: ../src/LevelEditor.cpp:1739
#, c-format
msgid "Add path to %s"
msgstr ""
# TRANSLATORS: Context: Undo/Redo ...
#: ../src/LevelEditor.cpp:1741
#, c-format
msgid "Remove a path point from %s"
msgstr ""
# TRANSLATORS: Context: Undo/Redo ...
#: ../src/LevelEditor.cpp:1747
#, c-format
msgid "Remove all paths from %s"
msgstr ""
# TRANSLATORS: Context: Undo/Redo ...
#: ../src/LevelEditor.cpp:1753
#, c-format
msgid "Add link from %s to %s"
msgstr ""
# TRANSLATORS: Context: Undo/Redo ...
#: ../src/LevelEditor.cpp:1759
#, c-format
msgid "Remove all links from %s"
msgstr ""
# TRANSLATORS: Context: Undo/Redo ...
#: ../src/LevelEditor.cpp:1766
msgid "Modify the %2 property of %1"
msgstr ""
# TRANSLATORS: Context: Undo/Redo ...
#: ../src/LevelEditor.cpp:1818
#, c-format
msgid "Edit the script of %s"
msgstr ""
# TRANSLATORS: Context: Undo/Redo ...
#: ../src/LevelEditor.cpp:1821
msgid "Edit the script of level"
msgstr ""
#: ../src/LevelEditor.cpp:2146 ../src/LevelEditor.cpp:2226
msgid "The level has unsaved changes."
msgstr ""
#: ../src/LevelEditor.cpp:2150 ../src/LevelEditor.cpp:2228
msgid "Are you sure you want to quit?"
msgstr ""
#: ../src/LevelEditor.cpp:2150 ../src/LevelEditor.cpp:2228
msgid "Quit prompt"
msgstr ""
#: ../src/LevelEditor.cpp:2797 ../src/LevelEditor.cpp:2799
#, c-format
msgid "Level \"%s\" saved"
msgstr ""
#: ../src/LevelEditor.cpp:2797 ../src/LevelEditor.cpp:2799
msgid "Saved"
msgstr ""
#: ../src/LevelEditor.cpp:2859 ../src/LevelEditSelect.cpp:208
msgid "Name:"
msgstr ""
#: ../src/LevelEditor.cpp:2866
msgid "Theme:"
msgstr ""
#: ../src/LevelEditor.cpp:2873
msgid "Examples: %DATA%/themes/classic"
msgstr ""
#: ../src/LevelEditor.cpp:2875
msgid "or %USER%/themes/Orange"
msgstr ""
#: ../src/LevelEditor.cpp:2878
msgid "Music:"
msgstr ""
#: ../src/LevelEditor.cpp:2887
msgid "Target time (s):"
msgstr ""
#: ../src/LevelEditor.cpp:2903
msgid "Target recordings:"
msgstr ""
#: ../src/LevelEditor.cpp:2919
msgid "Restart level editor is required"
msgstr ""
#: ../src/LevelEditor.cpp:3679 ../src/LevelEditor.cpp:3718
#: ../src/LevelEditor.cpp:3739
msgid "Please enter a layer name."
msgstr ""
#: ../src/LevelEditor.cpp:3679 ../src/LevelEditor.cpp:3683
#: ../src/LevelEditor.cpp:3718 ../src/LevelEditor.cpp:3722
#: ../src/LevelEditor.cpp:3739 ../src/LevelEditor.cpp:3743
#: ../src/LevelEditSelect.cpp:644 ../src/LevelEditSelect.cpp:683
#: ../src/LevelEditSelect.cpp:688 ../src/LevelEditSelect.cpp:693
#: ../src/LevelEditSelect.cpp:698 ../src/LevelEditSelect.cpp:796
msgid "Error"
msgstr ""
#: ../src/LevelEditor.cpp:3683 ../src/LevelEditor.cpp:3722
#, c-format
msgid "The layer '%s' already exists."
msgstr ""
#: ../src/LevelEditor.cpp:3743
msgid "Source and destination layers are the same."
msgstr ""
#: ../src/LevelEditor.cpp:3760
msgid "Scenery"
msgstr ""
#: ../src/LevelEditor.cpp:4190 ../src/LevelEditor.cpp:4218
#, c-format
msgid "Speed: %d = %0.2f block/s"
msgstr ""
#: ../src/LevelEditor.cpp:4203
msgid "Stop at this point"
msgstr ""
#: ../src/LevelEditor.cpp:4208
#, c-format
msgid "Pause: %d = %0.3fs"
msgstr ""
#: ../src/LevelEditSelect.cpp:41 ../src/TitleMenu.cpp:45
msgid "Map Editor"
msgstr ""
#: ../src/LevelEditSelect.cpp:66
msgid "New Levelpack"
msgstr ""
#: ../src/LevelEditSelect.cpp:71
msgid "Pack Properties"
msgstr ""
#: ../src/LevelEditSelect.cpp:76
msgid "Remove Pack"
msgstr ""
#: ../src/LevelEditSelect.cpp:81
msgid "Move Map"
msgstr ""
#: ../src/LevelEditSelect.cpp:89
msgid "Remove Map"
msgstr ""
#: ../src/LevelEditSelect.cpp:94
msgid "Edit Map"
msgstr ""
#: ../src/LevelEditSelect.cpp:205
msgid "Properties"
msgstr ""
#: ../src/LevelEditSelect.cpp:217
msgid "Description:"
msgstr ""
#: ../src/LevelEditSelect.cpp:226
msgid "Congratulation text:"
msgstr ""
#: ../src/LevelEditSelect.cpp:235
msgid "Music list:"
msgstr ""
#: ../src/LevelEditSelect.cpp:265 ../src/LevelEditSelect.cpp:485
msgid "Add level"
msgstr ""
#: ../src/LevelEditSelect.cpp:268
msgid "File name:"
msgstr ""
#: ../src/LevelEditSelect.cpp:293
msgid "Move level"
msgstr ""
#: ../src/LevelEditSelect.cpp:296
msgid "Level: "
msgstr ""
#: ../src/LevelEditSelect.cpp:310
msgid "Before"
msgstr ""
#: ../src/LevelEditSelect.cpp:311
msgid "After"
msgstr ""
#: ../src/LevelEditSelect.cpp:368 ../src/LevelPlaySelect.cpp:124
msgid "Individual levels which are not contained in any level packs"
msgstr ""
#: ../src/LevelEditSelect.cpp:577
#, c-format
msgid "Are you sure remove the level pack '%s'?"
msgstr ""
#: ../src/LevelEditSelect.cpp:577 ../src/LevelEditSelect.cpp:607
msgid "Remove prompt"
msgstr ""
#: ../src/LevelEditSelect.cpp:607
#, c-format
msgid "Are you sure remove the map '%s'?"
msgstr ""
#: ../src/LevelEditSelect.cpp:644
msgid "Levelpack name cannot be empty."
msgstr ""
#: ../src/LevelEditSelect.cpp:683
#, c-format
msgid "The levelpack directory '%s' already exists!"
msgstr ""
#: ../src/LevelEditSelect.cpp:688
#, c-format
msgid "Unable to create levelpack directory '%s'!"
msgstr ""
#: ../src/LevelEditSelect.cpp:693
#, c-format
msgid "The levelpack file '%s' already exists!"
msgstr ""
#: ../src/LevelEditSelect.cpp:698
#, c-format
msgid "Unable to create levelpack file '%s'!"
msgstr ""
#: ../src/LevelEditSelect.cpp:758
msgid "No file name given for the new level."
msgstr ""
#: ../src/LevelEditSelect.cpp:758
msgid "Missing file name"
msgstr ""
#: ../src/LevelEditSelect.cpp:796
#, c-format
msgid "The file %s already exists."
msgstr ""
#: ../src/LevelEditSelect.cpp:849
msgid "The entered level number isn't valid!"
msgstr ""
#: ../src/LevelEditSelect.cpp:849
msgid "Illegal number"
msgstr ""
#: ../src/LevelInfoRender.cpp:19
msgid "Choose a level"
msgstr ""
#: ../src/LevelInfoRender.cpp:20
msgid "Time:"
msgstr ""
#: ../src/LevelInfoRender.cpp:21 ../src/StatisticsScreen.cpp:259
msgid "Recordings:"
msgstr ""
#: ../src/LevelPackManager.cpp:124
msgid "Custom Levels"
msgstr ""
#: ../src/LevelPlaySelect.cpp:41
msgid "Select Level"
msgstr ""
# TRANSLATORS: Used for button which clear any level progress like unlocked levels and highscores.
#: ../src/OptionsMenu.cpp:66
msgid "Clear Progress"
msgstr ""
#: ../src/OptionsMenu.cpp:109
msgid "General"
msgstr ""
#: ../src/OptionsMenu.cpp:110
msgid "Controls"
msgstr ""
#: ../src/OptionsMenu.cpp:121
msgid "Music"
msgstr ""
#: ../src/OptionsMenu.cpp:129
msgid "Sound"
msgstr ""
#: ../src/OptionsMenu.cpp:137
msgid "Resolution"
msgstr ""
#: ../src/OptionsMenu.cpp:177
msgid "Language"
msgstr ""
# TRANSLATORS: as detect user's language automatically
#: ../src/OptionsMenu.cpp:185
msgid "Auto-Detect"
msgstr ""
#: ../src/OptionsMenu.cpp:209
msgid "Theme"
msgstr ""
#: ../src/OptionsMenu.cpp:247
msgid "Internet proxy"
msgstr ""
#: ../src/OptionsMenu.cpp:256
msgid "Fullscreen"
msgstr ""
#: ../src/OptionsMenu.cpp:261
msgid "Quick record"
msgstr ""
#: ../src/OptionsMenu.cpp:266
msgid "Internet"
msgstr ""
#: ../src/OptionsMenu.cpp:271
msgid "Fade transition"
msgstr ""
#: ../src/OptionsMenu.cpp:294
msgid "Save Changes"
msgstr ""
#: ../src/OptionsMenu.cpp:513
msgid "Do you really want to reset level progress?"
msgstr ""
#: ../src/OptionsMenu.cpp:513
msgid "Warning"
msgstr ""
#: ../src/StatisticsManager.cpp:386
msgid "New achievement:"
msgstr ""
#: ../src/StatisticsManager.cpp:394
#, c-format
msgid "Achieved on %s"
msgstr ""
#: ../src/StatisticsManager.cpp:400
msgid "Unknown achievement"
msgstr ""
#: ../src/StatisticsManager.cpp:406
#, c-format
msgid "Achieved %1.0f%%"
msgstr ""
#: ../src/StatisticsManager.cpp:410
msgid "Not achieved"
msgstr ""
#: ../src/StatisticsScreen.cpp:57 ../src/TitleMenu.cpp:55
msgid "Achievements and Statistics"
msgstr ""
#: ../src/StatisticsScreen.cpp:166
msgid "Achievements"
msgstr ""
#: ../src/StatisticsScreen.cpp:167
msgid "Statistics"
msgstr ""
#: ../src/StatisticsScreen.cpp:234
msgid "Total"
msgstr ""
#: ../src/StatisticsScreen.cpp:246
msgid "Traveling distance (m)"
msgstr ""
#: ../src/StatisticsScreen.cpp:247
msgid "Jump times"
msgstr ""
#: ../src/StatisticsScreen.cpp:248
msgid "Die times"
msgstr ""
#: ../src/StatisticsScreen.cpp:249
msgid "Squashed times"
msgstr ""
#: ../src/StatisticsScreen.cpp:260
msgid "Switch pulled times:"
msgstr ""
#: ../src/StatisticsScreen.cpp:261
msgid "Swap times:"
msgstr ""
#: ../src/StatisticsScreen.cpp:262
msgid "Save times:"
msgstr ""
#: ../src/StatisticsScreen.cpp:263
msgid "Load times:"
msgstr ""
#: ../src/StatisticsScreen.cpp:268
msgid "Completed levels:"
msgstr ""
#: ../src/StatisticsScreen.cpp:306
msgid "In-game time:"
msgstr ""
#: ../src/StatisticsScreen.cpp:308
msgid "Level editing time:"
msgstr ""
#: ../src/StatisticsScreen.cpp:310
msgid "Created levels:"
msgstr ""
#: ../src/TitleMenu.cpp:44
msgid "Options"
msgstr ""
#: ../src/TitleMenu.cpp:47
msgid "Quit"
msgstr ""
#: ../src/TitleMenu.cpp:131
msgid "Enable internet in order to install addons."
msgstr ""
#: ../src/TitleMenu.cpp:131
msgid "Internet disabled"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Return"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Escape"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Backspace"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Tab"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Space"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "CapsLock"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "PrintScreen"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "ScrollLock"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Pause"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Insert"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Home"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "PageUp"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Delete"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "End"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "PageDown"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Right"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Left"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Down"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Up"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Numlock"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "SysReq"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Left Ctrl"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Left Shift"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Left Alt"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Left GUI"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Right Ctrl"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Right Shift"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Right Alt"
msgstr ""
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Right GUI"
msgstr ""
diff --git a/data/locale/ru.po b/data/locale/ru.po
index 27d0e48..42aeec2 100644
--- a/data/locale/ru.po
+++ b/data/locale/ru.po
@@ -1,2027 +1,2027 @@
# Russian translation for Me and My Shadow strings
# Copyright (C)
# This file is distributed under the same license as the meandmyshadow package.
# Jz Pan <acme_pjz@hotmail.com>, 2012.
#
msgid ""
msgstr ""
"Project-Id-Version: Russian (Me And My Shadow)\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-09-09 16:18+0800\n"
-"PO-Revision-Date: 2018-09-29 22:36+0000\n"
+"PO-Revision-Date: 2018-10-16 17:37+0000\n"
"Last-Translator: mesnevi <shams@airpost.net>\n"
"Language-Team: Russian <https://hosted.weblate.org/projects/me-and-my-shadow/"
"translations/ru/>\n"
"Language: ru\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<="
"4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
-"X-Generator: Weblate 3.2-dev\n"
+"X-Generator: Weblate 3.2.1\n"
#: ../src/AchievementList.cpp:43
msgid "Newbie"
msgstr "Новичок"
#: ../src/AchievementList.cpp:43
msgid "Complete a level."
msgstr "Завершить уровень."
#: ../src/AchievementList.cpp:44
msgid "Experienced player"
msgstr "Матёрый игрок"
#: ../src/AchievementList.cpp:44
msgid "Complete 50 levels."
msgstr "Завершить 50 уровней."
#: ../src/AchievementList.cpp:45
msgid "Good job!"
msgstr "Молодец!"
#: ../src/AchievementList.cpp:45
msgid "Receive a gold medal."
msgstr "Получить золотую медаль."
#: ../src/AchievementList.cpp:46
msgid "Expert"
msgstr "Специалист"
#: ../src/AchievementList.cpp:46
msgid "Earn 50 gold medal."
msgstr "Получить 50 золотых медалей."
#: ../src/AchievementList.cpp:48
msgid "Graduate"
msgstr "Выпускник"
#: ../src/AchievementList.cpp:48
msgid "Complete the tutorial level pack."
msgstr "Завершить все обучающие уровни."
#: ../src/AchievementList.cpp:49
msgid "Outstanding graduate"
msgstr "Отличник"
#: ../src/AchievementList.cpp:49
msgid "Complete the tutorial level pack with gold for all levels."
msgstr "Завершить все обучающие уровни, собрав все золотые медали."
#: ../src/AchievementList.cpp:51
msgid "Hooked"
msgstr "Зависимость"
#: ../src/AchievementList.cpp:51
msgid "Play Me and My Shadow for more than 2 hours."
msgstr "За игрой прошло более двух часов."
#: ../src/AchievementList.cpp:52
msgid "Loyal fan of Me and My Shadow"
msgstr "Преданный поклонник"
#: ../src/AchievementList.cpp:52
msgid "Play Me and My Shadow for more than 24 hours."
msgstr "За игрой прошло более суток."
#: ../src/AchievementList.cpp:54
msgid "Constructor"
msgstr "Конструктор"
#: ../src/AchievementList.cpp:54
msgid "Use the level editor for more than 2 hours."
msgstr "Использовать редактор уровней более двух часов."
#: ../src/AchievementList.cpp:55
msgid "The creator"
msgstr "Творец"
#: ../src/AchievementList.cpp:55
msgid "Use the level editor for more than 24 hours."
msgstr "Использовать редактор уровней более суток."
#: ../src/AchievementList.cpp:57
msgid "Look, cute level!"
msgstr "Ах, какая прелесть!"
#: ../src/AchievementList.cpp:57
msgid "Create a level for the first time."
msgstr "Создать свой первый уровень."
#: ../src/AchievementList.cpp:58
msgid "The level museum"
msgstr "Музей уровнестроения"
#: ../src/AchievementList.cpp:58
msgid "Create 50 levels."
msgstr "Создать 50 уровней."
#: ../src/AchievementList.cpp:60
msgid "Hello, World!"
msgstr "Hello, World!"
#: ../src/AchievementList.cpp:60
msgid "Write a script for the first time."
msgstr "Написать свой первый скрипт."
#: ../src/AchievementList.cpp:62
msgid "Frog"
msgstr "Лягушка-попрыгушка"
#: ../src/AchievementList.cpp:62
msgid "Jump 1000 times."
msgstr "Прыгнуть 1000 раз."
#: ../src/AchievementList.cpp:64
msgid "Wanderer"
msgstr "Пешеход"
#: ../src/AchievementList.cpp:64
msgid "Travel 100 meters."
msgstr "Пройти 100 метров."
#: ../src/AchievementList.cpp:65
msgid "Runner"
msgstr "Бродилка"
#: ../src/AchievementList.cpp:65
msgid "Travel 1 kilometer."
msgstr "Пройти 1 километр."
#: ../src/AchievementList.cpp:66
msgid "Long distance runner"
msgstr "Дальнобойщик"
#: ../src/AchievementList.cpp:66
msgid "Travel 10 kilometers."
msgstr "Пройти 10 километров."
#: ../src/AchievementList.cpp:67
msgid "Marathon runner"
msgstr "Марафонец"
#: ../src/AchievementList.cpp:67
msgid "Travel 42,195 meters."
msgstr "Пройти 42195 метров."
#: ../src/AchievementList.cpp:69
msgid "Be careful!"
msgstr "Поберегись!"
#: ../src/AchievementList.cpp:69
msgid "Die for the first time."
msgstr "Умереть впервые."
#: ../src/AchievementList.cpp:70
msgid "It doesn't matter..."
msgstr "Ну и ладно..."
#: ../src/AchievementList.cpp:70
msgid "Die 50 times."
msgstr "Умереть 50 раз."
#: ../src/AchievementList.cpp:71
msgid "Expert of trial and error"
msgstr "Лауреат премии Дарвина"
#: ../src/AchievementList.cpp:71
msgid "Die 1000 times."
msgstr "Умереть 1000 раз."
#: ../src/AchievementList.cpp:73
msgid "Keep an eye for moving blocks!"
msgstr "Осторожно, они двигаются!"
#: ../src/AchievementList.cpp:73
msgid "Get squashed for the first time."
msgstr "Быть раздавленным первый раз."
#: ../src/AchievementList.cpp:74
msgid "Potato masher"
msgstr "Пюре"
#: ../src/AchievementList.cpp:74
msgid "Get squashed 50 times."
msgstr "Быть раздавленным 50 раз."
#: ../src/AchievementList.cpp:76
msgid "Double kill"
msgstr "За двумя зайцами"
#: ../src/AchievementList.cpp:76
msgid "Get both the player and the shadow dead."
msgstr "Добиться смерти игрока и его тени."
#: ../src/AchievementList.cpp:78
msgid "Bad luck"
msgstr "Тотальное невезение"
#: ../src/AchievementList.cpp:78
msgid "Die 5 times in under 5 seconds."
msgstr "Умереть 5 раз за менее, чем 5 секунд."
#: ../src/AchievementList.cpp:79
msgid "This level is too dangerous"
msgstr "Да что ж это за жизнь такая?"
#: ../src/AchievementList.cpp:79
msgid "Die 10 times in under 5 seconds."
msgstr "Умереть 10 раз за менее, чем 5 секунд."
#: ../src/AchievementList.cpp:81
msgid "You forgot your friend"
msgstr "Друзья? Нет, не слышал"
#: ../src/AchievementList.cpp:81
msgid "Finish the level with the player or the shadow dead."
msgstr "Завершить уровень при том, что игрок или тень мертвы."
#: ../src/AchievementList.cpp:82
msgid "Just in time"
msgstr "Точность - вежливость королей"
#: ../src/AchievementList.cpp:82
msgid "Reach the exit with the player and the shadow simultaneously."
msgstr "Достичь выхода игроком и тенью одновременно."
#: ../src/AchievementList.cpp:84
msgid "Recorder"
-msgstr "По-медленнее, я записываю!"
+msgstr "Помедленнее, я записываю!"
#: ../src/AchievementList.cpp:84
msgid "Record 100 times."
msgstr "Выполнить запись 100 раз."
#: ../src/AchievementList.cpp:85
msgid "Shadowmaster"
msgstr "У меня все ходы записаны!"
#: ../src/AchievementList.cpp:85
msgid "Record 1000 times."
msgstr "Выполнить запись 1000 раз."
#: ../src/AchievementList.cpp:87
msgid "Switch puller"
msgstr "Выключателевключатель"
#: ../src/AchievementList.cpp:87
msgid "Pull the switch 100 times."
msgstr "Включить выключатель 100 раз."
#: ../src/AchievementList.cpp:88
msgid "The switch is broken!"
msgstr "Выключателеломатель"
#: ../src/AchievementList.cpp:88
msgid "Pull the switch 1000 times."
msgstr "Включить выключатель 1000 раз."
#: ../src/AchievementList.cpp:90
msgid "Swapper"
msgstr "Обменный пункт"
#: ../src/AchievementList.cpp:90
msgid "Swap 100 times."
msgstr "Поменяться 100 раз."
#: ../src/AchievementList.cpp:91
msgid "Player to shadow to player to shadow..."
-msgstr "Туда-сюдашка"
+msgstr "Туда-сюда-обратно"
#: ../src/AchievementList.cpp:91
msgid "Swap 1000 times."
msgstr "Поменяться 1000 раз."
#: ../src/AchievementList.cpp:93
msgid "Play it save"
msgstr "Хорошо сохранился"
#: ../src/AchievementList.cpp:93
msgid "Save 1000 times."
msgstr "Сохраниться 1000 раз."
#: ../src/AchievementList.cpp:94
msgid "This game is too hard"
msgstr "Сизифов труд"
#: ../src/AchievementList.cpp:94
msgid "Load the game 1000 times."
msgstr "Загрузить игру 1000 раз."
#: ../src/AchievementList.cpp:96
msgid "No, thanks"
msgstr "Нет уж, спасибо"
#: ../src/AchievementList.cpp:96
msgid "Complete a level with checkpoint, but without saving."
msgstr "Пройти уровень с чекпоинтом, но без сохранений."
#: ../src/AchievementList.cpp:98
msgid "Panic save"
msgstr "Паническое сохранение"
#: ../src/AchievementList.cpp:98
msgid "Save twice in 1 second."
msgstr "Сохраниться дважды за секунду."
#: ../src/AchievementList.cpp:99
msgid "Panic load"
msgstr "Паническая загрузка"
#: ../src/AchievementList.cpp:99
msgid "Load twice in 1 second."
msgstr "Загрузиться дважды за секунду."
#: ../src/AchievementList.cpp:101
msgid "Bad saving position"
msgstr "Местечко так себе"
#: ../src/AchievementList.cpp:101
msgid "Load the game and die within 1 second."
msgstr "Загрузить сохранённую игру и умереть в течении секунды."
#: ../src/AchievementList.cpp:102
msgid "This level is too hard"
msgstr "Да что ж такое"
#: ../src/AchievementList.cpp:102
msgid "Load the same save and die 100 times."
msgstr "Загрузить игру и умереть 100 раз."
#: ../src/AchievementList.cpp:104
msgid "Quick swap"
msgstr "Быстрая смена"
#: ../src/AchievementList.cpp:104
msgid "Swap twice in under a second."
msgstr "Поменяться дважды за секунду."
#: ../src/AchievementList.cpp:107
msgid "Horizontal confusion"
msgstr "Сено-солома"
#: ../src/AchievementList.cpp:107
msgid "Press left and right simultaneously."
msgstr "Нажать влево и вправо одновременно."
#: ../src/AchievementList.cpp:109
msgid "Cheater"
msgstr "Жулик"
#: ../src/AchievementList.cpp:109
msgid "Cheat in game."
msgstr "Не надо было жульничать."
#: ../src/AchievementList.cpp:111
msgid "Programmer"
msgstr "Тыжпрограммист"
#: ../src/AchievementList.cpp:111
msgid "Play the development version of Me and My Shadow."
msgstr "Играть в версию в разработке."
#: ../src/Addons.cpp:44 ../src/LevelPackManager.cpp:108
msgid "Levels"
msgstr "Уровни"
#: ../src/Addons.cpp:44
msgid "Single level which usually contain demanding puzzles"
msgstr "Один уровень, который обычно содержит головоломки"
#: ../src/Addons.cpp:45
msgid "Levelpacks"
msgstr "Сборники уровней"
#: ../src/Addons.cpp:45
msgid "Collection of levels with the same author or style"
msgstr "Несколько уровней, созданных единым автором или в подобном стиле"
#: ../src/Addons.cpp:46
msgid "Themes"
msgstr "Темы"
#: ../src/Addons.cpp:46
msgid "Give every block and background a new look and feel"
msgstr "Придать каждому блоку и фону новый вид и стиль"
#: ../src/Addons.cpp:55 ../src/TitleMenu.cpp:46
msgid "Addons"
msgstr "Дополнения"
#: ../src/Addons.cpp:87
msgid "Unable to initialize addon menu:"
msgstr "Не удалось запустить меню дополнений:"
#: ../src/Addons.cpp:95 ../src/Addons.cpp:158 ../src/Addons.cpp:662
#: ../src/Addons.cpp:690 ../src/CreditsMenu.cpp:89 ../src/LevelSelect.cpp:168
#: ../src/StatisticsScreen.cpp:159
msgid "Back"
msgstr "Назад"
#: ../src/Addons.cpp:169
msgid "ERROR: unable to download addons file!"
msgstr "ОШИБКА: не удалось загрузить файл дополнения!"
#: ../src/Addons.cpp:182
msgid "ERROR: unable to load addon_list file!"
msgstr "ОШИБКА: не удалось загрузить файл addon_list!"
#: ../src/Addons.cpp:193
msgid "ERROR: Invalid file format of addons file!"
msgstr "ОШИБКА: Неверный формат файла дополнения!"
#: ../src/Addons.cpp:205
msgid "ERROR: Addon list version is unsupported!"
msgstr "ОШИБКА: версия списка дополнений не поддерживается!"
#: ../src/Addons.cpp:226
msgid "ERROR: Unable to create the installed_addons file."
msgstr "ОШИБКА: не удалось создать список дополнений installed_addons."
#: ../src/Addons.cpp:238
msgid "ERROR: Invalid file format of the installed_addons!"
msgstr "ОШИБКА: у списка дополнений installed_addons неправильный формат!"
#: ../src/Addons.cpp:389 ../src/Addons.cpp:621
#, c-format
msgid "by %s"
-msgstr "автор %"
+msgstr "автор: %s"
#: ../src/Addons.cpp:397
msgid "Installed"
msgstr "Установлено"
#: ../src/Addons.cpp:402
msgid "Updatable"
msgstr "Есть обновления"
#: ../src/Addons.cpp:412
msgid "Not installed"
msgstr "Не установлено"
#: ../src/Addons.cpp:625
#, c-format
msgid "Version: %d\n"
msgstr "Версия: %d\n"
#: ../src/Addons.cpp:627
#, c-format
msgid "Installed version: %d\n"
msgstr "Установленная версия: %d\n"
#: ../src/Addons.cpp:630
#, c-format
msgid "License: %s\n"
msgstr "Лицензия: %s\n"
#: ../src/Addons.cpp:633
#, c-format
msgid "Website: %s\n"
msgstr "Веб-сайт: %s\n"
#: ../src/Addons.cpp:637
msgid "(No descriptions provided)"
msgstr "(Нет описания)"
#: ../src/Addons.cpp:657 ../src/Addons.cpp:684
msgid "Remove"
msgstr "Удалить"
#: ../src/Addons.cpp:673
msgid "Update"
msgstr "Обновить"
#: ../src/Addons.cpp:679
msgid "Install"
msgstr "Установить"
#: ../src/Addons.cpp:774
#, c-format
msgid "This addon can't be removed because it's needed by %s."
msgstr "Это дополнение нельзя удалить, оно необходимо для правильной работы %s."
#: ../src/Addons.cpp:774 ../src/Addons.cpp:1051
msgid "Dependency"
msgstr "Зависимости"
#: ../src/Addons.cpp:803
#, c-format
msgid "WARNING: File '%s' appears to have been removed already."
msgstr "ВНИМАНИЕ: файл '%s' уже удалён."
#: ../src/Addons.cpp:803 ../src/Addons.cpp:810 ../src/Addons.cpp:818
#: ../src/Addons.cpp:825 ../src/Addons.cpp:834 ../src/Addons.cpp:840
#: ../src/Addons.cpp:859 ../src/Addons.cpp:866 ../src/Addons.cpp:893
#: ../src/Addons.cpp:900 ../src/Addons.cpp:907 ../src/Addons.cpp:918
#: ../src/Addons.cpp:947 ../src/Addons.cpp:952 ../src/Addons.cpp:962
#: ../src/Addons.cpp:968 ../src/Addons.cpp:981 ../src/Addons.cpp:986
#: ../src/Addons.cpp:1008 ../src/Addons.cpp:1014 ../src/Addons.cpp:1044
msgid "Addon error"
msgstr "Ошибка дополнения"
#: ../src/Addons.cpp:810
#, c-format
msgid "ERROR: Unable to remove file '%s'!"
msgstr "ОШИБКА: не получается удалить файл '%s'!"
#: ../src/Addons.cpp:818
#, c-format
msgid "WARNING: Directory '%s' appears to have been removed already."
msgstr "ВНИМАНИЕ: папка '%s' уже удалена."
#: ../src/Addons.cpp:825
#, c-format
msgid "ERROR: Unable to remove directory '%s'!"
msgstr "ОШИБКА: не получается удалить папку '%s'!"
#: ../src/Addons.cpp:834
#, c-format
msgid "WARNING: Level '%s' appears to have been removed already."
msgstr "ВНИМАНИЕ: уровень '%s' уже удалён."
#: ../src/Addons.cpp:840
#, c-format
msgid "ERROR: Unable to remove level '%s'!"
msgstr "ОШИБКА: не получается удалить уровень '%s'!"
#: ../src/Addons.cpp:859
#, c-format
msgid "WARNING: Levelpack directory '%s' appears to have been removed already."
msgstr "ВНИМАНИЕ: папка со сборником уровней '%s' уже удалена."
#: ../src/Addons.cpp:866
#, c-format
msgid "ERROR: Unable to remove levelpack directory '%s'!"
msgstr "ОШИБКА: не получается удалить набор уровней '%s'!"
#: ../src/Addons.cpp:893
#, c-format
msgid "ERROR: Unable to download addon file %s."
msgstr "ОШИБКА: не получается загрузить файл дополнения %s."
#: ../src/Addons.cpp:900
#, c-format
msgid "ERROR: Unable to extract addon file %s."
msgstr "ОШИБКА: не получается распаковать файл дополнения %s."
#: ../src/Addons.cpp:907
msgid "ERROR: Addon is missing metadata!"
msgstr "ОШИБКА: в дополнении отсутствуют метаданные!"
#: ../src/Addons.cpp:918
msgid "ERROR: Invalid file format for metadata file!"
msgstr "ОШИБКА: неверный формат файла метаданных!"
#: ../src/Addons.cpp:947
#, c-format
msgid "WARNING: File '%s' already exists, addon may be broken or not working!"
msgstr "ВНИМАНИЕ: файл '%s' уже существует, дополнение может глючить или не работать!"
#: ../src/Addons.cpp:952
#, c-format
msgid ""
"WARNING: Unable to copy file '%s' to '%s', addon may be broken or not "
"working!"
msgstr ""
"ВНИМАНИЕ: не получается скопировать файл '%s' в '%s', "
"дополнение может глючить или не работать!"
#: ../src/Addons.cpp:962
#, c-format
msgid ""
"WARNING: Destination directory '%s' already exists, addon may be broken or "
"not working!"
msgstr ""
"ВНИМАНИЕ: папка '%s' уже существует, "
"дополнение может глючить или не работать!"
#: ../src/Addons.cpp:968 ../src/Addons.cpp:1014
#, c-format
msgid ""
"WARNING: Unable to move directory '%s' to '%s', addon may be broken or not "
"working!"
msgstr ""
"ВНИМАНИЕ: не получается переместить папку '%s' в '%s', "
"дополнение может глючить или не работать!"
#: ../src/Addons.cpp:981
#, c-format
msgid "WARNING: Level '%s' already exists, addon may be broken or not working!"
msgstr "ВНИМАНИЕ: уровень '%s' уже существует, дополнение может глючить или не работать!"
#: ../src/Addons.cpp:986
#, c-format
msgid ""
"WARNING: Unable to copy level '%s' to '%s', addon may be broken or not "
"working!"
msgstr ""
"ВНИМАНИЕ: не получается скопировать уровень '%s' в '%s', "
"дополнение может глючить или не работать!"
#: ../src/Addons.cpp:1008
#, c-format
msgid ""
"WARNING: Levelpack directory '%s' already exists, addon may be broken or not "
"working!"
msgstr ""
"ВНИМАНИЕ: папка со сборником уровней '%s' уже существует, "
"дополнение может глючить или не работать!"
#: ../src/Addons.cpp:1044
#, c-format
msgid "ERROR: Addon requires another addon (%s) which can't be found!"
msgstr ""
"ОШИБКА: для правильной работы дополнения необходимо установить другое "
"дополнение (%s), однако его не удалось найти!"
#: ../src/Addons.cpp:1051
#, c-format
msgid "The addon %s is needed and will be installed now."
msgstr "Необходимо установить дополнение %s. Установка сейчас начнётся."
#: ../src/Block.cpp:822 ../src/LevelEditor.cpp:265
msgid "On"
msgstr "Вкл."
#: ../src/Block.cpp:823 ../src/LevelEditor.cpp:266
msgid "Off"
msgstr "Выкл."
#: ../src/CommandManager.cpp:41
#, c-format
msgid "Undo %s"
msgstr "Отменить %s"
#: ../src/CommandManager.cpp:43
msgid "Can't undo"
msgstr "Невозможно отменить"
#: ../src/CommandManager.cpp:49
#, c-format
msgid "Redo %s"
msgstr "Повторить %s"
#: ../src/CommandManager.cpp:51
msgid "Can't redo"
msgstr "Невозможно повторить"
#: ../src/Commands.cpp:190
msgid "Resize level"
msgstr "Изменить размер уровня"
#: ../src/Commands.cpp:807
msgid "Modify level property"
msgstr "Изменить свойства уровня"
#: ../src/Commands.cpp:919
#, c-format
msgid "Add scenery layer %s"
msgstr "Добавить фоновый слой %s"
#: ../src/Commands.cpp:921
#, c-format
msgid "Delete scenery layer %s"
msgstr "Удалить фоновый слой %s"
#: ../src/Commands.cpp:951
#, c-format
msgid "Modify the property of scenery layer %s"
msgstr "Изменить свойства фонового слоя %s"
#: ../src/Commands.cpp:1040
#, c-format
msgid "Move %d object from layer %s to layer %s"
msgid_plural "Move %d objects from layer %s to layer %s"
msgstr[0] "Переместить %d объект из слоя %s в слой %s"
msgstr[1] "Переместить %d объекта из слоя %s в слой %s"
msgstr[2] "Переместить %d объектов из слоя %s в слой %s"
msgstr[3] "Переместить %d объектов из слоя %s в слой %s"
#: ../src/CreditsMenu.cpp:35 ../src/TitleMenu.cpp:53
msgid "Credits"
msgstr "Благодарности"
# TRANSLATORS: Font used in GUI:
# - Use "knewave" for languages using Latin and Latin-derived alphabets
# - "DroidSansFallback" can be used for non-Latin writing systems
#: ../src/Functions.cpp:569 ../src/Functions.cpp:570 ../src/Functions.cpp:571
#: ../src/Functions.cpp:588
msgid "knewave"
msgstr "DejaVuSansCondensed-Oblique"
#: ../src/Functions.cpp:575
msgid "Blokletters-Viltstift"
msgstr "DejaVuSansCondensed-Oblique"
#: ../src/Functions.cpp:674
msgid "Loading..."
msgstr "Загрузка..."
#: ../src/Functions.cpp:1243 ../src/Functions.cpp:1270
#: ../src/LevelEditor.cpp:559 ../src/LevelEditor.cpp:693
#: ../src/LevelEditor.cpp:758 ../src/LevelEditor.cpp:821
#: ../src/LevelEditor.cpp:908 ../src/LevelEditor.cpp:1033
#: ../src/LevelEditor.cpp:1083 ../src/LevelEditor.cpp:1180
#: ../src/LevelEditor.cpp:1244 ../src/LevelEditor.cpp:2923
#: ../src/LevelEditSelect.cpp:244 ../src/LevelEditSelect.cpp:277
#: ../src/LevelEditSelect.cpp:317
msgid "OK"
msgstr "Да"
#: ../src/Functions.cpp:1244 ../src/Functions.cpp:1256
#: ../src/Functions.cpp:1266 ../src/LevelEditor.cpp:565
#: ../src/LevelEditor.cpp:699 ../src/LevelEditor.cpp:764
#: ../src/LevelEditor.cpp:827 ../src/LevelEditor.cpp:914
#: ../src/LevelEditor.cpp:1039 ../src/LevelEditor.cpp:1089
#: ../src/LevelEditor.cpp:1186 ../src/LevelEditor.cpp:1250
#: ../src/LevelEditor.cpp:2929 ../src/LevelEditSelect.cpp:248
#: ../src/LevelEditSelect.cpp:281 ../src/LevelEditSelect.cpp:321
#: ../src/OptionsMenu.cpp:289
msgid "Cancel"
msgstr "Отмена"
#: ../src/Functions.cpp:1248
msgid "Abort"
msgstr "Прервать"
#: ../src/Functions.cpp:1249 ../src/Functions.cpp:1265
msgid "Retry"
msgstr "Попробовать снова"
#: ../src/Functions.cpp:1250
msgid "Ignore"
msgstr "Пропустить"
#: ../src/Functions.cpp:1254 ../src/Functions.cpp:1260
msgid "Yes"
msgstr "Да"
#: ../src/Functions.cpp:1255 ../src/Functions.cpp:1261
msgid "No"
msgstr "Нет"
#: ../src/Game.cpp:280 ../src/Game.cpp:1236
#, c-format
msgid "Level %d %s"
msgstr "Уровень %d %s"
#: ../src/Game.cpp:915
#, c-format
msgid "Press %s key to save the game."
msgstr "Чтобы сохранить игру, нажмите клавишу %s."
#: ../src/Game.cpp:920
#, c-format
msgid "Press %s key to swap the position of player and shadow."
msgstr "Чтобы поменять позицию игрока и тени, нажмите клавишу %s."
#: ../src/Game.cpp:925
#, c-format
msgid "Press %s key to activate the switch."
msgstr "Чтобы активировать переключатель, нажмите клавишу %s."
#: ../src/Game.cpp:930
#, c-format
msgid "Press %s key to teleport."
msgstr "Чтобы телепортироваться, нажмите клавишу %s."
#: ../src/Game.cpp:972
#, c-format
msgid "Press %s to restart current level or press %s to load the game."
msgstr "Чтобы перезапустить этот уровень, нажмите %s, или нажмите %s, чтобы загрузить игру."
#: ../src/Game.cpp:983
#, c-format
msgid "Press %s to restart current level."
msgstr "Чтобы перезапустить этот уровень, нажмите %s."
#: ../src/Game.cpp:996
msgid "Your shadow has died."
msgstr "Ваша тень умерла."
#: ../src/Game.cpp:1052
#, c-format
msgid "%d recording"
msgid_plural "%d recordings"
msgstr[0] "%d запись"
msgstr[1] "%d записи"
msgstr[2] "%d записей"
msgstr[3] "%d записей"
#: ../src/Game.cpp:1224
msgid "You've finished:"
msgstr "Завершённых уровней:"
#: ../src/Game.cpp:1291
#, c-format
msgid "Time: %-.2fs"
msgstr "Время: %-.2fs"
#: ../src/Game.cpp:1300
#, c-format
msgid "Best time: %-.2fs"
msgstr "Лучшее время: %-.2fs"
#: ../src/Game.cpp:1311
#, c-format
msgid "Target time: %-.2fs"
msgstr "Необходимое время: %-.2fs"
#: ../src/Game.cpp:1332
#, c-format
msgid "Recordings: %d"
msgstr "Записей: %d"
#: ../src/Game.cpp:1340
#, c-format
msgid "Best recordings: %d"
msgstr "Лучшая запись: %d"
#: ../src/Game.cpp:1350
#, c-format
msgid "Target recordings: %d"
msgstr "Необходимо записей: %d"
#: ../src/Game.cpp:1363
#, c-format
msgid "You earned the %s medal"
msgstr "Вы получили %s медаль"
#: ../src/Game.cpp:1363
msgid "GOLD"
msgstr "ЗОЛОТУЮ"
#: ../src/Game.cpp:1363
msgid "SILVER"
msgstr "СЕРЕБРЯНУЮ"
#: ../src/Game.cpp:1363
msgid "BRONZE"
msgstr "БРОНЗОВУЮ"
#: ../src/Game.cpp:1390
msgid "Menu"
msgstr "Меню"
#: ../src/Game.cpp:1397 ../src/InputManager.cpp:47
msgid "Restart"
msgstr "Снова"
#: ../src/Game.cpp:1404
msgid "Next"
msgstr "Далее"
#: ../src/Game.cpp:1430
msgid "Game replay is done."
msgstr "Воспроизведение завершено."
#: ../src/Game.cpp:1430
msgid "Game Replay"
msgstr "Воспроизведение игры"
#: ../src/Game.cpp:1767 ../src/Game.cpp:1769
msgid "Congratulations"
msgstr "Поздравляем"
#: ../src/Game.cpp:1769
msgid "You have finished the levelpack!"
msgstr "Вы закончили этот сборник уровней!"
#: ../src/InputManager.cpp:46
msgid "Up (in menu)"
msgstr "Вверх (в меню)"
#: ../src/InputManager.cpp:46
msgid "Down (in menu)"
msgstr "Вниз (в меню)"
#: ../src/InputManager.cpp:46
msgid "Left"
msgstr "Влево"
#: ../src/InputManager.cpp:46
msgid "Right"
msgstr "Вправо"
#: ../src/InputManager.cpp:46
msgid "Jump"
msgstr "Прыжок"
#: ../src/InputManager.cpp:46
msgid "Action"
msgstr "Действие"
#: ../src/InputManager.cpp:46
msgid "Space (Record)"
msgstr "Пробел (Запись)"
#: ../src/InputManager.cpp:46
msgid "Cancel recording"
msgstr "Отменить запись"
#: ../src/InputManager.cpp:47
msgid "Escape"
msgstr "Выход"
#: ../src/InputManager.cpp:47
msgid "Tab (View shadow/Level prop.)"
msgstr "Tab (См. тень/Настр. уровня)"
#: ../src/InputManager.cpp:47
msgid "Save game (in editor)"
msgstr "Сохранить игру (в редакторе)"
#: ../src/InputManager.cpp:47
msgid "Load game"
msgstr "Загрузить игру"
#: ../src/InputManager.cpp:47
msgid "Swap (in editor)"
msgstr "Поменяться местами (в редакторе)"
#: ../src/InputManager.cpp:48
msgid "Teleport (in editor)"
msgstr "Телепорт (в редакторе)"
#: ../src/InputManager.cpp:48
msgid "Suicide (in editor)"
msgstr "Смерть (в редакторе)"
#: ../src/InputManager.cpp:48
msgid "Shift (in editor)"
msgstr "Сдвиг (в редакторе)"
#: ../src/InputManager.cpp:48
msgid "Next block type (in Editor)"
msgstr "Следующий вид блока (в редакторе)"
#: ../src/InputManager.cpp:49
msgid "Previous block type (in editor)"
msgstr "Предыдущий вид блока (в редакторе)"
#: ../src/InputManager.cpp:49
msgid "Select (in menu)"
msgstr "Выбрать (в меню)"
#: ../src/InputManager.cpp:156
#, c-format
msgid "(Key %d)"
msgstr "(Клавиша %d)"
#: ../src/InputManager.cpp:163
#, c-format
msgid "Joystick axis %d %s"
msgstr "Ось джойстика %d %s"
#: ../src/InputManager.cpp:166
#, c-format
msgid "Joystick button %d"
msgstr "Кнопка джойстика %d"
#: ../src/InputManager.cpp:171
#, c-format
msgid "Joystick hat %d left"
msgstr "Джойстик %d влево"
#: ../src/InputManager.cpp:174
#, c-format
msgid "Joystick hat %d right"
msgstr "Джойстик %d вправо"
#: ../src/InputManager.cpp:177
#, c-format
msgid "Joystick hat %d up"
msgstr "Джойстик %d вверх"
#: ../src/InputManager.cpp:180
#, c-format
msgid "Joystick hat %d down"
msgstr "Джойстик %d вниз"
#: ../src/InputManager.cpp:185
#, c-format
msgid "Joystick hat %d %d"
msgstr "Джойстик %d %d"
#: ../src/InputManager.cpp:202
msgid "OR"
msgstr "ИЛИ"
#: ../src/InputManager.cpp:416
msgid "Select an item and press a key to change it."
msgstr "Выберите элемент и нажмите клавишу, чтобы изменить его."
#: ../src/InputManager.cpp:419
msgid "Press backspace to clear the selected item."
msgstr "Нажмите backspace, чтобы очистить выбранный элемент."
#: ../src/LevelEditor.cpp:56
msgid "Block"
msgstr "Блок"
#: ../src/LevelEditor.cpp:56
msgid "Player Start"
msgstr "Здесь начинает игрок"
#: ../src/LevelEditor.cpp:56
msgid "Shadow Start"
msgstr "Здесь начинает тень"
#: ../src/LevelEditor.cpp:57
msgid "Exit"
msgstr "Выход"
#: ../src/LevelEditor.cpp:57
msgid "Shadow Block"
msgstr "Блок для тени"
#: ../src/LevelEditor.cpp:57
msgid "Spikes"
msgstr "Шипы"
#: ../src/LevelEditor.cpp:58
msgid "Checkpoint"
msgstr "Чекпоинт"
#: ../src/LevelEditor.cpp:58 ../src/LevelEditSelect.cpp:312
msgid "Swap"
msgstr "Поменяться"
#: ../src/LevelEditor.cpp:58
msgid "Fragile"
msgstr "Хрупкий"
#: ../src/LevelEditor.cpp:59
msgid "Moving Block"
msgstr "Движущийся блок"
#: ../src/LevelEditor.cpp:59
msgid "Moving Shadow Block"
msgstr "Движущийся блок для тени"
#: ../src/LevelEditor.cpp:59
msgid "Moving Spikes"
msgstr "Движущиеся шипы"
#: ../src/LevelEditor.cpp:60
msgid "Teleporter"
msgstr "Телепортер"
#: ../src/LevelEditor.cpp:60
msgid "Button"
msgstr "Кнопка"
#: ../src/LevelEditor.cpp:60
msgid "Switch"
msgstr "Переключатель"
#: ../src/LevelEditor.cpp:61
msgid "Conveyor Belt"
msgstr "Конвейер"
#: ../src/LevelEditor.cpp:61
msgid "Shadow Conveyor Belt"
msgstr "Конвейер для тени"
#: ../src/LevelEditor.cpp:61
msgid "Notification Block"
msgstr "Блок оповещения"
#: ../src/LevelEditor.cpp:61
msgid "Collectable"
-msgstr "Подбираемый предмет"
+msgstr "Ключ"
#: ../src/LevelEditor.cpp:61
msgid "Pushable"
msgstr "Толкаемый предмет"
#: ../src/LevelEditor.cpp:65 ../src/LevelEditor.cpp:310
msgid "Select"
msgstr "Выбрать"
#: ../src/LevelEditor.cpp:65
msgid "Add"
msgstr "Добавить"
#: ../src/LevelEditor.cpp:65 ../src/LevelEditor.cpp:311
msgid "Delete"
msgstr "Удалить"
#: ../src/LevelEditor.cpp:65 ../src/LevelPlaySelect.cpp:66
#: ../src/TitleMenu.cpp:43
msgid "Play"
msgstr "Играть"
#: ../src/LevelEditor.cpp:65 ../src/LevelEditor.cpp:2852
msgid "Level settings"
msgstr "Настройки уровня"
#: ../src/LevelEditor.cpp:65
msgid "Save level"
msgstr "Сохранить уровень"
#: ../src/LevelEditor.cpp:65
msgid "Back to menu"
msgstr "Назад в меню"
#: ../src/LevelEditor.cpp:65
msgid "Configure"
msgstr "Настройки"
#: ../src/LevelEditor.cpp:84
#, c-format
msgid "%s (Scenery)"
msgstr "%s (Фон)"
#: ../src/LevelEditor.cpp:267
msgid "Toggle"
msgstr "Переключать"
#: ../src/LevelEditor.cpp:270
msgid "Complete"
msgstr "Завершённый"
#: ../src/LevelEditor.cpp:271
msgid "One step"
msgstr "Один шаг"
#: ../src/LevelEditor.cpp:272
msgid "Two steps"
msgstr "Два шага"
#: ../src/LevelEditor.cpp:273
msgid "Gone"
msgstr "Разрушен"
#: ../src/LevelEditor.cpp:291
msgid "Negative infinity"
msgstr "Минус бесконечность"
#: ../src/LevelEditor.cpp:293
msgid "Zero"
msgstr "Ноль"
#: ../src/LevelEditor.cpp:295
msgid "Level size"
msgstr "Размер уровня"
#: ../src/LevelEditor.cpp:297
msgid "Positive infinity"
msgstr "Плюс бесконечность"
#: ../src/LevelEditor.cpp:299
msgid "Default"
msgstr "Стандартный"
#: ../src/LevelEditor.cpp:308
msgid "Deselect"
msgstr "Отменить выбор"
#: ../src/LevelEditor.cpp:318 ../src/LevelEditor.cpp:1136
#, c-format
msgid "Horizontal repeat start: %s"
msgstr "Начать горизонтальное повторение: %s"
#: ../src/LevelEditor.cpp:320 ../src/LevelEditor.cpp:1137
#, c-format
msgid "Horizontal repeat end: %s"
msgstr "Завершить горизонтальное повторение: %s"
#: ../src/LevelEditor.cpp:322 ../src/LevelEditor.cpp:1138
#, c-format
msgid "Vertical repeat start: %s"
msgstr "Начать вертикальное повторение: %s"
#: ../src/LevelEditor.cpp:324 ../src/LevelEditor.cpp:1139
#, c-format
msgid "Vertical repeat end: %s"
msgstr "Завершить вертикальное повторение: %s"
#: ../src/LevelEditor.cpp:329 ../src/LevelEditor.cpp:1150
msgid "Custom scenery"
msgstr "Настроить фон"
#: ../src/LevelEditor.cpp:335 ../src/LevelEditor.cpp:600
#: ../src/LevelEditor.cpp:602
msgid "Visible"
msgstr "Видимый"
#: ../src/LevelEditor.cpp:344
msgid "Link"
msgstr "Ссылка"
#: ../src/LevelEditor.cpp:345
msgid "Remove Links"
msgstr "Убрать ссылки"
#: ../src/LevelEditor.cpp:349 ../src/LevelEditor.cpp:624
#: ../src/LevelEditor.cpp:626
msgid "Automatic"
msgstr "Авто"
#: ../src/LevelEditor.cpp:359 ../src/LevelEditor.cpp:649
#, c-format
msgid "Behavior: %s"
msgstr "Поведение: %s"
#: ../src/LevelEditor.cpp:362
msgid "Path"
msgstr "Путь"
#: ../src/LevelEditor.cpp:363
msgid "Remove Path"
msgstr "Удалить путь"
#: ../src/LevelEditor.cpp:365 ../src/LevelEditor.cpp:371
#: ../src/LevelEditor.cpp:587 ../src/LevelEditor.cpp:589
msgid "Activated"
msgstr "Активировано"
#: ../src/LevelEditor.cpp:366 ../src/LevelEditor.cpp:612
#: ../src/LevelEditor.cpp:614
msgid "Looping"
msgstr "Повторять"
#: ../src/LevelEditor.cpp:372 ../src/LevelEditor.cpp:3526
msgid "Speed"
msgstr "Скорость"
#: ../src/LevelEditor.cpp:378 ../src/LevelEditor.cpp:668
#, c-format
msgid "State: %s"
msgstr "Состояние: %s"
#: ../src/LevelEditor.cpp:382 ../src/LevelEditor.cpp:3511
msgid "Message"
msgstr "Сообщение"
#: ../src/LevelEditor.cpp:384 ../src/LevelEditor.cpp:1202
#: ../src/LevelEditor.cpp:3825
msgid "Appearance"
msgstr "Внешний вид"
#: ../src/LevelEditor.cpp:389 ../src/LevelEditor.cpp:431
#: ../src/LevelEditor.cpp:715
msgid "Scripting"
msgstr "Скрипты"
#: ../src/LevelEditor.cpp:402 ../src/LevelEditor.cpp:867
#: ../src/LevelEditor.cpp:885
#, c-format
msgid "Background layer: %s"
msgstr "Слой фона: %s"
#: ../src/LevelEditor.cpp:409 ../src/LevelEditor.cpp:866
#: ../src/LevelEditor.cpp:884
msgid "Blocks layer"
msgstr "Сбой блоков"
#: ../src/LevelEditor.cpp:417 ../src/LevelEditor.cpp:867
#: ../src/LevelEditor.cpp:885
#, c-format
msgid "Foreground layer: %s"
msgstr "Передний план: %s"
#: ../src/LevelEditor.cpp:423
msgid "Add new layer"
msgstr "Добавить слой"
#: ../src/LevelEditor.cpp:424
msgid "Delete selected layer"
msgstr "Удалить выбранный слой"
#: ../src/LevelEditor.cpp:425
msgid "Configure selected layer"
msgstr "Настроить выбранный слой"
#: ../src/LevelEditor.cpp:426
msgid "Move selected object to layer"
msgstr "Переместить выбранный объект в слой"
#: ../src/LevelEditor.cpp:430 ../src/OptionsMenu.cpp:55
msgid "Settings"
msgstr "Настройки"
#: ../src/LevelEditor.cpp:463
msgid ""
"NOTE: the layers are sorted by name alphabetically.\n"
"The layer is background layer if its name is < 'f'\n"
"by dictionary order, otherwise it's foreground layer."
msgstr "ЗАМЕТКА: слои отсортированы по названию в алфавитном порядке.\n"
"Слой является фоновым слоем, если его имя < 'f'\n"
"по словарному порядку, в противоположном случае - это слой переднего плана."
#: ../src/LevelEditor.cpp:539
msgid "Notification block"
msgstr "Блок оповещения"
#: ../src/LevelEditor.cpp:545
msgid "Enter message here:"
msgstr "Введите сообщение:"
#: ../src/LevelEditor.cpp:646
msgid "Behavior"
msgstr "Поведение"
#: ../src/LevelEditor.cpp:665
msgid "State"
msgstr "Состояние"
#: ../src/LevelEditor.cpp:673
msgid "Conveyor belt speed"
msgstr "Скорость конвейера"
#: ../src/LevelEditor.cpp:679
msgid "Enter speed here:"
msgstr "Введите скорость:"
#: ../src/LevelEditor.cpp:690
msgid "NOTE: 1 Speed = 0.08 block/s"
msgstr "ПРИМ.: 1 Скорость = 0,08 блоков/с"
#: ../src/LevelEditor.cpp:721
msgid "Id:"
msgstr "Ид:"
#: ../src/LevelEditor.cpp:787
msgid "Level Scripting"
msgstr "Скрипты уровня"
#: ../src/LevelEditor.cpp:892
msgid "Add layer"
msgstr "Добавить слой"
#: ../src/LevelEditor.cpp:898
msgid "Enter the layer name:"
msgstr "Введите название слоя:"
#: ../src/LevelEditor.cpp:943
#, c-format
msgid "Are you sure you want to delete layer '%s'?"
msgstr "Вы уверены, что Вы хотите удалить слой '%s'?"
#: ../src/LevelEditor.cpp:944
msgid "Delete layer"
msgstr "Удалить слой"
#: ../src/LevelEditor.cpp:968
msgid "Layer settings"
msgstr "Настроить слой"
#: ../src/LevelEditor.cpp:974
msgid "Layer name:"
msgstr "Название слоя:"
#: ../src/LevelEditor.cpp:989
msgid "Layer moving speed (1 speed = 0.8 block/s):"
msgstr "Скорость перемещения слоя (1 скорость = 0,08 блоков/с):"
#: ../src/LevelEditor.cpp:1010
msgid "Speed of following camera:"
msgstr "Скорость камеры:"
#: ../src/LevelEditor.cpp:1062
msgid "Move to layer"
msgstr "Переместить в слой"
#: ../src/LevelEditor.cpp:1068
msgid "Enter the layer name (create new layer if necessary):"
msgstr "Введите название слоя (создать новый слой при необходимости):"
#: ../src/LevelEditor.cpp:1132
msgid "Repeat mode"
msgstr "Режим повторения"
#: ../src/LevelEditor.cpp:1156
msgid "Custom scenery:"
msgstr "Фон:"
#: ../src/LevelEditor.cpp:1219
msgid "(Use the default appearance for this block)"
msgstr "(Использовать обычный вид этого блока)"
#: ../src/LevelEditor.cpp:1465 ../src/LevelEditor.cpp:1707
#: ../src/LevelEditor.cpp:1723 ../src/LevelEditor.cpp:1772
#: ../src/LevelEditor.cpp:4400
msgid "Custom scenery block"
msgstr "Блок фона"
#: ../src/LevelEditor.cpp:1673
msgid "Toolbox"
msgstr "Инструменты"
#: ../src/LevelEditor.cpp:1705
#, c-format
msgid "Resize %s"
msgstr "Изменить размер %s"
#: ../src/LevelEditor.cpp:1705
#, c-format
msgid "Move %s"
msgstr "Переместить %s"
#: ../src/LevelEditor.cpp:1713
#, c-format
msgid "Move %d object"
msgid_plural "Move %d objects"
msgstr[0] "Переместить %d объект"
msgstr[1] "Переместить %d объекта"
msgstr[2] "Переместить %d объектов"
msgstr[3] "Переместить %d объектов"
#: ../src/LevelEditor.cpp:1721
#, c-format
msgid "Add %s"
msgstr "Добавить %s"
#: ../src/LevelEditor.cpp:1721
#, c-format
msgid "Remove %s"
msgstr "Удалить %s"
#: ../src/LevelEditor.cpp:1729
#, c-format
msgid "Add %d object"
msgid_plural "Add %d objects"
msgstr[0] "Добавить %d объект"
msgstr[1] "Добавить %d объекта"
msgstr[2] "Добавить %d объектов"
msgstr[3] "Добавить %d объектов"
#: ../src/LevelEditor.cpp:1731
#, c-format
msgid "Remove %d object"
msgid_plural "Remove %d objects"
msgstr[0] "Удалить %d объект"
msgstr[1] "Удалить %d объекта"
msgstr[2] "Удалить %d объектов"
msgstr[3] "Удалить %d объектов"
#: ../src/LevelEditor.cpp:1739
#, c-format
msgid "Add path to %s"
msgstr "Добавить путь к %s"
#: ../src/LevelEditor.cpp:1741
#, c-format
msgid "Remove a path point from %s"
msgstr "Удалить точку пути из %s"
#: ../src/LevelEditor.cpp:1747
#, c-format
msgid "Remove all paths from %s"
msgstr "Удалить все пути из %s"
#: ../src/LevelEditor.cpp:1753
#, c-format
msgid "Add link from %s to %s"
msgstr "Добавить сслыку между %s и %s"
#: ../src/LevelEditor.cpp:1759
#, c-format
msgid "Remove all links from %s"
msgstr "Удалить все ссылки из %s"
#: ../src/LevelEditor.cpp:1766
msgid "Modify the %2 property of %1"
msgstr "Изменить у %1 свойство %2"
#: ../src/LevelEditor.cpp:1818
#, c-format
msgid "Edit the script of %s"
msgstr "Редактировать скрипт %s"
#: ../src/LevelEditor.cpp:1821
msgid "Edit the script of level"
msgstr "Редактировать скрипт уровня"
#: ../src/LevelEditor.cpp:2146 ../src/LevelEditor.cpp:2226
msgid "The level has unsaved changes."
msgstr "В уровне есть несохранённые изменения."
#: ../src/LevelEditor.cpp:2150 ../src/LevelEditor.cpp:2228
msgid "Are you sure you want to quit?"
msgstr "Вы действительно хотите выйти?"
#: ../src/LevelEditor.cpp:2150 ../src/LevelEditor.cpp:2228
msgid "Quit prompt"
msgstr "Подтвердить выход"
#: ../src/LevelEditor.cpp:2797 ../src/LevelEditor.cpp:2799
#, c-format
msgid "Level \"%s\" saved"
msgstr "Уровень \"%s\" сохранён"
#: ../src/LevelEditor.cpp:2797 ../src/LevelEditor.cpp:2799
msgid "Saved"
msgstr "Сохранено"
#: ../src/LevelEditor.cpp:2859 ../src/LevelEditSelect.cpp:208
msgid "Name:"
msgstr "Название:"
#: ../src/LevelEditor.cpp:2866
msgid "Theme:"
msgstr "Тема:"
#: ../src/LevelEditor.cpp:2873
msgid "Examples: %DATA%/themes/classic"
msgstr "Примеры: %DATA%/themes/classic"
#: ../src/LevelEditor.cpp:2875
msgid "or %USER%/themes/Orange"
msgstr "или %USER%/themes/Orange"
#: ../src/LevelEditor.cpp:2878
msgid "Music:"
msgstr "Музыка:"
#: ../src/LevelEditor.cpp:2887
msgid "Target time (s):"
msgstr "Необходимое время (с):"
#: ../src/LevelEditor.cpp:2903
msgid "Target recordings:"
msgstr "Необходимо записей:"
#: ../src/LevelEditor.cpp:2919
msgid "Restart level editor is required"
msgstr "Необходимо перезапустить редактор уровней"
#: ../src/LevelEditor.cpp:3679 ../src/LevelEditor.cpp:3718
#: ../src/LevelEditor.cpp:3739
msgid "Please enter a layer name."
msgstr "Пожалуйста, введите название слоя."
#: ../src/LevelEditor.cpp:3679 ../src/LevelEditor.cpp:3683
#: ../src/LevelEditor.cpp:3718 ../src/LevelEditor.cpp:3722
#: ../src/LevelEditor.cpp:3739 ../src/LevelEditor.cpp:3743
#: ../src/LevelEditSelect.cpp:644 ../src/LevelEditSelect.cpp:683
#: ../src/LevelEditSelect.cpp:688 ../src/LevelEditSelect.cpp:693
#: ../src/LevelEditSelect.cpp:698 ../src/LevelEditSelect.cpp:796
msgid "Error"
msgstr "Ошибка"
#: ../src/LevelEditor.cpp:3683 ../src/LevelEditor.cpp:3722
#, c-format
msgid "The layer '%s' already exists."
msgstr "Слой '%s' уже существует."
#: ../src/LevelEditor.cpp:3743
msgid "Source and destination layers are the same."
msgstr "Исходный и конечный слои совпадают."
#: ../src/LevelEditor.cpp:3760
msgid "Scenery"
msgstr "Фон"
#: ../src/LevelEditor.cpp:4190 ../src/LevelEditor.cpp:4218
#, c-format
msgid "Speed: %d = %0.2f block/s"
msgstr "Скорость: %d = %0.2f блоков/с"
#: ../src/LevelEditor.cpp:4203
msgid "Stop at this point"
msgstr "Остановиться в этой точке"
#: ../src/LevelEditor.cpp:4208
#, c-format
msgid "Pause: %d = %0.3fs"
msgstr "Пауза: %d = %0.3fс"
#: ../src/LevelEditSelect.cpp:41 ../src/TitleMenu.cpp:45
msgid "Map Editor"
msgstr "Редактор карт"
#: ../src/LevelEditSelect.cpp:66
msgid "New Levelpack"
msgstr "Новый сборник уровней"
#: ../src/LevelEditSelect.cpp:71
msgid "Pack Properties"
msgstr "Свойства сборника"
#: ../src/LevelEditSelect.cpp:76
msgid "Remove Pack"
msgstr "Удалить сборник"
#: ../src/LevelEditSelect.cpp:81
msgid "Move Map"
msgstr "Переместить карту"
#: ../src/LevelEditSelect.cpp:89
msgid "Remove Map"
msgstr "Удалить карту"
#: ../src/LevelEditSelect.cpp:94
msgid "Edit Map"
msgstr "Редактировать карту"
#: ../src/LevelEditSelect.cpp:205
msgid "Properties"
msgstr "Свойства"
#: ../src/LevelEditSelect.cpp:217
msgid "Description:"
msgstr "Описание:"
#: ../src/LevelEditSelect.cpp:226
msgid "Congratulation text:"
msgstr "Текст поздравления:"
#: ../src/LevelEditSelect.cpp:235
msgid "Music list:"
msgstr "Список музыки:"
#: ../src/LevelEditSelect.cpp:265 ../src/LevelEditSelect.cpp:485
msgid "Add level"
msgstr "Добавить уровень"
#: ../src/LevelEditSelect.cpp:268
msgid "File name:"
msgstr "Название файла:"
#: ../src/LevelEditSelect.cpp:293
msgid "Move level"
msgstr "Переместить уровень"
#: ../src/LevelEditSelect.cpp:296
msgid "Level: "
msgstr "Уровень: "
#: ../src/LevelEditSelect.cpp:310
msgid "Before"
msgstr "До"
#: ../src/LevelEditSelect.cpp:311
msgid "After"
msgstr "После"
#: ../src/LevelEditSelect.cpp:368 ../src/LevelPlaySelect.cpp:124
msgid "Individual levels which are not contained in any level packs"
msgstr "Отдельные уровни, которые не содержатся ни в одном сборнике уровней"
#: ../src/LevelEditSelect.cpp:577
#, c-format
msgid "Are you sure remove the level pack '%s'?"
msgstr "Вы уверены, что хотите удалить сборник уровней '%s'?"
#: ../src/LevelEditSelect.cpp:577 ../src/LevelEditSelect.cpp:607
msgid "Remove prompt"
msgstr "Подтвердить удаление"
#: ../src/LevelEditSelect.cpp:607
#, c-format
msgid "Are you sure remove the map '%s'?"
msgstr "Вы уверены, что хотите удалить карту '%s'?"
#: ../src/LevelEditSelect.cpp:644
msgid "Levelpack name cannot be empty."
msgstr "Название сборника уровней не может быть пустым."
#: ../src/LevelEditSelect.cpp:683
#, c-format
msgid "The levelpack directory '%s' already exists!"
msgstr "Папка сборника уровней '%s' уже существует!"
#: ../src/LevelEditSelect.cpp:688
#, c-format
msgid "Unable to create levelpack directory '%s'!"
msgstr "Не удалось создать папку сборника уровней '%s'!"
#: ../src/LevelEditSelect.cpp:693
#, c-format
msgid "The levelpack file '%s' already exists!"
msgstr "Файл сборника уровней '%s' уже существует!"
#: ../src/LevelEditSelect.cpp:698
#, c-format
msgid "Unable to create levelpack file '%s'!"
msgstr "Не удалось создать файл сборника уровней '%s'!"
#: ../src/LevelEditSelect.cpp:758
msgid "No file name given for the new level."
msgstr "Новому уровню не было присвоено имя файла."
#: ../src/LevelEditSelect.cpp:758
msgid "Missing file name"
msgstr "Отсутствует имя файла"
#: ../src/LevelEditSelect.cpp:796
#, c-format
msgid "The file %s already exists."
msgstr "Файл %s уже существует."
#: ../src/LevelEditSelect.cpp:849
msgid "The entered level number isn't valid!"
msgstr "Введённый номер уровня некорректен!"
#: ../src/LevelEditSelect.cpp:849
msgid "Illegal number"
msgstr "Некорректное число"
#: ../src/LevelInfoRender.cpp:19
msgid "Choose a level"
msgstr "Выберите уровень"
#: ../src/LevelInfoRender.cpp:20
msgid "Time:"
msgstr "Время:"
#: ../src/LevelInfoRender.cpp:21 ../src/StatisticsScreen.cpp:259
msgid "Recordings:"
msgstr "Записей:"
#: ../src/LevelPackManager.cpp:124
msgid "Custom Levels"
msgstr "Другие уровни"
#: ../src/LevelPlaySelect.cpp:41
msgid "Select Level"
msgstr "Выберите уровень"
#: ../src/OptionsMenu.cpp:66
msgid "Clear Progress"
msgstr "Очистить прогресс"
#: ../src/OptionsMenu.cpp:109
msgid "General"
msgstr "Общие"
#: ../src/OptionsMenu.cpp:110
msgid "Controls"
msgstr "Управление"
#: ../src/OptionsMenu.cpp:121
msgid "Music"
msgstr "Музыка"
#: ../src/OptionsMenu.cpp:129
msgid "Sound"
msgstr "Звуки"
#: ../src/OptionsMenu.cpp:137
msgid "Resolution"
msgstr "Разрешение"
#: ../src/OptionsMenu.cpp:177
msgid "Language"
msgstr "Язык"
#: ../src/OptionsMenu.cpp:185
msgid "Auto-Detect"
msgstr "Автоопределение"
#: ../src/OptionsMenu.cpp:209
msgid "Theme"
msgstr "Тема"
#: ../src/OptionsMenu.cpp:247
msgid "Internet proxy"
msgstr "Интернет-прокси"
#: ../src/OptionsMenu.cpp:256
msgid "Fullscreen"
msgstr "На весь экран"
#: ../src/OptionsMenu.cpp:261
msgid "Quick record"
msgstr "Быстрая запись"
#: ../src/OptionsMenu.cpp:266
msgid "Internet"
msgstr "Интернет"
#: ../src/OptionsMenu.cpp:271
msgid "Fade transition"
msgstr "Плавный переход"
#: ../src/OptionsMenu.cpp:294
msgid "Save Changes"
msgstr "Сохранить изменения"
#: ../src/OptionsMenu.cpp:513
msgid "Do you really want to reset level progress?"
msgstr "Вы действительно хотите очистить прогресс уровня?"
#: ../src/OptionsMenu.cpp:513
msgid "Warning"
msgstr "Внимание"
#: ../src/StatisticsManager.cpp:386
msgid "New achievement:"
msgstr "Новое достижение:"
#: ../src/StatisticsManager.cpp:394
#, c-format
msgid "Achieved on %s"
msgstr "Достижение %s"
#: ../src/StatisticsManager.cpp:400
msgid "Unknown achievement"
msgstr "Неизвестное достижение"
#: ../src/StatisticsManager.cpp:406
#, c-format
msgid "Achieved %1.0f%%"
msgstr "Достижение %1.0f%%"
#: ../src/StatisticsManager.cpp:410
msgid "Not achieved"
msgstr "Не достигнуто"
#: ../src/StatisticsScreen.cpp:57 ../src/TitleMenu.cpp:55
msgid "Achievements and Statistics"
msgstr "Достижения и статистика"
#: ../src/StatisticsScreen.cpp:166
msgid "Achievements"
msgstr "Достижения"
#: ../src/StatisticsScreen.cpp:167
msgid "Statistics"
msgstr "Статистика"
#: ../src/StatisticsScreen.cpp:234
msgid "Total"
msgstr "Всего"
#: ../src/StatisticsScreen.cpp:246
msgid "Traveling distance (m)"
msgstr "Пройденное расстояние (м)"
#: ../src/StatisticsScreen.cpp:247
msgid "Jump times"
msgstr "Прыжков"
#: ../src/StatisticsScreen.cpp:248
msgid "Die times"
msgstr "Смертей"
#: ../src/StatisticsScreen.cpp:249
msgid "Squashed times"
msgstr "Раздавлен"
#: ../src/StatisticsScreen.cpp:260
msgid "Switch pulled times:"
msgstr "Включено выключателей:"
#: ../src/StatisticsScreen.cpp:261
msgid "Swap times:"
msgstr "Поменялся:"
#: ../src/StatisticsScreen.cpp:262
msgid "Save times:"
msgstr "Сохранений:"
#: ../src/StatisticsScreen.cpp:263
msgid "Load times:"
msgstr "Загрузок:"
#: ../src/StatisticsScreen.cpp:268
msgid "Completed levels:"
msgstr "Завершённых уровней:"
#: ../src/StatisticsScreen.cpp:306
msgid "In-game time:"
msgstr "Время в игре:"
#: ../src/StatisticsScreen.cpp:308
msgid "Level editing time:"
msgstr "Время в редакторе:"
#: ../src/StatisticsScreen.cpp:310
msgid "Created levels:"
msgstr "Создано уровней:"
#: ../src/TitleMenu.cpp:44
msgid "Options"
msgstr "Настройки"
#: ../src/TitleMenu.cpp:47
msgid "Quit"
msgstr "Выход"
#: ../src/TitleMenu.cpp:131
msgid "Enable internet in order to install addons."
msgstr "Чтобы устанавливать дополнения, разрешите подключение к Интернету."
#: ../src/TitleMenu.cpp:131
msgid "Internet disabled"
msgstr "Подключение к Интернету запрещено"
msgctxt "keys"
msgid "Return"
msgstr "Return"
msgctxt "keys"
msgid "Escape"
msgstr "Escape"
msgctxt "keys"
msgid "Backspace"
msgstr "Backspace"
msgctxt "keys"
msgid "Tab"
msgstr "Tab"
msgctxt "keys"
msgid "Space"
msgstr "Пробел"
msgctxt "keys"
msgid "CapsLock"
msgstr "CapsLock"
msgctxt "keys"
msgid "PrintScreen"
msgstr "PrintScreen"
msgctxt "keys"
msgid "ScrollLock"
msgstr "ScrollLock"
msgctxt "keys"
msgid "Pause"
msgstr "Pause"
msgctxt "keys"
msgid "Insert"
msgstr "Insert"
msgctxt "keys"
msgid "Home"
msgstr "Home"
msgctxt "keys"
msgid "PageUp"
msgstr "PageUp"
msgctxt "keys"
msgid "Delete"
msgstr "Delete"
msgctxt "keys"
msgid "End"
msgstr "End"
msgctxt "keys"
msgid "PageDown"
msgstr "PageDown"
msgctxt "keys"
msgid "Right"
msgstr "Вправо"
msgctxt "keys"
msgid "Left"
msgstr "Влево"
msgctxt "keys"
msgid "Down"
msgstr "Вниз"
msgctxt "keys"
msgid "Up"
msgstr "Вверх"
msgctxt "keys"
msgid "Numlock"
msgstr "Numlock"
msgctxt "keys"
msgid "SysReq"
msgstr "SysReq"
msgctxt "keys"
msgid "Left Ctrl"
msgstr "Левый Ctrl"
msgctxt "keys"
msgid "Left Shift"
msgstr "Левый Shift"
msgctxt "keys"
msgid "Left Alt"
msgstr "Левый Alt"
msgctxt "keys"
msgid "Left GUI"
msgstr "Левый GUI"
msgctxt "keys"
msgid "Right Ctrl"
msgstr "Правый Ctrl"
msgctxt "keys"
msgid "Right Shift"
msgstr "Правый Shift"
msgctxt "keys"
msgid "Right Alt"
msgstr "Правый Alt"
msgctxt "keys"
msgid "Right GUI"
msgstr "Правый GUI"
diff --git a/data/locale/uk.po b/data/locale/uk.po
index 3b17f28..8535eac 100644
--- a/data/locale/uk.po
+++ b/data/locale/uk.po
@@ -1,2110 +1,2111 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the meandmyshadow package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: meandmyshadow 0.5svn\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-09-09 16:18+0800\n"
-"PO-Revision-Date: 2018-09-13 12:13+0000\n"
-"Last-Translator: Jz Pan <acme_pjz@hotmail.com>\n"
-"Language-Team: Ukrainian <https://hosted.weblate.org/projects/me-and-my-shadow/"
-"translations/uk/>\n"
+"PO-Revision-Date: 2018-10-24 16:42+0000\n"
+"Last-Translator: Olexandr Nesterenko <olexn@ukr.net>\n"
+"Language-Team: Ukrainian <https://hosted.weblate.org/projects/"
+"me-and-my-shadow/translations/uk/>\n"
"Language: uk\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
-"n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || "
-"(n%100>=11 && n%100<=14)? 2 : 3);\n"
-"X-Generator: Weblate 3.2-dev\n"
+"Plural-Forms: nplurals=4; plural=(n % 1 == 0 && n % 10 == 1 && n % 100 != 11 "
+"? 0 : n % 1 == 0 && n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > "
+"14) ? 1 : n % 1 == 0 && (n % 10 ==0 || (n % 10 >=5 && n % 10 <=9) || (n % "
+"100 >=11 && n % 100 <=14 )) ? 2: 3);\n"
+"X-Generator: Weblate 3.3-dev\n"
#: ../src/AchievementList.cpp:43
msgid "Newbie"
msgstr "Початківець"
#: ../src/AchievementList.cpp:43
msgid "Complete a level."
msgstr "Завершити один рівень."
#: ../src/AchievementList.cpp:44
msgid "Experienced player"
msgstr "Досвідчений гравець"
#: ../src/AchievementList.cpp:44
msgid "Complete 50 levels."
msgstr "Завершити 50 рівнів."
#: ../src/AchievementList.cpp:45
msgid "Good job!"
msgstr "Молодець!"
#: ../src/AchievementList.cpp:45
msgid "Receive a gold medal."
msgstr "Отримати золоту медаль."
#: ../src/AchievementList.cpp:46
msgid "Expert"
msgstr "Експерт"
#: ../src/AchievementList.cpp:46
msgid "Earn 50 gold medal."
msgstr "Отримати 50 золотих медалей."
#: ../src/AchievementList.cpp:48
msgid "Graduate"
msgstr "Випускник"
#: ../src/AchievementList.cpp:48
msgid "Complete the tutorial level pack."
-msgstr "Завершити збірник навчальних рівнів."
+msgstr "Завершити збірку навчальних рівнів."
#: ../src/AchievementList.cpp:49
msgid "Outstanding graduate"
msgstr "Відмінник"
#: ../src/AchievementList.cpp:49
msgid "Complete the tutorial level pack with gold for all levels."
msgstr "Завершити усі навчальні рівні із золотими медалями."
#: ../src/AchievementList.cpp:51
msgid "Hooked"
msgstr "Засів надовго"
#: ../src/AchievementList.cpp:51
msgid "Play Me and My Shadow for more than 2 hours."
-msgstr "Грати у Me and My Shadow більше двох годин."
+msgstr "Грати більше двох годин."
#: ../src/AchievementList.cpp:52
msgid "Loyal fan of Me and My Shadow"
msgstr "Вірний фанат"
#: ../src/AchievementList.cpp:52
msgid "Play Me and My Shadow for more than 24 hours."
-msgstr "Грати у Me and My Shadow довше 24 годин."
+msgstr "Грати довше 24 годин."
#: ../src/AchievementList.cpp:54
msgid "Constructor"
msgstr "Конструктор"
#: ../src/AchievementList.cpp:54
msgid "Use the level editor for more than 2 hours."
msgstr "Використовувати редактор рівнів більше двох годин."
#: ../src/AchievementList.cpp:55
msgid "The creator"
msgstr "Творець"
#: ../src/AchievementList.cpp:55
msgid "Use the level editor for more than 24 hours."
msgstr "Використовувати редактор рівнів більше 24 годин."
#: ../src/AchievementList.cpp:57
msgid "Look, cute level!"
msgstr "Ой, яке ж воно файне!"
#: ../src/AchievementList.cpp:57
msgid "Create a level for the first time."
msgstr "Створити свій перший рівень."
#: ../src/AchievementList.cpp:58
msgid "The level museum"
msgstr "Музей рівнебудівництва"
#: ../src/AchievementList.cpp:58
msgid "Create 50 levels."
msgstr "Створити 50 рівнів."
#: ../src/AchievementList.cpp:60
msgid "Hello, World!"
msgstr "Hello, World!"
#: ../src/AchievementList.cpp:60
msgid "Write a script for the first time."
msgstr "Написати свій перший скрипт."
#: ../src/AchievementList.cpp:62
msgid "Frog"
msgstr "Коник-стрибунець"
#: ../src/AchievementList.cpp:62
msgid "Jump 1000 times."
msgstr "Стрибнути 1000 разів."
#: ../src/AchievementList.cpp:64
msgid "Wanderer"
msgstr "Пішохід"
#: ../src/AchievementList.cpp:64
msgid "Travel 100 meters."
msgstr "Пройти 100 метрів."
#: ../src/AchievementList.cpp:65
msgid "Runner"
msgstr "Мандрівник"
#: ../src/AchievementList.cpp:65
msgid "Travel 1 kilometer."
msgstr "Пройти 1 кілометр."
#: ../src/AchievementList.cpp:66
msgid "Long distance runner"
msgstr "Дальнобійник"
#: ../src/AchievementList.cpp:66
msgid "Travel 10 kilometers."
msgstr "Пройти 10 кілометрів."
#: ../src/AchievementList.cpp:67
msgid "Marathon runner"
msgstr "Марафонець"
#: ../src/AchievementList.cpp:67
msgid "Travel 42,195 meters."
-msgstr "Пройти 42195 метрів."
+msgstr "Пройти дистанцію у 42195 метрів."
#: ../src/AchievementList.cpp:69
msgid "Be careful!"
msgstr "Обережно!"
#: ../src/AchievementList.cpp:69
msgid "Die for the first time."
msgstr "Вмерти вперше."
#: ../src/AchievementList.cpp:70
msgid "It doesn't matter..."
msgstr "Я вже звикаю..."
#: ../src/AchievementList.cpp:70
msgid "Die 50 times."
msgstr "Померти 50 разів."
#: ../src/AchievementList.cpp:71
msgid "Expert of trial and error"
msgstr "Досвідчений мрець"
#: ../src/AchievementList.cpp:71
msgid "Die 1000 times."
msgstr "Померти 1000 разів."
#: ../src/AchievementList.cpp:73
msgid "Keep an eye for moving blocks!"
msgstr "Стережись рухомих блоків!"
#: ../src/AchievementList.cpp:73
msgid "Get squashed for the first time."
msgstr "Бути розчавленим уперше."
#: ../src/AchievementList.cpp:74
msgid "Potato masher"
msgstr "Коцюрба"
#: ../src/AchievementList.cpp:74
msgid "Get squashed 50 times."
msgstr "Бути розчавленим 50 разів."
#: ../src/AchievementList.cpp:76
msgid "Double kill"
msgstr "За двома зайцями"
#: ../src/AchievementList.cpp:76
msgid "Get both the player and the shadow dead."
msgstr "І гравець і тінь померли."
#: ../src/AchievementList.cpp:78
msgid "Bad luck"
msgstr "От, халепа"
#: ../src/AchievementList.cpp:78
msgid "Die 5 times in under 5 seconds."
msgstr "Померти 5 разів менш ніж за 5 секунд."
#: ../src/AchievementList.cpp:79
msgid "This level is too dangerous"
msgstr "Хай йому грець"
#: ../src/AchievementList.cpp:79
msgid "Die 10 times in under 5 seconds."
msgstr "Померти 10 разів менш ніж за 5 секунд."
#: ../src/AchievementList.cpp:81
msgid "You forgot your friend"
msgstr "Друзів не лишають у біді"
#: ../src/AchievementList.cpp:81
msgid "Finish the level with the player or the shadow dead."
msgstr "Завершити рівень при тому, що або гравець, або тінь померли."
#: ../src/AchievementList.cpp:82
msgid "Just in time"
msgstr "У самісіньке яблучко"
#: ../src/AchievementList.cpp:82
msgid "Reach the exit with the player and the shadow simultaneously."
msgstr "Одночасно досягнути виходу і гравцем, і тінню."
#: ../src/AchievementList.cpp:84
msgid "Recorder"
-msgstr "Рекордсмен"
+msgstr "Самописець"
#: ../src/AchievementList.cpp:84
msgid "Record 100 times."
-msgstr "Поставити рекорд 100 разів."
+msgstr "Зробити 100 записів."
#: ../src/AchievementList.cpp:85
msgid "Shadowmaster"
-msgstr "Чемпіон"
+msgstr "Редактор часопису"
#: ../src/AchievementList.cpp:85
msgid "Record 1000 times."
-msgstr "Поставити рекорд 1000 разів."
+msgstr "Зробити 1000 записів."
#: ../src/AchievementList.cpp:87
msgid "Switch puller"
msgstr "Вмикач вимикачів"
#: ../src/AchievementList.cpp:87
msgid "Pull the switch 100 times."
-msgstr "Увімкнути вимикач 100 разів."
+msgstr "Увімкнути 100 вимикачів."
#: ../src/AchievementList.cpp:88
msgid "The switch is broken!"
msgstr "Псувач вимикачів"
#: ../src/AchievementList.cpp:88
msgid "Pull the switch 1000 times."
-msgstr "Увімкнути вимикач 1000 разів."
+msgstr "Увімкнути 1000 вимикачів."
#: ../src/AchievementList.cpp:90
msgid "Swapper"
msgstr "Ся міняю"
#: ../src/AchievementList.cpp:90
msgid "Swap 100 times."
msgstr "Помінятися 100 разів."
#: ../src/AchievementList.cpp:91
msgid "Player to shadow to player to shadow..."
msgstr "Туди-сюдитель"
#: ../src/AchievementList.cpp:91
msgid "Swap 1000 times."
msgstr "Помінятися 1000 разів."
#: ../src/AchievementList.cpp:93
msgid "Play it save"
msgstr "Добре зберігся"
#: ../src/AchievementList.cpp:93
msgid "Save 1000 times."
msgstr "Зберегти гру 1000 разів."
#: ../src/AchievementList.cpp:94
msgid "This game is too hard"
msgstr "Ох і важко ж"
#: ../src/AchievementList.cpp:94
msgid "Load the game 1000 times."
msgstr "Завантажити гру 1000 разів."
#: ../src/AchievementList.cpp:96
msgid "No, thanks"
msgstr "Ні, дякую"
#: ../src/AchievementList.cpp:96
msgid "Complete a level with checkpoint, but without saving."
msgstr "Пройти рівень із чекпоінтом, але без збережень гри."
#: ../src/AchievementList.cpp:98
msgid "Panic save"
msgstr "Самозбережник"
#: ../src/AchievementList.cpp:98
msgid "Save twice in 1 second."
msgstr "Зберегти гру двічі за секунду."
#: ../src/AchievementList.cpp:99
msgid "Panic load"
msgstr "Панічне завантаження"
#: ../src/AchievementList.cpp:99
msgid "Load twice in 1 second."
msgstr "Завантажити гру двічі за секунду."
#: ../src/AchievementList.cpp:101
msgid "Bad saving position"
msgstr "Кепське місце для збереження"
#: ../src/AchievementList.cpp:101
msgid "Load the game and die within 1 second."
-msgstr "Завантажити гру й померти протягом одної секунди."
+msgstr "Завантажити гру й померти протягом однієї секунди."
#: ../src/AchievementList.cpp:102
msgid "This level is too hard"
msgstr "Заважкий рівень"
#: ../src/AchievementList.cpp:102
msgid "Load the same save and die 100 times."
-msgstr "Завантажити гру і померти 100 разів."
+msgstr "Завантажити ту саму гру і померти 100 разів."
#: ../src/AchievementList.cpp:104
msgid "Quick swap"
msgstr "Швидка зміна"
#: ../src/AchievementList.cpp:104
msgid "Swap twice in under a second."
msgstr "Помінятися двічі на секунду."
#: ../src/AchievementList.cpp:107
msgid "Horizontal confusion"
msgstr "Забув де право, а де ліво"
#: ../src/AchievementList.cpp:107
msgid "Press left and right simultaneously."
msgstr "Натиснути ліворуч і праворуч одночасно."
#: ../src/AchievementList.cpp:109
msgid "Cheater"
msgstr "Нечемний"
#: ../src/AchievementList.cpp:109
msgid "Cheat in game."
msgstr "Змухлювати у грі."
#: ../src/AchievementList.cpp:111
msgid "Programmer"
msgstr "Тижпрограміст"
#: ../src/AchievementList.cpp:111
msgid "Play the development version of Me and My Shadow."
msgstr "Грати у версію у розробці."
#: ../src/Addons.cpp:44 ../src/LevelPackManager.cpp:108
msgid "Levels"
msgstr "Рівні"
#: ../src/Addons.cpp:44
msgid "Single level which usually contain demanding puzzles"
-msgstr "Один рівень, що зазвичай містить головоломки"
+msgstr "Один рівень, що містить головоломки"
#: ../src/Addons.cpp:45
msgid "Levelpacks"
msgstr "Збірка рівнів"
#: ../src/Addons.cpp:45
msgid "Collection of levels with the same author or style"
msgstr "Колекція рівнів від одного автора чи із подібним стилем"
#: ../src/Addons.cpp:46
msgid "Themes"
msgstr "Оформлення"
#: ../src/Addons.cpp:46
msgid "Give every block and background a new look and feel"
-msgstr "Надати кожному блоку й тлу новий вигляд і відчуття"
+msgstr "Надати кожному блоку й тлу свіжий вигляд"
#: ../src/Addons.cpp:55 ../src/TitleMenu.cpp:46
msgid "Addons"
msgstr "Застосунки"
#: ../src/Addons.cpp:87
msgid "Unable to initialize addon menu:"
msgstr "Не вдалося ініціалізувати меню застосунків:"
#: ../src/Addons.cpp:95 ../src/Addons.cpp:158 ../src/Addons.cpp:662
#: ../src/Addons.cpp:690 ../src/CreditsMenu.cpp:89 ../src/LevelSelect.cpp:168
#: ../src/StatisticsScreen.cpp:159
msgid "Back"
-msgstr "Повернутися"
+msgstr "Назад"
#: ../src/Addons.cpp:169
msgid "ERROR: unable to download addons file!"
msgstr "ПОМИЛКА: неможливо зкачати файл застосунку!"
# TRANSLATORS: addon_list is the name of a file and should not be translated.
#: ../src/Addons.cpp:182
msgid "ERROR: unable to load addon_list file!"
msgstr "ПОМИЛКА: неможливо завантажити файл addon_list!"
#: ../src/Addons.cpp:193
msgid "ERROR: Invalid file format of addons file!"
msgstr "ПОМИЛКА: Невірний формат файлу застосунку!"
#: ../src/Addons.cpp:205
msgid "ERROR: Addon list version is unsupported!"
msgstr "ПОМИЛКА: Не підтримується версія списку застосунків!"
# TRANSLATORS: installed_addons is the name of a file and should not be
# translated.
#: ../src/Addons.cpp:226
msgid "ERROR: Unable to create the installed_addons file."
msgstr "ПОМИЛКА: Неможливо створити файл installed_addons."
#: ../src/Addons.cpp:238
msgid "ERROR: Invalid file format of the installed_addons!"
msgstr "ПОМИЛКА: Невірний формат файлу installed_addons!"
# TRANSLATORS: indicates the author of an addon.
#: ../src/Addons.cpp:389 ../src/Addons.cpp:621
#, c-format
msgid "by %s"
msgstr "від %s"
#: ../src/Addons.cpp:397
msgid "Installed"
msgstr "Установлено"
#: ../src/Addons.cpp:402
msgid "Updatable"
msgstr "Оновити"
#: ../src/Addons.cpp:412
msgid "Not installed"
msgstr "Не встановлено"
#: ../src/Addons.cpp:625
#, c-format
msgid "Version: %d\n"
msgstr "Версія: %d\n"
#: ../src/Addons.cpp:627
#, c-format
msgid "Installed version: %d\n"
msgstr "Установлена версія: %d\n"
#: ../src/Addons.cpp:630
#, c-format
msgid "License: %s\n"
msgstr "Ліцензія: %s\n"
#: ../src/Addons.cpp:633
#, c-format
msgid "Website: %s\n"
msgstr "Інтернет-сторінка: %s\n"
#: ../src/Addons.cpp:637
msgid "(No descriptions provided)"
msgstr "(Немає опису)"
#: ../src/Addons.cpp:657 ../src/Addons.cpp:684
msgid "Remove"
msgstr "Видалити"
#: ../src/Addons.cpp:673
msgid "Update"
msgstr "Оновити"
#: ../src/Addons.cpp:679
msgid "Install"
msgstr "Установити"
#: ../src/Addons.cpp:774
#, c-format
msgid "This addon can't be removed because it's needed by %s."
msgstr "Цей застосунок неможливо видалити, оскільки його потребує %s."
#: ../src/Addons.cpp:774 ../src/Addons.cpp:1051
msgid "Dependency"
-msgstr "Залежить"
+msgstr "Залежності"
#: ../src/Addons.cpp:803
#, c-format
msgid "WARNING: File '%s' appears to have been removed already."
msgstr "УВАГА: Схоже, що файл '%s' вже був видалений."
#: ../src/Addons.cpp:803 ../src/Addons.cpp:810 ../src/Addons.cpp:818
#: ../src/Addons.cpp:825 ../src/Addons.cpp:834 ../src/Addons.cpp:840
#: ../src/Addons.cpp:859 ../src/Addons.cpp:866 ../src/Addons.cpp:893
#: ../src/Addons.cpp:900 ../src/Addons.cpp:907 ../src/Addons.cpp:918
#: ../src/Addons.cpp:947 ../src/Addons.cpp:952 ../src/Addons.cpp:962
#: ../src/Addons.cpp:968 ../src/Addons.cpp:981 ../src/Addons.cpp:986
#: ../src/Addons.cpp:1008 ../src/Addons.cpp:1014 ../src/Addons.cpp:1044
msgid "Addon error"
msgstr "Помилка застосунку"
#: ../src/Addons.cpp:810
#, c-format
msgid "ERROR: Unable to remove file '%s'!"
msgstr "ПОМИЛКА: Неможливо видалити файл '%s'!"
#: ../src/Addons.cpp:818
#, c-format
msgid "WARNING: Directory '%s' appears to have been removed already."
msgstr "УВАГА: Схоже, що директорія '%s' вже була видалена."
#: ../src/Addons.cpp:825
#, c-format
msgid "ERROR: Unable to remove directory '%s'!"
msgstr "ПОМИЛКА: Неможливо видалити директорію '%s'!"
#: ../src/Addons.cpp:834
#, c-format
msgid "WARNING: Level '%s' appears to have been removed already."
msgstr "УВАГА: Схоже, що рівень '%s' вже був видалений."
#: ../src/Addons.cpp:840
#, c-format
msgid "ERROR: Unable to remove level '%s'!"
msgstr "ПОМИЛКА: Неможливо видалити рівень '%s'!"
#: ../src/Addons.cpp:859
#, c-format
msgid "WARNING: Levelpack directory '%s' appears to have been removed already."
msgstr "УВАГА: Схоже, що директорія збірки рівнів '%s' вже була видалена."
#: ../src/Addons.cpp:866
#, c-format
msgid "ERROR: Unable to remove levelpack directory '%s'!"
msgstr "ПОМИЛКА: Неможливо створити директорію збірки рівнів '%s'!"
#: ../src/Addons.cpp:893
#, c-format
msgid "ERROR: Unable to download addon file %s."
msgstr "ПОМИЛКА: Неможливо зкачати файл застосунку %s."
#: ../src/Addons.cpp:900
#, c-format
msgid "ERROR: Unable to extract addon file %s."
msgstr "ПОМИЛКА: Неможливо розпакувати файл застосунку %s."
#: ../src/Addons.cpp:907
msgid "ERROR: Addon is missing metadata!"
msgstr "ПОМИЛКА: Застосунок не має метаданих!"
#: ../src/Addons.cpp:918
msgid "ERROR: Invalid file format for metadata file!"
msgstr "ПОМИЛКА: Невірний формат файлу метаданих!"
#: ../src/Addons.cpp:947
#, c-format
msgid "WARNING: File '%s' already exists, addon may be broken or not working!"
msgstr "УВАГА: Файл '%s' вже існує, застосунок може бути пошкодженим або непрацездатним!"
#: ../src/Addons.cpp:952
#, c-format
msgid ""
"WARNING: Unable to copy file '%s' to '%s', addon may be broken or not "
"working!"
msgstr "УВАГА: Неможливо скопіювати файл '%s' до '%s', застосунок може бути пошкодженим або непрацездатним!"
#: ../src/Addons.cpp:962
#, c-format
msgid ""
"WARNING: Destination directory '%s' already exists, addon may be broken or "
"not working!"
msgstr "УВАГА: Цільова директорія '%s' вже існує, застосунок може бути пошкодженим або непрацездатним!"
#: ../src/Addons.cpp:968 ../src/Addons.cpp:1014
#, c-format
msgid ""
"WARNING: Unable to move directory '%s' to '%s', addon may be broken or not "
"working!"
msgstr "УВАГА: Неможливо перемістити директорію '%s' до '%s', застосунок може бути пошкодженим або непрацездатним!"
#: ../src/Addons.cpp:981
#, c-format
msgid "WARNING: Level '%s' already exists, addon may be broken or not working!"
msgstr "УВАГА: Рівень '%s' вже існує, застосунок може бути пошкодженим або непрацездатним!"
#: ../src/Addons.cpp:986
#, c-format
msgid ""
"WARNING: Unable to copy level '%s' to '%s', addon may be broken or not "
"working!"
msgstr "УВАГА: Неможливо скопіювати рівень '%s' до '%s', застосунок може бути пошкодженим або непрацездатним!"
#: ../src/Addons.cpp:1008
#, c-format
msgid ""
"WARNING: Levelpack directory '%s' already exists, addon may be broken or not "
"working!"
msgstr "УВАГА: Директорія зі збіркою рівнів '%s' вже існує, застосунок може бути пошкодженим або непрацездатним!"
#: ../src/Addons.cpp:1044
#, c-format
msgid "ERROR: Addon requires another addon (%s) which can't be found!"
msgstr "ПОМИЛКА: Застосунок потребує інший застосунок (%s), який не вдалося знайти!"
#: ../src/Addons.cpp:1051
#, c-format
msgid "The addon %s is needed and will be installed now."
msgstr "Потрібний застосунок %s буде зараз установлено."
#: ../src/Block.cpp:822 ../src/LevelEditor.cpp:265
msgid "On"
msgstr "Увімк."
#: ../src/Block.cpp:823 ../src/LevelEditor.cpp:266
msgid "Off"
msgstr "Вимк."
#: ../src/CommandManager.cpp:41
#, c-format
msgid "Undo %s"
msgstr "Відмінити %s"
#: ../src/CommandManager.cpp:43
msgid "Can't undo"
msgstr "Неможливо відмінити"
#: ../src/CommandManager.cpp:49
#, c-format
msgid "Redo %s"
msgstr "Повернути %s"
#: ../src/CommandManager.cpp:51
msgid "Can't redo"
msgstr "Неможливо повернути"
# TRANSLATORS: Context: Undo/Redo ...
#: ../src/Commands.cpp:190
msgid "Resize level"
msgstr "Змінити розмір рівня"
# TRANSLATORS: Context: Undo/Redo ...
#: ../src/Commands.cpp:807
msgid "Modify level property"
msgstr "Змінити властивості рівня"
# TRANSLATORS: Context: Undo/Redo ...
#: ../src/Commands.cpp:919
#, c-format
msgid "Add scenery layer %s"
msgstr "Додати фоновий шар %s"
# TRANSLATORS: Context: Undo/Redo ...
#: ../src/Commands.cpp:921
#, c-format
msgid "Delete scenery layer %s"
msgstr "Видалити фоновий шар %s"
# TRANSLATORS: Context: Undo/Redo ...
#: ../src/Commands.cpp:951
#, c-format
msgid "Modify the property of scenery layer %s"
msgstr "Змінити властивості фонового шару %s"
# TRANSLATORS: Context: Undo/Redo ...
#: ../src/Commands.cpp:1040
#, c-format
msgid "Move %d object from layer %s to layer %s"
msgid_plural "Move %d objects from layer %s to layer %s"
msgstr[0] "Перемістити %d об'єкт із шару %s у шар %s"
msgstr[1] "Перемістити %d об'єкти із шару %s у шар %s"
msgstr[2] "Перемістити %d об'єктів із шару %s у шар %s"
msgstr[3] "Перемістити %d об'єктів із шару %s у шар %s"
#: ../src/CreditsMenu.cpp:35 ../src/TitleMenu.cpp:53
msgid "Credits"
-msgstr "Титри"
+msgstr "Подяки"
# TRANSLATORS: Font used in GUI:
# - Use "knewave" for languages using Latin and Latin-derived alphabets
# - "DroidSansFallback" can be used for non-Latin writing systems
#: ../src/Functions.cpp:569 ../src/Functions.cpp:570 ../src/Functions.cpp:571
#: ../src/Functions.cpp:588
msgid "knewave"
msgstr "DejaVuSansCondensed-Oblique"
# TRANSLATORS: Font used for normal text:
# - Use "Blokletters-Viltstift" for languages using Latin and Latin-derived
# alphabets
# - "DroidSansFallback" can be used for non-Latin writing systems
#: ../src/Functions.cpp:575
msgid "Blokletters-Viltstift"
msgstr "DejaVuSansCondensed-Oblique"
#: ../src/Functions.cpp:674
msgid "Loading..."
msgstr "Завантаження..."
#: ../src/Functions.cpp:1243 ../src/Functions.cpp:1270
#: ../src/LevelEditor.cpp:559 ../src/LevelEditor.cpp:693
#: ../src/LevelEditor.cpp:758 ../src/LevelEditor.cpp:821
#: ../src/LevelEditor.cpp:908 ../src/LevelEditor.cpp:1033
#: ../src/LevelEditor.cpp:1083 ../src/LevelEditor.cpp:1180
#: ../src/LevelEditor.cpp:1244 ../src/LevelEditor.cpp:2923
#: ../src/LevelEditSelect.cpp:244 ../src/LevelEditSelect.cpp:277
#: ../src/LevelEditSelect.cpp:317
msgid "OK"
msgstr "Так"
#: ../src/Functions.cpp:1244 ../src/Functions.cpp:1256
#: ../src/Functions.cpp:1266 ../src/LevelEditor.cpp:565
#: ../src/LevelEditor.cpp:699 ../src/LevelEditor.cpp:764
#: ../src/LevelEditor.cpp:827 ../src/LevelEditor.cpp:914
#: ../src/LevelEditor.cpp:1039 ../src/LevelEditor.cpp:1089
#: ../src/LevelEditor.cpp:1186 ../src/LevelEditor.cpp:1250
#: ../src/LevelEditor.cpp:2929 ../src/LevelEditSelect.cpp:248
#: ../src/LevelEditSelect.cpp:281 ../src/LevelEditSelect.cpp:321
#: ../src/OptionsMenu.cpp:289
msgid "Cancel"
msgstr "Відміна"
#: ../src/Functions.cpp:1248
msgid "Abort"
msgstr "Перервати"
#: ../src/Functions.cpp:1249 ../src/Functions.cpp:1265
msgid "Retry"
-msgstr "Спробувати знову"
+msgstr "Повторити"
#: ../src/Functions.cpp:1250
msgid "Ignore"
-msgstr "Ігнорувати"
+msgstr "Пропустити"
#: ../src/Functions.cpp:1254 ../src/Functions.cpp:1260
msgid "Yes"
msgstr "Так"
#: ../src/Functions.cpp:1255 ../src/Functions.cpp:1261
msgid "No"
msgstr "Ні"
# TRANSLATORS: Please do not remove %s or %d from your translation:
# - %d means the level number in a levelpack
# - %s means the name of current level
#: ../src/Game.cpp:280 ../src/Game.cpp:1236
#, c-format
msgid "Level %d %s"
msgstr "Рівень %d %s"
# TRANSLATORS: Please do not remove %s from your translation:
# - %s will be replaced with current action key
#: ../src/Game.cpp:915
#, c-format
msgid "Press %s key to save the game."
msgstr "Натисніть клавішу %s, щоб зберегти гру."
# TRANSLATORS: Please do not remove %s from your translation:
# - %s will be replaced with current action key
#: ../src/Game.cpp:920
#, c-format
msgid "Press %s key to swap the position of player and shadow."
msgstr "Натисніть клавішу %s, щоб поміняти гравця і тінь місцями."
# TRANSLATORS: Please do not remove %s from your translation:
# - %s will be replaced with current action key
#: ../src/Game.cpp:925
#, c-format
msgid "Press %s key to activate the switch."
msgstr "Натисніть %s, щоб увімкнути вимикач."
# TRANSLATORS: Please do not remove %s from your translation:
# - %s will be replaced with current action key
#: ../src/Game.cpp:930
#, c-format
msgid "Press %s key to teleport."
msgstr "Натисніть клавішу %s, щоб телепортуватися."
# TRANSLATORS: Please do not remove %s from your translation:
# - first %s means currently configured key to restart game
# - Second %s means configured key to load from last save
#: ../src/Game.cpp:972
#, c-format
msgid "Press %s to restart current level or press %s to load the game."
msgstr "Натисніть клавішу %s, щоб перезапустити поточний рівень, або натисніть клавішу %s, щоб завантажити гру."
# TRANSLATORS: Please do not remove %s from your translation:
# - %s will be replaced with currently configured key to restart game
#: ../src/Game.cpp:983
#, c-format
msgid "Press %s to restart current level."
msgstr "Натисніть клавішу %s, щоб перезапустити поточний рівень."
#: ../src/Game.cpp:996
msgid "Your shadow has died."
msgstr "Ваша тінь померла."
#: ../src/Game.cpp:1052
#, c-format
msgid "%d recording"
msgid_plural "%d recordings"
msgstr[0] "%d запис"
msgstr[1] "%d записи"
msgstr[2] "%d записів"
msgstr[3] "%d записів"
#: ../src/Game.cpp:1224
msgid "You've finished:"
msgstr "Ви завершили:"
# TRANSLATORS: Please do not remove %-.2f from your translation:
# - %-.2f means time in seconds
# - s is shortened form of a second. Try to keep it so.
#: ../src/Game.cpp:1291
#, c-format
msgid "Time: %-.2fs"
msgstr "Час: %-.2fs"
# TRANSLATORS: Please do not remove %-.2f from your translation:
# - %-.2f means time in seconds
# - s is shortened form of a second. Try to keep it so.
#: ../src/Game.cpp:1300
#, c-format
msgid "Best time: %-.2fs"
msgstr "Найкращий час: %-.2fs"
#: ../src/Game.cpp:1311
#, c-format
msgid "Target time: %-.2fs"
msgstr "Необхідний час: %-.2fs"
# TRANSLATORS: Please do not remove %d from your translation:
# - %d means the number of recordings user has made
#: ../src/Game.cpp:1332
#, c-format
msgid "Recordings: %d"
msgstr "Записів: %d"
# TRANSLATORS: Please do not remove %d from your translation:
# - %d means the number of recordings user has made
#: ../src/Game.cpp:1340
#, c-format
msgid "Best recordings: %d"
msgstr "Найкращі записи: %d"
#: ../src/Game.cpp:1350
#, c-format
msgid "Target recordings: %d"
msgstr "Необхідно записів: %d"
# TRANSLATORS: Please do not remove %s from your translation:
# - %s will be replaced with name of a prize medal (gold, silver or bronze)
#: ../src/Game.cpp:1363
#, c-format
msgid "You earned the %s medal"
msgstr "Ви отримали %s медаль"
#: ../src/Game.cpp:1363
msgid "GOLD"
msgstr "ЗОЛОТУ"
#: ../src/Game.cpp:1363
msgid "SILVER"
msgstr "СРІБНУ"
#: ../src/Game.cpp:1363
msgid "BRONZE"
msgstr "БРОНЗОВУ"
# TRANSLATORS: used as return to the level selector menu
#: ../src/Game.cpp:1390
msgid "Menu"
msgstr "Меню"
# TRANSLATORS: used as restart level
#: ../src/Game.cpp:1397 ../src/InputManager.cpp:47
msgid "Restart"
-msgstr "Перезапустити"
+msgstr "Ще раз"
# TRANSLATORS: used as next level
#: ../src/Game.cpp:1404
msgid "Next"
msgstr "Далі"
#: ../src/Game.cpp:1430
msgid "Game replay is done."
msgstr "Відтворення завершене."
#: ../src/Game.cpp:1430
msgid "Game Replay"
msgstr "Відтворення гри"
#: ../src/Game.cpp:1767 ../src/Game.cpp:1769
msgid "Congratulations"
msgstr "Вітання"
#: ../src/Game.cpp:1769
msgid "You have finished the levelpack!"
msgstr "Ви закінчили цю збірку рівнів!"
#: ../src/InputManager.cpp:46
msgid "Up (in menu)"
msgstr "Вгору (в меню)"
#: ../src/InputManager.cpp:46
msgid "Down (in menu)"
msgstr "Вниз (в меню)"
#: ../src/InputManager.cpp:46
msgid "Left"
msgstr "Ліворуч"
#: ../src/InputManager.cpp:46
msgid "Right"
msgstr "Праворуч"
#: ../src/InputManager.cpp:46
msgid "Jump"
msgstr "Стрибок"
#: ../src/InputManager.cpp:46
msgid "Action"
msgstr "Дія"
#: ../src/InputManager.cpp:46
msgid "Space (Record)"
msgstr "Пробіл (Запис)"
#: ../src/InputManager.cpp:46
msgid "Cancel recording"
msgstr "Відмінити запис"
#: ../src/InputManager.cpp:47
msgid "Escape"
msgstr "Вихід"
#: ../src/InputManager.cpp:47
msgid "Tab (View shadow/Level prop.)"
msgstr "Tab (Див. тінь/Налашт. рівня)"
#: ../src/InputManager.cpp:47
msgid "Save game (in editor)"
msgstr "Зберегти гру (в редакторі)"
#: ../src/InputManager.cpp:47
msgid "Load game"
msgstr "Завантажити гру"
#: ../src/InputManager.cpp:47
msgid "Swap (in editor)"
msgstr "Помінятися (в редакторі)"
#: ../src/InputManager.cpp:48
msgid "Teleport (in editor)"
msgstr "Телепортація (в редакторі)"
#: ../src/InputManager.cpp:48
msgid "Suicide (in editor)"
msgstr "Самогубство (в редакторі)"
#: ../src/InputManager.cpp:48
msgid "Shift (in editor)"
-msgstr "Зсув (в редакторі)"
+msgstr "Зсув (у редакторі)"
#: ../src/InputManager.cpp:48
msgid "Next block type (in Editor)"
msgstr "Наступний тип блока (в редакторі)"
#: ../src/InputManager.cpp:49
msgid "Previous block type (in editor)"
msgstr "Попередній тип блока (в редакторі)"
#: ../src/InputManager.cpp:49
msgid "Select (in menu)"
msgstr "Обрати (в меню)"
# TRANSLAOTRS: This is used when the name of the key code is not found.
#: ../src/InputManager.cpp:156
#, c-format
msgid "(Key %d)"
msgstr "(Клавіша %d)"
#: ../src/InputManager.cpp:163
#, c-format
msgid "Joystick axis %d %s"
msgstr "Вісь джойстика %d %s"
#: ../src/InputManager.cpp:166
#, c-format
msgid "Joystick button %d"
msgstr "Кнопка джойстика %d"
#: ../src/InputManager.cpp:171
#, c-format
msgid "Joystick hat %d left"
msgstr "Джойстик %d ліворуч"
#: ../src/InputManager.cpp:174
#, c-format
msgid "Joystick hat %d right"
msgstr "Джойстик %d праворуч"
#: ../src/InputManager.cpp:177
#, c-format
msgid "Joystick hat %d up"
msgstr "Джойстик %d вгору"
#: ../src/InputManager.cpp:180
#, c-format
msgid "Joystick hat %d down"
msgstr "Джойстик %d вниз"
# TRANSLAOTRS: This is used when the JOYSTICK_HAT value is invalid.
#: ../src/InputManager.cpp:185
#, c-format
msgid "Joystick hat %d %d"
msgstr "Джойстик %d %d"
#: ../src/InputManager.cpp:202
msgid "OR"
msgstr "АБО"
#: ../src/InputManager.cpp:416
msgid "Select an item and press a key to change it."
msgstr "Оберіть елемент і натисніть клавішу, щоб змінити його."
#: ../src/InputManager.cpp:419
msgid "Press backspace to clear the selected item."
msgstr "Натисніть backspace, щоб очистити обраний елемент."
#: ../src/LevelEditor.cpp:56
msgid "Block"
msgstr "Блок"
#: ../src/LevelEditor.cpp:56
msgid "Player Start"
msgstr "Тут починає гравець"
#: ../src/LevelEditor.cpp:56
msgid "Shadow Start"
msgstr "Тут починає тінь"
#: ../src/LevelEditor.cpp:57
msgid "Exit"
msgstr "Вихід"
#: ../src/LevelEditor.cpp:57
msgid "Shadow Block"
msgstr "Блок для тіні"
#: ../src/LevelEditor.cpp:57
msgid "Spikes"
msgstr "Шипи"
#: ../src/LevelEditor.cpp:58
msgid "Checkpoint"
msgstr "Чекпоінт"
#: ../src/LevelEditor.cpp:58 ../src/LevelEditSelect.cpp:312
msgid "Swap"
msgstr "Помінятися"
#: ../src/LevelEditor.cpp:58
msgid "Fragile"
-msgstr "Крихкий"
+msgstr "Крихкий блок"
#: ../src/LevelEditor.cpp:59
msgid "Moving Block"
msgstr "Рухомий блок"
#: ../src/LevelEditor.cpp:59
msgid "Moving Shadow Block"
msgstr "Рухомий блок для тіні"
#: ../src/LevelEditor.cpp:59
msgid "Moving Spikes"
msgstr "Рухомі шипи"
#: ../src/LevelEditor.cpp:60
msgid "Teleporter"
msgstr "Телепортер"
#: ../src/LevelEditor.cpp:60
msgid "Button"
msgstr "Кнопка"
#: ../src/LevelEditor.cpp:60
msgid "Switch"
msgstr "Вимикач"
#: ../src/LevelEditor.cpp:61
msgid "Conveyor Belt"
msgstr "Конвеєр"
#: ../src/LevelEditor.cpp:61
msgid "Shadow Conveyor Belt"
msgstr "Конвеєр для тіні"
#: ../src/LevelEditor.cpp:61
msgid "Notification Block"
msgstr "Інформаційний блок"
#: ../src/LevelEditor.cpp:61
msgid "Collectable"
msgstr "Колекційний предмет"
#: ../src/LevelEditor.cpp:61
msgid "Pushable"
-msgstr "Блок, що можна штовхати"
+msgstr "Блок, який можна штовхати"
#: ../src/LevelEditor.cpp:65 ../src/LevelEditor.cpp:310
msgid "Select"
msgstr "Обрати"
#: ../src/LevelEditor.cpp:65
msgid "Add"
msgstr "Додати"
#: ../src/LevelEditor.cpp:65 ../src/LevelEditor.cpp:311
msgid "Delete"
msgstr "Видалити"
#: ../src/LevelEditor.cpp:65 ../src/LevelPlaySelect.cpp:66
#: ../src/TitleMenu.cpp:43
msgid "Play"
msgstr "Грати"
#: ../src/LevelEditor.cpp:65 ../src/LevelEditor.cpp:2852
msgid "Level settings"
msgstr "Налаштування рівня"
#: ../src/LevelEditor.cpp:65
msgid "Save level"
msgstr "Зберегти рівень"
#: ../src/LevelEditor.cpp:65
msgid "Back to menu"
msgstr "Назад до меню"
#: ../src/LevelEditor.cpp:65
msgid "Configure"
msgstr "Налаштування"
#: ../src/LevelEditor.cpp:84
#, c-format
msgid "%s (Scenery)"
msgstr "%s (Тло)"
#: ../src/LevelEditor.cpp:267
msgid "Toggle"
msgstr "Перемикач"
#: ../src/LevelEditor.cpp:270
msgid "Complete"
msgstr "Завершений"
#: ../src/LevelEditor.cpp:271
msgid "One step"
msgstr "Один крок"
#: ../src/LevelEditor.cpp:272
msgid "Two steps"
msgstr "Два кроки"
#: ../src/LevelEditor.cpp:273
msgid "Gone"
msgstr "Зник"
#: ../src/LevelEditor.cpp:291
msgid "Negative infinity"
msgstr "Мінус нескінченність"
#: ../src/LevelEditor.cpp:293
msgid "Zero"
msgstr "Нуль"
#: ../src/LevelEditor.cpp:295
msgid "Level size"
msgstr "Розмір рівня"
#: ../src/LevelEditor.cpp:297
msgid "Positive infinity"
msgstr "Плюс нескінченність"
#: ../src/LevelEditor.cpp:299
msgid "Default"
msgstr "За замовчуванням"
#: ../src/LevelEditor.cpp:308
msgid "Deselect"
msgstr "Зняти вибір"
#: ../src/LevelEditor.cpp:318 ../src/LevelEditor.cpp:1136
#, c-format
msgid "Horizontal repeat start: %s"
msgstr "Розпочати горизонтальний повтор: %s"
#: ../src/LevelEditor.cpp:320 ../src/LevelEditor.cpp:1137
#, c-format
msgid "Horizontal repeat end: %s"
msgstr "Завершити горизонтальний повтор: %s"
#: ../src/LevelEditor.cpp:322 ../src/LevelEditor.cpp:1138
#, c-format
msgid "Vertical repeat start: %s"
msgstr "Розпочати вертикальний повтор: %s"
#: ../src/LevelEditor.cpp:324 ../src/LevelEditor.cpp:1139
#, c-format
msgid "Vertical repeat end: %s"
msgstr "Завершити вертикальний повтор: %s"
#: ../src/LevelEditor.cpp:329 ../src/LevelEditor.cpp:1150
msgid "Custom scenery"
msgstr "Налаштувати тло"
#: ../src/LevelEditor.cpp:335 ../src/LevelEditor.cpp:600
#: ../src/LevelEditor.cpp:602
msgid "Visible"
msgstr "Видимий"
#: ../src/LevelEditor.cpp:344
msgid "Link"
msgstr "Посилання"
#: ../src/LevelEditor.cpp:345
msgid "Remove Links"
msgstr "Прибрати посилання"
#: ../src/LevelEditor.cpp:349 ../src/LevelEditor.cpp:624
#: ../src/LevelEditor.cpp:626
msgid "Automatic"
msgstr "Авто"
#: ../src/LevelEditor.cpp:359 ../src/LevelEditor.cpp:649
#, c-format
msgid "Behavior: %s"
msgstr "Поведінка: %s"
#: ../src/LevelEditor.cpp:362
msgid "Path"
msgstr "Шлях"
#: ../src/LevelEditor.cpp:363
msgid "Remove Path"
msgstr "Прибрати шлях"
#: ../src/LevelEditor.cpp:365 ../src/LevelEditor.cpp:371
#: ../src/LevelEditor.cpp:587 ../src/LevelEditor.cpp:589
msgid "Activated"
msgstr "Активовано"
#: ../src/LevelEditor.cpp:366 ../src/LevelEditor.cpp:612
#: ../src/LevelEditor.cpp:614
msgid "Looping"
msgstr "Повторювати"
#: ../src/LevelEditor.cpp:372 ../src/LevelEditor.cpp:3526
msgid "Speed"
msgstr "Швидкість"
#: ../src/LevelEditor.cpp:378 ../src/LevelEditor.cpp:668
#, c-format
msgid "State: %s"
msgstr "Стан: %s"
#: ../src/LevelEditor.cpp:382 ../src/LevelEditor.cpp:3511
msgid "Message"
msgstr "Повідомлення"
#: ../src/LevelEditor.cpp:384 ../src/LevelEditor.cpp:1202
#: ../src/LevelEditor.cpp:3825
msgid "Appearance"
msgstr "Зовнішній вигляд"
#: ../src/LevelEditor.cpp:389 ../src/LevelEditor.cpp:431
#: ../src/LevelEditor.cpp:715
msgid "Scripting"
msgstr "Скрипти"
#: ../src/LevelEditor.cpp:402 ../src/LevelEditor.cpp:867
#: ../src/LevelEditor.cpp:885
#, c-format
msgid "Background layer: %s"
msgstr "Шар тла: %s"
#: ../src/LevelEditor.cpp:409 ../src/LevelEditor.cpp:866
#: ../src/LevelEditor.cpp:884
msgid "Blocks layer"
msgstr "Шар блоків"
#: ../src/LevelEditor.cpp:417 ../src/LevelEditor.cpp:867
#: ../src/LevelEditor.cpp:885
#, c-format
msgid "Foreground layer: %s"
msgstr "Шар переднього плану: %s"
#: ../src/LevelEditor.cpp:423
msgid "Add new layer"
msgstr "Додати новий шар"
#: ../src/LevelEditor.cpp:424
msgid "Delete selected layer"
msgstr "Видалити обрані шари"
#: ../src/LevelEditor.cpp:425
msgid "Configure selected layer"
msgstr "Налаштувати обраний шар"
#: ../src/LevelEditor.cpp:426
msgid "Move selected object to layer"
msgstr "Перемістити обраний об'єкт у шар"
#: ../src/LevelEditor.cpp:430 ../src/OptionsMenu.cpp:55
msgid "Settings"
msgstr "Налаштування"
#: ../src/LevelEditor.cpp:463
msgid ""
"NOTE: the layers are sorted by name alphabetically.\n"
"The layer is background layer if its name is < 'f'\n"
"by dictionary order, otherwise it's foreground layer."
msgstr "ПРИМІТКА: шари сортуються за назвою у алфавітному порядку.\n"
"Шар є тлом, якщо його ім'я < 'f'\n"
"у словниковому порядку, інакше - це шар переднього плану."
#: ../src/LevelEditor.cpp:539
msgid "Notification block"
msgstr "Інформаційний блок"
#: ../src/LevelEditor.cpp:545
msgid "Enter message here:"
msgstr "Введіть повідомлення тут:"
#: ../src/LevelEditor.cpp:646
msgid "Behavior"
msgstr "Поведінка"
#: ../src/LevelEditor.cpp:665
msgid "State"
msgstr "Стан"
#: ../src/LevelEditor.cpp:673
msgid "Conveyor belt speed"
msgstr "Швидкість конвеєра"
#: ../src/LevelEditor.cpp:679
msgid "Enter speed here:"
msgstr "Введіть швидкість:"
#: ../src/LevelEditor.cpp:690
msgid "NOTE: 1 Speed = 0.08 block/s"
msgstr "ПРИМ.: 1 Швидкість = 0,08 блоків/с"
#: ../src/LevelEditor.cpp:721
msgid "Id:"
msgstr "Ід:"
#: ../src/LevelEditor.cpp:787
msgid "Level Scripting"
msgstr "Скрипти рівня"
#: ../src/LevelEditor.cpp:892
msgid "Add layer"
msgstr "Додати шар"
#: ../src/LevelEditor.cpp:898
msgid "Enter the layer name:"
msgstr "Введіть назву шару:"
#: ../src/LevelEditor.cpp:943
#, c-format
msgid "Are you sure you want to delete layer '%s'?"
msgstr "Ви впевнені, що хочете видалити шар '%s'?"
#: ../src/LevelEditor.cpp:944
msgid "Delete layer"
msgstr "Видалити шар"
#: ../src/LevelEditor.cpp:968
msgid "Layer settings"
msgstr "Налаштувати шар"
#: ../src/LevelEditor.cpp:974
msgid "Layer name:"
msgstr "Назва шару:"
#: ../src/LevelEditor.cpp:989
msgid "Layer moving speed (1 speed = 0.8 block/s):"
msgstr "Швидкість переміщення шару (1 швидкість = 0,08 блоків/с):"
#: ../src/LevelEditor.cpp:1010
msgid "Speed of following camera:"
msgstr "Швидкість камери:"
#: ../src/LevelEditor.cpp:1062
msgid "Move to layer"
msgstr "Перемістити у шар"
#: ../src/LevelEditor.cpp:1068
msgid "Enter the layer name (create new layer if necessary):"
msgstr "Введіть назву шару (створити новий шар за необхідності):"
#: ../src/LevelEditor.cpp:1132
msgid "Repeat mode"
msgstr "Режим повтору"
#: ../src/LevelEditor.cpp:1156
msgid "Custom scenery:"
msgstr "Тло:"
#: ../src/LevelEditor.cpp:1219
msgid "(Use the default appearance for this block)"
msgstr "(Використовувати звичайний вигляд цього блока)"
# TRANSLATORS: Block name
# TRANSLATORS: Context: Resize/Move ...
# TRANSLATORS: Context: Add/Remove ...
# TRANSLATORS: Context: Undo/Redo ...
#: ../src/LevelEditor.cpp:1465 ../src/LevelEditor.cpp:1707
#: ../src/LevelEditor.cpp:1723 ../src/LevelEditor.cpp:1772
#: ../src/LevelEditor.cpp:4400
msgid "Custom scenery block"
msgstr "Блок тла"
#: ../src/LevelEditor.cpp:1673
msgid "Toolbox"
msgstr "Інструменти"
#: ../src/LevelEditor.cpp:1705
#, c-format
msgid "Resize %s"
msgstr "Змінити розмір %s"
#: ../src/LevelEditor.cpp:1705
#, c-format
msgid "Move %s"
msgstr "Перемістити %s"
# TRANSLATORS: Context: Undo/Redo ...
#: ../src/LevelEditor.cpp:1713
#, c-format
msgid "Move %d object"
msgid_plural "Move %d objects"
msgstr[0] "Перемістити %d об'єкт"
msgstr[1] "Перемістити %d об'єкти"
msgstr[2] "Перемістити %d об'єктів"
msgstr[3] "Перемістити %d об'єктів"
#: ../src/LevelEditor.cpp:1721
#, c-format
msgid "Add %s"
msgstr "Додати %s"
#: ../src/LevelEditor.cpp:1721
#, c-format
msgid "Remove %s"
msgstr "Видалити %s"
# TRANSLATORS: Context: Undo/Redo ...
#: ../src/LevelEditor.cpp:1729
#, c-format
msgid "Add %d object"
msgid_plural "Add %d objects"
msgstr[0] "Додати %d об'єкт"
msgstr[1] "Додати %d об'єкти"
msgstr[2] "Додати %d об'єктів"
msgstr[3] "Додати %d об'єктів"
# TRANSLATORS: Context: Undo/Redo ...
#: ../src/LevelEditor.cpp:1731
#, c-format
msgid "Remove %d object"
msgid_plural "Remove %d objects"
msgstr[0] "Видалити %d об'єкт"
msgstr[1] "Видалити %d об'єкти"
msgstr[2] "Видалити %d об'єктів"
msgstr[3] "Видалити %d об'єктів"
# TRANSLATORS: Context: Undo/Redo ...
#: ../src/LevelEditor.cpp:1739
#, c-format
msgid "Add path to %s"
msgstr "Додати шлях до %s"
# TRANSLATORS: Context: Undo/Redo ...
#: ../src/LevelEditor.cpp:1741
#, c-format
msgid "Remove a path point from %s"
msgstr "Видалити точку шляху з %s"
# TRANSLATORS: Context: Undo/Redo ...
#: ../src/LevelEditor.cpp:1747
#, c-format
msgid "Remove all paths from %s"
msgstr "Видалити усі шляхи з %s"
# TRANSLATORS: Context: Undo/Redo ...
#: ../src/LevelEditor.cpp:1753
#, c-format
msgid "Add link from %s to %s"
-msgstr "Додати зв'язок між %s і %s"
+msgstr "Додати посилання з %s до %s"
# TRANSLATORS: Context: Undo/Redo ...
#: ../src/LevelEditor.cpp:1759
#, c-format
msgid "Remove all links from %s"
-msgstr "Видалити усі зв'язки з %s"
+msgstr "Видалити усі посилання з %s"
# TRANSLATORS: Context: Undo/Redo ...
#: ../src/LevelEditor.cpp:1766
msgid "Modify the %2 property of %1"
msgstr "Змінити у %1 властивість %2"
# TRANSLATORS: Context: Undo/Redo ...
#: ../src/LevelEditor.cpp:1818
#, c-format
msgid "Edit the script of %s"
msgstr "Редагувати скрипт %s"
# TRANSLATORS: Context: Undo/Redo ...
#: ../src/LevelEditor.cpp:1821
msgid "Edit the script of level"
msgstr "Редагувати скрипт рівня"
#: ../src/LevelEditor.cpp:2146 ../src/LevelEditor.cpp:2226
msgid "The level has unsaved changes."
msgstr "На рівні є незбережені зміни."
#: ../src/LevelEditor.cpp:2150 ../src/LevelEditor.cpp:2228
msgid "Are you sure you want to quit?"
msgstr "Ви дійсно хочете вийти?"
#: ../src/LevelEditor.cpp:2150 ../src/LevelEditor.cpp:2228
msgid "Quit prompt"
-msgstr "Вихід"
+msgstr "Підтвердіть вихід"
#: ../src/LevelEditor.cpp:2797 ../src/LevelEditor.cpp:2799
#, c-format
msgid "Level \"%s\" saved"
msgstr "Рівень \"%s\" збережено"
#: ../src/LevelEditor.cpp:2797 ../src/LevelEditor.cpp:2799
msgid "Saved"
msgstr "Збережено"
#: ../src/LevelEditor.cpp:2859 ../src/LevelEditSelect.cpp:208
msgid "Name:"
msgstr "Назва:"
#: ../src/LevelEditor.cpp:2866
msgid "Theme:"
msgstr "Оформлення:"
#: ../src/LevelEditor.cpp:2873
msgid "Examples: %DATA%/themes/classic"
msgstr "Приклади: %DATA%/themes/classic"
#: ../src/LevelEditor.cpp:2875
msgid "or %USER%/themes/Orange"
msgstr "або %USER%/themes/Orange"
#: ../src/LevelEditor.cpp:2878
msgid "Music:"
msgstr "Музика:"
#: ../src/LevelEditor.cpp:2887
msgid "Target time (s):"
msgstr "Необхідний час (с):"
#: ../src/LevelEditor.cpp:2903
msgid "Target recordings:"
msgstr "Необхідно записів:"
#: ../src/LevelEditor.cpp:2919
msgid "Restart level editor is required"
-msgstr "Необхідно перезавантажити редактор рівнів"
+msgstr "Необхідно перезапустити редактор рівнів"
#: ../src/LevelEditor.cpp:3679 ../src/LevelEditor.cpp:3718
#: ../src/LevelEditor.cpp:3739
msgid "Please enter a layer name."
msgstr "Будь ласка, введіть назву шару."
#: ../src/LevelEditor.cpp:3679 ../src/LevelEditor.cpp:3683
#: ../src/LevelEditor.cpp:3718 ../src/LevelEditor.cpp:3722
#: ../src/LevelEditor.cpp:3739 ../src/LevelEditor.cpp:3743
#: ../src/LevelEditSelect.cpp:644 ../src/LevelEditSelect.cpp:683
#: ../src/LevelEditSelect.cpp:688 ../src/LevelEditSelect.cpp:693
#: ../src/LevelEditSelect.cpp:698 ../src/LevelEditSelect.cpp:796
msgid "Error"
msgstr "Помилка"
#: ../src/LevelEditor.cpp:3683 ../src/LevelEditor.cpp:3722
#, c-format
msgid "The layer '%s' already exists."
msgstr "Шар '%s' вже існує."
#: ../src/LevelEditor.cpp:3743
msgid "Source and destination layers are the same."
msgstr "Вихідний та кінцевий шари співпадають."
#: ../src/LevelEditor.cpp:3760
msgid "Scenery"
msgstr "Тло"
#: ../src/LevelEditor.cpp:4190 ../src/LevelEditor.cpp:4218
#, c-format
msgid "Speed: %d = %0.2f block/s"
msgstr "Швидкість: %d = %0.2f блоків/с"
#: ../src/LevelEditor.cpp:4203
msgid "Stop at this point"
msgstr "Зупинитися у цій точці"
#: ../src/LevelEditor.cpp:4208
#, c-format
msgid "Pause: %d = %0.3fs"
msgstr "Пауза: %d = %0.3fs"
#: ../src/LevelEditSelect.cpp:41 ../src/TitleMenu.cpp:45
msgid "Map Editor"
msgstr "Редактор карт"
#: ../src/LevelEditSelect.cpp:66
msgid "New Levelpack"
msgstr "Нова збірка рівнів"
#: ../src/LevelEditSelect.cpp:71
msgid "Pack Properties"
msgstr "Властивості збірки"
#: ../src/LevelEditSelect.cpp:76
msgid "Remove Pack"
msgstr "Видалити збірку"
#: ../src/LevelEditSelect.cpp:81
msgid "Move Map"
msgstr "Перемістити карту"
#: ../src/LevelEditSelect.cpp:89
msgid "Remove Map"
msgstr "Видалити карту"
#: ../src/LevelEditSelect.cpp:94
msgid "Edit Map"
msgstr "Редагувати карту"
#: ../src/LevelEditSelect.cpp:205
msgid "Properties"
msgstr "Властивості"
#: ../src/LevelEditSelect.cpp:217
msgid "Description:"
msgstr "Опис:"
#: ../src/LevelEditSelect.cpp:226
msgid "Congratulation text:"
msgstr "Текст привітання:"
#: ../src/LevelEditSelect.cpp:235
msgid "Music list:"
msgstr "Перелік музики:"
#: ../src/LevelEditSelect.cpp:265 ../src/LevelEditSelect.cpp:485
msgid "Add level"
msgstr "Додати рівень"
#: ../src/LevelEditSelect.cpp:268
msgid "File name:"
msgstr "Назва файлу:"
#: ../src/LevelEditSelect.cpp:293
msgid "Move level"
msgstr "Перемістити рівень"
#: ../src/LevelEditSelect.cpp:296
msgid "Level: "
msgstr "Рівень: "
#: ../src/LevelEditSelect.cpp:310
msgid "Before"
msgstr "До"
#: ../src/LevelEditSelect.cpp:311
msgid "After"
msgstr "Після"
#: ../src/LevelEditSelect.cpp:368 ../src/LevelPlaySelect.cpp:124
msgid "Individual levels which are not contained in any level packs"
msgstr "Окремі рівні, що не включено до жодної збірки рівнів"
#: ../src/LevelEditSelect.cpp:577
#, c-format
msgid "Are you sure remove the level pack '%s'?"
msgstr "Ви впевнені, що хочете видалити збірку рівнів '%s'?"
#: ../src/LevelEditSelect.cpp:577 ../src/LevelEditSelect.cpp:607
msgid "Remove prompt"
-msgstr "Видалення"
+msgstr "Підтвердіть видалення"
#: ../src/LevelEditSelect.cpp:607
#, c-format
msgid "Are you sure remove the map '%s'?"
msgstr "Ви впевнені, що хочете видалити карту '%s'?"
#: ../src/LevelEditSelect.cpp:644
msgid "Levelpack name cannot be empty."
msgstr "Назва збірки рівнів не може бути порожньою."
#: ../src/LevelEditSelect.cpp:683
#, c-format
msgid "The levelpack directory '%s' already exists!"
msgstr "Директорія збірки рівнів '%s' вже існує!"
#: ../src/LevelEditSelect.cpp:688
#, c-format
msgid "Unable to create levelpack directory '%s'!"
msgstr "Неможливо створити директорію збірки рівнів '%s'!"
#: ../src/LevelEditSelect.cpp:693
#, c-format
msgid "The levelpack file '%s' already exists!"
msgstr "Файл збірки рівнів '%s' вже існує!"
#: ../src/LevelEditSelect.cpp:698
#, c-format
msgid "Unable to create levelpack file '%s'!"
msgstr "Неможливо створити файл збірки рівнів '%s'!"
#: ../src/LevelEditSelect.cpp:758
msgid "No file name given for the new level."
msgstr "Новому рівню не було призначене ім'я файлу."
#: ../src/LevelEditSelect.cpp:758
msgid "Missing file name"
msgstr "Відсутнє ім'я файлу"
#: ../src/LevelEditSelect.cpp:796
#, c-format
msgid "The file %s already exists."
msgstr "Файл %s вже існує."
#: ../src/LevelEditSelect.cpp:849
msgid "The entered level number isn't valid!"
msgstr "Введений номер рівня невірний!"
#: ../src/LevelEditSelect.cpp:849
msgid "Illegal number"
msgstr "Невірний номер"
#: ../src/LevelInfoRender.cpp:19
msgid "Choose a level"
msgstr "Оберіть рівень"
#: ../src/LevelInfoRender.cpp:20
msgid "Time:"
msgstr "Час:"
#: ../src/LevelInfoRender.cpp:21 ../src/StatisticsScreen.cpp:259
msgid "Recordings:"
msgstr "Записів:"
#: ../src/LevelPackManager.cpp:124
msgid "Custom Levels"
msgstr "Інші рівні"
#: ../src/LevelPlaySelect.cpp:41
msgid "Select Level"
msgstr "Оберіть рівень"
# TRANSLATORS: Used for button which clear any level progress like unlocked
# levels and highscores.
#: ../src/OptionsMenu.cpp:66
msgid "Clear Progress"
msgstr "Скинути прогрес"
#: ../src/OptionsMenu.cpp:109
msgid "General"
msgstr "Загальні"
#: ../src/OptionsMenu.cpp:110
msgid "Controls"
msgstr "Керування"
#: ../src/OptionsMenu.cpp:121
msgid "Music"
msgstr "Музика"
#: ../src/OptionsMenu.cpp:129
msgid "Sound"
msgstr "Звуки"
#: ../src/OptionsMenu.cpp:137
msgid "Resolution"
msgstr "Роздільна здатність"
#: ../src/OptionsMenu.cpp:177
msgid "Language"
msgstr "Мова"
# TRANSLATORS: as detect user's language automatically
#: ../src/OptionsMenu.cpp:185
msgid "Auto-Detect"
msgstr "Автовизначення"
#: ../src/OptionsMenu.cpp:209
msgid "Theme"
msgstr "Оформлення"
#: ../src/OptionsMenu.cpp:247
msgid "Internet proxy"
msgstr "Інтернет-проксі"
#: ../src/OptionsMenu.cpp:256
msgid "Fullscreen"
msgstr "На весь екран"
#: ../src/OptionsMenu.cpp:261
msgid "Quick record"
msgstr "Швидкий запис"
#: ../src/OptionsMenu.cpp:266
msgid "Internet"
msgstr "Інтернет"
#: ../src/OptionsMenu.cpp:271
msgid "Fade transition"
msgstr "Плавний перехід"
#: ../src/OptionsMenu.cpp:294
msgid "Save Changes"
msgstr "Зберегти зміни"
#: ../src/OptionsMenu.cpp:513
msgid "Do you really want to reset level progress?"
msgstr "Ви дійсно хочете скинути прогрес рівня?"
#: ../src/OptionsMenu.cpp:513
msgid "Warning"
msgstr "Попередження"
#: ../src/StatisticsManager.cpp:386
msgid "New achievement:"
msgstr "Нове досягнення:"
#: ../src/StatisticsManager.cpp:394
#, c-format
msgid "Achieved on %s"
msgstr "Досягнуто %s"
#: ../src/StatisticsManager.cpp:400
msgid "Unknown achievement"
msgstr "Невідоме досягнення"
#: ../src/StatisticsManager.cpp:406
#, c-format
msgid "Achieved %1.0f%%"
msgstr "Досягнуто %1.0f%%"
#: ../src/StatisticsManager.cpp:410
msgid "Not achieved"
msgstr "Не досягнуто"
#: ../src/StatisticsScreen.cpp:57 ../src/TitleMenu.cpp:55
msgid "Achievements and Statistics"
msgstr "Досягнення і статистика"
#: ../src/StatisticsScreen.cpp:166
msgid "Achievements"
msgstr "Досягнення"
#: ../src/StatisticsScreen.cpp:167
msgid "Statistics"
msgstr "Статистика"
#: ../src/StatisticsScreen.cpp:234
msgid "Total"
msgstr "Загалом"
#: ../src/StatisticsScreen.cpp:246
msgid "Traveling distance (m)"
msgstr "Пройдена відстань (м)"
#: ../src/StatisticsScreen.cpp:247
msgid "Jump times"
msgstr "Стрибків"
#: ../src/StatisticsScreen.cpp:248
msgid "Die times"
msgstr "Смертей"
#: ../src/StatisticsScreen.cpp:249
msgid "Squashed times"
msgstr "Разів розчавлено"
#: ../src/StatisticsScreen.cpp:260
msgid "Switch pulled times:"
msgstr "Увімкнено вимикачів:"
#: ../src/StatisticsScreen.cpp:261
msgid "Swap times:"
msgstr "Змін:"
#: ../src/StatisticsScreen.cpp:262
msgid "Save times:"
msgstr "Збережень:"
#: ../src/StatisticsScreen.cpp:263
msgid "Load times:"
msgstr "Завантажень:"
#: ../src/StatisticsScreen.cpp:268
msgid "Completed levels:"
msgstr "Завершених рівнів:"
#: ../src/StatisticsScreen.cpp:306
msgid "In-game time:"
msgstr "Час у грі:"
#: ../src/StatisticsScreen.cpp:308
msgid "Level editing time:"
msgstr "Час у редакторі:"
#: ../src/StatisticsScreen.cpp:310
msgid "Created levels:"
msgstr "Створено рівнів:"
#: ../src/TitleMenu.cpp:44
msgid "Options"
msgstr "Налаштування"
#: ../src/TitleMenu.cpp:47
msgid "Quit"
msgstr "Вихід"
#: ../src/TitleMenu.cpp:131
msgid "Enable internet in order to install addons."
msgstr "Щоб встановлювати застосунки, дозвольте підключення до Інтернету."
#: ../src/TitleMenu.cpp:131
msgid "Internet disabled"
-msgstr "Підключення до інтернету вимкнуто"
+msgstr "Підключення до Інтернету вимкнуто"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Return"
msgstr "Return"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Escape"
msgstr "Escape"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Backspace"
msgstr "Backspace"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Tab"
msgstr "Tab"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Space"
msgstr "Пробіл"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "CapsLock"
msgstr "CapsLock"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "PrintScreen"
msgstr "PrintScreen"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "ScrollLock"
msgstr "ScrollLock"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Pause"
msgstr "Pause"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Insert"
msgstr "Insert"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Home"
msgstr "Home"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "PageUp"
msgstr "PageUp"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Delete"
msgstr "Delete"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "End"
msgstr "End"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "PageDown"
msgstr "PageDown"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Right"
msgstr "Праворуч"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Left"
msgstr "Ліворуч"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Down"
msgstr "Вниз"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Up"
msgstr "Угору"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Numlock"
msgstr "Numlock"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "SysReq"
msgstr "SysReq"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Left Ctrl"
msgstr "Лівий Ctrl"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Left Shift"
msgstr "Лівий Shift"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Left Alt"
msgstr "Лівий Alt"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Left GUI"
msgstr "Лівий GUI"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Right Ctrl"
msgstr "Правий Ctrl"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Right Shift"
msgstr "Правий Shift"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Right Alt"
msgstr "Правий Alt"
# TRANSLATORS: name of a key
msgctxt "keys"
msgid "Right GUI"
msgstr "Правий GUI"
diff --git a/src/Functions.cpp b/src/Functions.cpp
index cae56e8..2a5cb09 100644
--- a/src/Functions.cpp
+++ b/src/Functions.cpp
@@ -1,1626 +1,1626 @@
/*
* Copyright (C) 2011-2013 Me and My Shadow
*
* This file is part of Me and My Shadow.
*
* Me and My Shadow is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Me and My Shadow 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 Me and My Shadow. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <algorithm>
#include <SDL.h>
#include <SDL_mixer.h>
#include <SDL_syswm.h>
#include <SDL_ttf.h>
#include <string>
#include "Globals.h"
#include "Functions.h"
#include "FontManager.h"
#include "FileManager.h"
#include "GameObjects.h"
#include "LevelPack.h"
#include "TitleMenu.h"
#include "OptionsMenu.h"
#include "CreditsMenu.h"
#include "LevelEditSelect.h"
#include "LevelEditor.h"
#include "Game.h"
#include "LevelPlaySelect.h"
#include "Addons.h"
#include "InputManager.h"
#include "ImageManager.h"
#include "MusicManager.h"
#include "SoundManager.h"
#include "ScriptExecutor.h"
#include "LevelPackManager.h"
#include "ThemeManager.h"
#include "GUIListBox.h"
#include "GUIOverlay.h"
#include "StatisticsManager.h"
#include "StatisticsScreen.h"
#include "Cursors.h"
#include "ScriptAPI.h"
#include "libs/tinyformat/tinyformat.h"
#include "libs/tinygettext/tinygettext.hpp"
#include "libs/tinygettext/log.hpp"
#include "libs/findlocale/findlocale.h"
using namespace std;
#ifdef WIN32
#include <windows.h>
#include <shellapi.h>
#include <shlobj.h>
#define TO_UTF8(SRC, DEST) WideCharToMultiByte(CP_UTF8, 0, SRC, -1, DEST, sizeof(DEST), NULL, NULL)
#define TO_UTF16(SRC, DEST) MultiByteToWideChar(CP_UTF8, 0, SRC, -1, DEST, sizeof(DEST)/sizeof(DEST[0]))
#else
#include <strings.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <dirent.h>
#endif
//Initialise the musicManager.
//The MusicManager is used to prevent loading music files multiple times and for playing/fading music.
MusicManager musicManager;
//Initialise the soundManager.
//The SoundManager is used to keep track of the sfx in the game.
SoundManager soundManager;
//Initialise the levelPackManager.
//The LevelPackManager is used to prevent loading levelpacks multiple times and for the game to know which levelpacks there are.
LevelPackManager levelPackManager;
//Map containing changed settings using command line arguments.
map<string,string> tmpSettings;
//Pointer to the settings object.
//It is used to load and save the settings file and change the settings.
Settings* settings=nullptr;
SDL_Renderer* sdlRenderer=nullptr;
std::string pgettext(const std::string& context, const std::string& message) {
if (dictionaryManager) {
return dictionaryManager->get_dictionary().translate_ctxt(context, message);
} else {
return message;
}
}
std::string ngettext(const std::string& message,const std::string& messageplural,int num) {
if (dictionaryManager) {
return dictionaryManager->get_dictionary().translate_plural(message, messageplural, num);
} else {
//Assume it's of English plural rule
return (num != 1) ? messageplural : message;
}
}
void applySurface(int x,int y,SDL_Surface* source,SDL_Surface* dest,SDL_Rect* clip){
//The offset is needed to draw at the right location.
SDL_Rect offset;
offset.x=x;
offset.y=y;
//Let SDL do the drawing of the surface.
SDL_BlitSurface(source,clip,dest,&offset);
}
void drawRect(int x,int y,int w,int h,SDL_Renderer& renderer,Uint32 color){
//NOTE: We let SDL_gfx render it.
SDL_SetRenderDrawColor(&renderer,color >> 24,color >> 16,color >> 8,255);
//rectangleRGBA(&renderer,x,y,x+w,y+h,color >> 24,color >> 16,color >> 8,255);
const SDL_Rect r{x,y,w,h};
SDL_RenderDrawRect(&renderer,&r);
}
//Draw a box with anti-aliased borders using SDL_gfx.
void drawGUIBox(int x,int y,int w,int h,SDL_Renderer& renderer,Uint32 color){
SDL_Renderer* rd = &renderer;
//FIXME, this may get the wrong color on system with different endianness.
//Fill content's background color from function parameter
SDL_SetRenderDrawColor(rd,color >> 24,color >> 16,color >> 8,color >> 0);
{
const SDL_Rect r{x+1,y+1,w-2,h-2};
SDL_RenderFillRect(rd, &r);
}
SDL_SetRenderDrawColor(rd,0,0,0,255);
//Draw first black borders around content and leave 1 pixel in every corner
SDL_RenderDrawLine(rd,x+1,y,x+w-2,y);
SDL_RenderDrawLine(rd,x+1,y+h-1,x+w-2,y+h-1);
SDL_RenderDrawLine(rd,x,y+1,x,y+h-2);
SDL_RenderDrawLine(rd,x+w-1,y+1,x+w-1,y+h-2);
//Fill the corners with transperent color to create anti-aliased borders
SDL_SetRenderDrawColor(rd,0,0,0,160);
SDL_RenderDrawPoint(rd,x,y);
SDL_RenderDrawPoint(rd,x,y+h-1);
SDL_RenderDrawPoint(rd,x+w-1,y);
SDL_RenderDrawPoint(rd,x+w-1,y+h-1);
//Draw second lighter border around content
SDL_SetRenderDrawColor(rd,0,0,0,64);
{
const SDL_Rect r{x+1,y+1,w-2,h-2};
SDL_RenderDrawRect(rd,&r);
}
SDL_SetRenderDrawColor(rd,0,0,0,50);
//Create anti-aliasing in corners of second border
SDL_RenderDrawPoint(rd,x+1,y+1);
SDL_RenderDrawPoint(rd,x+1,y+h-2);
SDL_RenderDrawPoint(rd,x+w-2,y+1);
SDL_RenderDrawPoint(rd,x+w-2,y+h-2);
}
void drawLine(int x1,int y1,int x2,int y2,SDL_Renderer& renderer,Uint32 color){
SDL_SetRenderDrawColor(&renderer,color >> 24,color >> 16,color >> 8,255);
//NOTE: We let SDL_gfx render it.
//lineRGBA(&renderer,x1,y1,x2,y2,color >> 24,color >> 16,color >> 8,255);
SDL_RenderDrawLine(&renderer,x1,y1,x2,y2);
}
void drawLineWithArrow(int x1,int y1,int x2,int y2,SDL_Renderer& renderer,Uint32 color,int spacing,int offset,int xsize,int ysize){
//Draw line first
drawLine(x1,y1,x2,y2,renderer,color);
//calc delta and length
double dx=x2-x1;
double dy=y2-y1;
double length=sqrt(dx*dx+dy*dy);
if(length<0.001) return;
//calc the unit vector
dx/=length; dy/=length;
//Now draw arrows on it
for(double p=offset;p<length;p+=spacing){
drawLine(int(x1+p*dx+0.5),int(y1+p*dy+0.5),
int(x1+(p-xsize)*dx-ysize*dy+0.5),int(y1+(p-xsize)*dy+ysize*dx+0.5),renderer,color);
drawLine(int(x1+p*dx+0.5),int(y1+p*dy+0.5),
int(x1+(p-xsize)*dx+ysize*dy+0.5),int(y1+(p-xsize)*dy-ysize*dx+0.5),renderer,color);
}
}
ScreenData creationFailed() {
return ScreenData{ nullptr };
}
ScreenData createScreen(){
//Check if we are going fullscreen.
if(settings->getBoolValue("fullscreen"))
pickFullscreenResolution();
//Set the screen_width and height.
SCREEN_WIDTH=atoi(settings->getValue("width").c_str());
SCREEN_HEIGHT=atoi(settings->getValue("height").c_str());
//Update the camera.
camera.w=SCREEN_WIDTH;
camera.h=SCREEN_HEIGHT;
//Set the flags.
Uint32 flags = 0;
Uint32 currentFlags = SDL_GetWindowFlags(sdlWindow);
//#if !defined(ANDROID)
// flags |= SDL_DOUBLEBUF;
//#endif
if(settings->getBoolValue("fullscreen")) {
flags|=SDL_WINDOW_FULLSCREEN; //TODO with SDL2 we can also do SDL_WINDOW_FULLSCREEN_DESKTOP
}
else if(settings->getBoolValue("resizable"))
flags|=SDL_WINDOW_RESIZABLE;
//Create the window and renderer if they don't exist and check if there weren't any errors.
if (!sdlWindow && !sdlRenderer) {
SDL_CreateWindowAndRenderer(SCREEN_WIDTH, SCREEN_HEIGHT, flags, &sdlWindow, &sdlRenderer);
if(!sdlWindow || !sdlRenderer){
std::cerr << "FATAL ERROR: SDL_CreateWindowAndRenderer failed.\nError: " << SDL_GetError() << std::endl;
return creationFailed();
}
SDL_SetRenderDrawBlendMode(sdlRenderer, SDL_BlendMode::SDL_BLENDMODE_BLEND);
// White background so we see the menu on failure.
SDL_SetRenderDrawColor(sdlRenderer, 255, 255, 255, 255);
} else if (sdlWindow) {
// Try changing to/from fullscreen
if(SDL_SetWindowFullscreen(sdlWindow, flags & SDL_WINDOW_FULLSCREEN) != 0) {
std::cerr << "WARNING: Failed to switch to fullscreen: " << SDL_GetError() << std::endl;
};
currentFlags = SDL_GetWindowFlags(sdlWindow);
// Change fullscreen resolution
if((currentFlags & SDL_WINDOW_FULLSCREEN ) || (currentFlags & SDL_WINDOW_FULLSCREEN_DESKTOP)) {
SDL_DisplayMode m{0,0,0,0,nullptr};
SDL_GetWindowDisplayMode(sdlWindow,&m);
m.w = SCREEN_WIDTH;
m.h = SCREEN_HEIGHT;
if(SDL_SetWindowDisplayMode(sdlWindow, &m) != 0) {
std::cerr << "WARNING: Failed to set display mode: " << SDL_GetError() << std::endl;
}
} else {
SDL_SetWindowSize(sdlWindow, SCREEN_WIDTH, SCREEN_HEIGHT);
}
}
//Now configure the newly created window (if windowed).
if(settings->getBoolValue("fullscreen")==false)
configureWindow();
//Set the the window caption.
SDL_SetWindowTitle(sdlWindow, ("Me and My Shadow "+version).c_str());
//FIXME Seems to be obsolete
// SDL_EnableUNICODE(1);
//Nothing went wrong so return true.
return ScreenData{sdlRenderer};
}
vector<SDL_Point> getResolutionList(){
//Vector that will hold the resolutions to choose from.
vector<SDL_Point> resolutionList;
//Enumerate available resolutions using SDL_ListModes()
//NOTE: we enumerate fullscreen resolutions because
// windowed resolutions always can be arbitrary
if(resolutionList.empty()){
// SDL_Rect **modes=SDL_ListModes(NULL,SDL_FULLSCREEN|SCREEN_FLAGS|SDL_ANYFORMAT);
//NOTe - currently only using the first display (0)
int numDisplayModes = SDL_GetNumDisplayModes(0);
if(numDisplayModes < 1){
cerr<<"ERROR: Can't enumerate available screen resolutions."
" Use predefined screen resolutions list instead."<<endl;
static const SDL_Point predefinedResolutionList[] = {
{800,600},
{1024,600},
{1024,768},
{1152,864},
{1280,720},
{1280,768},
{1280,800},
{1280,960},
{1280,1024},
{1360,768},
{1366,768},
{1440,900},
{1600,900},
{1600,1200},
{1680,1080},
{1920,1080},
{1920,1200},
{2560,1440},
{3840,2160}
};
//Fill the resolutionList.
for (unsigned int i = 0; i<sizeof(predefinedResolutionList) / sizeof(SDL_Point); i++){
resolutionList.push_back(predefinedResolutionList[i]);
}
}else{
//Fill the resolutionList.
for(int i=0;i < numDisplayModes; ++i){
SDL_DisplayMode mode;
int error = SDL_GetDisplayMode(0, i, &mode);
if(error < 0) {
//We failed to get a display mode. Should we crash here?
std::cerr << "ERROR: Failed to get display mode " << i << " " << std::endl;
}
//Check if the resolution is higher than the minimum (800x600).
if(mode.w >= 800 && mode.h >= 600){
SDL_Point res = { mode.w, mode.h };
resolutionList.push_back(res);
}
}
//Reverse it so that we begin with the lowest resolution.
reverse(resolutionList.begin(),resolutionList.end());
}
}
//Return the resolution list.
return resolutionList;
}
void pickFullscreenResolution(){
//Get the resolution list.
vector<SDL_Point> resolutionList=getResolutionList();
//The resolution that will hold the final result, we start with the minimum (800x600).
SDL_Point closestMatch = { 800, 600 };
int width=atoi(getSettings()->getValue("width").c_str());
int height=atoi(getSettings()->getValue("height").c_str());
int delta = 0x40000000;
//Now loop through the resolutionList.
for (int i = 0; i < (int)resolutionList.size(); i++){
int dx = width - resolutionList[i].x;
if (dx < 0) dx = -dx;
int dy = height - resolutionList[i].y;
if (dy < 0) dy = -dy;
if (dx + dy < delta){
delta = dx + dy;
closestMatch.x = resolutionList[i].x;
closestMatch.y = resolutionList[i].y;
}
}
//Now set the resolution to the closest match.
char s[64];
sprintf(s,"%d",closestMatch.x);
getSettings()->setValue("width",s);
sprintf(s,"%d",closestMatch.y);
getSettings()->setValue("height",s);
}
void configureWindow(){
//We only need to configure the window if it's resizable.
if(!getSettings()->getBoolValue("resizable"))
return;
//We use a new function in SDL2 to restrict minimum window size
SDL_SetWindowMinimumSize(sdlWindow, 800, 600);
}
void onVideoResize(ImageManager& imageManager, SDL_Renderer &renderer){
//Check if the resize event isn't malformed.
if(event.window.data1<=0 || event.window.data2<=0)
return;
//Check the size limit.
//TODO: SDL2 porting note: This may break on systems non-X11 or Windows systems as the window size won't be limited
//there.
if(event.window.data1<800)
event.window.data1=800;
if(event.window.data2<600)
event.window.data2=600;
//Check if it really resizes.
if(SCREEN_WIDTH==event.window.data1 && SCREEN_HEIGHT==event.window.data2)
return;
char s[32];
//Set the new width and height.
SDL_snprintf(s,32,"%d",event.window.data1);
getSettings()->setValue("width",s);
SDL_snprintf(s,32,"%d",event.window.data2);
getSettings()->setValue("height",s);
//FIXME: THIS doesn't work properly.
//Do resizing.
SCREEN_WIDTH = event.window.data1;
SCREEN_HEIGHT = event.window.data2;
//Update the camera.
camera.w=SCREEN_WIDTH;
camera.h=SCREEN_HEIGHT;
//Tell the theme to resize.
if(!loadTheme(imageManager,renderer,""))
return;
//And let the currentState update it's GUI to the new resolution.
currentState->resize(imageManager, renderer);
}
ScreenData init(){
//Initialze SDL.
- if(SDL_Init(SDL_INIT_EVERYTHING)==-1) {
+ if(SDL_Init(SDL_INIT_TIMER|SDL_INIT_VIDEO|SDL_INIT_AUDIO|SDL_INIT_JOYSTICK)==-1) {
std::cerr << "FATAL ERROR: SDL_Init failed\nError: " << SDL_GetError() << std::endl;
return creationFailed();
}
//Initialze SDL_mixer (audio).
//Note for SDL2 port: Changed frequency from 22050 to 44100.
//22050 caused some sound artifacts on my system, and I'm not sure
//why one would use it in this day and age anyhow.
//unless it's for compatability with some legacy system.
if(Mix_OpenAudio(44100,MIX_DEFAULT_FORMAT,2,1024)==-1){
std::cerr << "FATAL ERROR: Mix_OpenAudio failed\nError: " << Mix_GetError() << std::endl;
return creationFailed();
}
//Set the volume.
Mix_Volume(-1,atoi(settings->getValue("sound").c_str()));
//Increase the number of channels.
soundManager.setNumberOfChannels(48);
//Initialze SDL_ttf (fonts).
if(TTF_Init()==-1){
std::cerr << "FATAL ERROR: TTF_Init failed\nError: " << TTF_GetError() << std::endl;
return creationFailed();
}
//Create the screen.
ScreenData screenData(createScreen());
if(!screenData) {
return creationFailed();
}
//Load key config. Then initialize joystick support.
inputMgr.loadConfig();
inputMgr.openAllJoysitcks();
//Init tinygettext for translations for the right language
dictionaryManager = new tinygettext::DictionaryManager();
dictionaryManager->set_use_fuzzy(false);
dictionaryManager->add_directory(getDataPath()+"locale");
dictionaryManager->set_charset("UTF-8");
//Disable annoying 'Couldn't translate: blah blah blah'
tinygettext::Log::set_log_info_callback(NULL);
//Check if user have defined own language. If not, find it out for the player using findlocale
string lang=getSettings()->getValue("lang");
if(lang.length()>0){
printf("Locale set by user to %s\n",lang.c_str());
language=lang;
}else{
FL_Locale *locale;
FL_FindLocale(&locale,FL_MESSAGES);
printf("Locale isn't set by user: %s\n",locale->lang);
language=locale->lang;
if(locale->country!=NULL){
language+=string("_")+string(locale->country);
}
if(locale->variant!=NULL){
language+=string("@")+string(locale->variant);
}
FL_FreeLocale(&locale);
}
//Now set the language in the dictionaryManager.
dictionaryManager->set_language(tinygettext::Language::from_name(language));
#ifdef WIN32
//Some ad-hoc fix for Windows since it accepts "zh-CN" but not "zh_CN"
std::string language2;
for (auto c : language) {
if (isalnum(c)) language2.push_back(c);
else if (c == '_') language2.push_back('-');
else break;
}
const char* languagePtr = language2.c_str();
#else
const char* languagePtr = language.c_str();
#endif
//Set time format.
setlocale(LC_TIME, languagePtr);
//Also set the numeric format for tinyformat.
tfm::setNumericFormat(
/// TRANSLATORS: This is the decimal point character in your language.
pgettext("numeric", "."),
/// TRANSLATORS: This is the thousands separator character in your language.
pgettext("numeric", ","),
/// TRANSLATORS: This is the grouping of digits in your language,
/// see <http://www.cplusplus.com/reference/locale/numpunct/grouping/> for more information.
/// However, we use string containing "123..." instead of "\x01\x02\x03...", also, "0" is the same as "".
pgettext("numeric", "3")
);
//Create the types of blocks.
for(int i=0;i<TYPE_MAX;i++){
Game::blockNameMap[Game::blockName[i]]=i;
}
//Structure that holds the event type/name pair.
struct EventTypeName{
int type;
const char* name;
};
//Create the types of game object event types.
{
const EventTypeName types[]={
{GameObjectEvent_PlayerWalkOn,"playerWalkOn"},
{GameObjectEvent_PlayerIsOn,"playerIsOn"},
{GameObjectEvent_PlayerLeave,"playerLeave"},
{GameObjectEvent_OnCreate,"onCreate"},
{GameObjectEvent_OnEnterFrame,"onEnterFrame"},
{ GameObjectEvent_OnPlayerInteraction, "onPlayerInteraction" },
{GameObjectEvent_OnToggle,"onToggle"},
{GameObjectEvent_OnSwitchOn,"onSwitchOn"},
{GameObjectEvent_OnSwitchOff,"onSwitchOff"},
{0,NULL}
};
for(int i=0;types[i].name;i++){
Game::gameObjectEventNameMap[types[i].name]=types[i].type;
Game::gameObjectEventTypeMap[types[i].type]=types[i].name;
}
}
//Create the types of level event types.
{
const EventTypeName types[]={
{LevelEvent_OnCreate,"onCreate"},
{LevelEvent_OnSave,"onSave"},
{LevelEvent_OnLoad,"onLoad"},
{0,NULL}
};
for(int i=0;types[i].name;i++){
Game::levelEventNameMap[types[i].name]=types[i].type;
Game::levelEventTypeMap[types[i].type]=types[i].name;
}
}
//Nothing went wrong so we return true.
return screenData;
}
bool loadFonts(){
//Load the fonts.
//NOTE: This is a separate method because it will be called separately when re-initing in case of language change.
//NOTE2: Since the font fallback is implemented, the font will not be loaded again if call loadFonts() twice.
if (fontMgr) {
return true;
}
fontMgr = new FontManager;
fontMgr->loadFonts();
fontTitle = fontMgr->getFont("fontTitle");
fontGUI = fontMgr->getFont("fontGUI");
fontGUISmall = fontMgr->getFont("fontGUISmall");
fontText = fontMgr->getFont("fontText");
fontMono = fontMgr->getFont("fontMono");
if (fontTitle == NULL || fontGUI == NULL || fontGUISmall == NULL || fontText == NULL || fontMono == NULL){
printf("FATAL ERROR: Unable to load fonts!\n");
return false;
}
//Nothing went wrong so return true.
return true;
}
//Generate small arrows used for some GUI widgets.
static void generateArrows(SDL_Renderer& renderer){
TTF_Font* fontArrow = fontMgr->getFont("fontArrow");
arrowLeft1=textureFromText(renderer,*fontArrow,"<",objThemes.getTextColor(false));
arrowRight1=textureFromText(renderer,*fontArrow,">",objThemes.getTextColor(false));
arrowLeft2=textureFromText(renderer,*fontArrow,"<",objThemes.getTextColor(true));
arrowRight2=textureFromText(renderer,*fontArrow,">",objThemes.getTextColor(true));
}
bool loadTheme(ImageManager& imageManager,SDL_Renderer& renderer,std::string name){
//Load default fallback theme if it isn't loaded yet
if(objThemes.themeCount()==0){
if(objThemes.appendThemeFromFile(getDataPath()+"themes/Cloudscape/theme.mnmstheme", imageManager, renderer)==NULL){
printf("ERROR: Can't load default theme file\n");
return false;
}
}
//Resize background or load specific theme
bool success=true;
if(name==""||name.empty()){
objThemes.scaleToScreen();
}else{
string theme=processFileName(name);
if(objThemes.appendThemeFromFile(theme+"/theme.mnmstheme", imageManager, renderer)==NULL){
printf("ERROR: Can't load theme %s\n",theme.c_str());
success=false;
}
}
generateArrows(renderer);
//Everything went fine so return true.
return success;
}
static SDL_Cursor* loadCursor(const char* image[]){
int i,row,col;
//The array that holds the data (0=white 1=black)
Uint8 data[4*32];
//The array that holds the alpha mask (0=transparent 1=visible)
Uint8 mask[4*32];
//The coordinates of the hotspot of the cursor.
int hotspotX, hotspotY;
i=-1;
//Loop through the rows and columns.
//NOTE: We assume a cursor size of 32x32.
for(row=0;row<32;++row){
for(col=0; col<32;++col){
if(col % 8) {
data[i]<<=1;
mask[i]<<=1;
}else{
++i;
data[i]=mask[i]=0;
}
switch(image[4+row][col]){
case '+':
data[i] |= 0x01;
mask[i] |= 0x01;
break;
case '.':
mask[i] |= 0x01;
break;
default:
break;
}
}
}
//Get the hotspot x and y locations from the last line of the cursor.
sscanf(image[4+row],"%d,%d",&hotspotX,&hotspotY);
return SDL_CreateCursor(data,mask,32,32,hotspotX,hotspotY);
}
bool loadFiles(ImageManager& imageManager, SDL_Renderer& renderer){
//Load the fonts.
if(!loadFonts())
return false;
//Show a loading screen
{
int w = 0,h = 0;
SDL_GetRendererOutputSize(&renderer, &w, &h);
SDL_Color fg={255,255,255,0};
TexturePtr loadingTexture = titleTextureFromText(renderer, _("Loading..."), fg, w);
SDL_Rect loadingRect = rectFromTexture(*loadingTexture);
loadingRect.x = (w-loadingRect.w)/2;
loadingRect.y = (h-loadingRect.h)/2;
SDL_RenderCopy(sdlRenderer, loadingTexture.get(), NULL, &loadingRect);
SDL_RenderPresent(sdlRenderer);
SDL_RenderClear(sdlRenderer);
}
musicManager.destroy();
//Load the music and play it.
if(musicManager.loadMusic((getDataPath()+"music/menu.music")).empty()){
printf("WARNING: Unable to load background music! \n");
}
musicManager.playMusic("menu",false);
//Load all the music lists from the data and user data path.
{
vector<string> musicLists=enumAllFiles((getDataPath()+"music/"),"list",true);
for(unsigned int i=0;i<musicLists.size();i++)
getMusicManager()->loadMusicList(musicLists[i]);
musicLists=enumAllFiles((getUserPath(USER_DATA)+"music/"),"list",true);
for(unsigned int i=0;i<musicLists.size();i++)
getMusicManager()->loadMusicList(musicLists[i]);
}
//Set the list to the configured one.
getMusicManager()->setMusicList(getSettings()->getValue("musiclist"));
//Check if music is enabled.
if(getSettings()->getBoolValue("music"))
getMusicManager()->setEnabled();
//Load the sound effects
soundManager.loadSound((getDataPath()+"sfx/jump.wav").c_str(),"jump");
soundManager.loadSound((getDataPath()+"sfx/hit.wav").c_str(),"hit");
soundManager.loadSound((getDataPath()+"sfx/checkpoint.wav").c_str(),"checkpoint");
soundManager.loadSound((getDataPath()+"sfx/swap.wav").c_str(),"swap");
soundManager.loadSound((getDataPath()+"sfx/toggle.ogg").c_str(),"toggle");
soundManager.loadSound((getDataPath()+"sfx/error.wav").c_str(),"error");
soundManager.loadSound((getDataPath()+"sfx/collect.wav").c_str(),"collect");
soundManager.loadSound((getDataPath()+"sfx/achievement.ogg").c_str(),"achievement");
//Load the cursor images from the Cursor.h file.
cursors[CURSOR_POINTER]=loadCursor(pointer);
cursors[CURSOR_CARROT]=loadCursor(ibeam);
cursors[CURSOR_DRAG]=loadCursor(closedhand);
cursors[CURSOR_SIZE_HOR]=loadCursor(size_hor);
cursors[CURSOR_SIZE_VER]=loadCursor(size_ver);
cursors[CURSOR_SIZE_FDIAG]=loadCursor(size_fdiag);
cursors[CURSOR_SIZE_BDIAG]=loadCursor(size_bdiag);
cursors[CURSOR_REMOVE]=loadCursor(remove_cursor);
cursors[CURSOR_POINTING_HAND] = loadCursor(pointing_hand);
//Set the default cursor right now.
SDL_SetCursor(cursors[CURSOR_POINTER]);
levelPackManager.destroy();
//Now sum up all the levelpacks.
vector<string> v=enumAllDirs(getDataPath()+"levelpacks/");
for(vector<string>::iterator i=v.begin(); i!=v.end(); ++i){
levelPackManager.loadLevelPack(getDataPath()+"levelpacks/"+*i);
}
v=enumAllDirs(getUserPath(USER_DATA)+"levelpacks/");
for(vector<string>::iterator i=v.begin(); i!=v.end(); ++i){
levelPackManager.loadLevelPack(getUserPath(USER_DATA)+"levelpacks/"+*i);
}
v=enumAllDirs(getUserPath(USER_DATA)+"custom/levelpacks/");
for(vector<string>::iterator i=v.begin(); i!=v.end(); ++i){
levelPackManager.loadLevelPack(getUserPath(USER_DATA)+"custom/levelpacks/"+*i);
}
//Now we add a special levelpack that will contain the levels not in a levelpack.
LevelPack* levelsPack=new LevelPack;
levelsPack->levelpackName="Levels";
levelsPack->levelpackPath=LEVELS_PATH;
levelsPack->type=COLLECTION;
LevelPack* customLevelsPack=new LevelPack;
customLevelsPack->levelpackName="Custom Levels";
customLevelsPack->levelpackPath=CUSTOM_LEVELS_PATH;
customLevelsPack->type=COLLECTION;
//List the main levels and add them one for one.
v = enumAllFiles(getDataPath() + "levels/");
for (vector<string>::iterator i = v.begin(); i != v.end(); ++i){
levelsPack->addLevel(getDataPath() + "levels/" + *i);
levelsPack->setLocked(levelsPack->getLevelCount() - 1);
}
//List the addon levels and add them one for one.
v=enumAllFiles(getUserPath(USER_DATA)+"levels/");
for(vector<string>::iterator i=v.begin(); i!=v.end(); ++i){
levelsPack->addLevel(getUserPath(USER_DATA)+"levels/"+*i);
levelsPack->setLocked(levelsPack->getLevelCount()-1);
}
//List the custom levels and add them one for one.
v=enumAllFiles(getUserPath(USER_DATA)+"custom/levels/");
for(vector<string>::iterator i=v.begin(); i!=v.end(); ++i){
levelsPack->addLevel(getUserPath(USER_DATA)+"custom/levels/"+*i);
levelsPack->setLocked(levelsPack->getLevelCount()-1);
customLevelsPack->addLevel(getUserPath(USER_DATA)+"custom/levels/"+*i);
customLevelsPack->setLocked(customLevelsPack->getLevelCount()-1);
}
//Add them to the manager.
levelPackManager.addLevelPack(levelsPack);
levelPackManager.addLevelPack(customLevelsPack);
//Load statistics
statsMgr.loadPicture(renderer, imageManager);
statsMgr.registerAchievements(imageManager);
statsMgr.loadFile(getUserPath(USER_CONFIG)+"statistics");
//Do something ugly and slow
statsMgr.reloadCompletedLevelsAndAchievements();
statsMgr.reloadOtherAchievements();
//Load the theme, both menu and default.
//NOTE: Loading theme may fail and returning false would stop everything, default theme will be used instead.
if (!loadTheme(imageManager,renderer,getSettings()->getValue("theme"))){
getSettings()->setValue("theme","%DATA%/themes/Cloudscape");
saveSettings();
}
//Nothing failed so return true.
return true;
}
bool loadSettings(){
//Check the version of config file.
int version = 0;
std::string cfgV05 = getUserPath(USER_CONFIG) + "meandmyshadow_V0.5.cfg";
std::string cfgV04 = getUserPath(USER_CONFIG) + "meandmyshadow.cfg";
if (fileExists(cfgV05.c_str())) {
//We find a config file of current version.
version = 0x000500;
} else if (fileExists(cfgV04.c_str())) {
//We find a config file of V0.4 version or earlier.
copyFile(cfgV04.c_str(), cfgV05.c_str());
version = 0x000400;
} else {
//No config file found, just create a new one.
version = 0x000500;
}
settings=new Settings(cfgV05);
settings->parseFile(version);
//Now apply settings changed through command line arguments, if any.
map<string,string>::iterator it;
for(it=tmpSettings.begin();it!=tmpSettings.end();++it){
settings->setValue(it->first,it->second);
}
tmpSettings.clear();
//Always return true?
return true;
}
bool saveSettings(){
return settings->save();
}
Settings* getSettings(){
return settings;
}
MusicManager* getMusicManager(){
return &musicManager;
}
SoundManager* getSoundManager(){
return &soundManager;
}
LevelPackManager* getLevelPackManager(){
return &levelPackManager;
}
void flipScreen(SDL_Renderer& renderer){
// Render the data from the back buffer.
SDL_RenderPresent(&renderer);
}
void clean(){
//Save statistics
statsMgr.saveFile(getUserPath(USER_CONFIG)+"statistics");
//We delete the settings.
if(settings){
delete settings;
settings=NULL;
}
//Delete dictionaryManager.
delete dictionaryManager;
//Get rid of the currentstate.
//NOTE: The state is probably already deleted by the changeState function.
if(currentState)
delete currentState;
//Destroy the GUI if present.
if(GUIObjectRoot){
delete GUIObjectRoot;
GUIObjectRoot=NULL;
}
//These calls to destroy makes sure stuff is
//deleted before SDL is uninitialised (as these managers are stack allocated
//globals.)
//Destroy the musicManager.
musicManager.destroy();
//Destroy all sounds
soundManager.destroy();
//Destroy the cursors.
for(int i=0;i<CURSOR_MAX;i++){
SDL_FreeCursor(cursors[i]);
cursors[i]=NULL;
}
//Destroy the levelPackManager.
levelPackManager.destroy();
levels=NULL;
//Close all joysticks.
inputMgr.closeAllJoysticks();
//Close the fonts and quit SDL_ttf.
delete fontMgr;
fontMgr = NULL;
TTF_Quit();
//Remove the temp surface.
SDL_DestroyRenderer(sdlRenderer);
SDL_DestroyWindow(sdlWindow);
arrowLeft1.reset(nullptr);
arrowLeft2.reset(nullptr);
arrowRight1.reset(nullptr);
arrowRight2.reset(nullptr);
//Stop audio.and quit
Mix_CloseAudio();
//SDL2 porting note. Not sure why this was only done on apple.
//#ifndef __APPLE__
Mix_Quit();
//#endif
//And finally quit SDL.
SDL_Quit();
}
void setNextState(int newstate){
//Only change the state when we aren't already exiting.
if(nextState!=STATE_EXIT){
nextState=newstate;
}
}
void changeState(ImageManager& imageManager, SDL_Renderer& renderer, int fade){
//Check if there's a nextState.
if(nextState!=STATE_NULL){
//Fade out, if fading is enabled.
if (currentState && settings->getBoolValue("fading")) {
for (; fade >= 0; fade -= 17) {
currentState->render(imageManager, renderer);
//TODO: Shouldn't the gamestate take care of rendering the GUI?
if (GUIObjectRoot) GUIObjectRoot->render(renderer);
dimScreen(renderer, static_cast<Uint8>(255 - fade));
//draw new achievements (if any) as overlay
statsMgr.render(imageManager, renderer);
flipScreen(renderer);
SDL_Delay(1000/FPS);
}
}
//Delete the currentState.
delete currentState;
currentState=NULL;
//Set the currentState to the nextState.
stateID=nextState;
nextState=STATE_NULL;
//Init the state.
switch(stateID){
case STATE_GAME:
{
currentState=NULL;
Game* game=new Game(renderer, imageManager);
currentState=game;
//Check if we should load record file or a level.
if(!Game::recordFile.empty()){
game->loadRecord(imageManager,renderer,Game::recordFile.c_str());
Game::recordFile.clear();
}else{
game->loadLevel(imageManager,renderer,levels->getLevelFile());
levels->saveLevelProgress();
}
}
break;
case STATE_MENU:
currentState=new Menu(imageManager, renderer);
break;
case STATE_LEVEL_SELECT:
currentState=new LevelPlaySelect(imageManager, renderer);
break;
case STATE_LEVEL_EDIT_SELECT:
currentState=new LevelEditSelect(imageManager, renderer);
break;
case STATE_LEVEL_EDITOR:
{
currentState=NULL;
LevelEditor* levelEditor=new LevelEditor(renderer, imageManager);
currentState=levelEditor;
//Load the selected level.
levelEditor->loadLevel(imageManager,renderer,levels->getLevelFile());
}
break;
case STATE_OPTIONS:
currentState=new Options(imageManager, renderer);
break;
case STATE_ADDONS:
currentState=new Addons(renderer, imageManager);
break;
case STATE_CREDITS:
currentState=new Credits(imageManager,renderer);
break;
case STATE_STATISTICS:
currentState=new StatisticsScreen(imageManager,renderer);
break;
}
//NOTE: STATE_EXIT isn't mentioned, meaning that currentState is null.
//This way the game loop will break and the program will exit.
}
}
void musicStoppedHook(){
//We just call the musicStopped method of the MusicManager.
musicManager.musicStopped();
}
void channelFinishedHook(int channel){
soundManager.channelFinished(channel);
}
bool checkCollision(const SDL_Rect& a,const SDL_Rect& b){
//Check if the left side of box a isn't past the right side of b.
if(a.x>=b.x+b.w){
return false;
}
//Check if the right side of box a isn't left of the left side of b.
if(a.x+a.w<=b.x){
return false;
}
//Check if the top side of box a isn't under the bottom side of b.
if(a.y>=b.y+b.h){
return false;
}
//Check if the bottom side of box a isn't above the top side of b.
if(a.y+a.h<=b.y){
return false;
}
//We have collision.
return true;
}
bool pointOnRect(const SDL_Rect& point, const SDL_Rect& rect) {
if(point.x >= rect.x && point.x < rect.x + rect.w
&& point.y >= rect.y && point.y < rect.y + rect.h) {
return true;
}
return false;
}
int parseArguments(int argc, char** argv){
//Loop through all arguments.
//We start at one since 0 is the command itself.
for(int i=1;i<argc;i++){
string argument=argv[i];
//Check if the argument is the data-dir.
if(argument=="--data-dir"){
//We need a second argument so we increase i.
i++;
if(i>=argc){
printf("ERROR: Missing argument for command '%s'\n\n",argument.c_str());
return -1;
}
//Configure the dataPath with the given path.
dataPath=argv[i];
if(!getDataPath().empty()){
char c=dataPath[dataPath.size()-1];
if(c!='/'&&c!='\\') dataPath+="/";
}
}else if(argument=="--user-dir"){
//We need a second argument so we increase i.
i++;
if(i>=argc){
printf("ERROR: Missing argument for command '%s'\n\n",argument.c_str());
return -1;
}
//Configure the userPath with the given path.
userPath=argv[i];
if(!userPath.empty()){
char c=userPath[userPath.size()-1];
if(c!='/'&&c!='\\') userPath+="/";
}
}else if(argument=="-f" || argument=="-fullscreen" || argument=="--fullscreen"){
tmpSettings["fullscreen"]="1";
}else if(argument=="-w" || argument=="-windowed" || argument=="--windowed"){
tmpSettings["fullscreen"]="0";
}else if(argument=="-mv" || argument=="-music" || argument=="--music"){
//We need a second argument so we increase i.
i++;
if(i>=argc){
printf("ERROR: Missing argument for command '%s'\n\n",argument.c_str());
return -1;
}
//Now set the music volume.
tmpSettings["music"]=argv[i];
}else if(argument=="-sv" || argument=="-sound" || argument=="--sound"){
//We need a second argument so we increase i.
i++;
if(i>=argc){
printf("ERROR: Missing argument for command '%s'\n\n",argument.c_str());
return -1;
}
//Now set sound volume.
tmpSettings["sound"]=argv[i];
}else if(argument=="-set" || argument=="--set"){
//We need a second and a third argument so we increase i.
i+=2;
if(i>=argc){
printf("ERROR: Missing argument for command '%s'\n\n",argument.c_str());
return -1;
}
//And set the setting.
tmpSettings[argv[i-1]]=argv[i];
}else if(argument=="-v" || argument=="-version" || argument=="--version"){
//Print the version.
printf("%s\n",version.c_str());
return 0;
}else if(argument=="-h" || argument=="-help" || argument=="--help"){
//If the help is requested we'll return false without printing an error.
//This way the usage/help text will be printed.
return -1;
}else{
//Any other argument is unknow so we return false.
printf("ERROR: Unknown argument %s\n\n",argument.c_str());
return -1;
}
}
//If everything went well we can return true.
return 1;
}
//Special structure that will recieve the GUIEventCallbacks of the messagebox.
struct msgBoxHandler:public GUIEventCallback{
public:
//Integer containing the ret(urn) value of the messageBox.
int ret;
public:
//Constructor.
msgBoxHandler():ret(0){}
void GUIEventCallback_OnEvent(ImageManager& imageManager, SDL_Renderer& renderer, std::string name,GUIObject* obj,int eventType){
//Make sure it's a click event.
if(eventType==GUIEventClick){
//Set the return value.
ret=obj->value;
//After a click event we can delete the GUI.
if(GUIObjectRoot){
delete GUIObjectRoot;
GUIObjectRoot=NULL;
}
}
}
};
msgBoxResult msgBox(ImageManager& imageManager,SDL_Renderer& renderer, const string& prompt,msgBoxButtons buttons,const string& title){
//Create the event handler.
msgBoxHandler objHandler;
//Create the GUIObjectRoot, the height and y location is temp.
//It depends on the content what it will be.
GUIObject* root=new GUIFrame(imageManager,renderer,(SCREEN_WIDTH-600)/2,200,600,200,title.c_str());
//Integer containing the current y location used to grow dynamic depending on the content.
int y=50;
//Now process the prompt.
{
//NOTE: We shouldn't modify the cotents in the c_str() of a string,
//since it's said that at least in g++ the std::string is copy-on-write
//hence if we modify the content it may break
//The copy of the prompt.
std::vector<char> copyOfPrompt(prompt.begin(), prompt.end());
//Append another '\0' to it.
copyOfPrompt.push_back(0);
//Pointer to the string.
char* lps = &(copyOfPrompt[0]);
//Pointer to a character.
char* lp=NULL;
//The list of labels.
std::vector<GUIObject*> labels;
//We keep looping forever.
//The only way out is with the break statement.
for(;;){
//As long as it's still the same sentence we continue.
//It will stop when there's a newline or end of line.
for(lp=lps;*lp!='\n'&&*lp!='\r'&&*lp!=0;lp++);
//Store the character we stopped on. (End or newline)
char c=*lp;
//Set the character in the string to 0, making lps a string containing one sentence.
*lp=0;
//Add a GUIObjectLabel with the sentence.
GUIObject *label = new GUILabel(imageManager, renderer, 0, y, root->width, 25, lps, 0, true, true, GUIGravityCenter);
labels.push_back(label);
root->addChild(label);
//Calculate the width of the text.
int w = 0;
TTF_SizeUTF8(fontText, lps, &w, NULL);
w += 20;
if (w > root->width) root->width = w;
//Increase y with 25, about the height of the text.
y+=25;
//Check the stored character if it was a stop.
if(c==0){
//It was so break out of the for loop.
lps=lp;
break;
}
//It wasn't meaning more will follow.
//We set lps to point after the "newline" forming a new string.
lps=lp+1;
}
//Shrink the dialog if it's too big.
if (root->width > SCREEN_WIDTH - 20) root->width = SCREEN_WIDTH - 20;
root->left = (SCREEN_WIDTH - root->width) / 2;
//Move labels to their correct locations.
for (auto label : labels) {
label->width = root->width;
}
}
//Add 70 to y to leave some space between the content and the buttons.
y+=70;
//Recalc the size of the message box.
root->top=(SCREEN_HEIGHT-y)/2;
root->height=y;
//Now we need to add the buttons.
//Integer containing the number of buttons to add.
int count=0;
//Array with the return codes for the buttons.
int value[3]={0};
//Array containing the captation for the buttons.
string button[3]={"","",""};
switch(buttons){
case MsgBoxOKCancel:
count=2;
button[0]=_("OK");value[0]=MsgBoxOK;
button[1]=_("Cancel");value[1]=MsgBoxCancel;
break;
case MsgBoxAbortRetryIgnore:
count=3;
button[0]=_("Abort");value[0]=MsgBoxAbort;
button[1]=_("Retry");value[1]=MsgBoxRetry;
button[2]=_("Ignore");value[2]=MsgBoxIgnore;
break;
case MsgBoxYesNoCancel:
count=3;
button[0]=_("Yes");value[0]=MsgBoxYes;
button[1]=_("No");value[1]=MsgBoxNo;
button[2]=_("Cancel");value[2]=MsgBoxCancel;
break;
case MsgBoxYesNo:
count=2;
button[0]=_("Yes");value[0]=MsgBoxYes;
button[1]=_("No");value[1]=MsgBoxNo;
break;
case MsgBoxRetryCancel:
count=2;
button[0]=_("Retry");value[0]=MsgBoxRetry;
button[1]=_("Cancel");value[1]=MsgBoxCancel;
break;
default:
count=1;
button[0]=_("OK");value[0]=MsgBoxOK;
break;
}
//Now we start making the buttons.
{
//Reduce y so that the buttons fit inside the frame.
y-=40;
double places[3]={0.0};
if(count==1){
places[0]=0.5;
}else if(count==2){
places[0]=0.35;
places[1]=0.65;
}else if(count==3){
places[0]=0.25;
places[1]=0.5;
places[2]=0.75;
}
std::vector<GUIButton*> buttons;
//Loop to add the buttons.
for(int i=0;i<count;i++){
GUIButton* obj = new GUIButton(imageManager, renderer, root->width*places[i], y, -1, 36, button[i].c_str(), value[i], true, true, GUIGravityCenter);
obj->eventCallback=&objHandler;
buttons.push_back(obj);
root->addChild(obj);
}
//Update widgets
for (int i = 0; i < count; i++) {
buttons[i]->render(renderer, 0, 0, false);
}
bool overlap = false;
//Check if they overlap
if (buttons[0]->left - buttons[0]->gravityX < 5 ||
buttons[count - 1]->left - buttons[count - 1]->gravityX + buttons[count - 1]->width > root->width - 5)
{
overlap = true;
} else {
for (int i = 0; i < count - 1; i++) {
if (buttons[i]->left - buttons[i]->gravityX + buttons[i]->width >= buttons[i + 1]->left - buttons[i + 1]->gravityX) {
overlap = true;
break;
}
}
}
//Shrink the font size if any buttons are overlap
if (overlap) {
for (int i = 0; i < count; i++) {
buttons[i]->smallFont = true;
buttons[i]->width = -1;
}
}
}
//Now we dim the screen and keep the GUI rendering/updating.
GUIOverlay* overlay=new GUIOverlay(renderer,root);
overlay->keyboardNavigationMode = LeftRightFocus | UpDownFocus | TabFocus | ((count == 1) ? 0 : ReturnControls);
overlay->enterLoop(imageManager, renderer, true, count == 1);
//And return the result.
return (msgBoxResult)objHandler.ret;
}
// A helper function to read a character from utf8 string
// s: the string
// p [in,out]: the position
// return value: the character readed, in utf32 format, 0 means end of string, -1 means error
int utf8ReadForward(const char* s, int& p) {
int ch = (unsigned char)s[p];
if (ch < 0x80){
if (ch) p++;
return ch;
} else if (ch < 0xC0){
// skip invalid characters
while (((unsigned char)s[p] & 0xC0) == 0x80) p++;
return -1;
} else if (ch < 0xE0){
int c2 = (unsigned char)s[++p];
if ((c2 & 0xC0) != 0x80) return -1;
ch = ((ch & 0x1F) << 6) | (c2 & 0x3F);
p++;
return ch;
} else if (ch < 0xF0){
int c2 = (unsigned char)s[++p];
if ((c2 & 0xC0) != 0x80) return -1;
int c3 = (unsigned char)s[++p];
if ((c3 & 0xC0) != 0x80) return -1;
ch = ((ch & 0xF) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F);
p++;
return ch;
} else if (ch < 0xF8){
int c2 = (unsigned char)s[++p];
if ((c2 & 0xC0) != 0x80) return -1;
int c3 = (unsigned char)s[++p];
if ((c3 & 0xC0) != 0x80) return -1;
int c4 = (unsigned char)s[++p];
if ((c4 & 0xC0) != 0x80) return -1;
ch = ((ch & 0x7) << 18) | ((c2 & 0x3F) << 12) | ((c3 & 0x3F) << 6) | (c4 & 0x3F);
if (ch >= 0x110000) ch = -1;
p++;
return ch;
} else {
p++;
return -1;
}
}
// A helper function to read a character backward from utf8 string (experimental)
// s: the string
// p [in,out]: the position
// return value: the character readed, in utf32 format, 0 means end of string, -1 means error
int utf8ReadBackward(const char* s, int& p) {
if (p <= 0) return 0;
do {
p--;
} while (p > 0 && ((unsigned char)s[p] & 0xC0) == 0x80);
int tmp = p;
return utf8ReadForward(s, tmp);
}
#ifndef WIN32
// ad-hoc function to check if a program is installed
static bool programExists(const std::string& program) {
std::string p = tfm::format("which \"%s\" 2>&1", program);
const int BUFSIZE = 128;
char buf[BUFSIZE];
FILE *fp;
if ((fp = popen(p.c_str(), "r")) == NULL) {
return false;
}
while (fgets(buf, BUFSIZE, fp) != NULL) {
// Drop all outputs since 'which' returns -1 when the program is not found
}
if (pclose(fp)) {
return false;
}
return true;
}
#endif
void openWebsite(const std::string& url) {
#ifdef WIN32
wchar_t ws[4096];
TO_UTF16(url.c_str(), ws);
SDL_SysWMinfo info = {};
SDL_VERSION(&info.version);
SDL_GetWindowWMInfo(sdlWindow, &info);
ShellExecuteW(info.info.win.window, L"open", ws, NULL, NULL, SW_SHOW);
#else
static int method = -1;
// Some of these methods are copied from https://stackoverflow.com/questions/5116473/
const char* methods[] = {
"xdg-open", "xdg-open \"%s\"",
"gnome-open", "gnome-open \"%s\"",
"kde-open", "kde-open \"%s\"",
"open", "open \"%s\"",
"python", "python -m webbrowser \"%s\"",
"sensible-browser", "sensible-browser \"%s\"",
"x-www-browser", "x-www-browser \"%s\"",
NULL,
};
if (method < 0) {
for (method = 0; methods[method]; method += 2) {
if (programExists(methods[method])) break;
}
}
if (methods[method]) {
std::string p = tfm::format(methods[method + 1], url);
system(p.c_str());
} else {
fprintf(stderr, "TODO: openWebsite is not implemented on your system\n");
}
#endif
}
std::string appendURLToLicense(const std::string& license) {
// if the license doesn't include url, try to detect it from a predefined list
if (license.find("://") == std::string::npos) {
std::string normalized;
for (char c : license) {
if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z')) {
normalized.push_back(c);
} else if (c >= 'a' && c <= 'z') {
normalized.push_back(c + ('A' - 'a'));
}
}
const char* licenses[] = {
// AGPL
"AGPL1", "AGPLV1", NULL, "http://www.affero.org/oagpl.html",
"AGPL2", "AGPLV2", NULL, "http://www.affero.org/agpl2.html",
"AGPL", NULL, "https://gnu.org/licenses/agpl.html",
// LGPL
"LGPL21", "LGPLV21", NULL, "https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html",
"LGPL2", "LGPLV2", NULL, "https://www.gnu.org/licenses/old-licenses/lgpl-2.0.html",
"LGPL", NULL, "https://www.gnu.org/copyleft/lesser.html",
// GPL
"GPL1", "GPLV1", NULL, "https://www.gnu.org/licenses/old-licenses/gpl-1.0.html",
"GPL2", "GPLV2", NULL, "https://www.gnu.org/licenses/old-licenses/gpl-2.0.html",
"GPL", NULL, "https://gnu.org/licenses/gpl.html",
// CC BY-NC-ND
"CCBYNCND1", "CCBYNDNC1", NULL, "https://creativecommons.org/licenses/by-nd-nc/1.0",
"CCBYNCND25", "CCBYNDNC25", NULL, "https://creativecommons.org/licenses/by-nc-nd/2.5",
"CCBYNCND2", "CCBYNDNC2", NULL, "https://creativecommons.org/licenses/by-nc-nd/2.0",
"CCBYNCND3", "CCBYNDNC3", NULL, "https://creativecommons.org/licenses/by-nc-nd/3.0",
"CCBYNCND", "CCBYNDNC", NULL, "https://creativecommons.org/licenses/by-nc-nd/4.0",
// CC BY-NC-SA
"CCBYNCSA1", NULL, "https://creativecommons.org/licenses/by-nc-sa/1.0",
"CCBYNCSA25", NULL, "https://creativecommons.org/licenses/by-nc-sa/2.5",
"CCBYNCSA2", NULL, "https://creativecommons.org/licenses/by-nc-sa/2.0",
"CCBYNCSA3", NULL, "https://creativecommons.org/licenses/by-nc-sa/3.0",
"CCBYNCSA", NULL, "https://creativecommons.org/licenses/by-nc-sa/4.0",
// CC BY-ND
"CCBYND1", NULL, "https://creativecommons.org/licenses/by-nd/1.0",
"CCBYND25", NULL, "https://creativecommons.org/licenses/by-nd/2.5",
"CCBYND2", NULL, "https://creativecommons.org/licenses/by-nd/2.0",
"CCBYND3", NULL, "https://creativecommons.org/licenses/by-nd/3.0",
"CCBYND", NULL, "https://creativecommons.org/licenses/by-nd/4.0",
// CC BY-NC
"CCBYNC1", NULL, "https://creativecommons.org/licenses/by-nc/1.0",
"CCBYNC25", NULL, "https://creativecommons.org/licenses/by-nc/2.5",
"CCBYNC2", NULL, "https://creativecommons.org/licenses/by-nc/2.0",
"CCBYNC3", NULL, "https://creativecommons.org/licenses/by-nc/3.0",
"CCBYNC", NULL, "https://creativecommons.org/licenses/by-nc/4.0",
// CC BY-SA
"CCBYSA1", NULL, "https://creativecommons.org/licenses/by-sa/1.0",
"CCBYSA25", NULL, "https://creativecommons.org/licenses/by-sa/2.5",
"CCBYSA2", NULL, "https://creativecommons.org/licenses/by-sa/2.0",
"CCBYSA3", NULL, "https://creativecommons.org/licenses/by-sa/3.0",
"CCBYSA", NULL, "https://creativecommons.org/licenses/by-sa/4.0",
// CC BY
"CCBY1", NULL, "https://creativecommons.org/licenses/by/1.0",
"CCBY25", NULL, "https://creativecommons.org/licenses/by/2.5",
"CCBY2", NULL, "https://creativecommons.org/licenses/by/2.0",
"CCBY3", NULL, "https://creativecommons.org/licenses/by/3.0",
"CCBY", NULL, "https://creativecommons.org/licenses/by/4.0",
// CC0
"CC0", NULL, "https://creativecommons.org/publicdomain/zero/1.0",
// WTFPL
"WTFPL", NULL, "http://www.wtfpl.net/",
// end
NULL,
};
for (int i = 0; licenses[i]; i++) {
bool found = false;
for (; licenses[i]; i++) {
if (normalized.find(licenses[i]) != std::string::npos) found = true;
}
i++;
if (found) {
return license + tfm::format(" <%s>", licenses[i]);
}
}
}
return license;
}
int getKeyboardRepeatDelay() {
static int ret = -1;
if (ret < 0) {
#ifdef WIN32
int i = 0;
SystemParametersInfoW(SPI_GETKEYBOARDDELAY, 0, &i, 0);
// NOTE: these weird numbers are derived from Microsoft's documentation explaining the return value of SystemParametersInfo.
i = clamp(i, 0, 3);
ret = (i + 1) * 10;
#else
// TODO: platform-dependent code
// Assume it's 250ms, i.e. 10 frames
ret = 10;
#endif
// Debug
#ifdef _DEBUG
printf("getKeyboardRepeatDelay() = %d\n", ret);
#endif
}
return ret;
}
int getKeyboardRepeatInterval() {
static int ret = -1;
if (ret < 0) {
#ifdef WIN32
int i = 0;
SystemParametersInfoW(SPI_GETKEYBOARDSPEED, 0, &i, 0);
// NOTE: these weird numbers are derived from Microsoft's documentation explaining the return value of SystemParametersInfo.
i = clamp(i, 0, 31);
ret = (int)floor(40.0f / (2.5f + 0.887097f * (float)i) + 0.5f);
#else
// TODO: platform-dependent code
// Assume it's 25ms, i.e. 1 frame
ret = 1;
#endif
// Debug
#ifdef _DEBUG
printf("getKeyboardRepeatInterval() = %d\n", ret);
#endif
}
return ret;
}
diff --git a/src/Game.cpp b/src/Game.cpp
index 6ff589a..e580538 100644
--- a/src/Game.cpp
+++ b/src/Game.cpp
@@ -1,1963 +1,1972 @@
/*
* Copyright (C) 2011-2013 Me and My Shadow
*
* This file is part of Me and My Shadow.
*
* Me and My Shadow is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Me and My Shadow 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 Me and My Shadow. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Block.h"
#include "GameState.h"
#include "Functions.h"
#include "GameObjects.h"
#include "ThemeManager.h"
#include "Game.h"
#include "TreeStorageNode.h"
#include "POASerializer.h"
#include "InputManager.h"
#include "MusicManager.h"
#include "Render.h"
#include "StatisticsManager.h"
#include "ScriptExecutor.h"
#include "MD5.h"
#include <fstream>
#include <iostream>
#include <sstream>
#include <vector>
#include <map>
#include <algorithm>
#include <assert.h>
#include <stdio.h>
#include <SDL_ttf.h>
#include "libs/tinyformat/tinyformat.h"
using namespace std;
const char* Game::blockName[TYPE_MAX]={"Block","PlayerStart","ShadowStart",
"Exit","ShadowBlock","Spikes",
"Checkpoint","Swap","Fragile",
"MovingBlock","MovingShadowBlock","MovingSpikes",
"Teleporter","Button","Switch",
"ConveyorBelt","ShadowConveyorBelt","NotificationBlock", "Collectable", "Pushable"
};
map<string,int> Game::blockNameMap;
map<int,string> Game::gameObjectEventTypeMap;
map<string,int> Game::gameObjectEventNameMap;
map<int,string> Game::levelEventTypeMap;
map<string,int> Game::levelEventNameMap;
string Game::recordFile;
//An internal function.
static void copyCompiledScripts(lua_State *state, const std::map<int, int>& src, std::map<int, int>& dest) {
//Clear the existing scripts.
for (auto it = dest.begin(); it != dest.end(); ++it) {
luaL_unref(state, LUA_REGISTRYINDEX, it->second);
}
dest.clear();
//Copy the source to the destination.
for (auto it = src.begin(); it != src.end(); ++it) {
lua_rawgeti(state, LUA_REGISTRYINDEX, it->second);
dest[it->first] = luaL_ref(state, LUA_REGISTRYINDEX);
}
}
//An internal function.
static void copyLevelObjects(const std::vector<Block*>& src, std::vector<Block*>& dest, bool setActive) {
//Clear the existing objects.
for (auto o : dest) delete o;
dest.clear();
//Copy the source to the destination.
for (auto o : src) {
if (o == NULL || o->isDelete) continue;
Block* o2 = new Block(*o);
dest.push_back(o2);
if (setActive) o2->setActive();
}
}
Game::Game(SDL_Renderer &renderer, ImageManager &imageManager):isReset(false)
, scriptExecutor(new ScriptExecutor())
,currentLevelNode(NULL)
,customTheme(NULL)
,background(NULL)
, levelRect(SDL_Rect{ 0, 0, 0, 0 }), levelRectSaved(SDL_Rect{ 0, 0, 0, 0 }), levelRectInitial(SDL_Rect{ 0, 0, 0, 0 })
,won(false)
,interlevel(false)
,gameTipIndex(0)
,time(0),timeSaved(0)
,recordings(0),recordingsSaved(0)
,cameraMode(CAMERA_PLAYER),cameraModeSaved(CAMERA_PLAYER)
,player(this),shadow(this),objLastCheckPoint(NULL)
, currentCollectables(0), currentCollectablesSaved(0), currentCollectablesInitial(0)
, totalCollectables(0), totalCollectablesSaved(0), totalCollectablesInitial(0)
{
saveStateNextTime=false;
loadStateNextTime=false;
recentSwap=recentSwapSaved=-10000;
recentLoad=recentSave=0;
action=imageManager.loadTexture(getDataPath()+"gfx/actions.png", renderer);
medals=imageManager.loadTexture(getDataPath()+"gfx/medals.png", renderer);
//Get the collectable image from the theme.
//NOTE: Isn't there a better way to retrieve the image?
objThemes.getBlock(TYPE_COLLECTABLE)->createInstance(&collectable);
//Hide the cursor if not in the leveleditor.
if(stateID!=STATE_LEVEL_EDITOR)
SDL_ShowCursor(SDL_DISABLE);
}
Game::~Game(){
//Simply call our destroy method.
destroy();
//Before we leave make sure the cursor is visible.
SDL_ShowCursor(SDL_ENABLE);
}
void Game::destroy(){
delete scriptExecutor;
scriptExecutor = NULL;
//Loop through the levelObjects, etc. and delete them.
for (auto o : levelObjects) delete o;
levelObjects.clear();
for (auto o : levelObjectsSave) delete o;
levelObjectsSave.clear();
for (auto o : levelObjectsInitial) delete o;
levelObjectsInitial.clear();
//Loop through the sceneryLayers and delete them.
for(auto it=sceneryLayers.begin();it!=sceneryLayers.end();++it){
delete it->second;
}
sceneryLayers.clear();
//Clear the name and the editor data.
levelName.clear();
levelFile.clear();
editorData.clear();
//Remove everything from the themeManager.
background=NULL;
if(customTheme)
objThemes.removeTheme();
customTheme=NULL;
//If there's a (partial) theme bundled with the levelpack remove that as well.
if(levels->customTheme)
objThemes.removeTheme();
//delete current level (if any)
if(currentLevelNode){
delete currentLevelNode;
currentLevelNode=NULL;
}
//Reset the time.
time=timeSaved=0;
recordings=recordingsSaved=0;
recentSwap=recentSwapSaved=-10000;
//Set the music list back to the configured list.
getMusicManager()->setMusicList(getSettings()->getValue("musiclist"));
}
void Game::reloadMusic() {
//NOTE: level music is always enabled.
//Check if the levelpack has a prefered music list.
if (levels && !levels->levelpackMusicList.empty())
getMusicManager()->setMusicList(levels->levelpackMusicList);
//Check for the music to use.
string &s = editorData["music"];
if (!s.empty()) {
getMusicManager()->playMusic(s);
} else {
getMusicManager()->pickMusic();
}
}
void Game::loadLevelFromNode(ImageManager& imageManager,SDL_Renderer& renderer,TreeStorageNode* obj,const string& fileName){
//Make sure there's nothing left from any previous levels.
assert(levelObjects.empty() && levelObjectsSave.empty() && levelObjectsInitial.empty());
//set current level to loaded one.
currentLevelNode=obj;
//Set the level dimensions to the default, it will probably be changed by the editorData,
//but 800x600 is a fallback.
levelRect = levelRectSaved = levelRectInitial = SDL_Rect{ 0, 0, 800, 600 };
currentCollectables = currentCollectablesSaved = currentCollectablesInitial = 0;
totalCollectables = totalCollectablesSaved = totalCollectablesInitial = 0;
//Load the additional data.
for(map<string,vector<string> >::iterator i=obj->attributes.begin();i!=obj->attributes.end();++i){
if(i->first=="size"){
//We found the size attribute.
if(i->second.size()>=2){
//Set the dimensions of the level.
int w = atoi(i->second[0].c_str()), h = atoi(i->second[1].c_str());
levelRect = levelRectSaved = levelRectInitial = SDL_Rect{ 0, 0, w, h };
}
}else if(i->second.size()>0){
//Any other data will be put into the editorData.
editorData[i->first]=i->second[0];
}
}
//Get the theme.
{
//NOTE: level themes are always enabled.
//Check for bundled (partial) themes for level pack.
if (levels->customTheme){
if (objThemes.appendThemeFromFile(levels->levelpackPath + "/theme/theme.mnmstheme", imageManager, renderer) == NULL){
//The theme failed to load so set the customTheme boolean to false.
levels->customTheme = false;
}
}
//Check for the theme to use for this level. This has higher priority.
//Examples: %DATA%/themes/classic or %USER%/themes/Orange
string &s = editorData["theme"];
if (!s.empty()){
customTheme = objThemes.appendThemeFromFile(processFileName(s) + "/theme.mnmstheme", imageManager, renderer);
}
//Set the Appearance of the player and the shadow.
objThemes.getCharacter(false)->createInstance(&player.appearance, "standright");
player.appearanceInitial = player.appearanceSave = player.appearance;
objThemes.getCharacter(true)->createInstance(&shadow.appearance, "standright");
shadow.appearanceInitial = shadow.appearanceSave = shadow.appearance;
}
//Get the music.
reloadMusic();
//Load the data from the level node.
for(unsigned int i=0;i<obj->subNodes.size();i++){
TreeStorageNode* obj1=obj->subNodes[i];
if(obj1==NULL) continue;
if(obj1->name=="tile"){
Block* block=new Block(this);
if(!block->loadFromNode(imageManager,renderer,obj1)){
delete block;
continue;
}
//If the type is collectable, increase the number of totalCollectables
if (block->type == TYPE_COLLECTABLE) {
totalCollectablesSaved = totalCollectablesInitial = ++totalCollectables;
}
//Add the block to the levelObjects vector.
levelObjects.push_back(block);
}else if(obj1->name=="scenerylayer" && obj1->value.size()==1){
//Check if the layer exists.
if (sceneryLayers[obj1->value[0]] == NULL) {
sceneryLayers[obj1->value[0]] = new SceneryLayer();
}
//Load contents from node.
sceneryLayers[obj1->value[0]]->loadFromNode(this, imageManager, renderer, obj1);
}else if(obj1->name=="script" && !obj1->value.empty()){
map<string,int>::iterator it=Game::levelEventNameMap.find(obj1->value[0]);
if(it!=Game::levelEventNameMap.end()){
int eventType=it->second;
const std::string& script=obj1->attributes["script"][0];
if(!script.empty()) scripts[eventType]=script;
}
}
}
//Set the levelName to the name of the current level.
levelName=editorData["name"];
levelFile=fileName;
//Some extra stuff only needed when not in the levelEditor.
if(stateID!=STATE_LEVEL_EDITOR){
//We create a text with the text "Level <levelno> <levelName>".
//It will be shown in the left bottom corner of the screen.
string s;
if(levels->getLevelCount()>1 && levels->type!=COLLECTION){
s=tfm::format(_("Level %d %s"),levels->getCurrentLevel()+1,_CC(levels->getDictionaryManager(),editorData["name"]));
} else {
s = _CC(levels->getDictionaryManager(), editorData["name"]);
}
bmTips[0]=textureFromText(renderer, *fontText,s.c_str(),objThemes.getTextColor(true));
}
//Get the background
background=objThemes.getBackground(false);
//Now the loading is finished, we reset all objects to their initial states.
//Before doing that we swap the levelObjects to levelObjectsInitial.
std::swap(levelObjects, levelObjectsInitial);
reset(true, stateID == STATE_LEVEL_EDITOR);
}
void Game::loadLevel(ImageManager& imageManager,SDL_Renderer& renderer,std::string fileName){
//Create a TreeStorageNode that will hold the loaded data.
TreeStorageNode *obj=new TreeStorageNode();
{
POASerializer objSerializer;
string s=fileName;
//Parse the file.
if(!objSerializer.loadNodeFromFile(s.c_str(),obj,true)){
cerr<<"ERROR: Can't load level file "<<s<<endl;
delete obj;
return;
}
}
//Now call another function.
loadLevelFromNode(imageManager,renderer,obj,fileName);
}
void Game::saveRecord(const char* fileName){
//check if current level is NULL (which should be impossible)
if(currentLevelNode==NULL) return;
TreeStorageNode obj;
POASerializer objSerializer;
//put current level to the node.
currentLevelNode->name="map";
obj.subNodes.push_back(currentLevelNode);
//put the random seed into the attributes.
obj.attributes["seed"].push_back(prngSeed);
//serialize the game record using RLE compression.
#define PUSH_BACK \
if(j>0){ \
if(j>1){ \
sprintf(c,"%d*%d",last,j); \
}else{ \
sprintf(c,"%d",last); \
} \
v.push_back(c); \
}
vector<string> &v=obj.attributes["record"];
vector<int> *record=player.getRecord();
char c[64];
int i,j=0,last;
for(i=0;i<(int)record->size();i++){
int currentKey=(*record)[i];
if(j==0 || currentKey!=last){
PUSH_BACK;
last=currentKey;
j=1;
}else{
j++;
}
}
PUSH_BACK;
#undef PUSH_BACK
#ifdef RECORD_FILE_DEBUG
//add record file debug data.
{
obj.attributes["recordKeyPressLog"].push_back(player.keyPressLog());
vector<SDL_Rect> &playerPosition=player.playerPosition();
string s;
char c[32];
sprintf(c,"%d\n",int(playerPosition.size()));
s=c;
for(unsigned int i=0;i<playerPosition.size();i++){
SDL_Rect& r=playerPosition[i];
sprintf(c,"%d %d\n",r.x,r.y);
s+=c;
}
obj.attributes["recordPlayerPosition"].push_back(s);
}
#endif
//save it
objSerializer.saveNodeToFile(fileName,&obj,true,true);
//remove current level from node to prevent delete it.
obj.subNodes.clear();
}
void Game::loadRecord(ImageManager& imageManager, SDL_Renderer& renderer, const char* fileName){
//Create a TreeStorageNode that will hold the loaded data.
TreeStorageNode obj;
{
POASerializer objSerializer;
//Parse the file.
if(!objSerializer.loadNodeFromFile(fileName,&obj,true)){
cerr<<"ERROR: Can't load record file "<<fileName<<endl;
return;
}
}
//Load the seed of psuedo-random number generator.
prngSeed.clear();
{
auto it = obj.attributes.find("seed");
if (it != obj.attributes.end() && !it->second.empty()) {
prngSeed = it->second[0];
}
}
//find the node named 'map'.
bool loaded=false;
for(unsigned int i=0;i<obj.subNodes.size();i++){
if(obj.subNodes[i]->name=="map"){
//load the level. (fileName=???)
loadLevelFromNode(imageManager,renderer,obj.subNodes[i],"?record?");
//remove this node to prevent delete it.
obj.subNodes[i]=NULL;
//over
loaded=true;
break;
}
}
if(!loaded){
cerr<<"ERROR: Can't find subnode named 'map' from record file"<<endl;
return;
}
//load the record.
{
vector<int> *record=player.getRecord();
record->clear();
vector<string> &v=obj.attributes["record"];
for(unsigned int i=0;i<v.size();i++){
string &s=v[i];
string::size_type pos=s.find_first_of('*');
if(pos==string::npos){
//1 item only.
int i=atoi(s.c_str());
record->push_back(i);
}else{
//contains many items.
int i=atoi(s.substr(0,pos).c_str());
int j=atoi(s.substr(pos+1).c_str());
for(;j>0;j--){
record->push_back(i);
}
}
}
}
#ifdef RECORD_FILE_DEBUG
//load the debug data
{
vector<string> &v=obj.attributes["recordPlayerPosition"];
vector<SDL_Rect> &playerPosition=player.playerPosition();
playerPosition.clear();
if(!v.empty()){
if(!v[0].empty()){
stringstream st(v[0]);
int m;
st>>m;
for(int i=0;i<m;i++){
SDL_Rect r;
st>>r.x>>r.y;
r.w=0;
r.h=0;
playerPosition.push_back(r);
}
}
}
}
#endif
//play the record.
//TODO: tell the level manager don't save the level progress.
player.playRecord();
shadow.playRecord(); //???
}
/////////////EVENT///////////////
void Game::handleEvents(ImageManager& imageManager, SDL_Renderer& renderer){
//First of all let the player handle input.
player.handleInput(&shadow);
//Check for an SDL_QUIT event.
if(event.type==SDL_QUIT){
//We need to quit so enter STATE_EXIT.
setNextState(STATE_EXIT);
}
//Check for the escape key.
if(stateID != STATE_LEVEL_EDITOR && inputMgr.isKeyDownEvent(INPUTMGR_ESCAPE)){
//Escape means we go one level up, to the level select state.
setNextState(STATE_LEVEL_SELECT);
//Save the progress.
levels->saveLevelProgress();
//And change the music back to the menu music.
getMusicManager()->playMusic("menu");
}
//Check if 'R' is pressed.
if(inputMgr.isKeyDownEvent(INPUTMGR_RESTART)){
//Restart game only if we are not watching a replay.
if (!player.isPlayFromRecord() || interlevel) {
//Reset the game at next frame.
isReset = true;
//Also delete any gui (most likely the interlevel gui). Only in game mode.
if (GUIObjectRoot && stateID != STATE_LEVEL_EDITOR){
delete GUIObjectRoot;
GUIObjectRoot = NULL;
}
//And set interlevel to false.
interlevel = false;
}
}
//Check for the next level buttons when in the interlevel popup.
if (inputMgr.isKeyDownEvent(INPUTMGR_SPACE) || inputMgr.isKeyDownEvent(INPUTMGR_SELECT)){
if(interlevel){
//The interlevel popup is shown so we need to delete it.
if(GUIObjectRoot){
delete GUIObjectRoot;
GUIObjectRoot=NULL;
}
//Now goto the next level.
gotoNextLevel(imageManager,renderer);
}
}
//Check if tab is pressed.
if(inputMgr.isKeyDownEvent(INPUTMGR_TAB)){
//Switch the camera mode.
switch(cameraMode){
case CAMERA_PLAYER:
cameraMode=CAMERA_SHADOW;
break;
case CAMERA_SHADOW:
case CAMERA_CUSTOM:
cameraMode=CAMERA_PLAYER;
break;
}
}
}
/////////////////LOGIC///////////////////
void Game::logic(ImageManager& imageManager, SDL_Renderer& renderer){
//Add one tick to the time.
time++;
//NOTE: This code reverts some changes in commit 5f03ae5.
//This is part of old prepareFrame() code.
//This is needed since otherwise the script function block:setLocation() and block:moveTo() are completely broken.
//Later we should rewrite collision system completely which will remove this piece of code.
//NOTE: In new collision system the effect of dx/dy/xVel/yVel should only be restricted in one frame.
for (auto obj : levelObjects) {
switch (obj->type) {
default:
obj->dx = obj->dy = obj->xVel = obj->yVel = 0;
break;
case TYPE_PUSHABLE:
//NOTE: Currently the dx/dy/etc. of pushable blocks are still carry across frames, in order to make the collision system work correct.
break;
case TYPE_CONVEYOR_BELT: case TYPE_SHADOW_CONVEYOR_BELT:
//NOTE: We let the conveyor belt itself to reset its xVel/yVel.
obj->dx = obj->dy = 0;
break;
}
}
//NOTE2: The above code breaks pushable block with moving block in most cases,
//more precisely, if the pushable block is processed before the moving block then things may be broken.
//Therefore later we must process other blocks before moving pushable block.
//Process delay execution scripts.
getScriptExecutor()->processDelayExecution();
//Process any event in the queue.
for(unsigned int idx=0;idx<eventQueue.size();idx++){
//Get the event from the queue.
typeGameObjectEvent &e=eventQueue[idx];
//Check if the it has an id attached to it.
if(e.target){
//NOTE: Should we check if the target still exists???
e.target->onEvent(e.eventType);
}else if(e.flags&1){
//Loop through the levelObjects and give them the event if they have the right id.
for(unsigned int i=0;i<levelObjects.size();i++){
if(e.objectType<0 || levelObjects[i]->type==e.objectType){
if(levelObjects[i]->id==e.id){
levelObjects[i]->onEvent(e.eventType);
}
}
}
}else{
//Loop through the levelObjects and give them the event.
for(unsigned int i=0;i<levelObjects.size();i++){
if(e.objectType<0 || levelObjects[i]->type==e.objectType){
levelObjects[i]->onEvent(e.eventType);
}
}
}
}
//Done processing the events so clear the queue.
eventQueue.clear();
//Remove levelObjects whose isDelete is true.
{
int j = 0;
for (int i = 0; i < (int)levelObjects.size(); i++) {
if (levelObjects[i] == NULL) {
j++;
} else if (levelObjects[i]->isDelete) {
delete levelObjects[i];
levelObjects[i] = NULL;
j++;
} else if (j > 0) {
levelObjects[i - j] = levelObjects[i];
}
}
if (j > 0) levelObjects.resize(levelObjects.size() - j);
}
//Check if we should save/load state.
//NOTE: This happens after event handling so no eventQueue has to be saved/restored.
if(saveStateNextTime){
saveState();
}else if(loadStateNextTime){
loadState();
}
saveStateNextTime=false;
loadStateNextTime=false;
//Loop through the gameobjects to update them.
for(unsigned int i=0;i<levelObjects.size();i++){
//Send GameObjectEvent_OnEnterFrame event to the script
levelObjects[i]->onEvent(GameObjectEvent_OnEnterFrame);
}
//Let the gameobject handle movement.
{
std::vector<Block*> pushableBlocks;
//First we process blocks which are not pushable blocks.
for (auto o : levelObjects) {
if (o->type == TYPE_PUSHABLE) {
pushableBlocks.push_back(o);
} else {
o->move();
}
}
//Sort pushable blocks by their position, which is an ad-hoc workaround for
//<https://forum.freegamedev.net/viewtopic.php?f=48&t=8047#p77692>.
std::stable_sort(pushableBlocks.begin(), pushableBlocks.end(),
[](const Block* obj1, const Block* obj2)->bool
{
SDL_Rect r1 = const_cast<Block*>(obj1)->getBox(), r2 = const_cast<Block*>(obj2)->getBox();
if (r1.y > r2.y) return true;
else if (r1.y < r2.y) return false;
else return r1.x < r2.x;
});
//Now we process pushable blocks.
for (auto o : pushableBlocks) {
o->move();
}
}
//Also update the scenery.
for (auto it = sceneryLayers.begin(); it != sceneryLayers.end(); ++it){
it->second->updateAnimation();
}
//Let the player store his move, if recording.
player.shadowSetState();
//Let the player give his recording to the shadow, if configured.
player.shadowGiveState(&shadow);
//NOTE: to fix bugs regarding player/shadow swap, we should first process collision of player/shadow then move them
const SDL_Rect playerLastPosition = player.getBox();
const SDL_Rect shadowLastPosition = shadow.getBox();
//NOTE: The following is ad-hoc code to fix shadow on blocked player on conveyor belt bug
if (shadow.holdingOther) {
//We need to process shadow collision first if shadow is holding player.
//Let the shadow decide his move, if he's playing a recording.
shadow.moveLogic();
//Check collision for shadow.
shadow.collision(levelObjects, NULL);
//Get the new position of it.
const SDL_Rect r = shadow.getBox();
//Check collision for player. Transfer the velocity of shadow to it only if the shadow moves its position.
player.collision(levelObjects, (r.x != shadowLastPosition.x || r.y != shadowLastPosition.y) ? &shadow : NULL);
} else {
//Otherwise we process player first.
//Check collision for player.
player.collision(levelObjects, NULL);
//Get the new position of it.
const SDL_Rect r = player.getBox();
//Now let the shadow decide his move, if he's playing a recording.
shadow.moveLogic();
//Check collision for shadow. Transfer the velocity of player to it only if the player moves its position.
shadow.collision(levelObjects, (r.x != playerLastPosition.x || r.y != playerLastPosition.y) ? &player : NULL);
}
//Let the player move.
player.move(levelObjects, playerLastPosition.x, playerLastPosition.y);
//Let the shadow move.
shadow.move(levelObjects, shadowLastPosition.x, shadowLastPosition.y);
//Check collision and stuff for the shadow and player.
player.otherCheck(&shadow);
//Update the camera.
switch(cameraMode){
case CAMERA_PLAYER:
player.setMyCamera();
break;
case CAMERA_SHADOW:
shadow.setMyCamera();
break;
case CAMERA_CUSTOM:
//NOTE: The target is (should be) screen size independent so calculate the real target x and y here.
int targetX=cameraTarget.x-(SCREEN_WIDTH/2);
int targetY=cameraTarget.y-(SCREEN_HEIGHT/2);
//Move the camera to the cameraTarget.
if(camera.x>targetX){
camera.x-=(camera.x-targetX)>>4;
//Make sure we don't go too far.
if(camera.x<targetX)
camera.x=targetX;
}else if(camera.x<targetX){
camera.x+=(targetX-camera.x)>>4;
//Make sure we don't go too far.
if(camera.x>targetX)
camera.x=targetX;
}
if(camera.y>targetY){
camera.y-=(camera.y-targetY)>>4;
//Make sure we don't go too far.
if(camera.y<targetY)
camera.y=targetY;
}else if(camera.y<targetY){
camera.y+=(targetY-camera.y)>>4;
//Make sure we don't go too far.
if(camera.y>targetY)
camera.y=targetY;
}
break;
}
//Check if we won.
if(won){
//Check if it's playing from record
if(player.isPlayFromRecord() && !interlevel){
recordingEnded(imageManager,renderer);
}else{
//the string to store auto-save record path.
string bestTimeFilePath,bestRecordingFilePath;
//and if we can't get test path.
bool filePathError=false;
//Get current level
LevelPack::Level *level=levels->getLevel();
//Now check if we should update statistics
{
//Get previous and current medal
int oldMedal=level->won?1:0,newMedal=1;
int bestTime=level->time;
int targetTime=level->targetTime;
int bestRecordings=level->recordings;
int targetRecordings=level->targetRecordings;
if(oldMedal){
if(bestTime>=0 && (targetTime<0 || bestTime<=targetTime))
oldMedal++;
if(bestRecordings>=0 && (targetRecordings<0 || bestRecordings<=targetRecordings))
oldMedal++;
}else{
bestTime=time;
bestRecordings=recordings;
}
if(bestTime<0 || bestTime>time) bestTime=time;
if(bestRecordings<0 || bestRecordings>recordings) bestRecordings=recordings;
if(targetTime<0 || bestTime<=targetTime)
newMedal++;
if(targetRecordings<0 || bestRecordings<=targetRecordings)
newMedal++;
//Check if we need to update statistics
if(newMedal>oldMedal){
switch(oldMedal){
case 0:
statsMgr.completedLevels++;
break;
case 2:
statsMgr.silverLevels--;
break;
}
switch(newMedal){
case 2:
statsMgr.silverLevels++;
break;
case 3:
statsMgr.goldLevels++;
break;
}
}
}
//Check the achievement "Complete a level with checkpoint, but without saving"
if (objLastCheckPoint.get() == NULL) {
for (auto obj : levelObjects) {
if (obj->type == TYPE_CHECKPOINT) {
statsMgr.newAchievement("withoutsave");
break;
}
}
}
//Set the current level won.
level->won=true;
if(level->time==-1 || level->time>time){
level->time=time;
//save the best-time game record.
if(bestTimeFilePath.empty()){
getCurrentLevelAutoSaveRecordPath(bestTimeFilePath,bestRecordingFilePath,true);
}
if(bestTimeFilePath.empty()){
cerr<<"ERROR: Couldn't get auto-save record file path"<<endl;
filePathError=true;
}else{
saveRecord(bestTimeFilePath.c_str());
}
}
if(level->recordings==-1 || level->recordings>recordings){
level->recordings=recordings;
//save the best-recordings game record.
if(bestRecordingFilePath.empty() && !filePathError){
getCurrentLevelAutoSaveRecordPath(bestTimeFilePath,bestRecordingFilePath,true);
}
if(bestRecordingFilePath.empty()){
cerr<<"ERROR: Couldn't get auto-save record file path"<<endl;
filePathError=true;
}else{
saveRecord(bestRecordingFilePath.c_str());
}
}
//Set the next level unlocked if it exists.
if(levels->getCurrentLevel()+1<levels->getLevelCount()){
levels->setLocked(levels->getCurrentLevel()+1);
}
//And save the progress.
levels->saveLevelProgress();
//Now go to the interlevel screen.
replayPlay(imageManager,renderer);
//Update achievements
if(levels->levelpackName=="tutorial") statsMgr.updateTutorialAchievements();
statsMgr.updateLevelAchievements();
//NOTE: We set isReset false to prevent the user from getting a best time of 0.00s and 0 recordings.
isReset = false;
}
}
won=false;
//Check if we should reset.
if (isReset) {
//NOTE: we don't need to reset save ??? it looks like that there are no bugs
reset(false, false);
}
isReset=false;
}
+// ad-hoc function which only works for ASC characters (but it doesn't ruin UTF-8 characters)
+static inline char myToupper(char c) {
+ if (c >= 'a' && c <= 'z') {
+ return c + ('A' - 'a');
+ } else {
+ return c;
+ }
+}
+
/////////////////RENDER//////////////////
void Game::render(ImageManager&,SDL_Renderer &renderer){
//First of all render the background.
{
//Get a pointer to the background.
ThemeBackground* bg=background;
//Check if the background is null, but there are themes.
if(bg==NULL && objThemes.themeCount()>0){
//Get the background from the first theme in the stack.
bg=objThemes[0]->getBackground(false);
}
//Check if the background isn't null.
if(bg){
//It isn't so draw it.
bg->draw(renderer);
//And if it's the loaded background then also update the animation.
//FIXME: Updating the animation in the render method?
if(bg==background)
bg->updateAnimation();
}else{
//There's no background so fill the screen with white.
SDL_SetRenderDrawColor(&renderer, 255,255,255,255);
SDL_RenderClear(&renderer);
}
}
//Now draw the blackground layers.
auto it = sceneryLayers.begin();
for (; it != sceneryLayers.end(); ++it){
if (it->first >= "f") break; // now we meet a foreground layer
it->second->show(renderer);
}
//Now we draw the levelObjects.
{
//NEW: always render the pushable blocks in front of other blocks
std::vector<Block*> pushableBlocks;
for (auto o : levelObjects) {
if (o->type == TYPE_PUSHABLE) {
pushableBlocks.push_back(o);
} else {
o->show(renderer);
}
}
for (auto o : pushableBlocks) {
o->show(renderer);
}
}
//Followed by the player and the shadow.
//NOTE: We draw the shadow first, because he needs to be behind the player.
shadow.show(renderer);
player.show(renderer);
//Now draw the foreground layers.
for (; it != sceneryLayers.end(); ++it){
it->second->show(renderer);
}
//Show the levelName if it isn't the level editor.
if(stateID!=STATE_LEVEL_EDITOR && bmTips[0]!=NULL && !interlevel){
withTexture(*bmTips[0], [&](SDL_Rect r){
drawGUIBox(-2,SCREEN_HEIGHT-r.h-4,r.w+8,r.h+6,renderer,0xFFFFFFFF);
applyTexture(2,SCREEN_HEIGHT-r.h,*bmTips[0],renderer,NULL);
});
}
//Check if there's a tooltip.
//NOTE: gameTipIndex 0 is used for the levelName, 1 for shadow death, 2 for restart text, 3 for restart+checkpoint.
if(gameTipIndex>3 && gameTipIndex<TYPE_MAX){
//Check if there's a tooltip for the type.
if(bmTips[gameTipIndex]==NULL){
//There isn't thus make it.
string s;
string keyCode = InputManagerKeyCode::describeTwo(inputMgr.getKeyCode(INPUTMGR_ACTION, false), inputMgr.getKeyCode(INPUTMGR_ACTION, true));
- transform(keyCode.begin(),keyCode.end(),keyCode.begin(),::toupper);
+ transform(keyCode.begin(),keyCode.end(),keyCode.begin(),myToupper);
switch(gameTipIndex){
case TYPE_CHECKPOINT:
/// TRANSLATORS: Please do not remove %s from your translation:
/// - %s will be replaced with current action key
s=tfm::format(_("Press %s key to save the game."),keyCode);
break;
case TYPE_SWAP:
/// TRANSLATORS: Please do not remove %s from your translation:
/// - %s will be replaced with current action key
s=tfm::format(_("Press %s key to swap the position of player and shadow."),keyCode);
break;
case TYPE_SWITCH:
/// TRANSLATORS: Please do not remove %s from your translation:
/// - %s will be replaced with current action key
s=tfm::format(_("Press %s key to activate the switch."),keyCode);
break;
case TYPE_PORTAL:
/// TRANSLATORS: Please do not remove %s from your translation:
/// - %s will be replaced with current action key
s=tfm::format(_("Press %s key to teleport."),keyCode);
break;
}
//If we have a string then it's a supported GameObject type.
if(!s.empty()){
bmTips[gameTipIndex]=textureFromText(renderer, *fontText, s.c_str(), objThemes.getTextColor(true));
}
}
//We already have a gameTip for this type so draw it.
if(bmTips[gameTipIndex]!=NULL){
withTexture(*bmTips[gameTipIndex], [&](SDL_Rect r){
drawGUIBox(-2,-2,r.w+8,r.h+6,renderer,0xFFFFFFFF);
applyTexture(2,2,*bmTips[gameTipIndex],renderer);
});
}
}
//Set the gameTip to 0.
gameTipIndex=0;
// Limit the scope of bm, as it's a borrowed pointer.
{
//Pointer to the sdl texture that will contain a message, if any.
SDL_Texture* bm=NULL;
//Check if the player is dead, meaning we draw a message.
if(player.dead){
//Get user configured restart key
string keyCodeRestart = InputManagerKeyCode::describeTwo(inputMgr.getKeyCode(INPUTMGR_RESTART, false), inputMgr.getKeyCode(INPUTMGR_RESTART, true));
- transform(keyCodeRestart.begin(),keyCodeRestart.end(),keyCodeRestart.begin(),::toupper);
+ transform(keyCodeRestart.begin(),keyCodeRestart.end(),keyCodeRestart.begin(),myToupper);
//The player is dead, check if there's a state that can be loaded.
if(player.canLoadState()){
//Now check if the tip is already made, if not make it.
if(bmTips[3]==NULL){
//Get user defined key for loading checkpoint
string keyCodeLoad = InputManagerKeyCode::describeTwo(inputMgr.getKeyCode(INPUTMGR_LOAD, false), inputMgr.getKeyCode(INPUTMGR_LOAD, true));
- transform(keyCodeLoad.begin(),keyCodeLoad.end(),keyCodeLoad.begin(),::toupper);
+ transform(keyCodeLoad.begin(),keyCodeLoad.end(),keyCodeLoad.begin(),myToupper);
//Draw string
bmTips[3]=textureFromText(renderer, *fontText,//TTF_RenderUTF8_Blended(fontText,
/// TRANSLATORS: Please do not remove %s from your translation:
/// - first %s means currently configured key to restart game
/// - Second %s means configured key to load from last save
tfm::format(_("Press %s to restart current level or press %s to load the game."),
keyCodeRestart,keyCodeLoad).c_str(),
objThemes.getTextColor(true));
}
bm=bmTips[3].get();
}else{
//Now check if the tip is already made, if not make it.
if(bmTips[2]==NULL){
bmTips[2]=textureFromText(renderer, *fontText,
/// TRANSLATORS: Please do not remove %s from your translation:
/// - %s will be replaced with currently configured key to restart game
tfm::format(_("Press %s to restart current level."),keyCodeRestart).c_str(),
objThemes.getTextColor(true));
}
bm=bmTips[2].get();
}
}
//Check if the shadow has died (and there's no other notification).
//NOTE: We use the shadow's jumptime as countdown, this variable isn't used when the shadow is dead.
if(shadow.dead && bm==NULL && shadow.jumpTime>0){
//Now check if the tip is already made, if not make it.
if(bmTips[1]==NULL){
bmTips[1]=textureFromText(renderer, *fontText,
_("Your shadow has died."),
objThemes.getTextColor(true));
}
bm=bmTips[1].get();
//NOTE: Logic in the render loop, we substract the shadow's jumptime by one.
shadow.jumpTime--;
//return view to player and keep it there
cameraMode=CAMERA_PLAYER;
}
//Draw the tip.
if(bm!=NULL){
const SDL_Rect textureSize = rectFromTexture(*bm);
int x=(SCREEN_WIDTH-textureSize.w)/2;
int y=32;
drawGUIBox(x-8,y-8,textureSize.w+16,textureSize.h+14,renderer,0xFFFFFFFF);
applyTexture(x,y,*bm,renderer);
}
}
//Show the number of collectables the user has collected if there are collectables in the level.
//We hide this when interlevel.
if ((currentCollectables || totalCollectables) && !interlevel && time>0){
if (collectablesTexture.needsUpdate(currentCollectables ^ (totalCollectables << 16))) {
collectablesTexture.update(currentCollectables ^ (totalCollectables << 16),
textureFromText(renderer,
*fontText,
tfm::format("%d/%d", currentCollectables, totalCollectables).c_str(),
objThemes.getTextColor(true)));
}
SDL_Rect bmSize = rectFromTexture(*collectablesTexture.get());
//Draw background
drawGUIBox(SCREEN_WIDTH-bmSize.w-34,SCREEN_HEIGHT-bmSize.h-4,bmSize.w+34+2,bmSize.h+4+2,renderer,0xFFFFFFFF);
//Draw the collectable icon
collectable.draw(renderer,SCREEN_WIDTH-50+12,SCREEN_HEIGHT-50+10);
//Draw text
applyTexture(SCREEN_WIDTH-50-bmSize.w+22,SCREEN_HEIGHT-bmSize.h,collectablesTexture.getTexture(),renderer);
}
//show time and records used in level editor or during replay.
if((stateID==STATE_LEVEL_EDITOR || (!interlevel && player.isPlayFromRecord())) && time>0){
const SDL_Color fg=objThemes.getTextColor(true),bg={255,255,255,255};
const int alpha = 160;
if (recordingsTexture.needsUpdate(recordings)) {
recordingsTexture.update(recordings,
textureFromTextShaded(
renderer,
*fontText,
tfm::format(ngettext("%d recording","%d recordings",recordings).c_str(),recordings).c_str(),
fg,
bg
));
SDL_SetTextureAlphaMod(recordingsTexture.get(),alpha);
}
int y=SCREEN_HEIGHT - textureHeight(*recordingsTexture.get());
if (stateID != STATE_LEVEL_EDITOR && bmTips[0] != NULL && !interlevel) {
y -= textureHeight(bmTips[0]) + 4;
}
applyTexture(0,y,*recordingsTexture.get(), renderer);
if(timeTexture.needsUpdate(time)) {
const size_t len = 32;
timeTexture.update(time,
textureFromTextShaded(
renderer,
*fontText,
tfm::format("%-.2fs", time / 40.0).c_str(),
fg,
bg
));
}
y -= textureHeight(*timeTexture.get());
applyTexture(0,y,*timeTexture.get(), renderer);
}
//Draw the current action in the upper right corner.
if(player.record){
const SDL_Rect r = { 0, 0, 50, 50 };
applyTexture(SCREEN_WIDTH - 50, 0, *action, renderer, &r);
} else if (shadow.state != 0){
const SDL_Rect r={50,0,50,50};
applyTexture(SCREEN_WIDTH-50,0,*action,renderer,&r);
}
//if the game is play from record then draw something indicates it
if(player.isPlayFromRecord()){
//Dim the screen if interlevel is true.
if( interlevel){
dimScreen(renderer,191);
}else if((time & 0x10)==0x10){
// FIXME: replace this ugly ad-hoc animation by a better one
const SDL_Rect r={50,0,50,50};
applyTexture(0,0,*action,renderer,&r);
//applyTexture(0,SCREEN_HEIGHT-50,*action,renderer,&r);
//applyTexture(SCREEN_WIDTH-50,SCREEN_HEIGHT-50,*action,renderer,&r);
}
}else if(auto blockId = player.objNotificationBlock.get()){
//If the player is in front of a notification block show the message.
//And it isn't a replay.
//Check if we need to update the notification message texture.
int maxWidth = 0;
int y = 20;
//We check against blockId rather than the full message, as blockId is most likely shorter.
if(notificationTexture.needsUpdate(blockId)) {
const std::string &untranslated_message=blockId->message;
std::string message=_CC(levels->getDictionaryManager(),untranslated_message);
std::vector<std::string> string_data;
//Trim the message.
{
size_t lps = message.find_first_not_of("\n\r \t");
if (lps == string::npos) {
message.clear(); // it's completely empty
} else {
message = message.substr(lps, message.find_last_not_of("\n\r \t") - lps + 1);
}
}
//Split the message into lines.
for (int lps = 0;;) {
// determine the end of line
int lpe = lps;
for (; message[lpe] != '\n' && message[lpe] != '\r' && message[lpe] != '\0'; lpe++);
string_data.push_back(message.substr(lps, lpe - lps));
// break if the string ends
if (message[lpe] == '\0') break;
// skip "\r\n" for Windows line ending
if (message[lpe] == '\r' && message[lpe + 1] == '\n') lpe++;
// point to the start of next line
lps = lpe + 1;
}
vector<SurfacePtr> lines;
//Create the image for each lines
for (int i = 0; i < (int)string_data.size(); i++) {
//Integer used to center the sentence horizontally.
int x = 0;
TTF_SizeUTF8(fontText, string_data[i].c_str(), &x, NULL);
//Find out largest width
if (x>maxWidth)
maxWidth = x;
lines.emplace_back(TTF_RenderUTF8_Blended(fontText, string_data[i].c_str(), objThemes.getTextColor(true)));
//Increase y with 25, about the height of the text.
y += 25;
}
maxWidth+=SCREEN_WIDTH*0.15;
SurfacePtr surf = createSurface(maxWidth, y);
int y1 = y;
for(SurfacePtr &s : lines) {
if(s) {
applySurface((surf->w-s->w)/2,surf->h - y1,s.get(),surf.get(),NULL);
}
y1 -= 25;
}
notificationTexture.update(blockId, textureUniqueFromSurface(renderer,std::move(surf)));
} else {
auto texSize = rectFromTexture(*notificationTexture.get());
maxWidth=texSize.w;
y=texSize.h;
}
drawGUIBox((SCREEN_WIDTH-maxWidth)/2,SCREEN_HEIGHT-y-25,maxWidth,y+20,renderer,0xFFFFFFBF);
applyTexture((SCREEN_WIDTH-maxWidth)/2,SCREEN_HEIGHT-y,notificationTexture.getTexture(),renderer);
}
}
void Game::resize(ImageManager&, SDL_Renderer& /*renderer*/){
//Check if the interlevel popup is shown.
if(interlevel && GUIObjectRoot){
GUIObjectRoot->left=(SCREEN_WIDTH-GUIObjectRoot->width)/2;
}
}
void Game::replayPlay(ImageManager& imageManager,SDL_Renderer& renderer){
//Set interlevel true.
interlevel=true;
//Make a copy of the playerButtons.
vector<int> recordCopy=player.recordButton;
//Reset the game.
//NOTE: We don't reset the saves. I'll see that if it will introduce bugs.
reset(false, false);
//Make the cursor visible when the interlevel popup is up.
SDL_ShowCursor(SDL_ENABLE);
//Set the copy of playerButtons back.
player.recordButton=recordCopy;
//Now play the recording.
player.playRecord();
//Create the gui if it isn't already done.
if(!GUIObjectRoot){
//Create a new GUIObjectRoot the size of the screen.
GUIObjectRoot=new GUIObject(imageManager,renderer,0,0,SCREEN_WIDTH,SCREEN_HEIGHT);
//Make child widgets change color properly according to theme.
GUIObjectRoot->inDialog=true;
//Create a GUIFrame for the upper frame.
GUIFrame* upperFrame=new GUIFrame(imageManager,renderer,0,4,0,74);
GUIObjectRoot->addChild(upperFrame);
//Render the You've finished: text and add it to a GUIImage.
//NOTE: The texture is managed by the GUIImage so no need to free it ourselfs.
auto bm = SharedTexture(textureFromText(renderer, *fontGUI,_("You've finished:"),objThemes.getTextColor(true)));
const SDL_Rect textureSize = rectFromTexture(*bm);
GUIImage* title=new GUIImage(imageManager,renderer,0,4-GUI_FONT_RAISE,textureSize.w,textureSize.h,bm);
upperFrame->addChild(title);
//Create the sub title.
string s;
if (levels->getLevelCount()>0){
/// TRANSLATORS: Please do not remove %s or %d from your translation:
/// - %d means the level number in a levelpack
/// - %s means the name of current level
s=tfm::format(_("Level %d %s"),levels->getCurrentLevel()+1,_CC(levels->getDictionaryManager(),levelName));
}
GUIObject* obj=new GUILabel(imageManager,renderer,0,44,0,28,s.c_str(),0,true,true,GUIGravityCenter);
upperFrame->addChild(obj);
obj->render(renderer,0,0,false);
//Determine the width the upper frame should have.
int width;
if(textureSize.w>obj->width)
width=textureSize.w+32;
else
width=obj->width+32;
//Set the left of the title.
title->left=(width-title->width)/2;
//Set the width of the level label to the width of the frame for centering.
obj->width=width;
//Now set the position and width of the frame.
upperFrame->width=width;
upperFrame->left=(SCREEN_WIDTH-width)/2;
//Now create a GUIFrame for the lower frame.
GUIFrame* lowerFrame=new GUIFrame(imageManager,renderer,0,SCREEN_HEIGHT-140,570,135);
GUIObjectRoot->addChild(lowerFrame);
//The different values.
int bestTime=levels->getLevel()->time;
int targetTime=levels->getLevel()->targetTime;
int bestRecordings=levels->getLevel()->recordings;
int targetRecordings=levels->getLevel()->targetRecordings;
int medal=1;
if(bestTime>=0 && (targetTime<0 || bestTime<=targetTime))
medal++;
if(bestRecordings>=0 && (targetRecordings<0 || bestRecordings<=targetRecordings))
medal++;
int maxWidth=0;
int x=20;
//Is there a target time for this level?
int timeY=0;
bool isTargetTime=true;
if(targetTime<0){
isTargetTime=false;
timeY=12;
}
//Create the labels with the time and best time.
/// TRANSLATORS: Please do not remove %-.2f from your translation:
/// - %-.2f means time in seconds
/// - s is shortened form of a second. Try to keep it so.
obj=new GUILabel(imageManager,renderer,x,10+timeY,-1,36,tfm::format(_("Time: %-.2fs"),time/40.0).c_str());
lowerFrame->addChild(obj);
obj->render(renderer,0,0,false);
maxWidth=obj->width;
/// TRANSLATORS: Please do not remove %-.2f from your translation:
/// - %-.2f means time in seconds
/// - s is shortened form of a second. Try to keep it so.
obj=new GUILabel(imageManager,renderer,x,34+timeY,-1,36,tfm::format(_("Best time: %-.2fs"),bestTime/40.0).c_str());
lowerFrame->addChild(obj);
obj->render(renderer,0,0,false);
if(obj->width>maxWidth)
maxWidth=obj->width;
/// TRANSLATORS: Please do not remove %-.2f from your translation:
/// - %-.2f means time in seconds
/// - s is shortened form of a second. Try to keep it so.
if(isTargetTime){
obj=new GUILabel(imageManager,renderer,x,58,-1,36,tfm::format(_("Target time: %-.2fs"),targetTime/40.0).c_str());
lowerFrame->addChild(obj);
obj->render(renderer,0,0,false);
if(obj->width>maxWidth)
maxWidth=obj->width;
}
x+=maxWidth+20;
//Is there target recordings for this level?
int recsY=0;
bool isTargetRecs=true;
if(targetRecordings<0){
isTargetRecs=false;
recsY=12;
}
//Now the ones for the recordings.
/// TRANSLATORS: Please do not remove %d from your translation:
/// - %d means the number of recordings user has made
obj=new GUILabel(imageManager,renderer,x,10+recsY,-1,36,tfm::format(_("Recordings: %d"),recordings).c_str());
lowerFrame->addChild(obj);
obj->render(renderer,0,0,false);
maxWidth=obj->width;
/// TRANSLATORS: Please do not remove %d from your translation:
/// - %d means the number of recordings user has made
obj=new GUILabel(imageManager,renderer,x,34+recsY,-1,36,tfm::format(_("Best recordings: %d"),bestRecordings).c_str());
lowerFrame->addChild(obj);
obj->render(renderer,0,0,false);
if(obj->width>maxWidth)
maxWidth=obj->width;
/// TRANSLATORS: Please do not remove %d from your translation:
/// - %d means the number of recordings user has made
if(isTargetRecs){
obj=new GUILabel(imageManager,renderer,x,58,-1,36,tfm::format(_("Target recordings: %d"),targetRecordings).c_str());
lowerFrame->addChild(obj);
obj->render(renderer,0,0,false);
if(obj->width>maxWidth)
maxWidth=obj->width;
}
x+=maxWidth;
//The medal that is earned.
/// TRANSLATORS: Please do not remove %s from your translation:
/// - %s will be replaced with name of a prize medal (gold, silver or bronze)
string s1=tfm::format(_("You earned the %s medal"),(medal>1)?(medal==3)?_("GOLD"):_("SILVER"):_("BRONZE"));
obj=new GUILabel(imageManager,renderer,50,92,-1,36,s1.c_str(),0,true,true,GUIGravityCenter);
lowerFrame->addChild(obj);
obj->render(renderer,0,0,false);
if(obj->left+obj->width>x){
x=obj->left+obj->width+30;
}else{
obj->left=20+(x-20-obj->width)/2;
}
//Create the rectangle for the earned medal.
SDL_Rect r;
r.x=(medal-1)*30;
r.y=0;
r.w=30;
r.h=30;
//Create the medal on the left side.
obj=new GUIImage(imageManager,renderer,16,92,30,30,medals,r);
lowerFrame->addChild(obj);
//And the medal on the right side.
obj=new GUIImage(imageManager,renderer,x-24,92,30,30,medals,r);
lowerFrame->addChild(obj);
//Create the three buttons, Menu, Restart, Next.
/// TRANSLATORS: used as return to the level selector menu
GUIObject* b1=new GUIButton(imageManager,renderer,x,10,-1,36,_("Menu"),0,true,true,GUIGravityCenter);
b1->name="cmdMenu";
b1->eventCallback=this;
lowerFrame->addChild(b1);
b1->render(renderer,0,0,true);
/// TRANSLATORS: used as restart level
GUIObject* b2=new GUIButton(imageManager,renderer,x,50,-1,36,_("Restart"),0,true,true,GUIGravityCenter);
b2->name="cmdRestart";
b2->eventCallback=this;
lowerFrame->addChild(b2);
b2->render(renderer,0,0,true);
/// TRANSLATORS: used as next level
GUIObject* b3=new GUIButton(imageManager,renderer,x,90,-1,36,_("Next"),0,true,true,GUIGravityCenter);
b3->name="cmdNext";
b3->eventCallback=this;
lowerFrame->addChild(b3);
b3->render(renderer,0,0,true);
maxWidth=b1->width;
if(b2->width>maxWidth)
maxWidth=b2->width;
if(b3->width>maxWidth)
maxWidth=b3->width;
b1->left=b2->left=b3->left=x+maxWidth/2;
x+=maxWidth;
lowerFrame->width=x;
lowerFrame->left=(SCREEN_WIDTH-lowerFrame->width)/2;
}
}
void Game::recordingEnded(ImageManager& imageManager, SDL_Renderer& renderer){
//Check if it's a normal replay, if so just stop.
if(!interlevel){
//Show the cursor so that the user can press the ok button.
SDL_ShowCursor(SDL_ENABLE);
//Now show the message box.
msgBox(imageManager,renderer,_("Game replay is done."),MsgBoxOKOnly,_("Game Replay"));
//Go to the level select menu.
setNextState(STATE_LEVEL_SELECT);
//And change the music back to the menu music.
getMusicManager()->playMusic("menu");
}else{
//Instead of directly replaying we set won true to let the Game handle the replaying at the end of the update cycle.
won=true;
}
}
bool Game::canSaveState(){
return (player.canSaveState() && shadow.canSaveState());
}
bool Game::saveState(){
//Check if the player and shadow can save the current state.
if(canSaveState()){
//Let the player and the shadow save their state.
player.saveState();
shadow.saveState();
//Save the stats.
timeSaved=time;
recordingsSaved=recordings;
recentSwapSaved=recentSwap;
//Save the PRNG and seed.
prngSaved = prng;
prngSeedSaved = prngSeed;
//Save the level size.
levelRectSaved = levelRect;
//Save the camera mode and target.
cameraModeSaved=cameraMode;
cameraTargetSaved=cameraTarget;
//Save the current collectables
currentCollectablesSaved = currentCollectables;
totalCollectablesSaved = totalCollectables;
//Save scripts.
copyCompiledScripts(getScriptExecutor()->getLuaState(), compiledScripts, savedCompiledScripts);
//Save other state, for example moving blocks.
copyLevelObjects(levelObjects, levelObjectsSave, false);
//Also save states of scenery layers.
for (auto it = sceneryLayers.begin(); it != sceneryLayers.end(); ++it) {
it->second->saveAnimation();
}
//Also save the background animation, if any.
if(background)
background->saveAnimation();
if(!player.isPlayFromRecord() && !interlevel){
//Update achievements
Uint32 t=SDL_GetTicks()+5000; //Add a bias to prevent bugs
if(recentSave+1000>t){
statsMgr.newAchievement("panicSave");
}
recentSave=t;
//Update statistics.
statsMgr.saveTimes++;
//Update achievements
switch(statsMgr.saveTimes){
case 1000:
statsMgr.newAchievement("save1k");
break;
}
}
//Save the state for script executor.
getScriptExecutor()->saveState();
//Execute the onSave event.
executeScript(LevelEvent_OnSave);
//Return true.
return true;
}
//We can't save the state so return false.
return false;
}
bool Game::loadState(){
//Check if there's a state that can be loaded.
if(player.canLoadState() && shadow.canLoadState()){
//Let the player and the shadow load their state.
player.loadState();
shadow.loadState();
//Load the stats.
time=timeSaved;
recordings=recordingsSaved;
recentSwap=recentSwapSaved;
//Load the PRNG and seed.
prng = prngSaved;
prngSeed = prngSeedSaved;
//Load the level size.
levelRect = levelRectSaved;
//Load the camera mode and target.
cameraMode=cameraModeSaved;
cameraTarget=cameraTargetSaved;
//Load the current collactbles
currentCollectables = currentCollectablesSaved;
totalCollectables = totalCollectablesSaved;
//Load scripts.
copyCompiledScripts(getScriptExecutor()->getLuaState(), savedCompiledScripts, compiledScripts);
//Load other state, for example moving blocks.
copyLevelObjects(levelObjectsSave, levelObjects, true);
//Also load states of scenery layers.
for (auto it = sceneryLayers.begin(); it != sceneryLayers.end(); ++it) {
it->second->loadAnimation();
}
//Also load the background animation, if any.
if(background)
background->loadAnimation();
if(!player.isPlayFromRecord() && !interlevel){
//Update achievements.
Uint32 t=SDL_GetTicks()+5000; //Add a bias to prevent bugs
if(recentLoad+1000>t){
statsMgr.newAchievement("panicLoad");
}
recentLoad=t;
//Update statistics.
statsMgr.loadTimes++;
//Update achievements
switch(statsMgr.loadTimes){
case 1000:
statsMgr.newAchievement("load1k");
break;
}
}
//Load the state for script executor.
getScriptExecutor()->loadState();
//Execute the onLoad event, if any.
executeScript(LevelEvent_OnLoad);
//Return true.
return true;
}
//We can't load the state so return false.
return false;
}
static std::string createNewSeed() {
static int createSeedTime = 0;
struct Buffer {
time_t systemTime;
Uint32 sdlTicks;
int x;
int y;
int createSeedTime;
} buffer;
buffer.systemTime = time(NULL);
buffer.sdlTicks = SDL_GetTicks();
SDL_GetMouseState(&buffer.x, &buffer.y);
buffer.createSeedTime = ++createSeedTime;
return Md5::toString(Md5::calc(&buffer, sizeof(buffer), NULL));
}
void Game::reset(bool save,bool noScript){
//Some sanity check, i.e. if we switch from no-script mode to script mode, we should always reset the save
assert(noScript || getScriptExecutor() || save);
//We need to reset the game so we also reset the player and the shadow.
player.reset(save);
shadow.reset(save);
saveStateNextTime=false;
loadStateNextTime=false;
//Reset the stats if interlevel isn't true.
if(!interlevel){
time=0;
recordings=0;
}
recentSwap=-10000;
if(save) recentSwapSaved=-10000;
//Reset the pseudo-random number generator by creating a new seed, unless we are playing from record.
if (levelFile == "?record?" || interlevel) {
if (prngSeed.empty()) {
cout << "WARNING: The record file doesn't provide a random seed! Will create a new random seed!"
"This may breaks the behavior pseudo-random number generator in script!" << endl;
prngSeed = createNewSeed();
} else {
#ifdef _DEBUG
cout << "Use existing PRNG seed: " << prngSeed << endl;
#endif
}
} else {
prngSeed = createNewSeed();
#ifdef _DEBUG
cout << "Create new PRNG seed: " << prngSeed << endl;
#endif
}
prng.seed(std::seed_seq(prngSeed.begin(), prngSeed.end()));
if (save) {
prngSaved = prng;
prngSeedSaved = prngSeed;
}
//Reset the level size.
levelRect = levelRectInitial;
if (save) levelRectSaved = levelRectInitial;
//Reset the camera.
cameraMode=CAMERA_PLAYER;
if(save) cameraModeSaved=CAMERA_PLAYER;
cameraTarget = SDL_Rect{ 0, 0, 0, 0 };
if (save) cameraTargetSaved = SDL_Rect{ 0, 0, 0, 0 };
//Reset the number of collectables
currentCollectables = currentCollectablesInitial;
totalCollectables = totalCollectablesInitial;
if (save) {
currentCollectablesSaved = currentCollectablesInitial;
totalCollectablesSaved = totalCollectablesInitial;
}
//Clear the event queue, since all the events are from before the reset.
eventQueue.clear();
//Reset states of scenery layers.
for (auto it = sceneryLayers.begin(); it != sceneryLayers.end(); ++it) {
it->second->resetAnimation(save);
}
//Also reset the background animation, if any.
if(background)
background->resetAnimation(save);
//Reset the cached notification block
notificationTexture.update(NULL, NULL);
//Reset the script environment if necessary.
if (noScript) {
//Destroys the script environment completely.
scriptExecutor->destroy();
//Clear the level script.
compiledScripts.clear();
savedCompiledScripts.clear();
initialCompiledScripts.clear();
//Clear the block script.
for (auto block : levelObjects){
block->compiledScripts.clear();
}
for (auto block : levelObjectsSave){
block->compiledScripts.clear();
}
for (auto block : levelObjectsInitial){
block->compiledScripts.clear();
}
} else if (save) {
//Create a new script environment.
getScriptExecutor()->reset(true);
//Recompile the level script.
compiledScripts.clear();
savedCompiledScripts.clear();
initialCompiledScripts.clear();
for (auto it = scripts.begin(); it != scripts.end(); ++it){
int index = getScriptExecutor()->compileScript(it->second);
compiledScripts[it->first] = index;
lua_rawgeti(getScriptExecutor()->getLuaState(), LUA_REGISTRYINDEX, index);
savedCompiledScripts[it->first] = luaL_ref(getScriptExecutor()->getLuaState(), LUA_REGISTRYINDEX);
lua_rawgeti(getScriptExecutor()->getLuaState(), LUA_REGISTRYINDEX, index);
initialCompiledScripts[it->first] = luaL_ref(getScriptExecutor()->getLuaState(), LUA_REGISTRYINDEX);
}
//Recompile the block script.
for (auto block : levelObjects){
block->compiledScripts.clear();
}
for (auto block : levelObjectsSave){
block->compiledScripts.clear();
}
for (auto block : levelObjectsInitial) {
block->compiledScripts.clear();
for (auto it = block->scripts.begin(); it != block->scripts.end(); ++it){
int index = getScriptExecutor()->compileScript(it->second);
block->compiledScripts[it->first] = index;
}
}
} else {
assert(getScriptExecutor());
//Do a soft reset.
getScriptExecutor()->reset(false);
//Restore the level script to initial state.
copyCompiledScripts(getScriptExecutor()->getLuaState(), initialCompiledScripts, compiledScripts);
//NOTE: We don't need to restore the block script since it will be restored automatically when the block array is copied.
}
//We reset levelObjects here since we need to wait the compiledScripts being initialized.
copyLevelObjects(levelObjectsInitial, levelObjects, true);
if (save) {
copyLevelObjects(levelObjectsInitial, levelObjectsSave, false);
}
//Also reset the last checkpoint so set it to NULL.
if (save)
objLastCheckPoint = NULL;
//Call the level's onCreate event.
executeScript(LevelEvent_OnCreate);
//Send GameObjectEvent_OnCreate event to the script
for (auto block : levelObjects) {
block->onEvent(GameObjectEvent_OnCreate);
}
//Close exit(s) if there are any collectables
if (totalCollectables>0){
for (auto block : levelObjects){
if (block->type == TYPE_EXIT){
block->onEvent(GameObjectEvent_OnSwitchOff);
}
}
}
//Hide the cursor (if not the leveleditor).
if(stateID!=STATE_LEVEL_EDITOR)
SDL_ShowCursor(SDL_DISABLE);
}
void Game::executeScript(int eventType){
map<int,int>::iterator it;
//Check if there's a script for the given event.
it=compiledScripts.find(eventType);
if(it!=compiledScripts.end()){
//There is one so execute it.
getScriptExecutor()->executeScript(it->second);
}
}
void Game::broadcastObjectEvent(int eventType,int objectType,const char* id,GameObject* target){
//Create a typeGameObjectEvent that can be put into the queue.
typeGameObjectEvent e;
//Set the event type.
e.eventType=eventType;
//Set the object type.
e.objectType=objectType;
//By default flags=0.
e.flags=0;
//Unless there's an id.
if(id){
//Set flags to 0x1 and set the id.
e.flags|=1;
e.id=id;
}
//Or there's a target given.
if(target)
e.target=target;
else
e.target=NULL;
//Add the event to the queue.
eventQueue.push_back(e);
}
void Game::getCurrentLevelAutoSaveRecordPath(std::string &bestTimeFilePath,std::string &bestRecordingFilePath,bool createPath){
levels->getLevelAutoSaveRecordPath(-1,bestTimeFilePath,bestRecordingFilePath,createPath);
}
void Game::gotoNextLevel(ImageManager& imageManager, SDL_Renderer& renderer){
//Goto the next level.
levels->nextLevel();
//Check if the level exists.
if(levels->getCurrentLevel()<levels->getLevelCount()){
setNextState(STATE_GAME);
}else{
if(!levels->congratulationText.empty()){
msgBox(imageManager,renderer,_CC(levels->getDictionaryManager(),levels->congratulationText),MsgBoxOKOnly,_("Congratulations"));
}else{
msgBox(imageManager,renderer,_("You have finished the levelpack!"),MsgBoxOKOnly,_("Congratulations"));
}
//Now go back to the levelselect screen.
setNextState(STATE_LEVEL_SELECT);
//And set the music back to menu.
getMusicManager()->playMusic("menu");
}
}
void Game::GUIEventCallback_OnEvent(ImageManager& imageManager,SDL_Renderer& renderer, string name,GUIObject* obj,int eventType){
if(name=="cmdMenu"){
setNextState(STATE_LEVEL_SELECT);
//And change the music back to the menu music.
getMusicManager()->playMusic("menu");
}else if(name=="cmdRestart"){
//Clear the gui.
if(GUIObjectRoot){
delete GUIObjectRoot;
GUIObjectRoot=NULL;
}
interlevel=false;
//And reset the game.
//NOTE: We don't need to clear the save game because in level replay the game won't be saved (??)
//TODO: it seems work (??); I'll see if it introduce bugs
reset(false, false);
}else if(name=="cmdNext"){
//No matter what, clear the gui.
if(GUIObjectRoot){
delete GUIObjectRoot;
GUIObjectRoot=NULL;
}
//And goto the next level.
gotoNextLevel(imageManager,renderer);
}
}
void Game::invalidateNotificationTexture(Block *block) {
if (block == NULL || block == notificationTexture.getId()) {
notificationTexture.update(NULL, NULL);
}
}

File Metadata

Mime Type
text/x-diff
Expires
Sat, May 16, 7:15 PM (1 d, 10 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
63213
Default Alt Text
(364 KB)

Event Timeline